1. 程式人生 > >android 6.0 open failed enoent (no such file or directory)

android 6.0 open failed enoent (no such file or directory)

偶然在看網友們在Google Play Store 裡的留言,發現有人說會crash, 他用的 Android 是 6.0 版,窮到爆的我,怎麼可能有錢去買裝置來測,還好前陣子下載了 Genymotion,正好解決 Android 6.0 遇到的問題。

Screenshot 2016-06-19 01.23.40

實際 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, 有許可權,為什麼還是不能寫入 @[email protected]

;

最後解法是用這一段 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

Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app.