title: How to share an image file to WhatsApp and Viber on Android 7.1.1?
body: <h2>Background</h2>
  
  <p>Similar to issues I've recently had with sharing/opening APK files (<a href="https://stackoverflow.com/q/41160353/878126"><strong>here</strong></a>, <a href="https://stackoverflow.com/q/41085950/878126"><strong>here</strong></a> and <a href="https://stackoverflow.com/q/40941709/878126">here</a>) , I now have an issue of sending an image file (in assets, res/raw or even from a URL) to specific apps: WhatsApp and Viber. </p>
  
  <p>I need to be able to share an image file to all apps, especially popular ones such as WhatsApp and Viber.</p>
  
  <h2>The problem</h2>
  
  <p>Both WhatsApp and Viber have issues when I try to share the image files on Andorid 7.1.1 . On other apps, and on previous versions of Android, it worked fine.</p>
  
  <p>They either show a black screen (no image) or close themselves, on all of the test I've tried.</p>
  
  <h2>What I tried and found</h2>
  
  <p>1.I started sharing a file from the assets folder of the app, using a library called "<a href="https://github.com/commonsguy/cwac-provider" rel="nofollow noreferrer"><strong>cwac-provider</strong></a>". It worked fine with all apps, except for WhatsApp and Viber.</p>
  
  <p>On WhatsApp , I got this log (which is very similar to what I got for Viber) : </p>
  
  <blockquote>
    <p>02-06 17:05:04.379 24590-24590/com.whatsapp W/Bundle: Key
    android.intent.extra.STREAM expected ArrayList but value was a
    android.net.Uri$HierarchicalUri. The default value was returned. 02-06
    17:05:04.382 24590-24590/com.whatsapp W/Bundle: Attempt to cast
    generated internal exception: java.lang.ClassCastException:
    android.net.Uri$HierarchicalUri cannot be cast to java.util.ArrayList
    at android.os.Bundle.getParcelableArrayList(Bundle.java:916) at
    android.content.Intent.getParcelableArrayListExtra(Intent.java:6357)
    at 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)
    at
    android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2633)
    at
    android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2741)
    at android.app.ActivityThread.-wrap12(ActivityThread.java) at
    android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488)
    at 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)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)</p>
  </blockquote>
  
  <p>2.I was told (<a href="https://github.com/commonsguy/cwac-provider/issues/28#issuecomment-277853514" rel="nofollow noreferrer"><strong>here</strong></a>) to try to share by putting an <code>ArrayList&lt;Uri&gt;</code> into the <code>EXTRA_STREAM</code>:</p>
  
  <pre><code>    ArrayList&lt;Uri&gt; uriArrayList=new ArrayList&lt;&gt;();
      uriArrayList.add(getUri());
      share.putExtra(Intent.EXTRA_STREAM, uriArrayList);
  </code></pre>
  
  <p>It didn't work, and the log of WhatsApp shows:</p>
  
  <blockquote>
  <pre><code>                                                    Caused by: java.lang.SecurityException: Permission Denial: opening provider
  </code></pre>
    
    <p>com.commonsware.cwac.provider.StreamProvider from
    ProcessRecord{9405e93 12914:com.whatsapp/u0a210} (pid=12914,
    uid=10210) that is not exported from uid 10123
                                                                  at android.os.Parcel.readException(Parcel.java:1684)
                                                                  at android.os.Parcel.readException(Parcel.java:1637)
                                                                  at android.app.ActivityManagerProxy.getContentProvider(ActivityManagerNative.java:4213)
                                                                  at android.app.ActivityThread.acquireProvider(ActivityThread.java:5526)
                                                                  at android.app.ContextImpl$ApplicationContentResolver.acquireUnstableProvider(ContextImpl.java:2239)
                                                                  at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1517)
                                                                  at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1131)
                                                                  at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:984)
                                                                  at android.content.ContentResolver.openInputStream(ContentResolver.java:704)
                                                                  at com.whatsapp.util.ah.b(MediaFileUtils.java:1290)
                                                                  at com.whatsapp.util.ah.a(MediaFileUtils.java:1498)
                                                                  at com.whatsapp.util.ah.a(MediaFileUtils.java:1543)
                                                                  at 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)
                                                                  at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                  at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
                                                                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)</p>
  
  <pre><code>                                                          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
  
                                                            at java.lang.Thread.run(Thread.java:761)
  </code></pre>
  </blockquote>
  
  <p>3.I also tried to change the action of the intent to <code>ACTION_SEND_MULTIPLE</code>:</p>
  
  <pre><code>    Intent share = new Intent(Intent.ACTION_SEND_MULTIPLE);
      ...
      ArrayList&lt;Uri&gt; uriArrayList=new ArrayList&lt;&gt;();
      uriArrayList.add(getUri());
      share.putExtra(Intent.EXTRA_STREAM, uriArrayList);
  </code></pre>
  
  <p>but it also didn't help, showing this log for Viber (can't see anything special for WhatsApp) :</p>
  
  <blockquote>
    <p>02-07 09:54:07.084 926-10718/system_process W/ActivityManager:
    Permission Denial: opening provider
    com.commonsware.cwac.provider.StreamProvider from
    ProcessRecord{adbb1ed 5565:com.viber.voip/u0a175} (pid=5565,
    uid=10175) that is not exported from uid 10123 02-07 09:54:07.087
    926-10717/system_process W/ActivityManager: Permission Denial: opening
    provider com.commonsware.cwac.provider.StreamProvider from
    ProcessRecord{adbb1ed 5565:com.viber.voip/u0a175} (pid=5565,
    uid=10175) that is not exported from uid 10123 02-07 09:54:07.091
    926-946/system_process W/ActivityManager: Permission Denial: opening
    provider com.commonsware.cwac.provider.StreamProvider from
    ProcessRecord{adbb1ed 5565:com.viber.voip/u0a175} (pid=5565,
    uid=10175) that is not exported from uid 10123</p>
  </blockquote>
  
  <p>4.The weird thing is that for WhatsApp, on all of the above tries, it asked fro storage permission, even though it shouldn't (because the app provides the content by itself anyway).</p>
  
  <p>5.Another weird thing I've found, is that <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.photos&amp;hl=en" rel="nofollow noreferrer"><strong>Google Photos app</strong></a> works fine with sharing images to those apps, even if the image is from the server. It downloads the file somewhere and shares it. I can't see where it downloads the file, though. I thought it would be on the app's external storage path ("/.../Android/data/com.google.android.apps.photos/...") , but it's not there. </p>
  
  <p>6.I tried to make a POC of sharing a file from the external storage by using the FileProvider of the support library (as I've known how to use from sharing an APK file):</p>
  
  <p><strong>manifest</strong></p>
  
  <pre><code>&lt;provider
      android:name="android.support.v4.content.FileProvider"
      android:authorities="${applicationId}.provider"
      android:exported="false"
      android:grantUriPermissions="true"&gt;
      &lt;meta-data
          android:name="android.support.FILE_PROVIDER_PATHS"
          android:resource="@xml/provider_paths"/&gt;
  &lt;/provider&gt;
  </code></pre>
  
  <p><strong>res/xml/provider_paths.xml</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;paths&gt;
      &lt;external-path name="external_files" path="."/&gt;
  &lt;/paths&gt;
  </code></pre>
  
  <p>code: </p>
  
  <pre><code>    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);
  </code></pre>
  
  <p>but it worked only for WhatsApp, and not Viber, which showed a log </p>
  
  <blockquote>
    <p>02-07 10:21:19.285 24043-24043/com.viber.voip W/Bundle: Key
    android.intent.extra.STREAM expected ArrayList but value was a
    android.net.Uri$HierarchicalUri.  The default value  was
    returned. 02-07 10:21:19.285 24043-24043/com.viber.voip W/Bundle:
    Attempt to cast generated internal exception:
                                                            java.lang.ClassCastException: android.net.Uri$HierarchicalUri cannot
    be cast to java.util.ArrayList
                                                                at android.os.Bundle.getParcelableArrayList(Bundle.java:916)
                                                                at android.content.Intent.getParcelableArrayListExtra(Intent.java:6357)
                                                                at com.viber.voip.util.af.f(SourceFile:156)
                                                                at com.viber.voip.util.af.a(SourceFile:106)
                                                                at com.viber.voip.HomeActivity.i(SourceFile:487)
                                                                at com.viber.voip.HomeActivity.onCreate(SourceFile:317)
                                                                at android.app.Activity.performCreate(Activity.java:6688)
                                                                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
                                                                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2633)
                                                                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2741)
                                                                at android.app.ActivityThread.-wrap12(ActivityThread.java)
                                                                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1488)
                                                                at 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)
                                                                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:778)</p>
  </blockquote>
  
  <p>I tried to perform what I did on #2 and #3 , but it still didn't work on Viber.</p>
  
  <p>7.I tried sharing a file from external storage using the old way of doing it, which was supposed to be deprecated and replaced by FileProvider :</p>
  
  <pre><code>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;
  }
  </code></pre>
  
  <p>It works for both apps, but it works only if they both are granted with storage permission. For Viber, if it doesn't have storage permission, it shows a black image, and for WhatsApp, it asks the user to grant it.</p>
  
  <h2>The question</h2>
  
  <p>Why don't any of the above work?</p>
  
  <p>How should I really share an image file to those apps correctly? What's wrong even with sharing via the FileProvider ? How come Google Photos app work well ?</p>
  
  <p>Is there a workaround for this? </p>
  
  <p>Is it an issue on the apps themselves, or on Android ?</p>