我已经对这个问题进行了大量的研究,并看到了一些很好的回复,并找到了一些“解决方案”的好资源。但遗憾的是,在某些设备上,我仍然遇到了很多应用程序崩溃的情况。在某人拍摄照片后,相机意图应该将信息传递回调用活动,但是崩溃发生了。为了我的应用程序的目的,我只是用新拍摄的照片覆盖任何现有的照片,因此我可以几乎使用静态路径来访问文件位置。以下是我调用意图的方式:
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);
imageFileAndPath只是一个URI变量,我从另一个类中创建它,因为这解决了在几种设备类型上按“完成”或选中特定设备上的检查标记或其他东西来关闭相机意图时没有任何反应的问题。通过从单独的类创建URI,它以某种未知的方式解决了这个问题。
我的onActivityResult代码如下:
@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);
}
}
}
由于我不需要动态路径来保存我的照片(因为它会覆盖现有的照片),所以我只需要在我的活动中调用另一个方法,对照片进行调整大小和旋转。该方法如下:
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);
}
在该方法的顶部,您可以看到指向从相机意图保存的图像文件的静态路径。
我想可能是调整大小,旋转方法导致崩溃,但我不明白为什么会这样,那看起来对我来说都是很标准的java编码。
有人能看到我在这里做错了什么吗?正如我在这个主题的标题中所说的那样,我的代码在大约20%运行它的设备上会导致崩溃,这是不可接受的。我可以应付5%,但不能应付20%。
我意识到在这方面进行Android开发有点儿恶心,因为您必须考虑到许多不同的设备类型(制造商,Android版本等),但是我认为相机活动应该比这更加标准化。就像我在本主题的开头所说的那样,我已经对此问题进行了很多研究,并且看到了几个与我的问题类似的人们,但没有一种好的解决方案可以涵盖大多数设备。我真的不想从零开始编写自己的相机(也不认为我应该从零开始编写),必须有更好的默认内置相机意图在Android设备上实现...我只是还没有找到它。正如您所见,我甚至不关心动态创建图像,这应该使这个项目更加容易。
谢谢您的帮助
编辑:根据下面的评论,我添加了一个失败相机的堆栈跟踪。看起来像一个空指针异常。我拍了六张照片,并一直使用调用相机意图的按钮返回,直到最终它崩溃了。以下是堆栈跟踪:
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()
中没有直接引发NullPointerException
的行。您正在运行其他实现的onActivityResult()
,我们无法知道它可能包含什么,更不用说为什么会崩溃了。 - CommonsWare