I've been trying to look for a similar error but I'm having a hard time... I'm still new to android development, but hopefully someone can shine some direction.
I have a camera app that can preview, but when I tried to click on a button to take the picture, my app crashes. Can someone help me?
[PhotoActivity.java]
public class PhotoActivity extends Activity {
public static final int MEDIA_TYPE_IMAGE = 1;
protected static final String TAG = "Activity";
private Camera mCamera;
private CameraPreview mCameraPreview;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.photo);
mCamera = getCameraInstant();
mCameraPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(id.camera_preview);
preview.addView(mCameraPreview);
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// get an image from the camera
Log.e("log", "mPicture"+mPicture);
mCamera.takePicture(null, null, mPicture);
}
}
);
}
PictureCallback mPicture = new PictureCallback(){
#Override
public void onPictureTaken(byte[] data, Camera camera) {
// TODO Auto-generated method stub
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if(pictureFile==null){
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e){
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
}
};
/**
* Helper method to access the camera returns null if
* it cannot get the camera or does not exist
* #return
*/
private Camera getCameraInstant(){
Camera camera = null;
try{
camera=Camera.open();
}catch (Exception e){
// cannot get camera or does not exist
}
return camera;
}
/** Create a File for saving the image */
private File getOutputMediaFile(int type){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
return mediaFile;
}
}
Sorry for all the coding, but I'm really in need of some help... Thanks in advance.
UPDATED
[CameraPreview.java]
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "Preview";
private SurfaceHolder mSurfaceHolder;
private Camera mCamera;
//Constructor that obtains context and camera
public CameraPreview(Context context, Camera camera) {
super(context);
//this.mCamera = camera;
this.mCamera = camera;
this.mSurfaceHolder = this.getHolder();
this.mSurfaceHolder.addCallback(this); // we get notified when underlying surface is created and destroyed
this.mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //this is a deprecated method, is not requierd after 3.0
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
mCamera.release();
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
// left blank for now
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
if (mCamera != null) {
Log.d(TAG,"Stopping preview in SurfaceDestroyed().");
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
}
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format,
int width, int height) {
if(mSurfaceHolder.getSurface()==null){
//preview surface does not exist
return;
}
try {
mCamera.stopPreview();
}catch(Exception e){
//ignore: tried to stop a non-existent preview
}
// start preview with new settings
try {
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (Exception e) {
// intentionally left blank for a test
Log.d(TAG, "Error starting camera preview: "+e.getMessage());
}
}
}
Error
05-09 21:19:29.013: E/AndroidRuntime(3823): FATAL EXCEPTION: main
05-09 21:19:29.013: E/AndroidRuntime(3823): java.lang.RuntimeException: Method called after release()
05-09 20:21:01.214: E/AndroidRuntime(2813): at android.hardware.Camera.native_takePicture(Native Method)
05-09 20:21:01.214: E/AndroidRuntime(2813): at android.hardware.Camera.takePicture(Camera.java:746)
05-09 20:21:01.214: E/AndroidRuntime(2813): at android.hardware.Camera.takePicture(Camera.java:710)
05-09 20:21:01.214: E/AndroidRuntime(2813): at com.liu.photo.PhotoActivity$2.onClick(PhotoActivity.java:73)
05-09 20:21:01.214: E/AndroidRuntime(2813): at android.view.View.performClick(View.java:2486)
05-09 20:21:01.214: E/AndroidRuntime(2813): at android.view.View$PerformClick.run(View.java:9130)
05-09 20:21:01.214: E/AndroidRuntime(2813): at android.os.Handler.handleCallback(Handler.java:587)
05-09 20:21:01.214: E/AndroidRuntime(2813): at android.os.Handler.dispatchMessage(Handler.java:92)
05-09 20:21:01.214: E/AndroidRuntime(2813): at android.os.Looper.loop(Looper.java:130)
05-09 20:21:01.214: E/AndroidRuntime(2813): at android.app.ActivityThread.main(ActivityThread.java:3703)
05-09 20:21:01.214: E/AndroidRuntime(2813): at java.lang.reflect.Method.invokeNative(Native Method)
05-09 20:21:01.214: E/AndroidRuntime(2813): at java.lang.reflect.Method.invoke(Method.java:507)
05-09 20:21:01.214: E/AndroidRuntime(2813): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
05-09 20:21:01.214: E/AndroidRuntime(2813): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
05-09 20:21:01.214: E/AndroidRuntime(2813): at dalvik.system.NativeStart.main(Native Method)
Is this what the stack trace is? I'm very new, still learning the terms as well. Thank you
Remove these two lines from the surfaceCreated method:
mCamera.release();
mCamera = Camera.open();
You've already opened the Camera object in your Activity, no need to release it and reopen it again.
Edit You should actually remove your whole implementation of surfaceCreated and just leave the implementation empty. You're just repeating what you've already done in surfaceChanged, which is the important place to implement it anyway.
Please see this page:
http://developer.android.com/reference/android/hardware/Camera.html
And make sure you follow the rules.
Especially pay attention that you must start preview before you take a picture.
Related
I have been trying to encode bitmap images from a view into a mp4 video. I am using MediaRecorder setup with Surface as input. The code is failing on the second iteration in the loop. It appears that the canvas is not successfully unlocked, and then lockCanvas fails and throws an error.
What could be causing this exception?
public class ViewRecorder
{
private View recordView;
private boolean run = true;
private String filename;
public ViewRecorder(View recordView, String filename)
{
this.recordView = recordView;
this.filename = filename;
Thread thread = new Thread(new Task());
thread.start();
}
/*
* Stops the recording
*/
public void Stop()
{
this.run = false;
}
/*
* Encodes a frame every 100 mS
*/
private class Task implements Runnable
{
#Override
public void run()
{
try
{
MediaRecorder mediaRecorder = new MediaRecorder();
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setVideoFrameRate(10);
//this.mediaRecorder.setVideoEncodingBitRate(20000);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mediaRecorder.setOutputFile(filename + ".mp4");
recordView.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(recordView.getDrawingCache());
recordView.setDrawingCacheEnabled(false);
mediaRecorder.setVideoSize(bitmap.getWidth(), bitmap.getHeight());
mediaRecorder.prepare();
mediaRecorder.start(); // Recording is now started
while(run)
{
Thread.sleep(100);
recordView.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(recordView.getDrawingCache());
recordView.setDrawingCacheEnabled(false);
Surface surface = mediaRecorder.getSurface();
Canvas canvas = surface.lockCanvas(null);
canvas.drawBitmap(bitmap, 0, 0, new Paint());
surface.unlockCanvasAndPost(canvas);
}
mediaRecorder.stop();
mediaRecorder.reset();
mediaRecorder.release();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
}
This is the exception:
11-21 18:59:35.220 26737-27432/ W/System.err: java.lang.IllegalArgumentException
11-21 18:59:35.220 26737-27432/ W/System.err: at android.view.Surface.nativeLockCanvas(Native Method)
11-21 18:59:35.220 26737-27432/ W/System.err: at android.view.Surface.lockCanvas(Surface.java:322)
11-21 18:59:35.221 26737-27432/ W/System.err: at .ViewRecorder$Task.run(ViewRecorder.java:77)
11-21 18:59:35.221 26737-27432/ W/System.err: at java.lang.Thread.run(Thread.java:762)
11-21 19:00:47.783 26737-26744/ W/art: Suspending all threads took: 35.361ms
11-21 19:01:25.983 26737-26744/ W/art: Suspending all threads took: 22.830ms
Not sure if you're still after a solution but I found this:
Move - Surface surface = mediaRecorder.getSurface();
outside of the loop so it's only called once. Errors on the second time it's called
I've been working on this Camera app for a little while now. Basically what I want to do is take a picture(and store it internally), then display that image in the next Activity. The preview works perfectly, but when I hit the Capture button on MainActivity the error "Unfortunately, myApplication has stopped" shows up and the app crashes. AndroidStudio is not giving me any Event Log information either...
Here's the main activity(is something wrong with SendInfo?):
public class MainActivity extends ActionBarActivity {
public final static String EXTRA_MESSAGE = "File_name";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create an instance of Camera
Camera mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
CameraPreview mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Camera mCamera = getCameraInstance();
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
}
//////////////////////
public void sendInfo(View view)
{
Intent intent = new Intent(this,show_image.class);
Uri fileUri = getOutputMediaFileUri(1);
intent.putExtra(EXTRA_MESSAGE, fileUri.toString());
startActivity(intent);
}
/////////////////
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d("Logtag:", "Error creating media file, check storage permissions: "
);
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d("Logtag:", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("Logtag:", "Error accessing file: " + e.getMessage());
}
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/** A safe way to get an instance of the Camera object. */
public Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
Toast.makeText(getApplicationContext(), "Camera is not available (in use or does not exist)",
Toast.LENGTH_LONG).show();
}
return c; // returns null if camera is unavailable
}
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
// This locat ion works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("Logtag", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
}
And here is the second Activity that should be displaying the image...
public class show_image extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String stringURI = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
// Uri uri = Uri.parse(stringURI);
Bitmap bitmap = BitmapFactory.decodeFile(stringURI);
ImageView imageView = new ImageView(this);
imageView.setImageBitmap(bitmap);
setContentView(imageView);
}
public static Bitmap decodeFile(File f, final int maxSize) {
Bitmap b = null;
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
BitmapFactory.decodeStream(fis, null, o);
fis.close();
int scale = 1;
if (o.outHeight > maxSize || o.outWidth > maxSize) {
scale = (int) Math.pow(2, (int) Math.round(Math.log(maxSize / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
}
// Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
fis = new FileInputStream(f);
b = BitmapFactory.decodeStream(fis, null, o2);
} catch (Exception e) {
Log.e("Logtag", "Error processing bitmap", e);
} finally {
//FileUtil.closeQuietly(fis);
}
return b;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Output from Log Cat:
02-25 00:53:11.907 13191-13191/edu.ramapo.camer I/System.out﹕ debugger has settled (1480)
02-25 00:53:12.177 13191-13191/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.view.ViewGroup.onNestedScrollAccepted, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.onNestedScrollAccepted
02-25 00:53:12.177 13191-13191/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 11357: Landroid/view/ViewGroup;.onNestedScrollAccepted (Landroid/view/View;Landroid/view/View;I)V
02-25 00:53:12.177 13191-13191/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6f at 0x0000
02-25 00:53:12.177 13191-13191/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.view.ViewGroup.onStopNestedScroll, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.onStopNestedScroll
02-25 00:53:12.177 13191-13191/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 11363: Landroid/view/ViewGroup;.onStopNestedScroll (Landroid/view/View;)V
02-25 00:53:12.177 13191-13191/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6f at 0x0000
02-25 00:53:12.177 13191-13191/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.support.v7.internal.widget.ActionBarOverlayLayout.stopNestedScroll, referenced from method android.support.v7.internal.widget.ActionBarOverlayLayout.setHideOnContentScrollEnabled
02-25 00:53:12.177 13191-13191/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 9047: Landroid/support/v7/internal/widget/ActionBarOverlayLayout;.stopNestedScroll ()V
02-25 00:53:12.177 13191-13191/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x000e
02-25 00:53:12.207 13191-13191/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method android.support.v7.internal.widget.TintTypedArray.getChangingConfigurations
02-25 00:53:12.207 13191-13191/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 365: Landroid/content/res/TypedArray;.getChangingConfigurations ()I
02-25 00:53:12.207 13191-13191/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002
02-25 00:53:12.207 13191-13191/edu.ramapo.camer I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.internal.widget.TintTypedArray.getType
02-25 00:53:12.207 13191-13191/edu.ramapo.camer W/dalvikvm﹕ VFY: unable to resolve virtual method 387: Landroid/content/res/TypedArray;.getType (I)I
02-25 00:53:12.207 13191-13191/edu.ramapo.camer D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002
02-25 00:53:13.068 13191-13191/edu.ramapo.camer D/libEGL﹕ loaded /system/lib/egl/libEGL_adreno200.so
02-25 00:53:13.068 13191-13191/edu.ramapo.camer D/libEGL﹕ loaded /system/lib/egl/libGLESv1_CM_adreno200.so
02-25 00:53:13.078 13191-13191/edu.ramapo.camer D/libEGL﹕ loaded /system/lib/egl/libGLESv2_adreno200.so
02-25 00:53:13.078 13191-13191/edu.ramapo.camer I/Adreno200-EGL﹕ <qeglDrvAPI_eglInitialize:265>: EGL 1.4 QUALCOMM build: HAREESHG_Nondeterministic_AU+PATCH[ES]_msm8960_JB_1.9.6_MR2_CL3219408_release_ENGG (CL3219408)
Build Date: 09/28/13 Sat
Local Branch: hhh
Remote Branch: quic/jb_1.9.6_1
Local Patches: 8d50ec23e42ef52b570aa6ff1650afac0b503d78 CL3219408: Fix in the Glreadpixels for negative offsets and larger dimensions.
801859126f6ca69482b39a34ca61447e3f7cded8 rb: fix panel settings to clear undrawn/undefined buffers
Reconstruct Branch: LOCAL_PATCH[ES]
02-25 00:53:13.118 13191-13191/edu.ramapo.camer D/OpenGLRenderer﹕ Enabling debug mode 0
02-25 00:53:27.353 13191-13191/edu.ramapo.camer D/Logtag﹕ failed to create directory
02-25 00:53:27.353 13191-13191/edu.ramapo.camer D/Logtag:﹕ Error creating media file, check storage permissions:
I think the reason for the crash is because you are trying to get the camera instance twice: when your activity is created and when button captureButton is pressed. When you try to get it the second time, it returns null because it is already in use by your activity.
You should get the camera instance once before the captureButton button is pressed and process the picture taken after that.
public class MainActivity extends ActionBarActivity {
public final static String EXTRA_MESSAGE = "File_name";
private Camera mCamera;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
CameraPreview mPreview = new CameraPreview(this, mCamera);
FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
// Add a listener to the Capture button
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// get an image from the camera
mCamera.takePicture(null, null, mPicture);
}
}
);
}
...
Edit
To move to the next activity when a picture is taken, you could call startActivity after the Camera.PictureCallback
has saved the byte array to a file.
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
if (pictureFile == null){
Log.d("Logtag:", "Error creating media file, check storage permissions: "
);
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Intent intent = new Intent(this,show_image.class);
Uri fileUri = Uri.fromFile(pictureFile);
intent.putExtra(EXTRA_MESSAGE, fileUri.toString());
startActivity(intent);
} catch (FileNotFoundException e) {
Log.d("Logtag:", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("Logtag:", "Error accessing file: " + e.getMessage());
}
}
};
...
Edit 2
You need to add this permission to your manifest to store the photo on the device:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
I hope this helps.
I have an activity that is displayed in portrait only and in my tablet it causes the following:
android.view.WindowLeaked: Activity com.spicycurryman.getdisciplined10.app.InstalledAppActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{53210b88 V.E..... R.....ID 0,0-1520,192} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:354)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:216)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
at android.app.Dialog.show(Dialog.java:281)
at com.spicycurryman.getdisciplined10.app.InstalledAppActivity$LoadApplications.onPreExecute(InstalledAppActivity.java:306)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
at android.os.AsyncTask.execute(AsyncTask.java:534)
at com.spicycurryman.getdisciplined10.app.InstalledAppActivity.onCreate(InstalledAppActivity.java:105)
at android.app.Activity.performCreate(Activity.java:5104)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
at android.app.ActivityThread.access$600(ActivityThread.java:141)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
I am using an AsyncTask to load a listview of installed apps on the phone and using a progressdialog.
I have researched this problem:
Progress dialog and AsyncTask error
android.view.WindowLeaked exception
Android Error: Window Leaked in AsyncTask
I was able to produce this code so that the whole app doesn't crash and burn, but the exception is still thrown and the activity screen is kind of shaky after the button click and the whole transition is not really smooth.
#Override
protected void onPostExecute(Void result) {
apkList.setAdapter(new ApkAdapter(InstalledAppActivity.this, packageList1, packageManager));
try {
if ((this.pDialog != null) && this.pDialog.isShowing()) {
this.pDialog.dismiss();
}
} catch (final IllegalArgumentException e) {
// Handle or log or ignore
} catch (final Exception e) {
// Handle or log or ignore
} finally {
this.pDialog = null;
}
super.onPostExecute(result);
}
Dismissing the progress dialog or calling finish() doesn't really solve the problem either...
How would I fix this?
Here is most of the AsyncTask code:
private class LoadApplications extends AsyncTask<Void, Void, Void> {
private ProgressDialog pDialog;
List<PackageInfo> packageList1 = new ArrayList<PackageInfo>();
public LoadApplications(Context context){
Context mContext = context;
}
#Override
protected Void doInBackground(Void... params) {
List<PackageInfo> packageList = packageManager
.getInstalledPackages(PackageManager.GET_PERMISSIONS);
List<PackageInfo> packageList2 = packageManager
.getInstalledPackages(PackageManager.GET_PERMISSIONS);
for(PackageInfo pi : packageList) {
boolean b = isSystemPackage(pi);
boolean c = isSystemPackage1(pi);
boolean d = isSystemPackage2(pi);
if ((!b || !c ) && d ){
packageList1.add(pi);
}
}
//here you got email and message apps in the
for(PackageInfo pi : packageList) {
boolean b = isSystemPackage3(pi);
boolean c = isSystemPackage4(pi);
if (b || c){
packageList1.add(pi);
}
}
//sort by application name
final PackageItemInfo.DisplayNameComparator comparator = new PackageItemInfo.DisplayNameComparator(packageManager);
Collections.sort(packageList1, new Comparator<PackageInfo>() {
#Override
public int compare(PackageInfo lhs, PackageInfo rhs) {
return comparator.compare(lhs.applicationInfo, rhs.applicationInfo);
}
});
return null;
}
#Override
protected void onCancelled() {
super.onCancelled();
}
#Override
protected void onPreExecute() {
pDialog = new ProgressDialog(InstalledAppActivity.this);
pDialog.setMessage("Loading your apps...");
pDialog.show();
}
//Inefficient patch to prevent Window Manager error
#Override
protected void onPostExecute(Void result) {
apkList.setAdapter(new ApkAdapter(InstalledAppActivity.this, packageList1, packageManager));
try {
if ((this.pDialog != null) && this.pDialog.isShowing()) {
this.pDialog.dismiss();
}
} catch (final IllegalArgumentException e) {
// Handle or log or ignore
} catch (final Exception e) {
// Handle or log or ignore
} finally {
this.pDialog = null;
}
super.onPostExecute(result);
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
}
try this :
#Override
public Object onRetainNonConfigurationInstance() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog = null;
}
if (asynTask!= null) {
asynTask.detach();
}
return ayncTask;
}
Declaring a non-static inner AsyncTask in your activity is not a good idea because it holds a reference to the activity and this could be a couse of the leak. However, various configuration changes could cause the OS to destroy and recreate the activity. There are a number of solutions and Rustam's anser is an example.
However, I prefer to user either AsyncTaskLoader or use some sort of asynchronous callback, like a broadcast. The asynchronous callback decouples your AsyncTask from the Activity.
I am taking pictures in the background inside my Android App. However it gives an error:
02-09 15:22:12.061: E/cheeta(28633): timer testing
02-09 15:22:13.546: W/System.err(28633): java.lang.RuntimeException: takePicture failed
02-09 15:22:13.546: W/System.err(28633): at android.hardware.Camera.native_takePicture(Native Method)
02-09 15:22:13.546: W/System.err(28633): at android.hardware.Camera.takePicture(Camera.java:1194)
02-09 15:22:13.551: W/System.err(28633): at cam.sharp.MainActivity$MyTimerTask.run(MainActivity.java:69)
02-09 15:22:13.551: W/System.err(28633): at java.util.Timer$TimerImpl.run(Timer.java:284)
02-09 15:22:13.551: E/cheeta(28633): timer testing
02-09 15:22:15.051: W/System.err(28633): java.lang.RuntimeException: takePicture failed
02-09 15:22:15.051: W/System.err(28633): at android.hardware.Camera.native_takePicture(Native Method)
02-09 15:22:15.051: W/System.err(28633): at android.hardware.Camera.takePicture(Camera.java:1194)
02-09 15:22:15.051: W/System.err(28633): at cam.sharp.MainActivity$MyTimerTask.run(MainActivity.java:69)
02-09 15:22:15.051: W/System.err(28633): at java.util.Timer$TimerImpl.run(Timer.java:284)
02-09 15:22:15.051: E/cheeta(28633): timer testing
02-09 15:22:16.551: W/System.err(28633): java.lang.RuntimeException: takePicture failed
02-09 15:22:16.556: W/System.err(28633): at android.hardware.Camera.native_takePicture(Native Method)
02-09 15:22:16.556: W/System.err(28633): at android.hardware.Camera.takePicture(Camera.java:1194)
02-09 15:22:16.561: W/System.err(28633): at cam.sharp.MainActivity$MyTimerTask.run(MainActivity.java:69)
02-09 15:22:16.561: W/System.err(28633): at java.util.Timer$TimerImpl.run(Timer.java:284)
02-09 15:22:16.561: E/cheeta(28633): timer testing
I have two files.
MainActivity.java and CameraPreview.java
Here is the code for both.
MainActivity.java
package cam.sharp;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.Toast;
public class MainActivity extends Activity {
private int cameraId = 0;
private Camera mCamera;
private CameraPreview mPreview;
String fileName = "tempImage.jpeg";
File file;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create an instance of Camera
mCamera = getCameraInstance(cameraId);
if (mCamera == null) {
Toast.makeText(
getApplicationContext(),
"The camera service is currently unavailable, please try again!",
Toast.LENGTH_LONG).show();
finish();
} else {
// Create our Preview view and set it as the content of our
// activity.
mPreview = new CameraPreview(this, mCamera);
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.camera_preview);
frameLayout.addView(mPreview);
}
// start thread for these
MyTimerTask myTask = new MyTimerTask();
Timer myTimer = new Timer();
// public void schedule (TimerTask task, long delay, long period)
// Schedule a task for repeated fixed-delay execution after a specific
// delay.
//
// Parameters
// task the task to schedule.
// delay amount of time in milliseconds before first execution.
// period amount of time in milliseconds between subsequent executions.
myTimer.schedule(myTask, 3000, 1500);
}
class MyTimerTask extends TimerTask {
public void run() {
try {
mCamera.takePicture(null, null, null, mPictureCallback);
file = new File(getFilesDir(), fileName);
} catch (Exception e) {
e.printStackTrace();
}
Log.e("cheeta", "timer testing");
}
}
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {
Log.e("Callback TAG", "Here in jpeg Callback");
if (imageData != null) {
FileOutputStream outputStream;
try {
outputStream = openFileOutput(fileName,
Context.MODE_PRIVATE);
outputStream.write(imageData);
outputStream.close();
// Intent intent = new Intent(SnapScreen.this,
// PreviewScreen.class);
// if (fromMessageReview == true) {
// intent.putExtra("fromMessageReview", "true");
// }
// startActivity(intent);
// overridePendingTransition(R.anim.slide_in,
// R.anim.slide_out);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
#Override
protected void onDestroy() {
super.onDestroy();
releaseCamera();
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(int cameraId) {
Camera c = null;
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
c = Camera.open(cameraId);
} else {
c = Camera.open();
}
} catch (Exception e) {
c = null;
}
return c; // returns null if camera is unavailable
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release(); // release the camera for other applications
mCamera = null;
}
}
}
CameraPreview.java
package cam.sharp;
import java.io.IOException;
import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
/** A basic Camera preview class */
#SuppressLint("ViewConstructor")
public class CameraPreview extends SurfaceView implements
SurfaceHolder.Callback {
private static final String TAG = "Camera Preview";
private SurfaceHolder mHolder;
public Camera mCamera;
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mCamera.setDisplayOrientation(90);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the
// preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}
Can anyone see what is the issue? I am calling mCamera.startPreview(); but still no use.
Thanks
You have 2 problems in your code:
First: In your onPictureTaken call back you are calling the finish() method, wich in turn signals that the activity should be destroyed, and calls the onDestroy() method, wich in turn releases your camera. However your MainActivity.java is not destroyed (not really sure why, but through logCat, I found that the onCreate() is only being called once, so I assumed the activity is not destroyed. A possible explanation for this might be that the Timer is controlled by a diferent thread and as such might not be aware that the MainActivity was destroyed, but I can't confirm), and so your myTimer will continue to run, and when it gets to mCamera.takePicture(null, null, null, mPictureCallback); it will throw a NullPointException because the camera was already released, and the MainActivity.onCreate() wasn't called again to get a new instance to mCamera.
So, to solve the first problem:
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] imageData, Camera c) {
Log.e("Callback TAG", "Here in jpeg Callback");
if (imageData != null) {
FileOutputStream outputStream = null;
try {
outputStream = openFileOutput(fileName, Context.MODE_PRIVATE);
outputStream.write(imageData);
// Removed the finish call you had here
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null) try {
outputStream.close();
} catch (IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
}
}
};
Second: Is where you call your startPreview() method. Accooding to the documentation of takePicture():
This method is only valid when preview is active (after
startPreview()). Preview will be stopped after the image is taken;
callers must call startPreview() again if they want to re-start
preview or take more pictures. This should not be called between
start() and stop().
You were only calling startPreview() once, when you create the camera, and because of problem 1, the onCreate() on MainActivity is only being called once. Since you have a timer taking pictures every 1.5 seconds, you should call startPreview() before calling takePicture(), so to solve this:
class MyTimerTask extends TimerTask {
public void run() {
try {
// Call startPreview before taking a picture
mCamera.startPreview();
mCamera.takePicture(null, null, null, mPictureCallback);
file = new File(getFilesDir(), fileName);
} catch (NullPointerException ne) {
ne.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Log.e("cheeta", "timer testing");
}
}
After this the app continuasly takes pictures, and stores them. I never used a Timer like that so Im not sure how to make it stop. If you only want a small number of pictures taken within each call to the CameraPreview Activity I suggest you use a Timer with an action listener, like so:
Timer tm = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Take x pictures
tm.stop();
}
});
I'm am trying to capture an image in the ontouchevent of surfaceview. However, everytime a touch the screen, the app crashes with the following exception:
01-05 21:03:18.500: ERROR/AndroidRuntime(10367): FATAL EXCEPTION: main
java.lang.RuntimeException: takePicture failed
at android.hardware.Camera.native_takePicture(Native Method)
at android.hardware.Camera.takePicture(Camera.java:1126)
at android.hardware.Camera.takePicture(Camera.java:1071)
at com.test.MotionDetector.CameraSurfaceView.onTouchEvent(CameraSurfaceView.java:107)
at android.view.View.dispatchTouchEvent(View.java:7350)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2151)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1480)
at android.app.Activity.dispatchTouchEvent(Activity.java:2469)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2099)
at android.view.View.dispatchPointerEvent(View.java:7535)
at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3492)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3424)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4534)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4512)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4616)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:125)
at android.os.Looper.loop(Looper.java:124)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
My code:
package com.nadim.MotionDetector;
import android.content.Context;
import android.hardware.Camera;
import android.os.Environment;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private Context context;
public CameraSurfaceView(Context context, Camera camera) {
super(context);
this.context = context;
mCamera = camera;
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, now tell the camera where to draw the preview.
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d("MotionDetector", "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// empty. Take care of releasing the Camera preview in your activity.
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
if (mHolder.getSurface() == null) {
// preview surface does not exist
return;
}
// stop preview before making changes
try {
mCamera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
// set preview size and make any resize, rotate or
// reformatting changes here
// start preview with new settings
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.d("MotionDetector", "Error starting camera preview: " + e.getMessage());
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
Toast.makeText(context, "Picture taken", Toast.LENGTH_SHORT).show();
//System.gc(); tried this because it was suggested in a stackoverflow question but it didn't help.
mCamera.takePicture(null, mPicture, mPicture);
return true; //processed
}
private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.d("MotionDetector", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("MotionDetector", "Error accessing file: " + e.getMessage());
}
}
};
private static File getOutputMediaFile() {
File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "motiondetect");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir, timeStamp + ".jpg");
return mediaFile;
}
}
Permissions and features used:
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-feature android:name="android.hardware.camera.flash" />
I don't know why the crash occurs. Many other topic suggest calling Camera.startPreview first. I am doing that, but it doesn't solve the issue.
LogCat before taking picture:
01-05 21:45:57.667: WARN/ActivityManager(754): No content provider found for permission revoke: file:///data/local/tmp/com.test.MotionDetector
01-05 21:45:57.667: WARN/ActivityManager(754): No content provider found for permission revoke: file:///data/local/tmp/com.test.MotionDetector
01-05 21:45:57.687: INFO/ActivityManager(754): Force stopping com.test.MotionDetector appid=10103 user=-1: uninstall pkg
01-05 21:45:57.687: INFO/ActivityManager(754): Killing 4264:com.test.MotionDetector/u0a103 (adj 7): stop com.test.MotionDetector
01-05 21:45:57.687: INFO/ActivityManager(754): Force finishing activity ActivityRecord{437a6678 u0 com.test.MotionDetector/.MotionDetectActivity t144}
01-05 21:45:57.697: WARN/InputDispatcher(754): channel '42adff40 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9
01-05 21:45:57.697: ERROR/InputDispatcher(754): channel '42adff40 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
01-05 21:45:57.697: WARN/InputDispatcher(754): Attempted to unregister already unregistered input channel '42adff40 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity (server)'
01-05 21:45:57.697: INFO/WindowState(754): WIN DEATH: Window{42adff40 u0 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity}
01-05 21:45:57.757: INFO/PackageManager(754): Running dexopt on: com.test.MotionDetector
01-05 21:45:57.757: INFO/PackageManager(754): Package com.test.MotionDetector codePath changed from /data/app/com.test.MotionDetector-1.apk to /data/app/com.test.MotionDetector-2.apk; Retaining data and using new
01-05 21:45:57.807: INFO/ActivityManager(754): Force stopping com.test.MotionDetector appid=10103 user=-1: update pkg
01-05 21:45:57.807: WARN/PackageManager(754): Code path for pkg : com.test.MotionDetector changing from /data/app/com.test.MotionDetector-1.apk to /data/app/com.test.MotionDetector-2.apk
01-05 21:45:57.807: WARN/PackageManager(754): Resource path for pkg : com.test.MotionDetector changing from /data/app/com.test.MotionDetector-1.apk to /data/app/com.test.MotionDetector-2.apk
01-05 21:45:57.937: INFO/ActivityManager(754): Force stopping com.test.MotionDetector appid=10103 user=0: pkg removed
01-05 21:45:57.987: DEBUG/BackupManagerService(754): Received broadcast Intent { act=android.intent.action.PACKAGE_REMOVED dat=package:com.test.MotionDetector flg=0x4000010 (has extras) }
01-05 21:45:58.047: DEBUG/BackupManagerService(754): Received broadcast Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.test.MotionDetector flg=0x4000010 (has extras) }
01-05 21:45:58.567: INFO/Icing.InternalIcingCorporaProvider(12750): Updating corpora: A: com.test.MotionDetector, C: MAYBE
01-05 21:45:58.647: DEBUG/PackageAddedReceiver(1086): package added com.test.MotionDetector
01-05 21:45:58.737: INFO/ActivityManager(754): START u0 {flg=0x10000000 cmp=com.test.MotionDetector/.MotionDetectActivity} from pid 4578
01-05 21:45:58.777: INFO/ActivityManager(754): Start proc com.test.MotionDetector for activity com.test.MotionDetector/.MotionDetectActivity: pid=4630 uid=10103 gids={50103, 1028, 1015}
01-05 21:45:59.627: INFO/ActivityManager(754): Displayed com.test.MotionDetector/.MotionDetectActivity: +861ms (total +972ms)
01-05 21:45:59.657: INFO/WindowManager(754): Screen frozen for +869ms due to Window{43cb77a8 u0 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity}
Assuming that you want the jpeg saved, you don't need raw callback, so
change the call to takePicture() from:
mCamera.takePicture(null, mPicture, mPicture);
to
mCamera.takePicture(null, null, mPicture);
in your onTouchEvent(). This will use jpeg picture callback.
Calling takePicture() also causes the preview to stop, so you might want to call startPreview() again in your onPictureTaken() callback, if you want to take more pictures or have a preview restarted.
Also, in your onTouchEvent(), you might be getting multiple events, so filter for the one that works for you:
#Override
public boolean onTouchEvent(MotionEvent event) {
Toast.makeText(context, "Picture taken", Toast.LENGTH_SHORT).show();
//System.gc(); tried this because it was suggested in a stackoverflow question but it didn't help.
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// A pressed gesture has started, the motion contains the initial starting location
break;
case MotionEvent.ACTION_UP:
// A pressed gesture has finished, the motion contains the final release location
// as well as any intermediate points since the last down or move event.
mCamera.takePicture(null, mPicture, mPicture);
break;
default:
break;
}
return true; //processed
}
If you place takePicture() in ACTION_DOWN, it will be called as soon as you touch the screen, whereas when in ACTION_UP, it will happen when you remove finger. See which one works for you.