●補充說明和程式說明
(一)讀寫外部空間資料--在規劃好的資料夾中
1.寫入
=>用android device moniter看檔案位置會在如下圖的地方,這裡不需要使用權限,但當別的程式有完整讀取sd卡的權限時,就可以讀取到這邊的檔案,隱私性安全較差
public void outWrite(View view) {
String path = getExternalFilesDir("file").getAbsolutePath();
String fname=path + File.separator + "test1.txt";
try {
FileWriter fw = new FileWriter(fname);
BufferedWriter bw = new BufferedWriter(fw);
bw.write("happy to find you");
bw.newLine();
bw.write("it is sad");
bw.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
**說明:
1. 取得外部存檔的資料夾位置:getExternalFilesDir(檔案類型):參數的檔案類型可以自訂
=>File getExternalFilesDir (String type)
=>Returns absolute paths to application-specific directories on all shared/external storage devices where the application can place persistent files it owns.
2.後面做法都跟之前(BufferReader and BufferWriter)一樣
2.讀取
public void outRead(View view) {
String path = getExternalFilesDir("file").getAbsolutePath();
String fname=path + File.separator + "test1.txt";
try {
FileReader fr = new FileReader(fname);
BufferedReader br = new BufferedReader(fr);
String str;
while ((str=br.readLine()) != null)
{
Log.d("FNAME", "Read:" + str);
}
br.close();
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
(二)讀寫外部空間資料(自由的尋覽sd卡)
=>但現在android不建議如此做,基於隱私的考量以及避免在外部空間製造很多垃圾
=>先在AndroidManifest.xml設定權限(只要想要存取規劃的資料夾外的資料都要設定權限)
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
1.android6(api<23)以前的寫入
File f = Environment.getExternalStorageDirectory();
Log.d("FNAME","read"+f.getAbsolutePath());
File f2 = new File(f.getAbsolutePath()
+ File.separator + "mydata");
f2.mkdir();
File txtFile = new File(f2.getAbsolutePath()
+ File.separator + "data5.txt");
try {
FileWriter fw = new FileWriter(txtFile);
BufferedWriter bw = new BufferedWriter(fw);
bw.write("this is test");
bw.newLine();
bw.write("This is test2");
bw.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
**說明
1.Environment.getExternalStorageDirectory():取得sd卡路徑
=>File getExternalStorageDirectory ()
=>Return the primary shared/external storage directory.
=>前面兩筆是使用getExternalFilesDir("file").getAbsolutePath();取得的路徑=>是android指定的不需要授權的資料夾
=>後面一筆是使用Environment.getExternalStorageDirectory().getAbsolutePath();取得的路徑
2.mkdir()=>Creates the directory named by this abstract pathname.(建立資料夾mydata)
3.建立資料夾內容
4.android6以前的權限設定如上即可,使用早期版本的模擬器測試,只要有上面權限設定,寫入後就會在sdcard資料夾中產生我們要的資料夾
2.android6(api<23)以前的讀取
File f = Environment.getExternalStorageDirectory();
Log.d("FNAME", f.getAbsolutePath());
File f2 = new File(f.getAbsolutePath()
+ File.separator + "mydata");
File txtFile = new File(f2.getAbsolutePath()
+ File.separator + "data5.txt");
try {
FileReader fr = new FileReader(txtFile);
BufferedReader br = new BufferedReader(fr);
String str;
while ((str=br.readLine()) != null)
{
Log.d("FNAME", "Read:" + str);
}
br.close();
fr.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
**說明:
1.當使用android6以後的模擬器,只在AndroidManifest.xml設定權限會不夠,用android6以後的模擬器測試這段讀取程式,就會出現下列exception:FileNotFoundException,因為在android6以後的模擬器寫入不成功,所以也讀不到檔案
2.做法有兩種一種是讓使用者自己設定,在手機=>設定=>app設定=>app permisssions=>storage permissions=>我們app開啟
但這是不好的做法,應該是把設定寫在程式裡
3.android6以後的寫入與讀取
=>程式的流程應該是在每次要使用時,都會檢查程式是否有被授予權限,如果沒有就要跳出視窗詢問使用者是否授予權限,且這個跳出的視窗是android訂好的規格,我們不能改變或自訂
=>使用者決定允許或拒絕後,callback結果
=>參考檔案可以發現WRITE和READ是同一類權限,有開WRITE則READ就會有開
=>實際上讀取應該也要加權限,否則若是還沒有授權寫入或是被取消授權後直接按讀取就會有問題
public void nolimitwrite(View view) {
int permission = ActivityCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { //未取得權限,向使用者要求允許權 //因為要辨別使用者允許的是寫入還是讀取所以這邊的string只放write ActivityCompat.requestPermissions(this, new String[]{WRITE_EXTERNAL_STORAGE}, REQUEST_EXTERNAL_STORAGE); }else{ //已有權限,可進行檔案存取 sdwrite(); } } @Override public void onRequestPermissionsResult (int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode==REQUEST_EXTERNAL_STORAGE){ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //取得權限,進行檔案存取 String str=permissions[0]; //這邊用if判斷時要用equals(),不能用== if(str.equals("android.permission.WRITE_EXTERNAL_STORAGE") ){ sdwrite(); }else { sdread(); } } else { //使用者拒絕權限,停用檔案存取功能 } } } private void sdwrite(){ File f = Environment.getExternalStorageDirectory(); Log.d("FNAME","read"+f.getAbsolutePath()); File f2 = new File(f.getAbsolutePath() + File.separator + "mydata"); f2.mkdir(); File txtFile = new File(f2.getAbsolutePath() + File.separator + "data5.txt"); try { FileWriter fw = new FileWriter(txtFile); BufferedWriter bw = new BufferedWriter(fw); bw.write("this is test"); bw.newLine(); bw.write("This is test2"); bw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); } } public void nolimitread(View view) { int permission = ActivityCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { //未取得權限,向使用者要求允許權 ActivityCompat.requestPermissions(this, new String[]{READ_EXTERNAL_STORAGE}, REQUEST_EXTERNAL_STORAGE); }else{ //已有權限,可進行檔案存取 sdread(); } } private void sdread(){ File f = Environment.getExternalStorageDirectory(); Log.d("FNAME", f.getAbsolutePath()); File f2 = new File(f.getAbsolutePath() + File.separator + "mydata"); File txtFile = new File(f2.getAbsolutePath() + File.separator + "data5.txt"); try { FileReader fr = new FileReader(txtFile); BufferedReader br = new BufferedReader(fr); String str; while ((str=br.readLine()) != null) { Log.d("FNAME", "Read:" + str); } br.close(); fr.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
**說明
1.先檢查是否已經取得使用者的授權,檢查權限語法:int checkSelfPermission(Context context, String permission)
=>Determine whether you have been granted a particular permission.
=>String: The name of the permission being checked.
=>return int:PERMISSION_GRANTED if you have the permission, or PERMISSION_DENIED if not.
=>PackageManager.PERMISSION_GRANTED
int PERMISSION_GRANTED
Permission check result: this is returned by checkPermission(String, String) if the permission has been granted to the given package.
Constant Value: 0 (0x00000000)
=>PackageManager.PERMISSION_DENIED
int PERMISSION_DENIED
Permission check result: this is returned by checkPermission(String, String) if the permission has not been granted to the given package.
Constant Value: -1 (0xffffffff)
2.如果沒有取得權限,跳出允許授權對話框
=>requestPermissions:void requestPermissions (Activity activity, String[] permissions, int requestCode)
=>第一個參數是context,第二個參數是要求允許的權限,第三個參數是本次請求的辨識編碼(因為callback時要辨認是哪裡callback的)
=>因為後面要辨別這邊帶入的權限是write還是read,所以兩個click放的參數不同
3.把寫入和讀取的程式寫成兩個method,當授權ok或是已經有授權的時候直接呼叫這兩個方法
4.當跳出授權對話框後,對使用者的確認與取消授權做處理,用onRequestPermissionsResult
=>void onRequestPermissionsResult (int requestCode, String[] permissions, int[] grantResults)
Callback for the result from requesting permissions.
=>requestCodeint: The request code passed in requestPermissions(android.app.Activity, String[], int)
=>permissionsString: The requested permissions. Never null.
=>grantResultsint: The grant results for the corresponding permissions which is either PERMISSION_GRANTED or PERMISSION_DENIED. Never null.
5.先確認requestCode正確,再確認授權結果必須為GRANTED,再判斷傳回的permission為哪一個,來決定下一步是要寫入還是讀取,這邊的permissions陣列判斷不可以用==而是要用equals,因為在前面有new String,是不同物件不能用==,==兩邊必須是相同的參考物件,相關資訊可以參考說明:https://ppt.cc/fam5fx
6.如果想要查詢pemissions字串中的內容,可以用log看
Log.d("permission","read:"+permissions[0]);
●程式參考(GitHub):讀寫外部資料與設定讀寫外部資料權限
文章標籤
全站熱搜
留言列表