Local backup to/from zip old api permission fix

This commit is contained in:
Yuriy Liskov
2026-03-10 05:48:25 +02:00
parent 05f5f92427
commit 0a6496fe18
6 changed files with 59 additions and 79 deletions

View File

@@ -7,12 +7,12 @@ import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build.VERSION;
import android.os.Environment;
import android.provider.OpenableColumns;
import android.widget.Toast;
import androidx.core.content.FileProvider;
import com.liskovsoft.sharedutils.helpers.FileHelpers;
import com.liskovsoft.smartyoutubetv2.common.R;
import com.liskovsoft.smartyoutubetv2.common.app.presenters.settings.BackupSettingsPresenter;
import com.liskovsoft.smartyoutubetv2.common.misc.MotherActivity.OnResult;
@@ -27,8 +27,8 @@ public class BackupAndRestoreHelper implements OnResult {
private final Context mContext;
private Runnable mOnSuccess;
private final String[] mPreferredFileManagers = {
"com.lonelycatgames.Xplore",
"com.ghisler.android.TotalCommander",
"com.lonelycatgames.Xplore",
"com.alphainventor.filemanager",
"pl.solidexplorer2"
};
@@ -42,7 +42,7 @@ public class BackupAndRestoreHelper implements OnResult {
// return;
//}
File mediaDir = getExternalMediaDirectory();
File mediaDir = FileHelpers.getExternalMediaDirectory(mContext);
File dataDir = new File(mediaDir, "data");
if (!dataDir.exists()) return;
@@ -60,7 +60,8 @@ public class BackupAndRestoreHelper implements OnResult {
private void openFileManager(Uri uri) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("*/*"); // intent.setType("application/zip");
//intent.setType("application/zip");
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -111,7 +112,7 @@ public class BackupAndRestoreHelper implements OnResult {
if (data == null) return;
File mediaDir = getExternalMediaDirectory();
File mediaDir = FileHelpers.getExternalMediaDirectory(mContext);
File dataDir = new File(mediaDir, "data");
if (!mediaDir.exists()) mediaDir.mkdirs();
@@ -126,7 +127,8 @@ public class BackupAndRestoreHelper implements OnResult {
copyUriToDir(uri, zipFile);
// Cleanup previous data
deleteRecursive(dataDir);
//deleteRecursive(dataDir);
FileHelpers.delete(dataDir);
dataDir.mkdirs();
if (ZipHelper2.hasRootDir(zipFile, "data")) {
@@ -152,11 +154,12 @@ public class BackupAndRestoreHelper implements OnResult {
try {
// Target folder: /Android/media/<package>/data
File mediaDir = getExternalMediaDirectory();
File mediaDir = FileHelpers.getExternalMediaDirectory(mContext);
File dataDir = new File(mediaDir, "data");
// Remove old data
if (dataDir.exists()) deleteRecursive(dataDir);
//if (dataDir.exists()) deleteRecursive(dataDir);
if (dataDir.exists()) FileHelpers.delete(dataDir);
// Copy ZIP from URI to temporary file
File tempZip = new File(mediaDir, "imported_backup.zip");
@@ -238,56 +241,4 @@ public class BackupAndRestoreHelper implements OnResult {
}
return null;
}
@SuppressWarnings("deprecation")
private File getExternalStorageDirectory() {
File result;
if (VERSION.SDK_INT > 29) {
result = mContext.getExternalMediaDirs()[0];
if (!result.exists()) {
result.mkdirs();
}
} else {
result = Environment.getExternalStorageDirectory();
}
return result;
}
private File getExternalMediaDirectory() {
File result = null;
if (VERSION.SDK_INT >= 21) {
File[] dirs = mContext.getExternalMediaDirs();
if (dirs != null && dirs.length > 0) {
result = dirs[0];
}
}
if (result == null) {
result = new File(
Environment.getExternalStorageDirectory(),
"Android/media/" + mContext.getPackageName()
);
}
if (!result.exists()) {
result.mkdirs();
}
return result;
}
private void deleteRecursive(File f) {
if (!f.exists()) return;
if (f.isDirectory()) {
File[] children = f.listFiles();
if (children != null) {
for (File c : children) deleteRecursive(c);
}
}
f.delete();
}
}

View File

@@ -92,12 +92,8 @@ public class BackupAndRestoreManager implements MotherActivity.OnPermissions {
private File getExternalStorageDirectory() {
File result;
if (hasAccessOnlyToAppFolders() && VERSION.SDK_INT >= 21) {
result = mContext.getExternalMediaDirs()[0];
if (!result.exists()) {
result.mkdirs();
}
if (hasAccessOnlyToAppFolders()) {
result = FileHelpers.getExternalMediaDirectory(mContext);
} else {
result = Environment.getExternalStorageDirectory();
}
@@ -149,8 +145,12 @@ public class BackupAndRestoreManager implements MotherActivity.OnPermissions {
return;
}
// remove old backup
if (currentBackup.isDirectory()) {
if (hasAccessOnlyToAppFolders()) {
File mediaDir = FileHelpers.getExternalMediaDirectory(mContext);
File dataDir = new File(mediaDir, "data");
FileHelpers.delete(dataDir);
} else if (currentBackup.isDirectory()) { // plain sdcard storage
// remove old backup <app_id>
FileHelpers.delete(currentBackup);
}
@@ -283,10 +283,7 @@ public class BackupAndRestoreManager implements MotherActivity.OnPermissions {
}
public String getBackupRootPath() {
if (hasAccessOnlyToAppFolders()) {
return null; // Android 11+: only backup through the file manager (no shared dir)
}
// NOTE: Android 11+ only backup through the file manager (no shared dir)
return String.format("%s/data", getExternalStorageDirectory());
}

View File

@@ -2,19 +2,33 @@ package com.liskovsoft.smartyoutubetv2.common.misc;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build.VERSION;
import android.os.Bundle;
import androidx.annotation.NonNull;
import com.liskovsoft.sharedutils.helpers.PermissionHelpers;
public class BackupReceiverActivity extends Activity {
private BackupAndRestoreHelper mRestoreHelper;
private Runnable mPendingHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRestoreHelper = new BackupAndRestoreHelper(this);
mRestoreHelper.handleIncomingZip(getIntent());
finish();
// Android 11+ (API 30+) removed the need for storage permission
// when accessing files via content:// URIs. Apps are granted temporary
// access to the URI by the sender, so you can read the file without
// READ_EXTERNAL_STORAGE.
if (PermissionHelpers.hasStoragePermissions(this) || VERSION.SDK_INT > 29) {
restoreData();
finish();
} else {
mPendingHandler = this::restoreData;
PermissionHelpers.verifyStoragePermissions(this);
}
}
@Override
@@ -23,4 +37,22 @@ public class BackupReceiverActivity extends Activity {
mRestoreHelper.handleIncomingZip(intent);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PermissionHelpers.REQUEST_EXTERNAL_STORAGE) {
if (grantResults.length >= 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (mPendingHandler != null) {
mPendingHandler.run();
mPendingHandler = null;
}
}
finish();
}
}
private void restoreData() {
mRestoreHelper = new BackupAndRestoreHelper(this);
mRestoreHelper.handleIncomingZip(getIntent());
}
}

View File

@@ -127,7 +127,7 @@ android {
productFlavors {
stbeta {
applicationId "org.smarttube.beta"
//targetSdkVersion project.properties.compileSdkVersion
targetSdkVersion project.properties.compileSdkVersion
}
ststable {
applicationId "org.smarttube.stable"