【问题标题】:android.os.FileUriExposedException when relaying an Intent containing an Uri to a file将包含 Uri 的 Intent 中继到文件时出现 android.os.FileUriExposedException
【发布时间】:2017-03-06 17:59:04
【问题描述】:

基本上我正在尝试做“Andmade Share”所做的事情。将系统共享对话框替换为自定义对话框。

在某些情况下它可以工作,然后在其他情况下又不行。

例如,如果我转到相机应用程序并分享照片,我的应用程序会自动调用,并显示一个对话框,其中包含可用于分享照片的已安装目标应用程序。因此,如果我点击我在 RecyclerView 中的 Gmail 图标,Gmail 就会打开并且照片在草稿中。

如果我尝试对来自其他应用程序的 csv 文件执行相同操作,则购买,在我的情况下,我试图告诉“Libra - Weight Manager”我想共享备份,以便通过 Gmail 将其发送给我,然后我的应用程序获取共享请求(请记住,它正在替换操作系统提供的共享对话框),然后当它尝试使用转发的意图启动 Gmail 时,就会发生错误。

这是日志:

03-06 18:24:45.756 E/SharerAct: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
03-06 18:24:45.757 W/SharerAct: INSERT INTENT: Intent { act=android.intent.action.CHOOSER flg=0x10800000 cmp=org.example.android.my_app_name.app/.ui.activities.Insert (has extras) }
03-06 18:24:45.757 W/SharerAct: INSERT ACTION: android.intent.action.CHOOSER
03-06 18:24:45.757 W/SharerAct: INSERT TYPE: null
03-06 18:24:45.757 W/SharerAct: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
03-06 18:24:45.758 W/SharerAct: INSERT BUNDLE -> android.intent.extra.INITIAL_INTENTS -- [Landroid.os.Parcelable;@fa03561 -- ([Landroid.os.Parcelable;)
03-06 18:24:45.759 W/SharerAct: INSERT BUNDLE -> android.intent.extra.INTENT -- Intent { act=android.intent.action.SEND typ=text/csv flg=0x1 clip={text/csv T:https://play.google.com/store/apps/details?id=net.cachapa.libra} (has extras) } -- (android.content.Intent)
03-06 18:24:45.759 W/SharerAct: INSERT BUNDLE -> android.intent.extra.TITLE -- Datenbank exportieren -- (java.lang.String)
03-06 18:24:45.759 E/SharerAct: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
03-06 18:24:45.759 W/SharerAct: INSERT INNER INTENT: Intent { act=android.intent.action.SEND typ=text/csv flg=0x1 clip={text/csv T:https://play.google.com/store/apps/details?id=net.cachapa.libra} (has extras) }
03-06 18:24:45.760 W/SharerAct: INSERT INNER ACTION: android.intent.action.SEND
03-06 18:24:45.760 W/SharerAct: INSERT INNER TYPE: text/csv
03-06 18:24:45.760 W/SharerAct: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
03-06 18:24:45.761 W/SharerAct: INSERT INNER BUNDLE -> android.intent.extra.SUBJECT -- Libra Database: 2017-03-06 -- (java.lang.String)
03-06 18:24:45.761 W/SharerAct: INSERT INNER BUNDLE -> android.intent.extra.TEXT -- https://play.google.com/store/apps/details?id=net.cachapa.libra -- (java.lang.String)
03-06 18:24:45.762 W/SharerAct: INSERT INNER BUNDLE -> android.intent.extra.STREAM -- file:///storage/emulated/0/Android/data/net.cachapa.libra/cache/Libra_2017-03-06.csv -- (android.net.Uri$StringUri)
03-06 18:24:45.762 E/SharerAct: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
03-06 18:24:45.773 W/SharerAct: SharerActivity: finish
03-06 18:24:45.810 W/ChooserAct: #################################################
03-06 18:24:45.810 W/ChooserAct: ChooserAct: onCreate, sis: null
03-06 18:24:45.810 W/ChooserAct: #################################################
03-06 18:24:45.810 V/FA: onActivityCreated
03-06 18:24:45.841 E/ShrTrgtActvtsAdapter:  ---> Android Beam
03-06 18:24:45.854 E/ShrTrgtActvtsAdapter:  ---> In Google Drive speichern
03-06 18:24:45.865 E/ShrTrgtActvtsAdapter:  ---> Gmail
03-06 18:24:45.874 E/ShrTrgtActvtsAdapter:  ---> Per LAN
03-06 18:24:45.878 E/ShrTrgtActvtsAdapter:  ---> ES Speichern unter
03-06 18:24:45.886 E/ShrTrgtActvtsAdapter:  ---> Inbox
03-06 18:24:45.895 E/ShrTrgtActvtsAdapter:  ---> FolderSync

//... later, after clicking on Gmail

03-06 18:24:54.926 E/AndroidRuntime: FATAL EXCEPTION: main
 Process: org.example.android.my_app_name.app, PID: 21298
 android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/net.cachapa.libra/cache/Libra_2017-03-06.csv exposed beyond app through ClipData.Item.getUri()
     at android.os.StrictMode.onFileUriExposed(StrictMode.java:1796)
     at android.net.Uri.checkFileUriExposed(Uri.java:2346)
     at android.content.ClipData.prepareToLeaveProcess(ClipData.java:845)
     at android.content.Intent.prepareToLeaveProcess(Intent.java:8941)
     at android.content.Intent.prepareToLeaveProcess(Intent.java:8926)
     at android.app.Instrumentation.execStartActivity(Instrumentation.java:1517)
     at android.app.ContextImpl.startActivity(ContextImpl.java:791)
     at android.app.ContextImpl.startActivity(ContextImpl.java:768)
     at android.content.ContextWrapper.startActivity(ContextWrapper.java:356)
     at org.example.android.my_app_name.app.ui.adapters.ShareTargetActivitiesAdapter$ViewHolder$1.onClick(ShareTargetActivitiesAdapter.java:95)
     at android.view.View.performClick(View.java:5637)
     at android.view.View$PerformClick.run(View.java:22429)
     at android.os.Handler.handleCallback(Handler.java:751)
     at android.os.Handler.dispatchMessage(Handler.java:95)
     at android.os.Looper.loop(Looper.java:154)
     at android.app.ActivityThread.main(ActivityThread.java:6119)
     at java.lang.reflect.Method.invoke(Native Method)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

所以SharerAct 正在对android.intent.action.CHOOSER“广播”做出反应,获取存储在android.intent.extra.INTENT 中的Intent,并在完成之前将此Intent 转发给ChooserAct

ChooserAct,一个以对话框为主题的 Activity 然后通过向 RecyclerView 填充目标来构建对话框,这些目标是通过在转发的 Intent 上调用 pm.queryIntentActivities(iIntent, PackageManager.MATCH_DEFAULT_ONLY); 获得的。

当一个目标应用被点击时,下面的代码就会被执行

m_llLayout.setOnClickListener(new View.OnClickListener() {
    @Override public void onClick(View view) {
        int iPosition = (int)view.getTag(R.string.tag_index);
        PackageManager pm = MyApplication.getAppContext().getPackageManager();
        ResolveInfo info = m_ailIRItems.get(iPosition).m_riInfo;
        ActivityInfo activityInfo = info.activityInfo;
        m_iIntent.setClassName(activityInfo.packageName, activityInfo.name); // <- see this?
        m_iIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        //m_iIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        //m_iIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
        MyApplication.getAppContext().startActivity(m_iIntent);
        m_dlgAactivityChooser.finish();
    }
});

我用// &lt;- see this? 注释标记了上面的代码。我不知道这样做是否可以,基本上我正在覆盖目标,以防已经设置了目标。这似乎可行,所以我要这样做。

但是你知道,上面列出的exposed beyond app through ClipData.Item.getUri()-exception 发生在MyApplication.getAppContext().startActivity(m_iIntent); 行上

我的应用可以通过提供者访问文件系统:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="org.example.android.my_app_name.files"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/my_paths" />
</provider>

my_paths 在哪里

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="files" path="MyAppsHomeFolder/" />
    <external-path name="external_files" path="."/>
</paths>

最初我只在那里列出了MyAppsHomeFolder/,因为我在那里存储了仅属于应用程序的备份和内容。但是在尝试解决当前问题的同时,我现在还添加了&lt;external-path name="external_files" path="."/&gt; 行。

所以,我对如何处理这个android.os.FileUriExposedException一无所知。

我认为这与存储在/storage/emulated/0/Android/data 文件夹的受保护存储中的文件有关。但是“Andmade Share”能够依赖这种分享意图,所以我肯定缺少一些东西。

【问题讨论】:

  • 谈了很多。但是对于您省略代码的重要意图。请显示 m_iIntent 的所有代码。您为什么不在 onClick 中创建该意图?请这样做。让它成为本地的。不要使用全局指针。我们甚至看不到您使用了您的文件提供程序。
  • 1) m_iIntent 是recyclerview 适配器类的本地对象,其中包含onClick。我也可以将它附加到m_llLayout.setTag(),但 ATM 不需要它。
  • 2) 不在 onClick 中创建,因为它是在android.intent.action.CHOOSER 广播的android.intent.extra.INTENT 中传递给我的。这是为了不修改附加包中包含的任何内容,例如流。 (没有更多有用的代码可显示)这是一个我正在传递的包裹。
  • , then Gmail opens up and the photo is in the draft.。您不会在那里获得/使用文件 uri,而是内容方案。
  • Android 7 下你只会得到 FileUriExposedException 不是吗?

标签: android exception android-intent


【解决方案1】:

替换 “org.example.android.my_app_name.files”和“${applicationId}.provider”在标签内的清单文件中

我不确定,但它可能会帮助你:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    • 2016-11-25
    • 1970-01-01
    • 2014-03-05
    • 2012-07-26
    • 2021-05-21
    相关资源
    最近更新 更多