web-dev-qa-db-ja.com

Android SDカード上のKitKat4.4フォルダー

Android 4.4(EACCES Permission Denied)で、SDカード(外部ストレージ)へのファイルの書き込みに適用される新しいアクセス許可に違反しました。

KitKatの前は、書き込み可能なフォルダーを次のように設定していました。

mfolder = Environment.getExternalStorageDirectory().getPath() + "/appfiles";

しかし、何時間も検索した後、ファイルの書き込みを可能にする4.4デバイスでは、これを次のように変更する必要があるという結論に達しました。

mfolder = Environment.getExternalStorageDirectory().getPath() + "/Android/data/com.xyz.abc/appfiles";

したがって、mfolderは次のようになります:/mnt/sdcard/Android/data/com.xyz.abc/appfiles

これは正しいですか、4.4デバイスがファイルを書き込めるようにSDカードに上記のようなフォルダーを作成しますか?

mfolderは、共有設定に保存する文字列です。

次に、API> = 19の場合に1回実行されるこのコードがあり、mfolder文字列を変更してから、すべてのファイルを古いフォルダーから新しい「KitKat」フォルダーにコピーします。

if (Android.os.Build.VERSION.SDK_INT>=19){
        if (!mfolder.contains("/Android/data/com.xyz.abc/appfiles")){
            if (prefs.getBoolean("kitkatcheck", false)==false){

                //update mfolder from
                      // /mnt/sdcard/appfiles
                      // to
                      // /mnt/sdcard/Android/data/com.xyz.abc/appfiles
                String prekitkatfolder = mfolder;
                String kitkatfolder = mfolder.replace("/appfiles", "/Android/data/com.xyz.abc/appfiles");
                mfolder = kitkatfolder;
                try {
                    File sd = new File(mfolder);
                    if(!sd.exists() || !sd.isDirectory()) {
                        sd.mkdirs();
                    }
                } catch (Exception e) {
                    Toast.makeText(getBaseContext(), "Error creating KitKat folder!\n" + e.toString(), Toast.LENGTH_LONG).show();
                    return;
                }
                prefEditor.putString("patternfolder", mfolder);
                prefEditor.putBoolean("kitkatcheck", true);
                prefEditor.commit();

                //copy files and folder from old appfiles folder to new.
                AllFiles.clear();
                listFilesAndFilesSubDirectories(prekitkatfolder);
                if (AllFiles.size()>0){
                    for (File child : AllFiles ) {
                        try {

                            File dest = new File(child.toString().replace(prekitkatfolder, kitkatfolder));


                            try {
                                String filePath = dest.getPath().substring(0, dest.getPath().lastIndexOf(File.separator));
                                File subfolder = new File(filePath);
                                if(!subfolder.exists() || !subfolder.isDirectory()) {
                                    subfolder.mkdirs();
                                }
                            } catch (Exception ex) {
                            }

                            copyFile(child, dest);  

                        } catch (Throwable t) {

                        }
                    }

                }


            }

        }

次に、ファイルが新しいフォルダーにコピーされたことと、新しいアクセス許可のために古いprekitkatfolderフォルダーを手動で削除する必要があることをユーザーに通知します。新しい4.4の権限により、ストックファイルマネージャーを持っている場合、またはsdカードをマウント解除してPCに配置した場合にのみ、これを実行できると思いますか?

また、私たちにとって、これらの4.4の権限は、キットカットを使用するすべてのユーザーに影響を与えているわけではないようです。外部ストレージの元のフォルダの場所に書き込むことができるものもあれば、EACCES(Permission Denied)エラーが発生するものもあります。誰かがこれがなぜであるかについて何か光を当てることができますか、それは外部ストレージを使用するすべての4.4デバイスに適用されると思いますか?

実際の4.4デバイスがないため、エミュレーター(API 19)を使用してこのコードをテストする必要がありますが、EACCES PermissionDeniedエラーは発生しません。それで、上記のコードを含むベータ版をリリースし、コピーされたファイルが最終的に内部ストレージに保存されると言われましたが、どうすればよいでしょうか?

私たちが間違っていることについてのアイデア、事前に感謝します

16
Mark

更新されたソリューション。

これにより、KitKatの正しい場所にフォルダーが設定および作成されます。

mfolder = this.getExternalFilesDir("asubfoldername").getAbsolutePath();

ただし、これは完全な証拠ではありません。Androidデバイスに内部と外部の両方のセカンダリストレージの場所がある場合、上記では内部のストレージの場所が使用されます。パスが必要なため、実際には必要なものではありません。取り外し可能なSDカード、またはより良いのは、利用可能な空き容量が最も多いセカンダリストレージロケーションへのパスです。

File[] possible_KitKat_mounts = getExternalFilesDirs(null);

GetExternalFilesDirsの末尾の「s」に注意してください。これにより、セカンダリ外部ストレージの場所の配列が作成されます。

for (int x = 0; x < possible_KitKat_mounts.length; x++) {
    //Log.d("test", "possible_KitKat_mounts " + possible_KitKat_mounts[x].toString());
    boolean isgood=false;
    if (possible_KitKat_mounts[x] != null){
        isgood = test_mount(possible_KitKat_mounts[x].toString());  
        if (isgood==true){
            arrMyMounts.add(newymounts(Device_get_device_info(possible_KitKat_mounts[x].toString()), possible_KitKat_mounts[x].toString()));
        }   
    }
}                           

//sort arrMyMounts size so we can use largest
Collections.sort(arrMyMounts, new Comparator<mymounts>(){
    public int compare(mymounts obj1, mymounts obj2){
        return (obj1.avaliablesize > obj2.avaliablesize) ? -1: (obj1.avaliablesize > obj2.avaliablesize) ? 1:0 ;
    }
}); 


if (arrMyMounts.size()>0){
    mfolder = arrMyMounts.get(0).name + "/asubfoldername";
    //Log.d("test", "selected KitKat mount " + kitkatfolder);   
}else{
    //do something else...
}

Possible_KitKat_mountsの配列から、test_mountを介してチェックし、選択した場所に実際に書き込むことができるかどうかを確認し、成功した場合は、その場所をarrMyMountsに追加します。

ArrMyMountsを並べ替えることで、利用可能な空き容量が最も多い場所を取得できます。

ちょっとプレスト、arrMyMounts.get(0).nameは、最も空き容量のあるKitKatセカンダリストレージの場所です。

7
Mark

GoogleはAndroid 4.4で外部ストレージデバイスへの書き込みアクセスをブロックしました。それらが変更されるまで、rootなしで元に戻す方法はありません。

詳細: https://groups.google.com/forum/#!msg/Android-platform/14VUiIgwUjY/UsxMYwu02z0J

Minisdカードスロットを備えたキットカットを搭載した一部のデバイスで動作している可能性があります。それは紛らわしい :(

5
radzio