Reputation: 85
I try to create file in google drive app specific folder. I create OAuth 2.0 Client IDs in google developer and enable drive api and also add scopes in OAuth consent screen. App is successful sign in google account. it use below code to create file in appDataFolder but it create file in My Drive section. File is created in My Drive section but file id is also getting null.
File is created using 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))
}
}
Basically I add four scope in google api console.
Upvotes: 1
Views: 746
Reputation: 116868
File upload / create / update is done in two parts. First you upload the metadata followed by the file stream itself. The metadata includes things like the name of the file, the folder (parents) that you would like to create it in. Without setting the metadata your file will be uploaded as untitled.
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());
Upvotes: 1