I have tried about 10 answers to a similar question, but none of them were successful. Something might be out of date. Please give an answer for today.
Simple task:
I want my app to be able to send a file with an image to e-mail or whatsapp.
I put the file with the image in the application resources in the folder Drawable.
Its size is 5 MB.
How to do this in Java?
I'm asking for code, not links to similar answers. I've tried most of them already.
Some decisions came to null.bin.
Some don't send anything at all and throw an error.
Perhaps I am not specifying any permissions.
Something else is possible.
I'm new.
I would like an answer with comments (what I am writing and why)
// step 1. I put the picture in the folder Drawable
// clicking on the button sends the picture through the messenger to other users
public void onClick_sendMyImage(View v) {
// Step 2.Convert PICTURE to Bitmap
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image1);
saveImage(bitmap); // 3. save the PICTURE in the internal folder
send(); // 4.sending PICTURE (function code below)
}
// step 3. Saving the image in the internal folder:
private static void saveImage(Bitmap finalBitmap){
String root = Environment.getExternalStorageDirectory().getAbsolutePath();
File myDir = new File(root + "/saved_images");
//Log.i("Directory", "==" + myDir);
myDir.mkdirs();
String fname = "image_test" + ".jpg";
File file = new File(myDir, fname);
if(file.exists()) file.delete();
try{
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// Step 4. Sending the saved PICTURE
public void send(){
try{
File myFile = new File("/storage/emulated/0/saved_images/image_test.jpg");
// for something I create this type (so it is said in one of the answers)
MimeTypeMap mime = MimeTypeMap.getSingleton();
String ext = myFile.getName().substring(myFile.getName().lastIndexOf(".") + 1);
String type = mime.getMimeTypeFromExtension(ext);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType(type);
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(myFile));
Intent intent1 = Intent.createChooser(intent, "what do you want to send ?");
startActivity(intent1);
}catch (Exception e){
Toast.makeText(this, "repeat sending", Toast.LENGTH_SHORT).show();
}
}
Sending an image from an app turned out to be not a good idea.
The image cannot be edited if necessary.
Over time, you may want to add more images, etc..
I did it differently, and it turned out better:
I put the image on GoogleDisk.(now I can change it at any time without having
to ask users to reinstall the application every time the picture changes).
I placed a link to the picture in the FireBase Database. (I also placed a banner with a picture here.).
I connected the application to the Firebase Database.
In the activity I made a RecyclingView, where I get a banner(s) and a link(s) to the original image(s). The user can download this link or send it through whatsapp anywhere and download the original picture in good quality (A1, 2.5Mb).
thanks, guys..
I thank the guys for the tips, especially mr.Blackapps. In this case, you really can't do without a FileProvider.
I wanted to do an app for sharing pictures from the gallery for learning and i want the picture to be renamed so i use a bitmap that retrieve the data of the picture. But the thing is the file is always returning null.
I have a code and i don't know where is the problem.
File file = new File(this.getFilesDir().getAbsolutePath(), "logo");
if (!file.exists()) {
file.mkdirs();
}
File iconf = new File(file, "icon_launcher.png");
iconf.createNewFile();
OutputStream ios = new FileOutputStream(iconf);
example.compress(Bitmap.CompressFormat.PNG, 80, ios);
ios.flush();
ios.close();
//String uricon= MediaStore.Images.Media.insertImage(getContentResolver(),iconf.getAbsolutePath(),"icon_launcher.png","drawing");
Uri iconurl = Uri.parse(iconf.getAbsolutePath());
Intent email = new Intent(Intent.ACTION_SEND);
email.setType("image/png");
email.putExtra(Intent.EXTRA_STREAM, iconurl);
startActivityForResult(Intent.createChooser(email, "Envoyer par mail"), 1);
Thank you in advance for the help :)
I have succeeded to make the code work, i forget to use a FileProvider because i didn't have an External Storage.So you have to use a FileProvider to use Internal Storage.
I am working on a simple app that plays audio files and I would like to be able to open the app from an audio file in, for example, a file browser. The intent filter and all that is set, but I am struggling with how to use what I receive.
the content:// uri I receive doesn't seem to be meant to be used to get to the actual file - I have looked at the answers to the question here: Android: Getting a file URI from a content URI?, but the approach described there to get a file and not just use the inputStream (which is basically what I want) doesn't seem to be the right way, judging from the discouaging comments and also this site: How to Consume Content from a Uri. Or am I mistaken?
Right now, I am calling this method in my MainActivity to handle my intent, which basically just creates a temporary copy of the file and passes it to where it's used:
private fun handleIntent() {
val uri = intent.data
val inputStream = contentResolver.openInputStream(uri)
val outputFile = File(this.cacheDir, "output.wav")
val outputStream = FileOutputStream(outputFile)
inputStream.use { input ->
outputStream.use { output ->
input.copyTo(output)
}
}
DataRepository.handleFileFromIntent(outputFile)
showPlayerFragmentWithFreshSelection()
}
This almost works (as in I get what is passed to the app as a File), but in a wrong way. Since I want to add the file to a selection of audio files my player can go through, and would like to be able to save this selection, saving a temporary file, or even a copy at all is not the right approach here (I just named the file "output.wav" here because I knew for my test I would be using a .wav file)
Is there any proper and safe way to get the actual path to the file from my content uri or is this just something that can't (or shouldn't) be done at all?
I am writing this in Kotlin, but answers using Java are very wellcome too!
We are using same thing in a production level app, and it is working fine.
filePath = FileUtils.getPathFromURI(mUri);
public static String getPathFromURI(Uri contentUri) {
Cursor cursor = null;
try {
final String[] proj = {MediaStore.Images.Media.DATA};
cursor = getAppContext().getContentResolver().query(contentUri, proj, null, null, null);
if (cursor == null || cursor.getCount() == 0)
return "";
final int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} catch (IllegalArgumentException|SecurityException e) {
return "";
} finally {
if (cursor != null && !cursor.isClosed()) cursor.close();
}
}
I am able to play a local mp3 if I use the static method MediaPlayer.create(context, id) but it's not working if I use the non-static method MediaPlayer.setDataSource(String). What's happening is that I am getting a synchronous exception when I call MediaPlayer.prepare():
prepare exceptionjava.io.IOException: Prepare failed.: status=0x1
Here is my code (omitted logging):
String filename = "android.resource://" + this.getPackageName() + "/raw/test0";
mp = new MediaPlayer();
try { mp.setDataSource(filename); } catch (Exception e) {}
try { mp.prepare(); } catch (Exception e) {}
mp.start();
Note that I am not getting an errors about file not found or anything. The full name of the file is test0.mp3 and I place it in the /res/raw/ directory in Eclipse.
I assume that I am setting the path incorrectly but all the examples I find online use the FileDescriptor version of setDataPath instead of the String version of setDataPath.
EDIT: I am also able to play a local mp3 if I use the method MediaPlayer.setDataSource(FileDescriptor) and place the files in the /assets/ directory in Eclipse.
EDIT #2: I accepted the answer that this is not possible, but then realized that the library I am using (openFrameworks) actually does use the String method to load a file. See here:
https://github.com/openframeworks/openFrameworks/blob/master/addons/ofxAndroid/ofAndroidLib/src/cc/openframeworks/OFAndroidSoundPlayer.java
Alternative Solution #1: Using Resources.getIdentifier()
Why not use getResources().getIdentifier() to get id of the resource and use the static MediaPlayer.create() as usual?
public int getIdentifier (String name, String defType, String defPackage)
getIdentifier() takes your resource name (test0), resource type(raw), your package name and returns the actual resource id.
MediaPlayer mp;
//String filename = "android.resource://" + this.getPackageName() + "/raw/test0";
mp=MediaPlayer.create(getApplicationContext(), getResources().getIdentifier("test0","raw",getPackageName()));
mp.start();
I've tested this code and it works.
Update #1:
Alternative Solution #2: Using Uri.parse()
I've tested this code as well and it works too. Pass your resource path as URI to setDataSource(). I just made that change to your code to get it work.
String filename = "android.resource://" + this.getPackageName() + "/raw/test0";
mp = new MediaPlayer();
try { mp.setDataSource(this,Uri.parse(filename)); } catch (Exception e) {}
try { mp.prepare(); } catch (Exception e) {}
mp.start();
Update #2: Answer is NO
About setDataSource(String) call
After seeing your comment, it looks like you exactly want setDataSource(string) to be used for your purpose. I don't understand why. But, what I assume is, for some reason you are trying to avoid using "context". If that is not the case then the above two solutions should work perfectly for you or if you are trying to avoid context, I'm afraid that is not possible with the function with signature setDataSource(String) call. The reason is as below,
MediaPlayer setDataSource() function has these below options out of which you are only interested in setDataSource(String),
setDataSource(String) internally calls setDataSource(String path, String[] keys, String[] values) function. If you can check its source,
public void setDataSource(String path)
throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
setDataSource(path, null, null);
}
and if you check setDataSource(String path, String[] keys, String[] values) code, you will see the below condition filtering the path based on its scheme, particularly if it is "file" scheme it calls setDataSource(FileDescriptor) or if scheme is non "file", it calls native JNI media function.
{
final Uri uri = Uri.parse(path);
final String scheme = uri.getScheme();
if ("file".equals(scheme)) {
path = uri.getPath();
} else if (scheme != null) {
// handle non-file sources
nativeSetDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(path),
path,
keys,
values);
return;
}
final File file = new File(path);
if (file.exists()) {
FileInputStream is = new FileInputStream(file);
FileDescriptor fd = is.getFD();
setDataSource(fd);
is.close();
} else {
throw new IOException("setDataSource failed.");
}
}
In the above code, your resource file URI scheme will not be null (android.resource://) and setDataSource(String) will try to use native JNI function nativeSetDataSource() thinking that your path is http/https/rtsp and obviously that call will fail as well without throwing any exception. Thats why your call to setDataSource(String) escapes without an exception and gets to prepare() call with the following exception.
Prepare failed.: status=0x1
So setDataSource(String) override cannot handle your resource file. You need to choose another override for that.
On the other side, check setDataSource(Context context, Uri uri, Map headers) which is used by setDataSource(Context context, Uri uri), it uses AssetFileDescriptor, ContentResolver from your context and openAssetFileDescriptor to open the URI which gets success as openAssetFileDescriptor() can open your resource file and finally the resultant fd is used to call setDataSource(FileDescriptor) override.
AssetFileDescriptor fd = null;
try {
ContentResolver resolver = context.getContentResolver();
fd = resolver.openAssetFileDescriptor(uri, "r");
// :
// :
// :
if (fd.getDeclaredLength() < 0) {
setDataSource(fd.getFileDescriptor());
} else {
setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
}
To conclude, you cannot use setDataSource(String) override as is to use your resource mp3 file. Instead, if you want use string to play your resource file you can use either MediaPlayer.create() static function with getIdentifier() as given above or setDataSource(context,uri) as given in Update#1.
Refer to the complete source code for more understanding here: Android MediaPlayer
Update #3:
openFrameworks setDataSource(String):
As I have mentioned in the comments below, openFrameworks uses android MediaPlayer code asis. If you can refer to Line no: 4,
import android.media.MediaPlayer;
and Line no: 26, 27, 28 and 218
player = new MediaPlayer(); //26
player.setDataSource(fileName); //27
player.prepare(); //28
private MediaPlayer player; //218
So, if you try to pass ardroid.resource//+ this.getPackageName() + "raw/test0" to setDataSource() using openFrameworks, you will still get the same exception as I explained in Update#2. Having said that, I just tried my luck searching Google to double sure what I am saying and found this openFrameworks forum link where one of the openFrameworks core developer arturo says,
don't know exactly how the mediaPlayer works but everything in res/raw
or bin/data gets copied to /sdcard/cc.openframeworks.packagename
Based on that comment, you may try using the copied path in setDataSource(). Using resource file on setDataSource(String) of MediaPlayer is not possible as it cannot accept resource file path. Please note that, I said "resource file path" starts with the scheme android.resource// which is actually a jar location (within your apk), not a physical location. Local file will work with setDataSource(String) which starts with the scheme file://.
To make you clearly understand what you are trying to do with a resource file, try executing this below code and see the result in logcat,
try{
Log.d("RESURI", this.getClass().getClassLoader().getResource("res/raw/test0").toURI().toString());
}
catch(Exception e) {
}
You'll get the result as,
jar:file:/data/app/<packagename>/<apkname>.apk!/res/raw/test0
that is to show you that the resource file you are trying to access is not actually a file in physical path but a jar location (within apk) which you cannot access using setDataSource(String) method. (Try using 7zip to extract your apk file and you will see the res/raw/test0 in it).
Hope that helps.
PS: I know its bit lengthy answer, but I hope this explains it in detail. Leaving the alternative solutions in the top if that can help others.
Like the android documentation said
Arbitrary files to save in their raw form. To open these resources
with a raw InputStream, call Resources.openRawResource() with the
resource ID, which is R.raw.filename.
However, if you need access to original file names and file hierarchy,
you might consider saving some resources in the assets/ directory
(instead of res/raw/). Files in assets/ are not given a resource ID,
so you can read them only using AssetManager.
So you need to use a InputStream to read the audio file before set it to the media player.
I suggest you to put the audio file in the assets folder like you said you played
:)
Below code working for me i think this code will help you
player = MediaPlayer.create(this,R.raw.test0);
player.setLooping(true); // Set looping
player.setVolume(100,100);
player.start();
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
player.stop();
player.release();
}
When dealing with a raw resource, you should rely on the following constructor:
public static MediaPlayer create (Context context, int resid)
Convenience method to create a MediaPlayer for a given resource id. On success, prepare() will already have been called and must not be called again.
The code looks like
mediaPlayer = MediaPlayer.create(this, R.raw.test0);
mediaPlayer.start();
Don't forget to call mediaPlayer.release() when you're done with it.
(source)
From here,
When path refers to a local file, the file may actually be opened by a process other than the calling application. This implies that the pathname should be an absolute path (as any other process runs with unspecified current working directory), and that the pathname should reference a world-readable file. As an alternative, the application could first open the file for reading, and then use the file descriptor form setDataSource(FileDescriptor).
Try,
String filePath = "path/file.mp3";
File file = new File(filePath);
FileInputStream inputStream = new FileInputStream(file);
mediaPlayer.setDataSource(inputStream.getFD());
inputStream.close();
Hope it Helps!
You have to use setDataSource(#NonNull Context context, #NonNull Uri uri) instead of setDataSource(String path)
Since you want to resolve resource internal application resources, you have to provide Context which would be used to resolve this stuff
Also if you will take a look inside these two methods you will notice they use different strategies to find resulting resource.
Try this:
if(mediaPlayer != null ){
if (mediaPlayer.isPlaying()){mediaPlayer.stop();}
mediaPlayer.reset(); //this line is important!
String path = File.separator + "sdcard" + File.separator + utilsFields.repoDirRoot + File.separator + media.mp4;
try {
mediaPlayer.setDataSource(path);
}catch (Exception ignored){}
try {
mediaPlayer.prepare();
}catch (Exception ignored){}
mediaPlayer.start();
}
BACKGROUND
Hey so I have a camera that I have implemented myself in code. This means I access and control the camera hardware and use it to save pictures. I can save the picture using the Camera.takePicture() function when the camera is running: running means Camera.startPreview();
PROBLEM
My problem is that I want to be able to save the image also when the camera image is frozen: frozen is when Camera.stopPreview(); is called.When frozen I can see the image in my layout but how do I access it? Where is the image saved so that I might be able to modify it later?
Thanks in advance!
------------------Update 1
jpeg bla;
public class jpeg implements PictureCallback{
public void onPictureTaken(byte[] data, Camera camera) {
g_data = data;
}
}
This is part of my code. Here I am trying to write the data that would originally be saved to a global variable. However the value of g_data remains null and I am unable to set a breakpoint inside the onPictureTaken() call back function.
------------------Update 2
FileOutputStream outStream = null;
try {
// generate the folder
File imagesFolder = new File(Environment.getExternalStorageDirectory(), "MirrorMirror");
if( !imagesFolder.exists() ) {
imagesFolder.mkdirs();
}
// generate new image name
SimpleDateFormat formatter = new SimpleDateFormat("HH_mm_ss");
Date now = new Date();
String fileName = "image_" + formatter.format(now) + ".jpg";
// create outstream and write data
File image = new File(imagesFolder, fileName);
outStream = new FileOutputStream(image);
outStream.write(data);
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
} catch (FileNotFoundException e) { // <10>
//Toast.makeText(ctx, "Exception #2", Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {}
I used this code previously to save the file from the camera onPictureTaken() function. The key here is the byte[] data which I need to save and save later. However like I said I just get a null when I check it in the debugger.
Camera.takePicture never looks at the view you specified as previewDisplay. Actually, it isn't an ImageView, but a SurfaceView, and there are no API to read pixels from it.
You can call takePicture() preemptively just before you stopPreview(). Later, if you find out that you don't need the picture, just discard it.
Ok so the exact way to do this is to take the picture just before stopPreview() and save it to a temporary file. Actually with this implementation you never call stopPreview()(otherwise it will crash) since the takePicture() function stops the preview automatically.
try {
File temp = File.createTempFile("temp", ".jpg");
} catch (IOException e) {
e.printStackTrace();
}
Now that we have the temporary file saved we will access it later and move it to our new desired file location.
How to copy file.
temp.deleteOnExit();
be sure to call deleteonExit() so that Android deletes the file after the app is closed(if so desired).