How to differentiate between a file URI and contentprovider URI? - android

Suppose I'm selecting a file externally via:
Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, GALLERY_REQUEST_CODE);
and in the result is returned via onActivityResult
Uri file = data.getData();
This can be in different formats. What is the convention here to determine if a content resolver query is needed? If the file URI is a file path file:/// or a app URI like //package.example/....
I know I could check if the uri has a file:/// prefix but that seems a bit hacky. I just want the file path.

What is the convention here to determine if a content resolver query is needed?
openInputStream() on ContentResolver handles both the file scheme and the content scheme.
I know I could check if the uri has a file:/// prefix but that seems a bit hacky
Um, well, Uri has a getScheme() method.
I just want the file path.
There is no "file path" for a content Uri, as there is no requirement that the content be stored as a file.

Just to compliment CommonsWare answer. You can examine the scheme of the URI, using, for example, getScheme() method, as mentioned in CommonsWare's answer. A content provider URI scheme is content://, while a file URI scheme is file://

Related

Can I create a DocumentFile with a stored Uri?

I got a Uri using the following method.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, MY_REQUEST_CODE);
like:
content://com.android.externalstorage.documents/tree/primary%3A
Can I store this string to create a DocumentFile in application startup?
like:
DocumentFile.fromUri(this,Uri.pasre(str))
It works on Android 6.0,but it seems invalid in higher version.
Or I should get Uri every time I start it?
I have found that some file managers do not need to get Uri via startActivityForResult(). Like RE. Are they using the shell to get a list under /storage and then stitching them into Uri?
Then use grantUriPermission() and takePersistableUriPermission() to get Uri permissions?
Sorry, my English is too bad. TT

Rename URI file to share audio from raw folder

I'm trying to make an application with sharing of children that are inside the "raw" folder of the application, but I'm not getting it. The file is shared but does not have an .mp3 extension. I was not able to hear Windows Media Player, but I put a .mp3 extension manually. Does anybody have any idea how I do it to get .mp3 extension automatically? Transform / rename a URI into mp3 file.
The name of the song comes as it is registered in the file, I believe that if it was possible to rename adding the .mp3 in the end may work. But I'm not able to rename.
I am using this code:
Intent share;
Uri uri = Uri.parse("android.resource://"+this.getPackageName()+"/raw/name_musica");
share = new Intent(Intent.ACTION_SEND);
share.putExtra(Intent.EXTRA_STREAM, uri); share.setType("audio/*");
share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(share, "Enviar via: "));
The documentation for EXTRA_STREAM states that it is:
A content: URI holding a stream of data associated with the Intent, used with ACTION_SEND to supply the data being sent.
android.resource: is not content:. There is no requirement for anything that responds to ACTION_SEND to know what to do with an android.resource: Uri in EXTRA_STREAM.
Copy the resource to the local filesystem and use FileProvider, so FileProvider can give you a content: Uri to use with EXTRA_STREAM. Or, write your own ContentProvider that serves the content directly from your raw resource, and use a content: Uri for your provider.
Also, do not use audio/*. Use the actual concrete MIME type of the content that you are sharing.

Send an email with attached file

I'm with a problem... When I try to open the Gmail from an Intent, with a attached file, It shows to me in a Toast: "cant send empty file". My PDF file is inside in a folder in my app (/storage/emulated/0/Android/data/teste.com.br.cartaovisitateste/files/business.pdf), but I cant suck this file, to put in the email. Problably, the problem is with to localize the path, but I don't know how to solve this
This is my code:
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("vnd.android.cursor.dir/email");
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
i.putExtra(Intent.EXTRA_EMAIL, "wallacekingsdon#gmail.com");
// it does not work
i.putExtra(Intent.EXTRA_STREAM, Uri.parse("/storage/emulated/0/Android/data/digitalsa.com.br.cartaovisitaultragaz/files/business.pdf"));
// it does not work too
Uri.fromFile(new File(Environment.getDataDirectory().getAbsolutePath(), "business.pdf"));
i.putExtra(Intent.EXTRA_SUBJECT, String.valueOf(Hawk.get("registro_nome")).concat(" Business Card"));
startActivity(Intent.createChooser(i, "Enviando e-mail..."));
i.setType("vnd.android.cursor.dir/email");
The MIME type of a PDF file is application/pdf. The MIME type of an ACTION_SEND Intent is either the type used for EXTRA_STREAM or EXTRA_TEXT. In your case, you are using EXTRA_STREAM, and that appears to be attempting to point to a PDF file.
i.putExtra(Intent.EXTRA_STREAM, Uri.parse("/storage/emulated/0/Android/data/digitalsa.com.br.cartaovisitaultragaz/files/business.pdf"));
Do not hardcode paths. And do not pass things that are not Uri values to Uri.parse(). A Uri has a scheme, like https, file, or content.
Uri.fromFile(new File(Environment.getDataDirectory().getAbsolutePath(), "business.pdf"));
First, you are not putting that in an extra. The value is not being used.
Second, Uri.fromFile() will not work on Android 7.0+ in an Intent extra. You will get a FileUriExposedException. Use FileProvider to serve up the PDF, and use FileProvider.getUriForFile() to get the Uri to put into EXTRA_STREAM, at least on Android 7.0+ devices.

Android FileProvider.GetUriForFile is cutting off the start of the URI

I'm trying to update my code which gets the database file. I'm trying to use a FileProvider instead.
I'm a bit stuck because the original file path is "/storage/emulated/0/Android/data/com.abc/files/abcMobile.db3”
I need to get the URI which is returned by FileProvider.GetUriForFile to include "/storage/emulated/0/“ at the start of it.
Here is my code:
Log.Info ("directory", GetDirectory (dir).ToString());
Log.Info ("filename", filename);
File newFile = new File (GetDirectory (dir).AbsolutePath, "/" + filename);
Android.Net.Uri androidContentUri = FileProvider.GetUriForFile (Application.Context, Application.Context.PackageName + ".fileprovider", newFile);
System.Uri systemContentUri = SystemUri (androidContentUri);
return systemContentUri;
In the code above I have created a file which has a path of "/storage/emulated/0/Android/data/com.abc/files/abcMobile.db3” but when I pass the file to FileProvider.GetUriForFile() It seems to create an Android.Net.URI of {content://com.abc.fileprovider/./Android/data/com.abc/files/abcMobile.db3} and I cast it to a System.Net.URI which becomes {content://com.abc.fileprovider/Android/data/com.abc/files/abcMobile.db3}.
I just need to figure out why it deletes "/storage/emulated/0/“ from the start of the Android.Net.Uri and stop that from happening and then it should work. Any ideas?
I just need to figure out why it deletes "/storage/emulated/0/“ from the start of the Android.Net.Uri and stop that from happening and then it should work. Any ideas?
Because you are generating content uri for your file,which grant temporary permission for access to this file. Return a full path of the file is not considered to be a secure way.
And if you are refer to "Generating the Content URI for a File" section of FileProvider. You will find the following sentence:
To share a file with another app using a content URI, your app has to generate the content URI.
...
As a result of the previous snippet, getUriForFile() returns the content URI content://com.mydomain.fileprovider/my_images/default_image.jpg.
So, it is a expected form of ContentUri that returned by FileProvider.

How to convert a file:// uri into content:// uri?

I have found that on my device, the default media display tool is not showing me the same if Ihave a uri that is:
file://mnt/sdcard/DCIM/Image.jpg
When I go through picking the image with the built in intent I get this:
content://media/external/images/media/247
These both display the same file, but I don't have any sharing options when I use the first one.
My question is, how can I find the content Uri given the file Uri?
I was making the file, so I had a File object file.
So I do this now to get Uri for the file as a "content://" Uri.
Uri capturedImage = Uri.parse(
android.provider.MediaStore.Images.Media.insertImage(
getContentResolver(),
file.getAbsolutePath(), null, null));
Credit to answer on this question How can I capture an image in Android and have it show up in the gallery?

Categories

Resources