偶然在看網友們在Google Play Store 裡的留言,發現有人說會crash, 他用的 Android 是 6.0 版,窮到爆的我,怎麼可能有錢去買設備來測,還好前陣子下載了 Genymotion,正好解決 Android 6.0 遇到的問題。
實際 debug 後看到的錯誤訊息是:
java.io.IOException: open failed: ENOENT (No such file or directory)
在 AndroidManifest.xml 也有宣告權限:
<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” />
寫入檔案前,也有先create dirs:
final File dir = new File(root_path);
dir.mkdirs(); //create folders where write files
試到這裡,這樣還是不行。
建立檔案先,取出權限看看:
int permissionCheck = ContextCompat.checkSelfPermission(getActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE);
permissionCheck 結果是 true, 有權限,為什麼還是不能寫入 @_@;
最後解法是用這一段 code,新的 Android 存取外部共用空間時,不能偷偷摸摸存取,要設備主人的同意。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Request user permissions in runtime */
ActivityCompat.requestPermissions(MainActivity.this,
new String[] {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
},
100);
/* Request user permissions in runtime */
String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath();
String rootPath = storagePath + "/test";
String fileName = "/test.zip";
File root = new File(rootPath);
if(!root.mkdirs()) {
Log.i("Test", "This path is already exist: " + root.getAbsolutePath());
}
File file = new File(rootPath + fileName);
try {
int permissionCheck = ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
if (!file.createNewFile()) {
Log.i("Test", "This file is already exist: " + file.getAbsolutePath());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
@TargetApi(23)
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case 100:
if (grantResults.length > 0
|| grantResults[0] == PackageManager.PERMISSION_GRANTED
|| grantResults[1] == PackageManager.PERMISSION_GRANTED) {
/* User checks permission. */
} else {
Toast.makeText(MainActivity.this, "Permission is denied.", Toast.LENGTH_SHORT).show();
finish();
}
return;
}
}
}
另一個解法是盡量不要去存取共用空間,改用 getExternalCacheDir()。
public static void storeSnapshot(List<WifiReading> readings, String fileName, Context c) { String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { // We can read and write the external storage try { JSONArray json = readingsToJson(readings); File root = c.getExternalCacheDir(); File jsonFile = new File(root, constructFileName(fileName)); FileOutputStream out; out = new FileOutputStream(jsonFile); out.write(json.toString().getBytes()); out.close(); U.showToast(constructFileName(fileName)); Log.d(TAG, "Successfully stored snapshot to SDCard"); } catch (Exception e) { U.showToast("Could not save the snapshot on the SDCard."); Log.e(TAG, "Could not save the snapshot on the SDCard.", e); } } else { U.showToast("Cannot write to external storage."); } }
相關文章:
Requesting Permissions at Run Time
https://developer.android.com/training/permissions/requesting.html
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.