1

I am trying to share image stored in Internal memory using Intent. The process is as follows

  • Generate bitmap of a layout
  • Save this bitmap to a file in Internal
  • memory Share this file using intent (to Gmail)

Only empty file seem to be generated on execution (hence, cannot be attached to Gmail). I am not sure where the code begins getting messy. So, here goes the code

Method to Generate and Save Bitmap

    public void generateAndSaveBitmap(View layout) {
//Generate bitmap
        layout.setDrawingCacheEnabled(true);
        layout.buildDrawingCache();
        Bitmap imageToSave = layout.getDrawingCache();
        layout.destroyDrawingCache();

//Create a file and path
        File directory = layout.getContext().getDir("images", Context.MODE_PRIVATE);
        File fileName = new File(directory, "sharableImage.jpg");
        if (fileName.exists())
            fileName.delete();

//Compress and save bitmap under the mentioned fileName
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(fileName);
            imageToSave.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.flush();
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
//    return directory.getAbsolutePath();
    }

Method to Share the Image

public void moreShareOptions(Context context) {
    Intent shareIntent = new Intent(Intent.ACTION_SEND);
    shareIntent.setType("image/jpg");
    File photoFile = new File("sharableImage.jpg");
    shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(photoFile));
    context.startActivity(Intent.createChooser(shareIntent, context.getResources().getText(R.string.opsh_share_this)));
}

These two methods are placed inside onClickListener as below

    case R.id.more_share_options:
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                optionsShareThis.generateAndSaveBitmap(toolbarWebView);
            }
        });

        t.start();
        optionsShareThis.moreShareOptions(this);
        break;

Trying to find the issue. Am I missing something? Also, I would love to hear suggestions (if any) to improve the code.

Regards

EDIT:

Thanks for mentioning about FileProvider. Good to know about getCacheDir. However, even after using FileProvider, my code is continuing to return empty file. I have been exploring multiple resources, yet unable to generate a file with actual Image of the mentioned layout.

generateAndSaveBitmap(View layout) - no changes have been made to this method (code mentioned above).

Below is the code related to FileProvider

AndroidManifest.xml - nothing new to discuss

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.example.android"
    android:exported="false"
    android:grantUriPermissions="true">

    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_path" />

</provider>

file_path.xml - used to mention the file name and its path

<?xml version="1.0" encoding="utf-8"?>

<paths>
    <files-path name="sharableImage" path="images/"/>
</paths>

moreShareOptions() -

    public void moreShareOptions(Context context) {

// concatenate the internal cache folder with the document its path and filename
        final File file = new File(context.getFilesDir(), "images/sharableImage.jpg");
// let the FileProvider generate an URI for this private file
        final Uri uri = FileProvider.getUriForFile(context, "com.example.android", file);
// create an intent, so the user can choose which application he/she wants to use to share this file

        final Intent intent;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            intent = ShareCompat.IntentBuilder.from((Activity) context)
                    .setType("image/jpg")
                    .setStream(uri)
                    .createChooserIntent()
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
                    .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

            context.startActivity(intent);
        }else {
        intent = ShareCompat.IntentBuilder.from((Activity) context)
                .setType("image/jpg")
                .setStream(uri)
                .createChooserIntent()
                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
                .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

            context.startActivity(intent);
        }
    }

What have I been missing? I have spent hours searching for ways to get the necessary result. Nothing fruitful. Hence, I am posting this code with hope that others might be able to point out where I am going wrong.

Traveller
  • 157
  • 1
  • 3
  • 8

1 Answers1

0

Third-party apps do not have access to your internal storage. And, particularly starting with Android N, sharing files is strongly discouraged in general.

Instead, use FileProvider to share the content. This is also covered in the documentation.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks for mentioning about FileProvider. Still getting only an empty file. Is there something wrong with the code related to generating and saving the Bitmap? Please check the EDIT section for updated code. Any kind of indication to where i messed-up might actually help. – Traveller Apr 23 '16 at 10:02