Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing intents (queryIntentActivities) on Android 10 does no return all the expected ones

Tags:

android

share

I have a simple code to share photos through external apps that have been working as expected in previous Android versions. But we are getting some reports saying that users can not share photos with their apps because only some of them appears in the share sheet.

We did some tests in different phones (with Android 10), and the results is that there are only like 3 or 4 app available to share, and it depends on the phone. For instance, in some phones Gmail is shown, but no in other. In those where Gmail appears, it works correctly.

Any idea why?

This is how Uri looks: content://com.MyPackageName.fileprovider/external_cache/test2014_000000059279.jpg

This is how mime looks: image/jpeg

Here is the code, I've simplified it a bit.

public void shareViaIntent(Context context, Uri uri, String mimeType, CharSequence shareTitle) {
    Intent shareIntent = new Intent(Intent.ACTION_SEND);
    shareIntent.setType(mimeType);
    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // temp permission for receiving app to read file from temp cache path of our app
    shareIntent.putExtra(Intent.EXTRA_TEXT, context.getString(R.string.shared_text));
    shareIntent.putExtra(Intent.EXTRA_STREAM, uri);

    final ArrayList<Intent> shareIntents = getExternalShareIntents(context, shareIntent);

    Intent chooserIntent = Intent.createChooser(target, shareTitle);
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, shareIntents.toArray(new Parcelable[]{}));
    context.startActivity(chooserIntent);
}

private ArrayList<Intent> getExternalShareIntents(Context context, Intent shareIntent) throws Throwable {
    final List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(shareIntent, 0);

    final ArrayList<Intent> shareIntents = new ArrayList<>();
    for (ResolveInfo resolveInfo : resolveInfos) {
        final String packageName = resolveInfo.activityInfo.packageName;

        if (packageName.equals(buildInfo.getApplicationId())) {
            continue;
        }

        Intent intent = new Intent(shareIntent);
        intent.setComponent(new ComponentName(packageName, resolveInfo.activityInfo.name));
        shareIntents.add(intent);
    }

    return shareIntents;
}

And here you can see the behavior changes depending on the phone..

share examples

Thanks in advance

like image 384
adalpari Avatar asked Jan 29 '20 15:01

adalpari


People also ask

What is the purpose of the intent filter?

An intent filter declares the capabilities of its parent component — what an activity or service can do and what types of broadcasts a receiver can handle. It opens the component to receiving intents of the advertised type, while filtering out those that are not meaningful for the component.

What is android intent Action view?

An intent allows you to start an activity in another app by describing a simple action you'd like to perform (such as "view a map" or "take a picture") in an Intent object.

What are the different types of intent?

There are two types of intents in android: implicit and explicit.

What is the use of Intent in android Studio?

An intent is to perform an action on the screen. It is mostly used to start activity, send broadcast receiver,start services and send message between two activities.

What is Android intents and how does it work?

Android uses Intents and their associated extras to allow users to share information quickly and easily, using their favorite apps. Android provides two ways for users to share data between apps: The Android Sharesheet is primarily designed for sending content outside your app and/or directly to another user.

Does startactivity launch new intent in Android 11?

StartActivity does not launch new intent in Android 11 - API 30 version - Microsoft Q&A Q&A Global navigation Docs Documentation Learn Q&A Code Samples Q&A Questions Tags Users Feedback Site feedback Ask a question Home Anonymous Sign in to post Post Explore Tags Questions Site feedback Articles Users Skip to main content

What is the difference between the Android sharesheet and intent resolver?

The Android Sharesheet is primarily designed for sending content outside your app and/or directly to another user. For example, sharing a URL with a friend. The Android intent resolver is best suited for passing data to the next stage of a well-defined task. For example, opening a PDF from your app and letting users pick their preferred viewer.

How do I display the Android sharesheet in an intent?

In order to display the Android Sharesheet you need to call Intent.createChooser (), passing it your Intent object. It returns a version of your intent that will always display the Android Sharesheet.


1 Answers

When your app's targetSdkVersion is 30 or later, you will receive a filtered list of activities/packages. Hence, the weird results on different phones/setups. It's also worth noticing that this also affects ShareActionProvider which is commonly used for share actions.

Package Visibility in Android 11

Read about the details in Android Documentation. There you find the solution to this problem. The manifest must include a <queries> tag.

The solution

Run the latest version of Android Studio and Gradle. Then modify your AndroidManifest.xml as shown below. My sample only handles text/plain, but you can of course add other MIME types if your app needs it.

<manifest>
  <application>
    <!-- -->
  </application>
  <queries>
    <intent>
      <action android:name="android.intent.action.SEND" />
      <data android:mimeType="text/plain" />
    </intent>
  </queries>
</manifest>

With this in place, the Intent Chooser no longer shows a filtered list.

like image 164
l33t Avatar answered Oct 21 '22 19:10

l33t