【问题标题】:Intent with wrong filename in intent's data from downloaded files下载文件的意图数据中的意图文件名错误
【发布时间】:2015-01-14 16:32:43
【问题描述】:

我通过安卓模拟器的浏览器下载了一个名为 test.npk 的文件。它保存在/sdcard/Download/test.npk:

$ adb -e shell ls /sdcard/Download/
test.npk

当我打开模拟器的“下载”应用并单击 test.npk 时,我得到一个 Toast:“无法打开文件”

当我查看 logcat 时,我发现它尝试的意图是错误的:

01-14 15:49:36.262    1232-1690/system_process I/ActivityManager﹕ START u0 {act=android.intent.action.VIEW dat=content://downloads/all_downloads/2 typ=application/octet-stream flg=0x3} from uid 10005 on display 0
01-14 15:49:36.264    1337-1337/android.process.media W/DownloadManager﹕ Failed to start Intent { act=android.intent.action.VIEW dat=content://downloads/all_downloads/2 typ=application/octet-stream flg=0x3 }: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=content://downloads/all_downloads/2 typ=application/octet-stream flg=0x3 }

如您所见,意图的数据是 content://downloads/all_downloads/2。这是为什么?我应该如何为这样的意图制作一个意图过滤器?我期待像 file://bla-bla/test.npk 或者至少是这样的东西://bla/bal/test.npk

这些是我的意图过滤器:

    <activity android:name=".MyActivity"
        android:configChanges="keyboardHidden|orientation|screenSize"
        android:exported="true"
        android:parentActivityName="com.example.OtherActivity"
        android:uiOptions="splitActionBarWhenNarrow"
        >
        <meta-data android:name="android.support.UI_OPTIONS"
            android:value="splitActionBarWhenNarrow" />
        <meta-data android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.OtherActivity" />
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="file" />
            <data android:host="*" />
            <data android:pathPattern=".*\\.npk" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="http" />
            <data android:host="*" />
            <data android:pathPattern=".*\\.npk" />
        </intent-filter>
    </activity>

解决方案:

按照@CommonsWare 的建议,我可以使用以下意图过滤器打开我的活动:

        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="content"
                  android:host="*"
                  android:mimeType="application/vnd.com.fletech.npk"
                  android:pathPattern=".*"/>
        </intent-filter>

要打开“文件”,我需要使用以下代码:

    Intent intent = getIntent();
    String action = intent.getAction();
    if (null != action) {
        final Uri uri = intent.getData();
        if (null != uri) {


            // this part is optional, if you want to get the filename to save it by the same name
            String filename = null;
            Long filesize = null;
            Cursor cursor = null;
            try {
                cursor = this.getContentResolver().query(uri, new String[] {
                        OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}, null, null, null );
                if (cursor != null && cursor.moveToFirst()) {
                    filename = cursor.getString(0);
                    filesize = cursor.getLong(1);
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }



            // copy the "content://" into a cache / temporary / or permanent file
            final File file = new File(getCacheDir(), filename);
            InputStream is = null;
            OutputStream os = null;
            try {
                is = getContentResolver().openInputStream(uri);
                os = new FileOutputStream(file);
                try {
                    try {
                        final byte[] buffer = new byte[1024];
                        int read;

                        while ((read = is.read(buffer)) != -1) {
                            os.write(buffer, 0, read);
                        }

                        os.flush();
                    } finally {
                        os.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } finally {
                if (null != is) {
                    is.close();
                }
                if (null != os) {
                    os.close();
                }
            }

            // open the copied file
            if (file.exists()) {
                categoryPack = PackI18nCategory.fromFile(file);
            }
        }
    }

【问题讨论】:

    标签: android android-intent intentfilter


    【解决方案1】:

    如您所见,意图的数据是 content://downloads/all_downloads/2。这是为什么?

    因为这是由管理下载的ContentProvider 交给下载应用程序的。它是 Uri 到由下载 ContentProvider 处理的流。

    我应该如何为这样的意图制作一个意图过滤器?

    支持content的方案和application/octet-stream的MIME类型。

    我期待类似 file://bla-bla/test.npk 或至少是 //bla/bal/test.npk

    ContentProvider 不需要使用文件扩展名,这在整体上并不常见。 Android 一般不会对文件扩展名做太多,更喜欢使用 MIME 类型。

    【讨论】:

    • 应用程序/八位字节流?然后几乎每个文件都会“打开”我的活动,它只能处理我专有的“npk”文件格式。如果我的网络服务器会提供具有不同 MIME 类型的文件,会有帮助吗?我可以只做我的哑剧类型吗?假设是 application/x-npk 还是有首选的调用方式?
    • @Gavriel:“我可以制作我的哑剧类型吗?” - 当然。遵循供应商命名规则,并可能制作比application/x-npk 更详细的内容,以减少意外碰撞的几率。然后让您的服务器使用该 MIME 类型提供您的文件。
    • 是的,使用我的自定义 mime 类型开始我的活动,但我仍然无法打开文件。在问题底部查看我的更新
    • @Gavriel:因为你的更新没有说明你的问题是什么,你遇到了什么错误等等,我真的不能帮助你。您可能希望打开一个新的 Stack Overflow 问题,在其中提供您当前的代码并具体说明您遇到的问题。请注意,您将希望在您的应用中拥有READ_EXTERNAL_STORAGE 权限或WRITE_EXTERNAL_STORAGE 权限,因为即使对于来自提供者的流(出于莫名其妙的原因),某些提供商也要求这样做。
    • 我无法在我的活动中打开文件,但使用我在问题末尾添加的代码(使用其他几个 stackowerflow 答案)我终于可以做到了。最初的问题是关于意图过滤器的,所以我接受了你的回答
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 2021-10-15
    • 2018-09-17
    • 1970-01-01
    相关资源
    最近更新 更多