Remove reliance on WRITE_EXTERNAL_STORAGE
https://developer.android.com/about/versions/11/privacy/storage#permissions-target-11
This commit is contained in:
parent
bfc1b3d546
commit
5e34bd4570
|
@ -478,7 +478,7 @@ export default function SettingsPage() {
|
|||
),
|
||||
},
|
||||
{
|
||||
name: `Backup directory: ${backupString || "Downloads"}`,
|
||||
name: `Backup directory: ${backupString || "Not set yet!"}`,
|
||||
renderItem: (name: string) => (
|
||||
<Button
|
||||
style={{ alignSelf: "flex-start" }}
|
||||
|
@ -522,15 +522,15 @@ export default function SettingsPage() {
|
|||
<Button
|
||||
style={{ alignSelf: "flex-start" }}
|
||||
onPress={async () => {
|
||||
const result = await check(
|
||||
PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE
|
||||
);
|
||||
if (result === RESULTS.DENIED || result === RESULTS.BLOCKED) {
|
||||
await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE);
|
||||
let target = settings.backupDir
|
||||
if (!FileSystem.exists(target)) {
|
||||
const result = await DocumentPicker.pickDirectory();
|
||||
target = result.uri
|
||||
setValue("backupDir", result.uri);
|
||||
}
|
||||
const path = Dirs.DatabaseDir + "/massive.db";
|
||||
await FileSystem.cpExternal(path, "massive.db", "downloads");
|
||||
toast("Database exported. Check downloads.");
|
||||
const error = await NativeModules.BackupModule.once(target);
|
||||
if (error) toast(error);
|
||||
else toast("Database exported.");
|
||||
}}
|
||||
>
|
||||
{name}
|
||||
|
@ -543,13 +543,13 @@ export default function SettingsPage() {
|
|||
<Button
|
||||
style={{ alignSelf: "flex-start" }}
|
||||
onPress={async () => {
|
||||
const result = await check(
|
||||
PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE
|
||||
);
|
||||
if (result === RESULTS.DENIED || result === RESULTS.BLOCKED) {
|
||||
await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE);
|
||||
let target = settings.backupDir
|
||||
if (!target || !FileSystem.exists(target)) {
|
||||
const result = await DocumentPicker.pickDirectory();
|
||||
target = result.uri
|
||||
setValue("backupDir", result.uri);
|
||||
}
|
||||
await NativeModules.BackupModule.exportToCSV();
|
||||
await NativeModules.BackupModule.exportToCSV(target);
|
||||
toast("Exported sets as CSV.");
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
|
|
@ -7,7 +7,6 @@ import android.content.*
|
|||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import com.facebook.react.bridge.Promise
|
||||
import com.facebook.react.bridge.ReactApplicationContext
|
||||
|
@ -22,7 +21,6 @@ class BackupModule(context: ReactApplicationContext?) :
|
|||
val context: ReactApplicationContext = reactApplicationContext
|
||||
|
||||
private val copyReceiver = object : BroadcastReceiver() {
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
val targetDir = intent?.getStringExtra("targetDir")
|
||||
Log.d("BackupModule", "onReceive $targetDir")
|
||||
|
@ -40,7 +38,28 @@ class BackupModule(context: ReactApplicationContext?) :
|
|||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.M)
|
||||
@ReactMethod
|
||||
fun once(target: String, promise: Promise) {
|
||||
Log.d("BackupModule", "once $target")
|
||||
try {
|
||||
val treeUri: Uri = Uri.parse(target)
|
||||
val documentFile = context.let { DocumentFile.fromTreeUri(it, treeUri) }
|
||||
val file = documentFile?.createFile("application/octet-stream", "massive.db")
|
||||
val output = context.contentResolver?.openOutputStream(file!!.uri)
|
||||
val sourceFile = File(context.getDatabasePath("massive.db")!!.path)
|
||||
val input = FileInputStream(sourceFile)
|
||||
if (output != null) {
|
||||
input.copyTo(output)
|
||||
}
|
||||
output?.flush()
|
||||
output?.close()
|
||||
promise.resolve(0)
|
||||
}
|
||||
catch (error: Exception) {
|
||||
promise.reject("ERROR", error)
|
||||
}
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
fun start(baseUri: String) {
|
||||
Log.d("BackupModule", "start $baseUri")
|
||||
|
@ -66,7 +85,6 @@ class BackupModule(context: ReactApplicationContext?) :
|
|||
)
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.M)
|
||||
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||
fun stop() {
|
||||
val alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||
|
@ -77,10 +95,10 @@ class BackupModule(context: ReactApplicationContext?) :
|
|||
}
|
||||
|
||||
@ReactMethod
|
||||
fun exportToCSV(promise: Promise) {
|
||||
fun exportToCSV(target: String, promise: Promise) {
|
||||
try {
|
||||
val db = DatabaseHelper(reactApplicationContext)
|
||||
db.exportToCSV()
|
||||
db.exportToCSV(target, reactApplicationContext)
|
||||
promise.resolve("Export successful!")
|
||||
}
|
||||
catch (e: Exception) {
|
||||
|
|
|
@ -3,7 +3,10 @@ package com.massive
|
|||
import android.content.Context
|
||||
import android.database.sqlite.SQLiteDatabase
|
||||
import android.database.sqlite.SQLiteOpenHelper
|
||||
import android.net.Uri
|
||||
import android.os.Environment
|
||||
import android.util.Log
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import com.opencsv.CSVWriter
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
|
@ -15,16 +18,14 @@ class DatabaseHelper(context: Context) :
|
|||
private const val DATABASE_VERSION = 1
|
||||
}
|
||||
|
||||
fun exportToCSV() {
|
||||
val exportDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
||||
if (!exportDir.exists()) {
|
||||
exportDir.mkdirs()
|
||||
}
|
||||
fun exportToCSV(target: String, context: Context) {
|
||||
Log.d("DatabaseHelper", "exportToCSV $target")
|
||||
val treeUri: Uri = Uri.parse(target)
|
||||
val documentFile = context.let { DocumentFile.fromTreeUri(it, treeUri) }
|
||||
val file = documentFile?.createFile("application/octet-stream", "sets.csv") ?: return
|
||||
|
||||
val file = File(exportDir, "gym_sets.csv")
|
||||
file.createNewFile()
|
||||
|
||||
val csvWrite = CSVWriter(FileWriter(file))
|
||||
context.contentResolver.openOutputStream(file.uri).use { outputStream ->
|
||||
val csvWrite = CSVWriter(outputStream?.writer())
|
||||
val db = this.readableDatabase
|
||||
val cursor = db.rawQuery("SELECT * FROM sets", null)
|
||||
csvWrite.writeNext(cursor.columnNames)
|
||||
|
@ -40,6 +41,7 @@ class DatabaseHelper(context: Context) :
|
|||
csvWrite.close()
|
||||
cursor.close()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(db: SQLiteDatabase) {
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user