我尝试在谷歌驱动器应用程序特定文件夹中创建文件。我在谷歌开发者中创建了OAuth 2.0客户端ID,启用了驱动器api,并在OAuth同意屏幕中添加了范围。应用程序成功登录谷歌帐户。它使用以下代码在appDataFolder中创建文件,但它在"我的驱动器"部分创建文件。文件是在"我的驱动器"部分创建的,但文件id也为空。
文件是使用AsyncTask创建的。
class BackUpActivity : AppCompatActivity() {
private lateinit var googleDriveFile: File
private var mediaContent: FileContent? = null
private var rawTextFile: java.io.File? = null
private var fileMetadata: File? = null
var METADATA_FILE_PARENT = "appDataFolder"
var METADATA_FILE_TYPE = "text/plain"
private var fileList: FileList? = null
private var googleDriveService: Drive? = null
private val REQUEST_CODE_SIGN_IN: Int = 1
private lateinit var onBackupProcess: BackupRestoreProgress
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_back_up)
onBackupProcess = BackupRestoreProgress(this)
checkLastSignIn()
button.setOnClickListener {
createFileInAppFolder(onBackupProcess, googleDriveService!!, this)
}
}
private fun checkLastSignIn() {
val googleSignInAccount = GoogleSignIn.getLastSignedInAccount(this)
if (googleSignInAccount == null) {
requestSignIn()
return
}
setCredentials(googleSignInAccount)
listFilesFromAppFolder(onBackupProcess)
}
/**
* Starts a sign-in activity using [.REQUEST_CODE_SIGN_IN].
*/
private fun requestSignIn() {
Toast.makeText(this, "Start sign in, pls wait ...", Toast.LENGTH_LONG).show()
val signInOptions = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(
Scope(DriveScopes.DRIVE_FILE),
Scope(DriveScopes.DRIVE_APPDATA))
.requestEmail()
.build()
val client = GoogleSignIn.getClient(this, signInOptions)
startActivityForResult(client.signInIntent, REQUEST_CODE_SIGN_IN)
}
public override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
when (requestCode) {
REQUEST_CODE_SIGN_IN -> {
handleSignInResult(resultData!!)
}
}
super.onActivityResult(requestCode, resultCode, resultData)
}
/**
* Handles the `result` of a completed sign-in activity initiated from [ ][.requestSignIn].
*/
private fun handleSignInResult(result: Intent) {
GoogleSignIn.getSignedInAccountFromIntent(result)
.addOnSuccessListener { googleAccount ->
setCredentials(googleAccount)
}
.addOnFailureListener { exception -> throw exception }
}
fun setCredentials(googleSignInAccount: GoogleSignInAccount) {
val credential = GoogleAccountCredential.usingOAuth2(
this, listOf(
DriveScopes.DRIVE_FILE,
DriveScopes.DRIVE_APPDATA
)
)
credential.selectedAccount = googleSignInAccount.account
googleDriveService =
Drive.Builder(AndroidHttp.newCompatibleTransport(), GsonFactory(), credential)
.setApplicationName("Docscanner")
.build()
Toast.makeText(this, "Sign in successful", Toast.LENGTH_LONG).show()
}
@SuppressLint("StaticFieldLeak")
private fun listFilesFromAppFolder(
backupRestoreProgress: BackupRestoreProgress
) {
object : AsyncTask<Void?, Void?, Void?>() {
override fun onPreExecute() {
backupRestoreProgress.setMessage("Fetching backups...")
backupRestoreProgress.showDialog()
super.onPreExecute()
}
override fun doInBackground(vararg voidArr: Void?): Void? {
return try {
val list: Drive.Files.List =
googleDriveService!!.files().list()
fileList = list.setQ("mimeType ='$METADATA_FILE_TYPE'")
.setSpaces(METADATA_FILE_PARENT)
.setFields("files(id, name,size,createdTime,modifiedTime)")
.execute() as FileList
null
} catch (e: IOException) {
Log.d(TAG, "doInBackground: IOException ${e.message}")
null
}
}
override fun onPostExecute(voidR: Void?) {
super.onPostExecute(voidR)
backupRestoreProgress.dismissDialog()
if (fileList != null && fileList!!.files != null) {
Log.d(TAG, "onPostExecute: size ${fileList!!.size}")
for (i in fileList!!.files.indices) {
val file2: File = fileList!!.files[i]
val name: String = file2.name
val id: String = file2.id
Log.d(TAG, "onPostExecute: $name id = $id")
}
}
}
}.execute(*arrayOfNulls<Void>(0))
}
@SuppressLint("StaticFieldLeak")
fun createFileInAppFolder(
backupRestoreProgress: BackupRestoreProgress,
drive: Drive,
backUpActivity: BackUpActivity
) {
object : AsyncTask<Void?, Void?, Void?>() {
override fun onPreExecute() {
backupRestoreProgress.setMessage("Uploading to drive...")
backupRestoreProgress.showDialog()
fileMetadata = File()
fileMetadata!!.name = "test-text"
fileMetadata!!.parents = Collections.singletonList(METADATA_FILE_PARENT)
rawTextFile = getRawFile()
Log.d(TAG, "onPreExecute: ${rawTextFile!!.path}")
mediaContent = FileContent(METADATA_FILE_TYPE, rawTextFile)
super.onPreExecute()
}
private fun getRawFile(): java.io.File {
var inputStream = backUpActivity.resources.openRawResource(R.raw.demo)
var file = java.io.File(filesDir, "text");
var outputStream = FileOutputStream(file);
var read = 0;
val buffer = ByteArray(8 * 1024)
while (inputStream.read(buffer).also { read = it } != -1) {
outputStream.write(buffer, 0, read)
}
outputStream.close();
inputStream.close();
return file
}
override fun doInBackground(vararg params: Void?): Void? {
return try {
googleDriveFile =
drive.files().create(fileMetadata, mediaContent)
.execute() as File
Log.d(TAG, "doInBackground: id ${googleDriveFile.id}")
null
} catch (e: IOException) {
e.printStackTrace()
null
}
}
override fun onPostExecute(voidR: Void?) {
backupRestoreProgress.dismissDialog()
super.onPostExecute(voidR)
Handler(Looper.getMainLooper()).postDelayed({
Log.d(TAG, "onPostExecute: id ${googleDriveFile.id}")
},3000)
}
}.execute(*arrayOfNulls<Void>(0))
}
}
基本上,我在googleapi控制台中添加了四个作用域。
- https://www.googleapis.com/auth/drive.appdata
- https://www.googleapis.com/auth/drive.file
- https://www.googleapis.com/auth/drive.install
- https://www.googleapis.com/auth/drive
在"我的驱动器"部分创建"Untile"文件名
文件上传/创建/更新分为两部分。首先上传元数据,然后上传文件流本身。元数据包括文件的名称、您要在其中创建它的文件夹(父文件夹(。如果不设置元数据,您的文件将被上载为无标题。
File fileMetadata = new File();
fileMetadata.setName("photo.jpg");
fileMetadata.setParents(Collections.singletonList("appDataFolder"));
java.io.File filePath = new java.io.File("files/photo.jpg");
FileContent mediaContent = new FileContent("image/jpeg", filePath);
File file = driveService.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
System.out.println("File ID: " + file.getId());