I am trying to share an image by sending a Bitmap. The solution i found works on the emulator for Android 10.0 but not on Android 7.0 (neither on my LG V20 running Android 9) where it crashes.
Here is my current code. Any idea how to avoid the crash? Thanks in advance for your help.
picIV.buildDrawingCache();
Bitmap bitmap = picIV.getDrawingCache();
String path = MediaStore.Images.Media.insertImage(getContentResolver(),
bitmap, "Challengers", null);
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, "I found something cool!");
startActivity(Intent.createChooser(share, "Share Your Design!"));
The crash seems to be happenning when running this line
Uri uri = Uri.parse(path);
Maybe your path is null? Did you debug it?
From the source of the method Uri.parse(...) I noticed that it returns an error if it takes null as an argument and MediaStore.Images.Media.insertImage(...) returns null "if the image failed to be stored for any reason".
Found another method that worked on Android 7 but not on Android 10. So found out a way to make them work together.
Uri uri;
String path = MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Challengers", null);
if (path!=null) {
uri = Uri.parse(path);
}else{
uri = null;
String string="" ;
try {
File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "to-share.png");
FileOutputStream stream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
stream.close();
uri = Uri.fromFile(file);
} catch (IOException e) {
Log.d(string, "IOException while trying to write file for sharing: " + e.getMessage());
}
}
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
share.putExtra(Intent.EXTRA_STREAM, uri);
//share.putExtra(Intent.EXTRA_TEXT, "I found something cool!");
startActivity(Intent.createChooser(share, "Share Your Design!"));
This should work across each API -- Answer is in Koltin
Create Bitmap From View
fun createBitmapFromView(view: View): Bitmap {
val bitmap = Bitmap.createBitmap(view.measuredWidth,
view.measuredHeight, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
view.layout(view.left, view.top, view.right, view.bottom)
view.draw(canvas)
return bitmap
}
Create a File for saving the Bitmap
fun getFileFromBitmap(bitmap: Bitmap): File? {
val parentDirectory = File(externalCacheDir, "reminder_images") //image file is stored in external cache directory/reminder_images
if (!parentDirectory.exists()) {
parentDirectory.mkdirs()
}
val externalCacheFile = File(parentDirectory, "name_of_your_file.png")
return writeBitmapToFile(externalCacheFile, bitmap)
}
Write the Bitmap to File using Stream
fun writeBitmapToFile(externalCacheFile: File, bitmap: Bitmap): File? {
return try {
val fOut = FileOutputStream(externalCacheFile)
bitmap.compress(Bitmap.CompressFormat.PNG, 85, fOut)
fOut.flush()
fOut.close()
externalCacheFile
} catch (e: Exception) {
null
}
}
Create the FileProvider in Manifest
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.your_package_name.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
5.Create the provider_paths.xml resource file
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
Get Uri From File using FileProvider
val uri = FileProvider.getUriForFile(context,"com.your_package_name.FileProvider", externalCacheFile)
Once you have the Uri of the image file share the file as you were doing earlier using Intent.
In my solution, the image file is stored in app-specific external directories. This image file would be deleted if your app is uninstalled. If you want some other behaviour please check data-storage.
Finally found the problem. It was the permissions. Even though i had put the permissions in the Manifest.xml also need to add a couple lines in onCreate.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);
onRequestPermissionsResult(requestCode,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},grantResults);
Thanks everyone for your answers, really helpful!
Related
I dont know if im doing something wrong maybe im not using the image at all or im compressing the image in the wrong way because when im tring to send it to a server it responds me saying that the size is over 10 MB when my phone takes pictures jpg around 7-9 MB (In the Edit.java I have a comment that I before was using the thumbnail but needed to change it cause the thumbnail has a bad quality when im trying to see it in a Desktop)
Here is my code:
AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera"></uses-feature>
<provider
android:authorities="cam.com.example.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_path"/>
</provider>
file_path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external"
path="/"/>
<external-files-path
name="external_files"
path="/"/>
<cache-path
name="cache"
path="/"/>
<external-cache-path
name="external_cache"
path="/"/>
<files-path
name="files"
path="/"/>
</paths>
Edit.java
btn_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
REQUEST_IMAGE_CAPTURE = 1;
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getPackageManager()) != null) {
File imageFile = null;
try{
imageFile=getImageFile();
}catch (IOException e){
e.printStackTrace();
}
if(imageFile!=null){
Uri imageUri = FileProvider.getUriForFile(Edit.this,"cam.com.example.fileprovider",imageFile);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);
}
}
} catch (Exception e) {
Toasty.warning(getApplicationContext(), IC, Toast.LENGTH_SHORT, true).show();
}
}
});
public File getImageFile() throws IOException{
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageName = "jpg_"+timeStamp+"_";
File storageDir = getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File imageFile = File.createTempFile(imageName,".jpg",storageDir);
currentImagePath = imageFile.getAbsolutePath();
return imageFile;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
if (imagenString == null) {
File imgFile = new File(currentImagePath);
String path = imgFile.getAbsolutePath();
Bitmap mybitmap = BitmapFactory.decodeFile(path);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mybitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
imagenString = Base64.encodeToString(byteArray, Base64.DEFAULT);
/* **Before I was doing this, but the thumbnail has such a bad quality so needed to change it**
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
imagenString = Base64.encodeToString(byteArray, Base64.DEFAULT);*/
}
}
}
You are taking a picture with the user's choice of camera app. Usually, that will be saved as a JPEG image. JPEG images are compressed image formats, optimized for "real-world" images like photos.
You then attempt to read it all into memory. This is not a good plan, as you may not have enough memory to do that, for a full-size photo.
You then attempt to take the resulting Bitmap and encode it in PNG. PNG is a compressed image format, but one that is designed for icons and other artwork. A photo will almost always take more space in PNG than in JPEG. Worse, you are trying to encode it as a PNG into memory — again, you may not have sufficient memory to do this.
You then attempt to convert the encoded PNG into base-64. This will take up even more space than the encoded PNG, and, once again, you may not have sufficient memory for this.
I would expect your app to crash with an OutOfMemoryError a lot.
The best solution is to get rid of most of this, and simply upload the JPEG direct from disk. Do not load it into memory, do not convert it to PNG, and do not convert it to base-64.
It is because you're converting your image to Base64-encoding string which makes the size of the data bigger.
In the following code you're using a value of 100 for the compression, 100 is least compression and high quality.
mybitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
You can try to compress more your image, but it reduces the quality a bit:
mybitmap.compress(Bitmap.CompressFormat.PNG, 70, byteArrayOutputStream);
EDIT:Ok I have tried the suggestions and changed it to getExternalFilesDir() and am still getting the same error. Skip to the bottom where it says "EDITED CODE" to see what it is now. I also changed it so that the screenshot will save to the pictures directory instead of creating a new directory. (END EDIT)
I have an android app that contains a recyclerview. I have created a button that will export create a PNG of the recyclerview data, save it to the device, and then send it as an attachment to the email application so it can be emailed. I'm getting the exception " java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/ExportedFlares/FlareData.png"
Here is the code for the function that saves the bitmap to the device:
private void saveBitmap(Bitmap bitmap){
if(bitmap!=null){
try {
FileOutputStream outputStream = null;
try {
String file_path = Environment.getExternalStorageDirectory().getAbsolutePath() +
"/ExportedFlares";
File dir = new File(file_path, "FlareData");
if(!dir.exists())
dir.mkdirs();
outputStream = new FileOutputStream(dir); //here is set your file path where you want to save or also here you can set file object directly
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); // bitmap is your Bitmap instance, if you want to compress it you can compress reduce percentage
// PNG is a lossless format, the compression factor (100) is ignored
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
And here is the onClick code for when the button is tapped:
public void onClick(View v) {
saveBitmap(getScreenshotFromRecyclerView(recyclerView));
String filename = "FlareData.png";
File fileLocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/ExportedFlares", filename);
Uri path = FileProvider.getUriForFile(FlareActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileLocation);
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailIntent .setType("vnd.android.cursor.dir/email");
String to[] = {"email#gmail.com"};
emailIntent .putExtra(Intent.EXTRA_EMAIL, to);
emailIntent .putExtra(Intent.EXTRA_STREAM, path);
emailIntent .putExtra(Intent.EXTRA_SUBJECT, "Subject");
startActivity(Intent.createChooser(emailIntent , "Send email..."));
The final line of the following code is what is throwing the exception:
File fileLocation = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/ExportedFlares", filename);
Uri path = FileProvider.getUriForFile(FlareActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileLocation);
Here is the XML data, I have provider_paths.xml here:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="FlareData.png" path="ExportedFlares/"/>
</paths>
And this is from the manifest:
enter code here
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
EDITED CODE:
emailFlaresButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = getApplicationContext();
saveBitmap(context, getScreenshotFromRecyclerView(recyclerView));
String filename = "FlareData.png";
File fileLocation = new File(context.getExternalFilesDir(DIRECTORY_PICTURES).getAbsolutePath()
, filename);
Uri path = FileProvider.getUriForFile(FlareActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileLocation);
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
emailIntent .setType("vnd.android.cursor.dir/email");
String to[] = {"asd#gmail.com"};
emailIntent .putExtra(Intent.EXTRA_EMAIL, to);
emailIntent .putExtra(Intent.EXTRA_STREAM, path);
emailIntent .putExtra(Intent.EXTRA_SUBJECT, "Subject");
startActivity(Intent.createChooser(emailIntent , "Send
email..."));
// Intent intent = new Intent(FlareActivity.this,
AddFlareActivity.class);
//startActivityForResult(intent, ADD_FLARE_RESULT_CODE);
}
});
And here is the piece of code that the error is pointing to (the last line) :
Uri path = FileProvider.getUriForFile(FlareActivity.this, BuildConfig.APPLICATION_ID + ".provider",fileLocation);
I have tried it with the provider path being set to both external-files-path and external-path and it doesn't affect the issue
EDIT3: Full stack trace:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.android.fibrnah, PID: 22052
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.android.fibrnah/files/Pictures/FlareData.png
at androidx.core.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:739)
at androidx.core.content.FileProvider.getUriForFile(FileProvider.java:418)
at com.android.fibrnah.FlareActivity$2.onClick(FlareActivity.java:84)
at android.view.View.performClick(View.java:6274)
at android.view.View$PerformClick.run(View.java:24859)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6710)
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:770)
Change external-files-path to external-path.
Or, put your files in getExternalFilesDir() (called on a Context). This is the better solution, as your current code will not work on Android Q (by default) and Android R+ (for all apps).
I have a fragment in which it is supposed to capture an image and set it in an imageview and then send that image to a specific mail.
I got the first part, where I can capture the image and display it in the imageview.
But sending that image to another person via mail is not working.
Any help please
Use this
First of all enable drawing cache enabled property on imageview
final Bitmap bitmap = imageView.getDrawingCache();
on Button click to share do this
File dir = new File(Environment.getExternalStorageDirectory(), "AppNameFolder");
if (!dir.exists()) {
dir.mkdirs();
}
final File img = new File(dir, "image" + ".jpg");
if (img.exists()) {
img.delete();
}
final OutputStream outStream = new FileOutputStream(img);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
Uri photoURI = FileProvider.getUriForFile(context, getPackageName() + ".my.package.name.provider", img);
share.putExtra(Intent.EXTRA_STREAM, photoURI);
startActivity(Intent.createChooser(share, "Share image"));
Note:-
Make sure you have used File Provider and Read/Write Persmissions also
</application>
....
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="android.getqardio.com.gmslocationtest"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
</application>
where xml/provider_paths is
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path
name="share"
path="external_files"/>
</paths>
You can send image as an attachment via mail by using below code:
Intent i = new Intent(Intent.ACTION_SEND);
i.putExtra(Intent.EXTRA_EMAIL, new String[]{"abc#gmail.com"});
i.putExtra(Intent.EXTRA_SUBJECT,"Image as an attachment via mail");
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(pic));
i.setType("image/png");
startActivity(Intent.createChooser(i,"Share an Image"));
Happy Coding :)
Bitmap icon = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
icon.compress(Bitmap.CompressFormat.JPEG, 50, bytes);
File f = new File(Environment.getExternalStorageDirectory() + File.separator + "temporary_file.jpg");
try {
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
} catch (IOException e) {
e.printStackTrace();
}
Uri screenshotUri = Uri.fromFile(f);
sharingIntent.setType("image/jpg");
sharingIntent.putExtra(Intent.EXTRA_STREAM, screenshotUri);
context.startActivity(Intent.createChooser(sharingIntent, "share image"));
the below code helped me solve the above problem.
Intent intent=new Intent(Intent.ACTION_SEND);
intent.setType("message/rfc822");
intent.setType("image/png");
intent.putExtra(Intent.EXTRA_EMAIL, new String[]{"abc#gmail.com"});
intent.putExtra(Intent.EXTRA_SUBJECT, "Identification");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://"+mCurrentPhotoPath));
intent.putExtra(Intent.EXTRA_TEXT, str_mobile+","+str_mail);
try
{
startActivity(Intent.createChooser(intent,"Send mail..."));
}
catch (android.content.ActivityNotFoundException e)
{
Toast.makeText(getActivity().getApplicationContext(),"THERE ARE NO EMAIL CLIENTS INSTALLED",Toast.LENGTH_LONG).show();
}
I'm using the following code to share an audio file with Android Studio 3.3.2 and Java. The file is extracted from the /raw/ folder.
public void funktionTeilen(String file) {
Uri uri = Uri.parse("android.resource://" + this.getPackageName() + "/raw/" + file);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/mpeg3");
share.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(share, "Audio teilen"));
}
In principle the sharing works fine, but the file is sent without a file extension, which of course makes it unreadable by most apps. If I add the file extension manually (for example after downloading it from the e-mail client), the MP3 works fine.
"file" is fed in by another function and corresponds to the file name from the raw folder. It is also found basically, otherwise the sharing process would not work at all.
So, how can I share a file with retention of the file extension? Thanks for your help!
Update #1
public void funktionTeilen(String Datei) {
try {
File tmpFile = new File(this.getCacheDir() + "/tmpfile.mp3");
InputStream in = getResources().openRawResource(R.raw.meise1);
FileOutputStream out = new FileOutputStream(tmpFile, true);
byte[] buff = new byte[1024];
int read = 0;
try {
while ((read = in.read(buff)) > 0) {
out.write(buff, 0, read);
}
} finally {
in.close();
out.close();
}
// Uri uri = FileProvider.getUriForFile(this, this.getPackageName(), tmpFile);
Uri uri = Uri.fromFile(tmpFile);
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/*");
share.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(share, "Audio teilen"));
} catch (Exception e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
}
I'm using the following code to share an audio file with Android Studio 3.3.2 and Java
You are sharing a resource. That is a file on your development machine. It is not a file on the device.
In principle the sharing works fine, but the file is sent without a file extension, which of course makes it unreadable by most apps.
In Android, resources do not have file extensions when we work with them using the Android SDK.
So, how can I share a file with retention of the file extension?
If you share an actual file, using FileProvider, it will have a file extension. So, copy the bytes corresponding to your resource to a file (e.g., in getCacheDir()), then set up FileProvider and use FileProvider.getUriForFile() to get the Uri to use with EXTRA_STREAM.
I worked out the solution!
MainActivity.java
public void funktionTeilen(String Datei) {
try {
File tmpFile = new File(this.getCacheDir() + "/tmpfile.mp3");
InputStream in = getResources().openRawResource(R.raw.meise1);
FileOutputStream out = new FileOutputStream(tmpFile, false);
byte[] buff = new byte[1024];
int read = 0;
try {
while ((read = in.read(buff)) > 0) {
out.write(buff, 0, read);
}
} finally {
in.close();
out.close();
/* if (tmpFile.exists()) {
Toast.makeText(MainActivity.this, tmpFile.getAbsolutePath(), Toast.LENGTH_LONG).show();
} */
}
Uri uri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID, tmpFile.getAbsoluteFile());
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("audio/mpeg3");
share.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(Intent.createChooser(share, "Audio teilen"));
} catch (Exception e) {
Toast.makeText(MainActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<application>
<provider
android:name="android.support.v4.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="${applicationId}">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_provider_paths"/>
</provider>
</application>
file_provider_paths.xml
<paths>
<cache-path name="cache" path="/" />
<files-path name="files" path="/" />
</paths>
What I am trying to do is to get a file that is in the private area to be opened by another program. In this example, a image viewer app.
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.myapp"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/path" />
</provider>
/res/xml/path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="cache" path="cache/"/>
</paths>
Java code (file location)
File file = new File(context.getApplicationInfo().dataDir + File.separator + "cache" + File.separator + filename);
Java code (open file)
if(file != null && file.isFile() && file.canRead() && file.length() > 0){
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
List<ResolveInfo> resInfoList = this.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
Uri uri = Uri.parse(file.toURI().toString());
for (int i = 0; i < resInfoList.size(); i++) {
try{
ResolveInfo resolveInfo = resInfoList.get(i);
String packageName = resolveInfo.activityInfo.packageName;
grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}catch(Exception e){
}catch(Error e){
}
}
MimeTypeMap myMime = MimeTypeMap.getSingleton();
Intent newIntent = new Intent(Intent.ACTION_VIEW);
String mimeType = myMime.getMimeTypeFromExtension(".jpg");
newIntent.setDataAndType(Uri.fromFile(file), mimeType);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(newIntent);
return true;
} catch (Exception e) {
}
}
This always results in a toast message "Unable to find item". What am I doing wrong and how to resolve this?
What am I doing wrong
File file = new File(context.getApplicationInfo().dataDir + File.separator + "cache" + File.separator + filename);
Use getCacheDir() to get the cache directory, as your approach is not going to be reliable for secondary accounts on Android 4.2+ tablets and Android 5.0+ phones. So, this should be:
File file = new File(context.getCacheDir(), filename);
Then, you need to replace Uri.fromFile(file) with a call to getUriForFile() on FileProvider, as is covered in the documentation. What you presently have is a Uri pointing to a file, not pointing to a ContentProvider, let alone your FileProvider implementation.
Finally, you will need to call addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) on the Intent before you use it with startActivity(), as otherwise the app that responds to the startActivity() request will not have access to the content.
This sample app demonstrates a working implementation of a FileProvider.