Skip to content

Commit

Permalink
feat: share image directly via share menu item
Browse files Browse the repository at this point in the history
Solves issue murraycu#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.
  • Loading branch information
avitaker committed Apr 6, 2017
1 parent e018a84 commit 6c52efc
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 17 deletions.
24 changes: 7 additions & 17 deletions app/app.iml
Original file line number Diff line number Diff line change
Expand Up @@ -63,41 +63,31 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-resources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard-rules" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/sourceFolderJavaResources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@
<meta-data android:name="android.content.SyncAdapter"
android:resource="@xml/syncadapter" />
</service>

<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="@string/authority_fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
67 changes: 67 additions & 0 deletions app/src/main/java/com/murrayc/galaxyzoo/app/SubjectFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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}
Expand Down Expand Up @@ -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<String,Integer,Uri> {
@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;
}
}
}
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,9 @@
//when specifying a transition when starting an activity that contains this SubjectFragment.
<string name="transition_subject_image" translatable="false">transition_subject_image</string>

<!--share image strings-->
<string name="authority_fileprovider">com.murrayc.galaxyzoo.app.fileprovider</string>

<!-- The possible numbers of items that may be downloaded in advance before they are needed. -->
<string-array name="pref_cache_size_entries">
<item>5 subjects</item>
Expand Down

0 comments on commit 6c52efc

Please sign in to comment.