Reputation: 616
I am working on an app that uses a custom file type, I've figured out how to register my app with the system as being able to open files of this type using intent filters and my app will also show up on the list of apps that can be used to open this file from the built in email client when trying to open an attachment of this type. The problem is the code that handles opening the file when passed in from the file browser does not work when it is passed in from the email client. Here is the code that I use that works correctly when the Activity is called from the file browser after selecting a file of the correct type:
Intent i = getIntent();
if(i == null) return;
Uri u = i.getData();
if(u == null) return;
String filePath = u.getEncodedPath();
if(filePath == null) return;
Util.loadOTDRFile(filePath);
What I get in the "filePath" string when loading from the file browser is something like "mnt/storage/Android/data/com.fiberdroid.001/downloads/filename.trc... and that works fine my app loads it in the loadOTDRFile() function successfully.
However, when I open the same type of file from the email client the filePath variable in that code ends up being something like the following: "//mail/parts/4217" which does not load, my load function returns a file not found error.
Here is the relevant code from the loadOTDRFile() function:
File file = new File(filePath);
InputStream is;
try
{
is = new FileInputStream(filePath);
}
catch(FileNotFoundException e)
{
return D.ERROR_FILENOTFOUND;
}
I guess my question is what kind of path is "//mail/parts/4217" and why can't I open it?
Thank you.
Upvotes: 1
Views: 6362
Reputation: 616
For anyone that might stumble upon this question, here is what I did to read the file data from either a content URI or a file URI passed in with an intent from a third party application:
First, put these intent filters in your manifest, replacing ".trc" with the file extension with the type you want your app to open:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" />
<data android:scheme="file" />
<data android:host="*" />
<data android:port="*" />
<data android:pathPattern=".*..*..*..*..*..*.trc" />
<data android:pathPattern=".*..*..*..*..*.trc" />
<data android:pathPattern=".*..*..*..*.trc" />
<data android:pathPattern=".*..*..*.trc" />
<data android:pathPattern=".*..*.trc" />
<data android:pathPattern=".*.trc" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="content" />
<data android:mimeType="text/plain" />
</intent-filter>
Don't ask me about those path patterns, I tried many things that didn't work before stumbling on that solution on this website and it was the first one that worked so I kept it.
Then, add code similar to this to the onCreate() method of the activity that will be receiving the file (the util.loadOTDRFile functions are specific to my app, you'll have to make your own to load your files):
Intent i = getIntent();
if(i == null) return;
Uri u = i.getData();
if(u == null) return;
String scheme = u.getScheme();
if(ContentResolver.SCHEME_CONTENT.equals(scheme))
{
try
{
ContentResolver cr = getContentResolver();
AssetFileDescriptor afd = cr.openAssetFileDescriptor(u, "r");
long length = afd.getLength();
byte[] filedata = new byte[(int) length];
InputStream is = cr.openInputStream(u);
if(is == null) return;
try
{
is.read(filedata, 0, (int) length);
Util.loadOTDRFileFromByteArray(filedata);
}
catch(IOException e)
{
return;
}
}
catch(FileNotFoundException e)
{
return;
}
}
else
{
String filePath = u.getEncodedPath();
if(filePath == null) return;
Util.loadOTDRFileFromPath(filePath);
}
Upvotes: 7
Reputation: 6862
That's a Content URI... You'll need to use ContentResolver to open the file from the mail provider.
To do that you should do:
getContentResolver().openInputStream(u); // Where 'u' is the uri you extract from the intent.
You may wish to put something like this:
Uri u = i.getData();
String scheme = u.getScheme();
if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
// handle as content uri
} else {
// handle as file uri
}
Upvotes: 7