如何在Android 7.1.1上将图像文件共享给WhatsApp和Viber?

时间:2017-02-07 08:25:41

标签: android android-intent whatsapp commonsware-cwac viber

背景

与我最近分享/打开APK文件(hereherehere)的问题类似,我现在遇到发送图像文件的问题(在资产,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:Key   android.intent.extra.STREAM期望ArrayList但值是a   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)at   android.content.Intent.getParcelableArrayListExtra(Intent.java:6357)   在com.whatsapp.ContactPicker.k(ContactPicker.java:618)at   com.whatsapp.ContactPicker.onCreate(ContactPicker.java:360)at   android.app.Activity.performCreate(Activity.java:6688)at   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)at   android.os.Looper.loop(Looper.java:154)at   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)   在com.android.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的日志显示:

                                                    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)                                                                 在android.app.ContextImpl $ ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2239)                                                                 在android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1517)                                                                 在android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1131)                                                                 在android.content.ContentResolver.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 app可以很好地与这些应用共享图像,即使图像来自服务器。它在某处下载文件并共享它。但是,我无法看到它下载文件的位置。我认为它将在应用程序的外部存储路径上(&#34; /.../ Android / data / com.google.android.apps.photos /..."),但它& #39;不在那里。

6.我尝试使用支持库的FileProvider创建一个从外部存储共享文件的POC(因为我已经知道如何使用共享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>

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:Key   android.intent.extra.STREAM期望ArrayList但值是a   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.java:102)                                                               在android.os.Looper.loop(Looper.java:154)                                                               在android.app.ActivityThread.main(ActivityThread.java:6169)                                                               at java.lang.reflect.Method.invoke(Native Method)                                                               在com.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 个答案:

答案 0 :(得分:1)

目前我将使用解决方案#7,但它并不完美,因为它需要Viber和WhatsApp应用程序在能够访问文件之前授予(自己)存储权限。

可悲的是,我认为选择器上的所有应用都需要此权限。

如果Viber尚未授予此权限,则会显示黑屏。