Reputation: 53
My app requires to check if an email app is present so we can hide a button for sending the email.
On API 30, Android has made change to the package manager so we cannot access the activities anymore, unless they have been declared in the <queries>
tag.
I have setup the queries node on the AndroidManifest file as follows
<queries>
<intent>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.APP_EMAIL" />
</intent>
</queries>
When I try to query using the the intent, the method on the package manager returns zero items.
fun isEmailAppInstalled(context: Context): Boolean {
val intent = Intent(Intent.ACTION_MAIN)
intent.addCategory(Intent.CATEGORY_APP_EMAIL)
return context.packageManager.queryIntentActivities(intent, 0).isNotEmpty()
}
Upvotes: 5
Views: 2517
Reputation: 1237
In your AndroidManifest
add:
<queries>
<intent>
<action android:name="android.intent.action.SENDTO"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="mailto"/>
</intent>
</queries>
And alter your code to
val intent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"))
intent.addCategory(Intent.CATEGORY_DEFAULT)
return context.packageManager.queryIntentActivities(intent, 0).isNotEmpty()
Language syntax may need double chekcing/updating as I have tested the solution in Xamarin.Forms
and is back compat with API 29 and below too.
Upvotes: 13
Reputation: 740
According to the new documentation based on API level 30 or higher , if you want to access other apps installed on device you have to declare package visibility by adding the <queries>
element in your app's manifest file. What you are doing here. And same time the system makes some apps visible to your app automatically. We can check by
adb shell dumpsys package queries
In the command output, find the forceQueryable section. This section includes the list of packages that the device has made visible to your app automatically.(this part copied from documentation).
So in this case without <queries>
tag I can access Email app from my device on API 30 and also 29 by Intent.createChooser.
fun isEmailAppInstalled(context: Context) {
/* val intent = Intent(Intent.ACTION_MAIN)
intent.addCategory(Intent.CATEGORY_APP_EMAIL)
return context.packageManager.queryIntentActivities(intent, 0).isNotEmpty()*/
val intent = Intent(Intent.ACTION_MAIN)
intent.addCategory(Intent.CATEGORY_APP_EMAIL)
try {
startActivity(Intent.createChooser(intent, "Choose your Email App"))
} catch (e: ActivityNotFoundException) {
Log.i("ZI", "No Email App Found")
}
}
Upvotes: 0
Reputation: 8867
From documentation:
fun composeEmail(addresses: Array<String>, subject: String) {
val intent = Intent(Intent.ACTION_SENDTO).apply {
data = Uri.parse("mailto:") //<- only email apps should handle this
putExtra(Intent.EXTRA_EMAIL, addresses)
putExtra(Intent.EXTRA_SUBJECT, subject)
}
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
}
Upvotes: 0