web-dev-qa-db-ja.com

androidの外部ストレージにフォルダを作成できません

開発用の電話は_Nexus 5_で、_Android 4.4.2_を実行しています。

私のアプリケーションでは、アプリケーションのデバッグ情報を格納するフォルダーを外部ストレージに作成しようとしています。基本的には、アプリケーションによって実行されるすべてのコマンドが含まれているため、ユーザーが問題に遭遇したときに、デバッグフォルダーから情報を送信して分析することができます。

最初にファイルをフォルダーに書き込もうとしましたが、フォルダーの作成中にエラーが発生しました。最初はmkdir()を使用していましたが、次にmkdirs()に移動しましたが、これも機能しませんでした。

マニフェストに_<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />_があります。

これは、フォルダを作成するためのコードです。

_    File folder = new File(Environment.getExternalStorageDirectory() + "/DebugData");

    String path = folder.getPath();

    if(!folder.mkdirs() || !folder.exists()){        
            Log.e(LOG_TAG, path + " failed");
        } else {
            Log.d(LOG_TAG, path + " succeeded");
        } 
_

これも私が試したものです:

_    //Check SD card state
    String state = Environment.getExternalStorageState();
    if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) || !Environment.MEDIA_MOUNTED.equals(state)) {
        Log.e(LOG_TAG, "Error: external storage is read only or unavailable");
    } else {
        Log.d(LOG_TAG, "External storage is not read only or unavailable");
    }
_

これは、外部ストレージがnot読み取り専用または使用不可であることを返します。

File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "Folder1");などの別のパスも試しました

これは本当に混乱したところです。

別の電話で開発してみました。まず、_Galaxy S4 GT-i9505_を実行している_Android 4.2.2_を取得しました。フォルダーを作成して書き込むことができました。これにより、コードが機能していることがわかりました。また、S4とNexus 5でコードを実行して返されるパスは同じでした。

次に、それがAndroid=バージョン固有である可能性があると思ったので、_Nexus 4_を_Android 4.4.2_で取得し、コードも機能しました。フォルダを作成して、それらに書いてください。

根付いている電話はなく、すべて標準の電話です。特別なアプリケーションや、Nexus 5の賢明な設定で、パーミッションの問題を引き起こすと思われるものはありません。接続はメディアデバイス(MTP)に設定されます。

編集:

私もフォローアップを試しましたが、これもうまくいきませんでした:

  • 外部ストレージのルートディレクトリにファイルを書き込む
  • 外部ストレージのルートディレクトリにファイルを作成して書き込む
  • 概説されたパスにフォルダを作成し、そこにファイルを書き込む
  • 概説されたパスにファイルを作成して書き込む

これの原因について混乱していますが、問題を修正するために他にテストまたは変更できるものはありますか?

編集2:

問題はインデックス作成が原因であることがわかりました。

基本的に、私がテストした他のすべてのデバイスでは、USB接続を再接続して、作成されたファイルとフォルダーを表示できました。

何らかの理由で、Nexus 5はフォルダー/ファイルが存在しても、それらをインデックスに登録しません。

別のサードパーティのファイルエクスプローラーアプリケーションをダウンロードし、すべてのフォルダーとファイルがそこにあることに気付きました。

USBデバッグを介してこれらのフォルダーとファイルを表示するには、それらを再インデックス化するために電話を再起動する必要があります。

ありがとう。

14
benallansmith

これがNexusのインデックス作成の問題であるという点で、これは私にとってはうまくいきました:

MediaScannerConnection.scanFile(this, new String[] { file.toString() }, null,
        new MediaScannerConnection.OnScanCompletedListener() {
            public void onScanCompleted(String path, Uri uri) {
                Log.i("ExternalStorage", "Scanned " + path + ":");
                Log.i("ExternalStorage", "-> uri=" + uri);
            }
});

ファイルを作成して保存した直後に呼び出す必要があります。スキャナーを使用することで、デバイスを再接続するだけで、新しく作成されたファイルとディレクトリを確認できました。

docs によると:

MediaScannerConnectionは、新しく作成またはダウンロードしたメディアファイルをアプリケーションがメディアスキャナーサービスに渡す方法を提供します。メディアスキャナーサービスはファイルからメタデータを読み取り、メディアコンテンツプロバイダーにファイルを追加します。

これが他の誰かを助けることを願っています。

問題はインデックス作成が原因であることがわかりました。

基本的に、私がテストした他のすべてのデバイスでは、USB接続を再接続して、作成されたファイルとフォルダーを表示することができました。

何らかの理由で、Nexus 5はフォルダー/ファイルが存在していても、それらのインデックスを作成しません。

別のサードパーティのファイルエクスプローラーアプリケーションをダウンロードし、すべてのフォルダーとファイルがそこにあることに気付きました。

USBデバッグを介してこれらのフォルダーとファイルを表示するには、それらを再インデックス化するために電話を再起動する必要があります。

4
benallansmith

Android SDKバージョン23以降の場合、ユーザーが外部ストレージの権限を付与しているかどうかを確認する必要があります。

private void createFolder() {
    if (isStoragePermissionGranted()) {
        File folder = new File(Environment.getExternalStorageDirectory()+ File.separator + "DebugData");

        if(!folder.exists()){
            folder.mkdir();
        }
    }

public  boolean isStoragePermissionGranted() {
    if (Build.VERSION.SDK_INT >= 23) {
        if (checkSelfPermission(Android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED) {
            return true;
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
            return false;
        }
    }
    else { //permission is automatically granted on sdk<23 upon installation
        return true;
    }
}

上記のコードは私にとってはうまくいき、あなたのためにうまくいくことを願っています。

4
Bookan

同じ問題がありました。 Android 6でテストしていて、ランタイムのWRITE_EXTERNAL_STORAGE権限をチェックしなかったことがわかりました。

3
stoefln

まず、new File()は、ファイル接続用のオブジェクトを作成するだけです。
このファイルを使用したい、ファイルが存在する、またはcreateNewFile()
このファイルを使用してディレクトリを作成する場合は、ファイルが存在することを確認し、isDirectory()の後にmkDir()を実行します。
次に、チェックEnvironment.getExternalStorageDirectoryは可変パスです。
_DDMSまたはADBを仕事に使用できます。
さらに、何かエラーが発生したときに外部ストレージの読み取り権限を追加すると思います。

2
Amadas

Androidデバイスを実行している場合、mkdir()関数を呼び出す前にユーザーからの許可を要求する必要があります。サンプルコードを含む私の以前の答えは https://stackoverflow.com/a/38694026/508971

1
Diiiiii

通常、私はこれを行います:

_/**
 * Return a dedicated directory named "MyApp" at the top of external storage
 */
public static file getDataDir() {
    File sdcard = Environment.getExternalStorageDirectory();
    if( sdcard == null || !sdcard.isDirectory() ) {
        // TODO: warning popup
        Log.w(TAG, "Storage card not found " + sdcard);
        return null;
    }
    File dataDir = new File(sdcard, "MyApp");
    if( !confirmDir(dataDir) ) {
        // TODO: warning popup
        Log.e(TAG, "Unable to create " + dataDir);
        return null;
    }
    return dataDir;
}   

private static boolean confirmDir(File dir) {
    if (dir.isDirectory()) return true;  // already exists
    if (dir.exists()) return false;      // already exists, but is not a directory
    return dir.mkdirs();                 // create it
}       
_

また、この権限をマニフェストに追加します。

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

(sdcardではなく)アプリのプライベートストレージ(通常は/ data /の下)が必要な場合は、getDir()getFilesDir()fileList()openFileInput()openFileOutput()など.

API 8以降のsdcard内にプライベートディレクトリを取得するヘルパー関数もあります:getExternalFilesDir()getExternalCacheDir()など。

0
Edward Falk