Skip to content

Commit 8a4d4b0

Browse files
committed
- api 19 supported
- Threads are replaced with lifecycle aware executor services
1 parent 125d81a commit 8a4d4b0

File tree

11 files changed

+72
-510
lines changed

11 files changed

+72
-510
lines changed

.idea/.name

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/build.gradle

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ android {
99

1010
defaultConfig {
1111
applicationId "com.tos.drivebackup"
12-
minSdk 21
12+
minSdk 19
1313
targetSdk 33
1414
versionCode 1
1515
versionName "1.0"
1616

17+
multiDexEnabled true
18+
1719
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
1820
vectorDrawables {
1921
useSupportLibrary true
@@ -50,6 +52,8 @@ dependencies {
5052
implementation 'com.google.android.material:material:1.8.0'
5153
implementation 'com.google.code.gson:gson:2.10.1'
5254

55+
implementation "androidx.multidex:multidex:2.0.1"
56+
5357
implementation project(':libDriveBackup')
54-
// implementation 'com.github.fcat97:driveBackupApi:1.0.5'
58+
// implementation 'com.github.fcat97:driveBackupApi:1.0.6'
5559
}

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
<uses-permission android:name="android.permission.INTERNET"/>
66

77
<application
8-
android:allowBackup="true"
8+
android:name="androidx.multidex.MultiDexApplication"
9+
android:allowBackup="false"
910
android:dataExtractionRules="@xml/data_extraction_rules"
1011
android:fullBackupContent="@xml/backup_rules"
1112
android:icon="@mipmap/ic_launcher"

app/src/main/java/com/tos/drivebackup/MainActivity.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ import android.widget.TextView
77
import android.widget.Toast
88
import androidx.activity.ComponentActivity
99
import androidx.activity.result.contract.ActivityResultContracts
10+
import androidx.appcompat.app.AppCompatDelegate
1011
import androidx.lifecycle.MutableLiveData
12+
import androidx.multidex.BuildConfig
1113
import com.google.android.material.color.DynamicColors
1214
import com.google.android.material.textfield.TextInputEditText
1315
import com.tos.drivebackup.drive_backup.DriveBackupUtils
1416
import media.uqab.libdrivebackup.GoogleDriveBackupManager
1517
import java.io.File
1618
import java.io.FileReader
19+
import java.util.concurrent.Executors
1720

1821
class MainActivity : ComponentActivity() {
1922
companion object {
@@ -58,6 +61,8 @@ class MainActivity : ComponentActivity() {
5861
DynamicColors.applyToActivitiesIfAvailable(this.application)
5962
setContentView(R.layout.main_activity)
6063

64+
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
65+
6166
rootFolderButton = findViewById(R.id.createFolderButton)
6267
sendButton = findViewById(R.id.sendButton)
6368
fetchButton = findViewById(R.id.fetchButton)
@@ -108,7 +113,7 @@ class MainActivity : ComponentActivity() {
108113

109114
private fun fetchFiles() {
110115
googleDriveBackupManager.getFiles {
111-
printToTerminal("[backups]: \n" + it.joinToString(separator = "\n"))
116+
printToTerminal("[backups]: \n" + it.joinToString(separator = "\n\n"))
112117
}
113118
}
114119

app/src/main/java/com/tos/drivebackup/drive_backup/DriveBackupUtils.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.tos.drivebackup.drive_backup
22

33
import android.content.Context
44
import android.util.Log
5-
import androidx.annotation.RequiresApi
65
import com.google.gson.Gson
76
import com.tos.drivebackup.drive_backup.BackupSchema.CURRENT_BACKUP_SCHEMA_VER
87
import com.tos.drivebackup.drive_backup.BackupSchema.getBackupFile
@@ -12,10 +11,8 @@ import java.io.File
1211
import java.io.FileReader
1312
import java.text.SimpleDateFormat
1413
import java.util.*
15-
import kotlin.collections.List
1614

1715
object DriveBackupUtils {
18-
@RequiresApi(api = 21)
1916
fun backupToDrive(
2017
context: Context,
2118
backupManager: GoogleDriveBackupManager,
@@ -42,7 +39,6 @@ object DriveBackupUtils {
4239
}
4340
}
4441

45-
@RequiresApi(api = 21)
4642
fun restoreBackup(
4743
context: Context,
4844
backupManager: GoogleDriveBackupManager,

app/src/main/res/layout/main_activity.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@
124124
android:id="@+id/signInButton"
125125
android:layout_width="wrap_content"
126126
android:layout_height="wrap_content"
127-
android:text="Sign Out"
127+
android:text="Sign In"
128128
android:layout_marginVertical="8dp"
129129
style="@style/ThemeOverlay.Material3.Button.ElevatedButton"/>
130130

libDriveBackup/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ android {
99
compileSdk 33
1010

1111
defaultConfig {
12-
minSdk 21
12+
minSdk 19
1313
targetSdk 33
1414

1515
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -40,7 +40,7 @@ dependencies {
4040
implementation 'com.google.auth:google-auth-library-oauth2-http:1.16.0'
4141

4242
implementation 'com.google.api-client:google-api-client-android:2.2.0'
43-
implementation 'com.google.android.gms:play-services-auth:20.4.1'
43+
implementation 'com.google.android.gms:play-services-auth:20.5.0'
4444
}
4545

4646

@@ -50,7 +50,7 @@ afterEvaluate {
5050
publications {
5151
maven(MavenPublication) {
5252
group = 'media.uqab.driveBackupApi'
53-
version = '1.0.5'
53+
version = '1.0.6'
5454
artifactId = "driveBackupApi"
5555
from components.release
5656

libDriveBackup/src/main/java/media/uqab/libdrivebackup/GoogleDriveBackupManager.kt

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
11
package media.uqab.libdrivebackup
22

3-
import android.Manifest
43
import android.app.Activity
54
import android.content.Intent
65
import android.util.Log
76
import androidx.activity.ComponentActivity
87
import androidx.activity.result.contract.ActivityResultContracts
98
import androidx.lifecycle.Lifecycle
9+
import androidx.lifecycle.LifecycleEventObserver
10+
import androidx.lifecycle.LifecycleOwner
1011
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential
1112
import media.uqab.libdrivebackup.model.*
12-
import media.uqab.libdrivebackup.model.Constants
1313
import media.uqab.libdrivebackup.useCase.*
1414
import media.uqab.libdrivebackup.useCase.GetCredential.getCredential
1515
import media.uqab.libdrivebackup.useCase.GetOneTapSignInIntent.getSignInIntent
1616
import java.io.File
1717
import java.io.FileOutputStream
1818
import java.util.*
19+
import java.util.concurrent.ExecutorService
20+
import java.util.concurrent.Executors
1921

2022
/**
2123
* A manager class to view, update, delete and modify
@@ -34,19 +36,33 @@ import java.util.*
3436
class GoogleDriveBackupManager(
3537
appID: String,
3638
private val activity: ComponentActivity,
37-
private val credentialID: String,
39+
private val credentialID: String
3840
) {
3941
init {
4042
if (activity.lifecycle.currentState != Lifecycle.State.INITIALIZED) {
4143
throw InitializationException("Must initialize before OnStart but initialized in ${activity.lifecycle.currentState}")
4244
}
4345

46+
// attach an observer to cancel all running executor services
47+
activity.lifecycle.addObserver(object : LifecycleEventObserver {
48+
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
49+
if (event == Lifecycle.Event.ON_DESTROY) {
50+
_executor?.shutdown()
51+
}
52+
}
53+
})
54+
4455
if (credentialID.isBlank()) throw InitializationException("Credential ID not provided")
4556
if (appID.isEmpty()) throw InitializationException("App Name not provided")
4657

4758
Constants.APP_NAME = appID
4859
}
4960

61+
/**
62+
* A single threaded executor to run all the background tasks
63+
*/
64+
private var _executor: ExecutorService? = null
65+
5066
/**
5167
* Run this block when user grants drive uses permission. Must be set before
5268
* each operation.
@@ -86,7 +102,7 @@ class GoogleDriveBackupManager(
86102
onFailed: ((Exception) -> Unit)? = null,
87103
result: (List<FileInfo>) -> Unit
88104
) = requestConsentAndProceed(onFailed) {
89-
Thread {
105+
execute(onFailed) {
90106
try {
91107
val files = GetFiles.getFiles(it).files.map {
92108
FileInfo(
@@ -110,7 +126,7 @@ class GoogleDriveBackupManager(
110126
onFailed?.invoke(e)
111127
}
112128
}
113-
}.start()
129+
}
114130
}
115131

116132
/**
@@ -125,7 +141,7 @@ class GoogleDriveBackupManager(
125141
onFailed: ((Exception) -> Unit)? = null,
126142
result: (FileInfo) -> Unit
127143
) = requestConsentAndProceed(onFailed) { c ->
128-
Thread {
144+
execute(onFailed) {
129145
try {
130146
val file = GetFile.getFile(fileID, c).let {
131147
FileInfo(
@@ -145,7 +161,7 @@ class GoogleDriveBackupManager(
145161
onFailed?.invoke(e)
146162
}
147163
}
148-
}.start()
164+
}
149165
}
150166

151167
/**
@@ -157,7 +173,7 @@ class GoogleDriveBackupManager(
157173
onFailed: ((Exception) -> Unit)? = null,
158174
onUpload: (fileID: String) -> Unit
159175
) = requestConsentAndProceed(onFailed) {
160-
Thread {
176+
execute(onFailed) {
161177
try {
162178
val fileID = UploadAppData.uploadAppData(it, file, mimeType)
163179

@@ -170,7 +186,7 @@ class GoogleDriveBackupManager(
170186
onFailed?.invoke(e)
171187
}
172188
}
173-
}.start()
189+
}
174190
}
175191

176192
/**
@@ -188,7 +204,7 @@ class GoogleDriveBackupManager(
188204
onFailed: ((Exception) -> Unit)? = null,
189205
onDownload: (File) -> Unit
190206
) = requestConsentAndProceed(onFailed) {
191-
Thread {
207+
execute(onFailed) {
192208
val fos = FileOutputStream(outputFile)
193209
try {
194210
val baOs = DownloadFile.downloadFile(it, fileID)
@@ -207,7 +223,7 @@ class GoogleDriveBackupManager(
207223
} finally {
208224
fos.close()
209225
}
210-
}.start()
226+
}
211227
}
212228

213229
/**
@@ -220,7 +236,7 @@ class GoogleDriveBackupManager(
220236
onFailed: ((Exception) -> Unit)? = null,
221237
onCreate: (String) -> Unit
222238
) = requestConsentAndProceed(onFailed) {
223-
Thread {
239+
execute(onFailed) {
224240
try {
225241
val folderID = CreateRootFolder.create(it)
226242
activity.runOnUiThread {
@@ -233,7 +249,7 @@ class GoogleDriveBackupManager(
233249
onFailed?.invoke(e)
234250
}
235251
}
236-
}.start()
252+
}
237253
}
238254

239255
/**
@@ -247,7 +263,7 @@ class GoogleDriveBackupManager(
247263
onFailed: ((Exception) -> Unit)? = null,
248264
onDelete: () -> Unit
249265
) = requestConsentAndProceed(onFailed) {
250-
Thread {
266+
execute(onFailed) {
251267
try {
252268
DeleteFile.delete(it, fileID)
253269
activity.runOnUiThread {
@@ -259,7 +275,7 @@ class GoogleDriveBackupManager(
259275
}
260276
Log.w(TAG, "failed to delete file $fileID", e)
261277
}
262-
}.start()
278+
}
263279
}
264280

265281
fun signOut(
@@ -330,6 +346,27 @@ class GoogleDriveBackupManager(
330346
consentLauncher.launch(signInIntent)
331347
}
332348

349+
/**
350+
* Execute the task on the executor.
351+
*
352+
*/
353+
private fun execute(onFailed: ((Exception) -> Unit)?, task: Runnable) {
354+
try {
355+
getExecutor().submit(task)
356+
} catch (e: Exception) {
357+
activity.runOnUiThread {
358+
onFailed?.invoke(e)
359+
}
360+
}
361+
}
362+
363+
private fun getExecutor(): ExecutorService {
364+
if (_executor == null) _executor = Executors.newSingleThreadExecutor()
365+
else if (_executor!!.isTerminated) _executor = Executors.newSingleThreadExecutor()
366+
367+
return _executor!!
368+
}
369+
333370
companion object {
334371
private const val TAG = "BackupManager"
335372
}

libDriveBackup/src/main/java/media/uqab/libdrivebackup/useCase/GetCredential.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ internal object GetCredential {
4444
return credential
4545
} catch (e: Exception) {
4646
if(e is ApiException && e.statusCode == 10) {
47-
Log.e(TAG, "Not configured properly. Maybe you used wrong credential.")
47+
Log.e(TAG, "GCP not configured properly. Maybe you used wrong credential ID or wrong SHA-1.")
4848
} else {
4949
Log.e(TAG, "Failed to get credential", e)
5050
}

0 commit comments

Comments
 (0)