Android4.4 对 Secondary External Storage 的访问

Android在KitKat之后对Secondary External Storage(SES)的访问做了很大的修改。普通APP不再可以随意写整个SES,只能在属于自己的目录中进行写操作,比如Android/data/com.lnmcc.testsdcard,最后部分为APP的包名。并且APP在访问自己的私有文件夹时不再需要任何的权限。

在我的系统中,我把sd卡挂载到了/storage/sdcard1。 下面的代码片段将获取APP在SES上的的私有目录路径,之后就可以在这个路径下做读写操作了。

        private String SDCard1 = null;

        File[] files = getExternalFilesDirs(null);
        for (File file : files) {
            Log.d(TAG, file.getAbsolutePath());
            // sdcard1 is the external storage(SD card) on my platform
            String path = file.getAbsolutePath();
            if (path.contains("/storage/sdcard1")) {
                // found it
                SDCard1 = path;
                Log.d(TAG, SDCard1);
                break;
            }
        }

完整的DEMO:

public class MainActivity extends Activity implements OnClickListener {

    private static final String TAG = "TestSDCard";

    private String SDCard1 = null;

    private Button listBtn;
    private Button testWriteBtn;
    private TextView txt;
    private StringBuilder sb;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        File[] files = getExternalFilesDirs(null);
        for (File file : files) {
            Log.d(TAG, file.getAbsolutePath());
            // sdcard1 is the external storage(SD card) on my platform
            String path = file.getAbsolutePath();
            if (path.contains("/storage/sdcard1")) {
                // found it
                SDCard1 = path;
                Log.d(TAG, SDCard1);
                break;
            }
        }

        sb = new StringBuilder();

        listBtn = (Button) findViewById(R.id.listBtn);
        listBtn.setOnClickListener(this);

        testWriteBtn = (Button) findViewById(R.id.testWriteBtn);
        testWriteBtn.setOnClickListener(this);

        txt = (TextView) findViewById(R.id.txt);
    }

    @Override
    public void onClick(View v) {
        int btnId = v.getId();

        switch (btnId) {
        case R.id.listBtn:
            new AsyncTask<Void, Void, Void>() {

                @Override
                protected void onPreExecute() {
                    listBtn.setEnabled(false);
                }

                @Override
                protected void onPostExecute(Void result) {
                    txt.setText(sb.toString());
                    listBtn.setEnabled(true);
                }

                @Override
                protected Void doInBackground(Void... params) {
                    sb.delete(0, sb.length());
                    readFile(SDCard1);
                    return null;
                }
            }.execute();
            break;

        case R.id.testWriteBtn:

            new AsyncTask<Void, Void, Void>() {

                @Override
                protected void onPreExecute() {
                    testWriteBtn.setEnabled(false);
                }

                @Override
                protected void onPostExecute(Void result) {
                    sb.delete(0, sb.length());
                    readFile(SDCard1);
                    txt.setText(sb.toString());
                    testWriteBtn.setEnabled(true);
                }

                @Override
                protected Void doInBackground(Void... params) {
                    newFile(SDCard1);
                    return null;
                }
            }.execute();
            break;

        default:
            break;

        }
    }

    private void newFile(String path) {
        File file = null;

        try {
            file = File.createTempFile("TestSDCard", ".txt", new File(path));
            Log.d(TAG, file.getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void readFile(String path) {
        File file = new File(path);
        if (file.isDirectory()) {
            String[] subFiles = file.list();

            sb.append("Directory: ");
            sb.append(file.getName());
            sb.append("\n");

            for (String subFile : subFiles) {
                String subPath = file.getAbsolutePath() + "/" + subFile;
                Log.d(TAG, subPath);
                readFile(subPath);
            }
        } else {
            sb.append("file: ");
            sb.append(file.getName());
            sb.append("\n");
        }
    }
}

github: KitKatSecondaryExternalStorageRWDemo.git ref: https://source.android.com/devices/storage/ ref: https://developer.android.com/guide/topics/providers/document-provider.html ref: http://blog.csdn.net/zjbpku/article/details/25161131