在下载文件的intent数据中使用错误的文件名

时间:2015-01-14 16:32:43

标签: android android-intent intentfilter

我通过android模拟器的浏览器下载了一个名为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。这是为什么?我该如何为这样的意图制作一个intent-filter?我期待像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打开我的活动:

        <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);
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

  

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

因为这是由管理下载的ContentProvider传递到下载应用程序的内容。由下载Uri处理的流是ContentProvider

  

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

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

  

我期待像file://bla-bla/test.npk或至少某些东西://bla/bal/test.npk

ContentProvider不要求使用文件扩展名,而且整体而言并不常见。 Android通常对文件扩展名没有太大作用,更喜欢使用MIME类型。