6

Is there a way to use Intent.ACTION_SEND to share a screenshot without requiring android.permission.WRITE_EXTERNAL_STORAGE?

Here's the share part:

    Intent shareIntent = new Intent(Intent.ACTION_SEND);
    shareIntent.setType("image/jpeg");
    shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
    Intent chooserIntent = Intent.createChooser(shareIntent, shareTitle);
    startActivity(chooserIntent);

The share works fine when the uri points to a file in getExternalFilesDir(), but I'd prefer a solution that does not require the WRITE_EXTERNAL_STORAGE permission for privacy-concerned users.

I've tried 3 different approaches:

  1. File Provider:

    uri = FileProvider.getUriForFile(context, authority, imageFile);
    

This works for some share styles (Gmail) but not others (Google+).

  1. Upload to a web server:

    uri = Uri.parse("http://my-image-host.com/screenshot.jpg");
    

This fails everywhere, crashing some (Google+).

(I suspect this could work if I implemented sharing logic myself using per-social-network APIs instead of the chooserIntent)

  1. Inject into Media Store:

    uri = MediaStore.Images.Media.insertImage(contentResolver, bitmap, name, description);
    

This throws a SecurityException explaining it requires WRITE_EXTERNAL_STORAGE.

Are there other approaches I'm missing?

Darrell
  • 1,945
  • 15
  • 21
  • Try `FileProvider` mixed in with my `LegacyCompatCursorWrapper`, and see if you have better luck. That wrapper is part of [my CWAC-Provider project](https://github.com/commonsguy/cwac-provider#usage-legacycompatcursorwrapper), and [here is a sample app](https://github.com/commonsguy/cw-omnibus/tree/master/ContentProvider/V4FileProvider) showing its use with a small subclass of `FileProvider`. If it doesn't help with Google+, let me know (e.g., issue on the CWAC-Provider tracker). – CommonsWare Mar 23 '15 at 23:58

1 Answers1

3

Based on work by Stefan Rusek, I created LegacyCompatCursorWrapper, designed to help improve compatibility of FileProvider (and other ContentProvider implementations) with client apps that are looking for _DATA columns and not finding them. The _DATA pattern was used originally by MediaStore, but it was never a good idea for apps to try referring to that column.

To use it in conjunction with FileProvider, add my CWAC-Provider library as a dependency, and then create your own subclass of FileProvider, such as this one:

/***
 Copyright (c) 2015 CommonsWare, LLC
 Licensed under the Apache License, Version 2.0 (the "License"); you may not
 use this file except in compliance with the License. You may obtain a copy
 of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
 by applicable law or agreed to in writing, software distributed under the
 License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
 OF ANY KIND, either express or implied. See the License for the specific
 language governing permissions and limitations under the License.

 From _The Busy Coder's Guide to Android Development_
 http://commonsware.com/Android
 */

package com.commonsware.android.cp.v4file;

import android.database.Cursor;
import android.net.Uri;
import android.support.v4.content.FileProvider;
import com.commonsware.cwac.provider.LegacyCompatCursorWrapper;

public class LegacyCompatFileProvider extends FileProvider {
  @Override
  public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    return(new LegacyCompatCursorWrapper(super.query(uri, projection, selection, selectionArgs, sortOrder)));
  }
}

All this does is wrap the FileProvider query() results in a LegacyCompatCursorWrapper. The rest of your app configuration would be identical to using FileProvider directly (e.g., <meta-data> element), except that your <activity> element's android:name attribute would point to your own class. You can see this in action in this sample app.

Community
  • 1
  • 1
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 1
    Why should we use CWAC library when things explained in the following link works fine. Is it like some devices it wont work or something? https://medium.com/androidsrc/share-cache-files-with-other-android-apps-using-fileprovider-897fe5705e45 – nizam.sp Mar 07 '18 at 12:54
  • @nizam.sp: That is covered in the answer and in [the answer that I linked to](https://stackoverflow.com/a/25020642/115145). Many apps think that any `Uri` with a `content` scheme must have a `_DATA` column. That is incorrect, and was never correct, but it worked with the `MediaStore`, which is all that some developers cared about a few years ago. – CommonsWare Mar 07 '18 at 13:49