skip to Main Content

So I know that for android version >= 30 you need to add queries in the manifest, but this didnt do the trick for me.
Im using Android Version 29. I nevertheless added these lines to my manifest.

So my manifest looks like this.

 <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<queries>
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data android:scheme="https" />
    </intent>
    <intent>
        <action android:name="android.intent.action.DIAL" />
        <data android:scheme="tel" />
    </intent>
    <intent>
        <action android:name="android.intent.action.SEND" />
        <data android:mimeType="*/*" />
    </intent>
</queries>

I managed to reproduce the error for my machine with the code bellow. Nevertheless I get this error:

I/UrlLauncher(10601): component name for mailto:?subject=&body= is null

Down below you find the code for main.dart

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {return Scaffold(
      body: Center(
        child: ElevatedButton(
          style: ButtonStyle(
            shape: MaterialStateProperty.all<RoundedRectangleBorder>(
              RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(18.0)),
            ),
          ),
          onPressed: () => launchEmail(
            toEmail: "js",
            subject: "dm",
            message: "jd",
          ), child: Text("null"),
        ),
      ),
    );
  }

  Future launchEmail({
    required String toEmail,
    required String subject,
    required String message,
  }) async {
    final url =
        "mailto:$toEmail?subject=${Uri.encodeFull(subject)}&body=${Uri.encodeFull(message)}";
    if (await canLaunch(url)) {
      await launch(url);
    }
  }
}

2

Answers


  1. Chosen as BEST ANSWER

    What I did to resolve the error:

    I set my Android API to 30+

    Your manifest.xml should contains this:

    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
    <queries>
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <data android:scheme="https" />
        </intent>
        <intent>
            <action android:name="android.intent.action.DIAL" />
            <data android:scheme="tel" />
        </intent>
        <intent>
            <action android:name="android.intent.action.SEND" />
            <data android:mimeType="*/*" />
        </intent>
    </queries>
    

    If this doesnt fix it for you, Suj suggested to add:

    <package android:name="com.app" />
    

    to your manifest

    So just paste the lines under the start of your manifest:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        package="com.nikita.autolab">
        <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
            tools:ignore="QueryAllPackagesPermission" />
        <queries>
            <intent>
                <action android:name="android.intent.action.VIEW" />
                <data android:scheme="https" />
            </intent>
            <intent>
                <action android:name="android.intent.action.DIAL" />
                <data android:scheme="tel" />
            </intent>
            <intent>
                <action android:name="android.intent.action.SEND" />
                <data android:mimeType="*/*" />
            </intent>
        </queries>
       <application
            android:label="AutoLab"
            android:name="${applicationName}"
            android:icon="@mipmap/ic_launcher">
            <activity
                android:name=".MainActivity"
                android:exported="true"
                android:launchMode="singleTop"
                android:theme="@style/LaunchTheme"
                android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
                android:hardwareAccelerated="true"
                android:windowSoftInputMode="adjustResize">
                <!-- Specifies an Android theme to apply to this Activity as soon as
                     the Android process has started. This theme is visible to the user
                     while the Flutter UI initializes. After that, this theme continues
                     to determine the Window background behind the Flutter UI. -->
                <meta-data
                  android:name="io.flutter.embedding.android.NormalTheme"
                  android:resource="@style/NormalTheme"
                  />
                <intent-filter>
                    <action android:name="android.intent.action.MAIN"/>
                    <category android:name="android.intent.category.LAUNCHER"/>
                </intent-filter>
            </activity>
            <!-- Don't delete the meta-data below.
                 This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
            <meta-data
                android:name="flutterEmbedding"
                android:value="2" />
        </application>
    </manifest>
    

  2. By updating your API to 30 (minSdkVersion), you are restricting the devices and Android versions which can install your app.

    Alternative solution: Don’t call canLaunch for mailto links – use it only for http and https!

    Since I have both http(s) and mailto links in my app, I use the try-catch block.

    Here is the full function:

    class UrlHandler {
      /// Attempts to open the given [url] in in-app browser. Returns `true` after successful opening, `false` otherwise.
      static Future<bool> open(String url) async {
        try {
          await launch(
            url,
            enableJavaScript: true,
          );
          return true;
        } catch (e) {
          log(e.toString());
          return false;
        }
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search