Opening a downloaded PDF file - android

I'm trying to open downloaded pdf file trough implicit intent using FileProvider.
I'm using DownloadManager for downloading pdf file from remote server, It's working fine. Which is store at it's destination.
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(DownloadURL));
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
request.setAllowedOverRoaming(false);
request.setTitle(mFilename);
request.setDescription("Downloading...");
request.setVisibleInDownloadsUi(true);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "/FOLDER_NAME/" + mFilename);
After Finishing Download i want to open it.
public void OpenPdfFile(){
File sharedFile = new File(Environment.DIRECTORY_DOWNLOADS, "/FOLDER_NAME/" + mFilename);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri uri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID+ ".provider", sharedFile);
intent.setDataAndType(uri, "application/pdf");
PackageManager pm = mContext.getPackageManager();
if (intent.resolveActivity(pm) != null) {
mContext.startActivity(intent);
}
}
in Manifest file
<provider
android:name="android.support.v4.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>
and the provider_paths.xml as like
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external-path" path="." />
</paths>
it troughs me this error
java.lang.IllegalArgumentException: Failed to find configured root that contains /Download/FOLDER_NAME/demo_presentationfile.PDF
Any suggestions ?

File sharedFile = new File(Environment.DIRECTORY_DOWNLOADS, "/FOLDER_NAME/" + mFilename);
That evaluates to an impossible file system path. Which you would see if you inspected the value of sharedFile.getAbsolutePath().
Change to:
File sharedFile = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOWNLOADS), "FOLDER_NAME/" + mFilename);

Related

Unable to open file using FileProvider

I wish to open a file from downloads folder (/storage/emulated/0/Download) and this is my code
I first check if the file exists
File file = new File("/storage/emulated/0/Download" + File.separator + <file-name> + ".pdf");
if(file.exists()) {
openfile("/storage/emulated/0/Download" + File.separator + <file-name> + ".pdf");
Log.d("upload", "onClick: already exists");
}
else {
downloadfile(Url);
Log.d("upload", "onClick: download");
}
If the file exists I use this code to open the file
public void openfile(String path){
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID+".provider",new File(path));
intent.setDataAndType(uri, "application/pdf");
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.EXTRA_STREAM,uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(Intent.createChooser(intent,"Choose an application"));
}
This is my manifest
<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/path"/>
</provider>
and my path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
When I click to open the file it shows intent chooser and when drive pdf viewer is selected it opens up with a blank screen and closes immediately and when any other app is chosen then it shows error File not found(content://(package-name).provider/storage%2Femulated%2F0/Download/file-name.pdf). I don't know what I am doing wrong.
maybe not
intent.addFlags(Intent.EXTRA_STREAM,uri);
but
intent.putExtra(Intent.EXTRA_STREAM, uri)
?

Android open image from internal storage with intent

I'm trying to follow these instructions https://developer.android.com/reference/android/support/v4/content/FileProvider for opening an image with Intent from internal folder.
My path image is '/data/data/com.saffru.colombo.cartellaclinica/files/imgs/IMG-20200422-WA0001.jpg'
In my Manifest I added the provider as follow
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.saffru.colombo.cartellaclinica.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
My provider_paths.xml is
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
<files-path name="my_images" path="img/"/>
<cache-path name="img" path="img" />
</paths>
In my Activity I've an Imageview where I show the Bitmap image and with a click a user can open this image, but it doesn't work. Here my code
File file = new File(pathFile);
File imagePath = new File(getFilesDir(), "img");
File newFile = new File(imagePath, file.getName());
Uri contentUri = FileProvider.getUriForFile(ViewEsameActivity.this,
"com.saffru.colombo.cartellaclinica.fileprovider", newFile);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
//Uri uri = Uri.parse("content://" + file.getAbsolutePath());
grantUriPermission("com.saffru.colombo.cartellaclinica" +
".fileprovider", contentUri,
FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(contentUri,"image/*");
intent.setFlags(FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
Once the Gallery application is opened I receive the error 'File format isn't supported or file are corrupted'

Attach image using Intent.ACTION_SEND

I'm trying to attach an image using different applications with the following code:
val sendIntent = Intent(Intent.ACTION_SEND)
sendIntent.putExtra(Intent.EXTRA_TEXT, "Test example")
sendIntent.type = "image/png"
sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(logo.absolutePath))
startActivity(sendIntent)
The image that is attached is generated with this code:
// Generate file for application logo
val path = Environment.getExternalStorageDirectory().absolutePath
val logo = File(path, "logo.png")
// If logo doesn't exist
if (!logo.exists())
{
// Create new file
logo.createNewFile()
// Save application logo to new file
val fOut = FileOutputStream(logo)
val image = BitmapFactory.decodeResource(applicationContext.resources, R.mipmap.ic_launcher_round)
image.compress(Bitmap.CompressFormat.PNG, 100, fOut)
fOut.flush()
fOut.close()
}
But when I try to open GMAIL with this intent, only text shows app with an error: Couldn't attach file.
What am I missing?
EDIT
Here is another solution: android.os.FileUriExposedException: file.jpg exposed beyond app through ClipData.Item.getUri()
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
From Android N you have to use FileProvider to Obtain Uri.
Please see below example for file sharing.
ArrayList<Uri> files = new ArrayList<Uri>();
File file = new File(<Your File Path>);
Uri uri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(DetailActivity.this, BuildConfig.APPLICATION_ID + ".provider", file);
} else {
uri = Uri.fromFile(file);
}
files.add(uri);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND_MULTIPLE);
intent.putExtra(Intent.EXTRA_SUBJECT, "Product Sharing");
intent.setType("image/jpeg");
intent.putExtra(Intent.EXTRA_TEXT, "ANY TEXT MESSAGE");
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, files);
startActivity(intent);
Place below code in AndroidManifest.xml in Application tag
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths" />
</provider>
and place filepath.xml file in xml resource directory
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
You cannot send file without file provider. Gmail, for example, doesn't request READ/WRITE_EXTERNAL_STORAGE permissions, so it cannot access your file. You must use file provider with GRANT_READ_URI_PERMISSION. You can read more here
https://developer.android.com/reference/android/support/v4/content/FileProvider
https://developer.android.com/training/secure-file-sharing/setup-sharing
https://developer.android.com/training/secure-file-sharing/share-file

How does FileProvider choose/differentiate provider paths in provider_path.xml?

I got to use FileProvider in order to install an apk. Everything works well now but I don't really understand the behaviour FileProvider follows in order to choose the correct path defined inside the provider_paths.xml. Here's my code:
Manifest.xml
<provider
android:name="android.support.v4.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>
main_activity.java
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
intent = new Intent(Intent.ACTION_VIEW);
File apk = new File("/sdcard/example.apk");
String fileType = "application/vnd.android.package-archive";
intent.setDataAndType(Uri.fromFile(apk), fileType);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
} else {
intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
File directory = new File(Environment.getExternalStorageDirectory().toString());
File apk = new File(directory, "example.apk");
Uri fileUri = FileProvider.getUriForFile(this, valoresGenerales.appContext.getPackageName() + ".provider", apk);
String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(apk.getName()));
intent.setDataAndType(fileUri, type);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
startActivity(intent);
provider_paths.xml
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="." />
<files-path name="files_path" path="Download"/>
</paths>
What does make FileProvider choose between external_path or files_path (or whatever defined in the file) depends on?

Why using a FileProvider I can't open file from INTERNAL STORAGE with external apps?

I created an app which can import file in its internal storage.
In order to open a file with an external app (for example PF viewer or Photos) I tried to follow these guides: the official guide, topic1, topic2, topic3 and topic4 but without success.
Here is my code:
in my manifest
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.myapp.chatcher"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
my package value: package="com.myapp.catcher"
my file_paths.xml
<paths
xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="projection" path="." />
</paths>
my code
String fileName = path.substring(path.lastIndexOf("/") + 1);
String shelf = path.substring(path.lastIndexOf("PRIVATE") + 8, path.lastIndexOf("/"));
File filePath = new File(mContext.getFilesDir(), "PRIVATE".concat("/").concat(shelf).concat("/"));
File newFile = new File(filePath, fileName);
Uri contentUri = FileProvider.getUriForFile(mContext, "com.myapp.chatcher", newFile);
Intent myIntent = new Intent();
myIntent.setAction(Intent.ACTION_VIEW);
myIntent.setData(contentUri);
myIntent.setType(mimeType);
myIntent.setFlags(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
mContext.startActivity(myIntent);
I created a hierarchy like this:
PRIVATE -> shelf1 -> my files
-> shelf2 -> my files
-> shelfN -> my files
for example: data/user/0/com.myapp.chatcher/files/PRIVATE/testshelf/Screenshot_2017-01-04-09-45-13.png
the result of printing the newFile.getAbsolutePath() is
/data/user/0/com.myapp.chatcher/files/PRIVATE/bogl/imagetest.jpg
This code opens the chooser in which I can click on "Photos" and then it opens the "Photos app" without show me the imagetest.jpg but the folder in which there are all the pictures.
If i try with a pdf file, it doesn't open the pdf and it appears a toast with the message "no media".
What's wrong with my code?
Thanks to #greenapps that is an android expert, I found that the problem was not in the provider but in the intent.
Instead of this:
Intent myIntent = new Intent();
myIntent.setAction(Intent.ACTION_VIEW);
myIntent.setData(contentUri);
myIntent.setType(mimeType);
myIntent.setFlags(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
mContext.startActivity(myIntent);
I need to do this:
Intent myIntent = new Intent(Intent.ACTION_VIEW);
myIntent.setDataAndType(contentUri, mimeType);
myIntent.setFlags(FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
mContext.startActivity(myIntent);

Categories

Resources