您可能已經知道,除其他外,Google 更改了外部存盤訪問權限的準則。嘗試了谷歌檔案中的所有提示和技巧,但對我不起作用。一旦我點擊“備份”按鈕和“確定”,應用程式就會崩潰。我沒有更多的想法來解決這個問題。現在我請教各位專家。我對每一個小費都很滿意。
- 安卓 11
- 目標SDK 31
我將分享相關代碼,使它們盡可能清晰。
顯現:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
實用程式
public static Boolean askForReadPermission(final Activity activity, final PermissionCallback permissionCallback, View view){
if(android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Nammu.checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)){
return true;
}
else{
final String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (Nammu.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Snackbar.make(view, activity.getString(R.string.error_permission_backup),
Snackbar.LENGTH_INDEFINITE)
.setAction("OK", new View.OnClickListener() {
@Override
public void onClick(View view) {
Nammu.askForPermission(activity, permissions, permissionCallback);
}
}).show();
} else {
Nammu.askForPermission(activity, permissions, permissionCallback);
}
return false;
}
}
public static String getStorageDir(){
String path = Environment.getExternalStorageDirectory().getAbsolutePath() "/myApp";
File f = new File(path);
if(!f.exists()) if(!f.mkdirs()) return null;
return f.getAbsolutePath();
}
public static String getStorageDirForBackup(){
String path = Environment.getExternalStorageDirectory().getAbsolutePath() "/My_Backup";
File f = new File(path);
if(!f.exists()) if(!f.mkdirs()) return null;
return f.getAbsolutePath();
}
備份檔案
public class RealmBackup {
private static final String TAG = "Backuplog";
private final String EXPORT_REALM_FILE_NAME = "backup.realm";
private final Activity activity;
private final Realm realm;
public RealmBackupRestore(Activity activity, Realm realm) {
this.activity = activity;
this.realm = realm;
}
@SuppressLint("StaticFieldLeak")
public void backup() {
new AsyncTask<Void, Void, Boolean>() {
private SweetAlertDialog dialog;
@Override
protected void onPreExecute() {
dialog = new SweetAlertDialog(activity, SweetAlertDialog.PROGRESS_TYPE);
dialog.setContentText(activity.getString(R.string.settings_do_backup));
dialog.setTitleText("");
dialog.show();
}
@Override
protected Boolean doInBackground(Void... params) {
Realm realm = Realm.getDefaultInstance();
File exportRealmFile;
exportRealmFile = new File(Utils.getStorageDir(), EXPORT_REALM_FILE_NAME);
realm.writeCopyTo(exportRealmFile);
File zipFile = new File(Utils.getStorageDirForBackup(), "backup_" System.currentTimeMillis() ".zip");
zipFile.delete();
File wholeDirectory = new File(Utils.getStorageDir() "/");
ZipUtil.pack(wholeDirectory, zipFile);
exportRealmFile.delete();
realm.beginTransaction();
Objects.requireNonNull(Settings.getSettings(realm)).setLastBackup(new Date());
realm.commitTransaction();
realm.close();
return true;
}
@Override
protected void onPostExecute(Boolean result) {
dialog.cancel();
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(activity);
alertBuilder
.setMessage(activity.getString(R.string.settings_backup_stored))
.setNeutralButton(activity.getString(R.string.generell_ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
private String dbPath(){
return realm.getPath();
}
}
片段備份.java
backup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(getContext());
alertBuilder
.setMessage(R.string.settings_backup_store_dialog)
.setPositiveButton(R.string.generell_ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if(!Utils.askForReadPermission(getActivity(), permissionCallbackBackup ,backup))return;
realmBackupRestore.backup();
}
})
.setNegativeButton(R.string.generell_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
}
});
日志貓:
2021-12-28 16:38:54.375 28406-28575/devs.myApp E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: devs.myApp, PID: 28406
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$4.done(AsyncTask.java:415)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: io.realm.exceptions.RealmFileException: Unable to open a realm at path '/backup.realm'. Please use a path where your app has read-write permissions. (open("/backup.realm") failed: Read-only file system) (/backup.realm) in /home/cc/repo/realm/release/realm/realm-library/src/main/cpp/io_realm_internal_OsSharedRealm.cpp line 407 Kind: PERMISSION_DENIED.
at io.realm.internal.OsSharedRealm.nativeWriteCopy(Native Method)
at io.realm.internal.OsSharedRealm.writeCopy(OsSharedRealm.java:343)
at io.realm.BaseRealm.writeCopyTo(BaseRealm.java:274)
at io.realm.Realm.writeCopyTo(Realm.java:135)
at devs.myApp.utils.RealmBackupRestore$1.doInBackground(RealmBackupRestore.java:65)
at devs.myApp.utils.RealmBackupRestore$1.doInBackground(RealmBackupRestore.java:45)
at android.os.AsyncTask$3.call(AsyncTask.java:394)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
uj5u.com熱心網友回復:
嘗試添加清單
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
并要求用戶在應用程式運行時授予檔案管理權限
uj5u.com熱心網友回復:
字串路徑 = Environment.getExternalStorageDirectory().getAbsolutePath() "/myApp";
在 Android 11 設備上,應用程式無法在外部存盤的根目錄中創建自己的檔案夾。
而是嘗試在例如公共檔案目錄中創建您自己的檔案夾。
您應該更好地檢查 mkdir() 是否確實創建了想要的檔案夾。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/396403.html
標籤:爪哇 安卓 领域 android-权限 android-外部存储
