Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android camera intent crashes app on some phones (about 20% of them)

I have done a lot of researching into this issue and have seen some great responses and found some good resources of "solutions" to this problem. Unfortunately however, I'm still encountering a lot of app crashes on certain devices. The crashes occur after someone has taken their photo and the camera intent is supposed to pass the info back to the calling activity. For the purposes of my app, I'm just overwriting any existing photo with the newly taken photo so I can use pretty much a static path to the file location. Here's how I call the intent:

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // get the file path from an external class (necessary for galaxy nexus)
        imageFileAndPath = ImageServices.getOutputImageFileUri(cont);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileAndPath);
        startActivityForResult(intent, CAMERA_REQUEST_CODE);

the imageFileAndPath is just a URI variable and I am creating it from a separate class because that resolved another issue where pressing "done" or the checkmark or w/e it is on the particular device to close the camera intent wasn't doing anything on several device types. By creating the URI from a separate class, it resolves that issue for some unknown reason.

my onActivityResult looks like this:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(resultCode == Activity.RESULT_OK)
    {
        if (requestCode == CAMERA_REQUEST_CODE) {
            setupImageView();
    imageView = (ImageView) findViewById(R.id.image_view);
            webView.setVisibility(View.GONE);
            imageView.setVisibility(View.VISIBLE);
            button.setVisibility(View.GONE);
            reTakePicButton.setVisibility(View.VISIBLE);
            rl.setVisibility(View.VISIBLE);    
        }
    }
}

because I don't need a dynamic path to save my photos (since it is overwriting existing photos), I just call another method within my activity that resizes the photo and rotates it accordingly. That method is below:

private void setupImageView() {     
    imageLocation = Environment.getExternalStorageDirectory().getAbsolutePath() + "/myappphoto/myappphoto.jpg";


    // Get the dimensions of the View
    Display display = getWindowManager().getDefaultDisplay();
    Point size = getDisplaySize(display);
    int targetW = size.x;

    // Get the dimensions of the bitmap
    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inJustDecodeBounds = true;

    BitmapFactory.decodeFile(imageLocation, bmOptions);
    int photoW = bmOptions.outWidth;
    int photoH = bmOptions.outHeight;

    // Determine how much to scale down the image
    int scaleFactor = Math.min(photoW / targetW, photoH / targetW);

    // Decode the image file into a Bitmap sized to fill the View
    bmOptions.inJustDecodeBounds = false;
    bmOptions.inSampleSize = scaleFactor;
    bmOptions.inPurgeable = true;

    Bitmap bitmap = BitmapFactory.decodeFile(imageLocation, bmOptions);
    int rotationForImage = getRotationForImage(imageLocation);
    if (rotationForImage != 0) {
        int targetWidth = rotationForImage == 90 || rotationForImage == 270 ? bitmap.getHeight() : bitmap.getWidth();
        int targetHeight = rotationForImage == 90 || rotationForImage == 270 ? bitmap.getWidth() : bitmap.getHeight();




        Bitmap rotatedBitmap = Bitmap.createBitmap(targetWidth, targetHeight, bitmap.getConfig());
        Canvas canvas = new Canvas(rotatedBitmap);
        Matrix matrix = new Matrix();
        matrix.setRotate(rotationForImage, bitmap.getWidth() / 2, bitmap.getHeight() / 2);
        canvas.drawBitmap(bitmap, matrix, new Paint());

        bitmap.recycle();
        bitmap = rotatedBitmap;

    }



    Bitmap resized;

    if(bitmap.getWidth() >= 900 || bitmap.getHeight() >=900)
    {
        int newWidth = Math.round(bitmap.getWidth()/2);
        int newHeight = Math.round(bitmap.getHeight()/2);
        resized = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
    }
    else
    {
        resized = bitmap;
    }
    //bitmap.recycle();
    bitmap = resized;


    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 70, bytes);

    try
    {
        File f = new File(imageLocation);
        f.createNewFile();
        //write the bytes in file
        FileOutputStream fo = new FileOutputStream(f);
        fo.write(bytes.toByteArray());
        fo.close();
    }
    catch(java.io.IOException e){}
    imageView.setImageBitmap(bitmap);

}

you can see the static path at the top of that method to the image file that is saved from the camera intent.

I suppose it's possible that the resizing, rotation method is causing the crashes, but I don't see why it would, that all looks like pretty standard java coding to me.

Can anyone see anything glaringly wrong with what I'm doing here? As I said in the title of this thread, my code is causing crashes on about 20% of the devices that run it which is unacceptable. I can handle 5% but not 20%.

I realize that android development is somewhat of a nightmare in this regard because you have to account for so many different device types (manufacturers, versions of android etc), but I would think the camera activity should be better standardized than this. As I said at the top of this thread, I have done a LOT of looking into this issue and seen several people with similar issues to mine but no good resolution that covers most devices. I really don't want to have to write (nor do I think I should have to write) my own camera from ground zero. There has to be a better implementation of the default, built-in camera intent on android devices...I just haven't been able to find it yet. As you can see, I'm not even concerned with dynamically creating images which should make this project a ton easier.

TIA

Edit: per the comment below, I have added a stacktrace from a failing camera. It looks like a null pointer exception. I took like 6 pictures, and kept going back using the button that calls the camera intent until finally got it to fail. Here's the stack trace:

STACK_TRACE
"java.lang.RuntimeException: Unable to resume activity {com.myapp/com.myapp.MyActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=904, result=-1, data=null} to activity {com.myapp/com.myapp.MyActivity}: java.lang.NullPointerException
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2124)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2139)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1672)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2836)
    at android.app.ActivityThread.access$1600(ActivityThread.java:117)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:130)
    at android.app.ActivityThread.main(ActivityThread.java:3687)
    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:842)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=904, result=-1, data=null} to activity {com.myapp/com.myapp.MyActivity}: java.lang.NullPointerException
    at android.app.ActivityThread.deliverResults(ActivityThread.java:2536)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2111)
    ... 13 more
Caused by: java.lang.NullPointerException
    at com.myapp.MyActivity.onActivityResult(EnterContest.java:257)
    at android.app.Activity.dispatchActivityResult(Activity.java:3908)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:2532)
    ... 14 more
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=904, result=-1, data=null} to activity {com.myapp/com.myapp.MyActivity}: java.lang.NullPointerException
    at android.app.ActivityThread.deliverResults(ActivityThread.java:2536)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2111)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2139)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1672)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2836)
    at android.app.ActivityThread.access$1600(ActivityThread.java:117)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:130)
    at android.app.ActivityThread.main(ActivityThread.java:3687)
    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:842)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
    at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
    at com.myapp.MyActivity.onActivityResult(EnterContest.java:257)
    at android.app.Activity.dispatchActivityResult(Activity.java:3908)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:2532)
    ... 14 more
java.lang.NullPointerException
    at com.myapp.MyActivity.onActivityResult(EnterContest.java:257)
    at android.app.Activity.dispatchActivityResult(Activity.java:3908)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:2532)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2111)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2139)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1672)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2836)
    at android.app.ActivityThread.access$1600(ActivityThread.java:117)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:939)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:130)
    at android.app.ActivityThread.main(ActivityThread.java:3687)
    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:842)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
    at dalvik.system.NativeStart.main(Native Method)
like image 616
Christopher Johnson Avatar asked Dec 26 '12 18:12

Christopher Johnson


1 Answers

Maybe a guess but I think I had the same problem, I fixed it reading the bitmap in a new AsyncTask and not in the UI thread.

The exception happened (apparently in a random way) calling

getContentResolver().notifyChange(selectedImage, null);

where selectedImage is the URI set before in

intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));

What were you calling in com.myapp.MyActivity.onActivityResult(EnterContest.java:257) ?

I have a stack trace collected with ACRA:

java.lang.RuntimeException: Unable to resume activity {com.infonair.meetme.app/com.infonair.meetme.activity.photo.TakePhotoActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=7898789, result=-1, data=Intent { dat=content://media/external/images/media/9 }} to activity {com.infonair.meetme.app/com.infonair.meetme.activity.photo.TakePhotoActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2126)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2141)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1674)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2838)
at android.app.ActivityThread.access$1600(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3737)
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:894)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=7898789, result=-1, data=Intent { dat=content://media/external/images/media/9 }} to activity {com.infonair.meetme.app/com.infonair.meetme.activity.photo.TakePhotoActivity}: java.lang.NullPointerException
at android.app.ActivityThread.deliverResults(ActivityThread.java:2538)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2113)
... 13 more
Caused by: java.lang.NullPointerException
at android.os.Parcel.readException(Parcel.java:1328)
at android.os.Parcel.readException(Parcel.java:1276)
at android.content.IContentService$Stub$Proxy.notifyChange(IContentService.java:458)
at android.content.ContentResolver.notifyChange(ContentResolver.java:912)
at android.content.ContentResolver.notifyChange(ContentResolver.java:898)
at com.infonair.meetme.activity.photo.TakePhotoActivity.onActivityResult(TakePhotoActivity.java:154)
at android.app.Activity.dispatchActivityResult(Activity.java:3908)
at android.app.ActivityThread.deliverResults(ActivityThread.java:2534)
... 14 more
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=7898789, result=-1, data=Intent { dat=content://media/external/images/media/9 }} to activity {com.infonair.meetme.app/com.infonair.meetme.activity.photo.TakePhotoActivity}: java.lang.NullPointerException
at android.app.ActivityThread.deliverResults(ActivityThread.java:2538)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2113)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2141)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1674)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2838)
at android.app.ActivityThread.access$1600(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3737)
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:894)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.os.Parcel.readException(Parcel.java:1328)
at android.os.Parcel.readException(Parcel.java:1276)
at android.content.IContentService$Stub$Proxy.notifyChange(IContentService.java:458)
at android.content.ContentResolver.notifyChange(ContentResolver.java:912)
at android.content.ContentResolver.notifyChange(ContentResolver.java:898)
at com.infonair.meetme.activity.photo.TakePhotoActivity.onActivityResult(TakePhotoActivity.java:154)
at android.app.Activity.dispatchActivityResult(Activity.java:3908)
at android.app.ActivityThread.deliverResults(ActivityThread.java:2534)
... 14 more
java.lang.NullPointerException
at android.os.Parcel.readException(Parcel.java:1328)
at android.os.Parcel.readException(Parcel.java:1276)
at android.content.IContentService$Stub$Proxy.notifyChange(IContentService.java:458)
at android.content.ContentResolver.notifyChange(ContentResolver.java:912)
at android.content.ContentResolver.notifyChange(ContentResolver.java:898)
at com.infonair.meetme.activity.photo.TakePhotoActivity.onActivityResult(TakePhotoActivity.java:154)
at android.app.Activity.dispatchActivityResult(Activity.java:3908)
at android.app.ActivityThread.deliverResults(ActivityThread.java:2534)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2113)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2141)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1674)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2838)
at android.app.ActivityThread.access$1600(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3737)
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:894)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)
at dalvik.system.NativeStart.main(Native Method)
like image 66
Testo Testini Avatar answered Oct 23 '22 10:10

Testo Testini