Opening a PDF file will open a blank PDF - android

I am trying to open a PDF file (already downloaded) in Android App. I am sending ACTION.View intent. The concerned code is as follows
File pdfFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath()
+ File.separator + fileName);
Uri path = FileProvider.getUriForFile(MainActivity.this,BuildConfig.APPLICATION_ID + ".provider", pdfFile);
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.setDataAndType(path, "application/pdf");
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pdfIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
pdfIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
Toast.makeText(this, "hello: "+pdfFile, Toast.LENGTH_SHORT).show();
t1 = findViewById(R.id.textView);
//t1.setText(path.toString() + "####"+pdfFile.getPath());
try{
startActivity(pdfIntent);
}catch(ActivityNotFoundException e){
Toast.makeText(this, "No Application available to view PDF", Toast.LENGTH_SHORT).show();
t1.setText("No applicatoin available");
} catch ( Exception e){
t1.setText("No App Found sorry "+ e.getMessage());
Toast.makeText(this, "No App found, sorry", Toast.LENGTH_SHORT).show();
}
finally {
//Toast.makeText(this, "This is finally block", Toast.LENGTH_SHORT).show();
}
Corresponding XML in the Manifest file is as follows
<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/file_paths" />
</provider>
And the file_paths, content is as follows
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="Download" path="Download"/>
</paths>
Now it works fine to the extent that the PDF is being opened but it shows no content, and is rather blank. What I am suspecting is, the path of the PDF file may not be correct and hence it opens some dummy PDF perhaps? How do I provide correct path to application, I am particularly not sure about this line does in file_paths
**<external-path name="Download" path="Download"/>**
Can someone shed some light on it, how can I can fix it or debug it? What am I possibly doing wrong. I am new to Android development.
Here is my screen when opening PDF file which is basically blank (content is zero).
When I debug the code, the name of the path file is given as follows
content://com.example.openpdf.provider/Download/2019_10_22_03_37_25_pm5906.pdf
which I think is the problem (this pdf file is in the download folder by the way)

Related

How do I programmatically open an external folder in Android?

My app downloads an epub file to /external/downloads/{MyFolder}/. I can normally auto-open the file in an e-reader like Play Books. As a fall back, however, in case of no installed e-reader, I want to open the device's default File Browser to MyFolder. On my device, that browser program is called "My Files".
I'm getting an ActivityNotFoundException. How do I programmatically open that File Browser? Ideally to the {MyFolder} location.
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
File file = new File(fileUri.getPath());
File folder = new File(file.getParent());
Uri folderUri = Uri.fromFile(folder);
intent.setDataAndType(folderUri, "resource/folder");
getContext().startActivity(intent);
} catch (Exception e1) {
Toast.makeText(getContext(), "Ebook saving to " + fileUri.getPath(), Toast.LENGTH_LONG).show();
}
For the record, fileUri.toString() for the epub file is "content://media/external/downloads/16143".
.startActivity(intent) throws the exception:
No Activity found to handle Intent { act=android.intent.action.VIEW dat=content://com.{mydomain}.app.provider/root/external/downloads typ=resource/folder flg=0x1 }
I've also attempted to change folderUri declaration to the following, and get similar errors.
final ContentValues v = new ContentValues();
v.put(MediaStore.Downloads.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS + "/{MyFolder}/");
final ContentResolver r = getContext().getContentResolver();
Uri folderUri = r.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, v);
My AndroidManifest.xml has
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.{mydomain}.app.provider"
android:exported="false"
android:grantUriPermissions="true">
<!-- resource file to create -->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
And my file_paths.xml has
<?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="." />
<root-path name="root" path="." />
</paths>
I've also attempted with the paths being "./", and with no root-path element, and it makes no difference.
If you want directly browse the Camera folder in public DCIM folder with the Files app:
String scheme = "content://com.android.externalstorage.documents/document/primary%3ADCIM%2FCamera";
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(scheme), "vnd.android.document/root");
startActivity(intent );
I assume you can easily change that for Download/MyFolder.
I think this only works for Android 11+ devices. Please try out.

How to share Videos to any app using Intent?

Issue: What happens is after sharing the video when i launch the app to check the shared video it shows me error of "Unable to import" and "The video is no longer available".
Android Version: Oreo(8.0)
Code: I am trying with the following code to share videos with other apps using intent:
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("video/*");
share.putExtra(Intent.EXTRA_SUBJECT, "abc");
share.putExtra(Intent.EXTRA_TITLE, "abcd");
File imageFileToShare = new File(Environment.getExternalStorageDirectory() + "/mygallery/" + "airp.mp4");
Uri uri = FileProvider.getUriForFile(Main2Activity.this, "abc.dcf.fileprovider", imageFileToShare);
share.putExtra(Intent.EXTRA_STREAM, uri);
share.setPackage("com.abc.in");
startActivity(Intent.createChooser(share, "Message"));
The above code is working fine to share Images but its not working to share videos.
What i have tried: I have tried by sharing various file types like 3gp, mkv, mp4 but nothing is working out and I have also went through various similar questions but no solution is working in case of videos.
Please help me with this issue and also if there is any alternate way to do so?
You can add this to your OnCreate
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
If that doesn't work for you,
Add Provider to Manifest by doing this
<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>
Remember to use android:name="androidx.core.content.FileProvider" if you're using androidx
Create a file in xml directory (res/xml) and name provider_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="."/>
</paths>
Replace
Uri uri = FileProvider.getUriForFile(Main2Activity.this, "abc.dcf.fileprovider", imageFileToShare);
with this
Uri uri = FileProvider.getUriForFile(Main2Activity.this, BuildConfig.APPLICATION_ID + ".provider",imageFileToShare);

How to view / show a PDF file using FileProvider? Shows blank screen only

An Android app can create PDF files which should be stored to the external storage and viewed or shared by the user.
Creating, storing and sharing the file is no problem. However viewing the file fails and only a blank screen is shown.
This is my code:
<!-- Provider definition in manifest -->
<provider
android:authorities="com.example.MyApp.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_paths" />
</provider>
<!-- file_path.xml in xml resource dir -->
<?xml version="1.0" encoding="utf-8"?>
<path xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="ExternalDir" path="Documents/MyApp" />
</path>
// Sharing and viewing
File baseDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
File appDir = new File(baseDir, "MyApp");
appDir.mkdirs();
File pdfFile = new File(appDir, "Test.pdf");
savePDFToFile(pdfFile)
Uri fileUri = FileProvider.getUriForFile(this, "com.example.MyApp.fileprovider", pdfFile);
// View
Intent viewIntent = new Intent(Intent.ACTION_VIEW);
viewIntent .setDataAndType(fileUri, "application/pdf");
viewIntent .addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
viewIntent .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(viewIntent , "View"));
// Sharing
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("application/pdf");
sharingIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
startActivity(Intent.createChooser(sharingIntent, "Share"));
Creating/Writing the PDF file is no problem. Thus there seems to be no problem with the permissions. Sharing the file (e.g. saving it to Google Drive or sending it via email) is also no problem. Thus the FileProvider config and Uri creation seems to be correct.
So, what is wrong with the viewing intent? When testing this in the Emulator using API 26 only a blank page is shown. A user running the same code on a device with API 26 gets a message, that file access is not possible (without a reason).
However the file exists and access permission shouldn't be problem because otherwise the sharing intent would not work as well, would it?
How to solve this?

FileProvider - Internal Storage - Failed to find configured root that contains

I know that there are a lot of questions at SO about this problem. I tried about 10 different approaches and i couldn't make it work right. I always get next error:
java.lang.IllegalArgumentException: Failed to find configured root that contains /file:/storage/emulated/0/Android/data/app.kwork/files/IMG-afbfdc57c016fb1ff7dd983a056edffa-V.jpg
Official tutorial also didn't help. I'll share my code below, maybe i do something wrong, and you know what exactly is wrong here..
Manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="app.kwork.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
provider_paths.xml
<paths>
<files-path path="." name="files" />
</paths>
I save files into:
File futureStudioIconFile = new File(getExternalFilesDir(null) + File.separator + fileName);
Example of the file path: file:///storage/emulated/0/Android/data/app.kwork/files/IMG-afbfdc57c016fb1ff7dd983a056edffa-V.jpg
And try to share this file with next code:
public void openFile(String filePath){
File file = new File(filePath);
Log.d(TAG, "openFile: filePath: " + filePath);
Uri photoURI = FileProvider.getUriForFile(context, "app.kwork.provider", file);
MimeTypeMap myMime = MimeTypeMap.getSingleton();
Intent newIntent = new Intent(Intent.ACTION_VIEW);
String mimeType = myMime.getMimeTypeFromExtension(Utils.fileExt(filePath));
newIntent.setDataAndType(photoURI,mimeType);
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
newIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
context.startActivity(newIntent);
} catch (ActivityNotFoundException e) {
Toast.makeText(context, "No handler for this type of file.", Toast.LENGTH_LONG).show();
}
}
I tried different authorities and paths in xml, but i'm here now.
UPD: Testing on Android Oreo
Per the FileProvider documentation, it is <external-files-path> that corresponds with getExternalFilesDir() - the <files-path> you are using corresponds with getFilesDir().
You must change your paths.xml to use <external-files-path> or store your files in getFilesDir().
Example of the file path: file:///storage/emulated/0/Android/data/app.kwork/files/IMG-afbfdc57c016fb1ff7dd983a056edffa-V.jpg
This is not a file path. This is a Uri.
The file path is /storage/emulated/0/Android/data/app.kwork/files/IMG-afbfdc57c016fb1ff7dd983a056edffa-V.jpg.
Do not pass a string form of a Uri to the File constructor. You will wind up with a malformed File, and getUriForFile() will not be able to deal with that malformed File.

Android: Cannot share image from SD card

I try to share a picture from my SD card.
Class MainActivity.java
Intent shareIntent = new Intent(Intent.ACTION_SEND);
File baseDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
String fileName = "/cats.jpg";
File file = new File(baseDir + fileName);
Uri uri = Uri.fromFile(file);
shareIntent.setType("image/*");
shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
startActivity(shareIntent.createChooser(shareIntent, "Send Picture"));
I add to my Manifest.xml:
uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
The image "cats" is in
MySmartphone\Card\DCIM\cats.jpg
When I start my App, I can choose an application to share my picture. But when I open one, it cannot send or open the image.I got often a toast "not supported" or "error to share picture". I think my uri or file is wrong, but I cannot find my mistake. I have no problem to send text.
My uri:
file:///data/user/0/com.example.jana.showpicture/files/cats.jpg
My file: /storage/emulated/0/cats.jpg
Probably you are building for Android API 24 and above. Since API 24 a new kind of security was added. See:
https://developer.android.com/about/versions/nougat/android-7.0-changes.html#perm
You now need to do a bit more, add this in your AndroidManifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.jana.showpicture.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
/res/xml/provider_paths.xml:
<paths>
<external-path
name="external_files"
path="." />
</paths>
And Java:
Uri uri = FileProvider.getUriForFile(activity,"com.example.jana.showpicture.provider",
file);
shareIntent .setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY |
Intent.FLAG_GRANT_READ_URI_PERMISSION);

Categories

Resources