I've read the Android SDK and I've found that the MediaRecorder class can take input from a Camera, Audio or other source and compress it. Through the setOutputFile method you can specify where you want the data to be stored (File or URI), but what if I want to store that data in a memory buffer and send it over a connection? Or process it before sending it? I mean is there a way not to create a file but to use a memory buffer only?
You can of course read the file in later and do whatever you want with it in the way of processing. Assuming that u holds the Uri to the resulting audio file, here is a code snippet that reads it into a byte array and then deletes the file.
String audioUri = u.getPath();
InputStream in = new BufferedInputStream(this.getContentResolver().openInputStream(u));
byte[] b = new byte[BUFSIZE];
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(new File(mFileName/*mFilePath*/)));
int byteCnt = 0;
while (0 <= (byteCnt = in.read(b, 0, BUFSIZE)))
out.write(b, 0, byteCnt);
out.flush();
out.close();
// try to delete media file
try {
// Delete media file pointed to by Uri
new File(getRealPathFromURI(u)).delete();
} catch (Exception ex) {}
public String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
Related
Im trying to convert an audio file to byte array. where the audio file is fetch through attach file so its in an Uri
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileInputStream fis;
try {
//FileInputStream = reading the file
fis = new FileInputStream(new File(audioFxUri.getPath()));
byte[] buf = new byte[1024];
int n;
while (-1 != (n = fis.read(buf)))
baos.write(buf, 0, n);
} catch (Exception e) {
e.printStackTrace();
}
byte[] bbytes = baos.toByteArray();
i followed that code from this one but once i ran. It gave me an error
W/System.err: java.io.FileNotFoundException: /external/audio/media/646818: open failed: ENOENT (No such file or directory)
I also tried to play it with a MediaPlayer and place Uri as its Source
MediaPlayer player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(AttachAudio.this,audioFxUri.toString());
player.prepare();
player.start();
to make sure if the audio file is working or not. Ps. it worked.
Is there something wrong im doing as to why it didnt convert to byte array?
The File Uri you have /external/audio/media/646818 is not an actual File Path, hence it is giving FileNotFoundException.
You need to get absolute path from the URI and then read the file accordingly.
You can either use below code:
public String getRealPathFromURI(Uri contentUri)
{
String[] proj = { MediaStore.Audio.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
or Refer this or this SO link for other options/methods
here I want to send my image in database.. but i Can't assign imgPro to values.put.. Please help me..
else if (requestCode == 2) {
Uri selectedImage = data.getData();
String[] filePath = { MediaStore.Images.Media.DATA };
Cursor c = getContentResolver().query(selectedImage, filePath, null, null, null);
c.moveToFirst();
int columnIndex = c.getColumnIndex(filePath[0]);
String picturePath = c.getString(columnIndex);
c.close();
Bitmap thumbnail = (BitmapFactory.decodeFile(picturePath));
imgPro.setImageBitmap(thumbnail);
}
You can do like below.
public class ImageConverter {
public static String imageToStringConverter(Bitmap image){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
String imageToString = Base64.encodeToString(byteArray, Base64.NO_WRAP);
return imageToString;
}
public static Bitmap stringToimageConverter(String imageString){
byte[] stringTobyte = Base64.decode(imageString, Base64.NO_WRAP);
Bitmap bmp = BitmapFactory.decodeByteArray(stringTobyte, 0, stringTobyte.length);
return bmp;
}
}
You will call this two function to convert the image into string and then save in the database.Like below
String statusImage = ImageConverter.imageToStringConverter(selectedImage);
selectedImage is the bitmap you have selected from file. and if u want show the image then just again convert the string back to image.
Now why Base64??
When you have some binary data that you want to ship across a network,
you generally don't do it by just streaming the bits and bytes over
the wire in a raw format. Why? because some media are made for
streaming text. You never know -- some protocols may interpret your
binary data as control characters (like a modem), or your binary data
could be screwed up because the underlying protocol might think that
you've entered a special character combination (like how FTP
translates line endings).
So to get around this, people encode the binary data into characters.
Base64 is one of these types of encodings. Why 64? Because you can
generally rely on the same 64 characters being present in many
character sets, and you can be reasonably confident that your data's
going to end up on the other side of the wire uncorrupted.
I have tried many different ways or solutions and none of them seems to work. I have tried a few specific solutions which returns me a string and a context but i do not know what to do with the context even if I set the receiver of the context as null the app returns an error. What I want to do is, to be able to upload an image file for that I need the file path, a Uri or a content Uri gives me addresses like this
Content://something_something/304:
But i need something like this "
storage/sdcard/something_something/304.jpg"
how do it get that in KITKAT?
This is the code/method that I use for getting the path to the selected user Image.
public String getPath(Uri uri)
{
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
hope i provided enough details. Thank you for any help.
KITKAT does not provide the actual image path for security purpose.
if (Build.VERSION.SDK_INT >19){
InputStream imInputStream = getContentResolver().openInputStream(data.getData());
Bitmap bitmap = BitmapFactory.decodeStream(imInputStream);
String imagePath = saveGalaryImageOnKitkat(bitmap);
}
///After use you can delete the bitmap.
private String saveGalaryImageOnKitkat(Bitmap bitmap){
try{
File cacheDir;
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
cacheDir=new File(Environment.getExternalStorageDirectory(),getResources().getString(R.string.app_name));
else
cacheDir=getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if(!cacheDir.exists())
cacheDir.mkdirs();
String filename=java.lang.System.currentTimeMillis()+".png";
File file = new File(cacheDir, filename);
file.createNewFile();
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
return file.getAbsolutePath();
}catch(Exception e){
e.printStackTrace();
}
return null;
}
I've got an Image Uri, retrieved using the following:
public Uri getImageUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
This works just amazing for Intents that require an Image URI, etc (so I know for sure the URI is valid).
But now I want to save this Image URI to a file on the SDCARD. This is more difficult because the URI does not really point at a file on the SDCARD or the app.
Will I have to create a bitmap from the URI first, and then save the Bitmap on the SDCARD or is there a quicker way (preferable one that does not require the conversion to a bitmap first).
(I've had a look at this answer, but it returns file not found - https://stackoverflow.com/a/13133974/1683141)
The problem is that the Uri you've been given by Images.Media.insertImage() isn't to an image file, per se. It is to a database entry in the Gallery. So what you need to do is read the data from that Uri and write it out to a new file in the external storage using this answer https://stackoverflow.com/a/8664605/772095
This doesn't require creating a Bitmap, just duplicating the data linked to the Uri into a new file.
You can get the data using an InputStream using code like:
InputStream in = getContentResolver().openInputStream(imgUri);
Update
This is completely untested code, but you should be able to do something like this:
Uri imgUri = getImageUri(this, bitmap); // I'll assume this is a Context and bitmap is a Bitmap
final int chunkSize = 1024; // We'll read in one kB at a time
byte[] imageData = new byte[chunkSize];
try {
InputStream in = getContentResolver().openInputStream(imgUri);
OutputStream out = new FileOutputStream(file); // I'm assuming you already have the File object for where you're writing to
int bytesRead;
while ((bytesRead = in.read(imageData)) > 0) {
out.write(Arrays.copyOfRange(imageData, 0, Math.max(0, bytesRead)));
}
} catch (Exception ex) {
Log.e("Something went wrong.", ex);
} finally {
in.close();
out.close();
}
In my app the user can select a picture from their gallery as avatar, but i want to save it into my app storage so they can delete the file.
My code is:
//onActivityResult()
else if (requestCode == SELECT_PICTURE)
{
mFile = new File(getRealPathFromURI(data.getData()));
Date d = new Date();
long ms = d.getTime();
mName = String.valueOf(ms) + ".jpg";
copyfile(mFile,mName);
File file = new File(Environment.getExternalStorageDirectory(), mName);
Bitmap myBitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
imgPhoto.setImageBitmap(myBitmap);
}
public String getRealPathFromURI(Uri contentUri)
{
// can post image
String [] proj={MediaStore.Images.Media.DATA};
Cursor cursor = managedQuery( contentUri,proj,null,null,null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
private void copyfile(File file,String newFileName){
try{
InputStream in = new FileInputStream(file);
OutputStream out = openFileOutput(newFileName, MODE_PRIVATE);
byte[] buf = new byte[4096];
int len;
while ((len = in.read(buf)) > 0){
out.write(buf, 0, len);
}
in.close();
out.close();
Log.d(null,"success");
}
catch(FileNotFoundException ex){
ex.printStackTrace();
}
catch(IOException e){
e.printStackTrace();
}
}
If i decode mFile in the Bitmap, the image is shown, so mFile has the image. ¿Any ideas?
Well, first of all... you haven't told us the behavior you are currently getting. Does your app crash? Does the picture not get displayed? Some other unexpected behavior?
Other than that:
Don't use managedQuery()... it's run on the main UI thread so it can easily introduce lag into your application. Ideally you'd want to use a CursorLoader but it might be easier to just wrap all of your work in an AsyncTask (by "all of your work" I mean all of the work related to saving/retrieving/decoding the image file... and I suggest this because it can take a considerable amount of time to do all of this stuff, and your app might look slow if the UI thread is blocked for too long).
If you do choose to wrap your work in an AsyncTask (which I suggest you do), put all of the work in doInBackground() and update your UI accordingly when you are finished in onPostExecute().