webentwicklung-frage-antwort-db.com.de

Android: So schreiben Sie die Kamera in Android-Nougat

In meiner Android-Anwendung muss ich Bilder mit der Kamera auf den Button klicken. Es funktioniert in allen Android-Versionen außer Android 7 (Nougat). Wenn ich auf die Kameraoption klicke, wird die App auch dann beendet, wenn die Berechtigungen aktiviert sind Problem ist in der Kamera, die absichtlich aufruft. Darunter ist mein 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;
        }
    }
}

Was war das Problem für Nougat hier? Ist es wegen der von getImageFileUri () zurückgegebenen URIs? Bitte hilf mir, das zu lösen.

7
KJEjava48

Hey bitte folgt diesem Thread als Referenz. Es zeigt Ihnen, wie Sie File Provider verwenden, wenn Sie targetSDK auf 24 setzen und die folgenden Einstellungen vornehmen. In Ihrer private static Uri getImageFileUri()-Methode 

Ändern Sie diese Zeile 

return Uri.fromFile(image);

zu

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

Hoffen Sie, dass dies Ihnen helfen wird, Ihr Problem zu lösen.
Weitere Informationen finden Sie unter - Einrichten der Dateifreigabe - Offizielle Dokumentation

6

Versuchen Sie, dies ist nicht die Absicht, die das Problem verursacht, sobald Sie das Bild aufnehmen und auf der SD-Karte speichern. Wenn Sie den URI zurückbekommen, ist das in Nougat anders.

Es ist ziemlich einfach, FileProvider in Ihrer Anwendung zu implementieren. Zuerst müssen Sie ein FileProvider-Tag in AndroidManifest.xml unter dem folgenden Tag hinzufügen: 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>

Erstellen Sie dann eine Datei provider_paths.xml im Ordner xml unter dem Ordner res. Möglicherweise wird ein Ordner zum Erstellen benötigt, wenn er nicht vorhanden ist.

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>

Erledigt! FileProvider ist jetzt deklariert und kann verwendet werden.

Der letzte Schritt besteht darin, die folgende Codezeile in MainActivity.Java zu ändern

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

zu

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

Und fertig ! Ihre Anwendung sollte jetzt auf jeder Android-Version, einschließlich Android Nougat, einwandfrei funktionieren. Prost ! 

4
g7pro

Nun, es ist die Aufgabe von Android, den Entwicklern mit jedem Update das Leben zur Hölle zu machen :)

googlers, hier ist eine schrittweise Anleitung für Entwickler, die (wie die Frage) die Beispiele in Android-Dokumentationen verwendet haben;

1- in dem Teil, den Sie verwendet haben 

Uri.fromFile(image)

sie müssen dieses Snippet verwenden:

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

es ist natürlich unnötig zu sagen, dass Sie com.sample.test in Ihren Paketnamen ändern müssen.

2- Jetzt müssen Sie Ihren Provider in Ihrer AndroidManifest.xml-Datei angeben. Fügen Sie dazu unter Application-Tag dieses Tag ein:

<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- Achten Sie auf Android:resource="@xml/file_paths", Sie müssen eine xml-Datei mit dem gleichen Namen file_paths in Ihrem res/xml/-Ordner erstellen und Folgendes einfügen:

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

in einigen anderen Ausschnitten im Web und in der Dokumentation selbst heißt es, dass Sie dies schreiben müssen 

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

anstatt zu unserem, hängt es tatsächlich von Ihrem Code ab. Wenn Sie Ihre Datei mit Environment.getExternalStorageDirectory().getPath() erstellen, benötigen Sie sie nicht. Wenn Sie jedoch genau wie die Dokumente folgen, müssen Sie sich an die Dokumente halten

3
Muhammad Naderi

Hier wurde das Problem mit der Kameraabsicht in Version 7.0 behoben. 

file: // darf (Android N) nicht mehr mit Intent verbunden werden. Andernfalls wird FileUriExposedException ausgelöst. Dies kann dazu führen, dass Ihre App sofort zum Absturz führt.

Bitte überprüfen Sie alle Probleme und Lösungen.

Lösung

1
vishal gadhiya