Reputation: 2700
I'm having some trouble integrating the Google Drive API into my Android app. Basically, I'm trying to create a folder in which to store my error logs. The problem is that occasionally, the thread will run, and the folder won't be created by the time the file needs to be created, and so the app crashes. I'm trying to think about how to avoid this scenario, and have tried a few methods so far, including making the folder assignment in the folder callback, but all to no avail. I sometimes get lucky (particularly when debugging, unfortunately) and the file saves OK, but I obviously need to resolve the concurrency issue. Please let me know if any more code is needed for context.
protected void onPause() {
// TODO Find the right place for this
if (!mDriveLogList.isEmpty()) {
// Perform I/O off the UI thread.
// TODO Fix to use RxJava
new Thread() {
@Override
public void run() {
Timber.i("Starting File Creation");
// write content to DriveContents
if (mDriveContents == null) {
Timber.e("Drive Contents Were Null");
} else {
OutputStream outputStream = mDriveContents.getOutputStream();
Writer writer = new OutputStreamWriter(outputStream);
//TODO Clean/Refactor
try {
writer.write("Status Log For: " + DateHelper.getDate() + "\n");
for (String logEntry : mDriveLogList) {
writer.write(logEntry + "\n");
}
writer.close();
} catch (IOException e) {
Timber.e(e, "Error During Drive Contents Callback");
}
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(SURVEIL_DROID + " " + DateHelper.getDate())
.setMimeType("text/plain")
.setStarred(true).build();
MetadataChangeSet folderSet = new MetadataChangeSet.Builder()
.setTitle("SurveilCustomFolder")
.build();
Drive.DriveApi.getRootFolder(mGoogleApiClient)
.createFolder(mGoogleApiClient, folderSet)
.setResultCallback(folderCallback);
mDriveFolder = mFolderId.asDriveFolder();
mDriveFolder.createFile(mGoogleApiClient, changeSet, mDriveContents)
.setResultCallback(fileCallback);
mDriveLogList.clear();
}
}
}.start();
Upvotes: 0
Views: 213
Reputation: 101
createFolder() returns a PendingResult, you can use one of the await() methods of the PendingResult to block until the folder is created. See here: (https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html#await())
Upvotes: 0
Reputation: 3083
You could use a countdownlatch (See https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html) to help with the synchronization. Something like
protected void onPause() {
// TODO Find the right place for this
if (!mDriveLogList.isEmpty()) {
// Perform I/O off the UI thread.
// TODO Fix to use RxJava
new Thread() {
@Override
public void run() {
final protected CountDownLatch connectionLatch = new CountDownLatch(1);
protected boolean folderCreated = false;
Timber.i("Starting File Creation");
// write content to DriveContents
if (mDriveContents == null) {
Timber.e("Drive Contents Were Null");
} else {
OutputStream outputStream = mDriveContents.getOutputStream();
Writer writer = new OutputStreamWriter(outputStream);
//TODO Clean/Refactor
try {
writer.write("Status Log For: " + DateHelper.getDate() + "\n");
for (String logEntry : mDriveLogList) {
writer.write(logEntry + "\n");
}
writer.close();
} catch (IOException e) {
Timber.e(e, "Error During Drive Contents Callback");
}
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(SURVEIL_DROID + " " + DateHelper.getDate())
.setMimeType("text/plain")
.setStarred(true).build();
MetadataChangeSet folderSet = new MetadataChangeSet.Builder()
.setTitle("SurveilCustomFolder")
.build();
Drive.DriveApi.getRootFolder(mGoogleApiClient)
.createFolder(mGoogleApiClient, folderSet)
.setResultCallback(new
ResultCallback<DriveFolderResult>() {
@Override
public void onResult(DriveFolderResult result) {
folderCreated = result.getStatus().isSuccess();
connectionLatch.countDown(); // Release latch
}
});
try {
connectionLatch.await() ;
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
if (folderCreated) {
mDriveFolder = mFolderId.asDriveFolder();
mDriveFolder.createFile(mGoogleApiClient, changeSet, mDriveContents)
.setResultCallback(fileCallback);
mDriveLogList.clear();
}
}
}
}.start();
}
}
should work.
Upvotes: 1