安卓如何申請sd卡權限並寫入文件

最近項目有需求,需要向sd卡寫入文件,在網上找了一大堆文章,很多文章都是吧Internal Storage當成了sd卡,到最後解決辦法都變成了如何動態申請權限了。
在此記錄一下我的解決辦法,在安卓4.4之後,使用android.permission.WRITE_EXTERNAL_STORAGE權限已經不能向外置sd卡里面寫文件了,申請外置sd卡的權限需要使用google提供的Storage Access Framework,具體使用DocumentFile進行文件的寫入,而不能使用OutputStream寫文件,無論是否有權限,否則會報FileNotFound錯誤。
下面的代碼先申請sd卡的權限,然後在sd卡根目錄寫入一個名爲123.txt文件

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_simpletest);
        requestSdCardUriPermission(this, 2);
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // real write file to sdcard
        if (requestCode == 2 && resultCode == Activity.RESULT_OK) {
            Uri uri = data.getData();
            DocumentFile documentFile = DocumentFile.fromTreeUri(this, uri);
            DocumentFile file = documentFile.createFile("text/plain", "123.txt");
            OutputStream outputStream = null;
            try {
                outputStream = getContentResolver().openOutputStream(file.getUri());
                OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
                outputStreamWriter.write("hahahahahahaha");
                outputStreamWriter.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void requestSdCardUriPermission(Activity context, int requestCode) {
        Intent intent;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N
                && android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.P) {
            intent = createAccessIntent(context);
            if (null != intent) {
            //安卓Q以下,一般走這條路,彈出的是小型的授權框
                context.startActivityForResult(intent, requestCode);
            } else {
                intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
                context.startActivityForResult(intent, requestCode);
            }
        } else {
        // 安卓Q必須走這裏,因爲上面的方法會導致授權不成功
            intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
            context.startActivityForResult(intent, requestCode);
        }
    }

    private Intent createAccessIntent(Context context) {
        File file = new File(getSDCardName());
        StorageManager storageManager =
                (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
        StorageVolume volume;
        if (null != storageManager) {
            volume = storageManager.getStorageVolume(file);
            if (null != volume) {
                return volume.createAccessIntent(null);
            }
        }
        return null;
    }

    /**
     * get sdcard name
     * @return sdcard name
     */
    public String getSDCardName() {
        StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            List<StorageVolume> storageVolumeList = storageManager.getStorageVolumes();
            for (StorageVolume storageVolume : storageVolumeList) {
                if (storageVolume.isRemovable()) {
                    return storageVolume.getUuid();
                }
            }
        }
        return null;
    }
}

獲取權限由requestSdCardUriPermission完成,主要是建立一個Intent,然後startActivity去完成sd的授權,在安卓Q版本以下,授權界面是一個小的對話框,在安卓Q上面就是真正跳到另一個界面完成授權,完成授權就會返回到當前Activity的onActivityResult方法,在此處完成sd卡的文件的寫入。
下一篇文章介紹一種簡化sd卡權限申請的過程;如何優雅的申請sd卡權限

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章