1. ホーム
  2. android

[解決済み] オープンに失敗しました。EACCES (パーミッションが拒否されました)

2023-04-21 06:53:57

質問

いくつかのデバイスで、ストレージへのアクセスに非常に奇妙な問題があります。アプリは私のテスト デバイス (Nexus 4 & 7、Samsung GS5) で動作しています。私のデバイスはすべて Android 4.4.2 を実行しています。しかし、ユーザーから、アプリがストレージ(内部ストレージやSDカード)に書き込めないというメールをたくさん受け取りました。ユーザーのフィードバックから受け取ったログ ファイルから、問題は次のコードにあることがわかります。

try {
    if (fStream == null) {
    fStream = new FileOutputStream(filename, true);
}
    fStream.write(data, 0, bytes);
    return;
} catch (IOException ex) {
    ex.printStackTrace();
}

FileOutputStreamの作成時に、fStream = new FileOutputStream(filename, true);という行で例外がスローされます。

スタックログは

W/System.err( 8147): Caused by: java.io.FileNotFoundException: /storage/emulated/0/my_folder/test_file_name.png: open failed: EACCES (Permission denied)
w/System.err( 8147):    at libcore.io.IoBridge.open(IoBridge.java:409)
W/System.err( 8147):    at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
W/System.err( 8147):    at java.io.FileOutputStream.<init>(FileOutputStream.java:128)
W/System.err( 8147):    at myapp.save(SourceFile:515)
W/System.err( 8147):    ... 8 more
W/System.err( 8147): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
W/System.err( 8147):    at libcore.io.Posix.open(Native Method)
W/System.err( 8147):    at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
W/System.err( 8147):    at libcore.io.IoBridge.open(IoBridge.java:393)
W/System.err( 8147):    ... 11 more

AndroidManifest.xmlでは、以下のようなパーミッションが宣言されていますね。

 <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19"/>
    <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

ユーザーがSDカードで正しいアプリのプライベートを使っていることは確認しました。さらに奇妙なのは、内部ストレージへの書き込みにも失敗することです。読み取りと書き込みの両方の権限を持っているのに、どうしてこのようなことが起こるのでしょうか? ユーザーはその時、デバイスを PC に接続していないと言います。

アップデート

FileOutputStreamのopenとcloseを頻繁に呼び出していることが判明し、ある時点でFileNotFoundExceptionをスローしています。スレッドの問題のように聞こえます。

どのように解決するのですか?

しばらく前に同じような問題に遭遇しました。

あなたの問題は 2 つの異なる領域にある可能性があります。書き込むファイルをどのように作成しているか、または、書き込む方法が電話に依存しているという点で欠陥がある可能性があります。

SD カード上の特定の場所にファイルを書き込んでいる場合は、環境変数を使用してみてください。 これらは常に有効な場所を指しているはずです。 以下は、downloads フォルダに書き込む例です。

java.io.File xmlFile = new java.io.File(Environment
    .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
     + "/Filename.xml");

アプリケーションの内部ストレージにファイルを書き込む場合。 この例を試してみてください。

java.io.File xmlFile = new java.io.File((getActivity()
   .getApplicationContext().getFileStreamPath("FileName.xml")
   .getPath()));

個人的には、ファイルへのストリーミングを処理するために、外部ライブラリに依存しています。これはまだ私を失望させたことがありません。

org.apache.commons.io.FileUtils.copyInputStreamToFile(is, file);

私は書き込みに失敗してデータを失ったことが何度もあるので、IOの重労働はよく知られテストされたライブラリに頼っています。

ファイルが大きい場合、バックグラウンドでIOを実行するか、コールバックを使用することを検討する必要があるかもしれません。

すでに環境変数を使用している場合、パーミッションの問題である可能性があります。以下の Justin Fiedler の回答を参照してください。