Android - Setting wallpaper from file path takes longer than expected - android

I'm trying to set wallpaper from file path. However it takes more than 10 seconds and causes my app to freeze.
Here's the code I'm using:
public void SET_WALLPAPER_FROM_FILE_PATH (String file_path)
{
Bitmap image_bitmap;
File image_file;
FileInputStream fis;
try {
WallpaperManager wallpaper_manager = WallpaperManager.getInstance(m_context);
image_file = new File(file_path);
fis = new FileInputStream(image_file);
image_bitmap = BitmapFactory.decodeStream(fis);
wallpaper_manager.setBitmap(image_bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
I have tried to use:
wallpaper_manager.setStream(fis)
instead of:
wallpaper_manager.setBitmap(image_bitmap);
as suggested in this answer but couldn't load the wallpaper.
Can anyone guide me?
Thanks

Try to use AsyncTask,
in doInBackground method write something like this
public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_WIDTH=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
}
catch (FileNotFoundException e) {}
return null;
}

Related

How to prevent out of memory exception while trying to convert input stream object into bitmap in android?

I had used following code to convert inputstream object into bitmap. But it returns "out of memory error", and BitmapFactory Options always returns Zero.
S3ObjectInputStream inputStreamReceiptObject = objectReceiptFromAmazonS3
.getObjectContent();
Bitmap bitmapImageFromAmazon = null;
try {
if (inputStreamReceiptObject != null){
BitmapFactory.Options o = new BitmapFactory.Options();
o.inSampleSize = 8;
o.inJustDecodeBounds = true;
bitmapImageFromAmazon = BitmapFactory.decodeStream(inputStreamReceiptObject,null,o); // o is always null
if(bitmapImageFromAmazon == null){
System.out.println("Bitmap null");
}
}
Advance Thanks for any help !
SOLUTION : ( Lot of thanks to Honourable Don and Honourable Akshat )
ByteArrayOutputStream baos = null ;
InputStream is1 = null,is2 = null;
try {
baos = new ByteArrayOutputStream();
// Fake code simulating the copy
// You can generally do better with nio if you need...
// And please, unlike me, do something about the Exceptions :D
byte[] buffer = new byte[1024];
int len;
while ((len = inputStreamReceiptObject.read(buffer)) > -1 ) {
baos.write(buffer, 0, len);
}
baos.flush();
// Open new InputStreams using the recorded bytes
// Can be repeated as many times as you wish
is1 = new ByteArrayInputStream(baos.toByteArray());
is2 = new ByteArrayInputStream(baos.toByteArray());
bitmapImageFromAmazon = getBitmapFromInputStream(is1,is2);
if(bitmapImageFromAmazon == null)
System.out.println("IMAGE NULL");
else
System.out.println("IMAGE NOT NULL");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
baos.close();
is1.close();
is2.close();
}
public Bitmap getBitmapFromInputStream(InputStream is1,InputStream is2) throws IOException {
Bitmap bitmap = null;
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is1,null,o);
//Find the correct scale value. It should be the power of 2.
int scale=1;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
bitmap = BitmapFactory.decodeStream(is2, null, o2);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
Why dont you try and scale the bitmap image down? Thats mostly the reason why your app showed OOM exception
BitmapFactory.Options o = new BitmapFactory.Options();
o.inScaled = false;
o.inJustDecodeBounds = true;
FileInputStream stream1 = new FileInputStream(f);
BitmapFactory.decodeStream(stream1, null, o);
stream1.close();
// Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE = 70; //This is the max size of the bitmap in kilobytes
int width_tmp = o.outWidth, height_tmp = o.outHeight;
int scale = 1;
while (true) {
if (width_tmp / 2 < REQUIRED_SIZE
|| height_tmp / 2 < REQUIRED_SIZE)
break;
width_tmp /= 2;
height_tmp /= 2;
scale *= 2;
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
FileInputStream stream2 = new FileInputStream(f);
Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
The Out Of Memory error should be as it says: you do not have enough memory on your device to render the entire image. You need to ensure that the image you're downloading from S3 is not too big for the device.
To help you debug, try running downloading a smaller image to see if you are still receiving the OOM errors
URLConnection conn = new URL("http://upload.wikimedia.org/wikipedia/commons/thumb/a/a1/Victoria_Parade_postcard.jpg/120px-Victoria_Parade_postcard.jpg").openConnection();
InputStream stream = conn.getInputStream();
Bitmap image = BitmapFactory.decodeStream(stream, null, null);
The o you pass into decodeStream is null because of the OOM error (it must have gone out of scope when you examined it in the debugger).

Android OutOfMemoryException taking a picture with camera

I'm trying to take a picture and add an overlay on top of it. Here is my code (only the callback) :
private PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(final byte[] data, Camera camera) {
if(!dirFile.exists()){
dirFile.mkdirs();
}
try {
String name = new SimpleDateFormat("ddMMyyyy_HHmmss").format(new Date()) + ".jpg";
picturePath = new File(dirFile, name);
new AsyncTask<Void, Void, Void>(){
FileOutputStream fos = new FileOutputStream(picturePath);
Bitmap photo;
#Override
protected Void doInBackground(Void... params) {
photo = BitmapFactory.decodeByteArray(data, 0, data.length).copy(Config.ARGB_8888, true);
Bitmap cadre = BitmapFactory.decodeResource(getResources(), R.drawable.cadre16001200);
Canvas canvas = new Canvas(photo);
canvas.drawBitmap(cadre, new Matrix(), null);
cadre.recycle();
photo.compress(CompressFormat.JPEG, 100, fos);
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
geotag(picturePath.toString());
return null;
}
protected void onPostExecute(Void result) {
dialog.dismiss();
mCamera.startPreview();
//Affiche la nouvelle photo
picture.setImageBitmap(photo);
};
}.execute();
} catch (FileNotFoundException e) {
Log.d("PhotoActivity", "File not found: " + e.getMessage());
}
}
};
I get the following error on my Samsung Galaxy S3 (android 4.1.2) , with an OutOfMemoryException
07-04 10:01:24.076: E/dalvikvm-heap(2980): Out of memory on a 7680016-byte allocation.
Weird thing is that it works perfectly on the Samsung Gio (android 2.2.1) with the same resolution of 1600x1200.
I googled a lot, and I can't use the main solution of downsizing the picture. It is a memory issue, but I don't know how I can reduce the memory usage.
EDIT : I found this, seems it was the real matter : https://stackoverflow.com/a/12377158/1343969
you should decode the bitmap before proccessing it to the UI, here's a code example
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream stream1=new FileInputStream(f);
BitmapFactory.decodeStream(stream1,null,o);
stream1.close();
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
FileInputStream stream2=new FileInputStream(f);
Bitmap bitmap=BitmapFactory.decodeStream(stream2, null, o2);
stream2.close();
return bitmap;
} catch (FileNotFoundException e) {
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
You should simply call the empty constructor of Canvas and draw the photo on it. This would remove the copy() call and reduce the memory usage.
photo = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap cadre = BitmapFactory.decodeResource(getResources(), R.drawable.cadre16001200);
Canvas canvas = new Canvas();
canvas.drawBitmap(photo, 0, 0, null);
canvas.drawBitmap(cadre, new Matrix(), null);
cadre.recycle();
photo.compress(CompressFormat.JPEG, 100, fos);

Downloaded Image Appears very blurry

I downloaded an image to use following this excellent article. My own image I'm using is a google map static image that is 300x400. I've fiddle with a few of the settings and have expanded it to fill across the screen, however it just appears very blurry.
<ImageView
android:id="#+id/image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_x="0dp"
android:layout_y="0dp"
android:adjustViewBounds="true"
android:clickable="false"
android:gravity="center_vertical"
android:longClickable="false"
android:scaleType="fitCenter" />
That is what I have in the screen xml layout. Is this a common problem? I did a good search and couldn't find an answer. Is 300x400 not a good res for android?
Is 300x400 not a good res for android?
it depends on original image orientation and a couple of other things like your layout and device display. Alternatively, you could try the following code to download an image, this works fine for me:
don't forget to add
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
to your Manifest
public class MainActivity extends Activity {
private Button get;
private ImageView pic;
private static final String SRC = "http://www.allindiaflorist.com/imgs/arrangemen4.jpg";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
get = (Button)findViewById(R.id.button1);
pic = (ImageView)findViewById(R.id.imageView1);
get.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
pic.setImageBitmap(getBitmapFromURL(SRC));
}
});
}
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
Log.e("getBmpFromUrl error: ", e.getMessage().toString());
return null;
}
}
}
I found the reason why they were low, the image loader class had a built in compression:
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
So just remove this part so you are left with:
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
return BitmapFactory.decodeStream(new FileInputStream(f));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return null;
}
Crystal clear images.

Android Camera pick image and upload

I have written code to capture photo and upload the captured image to the Facebook.It worked great for all the devices but when i try to run the app on Samsung galaxy s3,the app got crashed and given outofmemory error and when i compressed the image it showing Null-pointer exception.
Intent intent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
this.file = new File(
Environment
.getExternalStorageDirectory(),
"tmp_"
+ String.valueOf(System
.currentTimeMillis())
+ ".jpg");
ImageCaptureUri = Uri.fromFile(file);
try {
intent.putExtra(
android.provider.MediaStore.EXTRA_OUTPUT,
ImageCaptureUri);
intent.putExtra("return-data", true);
startActivityForResult(intent,
PICK_FROM_CAMERA);
} catch (Exception e) {
e.printStackTrace();
}
::onActivityResult
uploadBitmap= decodeFile(MainActivity.this.file);
int width = uploadBitmap.getWidth()/3;
int height = uploadBitmap.getHeight()/3;
// uploadBitmap=Bitmap.createScaledBitmap(uploadBitmap, 50, 50, false);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
uploadBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
// Bitmap bitmap = BitmapFactory.decodeFile(path);
if (photoUrl != null) {
Bundle params = new Bundle();
params.putByteArray("photo", byteArray);
params.putString("caption",
MainActivity.locationData+" lat: "+MainActivity.latitude+" long:"+MainActivity.longitude);
String place ="\"location\""+": {"+
"\"latitude\""+":"+"\"12.9833\""+","+
"\"longitude\""+":"+"\"77.5833\""+
"}";
params.putString("place", placeid);
Utility.mAsyncRunner.request("me/photos", params, "POST",
new PhotoUploadListener(), null);
} else {
Toast.makeText(getApplicationContext(),
"Error capturing image",
Toast.LENGTH_SHORT).show();
}
try to decode as below
public static Bitmap decodeFile(File f,int WIDTH,int HIGHT){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_WIDTH=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}

Why am I getting java.io.IOException: Mark has been invalidated?

I'm trying to download imags from a url and then decode them.
The problem is that I don't know how large are they and if I decode them right away, the app crashes with too-big images.
I'm doing the following and it works with most of the images but with some of them, it throws the java.io.IOException: Mark has been invalidated exception.
It's not a matter of size because it happens with a 75KB or a 120KB image and not with a 20MB or 45KB image.
Also the format is not important as it can happen either with a jpg or png image.
pis is an InputStream.
Options opts = new BitmapFactory.Options();
BufferedInputStream bis = new BufferedInputStream(pis);
bis.mark(1024 * 1024);
opts.inJustDecodeBounds = true;
Bitmap bmImg=BitmapFactory.decodeStream(bis,null,opts);
Log.e("optwidth",opts.outWidth+"");
try {
bis.reset();
opts.inJustDecodeBounds = false;
int ratio = opts.outWidth/800;
Log.e("ratio",String.valueOf(ratio));
if (opts.outWidth>=800)opts.inSampleSize = ratio;
return BitmapFactory.decodeStream(bis,null,opts);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
I think you want to decode large image. I did it by selecting gallery image.
File photos= new File("imageFilePath that you select");
Bitmap b = decodeFile(photos);
"decodeFile(photos)" function is used for decode large image. I think you need to get image .png or .jpg formet.
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale++;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
you can display it by using imageView.
ImageView img = (ImageView)findViewById(R.id.sdcardimage);
img.setImageBitmap(b);

Categories

Resources