Opening pdf file Error: This file could not be accessed Check the location or the network and try again. Android 6 Marshmallow
Opening pdf file Error: This file could not be accessed Check the location or the network and try again. Android 6 Marshmallow
我正在尝试从外部存储中获取文件,然后我必须使用 intents 将该文件发送给 pdf 阅读器。之前下面的代码运行良好,但在安装 Android 6(Marshmallow 更新) 后,我的代码无法运行并收到消息
“无法访问此文件检查位置或网络,然后重试。”
(这是由于新的 android 运行时权限)。
我刚刚尝试了所有的解决方案(内容提供商等但没有工作)
任何解决方案?
File file = new File(getFilesDir(), "myfile.pdf");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intentChooser = Intent.createChooser(intent, "Choose Pdf Application");
try {
startActivity(intentChooser);
} catch (ActivityNotFoundException e) {
//com.adobe.reader
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.adobe.reader")));
}
刚刚为旧的和新的 Android OS 找到了一个可行的解决方案:
第 1 步:
创建一个 class names SampleContentProvider
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import java.io.File;
import java.io.FileNotFoundException;
/**
* Created by naveed on 7/2/16.
*/
public class SampleContentProvider extends ContentProvider {
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
File privateFile = new File(uri.getPath());
return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY);
}
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
第二步:
在 application body of manifest 中添加提供商:
<provider
android:name=".SampleContentProvider"
android:authorities="your_package_name"
android:exported="true" />
第 3 步:
现在终于通过 Uri
将文件 绝对路径 传递给 intent
Intent intent = new Intent(Intent.ACTION_VIEW);
File file = new File(getFilesDir(), "myfile.pdf");
String absoluteFilePath = file.getAbsolutePath();
String mimeType = "application/pdf";
Uri uri = Uri.parse("content://"+"Your_package_name"+"/" + absoluteFilePath);
intent.setDataAndType(uri, mimeType);
Intent intentChooser = Intent.createChooser(intent, "Choose Pdf Application");
startActivity(intentChooser);
希望对您有所帮助。谢谢大家的帮助。
使用FileProvider
(这是自Android牛轧糖以来公认的方法——否则你会得到android.os.FileUriExposedException
)然后不要忘记授予权限到它需要的所有包:
Uri uri = FileProvider.getUriForFile(
context,
context.getApplicationContext().getPackageName(), myFile);
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.setDataAndType(apkURI, "application/pdf");
pdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
grantAllUriPermissions(context, pdfIntent, apkURI);
其中 grantAllUriPermissions()
:
private void grantAllUriPermissions(Context context, Intent intent, Uri uri) {
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
查看以上答案后,最简单的解决方案如下。
Uri pdf = FileProvider.getUriForFile(this, this.getApplicationContext().getPackageName() + ".provider", file);
Intent pdfOpenintent = new Intent(Intent.ACTION_VIEW);
pdfOpenintent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_TOP);
pdfOpenintent.setDataAndType(pdf, "application/pdf");
try {
startActivity(pdfOpenintent);
} catch (ActivityNotFoundException e) {
// handle no application here....
}
关键是要同时设置FLAG_GRANT_READ_URI_PERMISSION和FLAG_ACTIVITY_CLEAR_TOP。
确保在 ApplicationManifest.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>
她的是 provider_paths 文件
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
触发处理已知 MIME 类型文件的意图,代码:
private void openFile(Uri fileUri) {
String mimeType = mModel.getMimeType(fileUri);
if (mimeType != null) { //we have determined a mime type and can probably handle the file.
try {
/*Implicit intent representing the action we want. The system will determine is it
can handle the request.*/
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(fileUri, mimeType);
//We ask the Activity to start this intent.
mView.getActivity().startActivity(i);
} catch (ActivityNotFoundException e) {
/*If we have figured out the mime type of the file, but have no application installed
to handle it, send the user a message.
*/
Toast.makeText(mView.getActivity(), "The System understands this file type," +
"but no applications are installed to handle it.",
Toast.LENGTH_LONG).show();
}
} else {
/*if we can't figure out the mime type of the file, let the user know.*/
Toast.makeText(mView.getActivity(), "System doesn't know how to handle that file type!",
Toast.LENGTH_LONG).show();
}
}
我正在尝试从外部存储中获取文件,然后我必须使用 intents 将该文件发送给 pdf 阅读器。之前下面的代码运行良好,但在安装 Android 6(Marshmallow 更新) 后,我的代码无法运行并收到消息
“无法访问此文件检查位置或网络,然后重试。”
(这是由于新的 android 运行时权限)。 我刚刚尝试了所有的解决方案(内容提供商等但没有工作) 任何解决方案?
File file = new File(getFilesDir(), "myfile.pdf");
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intentChooser = Intent.createChooser(intent, "Choose Pdf Application");
try {
startActivity(intentChooser);
} catch (ActivityNotFoundException e) {
//com.adobe.reader
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.adobe.reader")));
}
刚刚为旧的和新的 Android OS 找到了一个可行的解决方案:
第 1 步: 创建一个 class names SampleContentProvider
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import java.io.File;
import java.io.FileNotFoundException;
/**
* Created by naveed on 7/2/16.
*/
public class SampleContentProvider extends ContentProvider {
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
File privateFile = new File(uri.getPath());
return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY);
}
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
return null;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}
第二步: 在 application body of manifest 中添加提供商:
<provider
android:name=".SampleContentProvider"
android:authorities="your_package_name"
android:exported="true" />
第 3 步: 现在终于通过 Uri
将文件 绝对路径 传递给 intent Intent intent = new Intent(Intent.ACTION_VIEW);
File file = new File(getFilesDir(), "myfile.pdf");
String absoluteFilePath = file.getAbsolutePath();
String mimeType = "application/pdf";
Uri uri = Uri.parse("content://"+"Your_package_name"+"/" + absoluteFilePath);
intent.setDataAndType(uri, mimeType);
Intent intentChooser = Intent.createChooser(intent, "Choose Pdf Application");
startActivity(intentChooser);
希望对您有所帮助。谢谢大家的帮助。
使用FileProvider
(这是自Android牛轧糖以来公认的方法——否则你会得到android.os.FileUriExposedException
)然后不要忘记授予权限到它需要的所有包:
Uri uri = FileProvider.getUriForFile(
context,
context.getApplicationContext().getPackageName(), myFile);
Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
pdfIntent.setDataAndType(apkURI, "application/pdf");
pdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
grantAllUriPermissions(context, pdfIntent, apkURI);
其中 grantAllUriPermissions()
:
private void grantAllUriPermissions(Context context, Intent intent, Uri uri) {
List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
查看以上答案后,最简单的解决方案如下。
Uri pdf = FileProvider.getUriForFile(this, this.getApplicationContext().getPackageName() + ".provider", file);
Intent pdfOpenintent = new Intent(Intent.ACTION_VIEW);
pdfOpenintent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_TOP);
pdfOpenintent.setDataAndType(pdf, "application/pdf");
try {
startActivity(pdfOpenintent);
} catch (ActivityNotFoundException e) {
// handle no application here....
}
关键是要同时设置FLAG_GRANT_READ_URI_PERMISSION和FLAG_ACTIVITY_CLEAR_TOP。
确保在 ApplicationManifest.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>
她的是 provider_paths 文件
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="."/>
</paths>
触发处理已知 MIME 类型文件的意图,代码:
private void openFile(Uri fileUri) {
String mimeType = mModel.getMimeType(fileUri);
if (mimeType != null) { //we have determined a mime type and can probably handle the file.
try {
/*Implicit intent representing the action we want. The system will determine is it
can handle the request.*/
Intent i = new Intent(Intent.ACTION_VIEW);
i.setDataAndType(fileUri, mimeType);
//We ask the Activity to start this intent.
mView.getActivity().startActivity(i);
} catch (ActivityNotFoundException e) {
/*If we have figured out the mime type of the file, but have no application installed
to handle it, send the user a message.
*/
Toast.makeText(mView.getActivity(), "The System understands this file type," +
"but no applications are installed to handle it.",
Toast.LENGTH_LONG).show();
}
} else {
/*if we can't figure out the mime type of the file, let the user know.*/
Toast.makeText(mView.getActivity(), "System doesn't know how to handle that file type!",
Toast.LENGTH_LONG).show();
}
}