私はアプリを公開していますが、基本的な機能の1つは、ユーザーが写真を撮って、その写真を外部ストレージの特定のフォルダーに保存できるようにすることです。
すべてが正常に動作しているようですが、写真を撮り、[完了]をクリックしてカメラを終了(そしてアクティビティに戻る)すると、アプリが強制的に閉じられ、ユーザーが表示されるという報告が2件ありますホーム画面に戻ります。
これは、Samsung Nexus SとGalaxy Tabで発生します。以下に、インテントを設定したことと、onActivityResult()で写真を保存および表示する方法を示すコードを掲載しました。カメラアプリを終了するために[完了]をクリックした後、クラッシュの原因となる可能性があることについてのガイダンスをいただければ幸いです。
繰り返しますが、これはほとんどのデバイスで正常に機能しているようですが、それらが私が取るべきもっと効率的で普遍的なアプローチであるかどうか疑問に思っていました。ありがとうございました
カメラインテントを起動する方法
case ACTION_BAR_CAMERA:
// numbered image name
fileName = "image_" + String.valueOf(numImages) + ".jpg";
output = new File(direct + File.separator + fileName); // create
// output
while (output.exists()) { // while the file exists
numImages++; // increment number of images
fileName = "image_" + String.valueOf(numImages) + ".jpg";
output = new File(outputFolder, fileName);
}
camera = new Intent(Android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
uriSavedImage = Uri.fromFile(output); // get Uri of the output
camera.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage); //pass in Uri to camera intent
startActivityForResult(camera, 1);
break;
default:
return super.onHandleActionBarItemClick(item, position);
}
return true;
}
OnActivityResult()の設定方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) { // If data was passed successfully
Bundle extras = data.getExtras();
//Bundle extras = data.getBundleExtra(MediaStore.EXTRA_OUTPUT);
/*ad = new AlertDialog.Builder(this).create();
ad.setIcon(Android.R.drawable.ic_menu_camera);
ad.setTitle("Save Image");
ad.setMessage("Save This Image To Album?");
ad.setButton("Ok", this);
ad.show();*/
bmp = (Bitmap) extras.get("data"); // Set the bitmap to the bundle
// of data that was just
// received
image.setImageBitmap(bmp); // Set imageview to image that was
// captured
image.setScaleType(ScaleType.FIT_XY);
}
}
最初にそれを明確にしましょう-カメラからonActivityResultで画像データを取得する2つのオプションがあります。
1。保存する画像の正確な場所Uriを渡してカメラを開始します。
2。カメラを起動するだけでLoaction Uriを渡さない
1。最初のケースでは:
保存したい場所に画像Uriを渡してカメラを起動します。
String imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/picture.jpg";
File imageFile = new File(imageFilePath);
Uri imageFileUri = Uri.fromFile(imageFile); // convert path to Uri
Intent it = new Intent(Android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
it.putExtra(Android.provider.MediaStore.EXTRA_OUTPUT, imageFileUri);
startActivityForResult(it, CAMERA_RESULT);
OnActivityResultで次のように画像を受け取ります。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (RESULT_OK == resultCode) {
iv = (ImageView) findViewById(R.id.ReturnedImageView);
// Decode it for real
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = false;
//imageFilePath image path which you pass with intent
Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
// Display it
iv.setImageBitmap(bmp);
}
}
2。2番目のケース:
Intent(data)で画像を受け取りたい場合は、画像Uriを渡さずにカメラを起動します。
Intent it = new Intent(Android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(it, CAMERA_RESULT);
OnActivityResultでは、画像を次のように受け取ります。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (RESULT_OK == resultCode) {
// Get Extra from the intent
Bundle extras = data.getExtras();
// Get the returned image from extra
Bitmap bmp = (Bitmap) extras.get("data");
iv = (ImageView) findViewById(R.id.ReturnedImageView);
iv.setImageBitmap(bmp);
}
}
カメラボタンのクリックイベントで、これを試すことができます。
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(getTempFile(this)));
startActivityForResult(intent, TAKE_PHOTO_CODE);
declare TAKE_PHOTO_CODE globally as:
private static final int TAKE_PHOTO_CODE = 1;
コードにgetTempFile関数を追加します。これは、アプリのパッケージ名として指定されたフォルダーの下のsdcardでクリックしたmyImage.pngという名前の画像を保存するのに役立ちます。
private File getTempFile(Context context) {
final File path = new File(Environment.getExternalStorageDirectory(),
context.getPackageName());
if (!path.exists()) {
path.mkdir();
}
return new File(path, "myImage.png");
}
OnActivityResult関数にこれを追加します。
if (requestCode == TAKE_PHOTO_CODE) {
final File file = getTempFile(this);
try {
Uri uri = Uri.fromFile(file);
Bitmap captureBmp = Media.getBitmap(getContentResolver(),
uri);
image.setImageBitmap(captureBmp);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
メモリの問題が発生した場合は、以下のコードを追加してください:
@Override
protected void onPause() {
image.setImageURI(null);
super.onPause();
}
これがお役に立てば幸いです
3つの考えられる問題があなたの問題を引き起こしたと思われます:
一部のデバイスは、null
メソッドでextras.get("data");
を呼び出すとonActivityResult
を返すため、問題はNullPointerException
になる可能性があります。これを解決するには、正確なURI
の場所を渡して、カメラアプリに保存場所を伝え、onActivityResult
で使用して画像をBitmap
として取得する必要があります。 。
他の一部のデバイスは、Bitmap
内のextras.get("data");
のときにフルサイズonActivityResult
を返します。ビットマップが大きすぎてOutOfMemmoryError
が発生する可能性がある場合は、画像を小さいサイズでデコードして、メモリヒープをあまり消費しないようにする必要があります。この2つのリンクは、この状況で役立ちます。
http://developer.Android.com/training/displaying-bitmaps/load-bitmap.html
多分あなたの活動はGC
によって破壊されるので、onSavedInstanceState
とonRestoreInstanceState
を使用してActivity
のデータを保存する必要があります。詳細は この以前の投稿 の回答を参照してください。
あなたがすでにこれらの問題に対処したかどうかはわかりません。
それが役に立てば幸い:)
まず、リクエストコードを確認してください。他の誰かの結果をそこにキャッチしている可能性があります。次に、インテントのデータビットマップを使用しないでください-どちらかといえば小さいですが、キャプチャした画像を保存するパスを提供するため、そこに存在することはできません( ここ を参照)。したがって、yourリクエストのRESULT_OKを受け取ったときに、出力ファイルパスとして提供したURLを保存し、そこからビットマップを読み取ります。
...
// save your file uri, not necessarily static
mUriSavedImage = Uri.fromFile(output);
startActivityForResult(camera, MY_REQUEST_CODE);
/* Make a String like "com.myname.MY_REQUEST_CODE" and hash it into int to give it
a bit of uniqueness */
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Bitmap bmp = BitmapFactory.decodeFile(mUriSavedImage);
if (bmp != null) {
image.setImageBitmap(bmp); // Set imageview to image that was
// captured
image.setScaleType(ScaleType.FIT_XY);
} else {
Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
こんにちは私は答えが出たことを知っていますが、これも私が見つけた最も簡単な解決策の一つなので
これは、デバイス自体を悩ませている例です。
AndroidCameraUtils -プロジェクトをダウンロードし、ライブラリプロジェクトから以下に含めることで、使用できるコードスニペットです!
private void setupCameraIntentHelper() {
mCameraIntentHelper = new CameraIntentHelper(this, new CameraIntentHelperCallback() {
@Override
public void onPhotoUriFound(Date dateCameraIntentStarted, Uri photoUri, int rotateXDegrees) {
messageView.setText(getString(R.string.activity_camera_intent_photo_uri_found) + photoUri.toString());
Bitmap photo = BitmapHelper.readBitmap(CameraIntentActivity.this, photoUri);
if (photo != null) {
photo = BitmapHelper.shrinkBitmap(photo, 300, rotateXDegrees);
ImageView imageView = (ImageView) findViewById(de.ecotastic.Android.camerautil.sample.R.id.activity_camera_intent_image_view);
imageView.setImageBitmap(photo);
}
}
@Override
public void deletePhotoWithUri(Uri photoUri) {
BitmapHelper.deleteImageWithUriIfExists(photoUri, CameraIntentActivity.this);
}
@Override
public void onSdCardNotMounted() {
Toast.makeText(getApplicationContext(), getString(R.string.error_sd_card_not_mounted), Toast.LENGTH_LONG).show();
}
@Override
public void onCanceled() {
Toast.makeText(getApplicationContext(), getString(R.string.warning_camera_intent_canceled), Toast.LENGTH_LONG).show();
}
@Override
public void onCouldNotTakePhoto() {
Toast.makeText(getApplicationContext(), getString(R.string.error_could_not_take_photo), Toast.LENGTH_LONG).show();
}
@Override
public void onPhotoUriNotFound() {
messageView.setText(getString(R.string.activity_camera_intent_photo_uri_not_found));
}
@Override
public void logException(Exception e) {
Toast.makeText(getApplicationContext(), getString(R.string.error_sth_went_wrong), Toast.LENGTH_LONG).show();
Log.d(getClass().getName(), e.getMessage());
}
});
}
@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
mCameraIntentHelper.onSaveInstanceState(savedInstanceState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mCameraIntentHelper.onRestoreInstanceState(savedInstanceState);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
mCameraIntentHelper.onActivityResult(requestCode, resultCode, intent);
}
}
[〜#〜]ノート[〜#〜]:-私はカメラユーティリティの多くの例を試しましたが、もちろん、初心者のためにそれを処理する別の方法がありますコアコンセプトにあまり慣れていない人は、このプロジェクトの方が快適です。ありがとう!
この link に記載されている手順に従ってください。これがあなたに役立つことを願っています。
OR
クラッシュせずに画像を取得する
MainActivityに以下のコードを記述します
// Storage for camera image URI components
private final static String CAPTURED_PHOTO_PATH_KEY = "mCurrentPhotoPath";
private final static String CAPTURED_PHOTO_URI_KEY = "mCapturedImageURI";
// Required for camera operations in order to save the image file on resume.
private String mCurrentPhotoPath = null;
private Uri mCapturedImageURI = null;
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
if (mCurrentPhotoPath != null) {
savedInstanceState.putString(CAPTURED_PHOTO_PATH_KEY, mCurrentPhotoPath);
}
if (mCapturedImageURI != null) {
savedInstanceState.putString(CAPTURED_PHOTO_URI_KEY, mCapturedImageURI.toString());
}
super.onSaveInstanceState(savedInstanceState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState.containsKey(CAPTURED_PHOTO_PATH_KEY)) {
mCurrentPhotoPath = savedInstanceState.getString(CAPTURED_PHOTO_PATH_KEY);
}
if (savedInstanceState.containsKey(CAPTURED_PHOTO_URI_KEY)) {
mCapturedImageURI = Uri.parse(savedInstanceState.getString(CAPTURED_PHOTO_URI_KEY));
}
super.onRestoreInstanceState(savedInstanceState);
}
私は同じ問題に直面しました。どうやら修正は、uriSavedImageを静的にすることです。これが最善の方法かどうかはわかりません。しかし、これは私にとってはうまくいきます。
Samsungデバイスの場合、AndroidManifest.xmlファイルの1行の下に追加します
Android:configChanges = "orientation | screenSize"
これがうまくいくことを願っています