Android сбой после камеры - программирование
Подтвердить что ты не робот

Android сбой после камеры

У меня опубликовано приложение, и одна из основных функций - позволить пользователю сделать снимок, а затем сохранить эту фотографию в определенной папке на своем внешнем хранилище.

Кажется, что все работает нормально, но теперь у меня есть два отчета, которые утверждают, что после съемки фотографии и нажатия кнопки "Готово", чтобы выйти из камеры (и вернуться к активности), приложение принудительно закрыто, возвращая пользователя на главный экран.

Это происходит на 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);


    }

}
4b9b3361

Ответ 1

Сначала давайте проясним - у нас есть две возможности взять данные изображения в onActivityResult из камеры:

1. Запустите камеру, передав точное местоположение Uri изображения, в котором вы хотите сохранить.

2. Просто запускайте камеру, не пропустите Loiation 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. Во втором случае:

Запустите камеру без передачи изображения Uri, если вы хотите получить изображение в Intent (data):

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); 
    } 
} 

<ч/" > ***** Счастливое кодирование!!!! *****

Ответ 2

На событии нажатия кнопки камеры вы можете попробовать следующее:

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 в код, который поможет сохранить изображение с именем myImage.png, которое вы нажали на SD-карте под папкой, названной именем вашего приложения.

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

Я подозреваю, что 3 проблемы могут создать вашу проблему:

  • Некоторые устройства возвращают null при вызове extras.get("data"); в onActivityResult, поэтому ваша проблема может быть NullPointerException. Чтобы решить эту проблему, вам необходимо передать точное местоположение URI, чтобы сообщить приложению камеры, где вы хотите его сохранить, и использовать его в onActivityResult, чтобы получить изображение как Bitmap.

  • Некоторые другие устройства возвращают полный размер Bitmap, когда extras.get("data"); в onActivityResult. Если растровое изображение слишком велико, что может привести к OutOfMemmoryError, возможно, вам нужно декодировать изображение меньшего размера, чтобы не взять столько кучи memmory. Эти две ссылки могут помочь вам в этой ситуации:

    http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

    BitmapFactory OOM заставляет меня орехи

  • Возможно, ваша активность уничтожена GC, поэтому вам нужно использовать onSavedInstanceState и onRestoreInstanceState для сохранения ваших данных Activity. Для получения дополнительной информации см. Ответ этого предыдущего сообщения.

Я не знаю, уже ли вы справлялись с этими проблемами.

Надеюсь, что помогает:)

Ответ 4

Во-первых, обязательно проверьте код запроса, возможно, вы поймаете кого-то другого. Во-вторых, не используйте целевые данные. Bitmap - если угодно, то он маленький, но поскольку вы предоставляете путь для хранения захваченного изображения, его даже не должно быть (см. здесь). Итак, сохраните URL-адрес, который вы предоставили в качестве выходного файла, и прочитайте Bitmap оттуда, когда вы получили RESULT_OK для вашего запроса:

    ...
    // 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);
    }
}

Ответ 5

Я столкнулся с той же проблемой. По-видимому, исправление заключается в том, чтобы сделать uriSavedImage статичным. Не уверен, что это лучший способ. Но это работает для меня.

Ответ 6

Следуйте инструкциям, приведенным в этой ссылке. Надеюсь, это полезно для вас.

ИЛИ

Получение изображения без сбоев

Введите приведенный ниже код в 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); 
}

Ответ 7

Привет всем, я знаю, что ответ был дан, но поскольку это также одно из самых простых решений, которые я когда-либо нашел

Вот пример, который сам беспокоит устройство!

AndroidCameraUtils - Загрузите проект и из проекта библиотеки, включив его ниже, это фрагмент кода, который вы можете использовать!

private void setupCameraIntentHelper() {   mCameraIntentHelper = новый CameraIntentHelper (это новый CameraIntentHelperCallback() {       @Override       public void onPhotoUriFound (Дата 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);
}
}

ПРИМЕЧАНИЕ: - Я пробовал много примеров для утилит камеры, и, конечно, есть другие способы справиться с этим, но для новичков и людей, которые не слишком знакомы с основными понятиями, было бы больше комфорта с этим проект. Спасибо!

Ответ 8

Для устройств Samsung добавьте одну строку в свой файл AndroidManifest.xml.

андроид: configChanges = "ориентация | Размер экрана"

я надеюсь, что это сработает для вас