Update AndroidManifest.xml with intent:// permissions

Custom Code

I have a custom component for a Webview which receives an intent:// redirect to another external application. Everything works as intended on iOS and I am able to successfully open the other app from the Webview, but on Android I get the following error: ERR_UNKNOWN_URL_SCHEME.

I have done some research and found that it is related to permissions on Android, and not the implementation of the Webview component. I have also found that I can solve the problem using the url_launcher package, and adding intent permission to AndroidManifest.xml according to the docs:

"Add any URL schemes passed to canLaunchUrl as <queries> entries in your AndroidManifest.xml, otherwise it will return false in most cases starting on Android 11 (API 30) or higher."

My problem is that there is currently no way to update the AndroidManifest.xml in Flutterflow. The other threads that have similar issues all involve manual fixes and builds, which defeats the purpose of paying for a Pro subscription if I can't use the automatic deployment for Mobile Android.

I'll need to know if there is any way to handle this problem, while making sure that several manual steps are not added to my deployment procedure each time.

What have you tried so far?

Other threads that have issues with modifying AndroidManifest.xml:

https://community.flutterflow.io/ask-the-community/post/request-for-androidmanifest-editor-in-flutterflow-oza10MugzPRhBbe

https://community.flutterflow.io/ask-the-community/post/adding-into-androidmanifest-xml-4S1KsyTpg6Z3PMG

https://community.flutterflow.io/ask-the-community/post/add-intent-filter-in-androidmanifest-xml-PVzevm3wHbm7DEG

https://community.flutterflow.io/custom-code/post/modify-androidmanifest-xml-zj5YBBIGobo5CPC

All of these threads refer to a manual solution, but this will not work for me as it would significantly slow down my deployment speed. I am hopefully looking for a more general solution or for Flutterflow to add this functionality as part of their Pro tier.

Solution to handle intent:// URLs using URL Launcher: https://pub.dev/packages/url_launcher#android

In case that there might be an issue in my Webview component linking the code here:

// Automatic FlutterFlow imports
import '/backend/schema/structs/index.dart';
import '/backend/schema/enums/enums.dart';
import '/backend/supabase/supabase.dart';
import '/actions/actions.dart' as action_blocks;
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/custom_code/actions/index.dart'; // Imports custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:homai/index.dart';

class WebViewContainer extends StatefulWidget {
  const WebViewContainer({
    Key? key,
    this.width = 300,
    this.height = 400,
    required this.targetUrl,
  }) : super(key: key);

  final double width;
  final double height;
  final String targetUrl;

  @override
  State<WebViewContainer> createState() => _WebViewContainerState();
}

class _WebViewContainerState extends State<WebViewContainer> {
  InAppWebViewController? _webViewController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: InAppWebView(
        initialUrlRequest: URLRequest(
          url: WebUri(widget.targetUrl),
        ),
        onWebViewCreated: (controller) {
          _webViewController = controller;
        },
        onLoadStart: (controller, url) async {
          if (url != null) {
            final urlString = url.toString();

            // Handle `intent://` URLs for Android
            if (urlString.startsWith('intent://')) {
              await _handleIntentUrl(urlString);
              return;
            }

            // Handle `https://homai.dk` redirects
            if (urlString.startsWith('https://homai.dk')) {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => VerifyEloverblikWidget(),
                ),
              );
              return;
            }

            print('Page started loading: $url');
          }
        },
        onLoadStop: (controller, url) {
          setState(() {
            print('Page finished loading: $url');
          });
        },
      ),
    );
  }

  Future<void> _handleIntentUrl(String intentUrl) async {
    try {
      // Extract the fallback URL or app scheme from the intent URL
      final uri = Uri.parse(intentUrl);
      print('Final uri: $uri');

      // Attempt to launch the intent or fallback URL
      if (await canLaunchUrl(uri)) {
        await launchUrl(uri);
      } else {
        final fallbackUrl = uri.queryParameters['S.browser_fallback_url'];
        if (fallbackUrl != null && await canLaunchUrl(Uri.parse(fallbackUrl))) {
          await launchUrl(Uri.parse(fallbackUrl));
        } else {
          print('Could not launch URL: $intentUrl');
        }
      }
    } catch (e) {
      print('Error handling intent:// URL: $e');
    }
  }
}
Did you check FlutterFlow's Documentation for this topic?
Yes
4
3 replies