I searched extensively and did not find the problem. When you try to install an APK file using an Intent in Android Nougat, it simply does not install and displays the following warning: "There was a problem parsing the package".
It works perfectly to open PDF files, for example, with settings to open this type of file (.PDF). However to install .apk files does not work.
LogCat does not show any errors and I can not reach any solution.
What could be wrong?
The following code:
Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="br.com.xxxxxx.xxxxxx.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths"/>
</provider>
xml/filepaths:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="storage/emulated/0" path="."/>
Activity:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
try {
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
File file = new File(getContext().getFilesDir(), "app-debug.apk");
Uri uri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID + ".fileprovider", file);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}else{
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
File file = new File(Environment.getExternalStorageDirectory() + "/app-debug.apk");
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
finish();
} catch (Exception e) {
e.getMessage();
}
}
Please, what could be wrong with this code? Can someone help me?
I had to change the intent for N (and higher) and remove the type designation. Once I did that the install worked as expected.
So for N:
Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
File file = new File(getContext().getFilesDir(), "app-debug.apk");
Uri uri = FileProvider.getUriForFile(getContext(), BuildConfig.APPLICATION_ID + ".fileprovider", file);
intent.setData(uri)
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
finish();
Related
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();
}
I thoroughly checked that pdf file is
in
/storage/emulated/0/Download/Abcd.pdf"
but can't open it with intent.
I opened it in various viewers and some oh them result in a error: "can't open file". Microsoft word says: check file in the device, but Abcd.pdf file is opened well when I opened it in file directory in file system of android.
Did I set the route wrong?
AndroidManifest.xml
<provider
android:authorities="${applicationId}.provider"
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/provider_paths"/>
</provider>
MainActivity.Java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent=new Intent();
File mypath=new File( Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download/","Abcd.pdf");
Log.e("download",mypath.getAbsolutePath());
//this log says : /storage/emulated/0/Download/Abcd.pdf
Uri pdfUri = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() + ".provider", mypath);
Log.e("download",mypath.exists()+"");
if (mypath.exists()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Log.e("download","result : "+pdfUri.getPath());
intent = new Intent(Intent.ACTION_VIEW);
intent.setType("application/pdf");
intent.putExtra(MediaStore.EXTRA_OUTPUT, pdfUri);
}else{
}
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
startActivity(intent);
}
catch (ActivityNotFoundException e) {
Log.e("error","error"+e);
}
}
}
res/xml/provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="storage/emulated/0"
path="."/>
</paths>
I am using this function :
public void openPdf(LocalFile magazine) {
if (BuildConfig.DEBUG)
Log.d(TAG, "openPdf() called with: magazine = [" + magazine + "]");
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
File file = new File(Uri.parse(magazine.getPath()).getPath());
Uri uri = FileProvider.getUriForFile(getContext(),
getContext().getApplicationContext().getPackageName() + ".provider", file);
intent.setDataAndType(uri, "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
intent.setDataAndType(Uri.parse(magazine.getPath()), "application/pdf");
}
try {
startActivity(intent);
} catch (Throwable t) {
t.printStackTrace();
//attemptInstallViewer();
}
}
This is works fine for me.
I've one question by which this problem might be resolved, Have you wrote Storage Permission in Manifest?
Also is your App has Permission to Read External Storage? Check this from Mobile Settings and it would start working automatically.
Here is how you can initialize Permissions Statement in Manifest File.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
If it's given in Manifest and also your Mobile has guaranteed the Permissions and App is not working then share the full code of Activity, I might help you in that.
I have been trying to open a PDF file using the intent. It works fine for devices prior to Adroid N. Following is the code I have used
File file = new File(gridItems.get(position).getPath());
Intent intent = null;
if (Build.VERSION.SDK_INT < 24) {
intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
} else {
intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri pdfURI = FileProvider.getUriForFile(GalleryPdfActivity.this, getApplicationContext()
.getPackageName
() +
".provider", file);
intent.putExtra(Intent.EXTRA_STREAM, pdfURI);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.setType("application/pdf");
}
try {
if (intent.resolveActivity(getPackageManager()) != null)
startActivity(intent);
else
AppUtils.toast("No Application found to open the pdf", GalleryPdfActivity.this);
} catch (Exception e) {
AppUtils.toast(e.getMessage(), GalleryPdfActivity.this);
}
The file chooser opens and I have selected Google PDF Viewer to open the app. But it returns an error "Cannot display PDF(no file received)" . I was able to open the same file in devices prior to Android N
Add FLAG_GRANT_READ_URI_PERMISSION on the Intent in your FileProvider case. Otherwise, the other app has no access to the content. See the documentation.
Add FLAG_GRANT_READ_URI_PERMISSION
Intent intent = new Intent(Intent.ACTION_VIEW)
Uri outputFileUri = FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".provider", file);
intent.setDataAndType(outputFileUri, "application/pdf");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent in = Intent.createChooser(intent, "Open File");
startActivity(in);
also add provider_paths.xml at res -> xml folder
and need to add below code at manifests
<application>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
tools:replace="android:resource"
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths" />
</provider>
</application>
I'm developing an Android application and I have to open some files.
This is my code using intent:
public class FacturaActivity extends Activity {
(...)
public void downloadInvoice(View view) {
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+ filename);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file),"application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
}
}
File is in the root directory of the SD card and I can manually open it.
Problem
Application is closed when it arrives at startActivity(intent). I think the problem is in AndroidManifest.xml file, but I don't know how to put it correctly.
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="8" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:name="###.MyApplication" > <!--cant show complete name-->
<activity
android:name="###.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".FacturaActivity" >
</activity>
</application>
LogCat
07-03 15:49:13.094: E/AndroidRuntime(1032): FATAL EXCEPTION: main
07-03 15:49:13.094: E/AndroidRuntime(1032): java.lang.IllegalStateException: Could not execute method of the activity
(...)
07-03 15:49:13.094: E/AndroidRuntime(1032): Caused by: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=file:///mnt/sdcard/201209_F2012212782.PDF typ=application/pdf flg=0x40000000 }
07-03 15:49:13.094: E/AndroidRuntime(1032): at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1408)
07-03 15:49:13.094: E/AndroidRuntime(1032): at android.app.Instrumentation.execStartActivity(Instrumentation.java:1378)
07-03 15:49:13.094: E/AndroidRuntime(1032): at android.app.Activity.startActivityForResult(Activity.java:2817)
07-03 15:49:13.094: E/AndroidRuntime(1032): at android.app.Activity.startActivity(Activity.java:2923)
Can you help me to complete AndroidManifest? Or how can I open that pdf?
The problem is that there is no app installed to handle opening the PDF. You should use the Intent Chooser, like so:
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +"/"+ filename);
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(Uri.fromFile(file),"application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intent = Intent.createChooser(target, "Open File");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
// Instruct the user to install a PDF reader here, or something
}
As of API 24, sending a file:// URI to another app will throw a FileUriExposedException. Instead, use FileProvider to send a content:// URI:
public File getFile(Context context, String fileName) {
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return null;
}
File storageDir = context.getExternalFilesDir(null);
return new File(storageDir, fileName);
}
public Uri getFileUri(Context context, String fileName) {
File file = getFile(context, fileName);
return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file);
}
You must also define the FileProvider in your manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
Example file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="name" path="path" />
</paths>
Replace "name" and "path" as appropriate.
To give the PDF viewer access to the file, you also have to add the FLAG_GRANT_READ_URI_PERMISSION flag to the intent:
private void displayPdf(String fileName) {
Uri uri = getFileUri(this, fileName);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "application/pdf");
// FLAG_GRANT_READ_URI_PERMISSION is needed on API 24+ so the activity opening the file can read it
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (intent.resolveActivity(getPackageManager()) == null) {
// Show an error
} else {
startActivity(intent);
}
}
See the FileProvider documentation for more details.
String dir="/Attendancesystem";
public void displaypdf() {
File file = null;
file = new File(Environment.getExternalStorageDirectory()+dir+ "/sample.pdf");
Toast.makeText(getApplicationContext(), file.toString() , Toast.LENGTH_LONG).show();
if(file.exists()) {
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(Uri.fromFile(file), "application/pdf");
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intent = Intent.createChooser(target, "Open File");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
// Instruct the user to install a PDF reader here, or something
}
}
else
Toast.makeText(getApplicationContext(), "File path is incorrect." , Toast.LENGTH_LONG).show();
}
Kotlin version below (Updated version of #paul-burke response:
fun openPDFDocument(context: Context, filename: String) {
//Create PDF Intent
val pdfFile = File(Environment.getExternalStorageDirectory().absolutePath + "/" + filename)
val pdfIntent = Intent(Intent.ACTION_VIEW)
pdfIntent.setDataAndType(Uri.fromFile(pdfFile), "application/pdf")
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
//Create Viewer Intent
val viewerIntent = Intent.createChooser(pdfIntent, "Open PDF")
context.startActivity(viewerIntent)
}
The reason you don't have permissions to open file is because you didn't grant other apps to open or view the file on your intent. To grant other apps to open the downloaded file, include the flag(as shown below): FLAG_GRANT_READ_URI_PERMISSION
Intent browserIntent = new Intent(Intent.ACTION_VIEW);
browserIntent.setDataAndType(getUriFromFile(localFile), "application/pdf");
browserIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|
Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(browserIntent);
And for function:
getUriFromFile(localFile)
private Uri getUriFromFile(File file){
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
return Uri.fromFile(file);
}else {
return FileProvider.getUriForFile(itemView.getContext(), itemView.getContext().getApplicationContext().getPackageName() + ".provider", file);
}
}
Want to chime in with the answers above. The code is nearly identical, except it's in an Android Jetpack Compose composable (and therefore in Kotlin). That, and I did two videos talking through it.
Here's the happy path version, (clocking in at 10 minutes).
For the whole hog, this behemoth 30 minute screenshow has me provide a significant amount of context and a/b options of the code.
If you want to see the code, you can find it in this repo branch.
Is it possible to open the music app from my app in android, or is it best to write a whole new music app inside of mine. I would rather use theirs since the user will already be comfortable with it.
I found one way to do this.
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(YOUR_SONG_PATH), "audio/*");
startActivity(intent);
To simply launch the music player do:
Intent intent = new Intent(MediaStore.INTENT_ACTION_MUSIC_PLAYER);
startActivity(intent);
There are number of way by which you can achieve default audio player but those are device and OS specific.
With this code snippet you can get default audio player.
try
{
Intent myIntent = new Intent(android.content.Intent.ACTION_VIEW);
File file = new File("audiofilepath");
String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString());
String mimetype = android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
myIntent.setDataAndType(Uri.fromFile(file),mimetype);
startActivity(myIntent);
}
catch (Exception e)
{
e.printStackTrace();
}
This works for older versions and you May get FileUriExposed Exception due to the security Update in the latest Versions.
To avoid that use the following code
try{
File file = new File(filepath);
String mimeType = "audio/*";
Uri fileURI = FileProvider.getUriForFile(
getApplicationContext(),
getApplicationContext()
.getPackageName() + ".provider", file);
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(fileURI, mimeType);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
}catch (Exception e){
Log.e(TAG,"-------------------------------------------------------FAILED TO PLAY SONG "+e);
}
Add the Following in AndroidManifest.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>
Create a file provider_paths.xml under res/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>
You can also try this one.
Intent intent = new Intent(MediaStore.INTENT_ACTION_MUSIC_PLAYER);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);