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.