I'm building an app that require method to take picture from in-app camera, but for some Android devices (old device or low ram), it's quite freeze when taking picture triggered. Is there any code i can modify or optimize to make user experience feels better?
//this function trigger to take picture (or screenshot) from user screen
private void captureImage() {
mPreview.setDrawingCacheEnabled(true);
final Bitmap[] drawingCache = {Bitmap.createBitmap(mPreview.getDrawingCache())};
mPreview.setDrawingCacheEnabled(false);
mCameraSource.takePicture(null, bytes -> {
int orientation = Exif.getOrientation(bytes);
Bitmap temp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Bitmap picture = rotateImage(temp, orientation);
assert picture != null;
Bitmap overlay = Bitmap.createBitmap(mGraphicOverlay.getWidth(), mGraphicOverlay.getHeight(), picture.getConfig());
Canvas canvas = new Canvas(overlay);
Matrix matrix = new Matrix();
matrix.setScale((float) overlay.getWidth() / (float) picture.getWidth(), (float) overlay.getHeight() / (float) picture.getHeight());
// mirror by inverting scale and translating
matrix.preScale(-1, 1);
matrix.postTranslate(canvas.getWidth(), 0);
Paint paint = new Paint();
canvas.drawBitmap(picture, matrix, paint);
canvas.drawBitmap(drawingCache[0], 0, 0, paint);
//this function to save picture taken and put it on app storage cache
try {
String mainpath = getApplicationContext().getFilesDir().getPath() + separator + "e-Presensi" + separator;
File basePath = new File(mainpath);
if (!basePath.exists())
Log.d("CAPTURE_BASE_PATH", basePath.mkdirs() ? "Success" : "Failed");
//this function to get directory path of saved photo
String path = mainpath + "photo_" + getPhotoTime() + ".jpg";
String namafotoo = "photo_" + getPhotoTime() + ".jpg";
filePath = path;
namafoto = namafotoo;
SessionManager.createNamaFoto(namafoto);
File captureFile = new File(path);
boolean sucess = captureFile.createNewFile();
if (!captureFile.exists())
Log.d("CAPTURE_FILE_PATH", sucess ? "Success" : "Failed");
FileOutputStream stream = new FileOutputStream(captureFile);
overlay.compress(Bitmap.CompressFormat.WEBP, 60, stream);
stream.flush();
stream.close();
if (!picture.isRecycled()) {
picture.recycle();
}
if (drawingCache[0] != null && !drawingCache[0].isRecycled()) {
drawingCache[0].recycle();
drawingCache[0] = null;
}
mPreview.setDrawingCacheEnabled(false);
uploadPicture();
finish();
} catch (IOException e) {
e.printStackTrace();
}
});
}
Thanks for your help.
In general, I would advise you to step through your code and look at large memory resources you're generating on each line and consider setting those to null aggressively as you move throughout the method if you're done.
For example, you have a variable called temp which is size "Y" bytes that you appear to rotate and then never use temp after that. If picture is a rotated copy of temp then you have now used 2Y bytes of memory to keep temp and picture. I suspect if you simply set temp to null after creating picture, you might free up half that memory that your older/slower phones are going to badly need.
Take that same concept and follow through with the rest of your method to see if you can find other optimizations. Basically anywhere you're creating a copy of the image data you're not going to use, you should immediately set it to null so the garbage collector can throw it away aggressively.
Firt you need some variables:
byte[] byteArray_IMG;
String currentPhotoPath;
static final int REQUEST_TAKE_PHOTO = 1;
ImageView imageView; // maybe you need show the photo before send it
Then define the method to take the photo:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Toast.makeText(getApplicationContext(),Error takin the photo",Toast.LENGTH_LONG).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
path_img = photoFile.toString();
Uri photoURI = FileProvider.getUriForFile(this,"com.app.yournmamepackage.fileprovider" , photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
Create the method to create the file image
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
Override the activity result to:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode,resultCode,data);
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
/* Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
imageView.setImageBitmap(imageBitmap);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byteArray_IMG = stream.toByteArray();*/
MediaScannerConnection.scanFile(this, new String[]{path_img}, null,
new MediaScannerConnection.OnScanCompletedListener() {
#Override
public void onScanCompleted(String path, Uri uri) {
Log.i("path",""+path);
}
});
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap imageBitmap = BitmapFactory.decodeFile(path_img);
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 14, stream);
imageView.setImageBitmap(imageBitmap);
byteArray_IMG = stream.toByteArray();
}
}
Remember this is very important
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 25, stream)
// 25 is photo quality 0-100
Then you can upload the picture usin an asynchronous process
Firstly Initialize these variables above onCreate() method in your activity/fragment
val FILE_NAME:String="photo.jpg" //give any name with.jpg extension
private var imageuri: Uri?=null
val REQUEST_IMAGE=111
Now open camera
val intent: Intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
photofile = getphotofile(FILE_NAME)
imageuri = activity?.let { it1 -> FileProvider.getUriForFile(it1, "//your package name here//.fileprovider", photofile) } //put your package name
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageuri)
startActivityForResult(int, REQUEST_IMAGE)
onActivityResult() method
if(requestCode==REQUEST_IMAGE && resultCode == Activity.RESULT_OK){
val progressdialog: ProgressDialog = ProgressDialog(activity)
progressdialog.setTitle("Sending Image....")
progressdialog.show() //start your progressdialog
val ref= FirebaseDatabase.getInstance().reference
val messagekey=ref.push().key //create a key to store image in firebase
var bmp: Bitmap?=null
try {
bmp=MediaStore.Images.Media.getBitmap(activity?.contentResolver,imageuri) //get image in bitmap
} catch (e: IOException) {
e.printStackTrace();
}
val baos= ByteArrayOutputStream()
bmp!!.compress(Bitmap.CompressFormat.JPEG,50,baos) //compress the quality of image to 50 from 100
val fileinBytes: ByteArray =baos.toByteArray()
val store: StorageReference = FirebaseStorage.getInstance().reference.child("Chat Images/") //create a child reference in firebase
val path=store.child("$messagekey.jpg") //store a message in above reference with the unique key created above with .jpg extension
val uploadTask: StorageTask<*>
uploadTask=path.putBytes(fileinBytes) //it will upload the image to firebase at given path
uploadTask.continueWithTask(Continuation<UploadTask.TaskSnapshot, Task<Uri>> { task ->
if (!task.isSuccessful) {
task.exception?.let {
throw it
}
Toast.makeText(activity, "Upload Failed", Toast.LENGTH_SHORT).show()
}
return#Continuation path.downloadUrl
}).addOnCompleteListener { task->
if(task.isSuccessful){
url=task.result.toString() //get the url of uploaded image
//Do what you want with the url of your image
progressdialog.dismiss()
Toast.makeText(activity, "Image Uploaded", Toast.LENGTH_SHORT).show()
}
}.addOnFailureListener { e->
progressdialog.dismiss()
Toast.makeText(activity, "Failed " + e.message, Toast.LENGTH_SHORT)
.show();
}
uploadTask.addOnProgressListener { task->
var progress:Double=(100.0*task.bytesTransferred)/task.totalByteCount
progressdialog.setMessage("Sending ${progress.toInt()}%") //this will show the progress in progress bar 0-100%
}
}
I want to store data into the database and want to upload an image in optional.
It means that if i am inserting the record without adding image then it will store in database without the image name.
right now when i am fill the data and insert an image then it is storing in the database if i don't select any image and i add only data then in database the data is not inserted and showing me blank value in every field
I tried a lot but not getting the required output.
My code main.java
buy_image1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
selectImage();
edit.putInt("ImageID", 1);
edit.commit();
}
});
public void selectImage()
{
i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, RESULT_LOAD_IMAGE);
/*i.putExtra("crop", "true");
i.putExtra("outputX", 512);
i.putExtra("outputY", 512);
i.putExtra("aspectX", 1);
i.putExtra("aspectY", 1);
i.putExtra("scale", true);
*/
}
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == getActivity().RESULT_OK && null != data) {
final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
Uri selectedImage = data.getData();
int imgid = 0;
String[] filePathColumn = {MediaStore.MediaColumns.DATA};
Cursor cursor = getActivity().getContentResolver().query(selectedImage, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
picturePath = cursor.getString(columnIndex);
cursor.close();
Log.d("Value", picturePath);
fileName = new File(picturePath).getName();
// imgname.setText(fileName);
String fileNameSegments[] = picturePath.split("/");
fileName = fileNameSegments[fileNameSegments.length - 1];
// MyParams.put("filename", fileName);
Bitmap yourSelectedImage = BitmapFactory.decodeFile(picturePath);
sp = getActivity().getSharedPreferences("Image ID", Context.MODE_PRIVATE);
imgid = sp.getInt("ImageID", 0);
Log.d("IMGID", Integer.toString(imgid));
BitmapFactory.Options options =null;
options = new BitmapFactory.Options();
options.inSampleSize = 5;
bitmap = BitmapFactory.decodeFile(picturePath, options);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, stream);
byte[] byte_arr = stream.toByteArray();
// Encode Image to String
encodedString = Base64.encodeToString(byte_arr, 0);
if(imgid == 1) {
buy_image1.setImageBitmap(yourSelectedImage);
img1 = fileName;
encodedStringIMG1 = encodedString;
}else if(imgid == 2){
buy_image2.setImageBitmap(yourSelectedImage);
img2 = fileName;
encodedStringIMG2 = encodedString;
}
else{
Log.d("IMGID","IMAGE ID IS 0");
}
}
private void InsertWodinformation() {
service(strwodname,strbranch,strcontactperson,strcontact,strwhatsapp,stremail,
strspinnercity,straddress,opendate1,birthdate,ani,strpancard,strtinnumber,strbankname,strbankholdername,strbankac,
strbankcity, strifsccode,strsecuritycheque,strrefrence1,strrefrence2,strremarks,img1,encodedStringIMG1,img2,encodedStringIMG2);
}
private void service(
String strwodname,String strbranch,
String strcontactperson, String strcontact,
String strwhatsapp, String stremail, String strspinnercity,
String straddress, String opendate1, String birthdate, String ani,
String strpancard, String strtinnumber, String strbankname, String strbankholdername
,String strbankac,String strbankcity, String strifsccode,String strsecuritycheque,String strrefrence1,
String strrefrence2,String strremarks,String i1,String encode1,String i2,String encode2
) {
class AddVisitclass extends AsyncTask<String, Void, String> {
ProgressDialog loading;
RegisterUserClass ruc = new RegisterUserClass();
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
HashMap<String, String> param = new HashMap<String, String>();
/*param.put("firm", params[1]);
param.put("oname", params[2]);
param.put("pname1", params[3]);
param.put("pname2", params[4]);
*/
param.put("wname", params[0]);
param.put("branch", params[1]);
param.put("cname", params[2]);
param.put("contact", params[3]);
param.put("whatsapp", params[4]);
param.put("email", params[5]);
param.put("city", params[6]);
param.put("address", params[7]);
param.put("odate", params[8]);
param.put("bdate", params[9]);
param.put("adate", params[10]);
param.put("pancard", params[11]);
param.put("tinno", params[12]);
param.put("bnm", params[13]);
param.put("bank_ac_holder", params[14]);
param.put("bank_ac_no", params[15]);
param.put("bcity", params[16]);
param.put("ifsc_code", params[17]);
param.put("cheque", params[18]);
param.put("ref1", params[19]);
param.put("ref2", params[20]);
param.put("remarks", params[21]);
param.put("pan", params[22]);
param.put("epan", params[23]);
param.put("aadhar", params[24]);
param.put("eaadhar", params[25]);
/*
param.put("light", params[26]);
param.put("elight", params[27]);
param.put("vat", params[28]);
param.put("evat", params[29]);
param.put("vcard", params[30]);
param.put("evcard", params[31]);
param.put("shop", params[32]);
param.put("eshop", params[33]);
*/
param.put("username",uid);
String result = ruc.sendPostRequest(url_addwod, param);
Log.d("Result", result);
Log.d("Data", param.toString());
return result;
}
//#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//loading.dismiss();
Toast.makeText(getActivity(), "W.O.D. added successfully...!!!", Toast.LENGTH_LONG).show();
/* FragmentTransaction t = getActivity().getSupportFragmentManager().beginTransaction();
TabFragment mFrag = new TabFragment();
t.replace(com.Weal.sachin.omcom.R.id.framelayout, mFrag);
t.commit();
*/
}
}
AddVisitclass regi = new AddVisitclass();
regi.execute(strwodname,strbranch,strcontactperson,strcontact,strwhatsapp,stremail,
strspinnercity,straddress,opendate1,birthdate,ani,strpancard,strtinnumber,strbankname,strbankholdername,strbankac,
strbankcity, strifsccode,strsecuritycheque,strrefrence1,strrefrence2,strremarks,i1,encode1,i2,encode2);
}
And one more thing when image is uploading to the server it is generating the lower size but i want it in default size.
The best way to store images/files data is to save the images to the device storage resource (e.g internal memory or external),then you have the image URL/URI saved in your database (instead of having blob field in the database), and to display it all you have to do is to retrieve the file URL and display it on the device.
I hope this gives you a better solution for this issue.
The best way to save images are save them in your computer or device you are using and pass the path (location) of the image through a sql query to the database and when you want to access the image get the location of the image from the database and display.
following link will help you to understand
http://www.androidhive.info/2011/11/android-sqlite-database-tutorial/
Consider first compressing your images, to reduce the size of the image for storage. You have three options here, first you can get the base64 representation of the image, which is a string then store it , or get the byte array output and still store it. And lastly store the uri reference for the image located on the phone. Though i would not recommend this approach, because it is subjected to path changes and user deletion.
Here is a great library that uses google webp.WebP is a modern image format that provides superior lossless and lossy compression for images.WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller than comparable JPEG images at equivalent SSIM quality index. Link to library.
Here is a galore of code snippets that can perform your request!
private static String CompressJPEG(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteFormat = stream.toByteArray();
return Base64.encodeToString(byteFormat, Base64.DEFAULT);
}
private static byte[] CompressJPEGByteArray(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
private static String CompressPNG(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteFormat = stream.toByteArray();
return Base64.encodeToString(byteFormat, Base64.DEFAULT);
}
private static byte[] CompressPNGByteArray(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
return stream.toByteArray();
}
private static Bitmap RevertImageBase64(String encodedImage) {
byte[] decodedString = Base64.decode(encodedImage, Base64.DEFAULT);
return BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
}
public static Bitmap RevertFromByteArray(byte[] arr) {
return BitmapFactory.decodeByteArray(arr, 0, arr.length);
}
Here is also code to get the extension from a uri.
public static void GetExtensionFromContentURI(Context context, Uri uri) {
ContentResolver cR = context.getContentResolver();
MimeTypeMap mime = MimeTypeMap.getSingleton();
String ext = mime.getExtensionFromMimeType(cR.getType(uri));
}
Hope this helps :)
You have to covert bitmap to BLOB format to save it ti db llook below
code :
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
String encodedData = Base64.encodeToString(byteArray, Base64.DEFAULT);
dba.insertPhoto(byteArray);
Regarding the size issue you mentioned, in onActivityResult(), the statement:
options.inSampleSize = 5;
could be the reason for the file to be smaller than the original image.
This is needed for the ImageView. Before compressing, keep a non compressed coopy for transmission to the server.
To troubbleshoot the insert of the image you need to post:
If the column in the database is defined as "not null"
A Log.d() of the value it is sending to the server when no picture is selected.
The code on the server that receives the data and performs runs the insert.
Refactoring code like below might help you. Don't take method names, variable names and other parts as a real example. I wanted to give you a bird-eye view of sample design.
//controller of user request.
handleRequest(){
String imagePath=null;
if(imageExists){ //if user sent image to server.
imagePath=saveImageAndReturnImagePath(...);
}
saveRecordToDB(request.getText(), imagePath);
}
//save image to disk and return image path.
private String saveImageAndReturnImagePath(...){
//do image manipulation here, save image to disk, return path.
return imagePath;
}
//insert a new record to db.
private void saveRecordToDB(String text, imagePath){
Record a=new Record(text, imagePath);
dao.save(a);
}
The simplest way to cache images . is to use JakeWharton/picasso2-okhttp3-downloader
Here's an example :
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.networkInterceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder().header("Cache-Control", "max-age=" + (60 * 60 * 24 * 365)).build();
}
});
try{
okHttpClient.setCache(new Cache(this.getCacheDir(), Integer.MAX_VALUE));
OkHttpDownloader okHttpDownloader = new OkHttpDownloader(okHttpClient);
Picasso picasso = new Picasso.Builder(this).downloader(okHttpDownloader).build();
picasso.load("pucul").error(R.drawable.teacher).into(imgvw);
}
catch (Exception e){
add this to your gradle file
compile 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
Source :
I have a small issue with bitmaps which I want to load into a view with a picture in every entry. The application looks like this:
Application layout
I actually have two problems - the first is that when i compress the file in code by 90%, the result file gives me even higher file size, f.e. file before compressing was 500kb, after its 6MB.
The second problem is that the images are saved to internal storage of the application (/com.example.my.application/files/) but are not shown in the list itself. What you see on the picture is working when i use the pictures directly from gallery using URI of the files, although because of their size, the RAM usage gets too high and after adding 5-6 of them the application crashes.
Here is the code for getting selected picture, compressing and saving:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
File mypath=new File(new File(this.getApplicationContext().getFilesDir(),"")+"/"+data.getData().getLastPathSegment()+".jpg");
try {
FileOutputStream fos = new FileOutputStream(mypath);
Uri imageUri = data.getData();
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),imageUri);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
imageURI = data.getData().getLastPathSegment();
TextView tv = (TextView) findViewById(R.id.note_image_uri) ;
tv.setText(imageURI);
}
}
This is the adapter of a gridview:
#Override
public void onBindViewHolder(SolventViewHolders holder, int position) {
...
Uri uri = Uri.parse(context.getFilesDir()+"/files/"+itemList.get(position).getUrl());
//Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(image));
holder.countryPhoto.setImageURI(uri);
}
So basically the idea is that after an image from gallery is selected, i want to compress it, save it into /data/com.example....../ under the name specified by .getLastPathSegment(), and then load the picture using the same path with the last path segment which is unique for every object in the view. I guess Im missing something small, but Im not that good at it, so I need your help. Thanks for any help in advance!
When I pick an image from gallery, I can get the Uri for that image as given below:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent result) {
if (requestCode == Crop.REQUEST_PICK && resultCode == RESULT_OK) {
Uri uri = result.getData();
beginCrop(uri);
} else if (requestCode == Crop.REQUEST_CROP) {
handleCrop(resultCode, result);
}
}
The format of the Uri retrieved above is content://media/external/images/media/7266
However, I am unable to retrieve a Uri in this format when I try to fetch the Uri of an image I just saved as a file:
Date d = new Date();
CharSequence s = DateFormat.format("MM-dd-yy hh-mm-ss", d.getTime());
Bitmap bitmap = drawView.getResultBitmap();
File sdCardDirectory = Environment.getExternalStorageDirectory();
File image = new File(sdCardDirectory, "DCIM/Camera/" + s.toString() + ".png");
boolean success = false;
// Encode the file as a PNG image.
FileOutputStream outStream;
try {
outStream = new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
/* 100 to keep full quality of the image */
outStream.flush();
outStream.close();
success = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (success) {
MediaScannerConnection.scanFile(getActivity(), new String[]{
image.getAbsolutePath()},
null, new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
}
});
Uri uri = Uri.parse(image.getAbsolutePath());
beginCrop(uri);
The Uri obtained from above code is /storage/emulated/0/DCIM/Camera/02-04-16 12-49-16.png
I believe, this is not the correct Uri format, instead just absolute file path. Is there a way out by which I can get the Uri in the format content://media/external/images/media/ ?
Any help is much appreciated
I believe, this is not the correct Uri format, instead just absolute file path.
You are correct. Use Uri.fromFile() to convert a File into a Uri pointing to the file.
Is there a way out by which I can get the Uri in the format content://media/external/images/media/ ?
Not readily. At best, in onScanCompleted(), you might be able to run some query to get the Uri that the MediaStore uses. But, until then, MediaStore does not know about the file.
The Uri that you get from Uri.fromFile() is a valid Uri, but it will have a file scheme, not a content scheme.
you can get uri from Bitmap like this :
Uri getUri(Context context, Bitmap bitmap) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
String path = "";
try {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
path = MediaStore.Images.Media.insertImage(
context.getContentResolver(), bitmap, "Title", null);
} catch (Exception e) {
}
return Uri.parse(path);
}
I had a problem when saving picture on sdcard from my app.
that when i am taking a picture and saving it on sdcard and go to my app and take a new one and save it on sdcard the previous preview picture appear and when view it on my computer it appear corrupted ?
why this problem ?
public static void save(Bitmap bm, String path) {
OutputStream outStream = null;
try {
outStream = new FileOutputStream(new File(path));
bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
bm.recycle();
System.gc();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
enter code here
Use this method to store the image and display it.This is used to store the image
//create new directory to store image
File photo = new File(Environment.getExternalStorageDirectory()+"/Android/data/"+getApplicationContext().getPackageName()+"/files/Receipt");
boolean success = false;
if(!photo.exists())
{
success = photo.mkdirs();
}
//if exists save the image in specified path
if(!success)
{
dbimgguid = UUID.randomUUID();
imagename =dbimgguid.toString();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
photo = new File(Environment.getExternalStorageDirectory()+"/Android/data/"+getApplicationContext().getPackageName()+"/files/Receipt", imagename+".png");
intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(photo));
imageurl = Uri.fromFile(photo);
startActivityForResult(intent, CAMERA_RECEIPTREQUEST);
}
To view the image
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode)
{
case CAMERA_RECEIPTREQUEST:
if(resultCode== Activity.RESULT_OK)
{
//Toast.makeText(this, "Receipt Image Saved", Toast.LENGTH_SHORT).show();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
ImageView jpgView = (ImageView)findViewById(R.id.imageView1);
Bitmap receipt = BitmapFactory.decodeFile(photo.toString(),options);
jpgView.setImageBitmap(receipt);
}
break;
}
I hope this will help you..
}
Do you have permissions to store to the SD card? I believe you need save and save to sd permissions.