Google 云端控制臺
訪問 Google Cloud Console寒瓦。
如果還沒有項目爪飘,請創(chuàng)建一個懒熙。如果已有項目碍讯,請選擇該項目。
在導航菜單中選擇 APIs & Services > Dashboard载迄。
-
點擊 ENABLE APIS AND SERVICES 按鈕。搜索 "Google Drive API"奠涌,然后點擊 Google Drive API 進入詳情頁面宪巨。點擊 Enable 按鈕啟用此 API。
1732003634450.jpg 返回到導航欄溜畅,選擇 APIs & Services > Credentials捏卓。
點擊 CREATE CREDENTIALS 按鈕,并從下拉列表中選擇 OAuth client ID慈格。
-
在 "Application type" 選項中怠晴,選擇 "Android":
- 輸入 Name。
- 在 Signing-certificate fingerprint 中輸入您的應用程序簽名證書的 SHA-1 指紋浴捆。如果您不知道如何獲取 SHA-1 指紋蒜田,請參考這篇文章。
- 在 Package name 中輸入您的 Android 應用程序的包名选泻。包名必須與您實際應用的包名一致冲粤,否則授權(quán)將無法成功。
點擊 Create∫趁校現(xiàn)在梯捕,您將看到您的 Client ID。請務必安全地保存這些信息窝撵,稍后將在您的應用程序中使用它們傀顾。
Android端依賴
implementation 'com.google.android.gms:play-services-auth:19.2.0'
implementation 'com.google.apis:google-api-services-drive:v3-rev197-1.25.0'
implementation 'com.google.api-client:google-api-client-android:1.23.0'
Android端代碼
1.初始化服務,
private lateinit var googleSignInClient: GoogleSignInClient
private var isRecover: Boolean=false
private val RC_SIGN_IN = 9001
private fun initDrive() {
val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestScopes(Scope(DriveScopes.DRIVE_FILE))
.build()
googleSignInClient = GoogleSignIn.getClient(this, signInOptions)
}
切記 使用 requestScopes(Scope(DriveScopes.DRIVE_FILE)) 而不是 .requestIdToken(ApiAction.SERVER_CLIENT_ID)
.requestIdToken(ApiAction.SERVER_CLIENT_ID)是登錄注冊使用的
2.具體業(yè)務邏輯
點擊事件
views.backupGoogle.debouncedClicks {
if (isGooglePlayServicesAvailable(this)) {
isRecover = false
getDriveAuth()
} else {
T.showShort(this, "設備不支持谷歌登錄")
}
}
views.recoverGoogle.debouncedClicks {
if (isGooglePlayServicesAvailable(this)) {
isRecover = true
getDriveAuth()
} else {
T.showShort(this, "設備不支持谷歌登錄")
}
}
詳細方法
fun isGooglePlayServicesAvailable(context: Context): Boolean {
val googleApiAvailability = GoogleApiAvailability.getInstance()
val resultCode = googleApiAvailability.isGooglePlayServicesAvailable(context)
return resultCode == ConnectionResult.SUCCESS
}
private fun getDriveAuth() {
val signInIntent = googleSignInClient.signInIntent
startActivityForResult(signInIntent, RC_SIGN_IN)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == RC_SIGN_IN) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
handleSignInResult(task)
}
}
private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) {
try {
val account = completedTask.getResult(ApiException::class.java)
account?.let {
// Get a Drive service instance using the signed-in account.
getDriveService(this, it)?.let {drive->
lifecycleScope.launch(Dispatchers.IO) {
if(isRecover){
BackupUtil.restoreData(drive, "backup.txt").let { content->
L.v("===content==${content}")
}
}else{
BackupUtil.backupData(drive, privateHex, "backup.txt")
}
}
}
}
} catch (e: ApiException) {
L.v("=====signInResult:failed code=" + e.statusCode)
}
}
BackupUtil代碼碌奉,里面有覆蓋上傳以及更新上傳短曾,自我斟酌
import android.content.Context
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.api.client.extensions.android.http.AndroidHttp
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential
import com.google.api.client.http.InputStreamContent
import com.google.api.client.json.jackson2.JacksonFactory
import com.google.api.services.drive.Drive
import com.google.api.services.drive.DriveScopes
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.nio.charset.StandardCharsets
/**
* Author : lisir
* Time: 2024/11/18 14:17
* Describe :
*/
object BackupUtil {
/**
*實例化Google Drive
*/
fun getDriveService(context: Context, account: GoogleSignInAccount): Drive? {
return try {
val credential = GoogleAccountCredential.usingOAuth2(
context, listOf(DriveScopes.DRIVE_FILE)
)
credential.selectedAccount = account.account
Drive.Builder(
AndroidHttp.newCompatibleTransport(),
JacksonFactory.getDefaultInstance(),
credential
).setApplicationName(context.getString(R.string.app_name))
.build()
} catch (e: Exception) {
L.v("====" + e.message)
null
}
}
/**
* @param drive :Google Drive
* @param data :寫入數(shù)據(jù) eg:真是美好的一天
* @param fileName :文件夾名稱 eg: back.txt
* 這個方法可以實現(xiàn)云盤上只有一份文件
*/
fun backupData(drive: Drive, data: String, fileName: String):String? {
try {
val query = "mimeType='text/plain' and trashed=false and name='$fileName'"
val existingFiles = drive.files().list()
.setQ(query)
.setSpaces("drive")
.setFields("nextPageToken, files(id, name)")
.setPageSize(1)
.execute()
val metadata = com.google.api.services.drive.model.File()
.setName(fileName)
.setMimeType("text/plain")
val contentStream = ByteArrayInputStream(data.toByteArray(StandardCharsets.UTF_8))
val content = InputStreamContent("text/plain", contentStream)
if (existingFiles.files.isEmpty()) {
val newFile = drive.files().create(metadata, content).setFields("id").execute()
L.v("File ID=====:"+newFile.id)
return newFile.id
} else {
val fileId = existingFiles.files[0].id
val updatedFile = drive.files().update(fileId, metadata, content).setFields("id").execute()
L.v("Updated File ID:===="+updatedFile.id)
return updatedFile.id
}
}catch (e: Exception) {
L.v("====" + e.message)
return null
}
}
/**
* 當云盤只有一個名字唯一的文件時候,
* @param drive :Google Drive
* @param fileName :文件夾名稱 eg: back.txt
*/
fun restoreData(drive: Drive, fileName: String): String? {
try {
val query = "name='$fileName'"
val fileList = drive.files().list()
.setQ(query)
.execute()
if (fileList.files.isEmpty()) {
return null
}
val backupFile = fileList.files.first()
val outputStream = ByteArrayOutputStream()
drive.files().get(backupFile.id).executeMediaAndDownloadTo(outputStream)
return String(outputStream.toByteArray(), StandardCharsets.UTF_8)
} catch (e: Exception) {
L.v("====" + e.message)
return null
}
}
/**
* 當云盤有多個名字相同的文件時候赐劣,
* @param drive :Google Drive
* @param fileName :文件夾名稱 eg: back.txt
*/
fun restoreDataMore(drive: Drive, fileName: String): String? {
val query = "mimeType='text/plain' and trashed=false and name='$fileName'"
val existingFiles = drive.files().list()
.setQ(query)
.setSpaces("drive")
.setFields("nextPageToken, files(id, name)")
.setPageSize(1)
.execute()
if (existingFiles.files.isEmpty()) {
L.v("File not found:=="+fileName)
return null
}
// Download the file's content
val fileId = existingFiles.files[0].id
L.v("fileId:=="+fileId)
ByteArrayOutputStream().use { outputStream ->
drive.files().get(fileId)
.executeMediaAndDownloadTo(outputStream)
// Convert the downloaded content to a string
return outputStream.toString(StandardCharsets.UTF_8.name())
}
}
/**
* @param drive :Google Drive
* @param data :寫入數(shù)據(jù) eg:真是美好的一天
* @param fileName :文件夾名稱 eg: back.txt
* 這個方法可以實現(xiàn)云盤上有多份相同文件
*/
fun backupDataMore(drive: Drive, data: String, fileName: String) {
val metadata = com.google.api.services.drive.model.File()
.setName(fileName)
.setMimeType("text/plain")
val contentStream = ByteArrayInputStream(data.toByteArray(StandardCharsets.UTF_8))
val content = InputStreamContent("text/plain", contentStream)
val file = drive.files().create(metadata, content).setFields("id").execute()
L.v("File ID: " + file.id)
}
}