背景
与我最近分享/打开APK文件(here,here和here)时遇到的问题类似,我现在遇到了将图像文件(资产,res / raw甚至是URL)发送到特定应用程序的问题:WhatsApp和Viber .
我需要能够将图像文件共享给所有应用程序,特别是WhatsApp和Viber等受欢迎的应用程序 .
问题
当我尝试在Andorid 7.1.1上共享图像文件时,WhatsApp和Viber都有问题 . 在其他应用程序和以前版本的Android上,它运行良好 .
在我试过的所有测试中,它们要么显示黑屏(没有图像)要么关闭自己 .
我尝试过并找到了什么
1.我开始使用名为“cwac-provider”的库从应用程序的assets文件夹共享文件 . 除了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无法在android下强制转换为java.util.ArrayList位于com.whatsapp.ContactPicker的com.whatsapp.ContactPicker.k(ContactPicker.java:618)的android.content.Intent.getParcelableArrayListExtra(Intent.java:6357)中的.os.Bundle.getParcelableArrayList(Bundle.java:916) . onCreate(ContactPicker.java:360)位于android.app.Anstrumentation.callActivityOnCreate(Instrumentation.java:1118)android.app.ActivityThread.performLaunchActivity(ActivityThread.java)的android.app.Activity.performCreate(Activity.java:6688) :2633)在android.app.A活动中的android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2741)android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1488)的android.app.ActivityThread.-wrap12(ActivityThread.java)在android.app.ActivityThr的android.os.Handler.dispatchMessage(Handler.java:102)android.os.Looper.loop(Looper.java:154) ead.main(ActivityThread.java:6169)位于com.android的com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:888)的java.lang.reflect.Method.invoke(Native Method)中 . internal.os.ZygoteInit.main(ZygoteInit.java:778)
2.我被告知(here)试图通过将 ArrayList<Uri>
放入 EXTRA_STREAM
来分享:
ArrayList<Uri> uriArrayList=new ArrayList<>();
uriArrayList.add(getUri());
share.putExtra(Intent.EXTRA_STREAM, uriArrayList);
它不起作用,WhatsApp的日志显示:
引起:java.lang.SecurityException:Permission Denial:打开提供者
来自ProcessRecord的com.commonsware.cwac.provider.StreamProvider {9405e93 12914:com.whatsapp / u0a210}(pid = 12914,uid = 10210)未从uid 10123导出到android.os.Parcel.readException(Parcel.java: 1684)在Android.A.运行时Android.app.ActivityThread.acquireProvider(ActivityThread.java:5526)的android.app.Aard.Percel.readException(Parcel.java:1637)处于android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4213) . app.ContextImpl $ ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2239)在android.content.ContentResolver的android.content.ContentResolver.actentUnstableProvider(ContentResolver.java:1517)上的android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1131)位于com.whatsapp.util.ah的com.whatsapp.util.ah.b(MediaFileUtils.java:1290)的android.content.ContentResolver.openInputStream(ContentResolver.java:704)上的.openAssetFileDescriptor(ContentResolver.java:984) . a(MediaFileUtils.java:1498)在com.whatsapp.util.ah.a(MediaF) ileUtils.java:1543)com.whatsapp.gallerypicker.ImagePreview $ b $ 1.a(ImagePreview.java:901)at com.whatsapp.gallerypicker.ImagePreview $ b $ 1.doInBackground(ImagePreview.java:896)at 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)at java . util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:607)
在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:Permission Denial:从ProcessRecord打开提供者com.commonsware.cwac.provider.StreamProvider {adbb1ed 5565:com.viber.voip / u0a175}(pid = 5565 ,uid = 10175)未从uid导出10123 02-07 09:54:07.087 926-10717 / system_process W / ActivityManager:权限拒绝:从ProcessRecord打开提供程序com.commonsware.cwac.provider.StreamProvider {adbb1ed 5565:com .viber.voip / u0a175}(pid = 5565,uid = 10175)未从uid导出10123 02-07 09:54:07.091 926-946 / system_processW / ActivityManager:权限拒绝:从ProcessRecord打开提供程序com.commonsware.cwac.provider.StreamProvider {adbb1ed 5565:com.viber.voip / u0a175}(pid = 5565,uid = 10175),不从uid 10123导出
4.奇怪的是,对于WhatsApp,在上述所有尝试中,它都询问了存储权限,即使它不应该(因为应用程序无论如何都提供了内容) .
5.我发现的另一个奇怪的事情是,Google Photos app可以很好地与这些应用程序共享图像,即使图像来自服务器 . 它在某处下载文件并共享它 . 我可以't see where it downloads the file, though. I thought it would be on the app'的外部存储路径("/.../Android/data/com.google.android.apps.photos/..."),但它不在那里 .
6.我试图通过使用支持库的FileProvider来创建一个从外部存储共享文件的POC(因为我已经知道如何使用共享APK文件):
manifest
<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>
res/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)at 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.Anstrumentation.callActivityOnCreate(Instrumentation.java:1118)的android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2633)android.app.ActivityThread.handleLaunchActivity(ActivityThread . java:2741)在Android.app.Handler.dispatchMessage(Handler.jav)的android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1488)的android.app.ActivityThread.-wrap12(ActivityThread.java) a:102)在android.app.Looper.loop(Looper.java:154)的android.app.ActivityThread.main(ActivityThread.java:6169)at java.lang.reflect.Method.invoke(Native Method)at com .android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:888)at 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应用程序在能够访问文件之前授予存储权限(自己) .
可悲的是,我认为它需要在选择器上的所有应用程序上获得此权限 .
如果Viber尚未授予此权限,则会显示黑屏 .