How to open PDF file from internal storage in Oreo? - android

I try to open PDF file in Oreo but it does not open. I don't get any error. What is the issue? PDF file does not open. Only black screen is shown. In logcat no errors show. What is wrong?
How Can I resolve this issue? I referred many links but did not get solution. I also tried many codes but no help.
My Code is:
File file11 = new File(Environment.getExternalStorageDirectory().
getAbsolutePath(),
"AtmiyaImages/" + nameoffile1);
Intent target = new Intent(Intent.ACTION_VIEW);
target.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if(Build.VERSION.SDK_INT>24){
Uri uri=FileProvider.getUriForFile(AssignmentActivity.this,
getPackageName()+".provider",file11);
target.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
target.putExtra(Intent.EXTRA_STREAM,uri);
target.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
target.setType("application/pdf");
Intent intent=Intent.createChooser(target,"Open File");
try
{
startActivity(intent);
}
catch(ActivityNotFoundException e)
{
Toast.makeText(AssignmentActivity.this,"No Apps
can performs This acttion",Toast.LENGTH_LONG).show();
}
}
else
{
target.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
target.setDataAndType(Uri.fromFile(file11),"application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intent=Intent.createChooser(target,"Open File");
try
{
startActivity(intent);
}
catch(ActivityNotFoundException e)
{
Toast.makeText(AssignmentActivity.this,"No Apps can performs This
acttion",Toast.LENGTH_LONG).show();
}
}
In Manifest I also add
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.infinity.infoway.atmiya.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
And My Xml code is:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="Phonestorage"
path="/storage/emulated/0/AtmiyaImages"/>
</paths>

Replace your path value with "." - Look at below:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
Inside Manifest, "provider" code is like this, your one is also true.
<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>
For access proper file path follow this code:
File pdfFile = new File(getExternalFilesDir(GlobalUtils.AppFolder), fileName);
Uri path = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", pdfFile);
Log.e("create pdf uri path==>", "" + path);
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
finish();
} catch (ActivityNotFoundException e) {
Toast.makeText(getApplicationContext(),
"There is no any PDF Viewer",
Toast.LENGTH_SHORT).show();
finish();
}
Hope this will help you.

Some tweaks to Bhoomika's answer worked for me
xml/providers_path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="files" path="."/>
</paths>
AndroidManifest.xml
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="APPLICATION_ID.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
A Kotlin Extension function to open the PDF from an activity
fun Activity.openPdf(filename: String?) {
val file = File(filesDir, filename)
if(file.exists()) {
Intent(Intent.ACTION_VIEW).apply {
setDataAndType(FileProvider.getUriForFile(this#openPdf, BuildConfig.APPLICATION_ID + ".provider", file), "application/pdf")
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
try {
startActivity(this)
} catch (e: Exception) {
showErrorDialog(unable_to_open_doc)
}
}
} else {
showErrorDialog(file_doesnt_exist)
}
}

Related

Action view intent cannot open image in files dir with fileProvider

What it is, is that I have an image in the files directory of my app. And then I want to open it with an intent, action view.
I have been on this for ages it seems and it just does not want to work out for me.
I have the following code:
private void changeInputFileViewer(File file){
boolean noApp = false;
file = new File(getFilesDir()+"/test.png");
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(FileProvider.getUriForFile(getApplicationContext(), "com.example.mayzom", file), "image/png");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
} catch ( ActivityNotFoundException e) {
e.printStackTrace();
noApp = true;
}
if (noApp){
Toast.makeText(this, getString(R.string.noApp), Toast.LENGTH_SHORT).show();
}
}
Manifest:
<provider
android:name="androidx.core.content.FileProvider"
android:grantUriPermissions="true"
android:authorities="com.example.mayzom"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
Provider paths:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="files" path="."/>
</paths>
The image exists with the following path found in the device file explorer: /data/data/com.example.mayzom/files/test.png.
The image is opened as this an endless buffer, with the following info:
I looked around online for a fix for a former error and thus, I have the following code in my onCreate: StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
Maybe to add a more fulfilling answer than what it is in the comments.
You need to create a fileProvider. You can find a guide here, afterwards you need the following code for your intent
boolean noApp = false;
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(FileProvider.getUriForFile(getApplicationContext(), getPackageName()+".provider", file), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
} catch ( ActivityNotFoundException e) {
e.printStackTrace();
noApp = true;
}
if (noApp){
Toast.makeText(this, getString(R.string.noApp), Toast.LENGTH_SHORT).show();
}

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)
?

Unable to open the pdf in Android

I am new in android and working on one android project in which I have to display a chosen pdf from the device either from internal storage(Priority) or from external Storage. I am enclosing the used code below.
private void openLocalPDF(File pdffile) {
File file = new File(Environment.getExternalStorageDirectory(), pdffile.getName());
Uri path = PdfFileProvider.getUriForFile(activity.getApplicationContext(), BuildConfig.APPLICATION_ID + ".provider", file);
Intent target = new Intent(Intent.ACTION_VIEW);
target.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
target.setDataAndType(path, "application/pdf");
Intent intent = Intent.createChooser(target, "Open File");
try {
activity.startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(getActivity(), "Please install some pdf viewer app", Toast.LENGTH_LONG).show();
}
You should create a Provider Class and extends with FileProvider. and register in manifest and also if you using targetSdkVersion 29 add this permission AndroidManifest.xml android:requestLegacyExternalStorage="true"
<provider
android:authorities="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true"
android:name=".provider.GenericFileProvider">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
And add a provider_paths.xml file in xml folder :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
And use this method
public static void openFile(Context context, File file) {
Uri path = GenericFileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(path, "application/pdf);
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
}
}
I hope this will help you.
Follow below steps:
Step - 1: Create provider_paths.xml in your xml directory
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
Step - 2: Add FileProvider in your AndroidManifest.xml file
<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>
Step - 3: Since your file is in internal/external storage use getExternalStorageDirectory()
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), filename);
Uri path = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", file);
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(path, "application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
target.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent intent = Intent.createChooser(target, "Open File");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(getActivity(), "Please install some pdf viewer app", Toast.LENGTH_LONG).show();
}

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?

install apk from url

I am trying to install an APK from a URL. This is my code:
Intent promptInstall = new Intent(android.content.Intent.ACTION_VIEW);
promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
promptInstall.setDataAndType(Uri.parse("http://10.0.2.2:8081/MyAPPStore/apk/Teflouki.apk"), "application/vnd.android.package-archive" );
startActivity(promptInstall);
But I have this problem:
05-10 15:09:29.511: ERROR/AndroidRuntime(1668): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=http://10.0.2.2:8081/MyAPPStore/apk/Teflouki.apk typ=application/vnd.android.package-archive flg=0x10000000 }
Thanks in advance.
You should download xxx.apk in storage before install by:
Intent promptInstall = new Intent(android.content.Intent.ACTION_VIEW);
promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
promptInstall.setDataAndType(Uri.parse("storage/xxx.apk"), "application/vnd.android.package-archive" );
startActivity(promptInstall);
This won't help if the app is not available on the mearketplace, but in case it is:
Uri marketUri = Uri.parse("market://search?q=pname:com.appmaker.tefloukipackage");
Intent marketIntent = new Intent(Intent.ACTION_VIEW, marketUri);
try {
context.startActivity(marketIntent);
} catch (ActivityNotFoundException ex) {
showAlertDialog(context, "Error", "Could not launch the market application.", true, null);
}
Follow along.
In your module manifest, add
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
//Inside application block
<application>
<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_path"/>
</provider>
</application>
In your module res/xml folder, if not create this folder, with file provider_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>
And use this method.
private fun updateApplication(activity: Activity) {
//This will get you the root directory path
val externalStoragePublicDirectory: String =
Environment.getExternalStorageDirectory().path
val externalStoragePublicDirectoryFile =
File(externalStoragePublicDirectory, "MyApp" + ".apk")
val uri = FileProvider.getUriForFile(
activity.applicationContext,
activity.applicationContext.packageName + ".provider",
externalStoragePublicDirectoryFile
)
val installAppIntent = Intent(Intent.ACTION_VIEW)
.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
.setDataAndType(
uri,
"application/vnd.android.package-archive"
)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
activity.startActivity(installAppIntent)
//This will close your app, remove if not needed
exitProcess(0)
}
Important, also go to your phone settings, search for unknown sources, enable it in old devices, but in new devices, search for your app and allow it the permission to install new app packages. Only then you will get the pop up to install the app.

Categories

Resources