android - 针对特定 Activity 的文件扩展名 Intent 过滤器

标签 android android-intent intentfilter

我有 2 个自定义文件扩展名 *.abc*.xyz

我已经为 Activity 编写了 Intent 过滤器,其中具有*.abc扩展名的文件应在Activity1*.xyz中打开 应该在 Activity2

中打开

这些文件具有序列化java对象而不是纯文本文件。

这些是 AndroidManifest.xml 中这些 Activity 的 Intent 过滤器

<activity
    android:name=".ui.Activity1">
    <intent-filter tools:ignore="AppLinkUrlError">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />

        <data android:mimeType="*/*" />
        <data android:pathPattern=".*\\.abc" />
    </intent-filter>
</activity>
<activity
    android:name=".ui.Activity2">
    <intent-filter tools:ignore="AppLinkUrlError">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />

        <data android:mimeType="*/*" />
        <data android:pathPattern=".*\\.xyz" />
    </intent-filter>
</activity>

我能够在 Android 系统中注册这些扩展,并且我的应用程序 Activity 显示在 Android 系统 UI 的应用程序选择器中

我正在 logcat 中打印 URI 信息,如下

Timber.i(uri.toString())
val mimeType = contentResolver.getType(uri)
Timber.i(mimeType)

WhatsApp 打开文件时的 Logcat

content://com.whatsapp.provider.media/item/5237
application/octet-stream

Solid Explorer 打开文件时的 Logcat

content://pl.solidexplorer2.files/storage/emulated/0/Download/File1.abc
application/*

但是当点击任一文件(自定义扩展)时,它会将两个 Activity 显示为可打开的 Intent , 例如。如果单击文件 file1.abc,它将扩展的两个 Intent 过滤器显示为Activity1 和 Activity2

我想让这些扩展程序针对特定 Activity 就像如果点击扩展名为 *.abc 的文件,它在 Android 系统 UI 的 Intent Chooser 中应该只有 Activity1

我尝试了其他答案中解释的几种方法,但那些似乎对于具有内容类型URI的两种文件格式都能正常工作

某些解决方案仅在从 Solid Explorer 等文件浏览器打开文件时有效,但在从 WhatsApp 等使用 MIME 类型作为媒体的应用程序打开时无效

下面的 Intent 过滤器可以与 Solid Explorer 正确配合使用。 它根据自定义文件扩展名过滤 Activity 。但相同的 Intent Filter 不适用于 Android 系统的选择器对话框,因为它不适用于使用 Android 系统的 Intent Chooser 的 WhatsAppGmail 等应用

<activity
    android:name=".ui.Activity1">
    <intent-filter>
        <data
            android:host="*"
            android:mimeType="*/*"
            android:pathPattern=".*\\.abc"
            android:scheme="content" />

        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
    </intent-filter>
</activity>
<activity
    android:name=".ui.Activity2">
    <intent-filter>
        <data
            android:host="*"
            android:mimeType="*/*"
            android:pathPattern=".*\\.xyz"
            android:scheme="content" />

        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
    </intent-filter>
</activity>

任何帮助将不胜感激。 谢谢。

最佳答案

通过对每个 Activity 使用 Intent 过滤器没有直接解决此问题的方法,因此我创建了接受以下 Intent 过滤器的 FileIntentActivity

<intent-filter
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    tools:ignore="AppLinkUrlError">
    <action android:name="android.intent.action.VIEW" />
    <action android:name="android.intent.action.EDIT" />

    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="*/*" />
</intent-filter>

FileIntentActivity用于接受任何文件格式,然后根据使用引用的游标从内容URI转换的文件扩展名来决定进一步的操作this answer

fun getFileName(uri: Uri): String {
    lateinit var cursor: Cursor
    lateinit var result: String
    try {
        cursor = appContext.contentResolver.query(uri, null, null, null, null)
        if(cursor!=null && cursor.moveToFirst()){
            result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
        }
        return result
    } finally {
        cursor.close()
    }
}

private fun getFileType(fileName: String): FileType {
    return when (fileExtension) {
        FileFormats.ABC_FILE_FORMAT -> FileType.ABC
        FileFormats.XYZ_FILE_FORMAT -> FileType.XYZ
        else -> FileType.UNKNOWN
    }
}

并根据FileType打开Activity1Activity2

private fun openActivityByType(fileType: FileType) {
    when (fileType) {
        FileType.ABC -> startActivity1()
        FileType.XYZ -> startActivity2()
        FileType.UNKNOWN -> showFileUnsupportedMessage()
    }
}

这种方法至少可以让用户交互不那么困惑,因为它仅在 Android 的 Intent Chooser 中显示 1 个文件 Intent Activity ,而不是单个应用程序的多个 Activity 。

关于android - 针对特定 Activity 的文件扩展名 Intent 过滤器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48367934/

相关文章:

javascript - Youtube iframe API - 安卓全屏

java - Calendar.before() 和 Calendar.after() 返回不正确的值

java - 尝试从 android 中的兄弟打印机打印位图时出现以下异常

android:在浏览器中从网络下载文件时设置 Intent 过滤器以触发 Activity 时出现问题

android - 如何修复未 protected SMS BroadcastReceiver lint 警告

java - 如何在 android 的 ListView 中获取项目的 View ?

android - 为什么从 onMeasure 设置文本不会影响 TextView?

android - Sl4A 将 Intent 广播到 Minimalistic 文本小部件

android - 从 Android 上的 SD 卡中选择歌曲并播放

Android-Broadcast Receiver 和 Intent Filter