uses-permission
にWRITE_EXTERNAL_STORAGE
、MOUNT_UNMOUNT_FILESYSTEMS
、READ_EXTERNAL_STORAGE
を含むAndroidManifest.xml
を追加しました。
Nexus5(Android 6.0)でアプリケーションを実行しようとすると、次のように例外がスローされました。
Java.io.IOException: open failed: EACCES (Permission denied)
そして、別のAndroid電話(Android 5.1)を試しましたが、すべてが問題ありませんでした。コードは次のとおりです。
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
currentPhotoPath = image.getAbsolutePath();
return image;
}
Android 6.0には許可に関する違いがありますか?
AndroidはAndroid 6.0(Marshmallow)に新しい許可モデルを追加しました。
したがって、Runtime Permission
を確認する必要があります。
ランタイムパーミッションとは何ですか?
GoogleはAndroid 6.0 Marshmallowを使用して、アプリケーションが特定の許可を要求している理由をユーザーがよりよく理解できる新しい許可モデルを導入しました。ユーザーがインストール時に盲目的にすべての許可を受け入れるのではなく、ユーザーはアプリケーションの使用中に必要になったときに許可を受け入れるように求められます。
新しいモデルを実装するタイミング?
アプリケーションでバージョン23をターゲットにすることを選択するまで、完全なサポートは必要ありません。バージョン22以下をターゲットにしている場合、アプリケーションは、インストール時にMarshmallow未満のOSを実行しているデバイスと同様に、すべての権限を要求します。
この情報はここから取得されます。
このリンクから実装方法を確認してください:
Android 6(Marshmallow)では、ユーザーはインストール時にすべてのアクセス許可を受け入れましたが、それらのアクセス許可の一部を後で削除することを決定できます。
高速な解決策ですが、推奨されません:多分、グラドルのtargetSdkVersion
を22
に変更すると、問題は解決します。
実装方法(ベストプラクティス)
最初に、ユーザーのデバイスがマシュマロデバイスであるかどうかを判断します。
private boolean shouldAskPermission(){
return(Build.VERSION.SDK_INT>Build.VERSION_CODES.Lollipop_MR1);
}
shouldAskPermission()
がtrue
を返す場合、必要な許可を求めます。
String[] perms = {"Android.permission.WRITE_EXTERNAL_STORAGE"};
int permsRequestCode = 200;
requestPermissions(perms, permsRequestCode);
メソッドrequestPermissions(String[] permissions, int requestCode);
は、Android Activityクラス内にあるパブリックメソッドです。
以下に示すように、onRequestPermissionResultメソッドでリクエストの結果を受け取ります。
@Override
public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
switch(permsRequestCode){
case 200:
boolean writeAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
break;
}
}
結果を受け取ったら、それらを適切に処理する必要があります。
推奨される許可フロー:
詳細:
Marshmallowデバイスを使用しているユーザーは、アプリケーションの設定を介して危険な権限を取り消すことができるようになりました
Androidでは、一部の権限を「dangerous」および一部の権限を「normal」と定義しています。両方ともアプリケーションのマニフェストに必要ですが、危険のみです許可にはランタイム要求が必要です。
新しいアクセス許可モデル(ランタイム要求)を実装しないことを選択した場合、アクセス許可の取り消しにより、不要なユーザーエクスペリエンスが発生し、場合によってはアプリケーションがクラッシュする可能性があります。
以下の表は、現在のすべての危険な許可とそれぞれのグループをリストしています。
ユーザーがグループ/カテゴリで1つの許可を受け入れる場合、グループ全体を受け入れます!
出典:http://www.captechconsulting.com
Dexterライブラリの使用:
Dexter を使用できます。 Android実行時に許可を要求するプロセスを簡素化するライブラリ。
後方互換性のために ActivityCompat.requestPermissions を使用することもできます。
例:
private static final int REQUEST_CODE = 0x11;
String[] permissions = {"Android.permission.WRITE_EXTERNAL_STORAGE"};
ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE); // without sdk version check
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// save file
} else {
Toast.makeText(getApplicationContext(), "PERMISSION_DENIED", Toast.LENGTH_SHORT).show();
}
}
}
API-23から、マニフェストで既に宣言している場合でも、アクティビティで許可を宣言する必要があります。
// Storage Permissions variables
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
//persmission method.
public static void verifyStoragePermissions(Activity activity) {
// Check if we have read or write permission
int writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
int readPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE);
if (writePermission != PackageManager.PERMISSION_GRANTED || readPermission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so Prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
使用するには、onCreateでverifyStoragePermissions(this);
を呼び出すだけです。うまくいけばうまくいくはずです。
怠けている場合は、targetSdkVersionを22にダウングレードしてください(Lollipopの前)
これは私のために働いた。
設定->アプリケーション-> YourApp->ストレージ、連絡先などへのアクセス許可を提供します.