Open an image from the external storage - java

I've been trying for several hours to open an image from Android's external storage with Intent.ACTION_VIEW. And as you might have figured out already, I'm still not able to do that.
I've searched all over Google and I've tried a lot of ways to make this work, however none of them did. All what I could find are questions that are up to 1 year old. I tried using FileProvider and here's what I ended up with:
File imagePath = new File(Environment.getExternalStorageDirectory(), "LyceeLamartine/cache");
File newFile = new File(imagePath, "calendrier.png");
Uri contentUri = FileProvider.getUriForFile(MainActivity.this, "ml.toufic.lyceelamartine.fileprovider", newFile);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(contentUri, "image/*");
startActivity(intent);
The code above opens Google Photos successfully but it shows a black screen and the path seems to be: content://ml.toufic.lyceelamartine.fileprovider/name/calendrier.png and this seems like an internal storage path.
The image I want to access is stored at: "/storage/emulated/0/LyceeLamartine/cache/calendrier.png" and I'm using a phone with Android O (8.0).
I'm still a beginner in Java and any help would be greatly appreciated!

the path seems to be: content://ml.toufic.lyceelamartine.fileprovider/name/calendrier.png and this seems like an internal storage path.
That is not a path. That is a Uri. It has a scheme (content). It points to your FileProvider (ml.toufic.lyceelamartine.fileprovider). It seems fine — if there were a problem with the Uri, FileProvider would have thrown an exception when you tried to create it.
The code above opens Google Photos successfully but it shows a black screen
There are two problems with your Intent.
First, do not use a wildcard MIME type. It is your file. You know what the MIME type is. Use the actual MIME type (in this case, image/png).
Second, call addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) on the Intent as part of setting it up, before calling startActivity(). Right now, no app has rights to use your content.

Related

Notify images ContentProvider about new file on external storage

How should I notify images Content Provider, that I just saved a file in Pictures directory? I expect e.g. Gallery-like apps to be able to see my new file.
Uri uri = Uri.fromFile(file);
getContext().getContentResolver().notifyChange(uri, null);
which I found somewhere (Vogella?) does not seem to work. Or is it a wrong approach from the start?
The image notification is done after the image is inserted into media database. This is usually done by the android system media scanner when it finds the image.
You can write your own code to insert the image into the media database and then call getContext().getContentResolver().notifyChange(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null); to notify that some image has changed without beeing specific exatly which image.
If you modified an image that is already in the media database you have to translate the file uri into a content: uri. getContext().getContentResolver().notifyChange(imageContentUri, null); .
If you are implementing for android-4.4 or later You can ask the media scanner to (re)analyse your file. For details see How to trigger MediaScan on Nexus 7? . in pre android-4.4 this might not work as expected (i.e. on my android-4.2 it starts a complete rescan)

open music file from raw folder to play on default app of the device using an intent on android

I'm trying to write an intent to open the default music player of the device to play a music file (mp3) I have on raw folder in my android studio project . thus far I found the code for the intent but I got stack on how to order it to open the specific mp3 file an dplay it on the media player so far I have wrote something like this trying to find te uri also of the file but I cant put them together on how should I do it the file name of the mp3 is "greeceMusic" if it helps at all. the code I have so far is
`#Override
public void onClick(View view) {
Intent musicIntent = new Intent();
//use Action VIEW to launch app
musicIntent.setAction(Intent.ACTION_VIEW);
File file = new File("android.resource://" + getPackageName() + "/" + R.raw.greeceMusic);
musicIntent.setDataAndType(Uri.fromFile(file), "audio/*");
startActivity(musicIntent);
}`
any help would be gratly appreciated as for I'm really new at this and I need all the help I can get cause when I found a similar post in the forum it don't help me a lot cause I couldn't put together the instructions thanks in advance
File file = new File("android.resource://" + getPackageName() + "/" + R.raw.greeceMusic);
First, a resource is a file on your development machine. It is not a file on the device.
Second, you cannot use a Uri syntax with a scheme, like android.resource://, with File.
Third, do not use wildcard MIME types when creating an Intent like this. You know what the actual MIME type is, as you are the one packaging the media into your app. So, use the actual MIME type.
Fourth, even if you correctly created the Uri (e.g., Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.greeceMusic)), it is unlikely that many devices will have an app capable of playing a music file published in the form of a raw resource.
Your best option is to copy the resource contents to a file (e.g., openRawResource() on Resources, then copy the bytes from the InputStream to a FileOutputStream), then try to play the file (e.g., served via a FileProvider).

different URI scheme across different android version when trying to open a file

I am trying to use my app to open a file from external storage.
I am using Share via feature.
my code Export
File filelocation = new File(sPath);
Uri path = Uri.fromFile(filelocation);
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("vnd.android.cursor.dir/email");
emailIntent.putExtra(Intent.EXTRA_STREAM, path);
String mystring = ctx.getResources().getString(R.string.Import_rule);
emailIntent.putExtra(Intent.EXTRA_TEXT, mystring);
Import function
if (Intent.ACTION_SEND.equals(in.getAction()))
{
uri = (Uri) in.getParcelableExtra(Intent.EXTRA_STREAM);
uri.getPath();
}
When i try to get the uri.getPath() i see difference in differnt devices versions.
in Android 5.0 devicve :
file:///storage/emulated/0/Download/DeviceList.zip
in Android 6.0 device
content://0#media/external/file/1147
I dont know why the URI scheme is different across versions?
How can i resolve this?
Can you tell me how can i read from content and save as file
I dont know why the URI scheme is different across versions?
content has been a valid scheme since Android 1.0. It is has been preferred for years due to better security. It will become extremely important in the future, as Android N is beginning to ban file Uri values.
Also, please note that change in schemes this has little to do with the Android OS version. It has more to do with the version of the app you are using to trigger the ACTION_SEND Intent.
How can i resolve this?
Support both of them.
Can you tell me how can i read from content and save as file
Use ContentResolver and openInputStream() to get an InputStream on the content pointed to by the Uri. Then, use Java I/O to copy that data to a local file.

Get Image path and store In SQLite Android

I am trying to get the path of the image the user selects from the gallery. So far I have made the button and used the following code to get the user to select the image from gallery:
public void image(View v) {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE);
}
Now, I'm trying to get the path of this image so that I can store it in the database to be used to retrieve it later. I know how to insert the path into the DB but just don't know how to get the path name.
Also, I want to copy the image the user has selected and paste into a new folder, where all the images will be.
Any help will be appreciated.
Thanks
So far I have made the button and used the following code to get the user to select the image from gallery
No, you are asking the user to select an image. Any number of apps can offer an activity that supports ACTION_GET_CONTENT for image/* data, not just something that you consider to be a gallery.
Now, I'm trying to get the path of this image so that I can store it in the database to be used to retrieve it later
There is no path, and there is nothing that you can store that you can necessarily use later. The Uri that you get back (via the Intent passed into onActivityResult()) will work for a short time. It is reminiscent of a URL you might get to an image in a Web site, where the URL only works while the user is authenticated. Either use the Uri right away, or plan on having the user pick the image again in the future. Or, switch to the Storage Access Framework and hope that you get a Uri that is durable and has persistable permissions (and set your minSdkVersion to 19 or higher).
I want to copy the image the user has selected and paste into a new folder, where all the images will be
It is unclear what "copy the image the user has selected and paste into a new folder" means to you. If you mean what computer users would refer to as "copy the file", use ContentResolver and openInputStream() to get an InputStream on the image. Then, use standard Java I/O to copy that to some file under your control. The path to that file you could store in your database, as you are now managing that copy of the file. However, this causes duplication of data (two copies of the image), which the user may or may not want.
You can store image in bytearray format in sqlite database.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 60, baos);
byte[] byteArray=baos.toByteArray();
and then use this byteArray to insert image in Sqlite. :)
Hope this helps to you.

Sharing the audio file located on an url with other apps in android

My android application has mp3 files sitting on the amazon s3 bucket. I have an URL to access that audio clip. I am able to play the audio clip using MediaPlayer by passing the URL to the data source of the media player.
I am creating an application which lets the user share audio clips from my app to other IM apps like whatsapp. So, I will provide a share widget on the Activity and upon cliking on that widget then whatsapp should be opened and the user should be able to select a contact to which he wants to share the audio clip.
For this I need to download the audio clip to local storage system and then share the file with other app using ContentURI. However I am unable to figure out what is the best way to do it.
As per Android documentation the below code canbe used to send binary files:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)));
I am assuming that audio files are binary files. So, I am using the below code to send the audio clip.
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, uriToImage);
intent.setType("audio/mpeg3");
startActivity(intent);
Looks like the only piece I am missing here is "uriToImage". Can anyone help me understand how to get the "uriToImage" for the resource located at a URL. ?
Updated the code as per CommonsWare's comment. Below is the updated code:
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
Uri contentUri = Uri.fromFile(new File(clipAudioUrl));
intent.putExtra(Intent.EXTRA_STREAM, contentUri);
intent.setType("audio/mpeg");
intent.setPackage("com.whatsapp");
startActivity(intent);
Upon touching the share widget Watsapp is being opened directly(Which is what I want), however the share is familing with the error "Share failed". I am assuming that it is because of the uri for which I have used the below code:
Uri contentUri = Uri.fromFile(new File(clipAudioUrl));
As per CommonsWare's comment, whatsapp also expect the URI to be either in the format "file:\" or "content:\"
Could you please help me convert the URL in the format of either "file:\" or "content:\". Thank you.
I will provide a share widget on the Activity and upon cliking on that widget then whatsapp should be opened
Only if the user chooses WhatsApp. Please do not assume that all users of your app will have WhatsApp installed or will want to use WhatsApp for everything in your app.
For this I need to download the audio clip to local storage system and then share the file with other app using ContentURI.
Technically, you could use your S3 URL with ACTION_SEND, though that implies that the URL is public.
Otherwise, download the file using whatever you want (AWS SDK, HttpUrlConnection, OkHttp, etc.) to internal storage (e.g., getCacheDir()), then use FileProvider to serve it to other apps. FileProvider can give you the Uri to use with ACTION_SEND.
The solution is pretty much based on the suggestions from CommonsWare. However In my case I did not use FileProvder to send the file. Instead I used the below code to make it work.
public void onClick(View v) {
final Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
String audioClipFileName="shoutout.mp3";
shareIntent.setType("audio/mp3");
shareIntent.putExtra(android.content.Intent.EXTRA_STREAM, Uri.parse("file://"+"/sdcard/"+audioClipFileName));
shareIntent.setPackage("com.whatsapp");
startActivity(Intent.createChooser(shareIntent, "Share Audio Clip"));
}
To my surprise I actually discovered that my question is an outright duplicate of Intent.ACTION_SEND Whatsapp.
My solution which worked for me was from the answer for the above question.

Categories

Resources