代码运行得非常好。但它很慢,有时显示ANR。我想要一个单独的线程或连续运行的AsyncTask并处理imagebrightness值。我无法创建多个AsyncTask,因为(它们都执行相同的操作)。
我只需要获取YUV byte code
和convert it to bitmap
并将其设置为我的Activity View
。
private android.hardware.Camera.PreviewCallback previewCallback = new android.hardware.Camera.PreviewCallback()
{
public void onPreviewFrame(final byte abyte0[] , Camera camera)
{
int[] rgbData = YuvUtils.myDecodeGreyscale(abyteData, widthPreview, heightPreview, imageBrightness, nonGreencolorOffset, greenColorOffset);
editedBitmap.setPixels(rgbData, 0, widthPreview, 0, 0, widthPreview, heightPreview);
if(MainActivity2.cameraId==CameraInfo.CAMERA_FACING_FRONT)
{
matrix.setRotate(270F);
}
finalBitmap = Bitmap.createBitmap(editedBitmap, 0, 0, widthPreview, heightPreview, matrix, true);
//above all methods should be call on background Thread.
MainActivity2.drawView.setBitmapToDraw(finalBitmap);//only this statement should be use in Main Thread
}
};
我尝试了什么
我在每个previewFrame()调用上创建了一个新的AsyncTask。它挂起了设备。我也尝试过使用Thread但是遇到同样的问题。
我只是希望我的代码在单独的后台线程上执行,该线程与我的Activity绑定服务。 我也是Thread.sleep来克服ANR。但它会停止用户界面。
try
{
Thread.sleep(1L);
}
catch (InterruptedException interruptedexception)
{
interruptedexception.printStackTrace();
}
onPreviewFrame会在一秒钟内调用三次。我想在几秒钟内完成一到两次操作以显示连续的CameraPreview。 someOne能否告诉我如何实现这一目标。
我的想法是什么。
的AsyncTask
public class CameraPreviewTask extends AsyncTask<Void, Void, Void>
{
public static int cameraId;
public static boolean isRunning;
public Context ctx;
public byte[] data;
public boolean dataAvailable;
private Bitmap editedBitmap;
private Bitmap finalBitmap;
private int green;
public double greenColorOffset;
private int heightPreview;
private int widthPreview;
public int imageBrightness=70;
private int iterator;
private int iteratorLimit;
int j;
private Matrix matrix;
public double nonGreencolorOffset=30;
private int nongreen=20;
private int p;
private int[] pixels_preview;
public boolean saveCurrentFrame;
public boolean workingOnData;
public CameraPreviewTask(final Context ctx, final int widthPreview, final int heightPreview)
{
saveCurrentFrame = false;
dataAvailable = false;
workingOnData = false;
this.ctx = ctx;
this.widthPreview = widthPreview;
this.heightPreview = heightPreview;
iteratorLimit = widthPreview * heightPreview;
pixels_preview = new int[iteratorLimit];
editedBitmap = Bitmap.createBitmap(widthPreview, heightPreview, Config.ARGB_8888);
(matrix = new Matrix()).postRotate(90.0f);
CameraPreviewTask.isRunning = true;
}
protected Void doInBackground(final Void... array)
{
while (CameraPreviewTask.isRunning)
{
try
{
while (!dataAvailable)
{
Thread.sleep(1L);
}
}
catch (InterruptedException ex)
{
Log.e("EditorWorker", "Error while waiting for data =" + ex.getMessage());
}
try
{
workingOnData = true;
int[] rgbData = YuvUtils.myDecodeGreyscale(data, widthPreview, heightPreview, imageBrightness, nonGreencolorOffset, greenColorOffset);
editedBitmap.setPixels(rgbData, 0, widthPreview, 0, 0, widthPreview, heightPreview);
if(MainActivity2.cameraId==CameraInfo.CAMERA_FACING_FRONT)
{
matrix.setRotate(270F);
}
finalBitmap = Bitmap.createBitmap(editedBitmap, 0, 0, widthPreview, heightPreview, matrix, true);
publishProgress((Void[])new Void[0]);
workingOnData = false;
}
catch (Exception ex2)
{
Log.e("Error", ex2.getMessage() + "");
}
finally
{
workingOnData = false;
}
}
return null;
}
protected void onProgressUpdate(Void... array)
{
super.onProgressUpdate((Void[])array);
MainActivity2.drawView.setBitmapToDraw(finalBitmap);
if (saveCurrentFrame)
{
saveCurrentFrame = false;
new BitmapSaver(ctx, finalBitmap).start();
}
}
@TargetApi(11)
public void start()
{
if (Build.VERSION.SDK_INT >= 11)
{
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Void[0]);
}
else
{
execute(new Void[0]);
}
}
}
答案 0 :(得分:0)
我有一个可能以不同方式重新启动的想法,如果我在某处创建了可怕的内存泄漏或完全忽略线程安全,请有人纠正我。我总是指望只由一个线程写的变量。
在你的MainActivity中,制作一个Handler / Runnable组合,让它每次更新你的视图...... 40ms:
MainActivity extends Activity{ //beware pseudo code
Bitmap finalBitmap;
Handler viewHandler; //android.os.Handler, not the java one
boolean camIsRunning = false;
AtomicBoolean newBitmap = false;
Camera myCamera;
byte aByte[];
Runnable updateView = new Runnable(){
@Override
public void run(){
if(camIsRunning){
drawView.setBitmapToDraw(finalBitmap);
alsoUpdateSeekbarAndStuffIMayHaveForgotten(); //<- edit
viewHandler.postDelayed(updateView, 40);
}
}
};
onCreate(...){ //beware pdeudo code again
initYourStuff(); //whatever
viewHandler = new Handler();
finalBitmap = initBitmap(); //not sure how you initialize/start your bitmap handling, just make sure to draw your bitmap only after there is one, so put a placeholder here until the cam is running.
startCamera(); //also triggers camIsRunning;
//After there is a bitmap and the camera is running and actually every time you start up your camera:
viewHandler.post(updateView);
new BitmapOperator().start();
}
class BitmapOperator extends Thread{
public void run(){
while(camIsRunning){
if(newBitmap.weakCompareAndSet(true, false)) //if there is a new bitmap, reset to false and process.
processBitmap(aByte[], camera); //convert here
}
}
}
private android.hardware.Camera.PreviewCallback previewCallback = new android.hardware.Camera.PreviewCallback()
{
public void onPreviewFrame(final byte abyte0[] , Camera camera)
{
aByte[] = abyte0[];
myCamera = camera;
newBitmap.set(true); //Atomic for thread safety because I'm too lazy to sync stuff manually for just this one variable.
}
};
}