Android intent filter: associate an application with a file extension

I have my own type / file extension with which I want to associate my application.

As far as I know, the data element is created for this purpose, but I cannot get it to work. http://developer.android.com/guide/topics/manifest/data-element.html According to the docs and a lot of forum posts, it should work like this:

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

Well, that doesn't work. What have I done wrong? I just want to declare my own file type.

+87
android android-manifest intentfilter
Sep 21 '10 at 12:32
source share
16 answers

You need several intent filters to solve the various situations that you want to handle.

Example 1, process HTTP requests without 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:pathPattern=".*\\.pdf" /> </intent-filter> 

Handle with mimetypes, where the suffix doesn't matter:

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

Pay attention to the file browser application:

  <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> 
+111
Feb 23 '11 at 22:00
source share
โ€” -

Other solutions did not work reliably for me until I added:

 android:mimeType="*/*" 

Before that, he worked in some applications, in some not ...

complete solution for me:

 <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> 
+46
Oct. 16 '12 at 12:59
source share

The answers provided by Phyrum Tea and yuku are already very informative.

I want to add that starting from Android 7.0 Nougat there is a change in the way files are exchanged between applications:

From the official Android 7.0 Changes :

For applications targeting Android 7.0, the Android platform provides a StrictMode API policy prohibiting the publication of files: // URIs outside of your application. If the intent containing the file URI leaves your application, the application with a FileUriExposedException error.

To exchange files between applications, you must send the content: // URI and grant permission for temporary access to the URI. The easiest way to grant this permission is with the FileProvider class. For more information on permissions and shared files, see the "File Sharing" section.

If you have your own custom file ending without a specific mime-type (or I think even one), you may need to add a second scheme value to your intent-filter so that it works with FileProviders too.

Example:

 <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 ugly primitive PatternMatcher implementation that can't cope with finding a . early in the path unless it 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> 

Important here is the addition

 <data android:scheme="content" /> 

to the filter.

It was difficult for me to find out about this small change that did not allow my activity to open on Android 7.0 devices, while in older versions everything was fine. Hope this helps someone.

+19
06 Oct '16 at 0:45
source share

My findings:

You need several filters to handle various file extraction methods. those. via gmail attachment, file explorer, HTTP, FTP ... They all send completely different intentions.

And you need to filter out the intent that triggers your activity in your activity code.

In the example below, I created a fake file type new.mrz. And I got it from gmail attachment and file explorer.

Operation code added to 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! } } 

Gmail attachment filter:

  <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> 
  • LOG: content intent detected: android.intent.action.VIEW: content: //gmail-ls/l.foul@gmail.com/messages/2950/attachments/0.1/BEST/false: application / octet-stream: new. mrz

File Explorer Filter:

  <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> 
  • LOG: file intent detected: android.intent.action.VIEW: file: ///storage/sdcard0/My%20Documents/new.mrz: null: new.mrz

HTTP filter:

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

Private functions used above:

 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()); } } 
+18
Sep 25 '14 at 9:07
source share

pathPattern

 <data android:pathPattern=".*\\.pdf" /> 

does not work if the file path contains one or more points before the ".pdf".

This will work:

 <data android:pathPattern=".*\\.pdf" /> <data android:pathPattern=".*\\..*\\.pdf" /> <data android:pathPattern=".*\\..*\\..*\\.pdf" /> <data android:pathPattern=".*\\..*\\..*\\..*\\.pdf" /> 

Add more if you want to support more points.

+15
Aug 28 2018-12-12T00:
source share
Marcus Ressel is correct. Android 7.0 Nougat no longer allows file sharing between applications using a file URI. You must use the content URI. However, the content URI does not allow file sharing, but only the mime type. Therefore, you cannot use content URIs to associate an application with your own file extension.

Drobpox has an interesting behavior on Android 7.0. When it encounters an unknown file extension, it appears to generate the intent of the file URI, but instead of launching the intent, it calls the operating system to find out which applications can accept the intent. If there is only one application that can accept this file URI, it then sends the explicit content URL directly to that application. Therefore, to work with Dropbox you do not need to change the intent filters in your application. It does not require a URI filter for content. Just make sure that the application can get the URI of the content, and your application with your own file extension will work with Dropbox, as it was before Android 7.0.

Here is an example file upload code modified to accept the content 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); ... } } 
+4
Jun 11 '17 at 23:50
source share

Iโ€™ve been trying to get this to work for ages and tried all the suggested solutions, and still canโ€™t get Android to recognize certain file extensions. I have an intent filter with the "*/*" type mimetype, which seems to work, and file browsers now list my application as an option to open files, however now my application is shown as an option to open ANY VIEW even though I have specified file extensions using the pathPattern tag. It is still that even when I try to view / edit a contact in my contact list, Android asks me if I want to use my application to view a contact, and this is just one of many situations when this happens, it is VERY VERY annoying.

In the end, I found this post in google groups with a similar question, answered by the actual Android developer. She explains that Android just doesn't know anything about file extensions, only MIME types ( https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0 ).

So, from what I saw, tried and read, Android simply cannot distinguish between file extensions and the pathPattern tag - this is basically a huge waste of time and energy. If you are lucky that you only need files of a certain mime type (for example, text, video or audio), you can use the intent filter with the mime type. If you need a specific file extension or mime type unknown to Android, however you're out of luck.

If I am mistaken about any of this, please tell me so far I have read every message and tried every proposed solution that I could find, but no one worked.

I could write another or two pages about how common things are in Android and how intrusive the experience of developers is, but I will save you my angry ranting;). I hope I saved someone from trouble.

+3
Oct 29 '14 at 16:01
source share

Try to add

 <action android:name="android.intent.action.VIEW"/> 
+2
Sep 21 '10 at 13:03
source share

In the Gmail application you can use:

 <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/pdf" /> <!-- .pdf --> <data android:mimeType="application/msword" /> <!-- .doc / .dot --> <data android:mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" /> <!-- .docx --> <data android:mimeType="application/vnd.ms-excel" /> <!-- .xls / .xlt / .xla --> <data android:mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" /> <!-- .xlsx --> <data android:mimeType="application/vnd.ms-powerpoint" /> <!-- .ppt / .pps / .pot / .ppa --> <data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" /> <!-- .pptx --> <data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.slideshow" /> <!-- .ppsx --> <data android:mimeType="application/zip" /> <!-- .zip --> <data android:mimeType="image/jpeg" /> <!-- .jpeg --> <data android:mimeType="image/png" /> <!-- .png --> <data android:mimeType="image/gif" /> <!-- .gif --> <data android:mimeType="text/plain" /> <!-- .txt / .text / .log / .c / .c++ / ... --> 

Add as many mime types as needed. I only need those for my project.

+1
Jan 14 '15 at 10:28
source share
  <!-- Works for Files, Drive and DropBox --> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="file" /> <data android:mimeType="*/*" /> <data android:host="*" /> <data android:pathPattern=".*\\.teamz" /> </intent-filter> <!-- Works for Gmail --> <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:host="gmail-ls" android:scheme="content" android:mimeType="application/octet-stream"/> </intent-filter> 

Please note that this will force your application to open all gmail file attachments, there is no way to bypass it

+1
Sep 28 '15 at 18:39
source share

Those who have problems with other File Manager \ Explorer applications like @yuku and @ phyrum-tea answered

This works with the LG default file manager application

  <intent-filter android:label="@string/app_name_decrypt"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="file" /> <data android:pathPattern=".*\\.lock" /> <data android:pathPattern=".*\\..*\\.lock" /> <data android:pathPattern=".*\\..*\\..*\\.lock" /> </intent-filter> 

but could not work with ES File Explorer and other file managers, so I added

  android:mimeType="*/*" 

then it works with ES Explorer, but LG file manager could not determine the file type, so my solution

  <intent-filter android:label="@string/app_name_decrypt"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="file" /> <data android:pathPattern=".*\\.lock" /> <data android:pathPattern=".*\\..*\\.lock" /> <data android:pathPattern=".*\\..*\\..*\\.lock" /> </intent-filter> <intent-filter android:label="@string/app_name_decrypt"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="file"/> <data android:scheme="content" /> <data android:mimeType="*/*" /> <data android:pathPattern=".*\\.lock" /> <data android:pathPattern=".*\\..*\\.lock" /> <data android:pathPattern=".*\\..*\\..*\\.lock" /> </intent-filter> 
+1
Oct 26 '17 at 15:21
source share

Try it, it will help you. Instead of pdf, you can use other extensions. First you must add read permission from external storage to the androidmanifest.xml file.

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 

Then, in the androidmanifest file in the Activity tag, you add an intent filter, as shown below.

  <action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType= "application/pdf" /> <data android:host="*" /> </intent-filter> 

Finally, in your code, you will get the path to the PDF file, as shown below:

 Intent intent=getIntent(); if(intent!=null) { String action=intent.getAction(); String type=intent.getType(); if(Intent.ACTION_VIEW.equals(action) && type.endsWith("pdf")) { // Get the file from the intent object Uri file_uri=intent.getData(); if(file_uri!=null) filepath=file_uri.getPath(); else filepath="No file"; } else if(Intent.ACTION_SEND.equals(action) && type.endsWith("pdf")){ Uri uri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); filepath = uri.getPath(); } 
+1
Nov 26 '18 at 13:46
source share

URI of the ftw content and with an intent filter in the manifest ... if your files have their own .xyz extension, add the appropriate mime type:

  <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:host="*" android:mimeType="application/xyz" android:scheme="content" /> </intent-filter> 

Some applications, such as email, seem to convert the extension to a mime type. Now I can click on the attachment in the email and open it in my application.

0
Feb 14 '18 at 2:42
source share

// I tried this code. And it works well. You can use this code to accept a PDF file.

 <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="application/pdf" /> <data android:pathPattern=".*\\.pdf" /> <data android:pathPattern=".*\\..*\\.pdf" /> <data android:pathPattern=".*\\..*\\..*\\.pdf" /> <data android:pathPattern=".*\\..*\\..*\\..*\\.pdf" /> </intent-filter> 
0
May 24 '19 at 18:40
source share

Read the opening file in kotlin:

 private fun checkFileOpening(intent: Intent) { if (intent.action == Intent.ACTION_VIEW && (intent.scheme == ContentResolver.SCHEME_FILE || intent.scheme == ContentResolver.SCHEME_CONTENT)) { val text = intent.data?.let { contentResolver.openInputStream(it)?.bufferedReader()?.use(BufferedReader::readText) } } } 
0
Jun 12 '19 at 16:46
source share

Put this intent filter in the activity tag in the manifest that you want to open by touching the file:

 <intent-filter android:priority="999"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.OPENABLE" /> <data android:host="*" /> <data android:mimeType="application/octet-stream" /> <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.yourextension" /> <data android:pathPattern=".*\\..*\\..*\\..*\\.yourextension" /> <data android:pathPattern=".*\\..*\\..*\\.yourextension" /> <data android:pathPattern=".*\\..*\\.yourextension" /> <data android:pathPattern=".*\\.yourextension" /> <data android:scheme="content" /> </intent-filter> 
-one
May 03, '19 at 17:09
source share



All Articles