web-dev-qa-db-ja.com

オレオ(外部ストレージへの書き込み)許可

"developer.Android.com" によると

If the app targets Android 8.0 (API level 26), the system grants only 
READ_EXTERNAL_STORAGE at that time; however, if the app later requests 
WRITE_EXTERNAL_STORAGE, the system immediately grants that privilege 
without prompting the user.

現在、READ_EXTERNAL_STORAGEがあり、DownloadManagerにPublic Downloadフォルダー内のファイルをダウンロードするように要求しています

downloadRequest.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, mAttachmentItem.getFilename());

残念ながら、私は

E/UncaughtException: Java.lang.IllegalStateException: Unable to create directory: /storage/emulated/0/data/user/0/com.abc.cba/files
                                                                           at Android.app.DownloadManager$Request.setDestinationInExternalPublicDir(DownloadManager.Java:699)

マニフェストで両方の権限を宣言しました

<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission Android:name="Android.permission.READ_EXTERNAL_STORAGE" />

読み取り許可はすでに付与されており、ランタイムでは書き込み許可を要求していますが、システムはメッセージやダイアログを表示せず、「onRequestPermissionsResult」で常に拒否されます(付与されません)

public static boolean isPermissionsToAccessStorageAreGranted(Context context, Activity activity) {
    ArrayList<String> permissions = new ArrayList<>();

    if (!PermissionUtil.checkPermissions(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
        permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
    }

    if (!permissions.isEmpty()) {
        String[] permissionsList = permissions.toArray(new String[permissions.size()]);
        PermissionUtil.requestPermissions(activity, permissionsList,
                PermissionUtil.REQUESTCODE_ACCESS_STORAGE);
        return false;
    } else {
        return true;
    }
}


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if(requestCode==REQUESTCODE_ACCESS_STORAGE && grantResults[0]== PackageManager.PERMISSION_GRANTED){
 /* downloadFile(); */       
    }
}

私はADBを介してこれら2つの権限を付与しようとしていますが、エラーが表示されます:

adb Shell pm grant com.abc.cba 
Android.permission.WRITE_EXTERNAL_STORAGE
Operation not allowed: Java.lang.SecurityException: Package com.abc.cbs 
has not requested permission Android.permission.WRITE_EXTERNAL_STORAGE

adb Shell pm grant com.abc.cba 
Android.permission.READ_EXTERNAL_STORAGE
Operation not allowed: Java.lang.SecurityException: Can't change 
Android.permission.READ_EXTERNAL_STORAGE. It is required by the 
application
16
SoulaimenK

実際、それは外部の問題でした。私が使用しているアプリライブラリの1つは、Android:maxSdkVersionでWRITE_EXTERNAL_PERMISSIONを要求します。そのため、マニフェストとマージすると、アプリケーション全体のアクセス許可が削除されます。

ソリューションは追加することです:

<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" tools:node="replace"/> 
23
SoulaimenK

マニフェストに権限を追加するのは正しいです:

<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission Android:name="Android.permission.READ_EXTERNAL_STORAGE" />

Lollipop以降のバージョンでは、実行時に権限もリクエストする必要があります。この問題を解決するために、メインアクティビティの作成時に呼び出す新しいメソッドrequestAppPermissionを作成しました。このメソッドはLollipop以降でのみ実行され、それ以外の場合は早く戻ります。

private void requestAppPermissions() {
    if (Android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        return;
    }

    if (hasReadPermissions() && hasWritePermissions()) {
        return;
    }

    ActivityCompat.requestPermissions(this,
            new String[] {
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, REQUEST_WRITE_STORAGE_REQUEST_CODE); // your request code
}

private boolean hasReadPermissions() {
    return (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
}

private boolean hasWritePermissions() {
    return (ContextCompat.checkSelfPermission(getBaseContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
}

アクティビティのonCreateでこのメソッドを呼び出します:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Other things
    requestAppPermissions();
}

最初のロード時に、これはユーザーに許可を受け入れるように促します。

次に、ストレージの読み取りと書き込みが必要なコードを実行する前に、値を保存するか、上記のhasReadPermissions()およびhasWritePermissions()メソッドを使用してこれらのチェックを再度実行することで、これらの権限を確認できます。

11
Tina

オレオの場合、

すでに要求していてWRITE_EXTERNAL_STORAGE許可が付与されている場合でも、その逆の場合でも、明示的にREAD_EXTERNAL_STORAGE要求を(コードによって)行う必要があります。

これに先立ち、WRITE_EXTERNAL_STORAGEが許可されると、READ_EXTERNAL_STORAGEが自動的に許可されます。

あなたがする必要があるのは、

1)コードにWRITEパーミッションを要求します。

2)ユーザーがWRITEパーミッションを付与したら、READ許可-これは自動的に付与されます(明示的にREADを要求しないと例外が発生します)

Oreoの変更は私にはあまり意味がありません(自動的に付与される許可を要求する必要がある理由はわかりません)が、それはそういうものです。

https://developer.Android.com/about/versions/oreo/Android-8.0-changes.html#rmp

4
Angel Koh

実行時にMarshmallow以上の権限を付与する必要があります。サンプルスニペット:

private static final int REQUEST_WRITE_STORAGE = 112;

if (Android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            boolean hasPermission = (ContextCompat.checkSelfPermission(getBaseContext(),
                    Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
            if (!hasPermission) {
                ActivityCompat.requestPermissions(SplashScreen.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.RECORD_AUDIO, Manifest.permission.MODIFY_AUDIO_SETTINGS, Manifest.permission.INTERNET
                        },
                        REQUEST_WRITE_STORAGE);
            }else{ startMainActivity(); }
        }

それが役に立てば幸い。

許可が許可されていて、許可チェックをすでに実装していてもpermission deniedエラーが発生する場合、

aPIレベル29をターゲットにしていないことを確認してください。

変更targetSdkVersionおよびcompilesdkversionから 29to28またはその他の下位レベル。


うまくいけば、これは誰かの精神的健康と髪を救うでしょう。私はこのナンセンスと戦っている私のいくつかを失いました。

2
John Doe

ただの通知:Android Pで、上記のアプリがすべて外部ストレージを読み取れなくても、再起動後にのみ、アプリの再起動を求める終了ダイアログボックスをユーザーに表示する必要がありました。真剣に、グーグルの人は毎回Androidを改善します。 6、8、そして今は9で非常に多くのトラブルがあります。

1
Tertium