Tam*_*mas 90 android intentfilter android-manifest
我有一个自定义文件类型/扩展名,我想与我的应用程序关联.
据我所知,数据元素是为此目的而制作的,但我无法使其正常工作. http://developer.android.com/guide/topics/manifest/data-element.html 根据文档和很多论坛帖子,它应该像这样工作:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/pdf" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)
好吧,它不起作用.我做错了什么?我只想声明自己的文件类型.
Phy*_*Tea 113
您需要多个意图过滤器来解决您想要处理的不同情况.
例1,处理没有mimetypes的http请求:
<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=".*\\.pdf" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)
处理mimetypes,后缀无关紧要:
<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:mimeType="application/pdf" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)
处理文件浏览器应用程序中的意图:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:host="*" />
<data android:pathPattern=".*\\.pdf" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)
Emm*_*ery 48
在我添加之前,其他解决方案对我来说无法可靠地运行:
android:mimeType="*/*"
Run Code Online (Sandbox Code Playgroud)
之前它在某些应用程序中有效,有些则不...
完整的解决方案:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" android:host="*" android:pathPattern=".*\\.EXT" android:mimeType="*/*" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)
小智 24
Phyrum Tea和yuku给出的答案已经非常丰富.
我想补充一点,从Android 7.0 Nougat开始,对应用程序之间文件共享的处理方式有所改变:
从官方Android 7.0更改:
对于定位到Android 7.0的应用,Android框架会强制执行StrictMode API策略,该策略禁止在应用外部公开file:// URI.如果包含文件URI的intent离开了您的应用程序,则该应用程序将失败并出现FileUriExposedException异常.
要在应用程序之间共享文件,您应发送content:// URI并授予对URI的临时访问权限.授予此权限的最简单方法是使用FileProvider类.有关权限和共享文件的详细信息,请参阅共享文件.
如果你有自己的自定义文件没有特定的结尾mime-type
(或者我猜甚至有一个)你可能需要添加第二个scheme
值intent-filter
,使其也可以使用FileProviders
.
例:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:scheme="content" />
<data android:mimeType="*/*" />
<!--
Work around Android's ugly primitive PatternMatcher
implementation that can't cope with finding a . early in
the path unless it's explicitly matched.
-->
<data android:host="*" />
<data android:pathPattern=".*\\.sfx" />
<data android:pathPattern=".*\\..*\\.sfx" />
<data android:pathPattern=".*\\..*\\..*\\.sfx" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.sfx" />
<!-- keep going if you need more -->
</intent-filter>
Run Code Online (Sandbox Code Playgroud)
这里重要的是增加
<data android:scheme="content" />
Run Code Online (Sandbox Code Playgroud)
过滤器.
我很难发现这个小小的变化让我的活动在Android 7.0设备上打开,而旧版本的一切都很好.我希望它对某人有帮助.
LFO*_*FOR 19
我的发现:
您需要多个过滤器来处理检索文件的不同方法.即,通过gmail附件,通过文件浏览器,通过HTTP,通过FTP ...它们都发送非常不同的意图.
您需要过滤掉在活动代码中触发活动的意图.
对于下面的示例,我创建了一个假文件类型new.mrz.我从gmail附件和文件资源管理器中检索它.
onCreate()中添加的活动代码:
Intent intent = getIntent();
String action = intent.getAction();
if (action.compareTo(Intent.ACTION_VIEW) == 0) {
String scheme = intent.getScheme();
ContentResolver resolver = getContentResolver();
if (scheme.compareTo(ContentResolver.SCHEME_CONTENT) == 0) {
Uri uri = intent.getData();
String name = getContentName(resolver, uri);
Log.v("tag" , "Content intent detected: " + action + " : " + intent.getDataString() + " : " + intent.getType() + " : " + name);
InputStream input = resolver.openInputStream(uri);
String importfilepath = "/sdcard/My Documents/" + name;
InputStreamToFile(input, importfilepath);
}
else if (scheme.compareTo(ContentResolver.SCHEME_FILE) == 0) {
Uri uri = intent.getData();
String name = uri.getLastPathSegment();
Log.v("tag" , "File intent detected: " + action + " : " + intent.getDataString() + " : " + intent.getType() + " : " + name);
InputStream input = resolver.openInputStream(uri);
String importfilepath = "/sdcard/My Documents/" + name;
InputStreamToFile(input, importfilepath);
}
else if (scheme.compareTo("http") == 0) {
// TODO Import from HTTP!
}
else if (scheme.compareTo("ftp") == 0) {
// TODO Import from FTP!
}
}
Run Code Online (Sandbox Code Playgroud)
Gmail附加过滤器:
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" />
<data android:mimeType="application/octet-stream" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)
文件浏览器过滤器:
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:pathPattern=".*\\.mrz" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)
HTTP过滤器:
<intent-filter android:label="@string/rbook_viewer">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
<data android:pathPattern=".*\\.mrz" />
</intent-filter>
Run Code Online (Sandbox Code Playgroud)
上面使用的私有函数:
private String getContentName(ContentResolver resolver, Uri uri){
Cursor cursor = resolver.query(uri, null, null, null, null);
cursor.moveToFirst();
int nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
if (nameIndex >= 0) {
return cursor.getString(nameIndex);
} else {
return null;
}
}
private void InputStreamToFile(InputStream in, String file) {
try {
OutputStream out = new FileOutputStream(new File(file));
int size = 0;
byte[] buffer = new byte[1024];
while ((size = in.read(buffer)) != -1) {
out.write(buffer, 0, size);
}
out.close();
}
catch (Exception e) {
Log.e("MainActivity", "InputStreamToFile exception: " + e.getMessage());
}
}
Run Code Online (Sandbox Code Playgroud)
Ran*_*ku' 15
该 pathPattern
<data android:pathPattern=".*\\.pdf" />
Run Code Online (Sandbox Code Playgroud)
如果文件路径在".pdf"之前包含一个或多个点,则不起作用.
这将有效:
<data android:pathPattern=".*\\.pdf" />
<data android:pathPattern=".*\\..*\\.pdf" />
<data android:pathPattern=".*\\..*\\..*\\.pdf" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.pdf" />
Run Code Online (Sandbox Code Playgroud)
如果要支持更多点,请添加更多.
小智 5
我一直试图让它工作很长时间,并且基本上已经尝试了所有建议的解决方案,但仍然无法让 Android 识别特定的文件扩展名。我有一个带有"*/*"
mimetype的意图过滤器,它似乎是唯一可用的东西,文件浏览器现在将我的应用程序列为打开文件的选项,但是我的应用程序现在显示为打开任何类型文件的选项,即使我已经使用 pathPattern 标记指定了特定的文件扩展名。到目前为止,即使我尝试查看/编辑联系人列表中的联系人,Android 也会询问我是否要使用我的应用程序查看联系人,这只是发生这种情况的许多情况之一,非常非常烦人。
最终我发现这个 google groups 帖子有一个类似的问题,一个实际的 Android 框架工程师回答了这个问题。她解释说,Android 根本不了解文件扩展名,只了解 MIME 类型(https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0)。
因此,从我所看到、尝试和阅读的情况来看,Android 根本无法区分文件扩展名,而 pathPattern 标签基本上是对时间和精力的巨大浪费。如果你足够幸运只需要某种 mime 类型的文件(比如文本、视频或音频),你可以使用带有 mime 类型的意图过滤器。但是,如果您需要特定的文件扩展名或 Android 不知道的 mime 类型,那么您就不走运了。
如果我对此有任何错误,请告诉我,到目前为止,我已经阅读了所有帖子并尝试了我能找到的所有建议解决方案,但都没有奏效。
我可以再写一两页关于这类事情在 Android 中似乎是多么普遍以及开发者体验是多么糟糕,但我会为你省去我愤怒的咆哮;)。希望我为某人省了一些麻烦。
小智 5
Markus Ressel 是正确的。Android 7.0 Nougat 不再允许使用文件 URI 在应用之间共享文件。必须使用内容 URI。但是,内容 URI 不允许共享文件路径,只能共享 MIME 类型。因此,您不能使用内容 URI 将您的应用与您自己的文件扩展名相关联。
Drobpox 在 Android 7.0 上有一个有趣的行为。当它遇到未知的文件扩展名时,它似乎会形成一个文件 URI 意图,但它不会启动该意图,而是调用操作系统来找出哪些应用程序可以接受该意图。如果只有一个应用程序可以接受该文件 URI,则它会直接向该应用程序发送显式内容 URI。因此,要使用 Dropbox,您无需更改应用程序上的意图过滤器。它不需要内容 URI 意图过滤器。只需确保该应用程序可以接收内容 URI,并且您的具有您自己的文件扩展名的应用程序可以像 Android 7.0 之前一样在 Dropbox 中使用。
这是我的文件加载代码修改为接受内容 URI 的示例:
Uri uri = getIntent().getData();
if (uri != null) {
File myFile = null;
String scheme = uri.getScheme();
if (scheme.equals("file")) {
String fileName = uri.getEncodedPath();
myFile = new File(filename);
}
else if (!scheme.equals("content")) {
//error
return;
}
try {
InputStream inStream;
if (myFile != null) inStream = new FileInputStream(myFile);
else inStream = getContentResolver().openInputStream(uri);
InputStreamReader rdr = new InputStreamReader(inStream);
...
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
65369 次 |
最近记录: |