将包含Uri的Intent中继到文件

时间:2017-03-06 17:59:04

标签: android exception android-intent

基本上我是在尝试做什么" 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中的意图,并将此意图转发给ChooserAct在完成之前。

ChooserAct,一个Dialog-Themed 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();
    }
});

我用// <- see this?评论标记了上面的代码。我不知道是否可以这样做,基本上我会覆盖目标,以防目标已经设置。这似乎有效,所以我就是这样做的。

但是你知道,上面列出的exposed beyond app through ClipData.Item.getUri() - 例外情况发生在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/,因为我存储了仅属于应用程序的备份和内容。但在尝试解决当前问题时,我现在还添加了<external-path name="external_files" path="."/>行。

所以,我在这里对于如何处理android.os.FileUriExposedException非常无能为力。

我认为它与存储在/storage/emulated/0/Android/data文件夹的受保护存储中的文件有关。但是&#34; Andmade Share&#34;能够依赖这种分享意图,所以必须有一些我不知道的东西。

1 个答案:

答案 0 :(得分:0)

替换 &#34; org.example.android.my_app_name.files&#34;使用&#34; $ {applicationId} .provider&#34;在标记

中的清单文件中

我不确定,但它可能对你有所帮助:)