私はこの問題について多くの調査を行い、いくつかの素晴らしい反応を見て、この問題の「解決策」のいくつかの優れたリソースを見つけました。ただし、残念ながら、特定のデバイスでまだ多くのアプリのクラッシュが発生しています。クラッシュは、誰かが写真を撮った後に発生し、カメラの意図が情報を呼び出し元のアクティビティに返すことになっています。アプリの目的上、既存の写真を新しく撮影した写真で上書きするだけなので、ファイルの場所への静的パスをほぼ使用できます。これが私がインテントと呼ぶ方法です:
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デバイスでのデフォルトの組み込みカメラインテントのより良い実装が必要です...私はまだそれを見つけることができませんでした。ご覧のとおり、このプロジェクトを非常に簡単にする画像を動的に作成することすら気にしません。
TIA
編集:以下のコメントに従って、故障したカメラからのスタックトレースを追加しました。nullポインタ例外のように見えます。私は6枚の写真を撮り、最終的に失敗するまでカメラインテントを呼び出すボタンを使用して戻り続けました。スタックトレースは次のとおりです。
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)