我在 HTC Wildfire S 设备上遇到了一个大问题。我的应用程序使用图像 uri 启动第二个活动,用户可以旋转图像,然后将其保存并返回到主活动。问题出在 HTC 上,只有第一张照片会被返回,而第二张照片会导致应用程序崩溃,并出现以下错误:
java.lang.IllegalStateException: Can't compress a recycled bitmap
at android.graphics.Bitmap.checkRecycled(Bitmap.java:372)
at android.graphics.Bitmap.compress(Bitmap.java:799)
at zapytaj.hot.or.not.ImageRotator.end(ImageRotator.java:151)
at zapytaj.hot.or.not.ImageRotator$RotatorClass.onClick(ImageRotator.java:80)
at android.view.View.performClick(View.java:2532)
at android.view.View$PerformClick.run(View.java:9293)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:4277)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
我已经读过我应该 .copy bitmap 以避免在另一篇文章中出现这个问题,但无法弄清楚如何在我的代码上做到这一点。谢谢你的帮助。第二个活动的代码如下:
package com.example.app;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Base64;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;
public class ImageRotator extends Activity {
private static final String TAG = "Rotator";
private Uri file;
private String suffix = "";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.picture);
Bundle b = getIntent().getExtras();
file = getIntent().getData();
suffix = b.getString("suffix");
Bitmap bm = this.getBitmap();
ImageView box = (ImageView) findViewById(R.id.imageView1);
box.setImageBitmap(bm);
ImageButton v1 = (ImageButton) findViewById(R.id.rotateLeft);
ImageButton v2 = (ImageButton) findViewById(R.id.rotateRight);
ImageButton v3 = (ImageButton) findViewById(R.id.save);
v1.setOnClickListener(new RotatorClass());
v2.setOnClickListener(new RotatorClass());
v3.setOnClickListener(new RotatorClass());
}
class RotatorClass implements ImageButton.OnClickListener
{
public void onClick(View v) {
final int id = v.getId();
int change = 0;
switch(id) {
case R.id.rotateLeft:
change = -90;
break;
case R.id.rotateRight:
change = 90;
break;
case R.id.save:
end(true);
return;
}
Log.d(TAG, "change: "+change);
ImageRotator.this.rotate(change);
}
}
@Override
public void onBackPressed() {
final AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Podane zdjęcie nie zostanie dodane. Kontynuować?");
alertDialog.setButton("Tak", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
end(false);
}
});
alertDialog.setButton2("Nie", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
alertDialog.cancel();
}
});
alertDialog.setCancelable(false);
alertDialog.show();
}
public void rotate(int change) {
// TODO Auto-generated method stub
ImageView imageView = (ImageView) findViewById(R.id.imageView1);
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bm = drawable.getBitmap();
Matrix matrix = new Matrix();
matrix.postRotate(change);
Bitmap bm2 = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
bm = null;
imageView.setImageBitmap(bm2);
}
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);
}
public void end(boolean save) {
Intent in = new Intent();
if(save == true) {
File file2 = new File(getRealPathFromURI(file));
try {
FileOutputStream fos = new FileOutputStream(file2);
ImageView imageView = (ImageView) findViewById(R.id.imageView1);
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bm = drawable.getBitmap();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 30, baos);
byte[] b = baos.toByteArray();
String base = Base64.encodeToString(b, Base64.NO_WRAP);
bm.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.flush();
fos.close();
bm.recycle();
bm = null;
in.setData(file);
in.putExtra("base", base);
System.gc();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
setResult(4,in);
finish();
}
private Bitmap getBitmap() {
Uri uri = this.file;
InputStream in = null;
ContentResolver mContentResolver = getContentResolver();
try {
final int IMAGE_MAX_SIZE = 300000;
in = mContentResolver.openInputStream(uri);
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, o);
in.close();
int scale = 1;
while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) {
scale++;
}
Log.d(TAG, "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight);
Bitmap b = null;
in = mContentResolver.openInputStream(uri);
if (scale > 1) {
scale--;
// scale to max possible inSampleSize that still yields an image
// larger than target
o = new BitmapFactory.Options();
o.inSampleSize = scale;
b = BitmapFactory.decodeStream(in, null, o);
// resize to desired dimensions
int height = b.getHeight();
int width = b.getWidth();
Log.d(TAG, "1th scale operation dimenions - width: " + width + ", height: " + height);
double y = Math.sqrt(IMAGE_MAX_SIZE
/ (((double) width) / height));
double x = (y / height) * width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x, (int) y, true);
b.recycle();
b = null;
b = scaledBitmap;
} else {
b = BitmapFactory.decodeStream(in);
}
in.close();
return b;
} catch (IOException e) {
Log.e(TAG, e.getMessage(),e);
return null;
}
}
}