From 6c52efc50c2906b3fcd18934d9942399e0879cb1 Mon Sep 17 00:00:00 2001 From: Avinash David Date: Thu, 6 Apr 2017 15:41:45 -0500 Subject: [PATCH] feat: share image directly via share menu item Solves issue #30. Previously, there were permission problems from trying to share the image to image sharing apps, according to the issue tracker. The following changes were made: FileProvider class is defined in AndroidManifest, along with the required meta-data and associated files (a string was added to strings.xml for the provider authority). This is apparently required for sharing streams in Android M and above. Temporary file of the image is written to keep track of exact file location, as well as have a temporary cache of previously shared images. This is done in an AsyncTask that is defined at the bottom of SubjectFragment and executed in the updateShareIntent method. In devices with Android M or above, explicit permission to write and read images is obtained if not already provided. The FileProvider class is used to create the URI that will eventually be sent in the intent. An intent flag is added for purposes of magic (I'm not really sure what it does, but it works). In the limited use case of trying to share images, this code works. Additional changes might be required to distinguish text from image intents to share, because the code right now will set the share intent to an image type if mUriImageRemote is not null. --- app/app.iml | 24 ++----- app/src/main/AndroidManifest.xml | 10 +++ .../galaxyzoo/app/ClassifyFragment.java | 1 + .../galaxyzoo/app/SubjectFragment.java | 67 +++++++++++++++++++ app/src/main/res/values/strings.xml | 3 + 5 files changed, 88 insertions(+), 17 deletions(-) diff --git a/app/app.iml b/app/app.iml index 19fd22bb..5a074cf1 100644 --- a/app/app.iml +++ b/app/app.iml @@ -63,13 +63,6 @@ - - - - - - - @@ -77,27 +70,24 @@ + + + + + + + - - - - - - - - - - diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 031dcdf6..46754a9d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -139,6 +139,16 @@ + + + + diff --git a/app/src/main/java/com/murrayc/galaxyzoo/app/ClassifyFragment.java b/app/src/main/java/com/murrayc/galaxyzoo/app/ClassifyFragment.java index 0416f366..a75c77ad 100644 --- a/app/src/main/java/com/murrayc/galaxyzoo/app/ClassifyFragment.java +++ b/app/src/main/java/com/murrayc/galaxyzoo/app/ClassifyFragment.java @@ -24,6 +24,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; diff --git a/app/src/main/java/com/murrayc/galaxyzoo/app/SubjectFragment.java b/app/src/main/java/com/murrayc/galaxyzoo/app/SubjectFragment.java index 2733d689..e0823b21 100644 --- a/app/src/main/java/com/murrayc/galaxyzoo/app/SubjectFragment.java +++ b/app/src/main/java/com/murrayc/galaxyzoo/app/SubjectFragment.java @@ -23,11 +23,17 @@ import android.app.DownloadManager; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.database.Cursor; +import android.graphics.Bitmap; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; +import android.os.Environment; +import android.support.v4.app.ActivityCompat; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; +import android.support.v4.content.FileProvider; import android.support.v4.content.Loader; import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.ShareActionProvider; @@ -45,6 +51,11 @@ import com.squareup.picasso.Callback; import com.squareup.picasso.Picasso; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + /** * A fragment representing a single subject. * This fragment is either contained in a {@link ListActivity} @@ -427,7 +438,63 @@ private void updateShareActionIntent() { //shareIntent.putExtra(Intent.EXTRA_STREAM, mUriImageStandard); //shareIntent.setType("image/*"); + if (mUriStandardRemote!=null) { + GetImageBitmapAsyncTask getImageBitmapAsyncTask = new GetImageBitmapAsyncTask(){ + @Override + protected void onPostExecute(Uri uri) { + shareIntent.setType("image/*"); + shareIntent.putExtra(Intent.EXTRA_STREAM, uri); + shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + mShareActionProvider.setShareIntent(shareIntent); + } + }; + getImageBitmapAsyncTask.execute(mUriStandardRemote); + } + mShareActionProvider.setShareIntent(shareIntent); } + + private static final int REQUEST_EXTERNAL_STORAGE = 1; + private static String[] PERMISSIONS_STORAGE = { + "android.permission.WRITE_EXTERNAL_STORAGE", + "android.permission.READ_EXTERNAL_STORAGE" + }; + + public static void verifyStoragePermissions(Activity activity) { + int permission = ActivityCompat.checkSelfPermission(activity, "android.permission.WRITE_EXTERNAL_STORAGE"); + + if (permission != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions( + activity, + PERMISSIONS_STORAGE, + REQUEST_EXTERNAL_STORAGE + ); + } + } + + private class GetImageBitmapAsyncTask extends AsyncTask { + @Override + protected Uri doInBackground(String... params) { + try { + Bitmap image = Picasso.with(getContext()).load(params[0]).get(); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + image.compress(Bitmap.CompressFormat.JPEG, 100, bytes); + + //TODO: PROVIDE A MORE DESCRIPTIVE FILENAME HERE IF PLAUSIBLE. Filename will be visible when sharing via certain apps like Gmail etc. + String filename = "galaxy_zoo_image.jpg"; + + String pathname = Environment.getExternalStorageDirectory() + File.separator + filename; + File f = new File(pathname); + f.createNewFile(); + FileOutputStream fo = new FileOutputStream(f); + fo.write(bytes.toByteArray()); + return FileProvider.getUriForFile(getActivity(), getString(R.string.authority_fileprovider), f); + } catch (IOException e) { + verifyStoragePermissions(getActivity()); + e.printStackTrace(); + } + return null; + } + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3eeb687b..a98a69ae 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -186,6 +186,9 @@ //when specifying a transition when starting an activity that contains this SubjectFragment. transition_subject_image + + com.murrayc.galaxyzoo.app.fileprovider + 5 subjects