web-dev-qa-db-fra.com

Android se brisant après l'objectif de la caméra

J'ai une application publiée et l'une des fonctionnalités fondamentales est de permettre à l'utilisateur de prendre une photo, puis de l'enregistrer dans un dossier spécifique de son stockage externe. 

Tout semble bien fonctionner, mais j'ai maintenant deux rapports qui prétendent qu'après avoir pris une photo et cliqué sur "Terminé" pour quitter l'appareil photo (et revenir à l'activité), l'application est fermée de force, ce qui amène l'utilisateur retour à l'écran d'accueil. 

Cela se produit sur un Samsung Nexus S et le Galaxy Tab. Ci-dessous, j'ai posté mon code pour montrer que je définissais mon intention et comment je gérais l'enregistrement et l'affichage de la photo dans onActivityResult (). Toute indication sur ce qui pourrait provoquer son blocage après avoir cliqué sur "Terminé" pour quitter l'application pour appareil photo serait grandement appréciée! 

Encore une fois, cela semble bien fonctionner sur la plupart des appareils, mais je me demandais si leur approche serait plus efficace et universelle. Je vous remercie

Comment je tire la caméra

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

Comment je configure 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);


    }

}
19
Jade Byfield

Tout d’abord, précisons: nous avons deux options pour prendre des données d’image dans onActivityResult from Camera:

1. Démarrez l'appareil photo en passant l'adresse Uri exacte de l'image où vous souhaitez enregistrer.

2. Il suffit de démarrer l'appareil photo pour ne laisser passer aucun Uri en loaction.


1 . EN PREMIER CAS:

Démarrez Caméra en passant l'image Uri où vous souhaitez enregistrer:

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

Dans onActivityResult, recevez l'image en tant que:

@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. DANS UN SECOND CAS:

Démarrez Appareil photo sans passer d'image Uri, si vous souhaitez recevoir une image dans Intention (données):

Intent it = new Intent(Android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
startActivityForResult(it, CAMERA_RESULT); 

Dans onActivityResult recive image en tant que: 

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


***** Bon codage !!!! *****

33
ρяσѕρєя K

Sur l'événement de clic du bouton de la caméra, vous pouvez essayer ceci:

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;

Ajoutez la fonction getTempFile dans le code, ce qui vous aidera à enregistrer l'image nommée myImage.png sur laquelle vous avez cliqué dans la carte mémoire sous le dossier nommé en tant que nom de package de votre application.

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

Maintenant sur la fonction OnActivityResult, ajoutez ceci:

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

au cas où vous auriez des problèmes de mémoire, ajoutez le code ci-dessous:

@Override
    protected void onPause() {
        image.setImageURI(null);
        super.onPause();
    }

J'espère que cela t'aidera

4
AkashG

Je suspecte que 3 problèmes possibles aient pu créer votre problème:

  1. Certains périphériques renvoient null lorsque vous appelez extras.get("data"); dans la méthode onActivityResult afin que votre problème puisse être un NullPointerException. Pour résoudre ce problème, vous devez indiquer l'emplacement exact URI pour indiquer à l'application de caméra où vous souhaitez le stocker et l'utiliser dans onActivityResult pour récupérer l'image en tant que Bitmap.

  2. Certains autres périphériques renvoient un Bitmap de taille normale lorsque extras.get("data"); dans onActivityResult. Si le bitmap est trop volumineux, OutOfMemmoryError peut en résulter, vous devrez peut-être décoder votre image dans un format plus petit pour ne pas prendre autant de mémoire. Ces deux liens peuvent vous aider dans cette situation:

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

    MOO BitmapFactory me rend fou

  3. Votre activité est peut-être détruite par GC et vous devez donc utiliser onSavedInstanceState et onRestoreInstanceState pour enregistrer les données de votre Activity. Voir la réponse de ce post précédent pour plus d'informations.

Je ne sais pas si vous avez déjà traité ces problèmes.

J'espère que cela pourra aider:)

3
Angelo

Tout d’abord, assurez-vous de vérifier le code de la demande, vous pourriez peut-être y trouver le résultat de quelqu'un d’autre. Deuxièmement, n'utilisez pas le bitmap de données de l'intention - si tant est que ce soit, c'est petit, mais puisque vous fournissez le chemin pour stocker l'image capturée, il ne devrait même pas être là (voir ici ). Donc, stockez l'URL que vous avez fournie comme chemin du fichier de sortie et lisez Bitmap à partir de là lorsque vous aurez reçu RESULT_OK pour la requête :

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

Bonjour tout ce que je sais réponse a été donnée mais comme c'est aussi l'une des solution la plus simple que j'ai jamais trouvée

Voici l'exemple qui se préoccupe de l'appareil!

AndroidCameraUtils - Téléchargez le projet et à partir du projet de la bibliothèque en l'incluant ci-dessous. L'extrait de code que vous pouvez utiliser!

privé void setupCameraIntentHelper () { mcameraIntentHelper = nouveau CameraIntentHelper (ceci, nouveau CameraIntentHelperCallback () { @Override .__ 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);
}
}

NOTE: - J'ai essayé de nombreux exemples pour les utilités de la caméra et bien sûr, il existe un autre moyen de le gérer, mais pour les débutants et les personnes qui ne sont pas très familières avec les concepts de base, ce projet serait plus confortable. Merci!

0
Hardy

Suivez les étapes indiquées sur ce lien - link . J'espère que cela vous sera utile.

OR

Récupérer votre image sans planter

Ecrivez le code ci-dessous dans 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); 
}
0
Kailas

J'ai fait face au même problème. Apparemment, la solution consiste à rendre uriSavedImage statique. Je ne sais pas si c'est le meilleur moyen. Mais cela fonctionne pour moi.

0
san