-
Notifications
You must be signed in to change notification settings - Fork 571
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1610 from MohitMandalia/gdrive
feature: drive module initial commit
- Loading branch information
Showing
15 changed files
with
598 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import com.ivy.buildsrc.Google | ||
import com.ivy.buildsrc.Timber | ||
import com.ivy.buildsrc.Hilt | ||
|
||
apply<com.ivy.buildsrc.IvyPlugin>() | ||
|
||
plugins { | ||
id("com.android.library") | ||
id("kotlin-android") | ||
id("kotlin-kapt") | ||
id("org.jetbrains.kotlin.android") | ||
id("dagger.hilt.android.plugin") | ||
} | ||
|
||
android { | ||
namespace = "com.ivy.drive.google_drive" | ||
compileSdk = 32 | ||
|
||
defaultConfig { | ||
minSdk = 24 | ||
targetSdk = 32 | ||
|
||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" | ||
// consumerProguardFiles("consumer-rules.pro") | ||
} | ||
|
||
buildTypes { | ||
release { | ||
isMinifyEnabled = false | ||
proguardFiles( | ||
getDefaultProguardFile("proguard-android-optimize.txt"), | ||
"proguard-rules.pro" | ||
) | ||
} | ||
} | ||
compileOptions { | ||
sourceCompatibility = JavaVersion.VERSION_1_8 | ||
targetCompatibility = JavaVersion.VERSION_1_8 | ||
} | ||
kotlinOptions { | ||
jvmTarget = "1.8" | ||
} | ||
|
||
|
||
packagingOptions { | ||
|
||
resources.excludes.add("META-INF/DEPENDENCIES") | ||
resources.excludes.add("listenablefuture") | ||
} | ||
} | ||
|
||
dependencies { | ||
|
||
// implementation("androidx.core:core-ktx:1.7.0") | ||
implementation("androidx.appcompat:appcompat:1.5.1") | ||
implementation("com.google.android.material:material:1.6.1") | ||
testImplementation("junit:junit:4.13.2") | ||
androidTestImplementation("androidx.test.ext:junit:1.1.3") | ||
androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") | ||
|
||
|
||
|
||
implementation("com.google.apis:google-api-services-drive:v3-rev136-1.25.0") { | ||
exclude(group = "com.google.guava", module = "listenablefuture") | ||
} | ||
implementation("com.google.http-client:google-http-client-gson:1.26.0") | ||
implementation("com.google.api-client:google-api-client-android:1.26.0") { | ||
exclude(group = "com.google.guava", module = "listenablefuture") | ||
} | ||
api("com.google.guava:guava:28.1-android") | ||
|
||
Hilt() | ||
|
||
Google() | ||
|
||
Timber(api = true) | ||
|
||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Add project specific ProGuard rules here. | ||
# You can control the set of applied configuration files using the | ||
# proguardFiles setting in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
24 changes: 24 additions & 0 deletions
24
...e/google-drive/src/androidTest/java/com/ivy/drive/google_drive/ExampleInstrumentedTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.ivy.drive.google_drive | ||
|
||
import androidx.test.platform.app.InstrumentationRegistry | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
|
||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
import org.junit.Assert.* | ||
|
||
/** | ||
* Instrumented test, which will execute on an Android device. | ||
* | ||
* See [testing documentation](http://d.android.com/tools/testing). | ||
*/ | ||
@RunWith(AndroidJUnit4::class) | ||
class ExampleInstrumentedTest { | ||
@Test | ||
fun useAppContext() { | ||
// Context of the app under test. | ||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext | ||
assertEquals("com.ivy.drive.google_drive.test", appContext.packageName) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
||
</manifest> |
20 changes: 20 additions & 0 deletions
20
drive/google-drive/src/main/java/com/ivy/drive/google_drive/data/GoogleDriveFileType.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.ivy.drive.google_drive.data | ||
|
||
sealed class GoogleDriveFileType { | ||
class Backup(val type: GoogleDriveType = GoogleDriveType.BackupTypeCSV): GoogleDriveFileType(){ | ||
companion object { | ||
const val FOLDER_NAME = "Backup" | ||
} | ||
} | ||
class Image(val type: GoogleDriveType = GoogleDriveType.ImageTypeJPEG): GoogleDriveFileType(){ | ||
companion object { | ||
const val FOLDER_NAME = "Image" | ||
} | ||
} | ||
class Video(val type: GoogleDriveType = GoogleDriveType.VideoType): GoogleDriveFileType(){ | ||
companion object { | ||
const val FOLDER_NAME = "Video" | ||
} | ||
} | ||
|
||
} |
167 changes: 167 additions & 0 deletions
167
drive/google-drive/src/main/java/com/ivy/drive/google_drive/data/GoogleDriveServiceHelper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package com.ivy.drive.google_drive.data | ||
|
||
import com.google.api.client.http.FileContent | ||
import com.google.api.services.drive.Drive | ||
import com.google.api.services.drive.model.File | ||
import com.google.api.services.drive.model.FileList | ||
import com.ivy.drive.google_drive.data.GoogleDriveFileType.Image | ||
import com.ivy.drive.google_drive.data.GoogleDriveFileType.Backup | ||
import com.ivy.drive.google_drive.data.GoogleDriveFileType.Video | ||
import com.ivy.drive.google_drive.util.GoogleDriveUtil | ||
import com.ivy.drive.google_drive.util.GoogleDriveUtil.IVY_WALLET_ROOT_FOLDER | ||
import com.ivy.drive.google_drive.util.GoogleDriveUtil.createGoogleDriveFile | ||
import com.ivy.drive.google_drive.util.GoogleDriveUtil.getParents | ||
import com.ivy.drive.google_drive.util.GoogleDriveUtil.ivyRootFolderParent | ||
import com.ivy.drive.google_drive.util.GoogleDriveUtil.updateGoogleDriveFile | ||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Deferred | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.async | ||
import timber.log.Timber | ||
import java.io.ByteArrayOutputStream | ||
import java.io.IOException | ||
import java.io.OutputStream | ||
|
||
internal class GoogleDriveServiceHelper(private val drive: Drive) { | ||
|
||
fun uploadFileAsync( | ||
file: File, | ||
fileContent: FileContent? = null, | ||
driveFiletype: GoogleDriveFileType | ||
): Deferred<String> { | ||
|
||
return CoroutineScope(Dispatchers.IO).async { | ||
val currentFile = getFileByName(file.name) | ||
|
||
if(currentFile != null) { | ||
Timber.d("Current File not null") | ||
val parentFolder = checkIfFolderExist(driveFiletype.toString()) | ||
if (fileContent != null) { | ||
updateFile( | ||
fileId = currentFile.id, | ||
driveType = driveFiletype, | ||
fileName = currentFile.name, | ||
parent = parentFolder, | ||
fileContent = fileContent | ||
) | ||
} else { | ||
"Couldn't upload the file as contents were empty" | ||
} | ||
} else { | ||
Timber.d("Current File null creating new file") | ||
|
||
createFile( | ||
fileContent = fileContent, | ||
fileName = file.name, | ||
driveType = driveFiletype | ||
) | ||
} | ||
} | ||
} | ||
|
||
fun downloadFile(fileName: String): OutputStream? { | ||
val file = getFileByName(fileName) | ||
val outputStream = ByteArrayOutputStream() | ||
if(file != null) { | ||
drive.files().get(file.id).executeAndDownloadTo(outputStream) | ||
return outputStream | ||
} | ||
return null | ||
} | ||
|
||
private fun updateFile( | ||
fileId: String, | ||
fileContent: FileContent, | ||
fileName: String, | ||
parent: String?, | ||
driveType: GoogleDriveFileType | ||
): String { | ||
val type = driveType.toString() | ||
val fileMetadata = updateGoogleDriveFile(fileName,type) | ||
val googleFile = drive.files().update(fileId,fileMetadata,fileContent).setAddParents(parent).execute() | ||
?: throw IOException("Error while updating and uploading google drive file") | ||
return googleFile.id | ||
} | ||
|
||
private fun createFile( | ||
fileContent: FileContent?, | ||
fileName: String, | ||
driveType: GoogleDriveFileType | ||
): String { | ||
val type = when(driveType) { | ||
is Backup -> driveType.type | ||
is Image -> driveType.type | ||
is Video -> driveType.type | ||
} | ||
|
||
val typeValue = when(type) { | ||
is GoogleDriveType.BackupTypeCSV -> type.VALUE | ||
is GoogleDriveType.ImageTypeJPEG -> type.VALUE | ||
is GoogleDriveType.ImageTypePNG -> type.VALUE | ||
is GoogleDriveType.ImageTypeWEBP -> type.VALUE | ||
is GoogleDriveType.BackupTypePlainText -> type.VALUE | ||
else -> { | ||
GoogleDriveType.BackupTypePlainText.VALUE | ||
} | ||
} | ||
val parentId = checkIfFolderExist(driveType.toString()) | ||
val parents = if(parentId != null) { | ||
getParents(parentId) | ||
} else { | ||
val rootId = checkIfFolderExist(IVY_WALLET_ROOT_FOLDER) | ||
val rootParents = | ||
if(rootId != null) { | ||
getParents(rootId) | ||
} else { | ||
val id = createFolder() | ||
getParents(id) | ||
} | ||
val id = createFolder(rootParents,driveType.toString()) | ||
getParents(id) | ||
} | ||
val fileMetadata = createGoogleDriveFile(fileName,parents,typeValue) | ||
|
||
val googleFile = | ||
if(fileContent == null) { | ||
drive.files().create(fileMetadata).execute() | ||
?: throw IOException("Error while creating and uploading google drive file") | ||
} else { | ||
drive.files().create(fileMetadata, fileContent).execute() | ||
?: throw IOException("Error while creating and uploading google drive file") | ||
} | ||
return googleFile.id | ||
} | ||
|
||
private fun getFileByName(fileName: String): File? { | ||
val fileList = getAllFiles() | ||
if(fileList.isEmpty().not()) { | ||
return fileList.files.firstOrNull { it.name == fileName } | ||
} | ||
return null | ||
} | ||
|
||
private fun getAllFiles(): FileList { | ||
return drive.files().list().setSpaces(GoogleDriveUtil.DRIVE_SPACE).execute() | ||
?: throw Exception ("Error in querying the files from the drive") | ||
} | ||
|
||
private fun checkIfFolderExist(fileName: String): String? { | ||
val files = getAllFiles() | ||
val file = files.files.firstOrNull { it.name == fileName } | ||
return file?.id | ||
} | ||
|
||
private fun createFolder( | ||
parents: List<String> = ivyRootFolderParent, | ||
folderName: String = IVY_WALLET_ROOT_FOLDER | ||
): String { | ||
val metadata = createGoogleDriveFile( | ||
folderName, | ||
parents, | ||
GoogleDriveUtil.MIME_TYPE_FOLDER | ||
) | ||
val googleFile = drive.files().create(metadata).execute() | ||
?: throw IOException("Error when requesting file creation.") | ||
return googleFile.id | ||
} | ||
} |
Oops, something went wrong.