How to mimic a chooser activity/share menu?
Asked Answered
D

1

6

I have tried to make my own Chooser Activity to replace androids share to... popup.

I took a look at ChooserActivity extends ResolverActivity and tried to copy the code. In my manifest I have

<intent-filter>
    <action android:name="android.intent.action.CHOOSER" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

And in onCreate I do

Intent intent = getIntent();
Parcelable parcelable = intent.getParcelableExtra("android.intent.extra.INTENT");

Intent shareIntent = (Intent) parcelable;
shareIntent.setComponent(new ComponentName(packageName, activityName));
startActivity(shareIntent);
finish();

This works, with the exception of shares that have files attached. There, I get this crash:

java.lang.SecurityException: UID 10098 does not have permission to content://com.android.chrome.FileProvider/images/screenshot/15305419271134395322470190280016.jpg [user 0]
    at android.os.Parcel.readException(Parcel.java:1942)
    at android.os.Parcel.readException(Parcel.java:1888)
    at android.app.IActivityManager$Stub$Proxy.startActivity(IActivityManager.java:4365)
    at android.app.Instrumentation.execStartActivity(Instrumentation.java:1610)
    at android.app.Activity.startActivityForResult(Activity.java:4472)
    at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:754)
    at android.app.Activity.startActivityForResult(Activity.java:4430)
    at androidx.fragment.app.FragmentActivity.startActivityForResult(FragmentActivity.java:741)
    at android.app.Activity.startActivity(Activity.java:4791)
    at android.app.Activity.startActivity(Activity.java:4759)

It seems like my activity cannot execute the original intent because it has no permission to these files. What can be done to fix this? Is there a way to get permission? After all, android somehow does it too.

I have tried a few fixes, but nothing has worked so far. If I can't make it work, I would like to invoke the usual share menu from android to handle this, but I can't make this work either.

addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

Doesn't work, as these flags already exist in the intent. Removing them on the other hand will cause the share to work, but the files won't be shared, it will be empty.

startActivity(Intent.createChooser(shareIntent, "test");

Will throw the same exception.

startActivity(Intent.createChooser(intent, "test"));

I have tried to invoke the android share menu this way by making a chooser for the original intent, but it just gives me a window that lets me select me app.

intent.setComponent(null);
startActivity(Intent.createChooser(intent, "test"));

This on the other hand worked and I was able to select the android share menu, but nothing happened when I tried sharing. The app would act like it hasn't received anything.

intent.setComponent(new ComponentName("android", "com.android.internal.app.ChooserActivity"));
startActivity(intent);

Does exactly what I wanted, open the normal android share menu. But one problem remains: No matter what the share was, it doesn't do anything. I choose something, and that's it, it closes. Nothing else. Why does this happen? I basically start the same intent the old app did, and redirect it to android. Why doesn't it work anymore? What can I do?

I read that root permissions may be necessary to make it work, but maybe there is still a workaround? Or at least a way to feed the original intent back to the android share menu without breaking it?

When sharing from some apps it works, for example gallery apps. Those apps that cause no problems all use an URI starting with content://media/...

Also, from my research it seems like it might have something to do with the FileProvider, but it seems like that would have to be done in the app that is sharing to me, and not my app, so I can't do anything about that.

Also, please note that I am NOT creating the share Intent, but receiving and sending it to another app.

Here is the issuetracker from google

Dato answered 2/7, 2018 at 14:48 Comment(0)
R
-1

I think you need FileProvider at your app. There is a change of file haring in Lollipop. To start with, you create a provider in AndroidManifest.xml

Step 1:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.mydomain.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
</provider>

Step 2: Create and define file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="image" path="image/"/>
    <external-path name="externalPath" path="external/path"/>
    <cache-path name="cachePath" path="./" />
</paths>

Depends on where you put the file to share, you have to put them in the correct attribute, files-path, external-path, cache-path. Check here for more information.

Step 3: The sharing code.

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
    File imagePath = new File(Context.getFilesDir(), "images");
    File newFile = new File(imagePath, "default_image.jpg");
    Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
    intent.setFlags(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
}else{
    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image));
}

startActivity(intent);   
Rowe answered 13/7, 2018 at 1:24 Comment(3)
The problem is that my Chooser Activity doesn't have permission to those files, so startActivity will make it crash with SecurityException again.Dato
Yep. This code is for sharing from an app. The OP's app is the Chooser activity, the app you get when you want to share something and need to pick an app.Capillary
I see, now I understand the issue.Rowe

© 2022 - 2024 — McMap. All rights reserved.