Image not being shared to Apps - java

I want my users to be able to share an image and select an app to share it to whether its something like their native messenger app, or twitter. Whenever I go to select the app I want to share the image to, I get a message saying "This media can't be loaded" or something like that. Here is the sharing code in BitmapUtils.java
static void shareImage(Context context, String imagePath) {
// Create the share intent and start the share activity
File imageFile = new File(imagePath);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
Uri photoURI = FileProvider.getUriForFile(context, FILE_PROVIDER_AUTHORITY, imageFile);
shareIntent.putExtra(Intent.EXTRA_STREAM, photoURI);
context.startActivity(shareIntent);
}
Here is my file provider code in my Manifest file:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.aaronapp.hideme.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
Here is the file_paths file which contains the file paths.
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-cache-path name="my_cache" path="." />
<external-path name="my_images" path="Pictures/" />
</paths>
Here is the share method that is invoked inside the MainActivity class.
/**
* OnClick method for the share button, saves and shares the new bitmap.
*/
#OnClick(R.id.share_button)
public void shareMe() {
// Delete the temporary image file
BitmapUtils.deleteImageFile(this, mTempPhotoPath);
// Share the image
BitmapUtils.shareImage(this, mTempPhotoPath);
}
If you need anymore information that I forgot to show I'll be happy to supply it. I'm trying to fix this issue and get my images to share to different apps(I know Facebook has a certain way of sharing images, but I will tackle that later)
You can also replicate this issue by downloading the Hide me, Emoji App on the google play store, taking a picture and trying to share it across your apps.https://play.google.com/store/apps/details?id=com.aaronapp.hideme

This will allow you to read files from Internal or external sdcard.
Add this in manifest.xml
<!-- this is For Access External file Storage -->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.demo.test.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"/>
</provider>
file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external_files"
path="." />
<root-path
name="external_files"
path="/storage/"/>
</paths>

Try with adding flag Intent.FLAG_GRANT_READ_URI_PERMISSION to Intent
The file you want to share with another app, you need to allow the client app to access the file. To allow access, grant permissions to the client app by adding the content URI to an Intent and then setting permission flags on the Intent.
// Grant temporary read permission to the content URI
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
The permissions you grant are temporary and expire automatically when the receiving app's task stack is finished.

Please try this code, this is working in my case
File filePath = new File(FIlePath);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND_MULTIPLE);
ArrayList<Uri> uriArrayList = new ArrayList<>();
uriArrayList.add(getUriFromFilePath(filePath));
intent.setType("image/*");
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriArrayList);
startActivity(intent);
public Uri getUriFromFilePath(Context theCtx, File theSrcPath) {
Uri requirdUri = null;
// observation
// SDKversion: 25 -- Uri.fromFile Not working, So we have to use Provider
// FileProvider.getUriForFile will not work when the file is located in external Sdcard.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
requirdUri = FileProvider.getUriForFile(theCtx,
theCtx.getApplicationContext().getPackageName() + PROVIDER_FILE_EXTENSION,
theSrcPath);
} else {
requirdUri = Uri.fromFile(theSrcPath);
}
return requirdUri;
}

I have done following changes in your code, i had tested app after
changes and able to share image now.
Please check and let me know.
in MainActivity, shareMe method you have delete the temp file before sharing that why the error was occured.
now i have delete the Temp file after sharing.
Modified code in MainActivity.java
public static final int REQUEST_CODE_SHARE_FILE = 100;
public void shareMe()
{
// BitmapUtils.deleteImageFile(this, mTempPhotoPath); delete temp file in on activity result.
BitmapUtils.shareImage(MainActivity.this, mTempPhotoPath);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
//If the image capture activity was called and was successful
if(requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK)
{
processAndSetImage();
}
else if(requestCode == REQUEST_CODE_SHARE_FILE)
{
BitmapUtils.deleteImageFile(this, mTempPhotoPath);
}else {
BitmapUtils.deleteImageFile(this, mTempPhotoPath);
}
}
Modified code in BitmapUtils.java
static void shareImage(Activity activity, String imagePath) {
// Create the share intent and start the share activity
File imageFile = new File(imagePath);
Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("image/*");
Uri photoURI = FileProvider.getUriForFile(activity, FILE_PROVIDER_AUTHORITY, imageFile);
shareIntent.putExtra(Intent.EXTRA_STREAM, photoURI);
activity.startActivityForResult(shareIntent,MainActivity.REQUEST_CODE_SHARE_FILE);
}
I am testing your app on the device with Android version 6.0 and app gets crashed every time.
Inside detectFacesandOverlayEmoji method, on line number 32(SparseArray faces = detector.detect(frame);)
a) Sometimes app remains open without showing anything in logcat.
b) Sometimes app crashed with following error in logcat.
05-24 11:00:27.192 17880-17880/com.aaronapp.hideme E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.aaronapp.hideme, PID: 17880
java.lang.OutOfMemoryError: Failed to allocate a 51916812 byte allocation with 16765168 free bytes and 36MB until OOM
at com.google.android.gms.vision.Frame.zzTM(Unknown Source)
at com.google.android.gms.vision.Frame.getGrayscaleImageData(Unknown Source)
at com.google.android.gms.vision.face.FaceDetector.detect(Unknown Source)
at com.aaronapp.hideme.HideMe.detectFacesandOverlayEmoji(HideMe.java:32)
at com.aaronapp.hideme.MainActivity.processAndSetImage(MainActivity.java:153)
at com.aaronapp.hideme.MainActivity.onActivityResult(MainActivity.java:133)
at android.app.Activity.dispatchActivityResult(Activity.java:6428)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

Make use of Picasso, sharing you a working code from my project.
Put this in your App level gradle,
implementation 'com.squareup.picasso:picasso:2.71828'
Code used is given below,
static void shareImage(Context context, String imagePath) {
// Create the share intent and start the share activity
Picasso.with(getApplicationContext())
.load(imagePath)
.into(new Target() {
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("image/*");
i.putExtra(Intent.EXTRA_STREAM, getLocalBitmapUri(bitmap));
if (!TextUtils.isEmpty(des)) {
i.putExtra(Intent.EXTRA_TEXT, des);
}
startActivity(Intent.createChooser(i, "Share Image"));
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
}
public Uri getLocalBitmapUri(Bitmap bmp) {
Uri bmpUri = null;
try {
File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES),
"share_image_" + System.currentTimeMillis() + ".png");
FileOutputStream out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
out.close();
bmpUri = Uri.fromFile(file);
} catch (IOException e) {
e.printStackTrace();
}
return bmpUri;
}
Hope it may help you.

Related

java.io.IOException: Permission denied when using Camera on Andoid?

I have confirmed that the permissions are correct for Camera access, however on the later OS versions (perhaps API 25 and above) the camera does not open, it just gives the errror in debug console;
W/System.err: java.io.IOException: Permission denied
This is the method;
public void cameraClicked(View view) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File tempFile = new File(Environment.getExternalStorageDirectory().getPath()+ "/photoTemp.png");
try {
tempFile.createNewFile();
Uri uri = Uri.fromFile(tempFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(takePictureIntent, 2);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
It does work on Android 7 and below.
EDIT - The following code is now opening the camera correctly, however once the photo is taken it progresses to the next screen but does not show the captured image... Just a black image.
public void cameraClicked(View view) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String path=this.getExternalCacheDir()+"file.png";
File file=new File(path);
Uri uri = FileProvider.getUriForFile(MainActivity.this, BuildConfig.APPLICATION_ID + ".provider",file);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(takePictureIntent, 2);
}
W/System.err: java.io.IOException: Permission denied
This happened because you create file to external storage over Android8/9/10.
If your targetSdk is 23 or higher, you should request permissions
dynamically. to know more : Requesting Permissions at Run Time
to get File path you can use
Context.getExternalFilesDir()/Context.getExternalCacheDir() for
example String path=Context.getExternalCacheDir()+"file.text"; File
file=new File(path) it doesnt need permission if the filepath is
"Android/data/app package/file name"
As in the Android Documentation, you need to write to the external storage, you must request the WRITE_EXTERNAL_STORAGE permission in your manifest file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
If you use API 23 (Marshmallow) and above, you need to Requesting Permissions at Run Time because it's a Dangerous Permission.
if (ContextCompat.checkSelfPermission(
CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
PackageManager.PERMISSION_GRANTED) {
// You can use the API that requires the permission.
performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
// In an educational UI, explain to the user why your app requires this
// permission for a specific feature to behave as expected. In this UI,
// include a "cancel" or "no thanks" button that allows the user to
// continue using your app without granting the permission.
showInContextUI(...);
} else {
// You can directly ask for the permission.
// The registered ActivityResultCallback gets the result of this request.
requestPermissionLauncher.launch(
Manifest.permission.REQUESTED_PERMISSION);
}
Reference source link
reference
make file to external
Edit answer
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 0);
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode){
case 0:
if (resultCode == Activity.RESULT_OK){
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
SaveImage(thumbnail);
}
break;
}
}
private static void SaveImage(Bitmap finalBitmap) {
String root = Environment.getExternalStorageDirectory().getAbsolutePath();
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
String fname = "Image-"+ Math.random() +".jpg";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
I also faced this issue before, seems like adding this inside the Application tag under AndroidManifest.xml file solve the problem for me:
<application
...
android:requestLegacyExternalStorage="true">
</application>

Sharing a sticker to Instagram Story broken?

EDIT: Facebook issue : https://developers.facebook.com/support/bugs/2434932356771915/
I'm trying to share a bitmap to an Instagram story sticker.
But it loads Instagram, but doesn't show any sticker, no background colors, only a black story screen.
What is wrong with this code ? I check if file was in the external data cache directory and that's good.
According to Facebook's Instagram documentation :
I added read/write rights to storage and a provider to my AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<provider
android:authorities="my.app.id.fileprovider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
I added a file_paths.xml to share my external cache folder to other apps
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-cache-path name="share" path="."/>
</paths>
</resources>
I create a bitmap from a drawable, write it to a file on the external cache dir, and apply the Intent like example in the docs
public static void sendStickerToInstagram() {
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), R.drawable.sticker);
File extStorageDirectory = context.getExternalCacheDir();
File stickerFile = new File(extStorageDirectory, "sticker.png");
try {
FileOutputStream outStream = new FileOutputStream(stickerFile);
bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
} catch (IOException e) {
Log.e("TEST", e.getMessage());
}
Uri stickerUri = FileProvider.getUriForFile(activity, "my.app.id.fileprovider", stickerFile);
// Uri stickerUri = Uri.fromFile(stickerFile);
String linkUrl = "https://stackoverflow.com";
Intent intent = new Intent("com.instagram.share.ADD_TO_STORY");
intent.setType("image/*");
intent.putExtra("interactive_asset_uri", stickerUri);
intent.putExtra("content_url", linkUrl);
intent.putExtra("top_background_color", "#33FF33");
intent.putExtra("bottom_background_color", "#FF00FF");
grantUriPermission("com.instagram.android", stickerUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (getPackageManager().resolveActivity(intent, 0) != null) {
startActivityForResult(intent, 0);
}
}
Most strange part is when I test to share my sticker as background, it works, so the file is loaded as espected, with all permissions.
Intent intent = new Intent("com.instagram.share.ADD_TO_STORY");
intent.setDataAndType(stickerUri, "image/*");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra("content_url", linkUrl);
if (activity.getPackageManager().resolveActivity(intent, 0) != null) {
activity.startActivityForResult(intent, 0);
}
Any idea why I can't share a sticker ?
Don't worry... It's not you. It's Instagram. :P
Their most recent release of Instagram on Android broke the
com.instagram.share.ADD_TO_STORY intent.
Keep an eye on this thread for updates.
https://developers.facebook.com/support/bugs/2434932356771915/

How to save a bitmap in and share from cache?

I have a method that shares bitmap from the app with 3rd party social media apps. I am trying to save my bitmap to the cache folder and share it from there. This is my method:
public void shareMeme(Bitmap bitmap) {
String path = Objects.requireNonNull(getContext()).getCacheDir().getAbsolutePath();
Uri uri = Uri.parse(path);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
share.putExtra(Intent.EXTRA_STREAM, uri);
share.putExtra(Intent.EXTRA_TEXT, "This is my Meme");
getContext().startActivity(Intent.createChooser(share, "Share Your Meme!"));
Toast.makeText(getContext(), "The Cache drive is: " + path, Toast.LENGTH_LONG).show();
}
The method gets the bitmap from another method through its parameters. I want to know how to incorporate the shareMeme(Bitmap bitmap) parameters with the above code.
UPDATE
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.omar.memegenerator">
...
<application
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.omar.memegenerator.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
...
</application>
</manifest>
The new shareMeme(Bitmap bitmap) method:
public void shareMeme(Bitmap bitmap) {
String path = Objects.requireNonNull(getContext()).getCacheDir().getAbsolutePath();
File file = new File(path + "/Memes/" + timeStamp + counter + ".jpg");
Uri uri = FileProvider.getUriForFile(getContext(), "com.example.omar.memegenerator.fileprovider", file);
try {
OutputStream stream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
stream.flush();
stream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
share.putExtra(Intent.EXTRA_STREAM, uri);
share.putExtra(Intent.EXTRA_TEXT, "This is my Meme");
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
getContext().startActivity(Intent.createChooser(share, "Share Your Meme!"));
Toast.makeText(getContext(), "The Cache drive is: " + path, Toast.LENGTH_LONG).show();
}
Stack Trace:
2019-04-09 05:08:51.324 19288-19288/com.example.omar.memegenerator E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.omar.memegenerator, PID: 19288
java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/com.example.omar.memegenerator/cache/Memes/201904090.jpg
at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:739)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:418)
at com.example.omar.memegenerator.TopImageFragment.shareMeme(TopImageFragment.java:232)
at com.example.omar.memegenerator.TopImageFragment$6.onReceive(TopImageFragment.java:303)
at android.support.v4.content.LocalBroadcastManager.executePendingBroadcasts(LocalBroadcastManager.java:313)
at android.support.v4.content.LocalBroadcastManager$1.handleMessage(LocalBroadcastManager.java:121)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6703)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)
Step #1: Use compress() on Bitmap to save it to a file in getCacheDir()
Step #2: Add FileProvider to your project, configured to serve files from getCacheDir()
Step #3: Use FileProvider.getUriForFile(), instead of your existing code, to get a Uri to put in EXTRA_STREAM
Step #4: Add Intent.FLAG_GRANT_READ_URI_PERMISSION to the Intent before calling startActivity(), so the recipient has rights to access your content

FileProvider failed to find configured root that contains... error

I have seen this question asked previously, but before you mark this question as redundant let me just say that I've been trying to figure this out for three hours and I'm just confused. My goal is to take a photo, set it to an imageview, and upload it to Firebase Storage. In order to get the full size photo, I believe I have to save it to a local file, because the FileProvider takes a reference to a file and that's where the full size photo goes. Is that correct so far? I cannot for the life of me get the FileProvider to accomplish this.
After many attempts, this is what I have:
// It all starts here
public void onClick(View v) {
Log.d("DebugMySocks", "Change photo button clicked");
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(getApplicationContext(),
getPackageName(),
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp;
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
mProfileImage.setImageBitmap(imageBitmap);
}
}
// in manifest file
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
// in /xml/filepaths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="com.example.kevin.moresocksplease/files/Pictures" />
</paths>
and the error message is:
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example.kevin.moresocksplease/files/Pictures/JPEG_20171214_111337.jpg706457555.jpg
Replace:
<external-path name="my_images" path="com.example.kevin.moresocksplease/files/Pictures" />
with:
<external-files-path name="my_images" />

Android Share Multiple Images with Other Apps

I'm attempting to use the native Android share functionality to share a set of images I retrieved using Glide. So any app that is compatible with the images will show up in Android's share menu.
I created a method that gets invoked when share is clicked.
private void onShareClicked() {
GlideUrl glideUrl = new GlideUrl(url1, new LazyHeaders.Builder().addHeader("x-auth-token", mToken).build());
FutureTarget<File> image1 = mGlide.load(glideUrl).downloadOnly(SIZE_ORIGINAL, SIZE_ORIGINAL);
glideUrl = new GlideUrl(url2, new LazyHeaders.Builder().addHeader("x-auth-token", token).build());
FutureTarget<File> image2 = mGlide.load(glideUrl).downloadOnly(SIZE_ORIGINAL, SIZE_ORIGINAL);
new ShareImagesTask(this, "image/png").execute(image1, image2);
}
Then created ShareImagesTask which allows you to share multiple images by completing the request to get the images files via Glide:
public class ShareImagesTask extends AsyncTask<FutureTarget<File>, Void, ArrayList<Uri>> {
private final Context mContext;
private final String mMimeType;
public ShareImagesTask(Context context, String mimeType) {
this.mContext = context;
this.mMimeType = mimeType;
}
#Override
protected ArrayList<Uri> doInBackground(FutureTarget<File>... targets) {
final ArrayList<Uri> imageUris = new ArrayList<>(targets.length);
for(FutureTarget<File> target : targets) {
try {
File file = target.get();
Uri uri = FileProvider.getUriForFile(mContext, "com.myapp.fileprovider", file);
imageUris.add(uri);
} catch (Exception ex) {
Log.w("SHARE", "Sharing failed for one or more image files.", ex);
}
}
return imageUris;
}
#Override
protected void onPostExecute(ArrayList<Uri> result) {
if(!result.isEmpty()) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND_MULTIPLE);
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, result);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setType(mMimeType);
mContext.startActivity(Intent.createChooser(intent, "Share Your Photo"));
}
}
}
Here is my AndroidManifest.xml FileProvider:
<provider
android:name=".provider.MyAppFileProvider"
android:authorities="com.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
And finally, filepaths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="shared_images" path="/data/data/com.myapp/cache/image_manager_disk_cache/"/>
</paths>
I am able to get to the point of calling FileProvider.getUriForProvider() and it gives the exception below. I have also tried changing the path in filepaths.xml to variations of the path mentioned in the exception but I get the same error. Any ideas?
java.lang.IllegalArgumentException: Failed to find configured root
that contains
/data/data/com.myapp/cache/image_manager_disk_cache/11fa9845150748cc77d49a75954d92f246cc7095e72e36b85d6a07dbdeb9cf46.0
Replace:
<cache-path name="shared_images" path="/data/data/com.myapp/cache/image_manager_disk_cache/"/>
with:
<cache-path name="shared_images" />
or possibly with:
<cache-path name="shared_images" path="image_manager_disk_cache/"/>
if you are trying to restrict FileProvider to a subset of getCacheDir().

Categories

Resources