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)
onActivityResult()
that you have here that could raise aNullPointerException
. You are running some other implementation ofonActivityResult()
, and we have no way of knowing what that might contain, let alone why it might be crashing. – Cay