Androidでの例外「オープン失敗:EACCES(アクセス拒否)」


297

私は得ています

開けませんでした: EACCES (Permission denied)

ライン上 OutputStream myOutput = new FileOutputStream(outFileName);

ルートを確認してみました android.permission.WRITE_EXTERNAL_STORAGE

この問題を解決するにはどうすればよいですか?

try {
    InputStream myInput;

    myInput = getAssets().open("XXX.db");

    // Path to the just created empty db
    String outFileName = "/data/data/XX/databases/"
            + "XXX.db";

    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    // Transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }

    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();
    buffer = null;
    outFileName = null;
}
catch (IOException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

私はAndroidタブレットでも同じ問題を抱えていましたが、私の状況は独特である可能性があるため、コメントで私の解決策を報告します。エラーは、アプリが50個を超えるxmlファイルを持つ/ data / data / myapp / fooディレクトリにアクセスしようとしたときに発生しました。バグのため、アプリはフォルダーをクリーンアップしませんでした。古いファイルがいくつか削除された後、エラーは消えました。何故かはわからない。一般的なAndroidデバイスの問題である可能性があります。
香港

これは、私を解く:stackoverflow.com/questions/33666071/...
partho

回答:


236

私も同じ問題を抱えていました... <uses-permission間違った場所にありました。これは正しいです:

 <manifest>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        ...
        <application>
            ...
            <activity> 
                ...
            </activity>
        </application>
    </manifest> 

uses-permissionタグは外にする必要がありますapplicationタグ。


2
それは、uses-permissionがアプリケーションの外側にある必要があるということです
user462990

3
「:私は警告を取得<uses-permission>タグが後に表示される<application>タグ」
MR5

11
警告android 4.4.4では、パラメーターを使用しないでくださいandroid:maxSdkVersion="18"。この例外が発生していました
guisantogui 2014

1
この権限はAPIレベル19以降で適用されます。APIレベル19より前は、この権限は適用されず、すべてのアプリが外部ストレージからの読み取りアクセス権を持っています。
Zar E Ahmer、2015

1
imはAPIレベル15を使用していますが、ファイルをOTG USBスティックに移動しようとするとエラーが発生します
Ravi Mehta

330

API 23+の場合、マニフェストにすでに存在する場合でも、読み取り/書き込み権限をリクエストする必要があります。

// Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}

AndroidManifest.xml

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

API 23以降の権限のリクエストに関する公式ドキュメントについては、https: //developer.android.com/training/permissions/requesting.htmlを確認してください


13
明確にするために、これが機能するためには、アクティビティーがアクティビティー許可要求応答を処理する必要があります。詳細については、developer.android.com / training / permissions / をご覧ください。
kldavis4

説明と例の便利
Paul Alexander

1
これは悪いことではないですか?ユーザーエクスペリエンスに関して。
M. Usman Khan

5
しかし、どこでそれを使用しますか?たとえば、写真を撮りたい場合、startActivityForResultの前、またはonActivityResultでverifyStoragePermissionsを実行する必要がありますか?それは本当に私を混乱させます。
キウイリー

3
おかげで私の問題は解決しました。注:誰かが「Manifest.permission」を解決できない場合は、「import android.Manifest」をインポートする必要があります。
Oubaida AlQuraan 16

167

GoogleにはAndroid Qの新機能があります。外部ストレージのフィルタービューです。そのための簡単な修正は、このコードをAndroidManifest.xmlファイルに追加することです。

<manifest ... >
    <!-- This attribute is "false" by default on apps targeting Android Q. -->
    <application android:requestLegacyExternalStorage="true" ... >
     ...
    </application>
</manifest>

詳しくは、https//developer.android.com/training/data-storage/compatibilityをご覧ください。


@ビリー私はそれがapi 29のデバイスでのみ発生することに気づきました。それで、ファイルプロバイダーの変更を検索しました
Uriel Frankel

ようやくcloudtestingscreenshotter_lib.aarがandroidTestマニフェストに追加されたこの行で動作するようになりました。この発見に感謝します。
bko

6
あなたは、私を多くの時間を節約しました。Qでは、多くのことが開発者の悩みの種になっています。この回答は別の質問として投稿する必要があり、より多くの投票に値すると思います。
sanjeev

この素敵な小さな黒魔術についてもっと読みたいと思いますが、残念ながらリンクは404エラーを返します...とにかくありがとう
SadSido

android:requestLegacyExternalStorage="true"これは警告を与えますこれは下位バージョンのrytを壊しませんか?@UrielFrankel
Santanu Sur

58

エミュレータ内でアプリケーションを実行しているときに、これを一度観察しました。エミュレータの設定では、外部ストレージ(「SDカード」)のサイズを適切に指定する必要があります。デフォルトでは、「外部ストレージ」フィールドは空です。これは、おそらくそのようなデバイスがなく、マニフェストで権限が付与されている場合でもEACCESがスローされることを意味します。


51

すべての回答に加えて、スマートフォンをUSBストレージとして使用していないことを確認してください。

HTC Sensation on USB storage mode enabledで同じ問題が発生していました。アプリをデバッグ/実行することはできますが、外部ストレージに保存できません。


おかげで、実行時にユーザーからのアクセス許可を要求したにもかかわらず。このエラーはエミュレータで発生しました。
Sharp Edge

1
Samsung Galaxy S6デバイスを接続すると、最初に「デバイスデータへのアクセスを許可する」というオプションが「拒否」または「許可」で表示され、通知バーからも「1. MTP 2. PTP 3. MIDIにUSBを使用」というオプションが表示されます。デバイス4.充電。どれを選ぶ?
testsingh 2016年

34

android:requestLegacyExternalStorage = "true"をAndroidマニフェストに追加します。これは、SDK 29
以降のAndroid 10(Q)またはAndroid Xの移行後に動作します。

 <application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:hardwareAccelerated="true"
    android:icon=""
    android:label=""
    android:largeHeap="true"
    android:supportsRtl=""
    android:theme=""
    android:requestLegacyExternalStorage="true">

Wowは完璧に機能します。それが私が求めていた答えでした。すばらしい、@ rhaldarに感謝します。あなたは私の一日を救いました
Ayush Katuwal

29

私の問題は「TargetApi(23)」でした。これは、minSdkVersionが23未満の場合に必要です。

だから、私は次のスニペットで許可をリクエストしています

protected boolean shouldAskPermissions() {
    return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
}

@TargetApi(23)
protected void askPermissions() {
    String[] permissions = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE"
    };
    int requestCode = 200;
    requestPermissions(permissions, requestCode);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
// ...
    if (shouldAskPermissions()) {
        askPermissions();
    }
}

28

Android Qのソリューション:

<application ...
    android:requestLegacyExternalStorage="true" ... >

あなたは私の日を救った。許可は与えられますが、これを設定するまで、Glideは画像を読み取ることができません。
リーゴール

注意:Android 11では2020年8月にレガシーアクセスが完全に削除されるため、ファイルアクセスをアップグレードして、アプリにStorage Access Framework(SAF)を使用するようにしてください
dimib

16

私は同じことを経験しています。私が見つけたのは、[設定]-> [アプリケーションマネージャ]-> [アプリ]-> [アクセス許可]-> [ストレージを有効にする]に移動すると、問題が解決することです。


1
このセクションが見つかりませんか?
エヴァンセビー2018

13

結局のところ、自分の電話をデスクトップPCに接続したままで、これを認識していなかったので、それは愚かな間違いでした。

だから私はUSB接続をオフにする必要があり、すべてがうまくいきました。


私のためにも働いた。しかし、なぜそれが機能するのですか?USBをPCに接続しないとどのような違いがありますか。
user13107

良い質問。これ以上調査することはありません。デバイスを接続した瞬間にシステムからの書き込みロックがあると思います(そのため、コンピューター上のUSBデバイスをエミュレートする可能性があります)。多分これは矛盾したデータを避けるためです。確かではありません。
トビアスライヒ

ここに理由を見つけましたstackoverflow.com/questions/7396757/…また、私の答えを参照してくださいstackoverflow.com/a/43863548/1729501
user13107

13

CM 12.1を実行しているSamsung Galaxy Note 3でも同じ問題が発生しました。私にとっての問題は、私が持っていたということでした

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="18"/>

ユーザーの写真を撮って保存するためにそれを使わなければなりませんでした。ImageLoaderで同じ写真を読み込もうとすると、(Permission denied)エラーが発生しました。解決策は明示的に追加することでした

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

上記のパーミッションは、APIバージョン18までの書き込みパーミッションのみを制限しているため、これにより読み取りパーミッションが制限されます。


助けてくれなかった!試してみる価値があります!ありがとう。
Sakiboy、2017

9

すべての回答に加えて、クライアントがAndroid 6.0を使用している場合、Android は(Marshmallow)の新しい権限モデルを追加しました。

トリック:バージョン22以下をターゲットにしている場合、Marshmallow未満のOSを実行しているデバイスの場合と同様に、アプリケーションはインストール時にすべての権限を要求します。エミュレータを試す場合、Android 6.0以降では、設定->アプリ-> YOURAPP->権限に明示的に移動し、権限を指定している場合は変更する必要があります。


2
信じられないほど、私はこれを理解するために2日間費やしました。Androidでスムーズに動作していると感じるたびに、このようなことが発生します。
Jaime Ivan Cervantes

7

奇妙なことに、私のnewFileの前にスラッシュ「/」を置いた後、私の問題は解決されました。私はこれを変更しました:

File myFile= new File(Environment.getExternalStorageDirectory() + "newFile");

これに:

File myFile= new File(Environment.getExternalStorageDirectory() + "/newFile");

1
ここで奇妙なことは何もありません。最初の行では、外部ストレージディレクトリを含むディレクトリと同じディレクトリにファイルを作成しようとしています。すなわち/storage/.../somethingnewfileの代わり/storage/.../something/newfile
ステファン

@Stéphane幅広い回答を見ると、エラー自体は奇妙です。
Darush 2017年

3
これを行う正しい方法は、File(dir、file)cosntructorを使用することです
Nick Cardoso

@NickCardoso File(String pathname)を使用することもできます。あなたはここでポイントを獲得していないようです。問題は、Fileクラスの使用方法ではありません。このスレッドの回答の範囲は、このエラーがいかに誤解を招くか、およびそれを解決するための可能な方法がいくつあるかを示しています。私の場合、エラーは欠落したスラッシュでした。一部の人々はそれが便利だと思っています。もちろん、独自の方法でファイルにアクセスできます。先に行き、あなたの答えを投稿してください。それは誰かの問題を解決するかもしれません。
Darush、2018

あなたは要点を得ていません。正しいコンストラクターを使用する場合、ハックは必要ありません。私のコメントが追加されたので、あなたの間違いに惑わされた将来の読者を助けることができます。それは個人的な批判ではなく、返答も必要ありませんでした
Nick Cardoso

6

私は同じ問題を抱えており、どの提案も役に立ちませんでした。しかし、その物理的なデバイスであるGalaxy Tabの興味深い理由を見つけました。

USBストレージがオンの場合、外部ストレージの読み取りおよび書き込み権限は影響しません。USBストレージをオフにするだけで、適切な権限があれば問題は解決します。


2
くそー、私はちょうど3時間くらい働いて過ごしました。さらに、デバイスを再起動する必要があり、うまくいきました。どうもありがとうございました
crgarridos

5

以下のすべて/dataが「内部ストレージ」に属していると思います。ただし、に書き込むことができる必要があります/sdcard


5
<uses-permission android:name = "android.permission.WRITE_INTERNAL_STORAGE" />も試しました。まだ同じ。
MERT

1
/ data-partitionは通常、通常のファイルアクセスを試みる通常の(非root)ユーザーに対して書き込み保護されています。内部ストレージの場合、特にデータベースにアクセスする場合は、そのための特別な方法があります。この問題については、Android開発者ページが役立つはずです。
オーブンストーブ

5

/system/etc/permission/platform.xml
以下のようにあなたとグループの権限プロパティを変更する必要があります。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
    <group android:gid="sdcard_rw" />
    <group android:gid="media_rw" />    
</uses-permission>

platform.xmlはすぐにロックされ、adbシェルを介してこれを試みますが、ADBでmodに使用できるスクリプトが必要です。
John

不合格。デバイスを起動ループに入れます。
Tobse 16

5

Galaxy S5(android 6.0.1)のDCIM / cameraフォルダーに画像を書き込もうとしたときにも同じエラーが発生し、このフォルダーのみが制限されていることがわかりました。カメラではなく、DCIM /任意のフォルダーに書き込むことができます。これは、ブランドベースの制限/カスタマイズである必要があります。


4

アプリケーションがシステムアプリケーションに属している場合、SDカードにアクセスできません。


4

マニフェストにすべての正しい権限を設定した場合でも、サードパーティアプリが外部カードへの書き込みを許可されている唯一の場所は、「自分のディレクトリ」(つまり、/ sdcard / Android / data /)に書き込みを試みることです。その他の場所:例外が発生します:EACCES(アクセスが拒否されました)


3

おそらく答えはこれです:

API> = 23デバイスで、アプリをインストールする場合(アプリはシステムアプリではありません)、[設定-アプリケーション]でストレージのアクセス許可を確認する必要があります。すべてのアプリにアクセス許可リストがあり、確認する必要があります!試す


3

私の場合、外部ストレージへのパスを返すファイルピッカーライブラリを使用していましたが、それはから始まりました/root/。実行時にWRITE_EXTERNAL_STORAGE権限が付与されていても、エラーEACCES(権限が拒否されました)が発生しました。
だから使うEnvironment.getExternalStorageDirectory()、外部ストレージへの正しいパスを取得するためにします。

例:
書き込み不可: /root/storage/emulated/0/newfile.txt
書き込み可能: /storage/emulated/0/newfile.txt

boolean externalStorageWritable = isExternalStorageWritable();
File file = new File(filePath);
boolean canWrite = file.canWrite();
boolean isFile = file.isFile();
long usableSpace = file.getUsableSpace();

Log.d(TAG, "externalStorageWritable: " + externalStorageWritable);
Log.d(TAG, "filePath: " + filePath);
Log.d(TAG, "canWrite: " + canWrite);
Log.d(TAG, "isFile: " + isFile);
Log.d(TAG, "usableSpace: " + usableSpace);

/* Checks if external storage is available for read and write */
public boolean isExternalStorageWritable() {
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED.equals(state)) {
        return true;
    }
    return false;
}

出力1:

externalStorageWritable: true
filePath: /root/storage/emulated/0/newfile.txt
isFile: false
usableSpace: 0

出力2:

externalStorageWritable: true
filePath: /storage/emulated/0/newfile.txt
isFile: true
usableSpace: 1331007488

私はまったく同じ問題を抱えていました。rootパスからパーツを削除すると、問題が解決しました。
xabush 2017年


3

検索結果からここに来てAndroid 10をターゲットにしているユーザーの場合:Android 10(API 29)は、ストレージに関連する一部の権限を変更します。

以前のインスタンスEnvironment.getExternalStorageDirectory()(API 29で非推奨)を次のものと置き換えたときに問題を修正しましたcontext.getExternalFilesDir(null)

ご了承ください context.getExternalFilesDir(type)保管場所が利用できない場合は、外部の権限を持っている場合は、チェックしているときは常にいることを確認してくださいので、ヌルを返すことができます。

詳細はこちら


2

私はinit.rcの/ data /の下にフォルダーを作成しています(Nexus 7のaospをいじくり回しています)が、まさにこの問題がありました。

フォルダーにrw(666)権限を与えるだけでは不十分で、rwx(777)でなければならないことがわかりました。


2

これらのadbコマンドを介してルート化されたデバイスがある場合、ストレージパーミッションのポスト6.0の施行はバイパスできます。

root@msm8996:/ # getenforce
getenforce
Enforcing
root@msm8996:/ # setenforce 0
setenforce 0
root@msm8996:/ # getenforce
getenforce
Permissive

1

マニフェストにアクセス許可を追加します。

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

3
許可はありませんandroid.permission.READ_INTERNAL_STORAGE
ライアンR

0

同じ問題が発生しました(API> = 23)。

ソリューションhttps://stackoverflow.com/a/13569364/1729501は私にとってはうまくいきましたが、デバッグのためにアプリを切断することは現実的ではありませんでした。

私の解決策は、Windowsに適切なadbデバイスドライバーをインストールすることでした。Google USBドライバーが私のデバイスで機能しませんでした。

ステップ1:デバイスブランド用のadbドライバーをダウンロードします。

ステップ2:デバイスマネージャーに移動->他のデバイス->「adb」という単語を含むエントリを検索-> [ドライバーの更新]を選択->ステップ1で場所を指定


0

許可を追加した後、私の問題は解決しました

<uses-permission android:name="android.permission.INTERNET"/>

0

Gradleの依存関係を追加する

implementation 'com.karumi:dexter:4.2.0'

以下のコードをメインアクティビティに追加します。

import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_splash);

    new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {


                checkMermission();
            }
        }, 4000);
    }

    private void checkMermission(){
        Dexter.withActivity(this)
                .withPermissions(
                        android.Manifest.permission.READ_EXTERNAL_STORAGE,
                        android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        android.Manifest.permission.ACCESS_NETWORK_STATE,
                        Manifest.permission.INTERNET
                ).withListener(new MultiplePermissionsListener() {
            @Override
            public void onPermissionsChecked(MultiplePermissionsReport report) {
                if (report.isAnyPermissionPermanentlyDenied()){
                    checkMermission();
                } else if (report.areAllPermissionsGranted()){
                    // copy some things
                } else {
                    checkMermission();
                }

            }
            @Override
            public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
                token.continuePermissionRequest();
            }
        }).check();
    }

0

私の場合、エラーはラインに表示されていました

      target.createNewFile();

sdカードに新しいファイルを作成できなかったため、DocumentFileアプローチを使用する必要がありました。

      documentFile.createFile(mime, target.getName());

上記の質問の場合、問題はこのアプローチで解決される可能性があります。

    fos=context.getContentResolver().openOutputStream(documentFile.getUri());

このスレッドも参照してください 。Android5.0(Lollipop)用に提示された新しいSDカードアクセスAPIの使用方法は?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.