Как отправить файл изображения в WhatsApp и Viber на Android 7.1.1?

Фон

Подобно проблемам, с которыми я недавно столкнулся при совместном использовании / открытии файлов APK ( здесь, здесь и здесь), у меня теперь есть проблема отправки файла изображения (в ресурсах, res/raw или даже из URL) в определенные приложения: WhatsApp и Viber.

Мне нужно иметь возможность поделиться файлом изображения со всеми приложениями, особенно такими, как WhatsApp и Viber.

Эта проблема

Как в WhatsApp, так и в Viber возникают проблемы при попытке поделиться файлами изображений на Andorid 7.1.1. На других приложениях и на предыдущих версиях Android все работало нормально.

Они либо показывают черный экран (без изображения), либо закрываются, во всех тестах, которые я пробовал.

Что я попробовал и нашел

1. Я начал делиться файлом из папки активов приложения, используя библиотеку cwac-provider. Он работал нормально со всеми приложениями, кроме WhatsApp и Viber.

На WhatsApp я получил этот журнал (который очень похож на то, что я получил для Viber):

02-06 17: 05: 04.379 24590-24590 / com.whatsapp W / Bundle: ключ android.intent.extra.STREAM ожидал ArrayList, но значением был android.net.Uri$HierarchicalUri. Значение по умолчанию было возвращено. 02-06 17:05:04.382 24590-24590/com.whatsapp W/Bundle: Попытка вызвать сгенерированное внутреннее исключение: java.lang.ClassCastException: android.net.Uri$HierarchicalUri нельзя преобразовать в java.util.ArrayList на Android.os.Bundle.getParcelableArrayList(Bundle.java:916) в android.content.Intent.getParcelableArrayListExtra(Intent.java:6357) в com.whatsapp.ContactPicker.k(ContactPicker.java:618) в com.whatsapp.Contact onCreate(ContactPicker.java:360) в android.app.Activity.performCreate(Activity.java:6688) в android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) в android.app.ActivityThread.performLaunchActivity(ActivityThread.java):2633) в android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2741) в android.app.ActivityThread.-wrap12(ActivityThread.java) в android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488) в android.os.Handler.dispatchMessage(Handler.java:102) в android.os.Looper.loop(Looper.java:154) в android.app.ActivityThread.main(ActivityThread.java:6169) в java.lang.reflect.Method.invoke(собственный метод) в com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:888) в com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)

2. Мне сказали ( здесь), чтобы попытаться поделиться, поставив ArrayList<Uri> в EXTRA_STREAM:

    ArrayList<Uri> uriArrayList=new ArrayList<>();
    uriArrayList.add(getUri());
    share.putExtra(Intent.EXTRA_STREAM, uriArrayList);

Это не сработало, и журнал WhatsApp показывает:

                                                    Caused by: java.lang.SecurityException: Permission Denial: opening provider

com.commonsware.cwac.provider.StreamProvider из ProcessRecord{9405e93 12914:com.whatsapp/u0a210} (pid=12914, uid=10210), который не экспортируется из uid 10123 в android.os.Parcel.readException(Parcel.java:1684) на android.os.Parcel.readException(Parcel.java:1637) на android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4213) на android.app.ActivityThread.acquireProvider(ActivityThread.java:5526) на андроиде.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2239) по адресу android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1517) по адресу android.content.ContentResolver.openTavaContent.openTyContent.openAssetFileDescriptor(ContentResolver.java:984) на android.content.ContentResolver.openInputStream(ContentResolver.java:704) на com.whatsapp.util.ah.b(MediaFileUtils.java:1290) на com.whatsapp.util.ah.a(MediaFileUtils.java:1498) на com.whatsapp.util.ah.a(MediaFileUtils.java:1543) на com.whatsapp.gallerypicker.ImagePreview$b$1.a(ImagePreview.java:901) на com.whatsapp.gallerypicker.ImagePreview$b$1.doInBackground(ImagePreview.java:896) на android.os.AsyncTask$2.call(AsyncTask.java:305) в java.util.concurrent.FutureTask.run(FutureTask.java:237) в android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) в java. util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1133)

                                                          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)

                                                          at java.lang.Thread.run(Thread.java:761)

3. Я также пытался изменить действие намерения ACTION_SEND_MULTIPLE:

    Intent share = new Intent(Intent.ACTION_SEND_MULTIPLE);
    ...
    ArrayList<Uri> uriArrayList=new ArrayList<>();
    uriArrayList.add(getUri());
    share.putExtra(Intent.EXTRA_STREAM, uriArrayList);

но это также не помогло, показывая этот журнал для Viber (не вижу ничего особенного для WhatsApp):

02-07 09: 54: 07.084 926-10718 / system_process W / ActivityManager: отказ в разрешении: открытие поставщика com.commonsware.cwac.provider.StreamProvider из ProcessRecord{adbb1ed 5565:com.viber.voip/u0a175} (pid=5565, uid=10175), который не экспортируется из uid 10123 02-07 09:54:07.087 926-10717/system_process W/ActivityManager: Отказ в разрешении: открытие поставщика com.commonsware.cwac.provider.StreamProvider из ProcessRecord {adbb1ed 5565: com. viber.voip / u0a175} (pid = 5565, uid = 10175), который не экспортируется из uid 10123 02-07 09:54:07.091 926-946/system_process W/ActivityManager: отказ в разрешении: открытие поставщика com.commonsware.cwac. provider.StreamProvider из ProcessRecord{adbb1ed 5565:com.viber.voip/u0a175} (pid=5565, uid=10175), который не экспортируется из uid 10123

4. Странная вещь в том, что для WhatsApp во всех вышеперечисленных попытках он запрашивал разрешение на хранение, хотя и не должен (потому что приложение в любом случае предоставляет контент).

5. Еще одна странная вещь, которую я обнаружил, заключается в том, что приложение Google Photos прекрасно работает с возможностью обмена изображениями с этими приложениями, даже если изображение с сервера. Он скачивает файл куда-то и делится им. Я не вижу, где он загружает файл, хотя. Я думал, что это будет на внешнем хранилище приложения ("/.../Android/data/com.google.android.apps.photos/..."), но его там нет.

6. Я попытался создать POC для совместного использования файла из внешнего хранилища, используя FileProvider из библиотеки поддержки (как я знал, как использовать общий доступ к файлу APK):

манифест

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

Рез / XML /provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="."/>
</paths>

код:

    final File bitmapFile = new File(getExternalFilesDir(null), "test.jpg");
    if (!bitmapFile.exists()) {
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), android.R.drawable.sym_def_app_icon);
        bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(bitmapFile));
    }
    Intent intent = new Intent(Intent.ACTION_SEND);
    Uri fileUri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", bitmapFile);
    intent.setType(MimeTypeMap.getSingleton().getMimeTypeFromExtension("jpg"));
    intent.putExtra(Intent.EXTRA_STREAM, fileUri);
    intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    startActivity(intent);

но он работал только для WhatsApp, а не Viber, который показал логи

02-07 10:21:19.285 24043-24043/com.viber.voip W/Bundle: ключ android.intent.extra.STREAM ожидал ArrayList, но значением был android.net.Uri$HierarchicalUri. Значение по умолчанию было возвращено. 02-07 10:21:19.285 24043-24043/com.viber.voip W/Bundle: Попытка создать сгенерированное внутреннее исключение: java.lang.ClassCastException: android.net.Uri$HierarchicalUri не может быть приведен к java.util.ArrayList на android.os.Bundle.getParcelableArrayList(Bundle.java:916) на android.content.Intent.getParcelableArrayListExtra(Intent.java:6357) на com.viber.voip.util.af.f(SourceFile:156) на com.viber.voip.util.af.a(SourceFile:106) на com.viber.voip.HomeActivity.i(SourceFile:487) на com.viber.voip.HomeActivity.onCreate(SourceFile:317) на android.app.Activity.performCreate(Activity.java:6688) в android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118) в android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2633) в android.app.ActivityThread.handleLaunchActivity (ActivityThread. Java: 2741) на android.app.ActivityThread.-wrap12(ActivityThread.java) на android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488) на android.os.Handler.dispatchMessage (Handler.jav) a: 102) в android.os.Looper.loop(Looper.java:154) в android.app.ActivityThread.main (ActivityThread.java:6169) в java.lang.reflect.Method.invoke(собственный метод) в.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:888) в com.android.internal.os.ZygoteInit.main (ZygoteInit.java:778)

Я пытался выполнить то, что я делал на #2 и #3, но это все еще не работало на Viber.

7. Я попытался открыть общий доступ к файлу из внешнего хранилища, используя старый способ, который должен был быть признан устаревшим и заменен FileProvider:

startActivityForResult(Intent.createChooser(prepareIntentToSharePhoto(bitmapFile.getAbsolutePath(), "title",
                "body"), "choose"), 1);

public static Intent prepareIntentToSharePhoto(String imagePath, String title, String body) {
    Intent sharingIntent = new Intent(Intent.ACTION_SEND).setType("image/*")
            .putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + imagePath)).putExtra(android.content.Intent.EXTRA_SUBJECT, title)
            .putExtra(android.content.Intent.EXTRA_TEXT, body);
    return sharingIntent;
}

Он работает для обоих приложений, но работает, только если им обоим предоставлено разрешение на хранение. Для Viber, если у него нет разрешения на хранение, он показывает черное изображение, а для WhatsApp, он просит пользователя предоставить его.

Вопрос

Почему ничего из вышеперечисленного не работает?

Как мне правильно предоставить общий доступ к файлу изображения для этих приложений? Что не так даже с обменом через FileProvider? Почему приложение Google Фото работает хорошо?

Есть ли обходной путь для этого?

Это проблема самих приложений или Android?

1 ответ

Решение

Сейчас я буду использовать решение № 7, но оно не идеально, потому что для доступа к файлам требуется, чтобы приложения Viber и WhatsApp предоставили разрешение на хранение (самим себе).

К сожалению, я думаю, что требуется это разрешение для всех приложений на Chooser.

Если Viber еще не получил это разрешение, он показывает черный экран.

Другие вопросы по тегам