web-dev-qa-db-ja.com

Android:にカメラの意図を書き込む方法Android nougat

私のAndroidアプリケーションでは、ボタンがクリックされたときにカメラを使用して画像を撮影する必要があります。Androidバージョンを除くAndroid 7(Nougat)。カメラオプションを選択すると、権限が許可されていてもアプリが終了します。問題はカメラ呼び出しインテントにあると思います。

_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 (icon) and 2 for REQUEST_CAMERA_ATT (attachment)
        }
    }
}

private static Uri getImageFileUri(){
    // Create a storage directory for the images
    // To be safe(r), you should check that the SD card 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;
        }
    }
}
_

ここでヌガーの問題は何ですか? getImageFileUri()によって返されるUriが原因ですか?

10
KJEjava48

このスレッド を参考にしてください。 targetSDKを24に設定し、以下を変更する場合のFile Providerの使用方法を示します。 private static Uri getImageFileUri()メソッドで

この行を変更

return Uri.fromFile(image);

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

これが問題の解決に役立つことを願っています。
詳細については、- ファイル共有のセットアップ-公式ドキュメント

8

これを試してみてください。写真を撮ってsdカードに保存してからURIを取り戻すことは、Nougatでは異なります。

アプリケーションにFileProviderを実装するのは非常に簡単です。まず、AndroidManifest.xmlのFileProviderタグを以下のようなタグの下に追加する必要があります。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>

そして、resフォルダーの下のxmlフォルダーにprovider_paths.xmlファイルを作成します。フォルダーが存在しない場合、作成する必要がある場合があります。

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>

できた! FileProviderが宣言され、使用できる状態になりました。

最後の手順は、MainActivity.Javaで以下のコード行を変更することです

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

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

そして....完了!アプリケーションは、Androidを含むバージョンAndroid Nougat。Cheers!

5
g7pro

開発者の生活をアップデートするたびに生き生きとさせるのはAndroidの仕事です:)

googlers、ここではAndroid documentations;のサンプルを使用した(質問のように)開発者向けのステップバイステップガイドです。

1-使用した部分

_Uri.fromFile(image)
_

このスニペットを使用する必要があります。

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

もちろん、_com.sample.test_をパッケージ名に変更する必要があることは言うまでもありません。

2-次に、AndroidManifest.xmlでプロバイダーを宣言する必要があります。これを行うには、Applicationタグの下にこのタグを貼り付けます。

_<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- _Android:resource="@xml/file_paths"_に注意を払って、_file_paths_フォルダーの下に同じ名前_res/xml/_のxmlファイルを作成し、これを配置する必要があります。

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

ウェブ上の他のいくつかのスニペットとドキュメント自体に、これを書く必要があると書かれています

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

私たちの代わりに、それは実際にあなたのコードに依存しています、Environment.getExternalStorageDirectory().getPath()を使用してファイルを作成する場合、それは必要ありませんが、ドキュメントとまったく同じように従った場合、ドキュメントに固執する必要があります

5
Muhammad Naderi

ここでは、7.0バージョンでのカメラの意図の問題を修正しました。

file://はIntentでアタッチできません(Android N)か、FileUriExposedExceptionがスローされ、すぐにアプリがクラッシュする可能性があります。

問題と解決策の詳細を確認してください。

ソリューション

1
vishal gadhiya