Android receive share text file but not share text content - android

I am making an app that is able to upload single or multiple files or folders. The intent-filter is defined like this:
<activity android:name=".UploadActivity" android:launchMode="singleTop" android:theme="#style/Theme.Sherlock">
<intent-filter android:label="#string/upload_intent">
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/*" />
<data android:mimeType="audio/*" />
<data android:mimeType="image/*" />
<data android:mimeType="media/*" />
<data android:mimeType="multipart/*" />
<data android:mimeType="text/*" />
<data android:mimeType="video/*" />
</intent-filter>
<intent-filter android:label="#string/upload_intent">
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="*/*" />
</intent-filter>
</activity>
This works great with Blackmoon File Explorer and the Android 4.0.3 Gallery. My app shows up in the Share menus. However, it also shows in the Browser, when you long-press the URL and choose to Share Page.
When I send a text file to my app, I get this:
getIntent().getAction() returns Intent.ACTION_SEND
getIntent().getType() returns "text/plain"
getIntent().getScheme() returns null
getIntent().getExtras().getString(Intent.EXTRA_STREAM) returns the filename
However, sending a URL from the Browser returns the same thing minus the Intent.EXTRA_STREAM. I can detect this easily in code and say "hey I can't upload text!" but I'd rather change the intent filter so that it only triggers when there is an EXTRA_STREAM. Is it possible to do so?
(I tried using android:scheme but that won't differentiate between a file and a text string being shared, since they are both null...)

You have:
getIntent().getExtras().getString(Intent.EXTRA_STREAM) returns the filename
AFAIK, Android never sends you an open fh or socket to a file. Just the plain, old path to the file, which you then handle with:
File somefile = new File(filename);
And then read it or write to it or what not.
As for the incoming text being EXTRA_TEXT or STREAM, just test for both and handle appropriately. Hope this helps.

I registered for file in the manifest:
<activity android:name=".ReaderActivity">
<intent-filter >
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file"/>
<data android:mimeType="text/plain"/>
</intent-filter>
</activity>
And then used getData() and a content resolver in my activity.
Uri uri = getIntent().getData();
InputStream inputStream = getContentResolver().openInputStream(uri);
...
See this answer to find out what the ... is.

Related

android download manager open file with my application

I have my android app, that downloads a file via the DownloadService. This file is in special file format, that only can be used in my app - it has the suffix *.foobar.
I start the download this way:
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDestinationInExternalPublicDir("/", "aaaa.foobar");
// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
Download works fine, but when I tap on the notification "download finished", I want that my activity will be opened. What I get is the toast "File can not be opened".
In my Manifest I have a intent-filter for the .foobar file suffix.
<intent-filter android:label="#string/app_name">
<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:mimeType="*/*" />
<data android:pathPattern=".*\\.foobar" />
<data android:host="*" />
</intent-filter>
Am I missing something?
finally found the solution!
I had to remove the path pattern line
<data android:pathPattern=".*\\.foobar" />
and change the schema to content. So the complete intent filter is:
<intent-filter android:label="#string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="content" />
<data android:mimeType="application/wcmap" />
<data android:host="*" />
</intent-filter>
I think you will find the answer to this answer. Most likely you have a problem in the treatment of Activiti or slightly incorrect description of intent.
Try adding a priority.
android:priority="integer"
Also you should look:
Android intent filter for a particular file extension?
Android intent filter for custom file extension
Good luck. Sorry that can not help more. Too much text for a comment.

Saving File and Opening with Android App

I am saving a binary to a file with a custom extension for instance .custom. How do I save it to a specific mime type? I want my app to be called to open that custom file. In the manifest I used / as mimeType but the app gets called even when tapping an image. I used octet-stream but the file doesn't get recognized and the app does not get opened. I just want to save a binary with custom extension and the OS would call my app when it encounters this file.
<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:mimeType="application/octet-stream" />
<data android:pathPattern=".*\\.test" />
<data android:host="*" />
</intent-filter>
Finally, after several views only without answers I figured it out. The post on this link helped me resolve my issue.
https://publish.illinois.edu/weiyang-david/2013/04/11/how-to-write-intent-filter-dealing-with-mime-type-problem/
This example was it
<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>
I replaced the scheme to "file" and replaced with my pathPattern. Removing the mimeType was key to solving my issue. File browsers now suggests to open the custom file with my app.

Android app has been assigned to any possible file - should be assigned to my custom file only

I'm trying to assign my Android app to custom file (json content) with extension "kka".
I'd like to be able to open my app and read *.kka file in following cases:
1. *.kka as email attachment (gmail client)
2. *.kka as file stored in filesystem e.g. Downloads/ folder
My AndroidManifest.xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mydomain.kka" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.mydomain.kka.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</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="file" android:pathPattern=".*\\.kka" android:mimeType="*/*"/>
<data android:scheme="content" android:pathPattern=".*\\.kka" android:mimeType="application/stream-octet"/>
</intent-filter>
</activity>
</application>
</manifest>
That's the only configuration I found to be able to start my app tapping *.kka as attachment in gmail client and as file in filesystem.
The problem is that my app appears in every possible place where I want to open email attachment or file on filesystem, no matter what kind of file it is, so my KKATest app is on the list of assigned apps for e.g. XMLs, PDFs, even APKs, etc.
It seems to ignore file extension I clearly mentioned in AndroidManifest file.
This situation takes place on Galaxy Nexus with Android 4.4, Galaxy S4 with Android 4.3 and few more.
I've read many suggestions on StackOverflow but no one solves my problem. What's wrong with my manifest file?
I was struggling with the same issue. I need to open my file from both SD card as well as from email attachment. For me it was also trail and error, but this is my solution:
<intent-filter> <!-- Intent filter for opening files from system -->
<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:host="*" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.locx" />
</intent-filter>
<intent-filter> <!-- Intent filter for open files from email -->
<data android:scheme="content" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:mimeType="application/octet-stream" />
<data android:pathPattern=".*\\.locx" />
</intent-filter>
locx is my file type obviously.
BTW: I only tested with Gmail app, from other forum posts I understand that other email apps might work different.
Indeed, as you pointed out, some email clients replace the mime type with application/octet-stream. So I ended up using an intent filter like this:
<!-- Filters for handling local files -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" android:scheme="file" android:pathPattern=".*\\.mtype" android:host="*"/>
</intent-filter>
<!-- Filter for email apps -->
<intent-filter>
<action android:name="android.intent.action.VIEW"></action>
<category android:name="android.intent.category.DEFAULT"></category>
<category android:name="android.intent.category.BROWSABLE"></category>
<data android:scheme="content"/>
<data android:mimeType="application/octet-stream"/>
<data android:mimeType="application/mtype"/>
</intent-filter>
This will have your app handle both mtype, and octet-stream. But in the octet-stream case, it may not be actually your file, so you need to do some checking in the app. This means getting the file name, and checking the extension. For this, you can query the content provider, using the uri handled to you in the app, via the intent:
Cursor cursor = mContext.getContentResolver().query(data, null, null, null, null);
int fileNameColumnIndex = cursor.getColumnIndex("_display_name");
if (fileNameColumnIndex != -1) {
String fileName = cursor.getString(fileNameColumnIndex);
}
Now, there are a couple of scenarios:
If you used the gmail client, ther "_display_name" is present;
If you clicked the file, in the Downloader native app, the "_display_name" is present;
If you used the native email client, it is not present; And in this case, i prompt the user to first download the file. If he does so, and then opens the file in the email client again, it will actually open the file, and it will be handled by the first intent-filter.
I've found a solution (almost) and the solution looks like this:
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mydomain.kka" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.mydomain.kka.MainActivity"
android:label="#string/app_name" >
<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="*" android:mimeType="*/*" android:pathPattern=".*\.kka" android:scheme="file" />
</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:mimeType="application/custom-kka" android:scheme="content" />
</intent-filter>
</activity>
</application>
</manifest>
I don't know why entry <data android:host="*" android:mimeType="*/*" android:pathPattern=".*\.kka" android:scheme="file" /> with one backslash ("\") instead of two ("\\") solves the issue with opening all possible files from filesystem - now my app opens only for *.kka files ...
Opening files attached to mails needs to be handled by assigning to mime-type, not file extension. I created custom mime-type "application/custom-kka" and ensured that during sending mail with the file there needs to be set my custom mime-type for attachment.
To do so, I put a piece of code in email composer code:
...
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("application/custom-kka");
...
which should guarantee me proper mime-type for my attachment. Unfortunately, android mail clients (gmail, generic mail client) on few devices send mails with different then mine mime-type, e.g. "application/octet-stream;", "<nothing here>;" but not desired "application/custom-kka;" and my app can't identify such attachment as assigned to it.
That's the PhoneGap application, so I have also iOS version, where sending this mail with custom mime-type works perfectly and android app can recognise the attachment.
Maybe someone had such issue and could help?

Android Intent-Filter custom filetype

First of all, I have scoured the SO and internet about this, an no solutions work. I've been trying to use the filebrowsers AndExplorer and Root Explorer to select *.las files and trigger my application.
This is my current intent filters (although it has gone through tons of revisions trying many different ideas):
<activity android:name=".Viewer"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<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:host="*" />
<data android:pathPattern=".*\\.las" />
</intent-filter>
</activity>
Does anyone have any idea how to trigger the custom filetype response? I want to be able to launch my application and grab the filepath of the file from both a file browser, and after an internet download of the file.
Thank so much!
It looks like the big issue with file type intent filters is that allot of different programs handle the intents differently. I couldn't get AndExplorer to respond to any thing I found(i.e get it to open the .eva file). However I did get file manager and astro file browser working using the intent filters below. As an alternative having the app launch an activity to select the file dose work for all the file browsers I tried(if your using file manager it dose not return data like the other ones, so some adjustments have to be made(just saw this in debugging didnt write code to fix it), but instead I am just working on creating a custom file chooser, as it avoids any issues that other file managers users may have):
...
<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="content" android:host="*"
android:pathPattern=".*\\.eva" />
<data android:scheme="file" android:host="*"
android:pathPattern=".*\\.eva" />
</intent-filter>
<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:mimeType="*/*" />
<data android:scheme="content" android:host="*"
android:pathPattern=".*\\.eva" />
<data android:scheme="file" android:host="*"
android:pathPattern=".*\\.eva" />
</intent-filter>
...
Intent intent2Browse = new Intent();
Toast.makeText(this, R.string.Choose_EVAKey_File, Toast.LENGTH_LONG).show();
intent2Browse.addCategory(Intent.CATEGORY_OPENABLE);
intent2Browse.setType("application/xml");
intent2Browse.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent2Browse,Select_EVA_FILE);
....
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == Select_EVA_FILE && resultCode == RESULT_OK) {
Uri currFileURI = data.getData();
path2Key = currFileURI.getPath();
...

Android intent filter: associate app with file extension

I have a custom file type/extension that I want to associate my app with.
As far as I know, the data element is made for this purpose, but I can't get it working.
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, it does not work. What did I do wrong? I simply want to declare my own file type.
You need multiple intent filters to address different situation you want to handle.
Example 1, handle 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 is irrelevant:
<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>
Handle intent from a file browser app:
<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>
The other solutions did not work reliably for me until I added:
android:mimeType="*/*"
Before that it 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>
The answeres given by Phyrum Tea and yuku are very informative already.
I want to add that starting with Android 7.0 Nougat there is a change to the way file sharing between apps is handled:
From official Android 7.0 Changes:
For apps targeting Android 7.0, the Android framework enforces the
StrictMode API policy that prohibits exposing file:// URIs outside
your app. If an intent containing a file URI leaves your app, the app
fails with a FileUriExposedException exception.
To share files between applications, you should send a content:// URI
and grant a temporary access permission on the URI. The easiest way to
grant this permission is by using the FileProvider class. For more
information on permissions and sharing files, see Sharing Files.
If you have your own custom file ending without a specific mime-type (or i guess even with one) you may have to add a second scheme value to your intent-filter to make it work 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'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>
The important thing here is the addition of
<data android:scheme="content" />
to the filter.
I had a hard time finding out about this little change which kept my activity from opening on Android 7.0 devices while everything was fine on older versions. I hope it helps someone.
My findings:
You need several filters to deal with the different ways of retrieving a file. ie, by gmail attachment, by file explorer, by HTTP, by FTP...
They all send very different intents.
And you need to filter out the intent that trigger your activity in your activity code.
For the example below, I created a fake file type new.mrz. And I retrieved it from gmail attachment and file explorer.
Activity code added in the 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 attachement 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());
}
}
The pathPattern
<data android:pathPattern=".*\\.pdf" />
does not work if the file path contains one or more dots before ".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 dots.
I've been trying to get this to work for ages and have tried basicly all the suggested solutions and still cannot get Android to recognise specific file extensions. I have an intent-filter with a "*/*" mimetype which is the only thing that seems to work and file-browsers now list my app as an option for opening files, however my app is now shown as an option for opening ANY KIND of file even though I've specified specific file extensions using the pathPattern tag. This goes so far that even when I try to view/edit a contact in my contacts list Android asks me if I want to use my app to view the contact, and that is just one of many situations where this occurs, VERY VERY annoying.
Eventually I found this google groups post with a similar question to which an actual Android framework engineer replied. She explains that Android simply does not know anything about file-extensions, only MIME-types (https://groups.google.com/forum/#!topic/android-developers/a7qsSl3vQq0).
So from what I've seen, tried and read, Android simply cannot distinguish between file-extensions and the pathPattern tag is basicly a gigantic waste of time and energy. If you are fortunate enough to only need files of a certain mime-type (say text, video or audio), you can use an intent-filter with a mime-type. If you need a specific file-extension or a mime-type not known by Android however then you're out of luck.
If I'm wrong about any of this please tell me, so far I've read every post and tried every proposed solution I could find but none have worked.
I could write another page or two about how common these kinds of things seem to be in Android and how screwed up the developer experience is, but I'll save you my angry rantings ;). Hope I saved someone some trouble.
Markus Ressel is correct. Android 7.0 Nougat no longer permits file sharing between apps using a file URI. A content URI must be used. However, a content URI does not allow a file path to be shared, only a mime type. So you cannot use a content URI to associate your app with your own file extension.
Drobpox has an interesting behavior on Android 7.0. When it meets an unknown file extension it appears to form a file URI intent but instead of launching the intent it calls the operating system to find out which apps can accept the intent. If there is only one app that can accept that file URI it then sends an explicit content URI directly to that app. So to work with Dropbox you do not need to change the intent filters on your app. It does not require a content URI intent filter. Just make sure the app can receive a content URI and your app with your own file extension will work with Dropbox just like it did before Android 7.0.
Here is an example of my file loading code modified to accept a 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);
...
}
}
Those who having issue with other File Manager\Explorer apps, as #yuku and #phyrum-tea answered
This works with LG default file manager app
<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 detect file type so my solution is
<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>
You try this it will help for you.Instead of pdf you can use other extensions also.
First you have to add read external storage permission in 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 get path of 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();
}
Read 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)
}
}
}
Try adding
<action android:name="android.intent.action.VIEW"/>
For Gmail attachment, 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.
<!--
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>
Notice that this will get your app open all gmail file attachments, there is no way to work around it
Content URI ftw, and with the intent filter in the manifest... if your files have a custom extension .xyz, add a matching 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 apps such as email seem to convert the extension into a mime type. Now I can click on the attachment in email and have it open in my app.
Put this intent filter inside the activity tag in manifest you'd like to open 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>
None of the above solution worked for me, I had to combine all of them to make it work like this:
<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>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="content"/>
<data android:scheme="file"/>
<data android:mimeType="application/pdf"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="content"/>
<data android:scheme="file"/>
<data android:host="*"/>
<data android:pathPattern=".*\\.pdf"/>
</intent-filter>
// I have tried this code. And it is working well. You can use this code to accept 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>

Categories

Resources