I have used the following codes to exclude facebook app from my app chooser:
List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("image/*");
List<ResolveInfo> resInfo = getActivity().getPackageManager().queryIntentActivities(intent, 0);
if (!resInfo.isEmpty()) {
for (ResolveInfo resolveInfo : resInfo) {
String packageName = resolveInfo.activityInfo.packageName;
Intent targetedShareIntent = new Intent(android.content.Intent.ACTION_SEND);
targetedShareIntent.setType("image/*");
targetedShareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "tooter.nl");
if (!TextUtils.equals(packageName, "com.facebook.katana")) {
targetedShareIntent.putExtra(android.content.Intent.EXTRA_TEXT, st);
targetedShareIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
targetedShareIntent.setPackage(packageName);
targetedShareIntents.add(targetedShareIntent);
}
}
Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), "Select app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[targetedShareIntents.size()]));
startActivity(chooserIntent);
}
Facebook app was removed when I used the code. But the sad part was, even Twitter app was also removed from the app chooser and other unnecessary apps like "Android system" was listed on the chooser . What should i do ? Is something missing or wrong with this code ?
Check my answer below. It will exclude only facebook application from sharing.
void shareOnOtherSocialMedia() {
List<Intent> shareIntentsLists = new ArrayList<Intent>();
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("image/*");
List<ResolveInfo> resInfos = getPackageManager().queryIntentActivities(shareIntent, 0);
if (!resInfos.isEmpty()) {
for (ResolveInfo resInfo : resInfos) {
String packageName = resInfo.activityInfo.packageName;
if (!packageName.toLowerCase().contains("facebook")) {
Intent intent = new Intent();
intent.setComponent(new ComponentName(packageName, resInfo.activityInfo.name));
intent.setAction(Intent.ACTION_SEND);
intent.setType("image/*");
intent.setPackage(packageName);
shareIntentsLists.add(intent);
}
}
if (!shareIntentsLists.isEmpty()) {
Intent chooserIntent = Intent.createChooser(shareIntentsLists.remove(0), "Choose app to share");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, shareIntentsLists.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
} else
Log.e("Error", "No Apps can perform your task");
}
}
}
And call the above function wherever you want.
Let me know for queries.
For Android API 24 and above, you can use this:
val components = arrayOf(ComponentName(applicationContext, YourActivity::class.java))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
startActivity(Intent.createChooser(intent, null).putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS,components))
For the rest, you can have this solution I wrote about (which allows you to have a condition which to exclude
Here's a more generalized solution, to be able to choose which to exclude for all Android versions:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val targetIntent = Intent(Intent.ACTION_SEND)
targetIntent.type = "text/plain"
targetIntent.putExtra(Intent.EXTRA_SUBJECT, "subject")
targetIntent.putExtra(Intent.EXTRA_TEXT, "text")
val excludedAppsPackageNames = hashSetOf( "com.pushbullet.android","com.android.bluetooth","com.google.android.apps.docs","com.google.android.gm")
getIntentChooser(this, targetIntent, "choose!", object : ComponentNameFilter {
override fun shouldBeFilteredOut(componentName: ComponentName): Boolean = excludedAppsPackageNames.contains(componentName.packageName)
})?.let { startActivity(it) }
}
interface ComponentNameFilter {
fun shouldBeFilteredOut(componentName: ComponentName): Boolean
}
private fun getIntentChooser(context: Context, intent: Intent, chooserTitle: CharSequence? = null, filter: ComponentNameFilter): Intent? {
val resolveInfos = context.packageManager.queryIntentActivities(intent, 0)
// Log.d("AppLog", "found apps to handle the intent:")
val excludedComponentNames = HashSet<ComponentName>()
resolveInfos.forEach {
val activityInfo = it.activityInfo
val componentName = ComponentName(activityInfo.packageName, activityInfo.name)
// Log.d("AppLog", "componentName:$componentName")
if (filter.shouldBeFilteredOut(componentName))
excludedComponentNames.add(componentName)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return Intent.createChooser(intent, chooserTitle).putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponentNames.toTypedArray())
}
if (resolveInfos.isNotEmpty()) {
val targetIntents: MutableList<Intent> = ArrayList()
for (resolveInfo in resolveInfos) {
val activityInfo = resolveInfo.activityInfo
if (excludedComponentNames.contains(ComponentName(activityInfo.packageName, activityInfo.name)))
continue
val targetIntent = Intent(intent)
targetIntent.setPackage(activityInfo.packageName)
targetIntent.component = ComponentName(activityInfo.packageName, activityInfo.name)
// wrap with LabeledIntent to show correct name and icon
val labeledIntent = LabeledIntent(targetIntent, activityInfo.packageName, resolveInfo.labelRes, resolveInfo.icon)
// add filtered intent to a list
targetIntents.add(labeledIntent)
}
val chooserIntent: Intent?
// deal with M list seperate problem
chooserIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// create chooser with empty intent in M could fix the empty cells problem
Intent.createChooser(Intent(), chooserTitle)
} else {
// create chooser with one target intent below M
Intent.createChooser(targetIntents.removeAt(0), chooserTitle)
}
if (chooserIntent == null) {
return null
}
// add initial intents
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toTypedArray<Parcelable>())
return chooserIntent
}
return null
}
}
I had to exclude facebook apps as they had a broken share intent (something about user originality) using Intent#EXTRA_EXCLUDE_COMPONENTS I resorted to this:
Intent intent = new Intent(Intent.ACTION_SEND);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
intent.setTypeAndNormalize("text/plain");
} else {
intent.setType("text/plain");
}
intent.putExtra(Intent.EXTRA_TEXT, "Text to share");
Intent chooser = Intent.createChooser(intent, "Share Text");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
ArrayList<ComponentName> targets = new ArrayList<>();
// remove facebook which has a broken share intent
for (ResolveInfo candidate : requireActivity().getPackageManager().queryIntentActivities(intent, 0)) {
String packageName = candidate.activityInfo.packageName;
if (packageName.toLowerCase().contains("facebook")) {
targets.add(new ComponentName(packageName, candidate.activityInfo.name));
}
}
chooser.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, targets.toArray(new ComponentName[0]));
}
startActivity(chooser);
This only works for android N and above
Android N (API 24) introduces blacklist Intent.EXTRA_EXCLUDE_COMPONENTS, which is better and simpler than whitelist Intent.EXTRA_INITIAL_INTENTS.
Updated Kotlin answer based on Ragu Swaminathan's answer
fun share() {
val shareIntent = Intent()
shareIntent.action = Intent.ACTION_SEND
shareIntent.type = "text/plain"
val resInfoList = activity?.packageManager?.queryIntentActivities(shareIntent, 0)
val shareIntentList = arrayListOf<Intent>()
if (resInfoList?.isNotEmpty() == true) {
for (resInfo in resInfoList) {
val packageName = resInfo.activityInfo.packageName
if (!packageName.toLowerCase().contains("discord")) {
val intent = Intent()
intent.component = ComponentName(packageName, resInfo.activityInfo.name)
intent.action = Intent.ACTION_SEND
intent.type = "text/plain"
intent.`package` = packageName
intent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
shareIntentList.add(intent)
}
}
}
if (shareIntentList.isEmpty()) {
Toast.makeText(activity, "No apps to share!", Toast.LENGTH_LONG).show()
} else {
val chooserIntent = Intent.createChooser(Intent(), "Choose app to share")
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, shareIntentList.toTypedArray())
activity?.startActivity(chooserIntent)
}
}
Thanks to Ragu Swaminathan's answer, it works perfectly to exclude specific application in an IntentChooser. However, because the 'shareIntentLists' is added in front of the 'chooserIntent', some empty spaces may occur if the size of list is not multiple of 4. To solve this, try:
Intent chooserIntent = Intent.createChooser(new Intent(), "Choose app to share");
After updating targetSdkVersion to 31 the older solution will stop working.
This below solution will work for all android version
In Manifest file AndroidManidest.xml
(In Android api 31 by default queryIntentActivities() will return empty list to get the desired result from queryIntentActivities you need to add the below query parameter in manifest file.)
<manifest>
<queries>
<intent>
<!--Change the action and data depending on you share intent-->
<action android:name="android.intent.action.SEND" />
<data android:mimeType="text/*"/>
</intent>
</queries>
</manifest>
In the activity file share function
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, "Link");
shareIntent.putExtra(Intent.EXTRA_SUBJECT,"Description")
ArrayList<ComponentName> excludedComponents = new ArrayList<ComponentName>();
PackageManager packageManager = context.getPackageManager();
for (ResolveInfo resolveInfo : packageManager.queryIntentActivities(shareIntent, 0)){
String packageName = resolveInfo.activityInfo.packageName;
//change facebook with whichever app you want to exclude or you can directly search for the specific package name
if (packageName.contains("facebook")){
excludedComponents.add(new
ComponentName(packageName,resolveInfo.activityInfo.name));
}
}
Intent intentChooser = Intent.createChooser(shareIntent, "Share");
intentChooser.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, excludedComponents.toArray(new Parcelable[]{}));
startActivity(intentChooser);
Related
I have multiple email account installed on Android. But when I launch the Intent I see only three of them. I've added also the browsers installed. But still I can see only three options. Is there a way to show all the options available?
This is the code I'm using:
fun openEmailPicker(){
val packageManager = activity.packageManager
val resInfoEmail = extractResInfoFromIntent("mailto:", packageManager)
val resInfoBrowser = extractResInfoFromIntent("http://www.gmail.com", packageManager)
if (resInfoEmail.size > 0) {
val openInChooser = buildHeader(resInfoEmail, packageManager)
val emailIntents = createIntentLIst(1, resInfoEmail, packageManager)
val browserIntents = createIntentLIst(0, resInfoBrowser, packageManager)
browserIntents.addAll(emailIntents)
openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, browserIntents.toTypedArray())
startActivity(openInChooser)
}
}
private fun buildHeader(resInfo: MutableList<ResolveInfo>, packageManager: PackageManager): Intent {
val resolveInfo = resInfo[0]
val intentChooser = packageManager.getLaunchIntentForPackage(resolveInfo.activityInfo.packageName)
return Intent.createChooser(intentChooser, getString(R.string.select_to_open_email))
}
private fun createIntentLIst(from: Int, resInfo: MutableList<ResolveInfo>, packageManager: PackageManager): MutableList<LabeledIntent> {
val intentList: MutableList<LabeledIntent> = ArrayList()
for (index in from until resInfo.size) {
extractLabelToLabeledIntent(resInfo, index, packageManager, intentList)
}
return intentList
}
private fun extractLabelToLabeledIntent(resInfo: MutableList<ResolveInfo>, i: Int, pm: PackageManager, intentList: MutableList<LabeledIntent>) {
val resolveInfo = resInfo[i]
val packageName = resolveInfo.activityInfo.packageName
val intent = pm.getLaunchIntentForPackage(packageName)
intentList.add(LabeledIntent(intent, packageName, resolveInfo.loadLabel(pm), resolveInfo.icon))
}
private fun extractResInfoFromIntent(URI: String, packageManager: PackageManager): MutableList<ResolveInfo> {
val emailIntent = Intent(Intent.ACTION_VIEW, Uri.parse(URI))
return packageManager.queryIntentActivities(emailIntent, 0)
}
You misunderstand what account and what application is. When you fire the intent, you get the list of the applications that can handle that intent. No matter how many separate accounts or whatever are created within these application. Once you got an application open, then you can select the account and the address -- you don't get a separate icon for every account within the same application in the intent chooser dialog.
You may get a list of the applications that are capable to handle your intent with queryIntentActivities() to receive a list of activities.
Official doc for App Chooser: https://developer.android.com/training/basics/intents/sending
I think those mail clients don't have action intent,
Any way you can add them manually by adding their package names something similar to this
List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent shareInent = new Intent(Intent.ACTION_SEND);
shareInent.setType("text/plain");
List<ResolveInfo> resInfo = activity.getPackageManager().queryIntentActivities(shareInent, 0);
// put the name of the packages you want in this ArrayList
ArrayList<String> wantedPackage = new ArrayList<>();
if (!resInfo.isEmpty()) {
for (ResolveInfo info : resInfo) {
Intent targetedShare = new Intent(android.content.Intent.ACTION_SEND);
targetedShare.setType("text/plain");
String infoPackageName = info.activityInfo.packageName.toLowerCase();
if (wantedPackage.contains(infoPackageName)) {
targetedShare.putExtra(Intent.EXTRA_TEXT, "put your text here");
targetedShare.setPackage(info.activityInfo.packageName.toLowerCase());
targetedShareIntents.add(targetedShare);
resPackageNames.add(infoPackageName);
}
}
Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), "Chooser title");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
}
You can show the email clients in the chooser dialog but I don't think those clients would perform the action you desire since they lack the intent handling.
I'm using this code to open email chooser via intent
val mIntent = Intent(
Intent.ACTION_SENDTO, Uri.fromParts(
"mailto",
"name#email.com", null
)
)
mIntent.putExtra(Intent.EXTRA_SUBJECT, "[Feedback - App Name]")
mIntent.putExtra(Intent.EXTRA_TEXT, "")
try {
startActivity(Intent.createChooser(mIntent, "Choose Email Client..."))
} catch (e: Exception) {
(activity as MainActivity).showToast("There are no email clients installed.")
}
it works as expected but it also includes PayPal app in the list of email clients.
On clicking PayPal, if the email is registered with PayPal, it redirects to the payment page. And if not registered, it shows below screen.
In both scenarios, there is no option to send emails from the PayPal app.
So, How can I include only email clients in the intent chooser?
I have tried this code as well, it also results in the same.
val intent = Intent(Intent.ACTION_SENDTO)
intent.data = Uri.parse("mailto:")
intent.putExtra(Intent.EXTRA_EMAIL, "addresses")
intent.putExtra(Intent.EXTRA_SUBJECT, "subject")
if (intent.resolveActivity(activity?.getPackageManager()!!) != null) {
startActivity(Intent.createChooser(intent, "Choose Email Client..."))
}
EDIT :
I have checked in other apps where the same dialog is opening. May be PayPal app is listening to mail events.
Please look into this :
private void openEmailApp() {
List<Intent> emailAppLauncherIntents = new ArrayList<>();
//Intent that only email apps can handle:
Intent emailAppIntent = new Intent(Intent.ACTION_SENDTO);
emailAppIntent.setData(Uri.parse("mailto:"));
emailAppIntent.putExtra(Intent.EXTRA_EMAIL, "");
emailAppIntent.putExtra(Intent.EXTRA_SUBJECT, "");
PackageManager packageManager = getPackageManager();
//All installed apps that can handle email intent:
List<ResolveInfo> emailApps = packageManager.queryIntentActivities(emailAppIntent, PackageManager.MATCH_ALL);
for (ResolveInfo resolveInfo : emailApps) {
String packageName = resolveInfo.activityInfo.packageName;
Intent launchIntent = packageManager.getLaunchIntentForPackage(packageName);
emailAppLauncherIntents.add(launchIntent);
}
//Create chooser
Intent chooserIntent = Intent.createChooser(new Intent(), "Select email app:");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, emailAppLauncherIntents.toArray(new Parcelable[emailAppLauncherIntents.size()]));
startActivity(chooserIntent);
}
Edited
private void sendEmail(Connect connect) {
Intent email = new Intent(Intent.ACTION_SENDTO);
email.setData(Uri.parse("mailto:"));
email.putExtra(Intent.EXTRA_EMAIL, new String[]{connect.getEmail()});
email.putExtra(Intent.EXTRA_SUBJECT, "");
email.putExtra(Intent.EXTRA_TEXT, "");
try {
startActivity(Intent.createChooser(email, getString(R.string.choose_email_client)));
} catch (ActivityNotFoundException activityNotFoundException) {
UIUtils.showShortSnackBar(fragmentConnectLayout, getString(R.string.no_email_client));
}
}
You can loop through the intent package names and remove PayPal. Then create a chooser with your filtered list.
val emailAppLauncherIntents = ArrayList<Intent>()
// Intent that only email apps can handle:
val emailAppIntent = Intent(Intent.ACTION_SENDTO)
emailAppIntent.data = Uri.parse("mailto:")
val packageManager = requireActivity().packageManager
// All installed apps that can handle email intent
val emailApps = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
packageManager.queryIntentActivities(emailAppIntent, PackageManager.MATCH_ALL)
} else {
packageManager.queryIntentActivities(emailAppIntent, PackageManager.MATCH_DEFAULT_ONLY)
}
emailApps.forEach { resolveInfo ->
val packageName = resolveInfo.activityInfo.packageName
val launchIntent = packageManager.getLaunchIntentForPackage(packageName)
// Paypal shows up for send intent - we don't want this
if (!packageName.contains("paypal") && launchIntent != null) {
emailAppLauncherIntents.add(launchIntent)
}
}
val chooser = Intent.createChooser(Intent(), getString(R.string.select_email_client))
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, emailAppLauncherIntents.toTypedArray())
startActivity(chooser)
I have an android app which can open specific urls. So in my Manifest I add intent-filter section like this:
<intent-filter>
<data andriod:host="someurl.com"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.intent.action.VIEW" />
</intent-filter>
When user clicks on my links(outside of the app) my app is shown as one of the apps that can open url and it's fine.
But I have links inside my app that can started with "someurl.com" and in this situation I should remove my app from IntentChooser dialog. I do this like below:
public Intent generateCustomChooserIntent(Intent prototype) throws Exception {
List<Intent> targetedShareIntents = new ArrayList<Intent>();
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(prototype, 0);
if (!resInfo.isEmpty()) {
for (ResolveInfo resolveInfo : resInfo) {
// do not include my app in intent chooser dialog
if (resolveInfo.activityInfo == null || resolveInfo.activityInfo.packageName.equals(getPackageName())) {
continue;
}
// add Intent to intent chooser dialog
Intent targetedShareIntent = (Intent) prototype.clone();
targetedShareIntent.setPackage(resolveInfo.activityInfo.packageName);
targetedShareIntent.setClassName(resolveInfo.activityInfo.packageName, resolveInfo.activityInfo.name);
targetedShareIntents.add(targetedShareIntent);
}
if (!targetedShareIntents.isEmpty()) {
// pass new Intent to create no chooser in first row
Intent chooserIntent = Intent.createChooser(targetedShareIntents.get(0), getString(R.string.open_link_with));
targetedShareIntents.remove(0);
// pass extra intent chooser
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[targetedShareIntents.size()]));
return chooserIntent;
}
}
// there is no appropriate intent to run
throw new Exception();
}
And it's fine too.
But in some android devices(like samsung A5 2016) when I ask for intents which can handle url, it just return my app as appropriate app(and doesn't include apps like google chrome), then I remove my app from IntentChooser dialog, and then nothing left to choose from.
How can I solve this?
There is workaround here which you can use like this
public Intent generateCustomChooserIntent(Context context, String url) throws Exception {
Uri fakeUri = Uri.parse("https://www.google.com");
Uri realUri = Uri.parse(url);
Intent shareIntent = new Intent(Intent.ACTION_VIEW, fakeUri);
List<ResolveInfo> resInfo;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
resInfo = context.getPackageManager().queryIntentActivities(
shareIntent, PackageManager.MATCH_ALL);
} else {
resInfo = context.getPackageManager().queryIntentActivities(
shareIntent, 0);
}
if (!resInfo.isEmpty()) {
List<Intent> targetedShareIntents = removeCurrentApp(context, realUri, resInfo);
if (!targetedShareIntents.isEmpty()) {
// pass new Intent to create no chooser in first row
Intent chooserIntent = Intent.createChooser(
targetedShareIntents.get(0), context.getString(R.string.open_link_with));
targetedShareIntents.remove(0);
// pass extra intent chooser
chooserIntent.putExtra(
Intent.EXTRA_INITIAL_INTENTS,
targetedShareIntents.toArray(new Parcelable[targetedShareIntents.size()]));
return chooserIntent;
}
}
// there is no appropriate intent to run
throw new Exception();
}
#NonNull
private List<Intent> removeCurrentApp(Context context, Uri realUri, List<ResolveInfo> resInfo) {
List<Intent> targetedShareIntents = new ArrayList<>();
String currentPackageName = context.getPackageName();
for (ResolveInfo resolveInfo : resInfo) {
// do not include my app in intent chooser dialog
if (resolveInfo.activityInfo == null) {
continue;
}
String packageName = resolveInfo.activityInfo.packageName;
if (currentPackageName.equalsIgnoreCase(packageName)) {
continue;
}
Intent intent = new Intent(Intent.ACTION_VIEW, realUri);
intent.setClassName(
resolveInfo.activityInfo.applicationInfo.packageName,
resolveInfo.activityInfo.name);
intent.setPackage(packageName);
targetedShareIntents.add(intent);
}
return targetedShareIntents;
}
How can i remove Google+ from the intent?
Intent intent = new Intent(Intent.ACTION_SEND);
...
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, title);
// Verify the intent will resolve to at least one activity
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
How can i remove Google+ from the intent?
List<Intent> targetIntents = new ArrayList<Intent>();
Intent templateIntent = new Intent(Intent.ACTION_SEND);
templateIntent.setType("text/plain");
List<ResolveInfo> packages = this.getPackageManager().
queryIntentActivities(templateIntent, 0);
// remove desired package
for (ResolveInfo candidate : packages) {
String packageName = candidate.activityInfo.packageName;
if (!packageName.equals("com.google.android.apps.plus")) { //GooglePlus Package name
Intent target = new Intent(android.content.Intent.ACTION_SEND);
target.setType("text/plain");
target.putExtra(Intent.EXTRA_TEXT, "Your Text Here");
target.setPackage(packageName);
targetIntents.add(target);
}
}
Intent chooserIntent = Intent.createChooser(targetIntents.remove(0), "Share.");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetIntents.toArray(new Parcelable[]{}));
startActivity(chooserIntent);
I'm trying to link a button to the mail app. Not to send mail, but just to open the inbox.
Should I do this with Intent intent = new Intent(...)?
If so, what should be between the ( )?
If the goal is to open the default email app to view the inbox, then key is to add an intent category and use the ACTION_MAIN intent like so:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_APP_EMAIL);
getActivity().startActivity(intent);
https://developer.android.com/reference/android/content/Intent.html#CATEGORY_APP_EMAIL
This code worked for me. It opens a picker with all email apps registered to device and straight to Inbox:
Intent emailIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("mailto:"));
PackageManager pm = getPackageManager();
List<ResolveInfo> resInfo = pm.queryIntentActivities(emailIntent, 0);
if (resInfo.size() > 0) {
ResolveInfo ri = resInfo.get(0);
// First create an intent with only the package name of the first registered email app
// and build a picked based on it
Intent intentChooser = pm.getLaunchIntentForPackage(ri.activityInfo.packageName);
Intent openInChooser =
Intent.createChooser(intentChooser,
getString(R.string.user_reg_email_client_chooser_title));
// Then create a list of LabeledIntent for the rest of the registered email apps
List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
for (int i = 1; i < resInfo.size(); i++) {
// Extract the label and repackage it in a LabeledIntent
ri = resInfo.get(i);
String packageName = ri.activityInfo.packageName;
Intent intent = pm.getLaunchIntentForPackage(packageName);
intentList.add(new LabeledIntent(intent, packageName, ri.loadLabel(pm), ri.icon));
}
LabeledIntent[] extraIntents = intentList.toArray(new LabeledIntent[intentList.size()]);
// Add the rest of the email apps to the picker selection
openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
startActivity(openInChooser);
}
Any suggestions to avoid the crash if the default mail in the device is not configured?
Yes, it's possible to open the Android default email inbox.
Use this code:
Intent intent = getPackageManager().getLaunchIntentForPackage("com.android.email");
startActivity(intent);
This code works, you have to configure your Android device default mail first. If you already configured your mail it works fine. Otherwise, it force closes with a NullPointerException.
To open it new task use the below code:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_APP_EMAIL);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Based on the answer https://stackoverflow.com/a/28190156/3289338
Starting from Android 11 the system won't return anything for queryIntentActivities because we first need to add an entry in the queries (in the manifest) like this
<manifest ...>
<queries>
...
<intent>
<action
android:name="android.intent.action.VIEW" />
<data
android:scheme="mailto" />
</intent>
</queries>
...
</manifest>
and here a kotlin version of the solution:
fun Context.openMailbox(chooserTitle: String) {
val emailIntent = Intent(Intent.ACTION_VIEW, Uri.parse("mailto:"))
val resInfo = packageManager.queryIntentActivities(emailIntent, 0)
if (resInfo.isNotEmpty()) {
// First create an intent with only the package name of the first registered email app
// and build a picked based on it
val intentChooser = packageManager.getLaunchIntentForPackage(
resInfo.first().activityInfo.packageName
)
val openInChooser = Intent.createChooser(intentChooser, chooserTitle)
// Then create a list of LabeledIntent for the rest of the registered email apps
val emailApps = resInfo.toLabeledIntentArray(packageManager)
// Add the rest of the email apps to the picker selection
openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, emailApps)
startActivity(openInChooser)
} else {
Timber.e("No email app found")
}
}
private fun List<ResolveInfo>.toLabeledIntentArray(packageManager: PackageManager): Array<LabeledIntent> = map {
val packageName = it.activityInfo.packageName
val intent = packageManager.getLaunchIntentForPackage(packageName)
LabeledIntent(intent, packageName, it.loadLabel(packageManager), it.icon)
}.toTypedArray()
You can simply use below code when for no attachment:
Intent i = new Intent(Intent.ACTION_SENDTO);
i.setData(Uri.parse("mailto:support#mailname.com"));
i.putExtra(Intent.EXTRA_SUBJECT, "Feedback/Support");
startActivity(Intent.createChooser(emailIntent, "Send feedback"));
For details I recommend to visit:
https://developer.android.com/guide/components/intents-common.html#Email
I'm with jetpack compose and this works for me :
val context = LocalContext.current
val intent = Intent(Intent.ACTION_MAIN)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addCategory(Intent.CATEGORY_APP_EMAIL)
Button(
onClick = { startActivity(context, intent, null) }
)
You can use this but it is for gmail only
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("plain/text");
startActivity(emailIntent);
For kotlin:
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)
}
}
Ref: https://developer.android.com/reference/android/content/Intent.html#CATEGORY_APP_EMAIL
val intent = Intent(Intent.ACTION_MAIN)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addCategory(Intent.CATEGORY_APP_EMAIL)
startActivity(intent)
The code works for me:
Intent intent= new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_APP_EMAIL);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(Intent.createChooser(intent, ""));
Unfortunately it doesn't look promising. This has been asked before
How do I launch the email client directly to inbox view?
you can open the email client in compose mode, but you seem to already know that.
Bit late, here is proper working code.
Intent intent = Intent.makeMainSelectorActivity(
Intent.ACTION_MAIN,
Intent.CATEGORY_APP_EMAIL
);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(Intent.createChooser(intent, "Email"));
For further details check this document:
CATEGORY_APP_EMAIL
makeMainSelectorActivity
Intent email = new Intent(Intent.ACTION_MAIN);
email.addCategory(Intent.CATEGORY_APP_EMAIL);
startActivity(email);
You can open Android default e-mail client using this:
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/plain");
emailIntent.setClassName("com.android.email", "com.android.email.activity.Welcome");
emailIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(emailIntent);