Как отправить файл изображения в 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 еще не получил это разрешение, он показывает черный экран.