Android Intent FileProvider“权限被拒绝”在谷歌地球中打开KML文件?
Posted
技术标签:
【中文标题】Android Intent FileProvider“权限被拒绝”在谷歌地球中打开KML文件?【英文标题】:Android Intent FileProvider "Permision denied" to open KML file in Google Earth? 【发布时间】:2018-07-19 10:14:36 【问题描述】:在 android Nougat (7.0) 之前,在外部存储中创建 KML 文件并使用文件 uri 和 KML 的 Google 地球 mime 类型启动意图很容易。 Google 地球应用神奇地打开并飞到了我的 KML。
在 Android Nougat (7.0) 上,您必须使用 FileProvider 来表示意图。您必须将提供程序添加到 AndroidManifest.xml 和 /res/xml/provider_paths.xml。
使用 FileProvider 意图,安装的 Google 地球 应用将启动,然后在 Google 地球 中显示“加载文件时出错”消息。
Logcat 显示“FileNotFoundException Permission denied”。
文件:AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<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>
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
文件:/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="external_files" path="."/>
</paths>
// File: MainActivity.java
// I used Android Device Monitor to push mooCow.kml to
// /storage/emulated/0/Download/mooCow.kml
public void onClick(View arg0)
File folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
File kmlFile = new File(folder, "mooCow.kml");
String pathToLocalKmlFile = kmlFile.getAbsolutePath();
openKmlInGoogleEarth(pathToLocalKmlFile);
// This works with KML and file extensions supported by getMimeTypeFromExtension
public void openKmlInGoogleEarth(String pathToFileInExternalStorage)
try
String[] splits = pathToFileInExternalStorage.split("\\.");
String ext = "";
if(splits.length >= 2)
ext = splits[splits.length-1];
MimeTypeMap mime = MimeTypeMap.getSingleton();
String mimeType = mime.getMimeTypeFromExtension(ext);
File file = new File(pathToFileInExternalStorage);
Uri uri;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
// Use file Uri before Android Nougat ( 7.0 )
uri = Uri.fromFile(file);
else
// Android Nougat ( 7.0 ) and later,
// use a FileProvider, AndroidManifest provider, and /res/xml/provider_paths.xml
uri = FileProvider.getUriForFile(MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
file);
final String type = "application/vnd.google-earth.kml+xml";
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, mimeType);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
catch(IllegalArgumentException e)
Log.e(TAG, "Unexpected exception openKmlInGoogleEarth", e);
adb logcat指向com.google.android.apps.earth权限问题。
华硕文件管理器应用程序如何在 Google 地球中打开完全相同的文件,而我的应用程序却不能?我的非 FileProvider 在 Android 5.2 上运行良好,但在 Android 6 上它只启动 Google 地球?
E Class : Error reading file from URI: content://com.subsite.googleearthbutton.provider/external_files/Documents/mooCow.kml
E Class : java.io.FileNotFoundException: Permission denied
E Class : at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:144)
E Class : at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:692)
E Class : at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1104)
E Class : at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:942)
E Class : at android.content.ContentResolver.openInputStream(ContentResolver.java:662)
E Class : at com.google.android.apps.earth.p.m.a(FileUtil.java:6)
什么可能导致文件访问“权限被拒绝”?
【问题讨论】:
相关问题***.com/questions/38200282/… “在 Android 6 上,我认为我需要使用 FileProvider”——不,您仍然可以使用Uri.fromFile()
,至少就操作系统而言。在 Android 7.0+ 上,需要 FileProvider
。您的 <uses-permission>
元素位于错误的位置(需要在 <application>
之外)。除此之外,也许pathToLocalKmlFile
不存在。另外,您的 LogCat 条目是来自您的应用还是来自 Google 地球?
"$applicationId.provider"
是否解析为"com.subsite.googleearthbutton.provider"
?
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
如果您不使用文件提供程序,请尝试不使用。
@CommonsWare 所以我确实不需要在 6.0 上需要 FileProvider。我将pathToLocalKmlFile
作为参数传递给openKmlInGoogleEarth
。我更正了帖子错误并将<uses-permission>
移到<application>
之外。 “权限被拒绝”来自 com.google.android.apps.earth.p.m.a(FileUtil.java:6)。 Asus File Manager 可以以某种方式打开 KML 文件。我不能有或没有 FileProvider 但相同的代码在 Android 5.1 上工作正常?
【参考方案1】:
解决了。
我忘记添加运行时检查并请求 WRITE_EXTERNAL_STORAGE 权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
我认为在旧版本的 Android 上,我所要做的就是在 AndroidManifest.xml 中添加一个 <uses-permission>
元素
在我检查并请求之前,我既没有 READ_EXTERNAL_STORAGE 也没有 WRITE_EXTERNAL_STORAGE。
感谢大家的帮助。
【讨论】:
【参考方案2】:对我来说,现在这是有效的:
Uri uriFromFile = FileProvider.getUriForFile(context, GenericFileProvider.class.getName(), file);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uriFromFile, "application/vnd.google-earth.kml+xml");
intent.putExtra("com.google.earth.EXTRA.tour_feature_id", "my_track");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
【讨论】:
putExtra "com.google.earth.EXTRA.tour_feature_id" 添加了什么? 请参阅***.com/a/11943958/257948@EdoftheMountain以上是关于Android Intent FileProvider“权限被拒绝”在谷歌地球中打开KML文件?的主要内容,如果未能解决你的问题,请参考以下文章
怎么获取android系统服务,如Uri,intent参数等,或者说去哪里查看