【问题标题】:Intent Filter of File Extension for specific activity特定活动的文件扩展名的意图过滤器
【发布时间】:2018-06-30 06:41:11
【问题描述】:

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

我已经为应该在Activity1 中打开具有*.abc 扩展名的文件并且应该在Activity2 中打开*.xyz 的活动编写了意图过滤器

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

这些是 AndroidManifest.xml

中这些活动的意图过滤器
<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 系统中注册这些扩展,并且我的应用程序活动显示在 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/*

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

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

我尝试了其他答案中解释的几种方法,但那些 似乎适用于具有 content type URI

的两种文件格式

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

下面的意图过滤器与 Solid Explorer 一起正常工作。 它基于自定义文件扩展名过滤活动。但同样的 Intent Filter 不适用于 Android 系统的选择器对话框,因为它不适用于像 WhatsAppGmail 这样使用 Android 系统的 Intent 选择器的应用程序

<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>

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

【问题讨论】:

  • 过滤文件扩展名将越来越没用。 Uri 不需要文件扩展名,更不用说有意义的了。停止依赖文件扩展名。
  • @CommonsWare 所以你建议怎么做?如何为特定文件类型注册这些活动?
  • "我如何为特定文件类型注册这些活动?" ——你没有。您不能强迫其他开发人员(更不用说用户)使用您的自定义文件扩展名,甚至是自定义 MIME 类型。恕我直言,您使用 Java 序列化的决定是糟糕。如果您使用 XML 或 JSON,您至少可以依赖一些传统的 MIME 类型。就目前而言,无论您使用推送 (&lt;intent-filter&gt;) 还是拉取 (ACTION_OPEN_DOCUMENTACTION_GET_CONTENT),您都必须满足于请求任何类型的文件,才能获得任何结果。
  • @CommonsWare 实际上我正在开发文本加密应用程序,因此不能像普通的纯文本数据持有者那样直接使用 XML 或 JSON。是的,我需要满足于请求任何类型的文件。难道没有另一种方法来实现这一点,而不依赖于用户每次都在它们之间进行选择
  • 就个人而言,在这种情况下,我会使用 pull:ACTION_OPEN_DOCUMENT,如果您的 minSdkVersion 低于 19,则加上 ACTION_GET_CONTENT。这些对应于您在中看到的“文件打开”对话框其他 GUI 工具包。这至少将情况限制在用户在您的应用程序中并且特别希望将内容加载到其中的位置。使用 accept-everything &lt;intent-filter&gt; 意味着你会不断出现在用户可能不想要你的地方,这会增加用户意外选择你的应用的机会。

标签: android android-intent intentfilter


【解决方案1】:

没有直接解决这个问题的方法是使用每个 Activity 的 Intent Filters,所以我创建了 FileIntentActivity,它接受以下 Intent Filter

<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 用于接受任何文件格式,然后根据 文件扩展名 决定进一步的操作,该文件扩展名由 Content 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 选择器中仅显示 1 个文件 Intent Activity 而不是单个应用程序的多个 Activity,至少使用户交互不那么混乱

【讨论】:

    猜你喜欢
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 1970-01-01
    • 2015-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多