web-dev-qa-db-fra.com

Android: comment écrire l'intention de la caméra dans le nougat Android

Dans mon application Android, je dois prendre des images à l'aide de l'appareil photo en cliquant sur un bouton.Il fonctionne parfaitement dans toutes les versions d'Android sauf Android 7 (Nougat). problème est dans la caméra appelant l'intention.Below est mon code.

    camera = (ImageView) dialog.findViewById(R.id.camera);

camera.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        clickCamera();
        dialog.dismiss();
    }
});

private void clickCamera() { // 1 for icon and 2 for attachment
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.CAMERA},MY_REQUEST_CODE);
    }else {
        if (ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_REQUEST_CODE_STORAGE);
        }else{
            currentImageUri = getImageFileUri();
            Intent intentPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intentPicture.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri); // set the image file name
            // start the image capture Intent
            startActivityForResult(intentPicture, REQUEST_CAMERA);  // 1 for REQUEST_CAMERA and 2 for REQUEST_CAMERA_ATT
        }
    }
}

private static Uri getImageFileUri(){
    // Create a storage directory for the images
    // To be safe(er), you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this

    imagePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyProject");
    if (! imagePath.exists()){
        if (! imagePath.mkdirs()){
            return null;
        }else{
            //create new folder
        }
    }

    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File image = new File(imagePath,"MyProject_"+ timeStamp + ".jpg");

    if(!image.exists()){
        try {
            image.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // Create an File Uri
    return Uri.fromFile(image);
}


@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_REQUEST_CODE: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // permission was granted, yay! Do the
            // contacts-related task you need to do.
                if (ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_REQUEST_CODE_STORAGE);
                }else{
                    currentImageUri = getImageFileUri();
                    Intent intentPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    intentPicture.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri); // set the image file name
                    // start the image capture Intent
                    startActivityForResult(intentPicture, REQUEST_CAMERA);
                }
            } else {
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
                Toast.makeText(this,"Doesn't have permission... ", Toast.LENGTH_SHORT).show();
            }
            return;
        }
        case MY_REQUEST_CODE_STORAGE : {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                currentImageUri = getImageFileUri();
                Intent intentPicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                intentPicture.putExtra(MediaStore.EXTRA_OUTPUT, currentImageUri); // set the image file name
                // start the image capture Intent
                startActivityForResult(intentPicture, REQUEST_CAMERA);
            } else {
                // permission denied, boo! Disable the
                // functionality that depends on this permission.
                Toast.makeText(this,"Doesn't have permission...", Toast.LENGTH_SHORT).show();
            }
            return;
        }
    }
}

Quel était le problème ici pour Nougat? Est-ce à cause de l'URI renvoyé par getImageFileUri () ?? S'il vous plaît aidez-moi à résoudre ce problème.

7
KJEjava48

Hé s'il vous plaît suivre ce fil comme référence. Il vous montrera comment utiliser Fournisseur de fichiers lorsque vous définissez votre targetSDK sur 24 et que vous modifiez les opérations suivantes. Dans votre méthode private static Uri getImageFileUri() 

Changer cette ligne 

return Uri.fromFile(image);

à

FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".provider", createImageFile());

J'espère que cela vous aidera à résoudre votre problème .
Pour plus, allez à - Configuration du partage de fichiers - Documentation officielle

6
android_griezmann

Essayez ceci, ce n’est pas l’intention qui crée le problème une fois que vous avez pris la photo, sauvegardé sur la carte SD et récupéré l’URI est différent dans le Nougat ....

Il est assez facile d'implémenter FileProvider sur votre application. Vous devez d’abord ajouter une balise FileProvider dans AndroidManifest.xml sous la balise comme ci-dessous: AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
    ...
    <application
        ...
        <provider
            Android:name="Android.support.v4.content.FileProvider"
            Android:authorities="${applicationId}.provider"
            Android:exported="false"
            Android:grantUriPermissions="true">
            <meta-data
                Android:name="Android.support.FILE_PROVIDER_PATHS"
                Android:resource="@xml/provider_paths"/>
        </provider>
    </application>
</manifest>

Et créez ensuite un fichier provider_paths.xml dans le dossier xml sous le dossier res. Un dossier peut être nécessaire pour créer s'il n'existe pas.

res/xml/provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <external-path name="external_files" path="."/>
</paths>

Terminé! FileProvider est maintenant déclaré et prêt à être utilisé.

La dernière étape consiste à modifier la ligne de code ci-dessous dans MainActivity.Java.

Uri photoURI = Uri.fromFile(createImageFile());

à

Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
            BuildConfig.APPLICATION_ID + ".provider",
            createImageFile());

Et fait ! Votre application devrait maintenant fonctionner parfaitement sur toutes les versions d'Android, y compris Android Nougat. À votre santé ! 

4
g7pro

Eh bien, c'est le travail d'Android de faire de la vie des développeurs un enfer à chaque mise à jour :)

googlers, voici un guide étape par étape pour les développeurs qui (comme la question) ont utilisé les exemples dans la documentation Android;

1- dans la partie que vous avez utilisée 

Uri.fromFile(image)

vous devez utiliser cet extrait:

Uri photoURI = FileProvider.getUriForFile(mContext,
                        "com.sample.test.fileprovider",
                        image);

bien sûr, il est inutile de dire que vous devez remplacer com.sample.test par le nom de votre paquet.

2- Vous devez maintenant déclarer votre fournisseur dans votre fichier AndroidManifest.xml. Sous la balise Application, collez cette balise:

<provider
            Android:name="Android.support.v4.content.FileProvider"
            Android:authorities="com.sample.test.fileprovider"
            Android:exported="false"
            Android:grantUriPermissions="true">
            <meta-data
                Android:name="Android.support.FILE_PROVIDER_PATHS"
                Android:resource="@xml/file_paths" />

3- faites attention à Android:resource="@xml/file_paths" vous devez créer un fichier xml avec le même nom file_paths sous votre dossier res/xml/ et y placer ceci:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <external-path name="pictures"/>
</paths>

sur quelques autres extraits sur le Web et la documentation elle-même, il est indiqué que vous devez écrire ceci 

<external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />

au lieu de la nôtre, cela dépend en fait de votre code. Si vous créez votre fichier à l’aide de Environment.getExternalStorageDirectory().getPath(), vous n’en avez pas besoin, mais si vous suivez exactement les instructions, vous devez vous en tenir à la documentation

3
Muhammad Naderi

Ici résolu votre problème d'intention de la caméra dans la version 7.0, 

file: // n'est pas autorisé (Android N) à se lier avec Intent sinon il lancera lancer FileUriExposedException, ce qui peut provoquer le blocage immédiat de votre application.

S'il vous plaît vérifier tous les détails des problèmes et solution.

Solution

1
vishal gadhiya