web-dev-qa-db-ja.com

Android 6.0のオープンに失敗しました:EACCES(許可が拒否されました)

uses-permissionWRITE_EXTERNAL_STORAGEMOUNT_UNMOUNT_FILESYSTEMSREAD_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には許可に関する違いがありますか?

55
HelloSilence

AndroidはAndroid 6.0(Marshmallow)に新しい許可モデルを追加しました。

http://www.captechconsulting.com/blogs/runtime-permissions-best-practices-and-how-to-gracefully-handle-permission-removal

したがって、Runtime Permissionを確認する必要があります。

ランタイムパーミッションとは何ですか?

GoogleはAndroid 6.0 Marshmallowを使用して、アプリケーションが特定の許可を要求している理由をユーザーがよりよく理解できる新しい許可モデルを導入しました。ユーザーがインストール時に盲目的にすべての許可を受け入れるのではなく、ユーザーはアプリケーションの使用中に必要になったときに許可を受け入れるように求められます。

新しいモデルを実装するタイミング?

アプリケーションでバージョン23をターゲットにすることを選択するまで、完全なサポートは必要ありません。バージョン22以下をターゲットにしている場合、アプリケーションは、インストール時にMarshmallow未満のOSを実行しているデバイスと同様に、すべての権限を要求します。

この情報はここから取得されます。

このリンクから実装方法を確認してください:

http://www.captechconsulting.com/blogs/runtime-permissions-best-practices-and-how-to-gracefully-handle-permission-removal

51
AndiGeeky

Android 6(Marshmallow)では、ユーザーはインストール時にすべてのアクセス許可を受け入れましたが、それらのアクセス許可の一部を後で削除することを決定できます。

高速な解決策ですが、推奨されません:多分、グラドルのtargetSdkVersion22に変更すると、問題は解決します。

実装方法(ベストプラクティス)

  1. 最初に、ユーザーのデバイスがマシュマロデバイスであるかどうかを判断します。

    private boolean shouldAskPermission(){
    
    return(Build.VERSION.SDK_INT>Build.VERSION_CODES.Lollipop_MR1);
    
    }
    
  2. shouldAskPermission()trueを返す場合、必要な許可を求めます。

    String[] perms = {"Android.permission.WRITE_EXTERNAL_STORAGE"};
    
    int permsRequestCode = 200;
    
    requestPermissions(perms, permsRequestCode);
    

メソッドrequestPermissions(String[] permissions, int requestCode);は、Android Activityクラス内にあるパブリックメソッドです。

  1. 以下に示すように、onRequestPermissionResultメソッドでリクエストの結果を受け取ります。

    @Override
    public void onRequestPermissionsResult(int permsRequestCode, String[] permissions, int[] grantResults){
    
    switch(permsRequestCode){
    
        case 200:
    
            boolean writeAccepted = grantResults[0]==PackageManager.PERMISSION_GRANTED;
    
            break;
    
    }
    
    }
    

結果を受け取ったら、それらを適切に処理する必要があります。

推奨される許可フロー:

enter image description here

詳細:

Marshmallowデバイスを使用しているユーザーは、アプリケーションの設定を介して危険な権限を取り消すことができるようになりました

Androidでは、一部の権限を「dangerous」および一部の権限を「normal」と定義しています。両方ともアプリケーションのマニフェストに必要ですが、危険のみです許可にはランタイム要求が必要です。

新しいアクセス許可モデル(ランタイム要求)を実装しないことを選択した場合、アクセス許可の取り消しにより、不要なユーザーエクスペリエンスが発生し、場合によってはアプリケーションがクラッシュする可能性があります。

以下の表は、現在のすべての危険な許可とそれぞれのグループをリストしています。

enter image description here

ユーザーがグループ/カテゴリで1つの許可を受け入れる場合、グループ全体を受け入れます!

出典:http://www.captechconsulting.com

Dexterライブラリの使用:

Dexter を使用できます。 Android実行時に許可を要求するプロセスを簡素化するライブラリ。

49
Hamed.Ghadirian

後方互換性のために 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();
        }
    }
}
13
c0ming

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);を呼び出すだけです。うまくいけばうまくいくはずです。

10
Ronny Kibet

怠けている場合は、targetSdkVersionを22にダウングレードしてください(Lollipopの前)

2
gderaco

これは私のために働いた。

設定->アプリケーション-> YourApp->ストレージ、連絡先などへのアクセス許可を提供します.

2
Uma