问题是来自“ DriveId.getResourceId() ”的“resourceID”在新创建的文件(“ DriveFolder.createFile(GAC, meta, cont) ”的产品)上不可用(返回NULL )。如果通过常规列表或查询过程检索文件,则“resourceID”是正确的。
我怀疑这是一个时间/延迟问题,但不清楚是否存在强制刷新的应用程序操作。“ Drive.DriveApi.requestSync(GAC) ”似乎没有效果。
问题是来自“ DriveId.getResourceId() ”的“resourceID”在新创建的文件(“ DriveFolder.createFile(GAC, meta, cont) ”的产品)上不可用(返回NULL )。如果通过常规列表或查询过程检索文件,则“resourceID”是正确的。
我怀疑这是一个时间/延迟问题,但不清楚是否存在强制刷新的应用程序操作。“ Drive.DriveApi.requestSync(GAC) ”似乎没有效果。
更新(2015 年 7 月 22 日)
感谢 Steven Bazyl 的迅速回应(见下面的评论),我终于有了一个使用Completion Events的令人满意的解决方案。这是两个缩小的代码片段,它们在新创建的文件传播到驱动器后立即将ResourceId传递给应用程序:
文件创建,添加变更订阅:
public class CreateEmptyFileActivity extends BaseDemoActivity {
private static final String TAG = "_X_";
@Override
public void onConnected(Bundle connectionHint) { super.onConnected(connectionHint);
MetadataChangeSet meta = new MetadataChangeSet.Builder()
.setTitle("EmptyFile.txt").setMimeType("text/plain")
.build();
Drive.DriveApi.getRootFolder(getGoogleApiClient())
.createFile(getGoogleApiClient(), meta, null,
new ExecutionOptions.Builder()
.setNotifyOnCompletion(true)
.build()
)
.setResultCallback(new ResultCallback<DriveFileResult>() {
@Override
public void onResult(DriveFileResult result) {
if (result.getStatus().isSuccess()) {
DriveId driveId = result.getDriveFile().getDriveId();
Log.d(TAG, "Created a empty file: " + driveId);
DriveFile file = Drive.DriveApi.getFile(getGoogleApiClient(), driveId);
file.addChangeSubscription(getGoogleApiClient());
}
}
});
}
}
事件服务,捕获完成:
public class ChngeSvc extends DriveEventService {
private static final String TAG = "_X_";
@Override
public void onCompletion(CompletionEvent event) { super.onCompletion(event);
DriveId driveId = event.getDriveId();
Log.d(TAG, "onComplete: " + driveId.getResourceId());
switch (event.getStatus()) {
case CompletionEvent.STATUS_CONFLICT: Log.d(TAG, "STATUS_CONFLICT"); event.dismiss(); break;
case CompletionEvent.STATUS_FAILURE: Log.d(TAG, "STATUS_FAILURE"); event.dismiss(); break;
case CompletionEvent.STATUS_SUCCESS: Log.d(TAG, "STATUS_SUCCESS "); event.dismiss(); break;
}
}
}
在正常情况下(wifi),我几乎立即得到ResourceId 。
20:40:53.247﹕Created a empty file: DriveId:CAESABiiAiDGsfO61VMoAA==
20:40:54.305: onComplete, ResourceId: 0BxOS7mTBMR_bMHZRUjJ5NU1ZOWs
……暂时完成。
原始帖子,已弃用,留在这里供参考。
我让这个答案搁置了一年,希望GDAA能够开发出一个可行的解决方案。我唠叨的原因很简单。如果我的应用程序创建了一个文件,它需要使用有意义的 ID(即 ResourceId)将这一事实广播给它的伙伴(例如其他设备)。这是REST Api 下的一项微不足道的任务,一旦成功创建文件,ResourceId 就会返回。
不用说,我理解 GDAA 将应用程序与网络原语、缓存、批处理等隔离开来的哲学……但很明显,在这种情况下,ResourceID 在交付给应用程序之前很久就可用了。
本来,我实现了Cheryl Simon的建议,在一个新创建的文件上添加了一个ChangeListener,希望在文件传播的时候得到ResourceID 。使用来自android-demos 的经典CreateEmptyFileActivity,我将以下测试代码拼凑在一起:
public class CreateEmptyFileActivity extends BaseDemoActivity {
private static final String TAG = "CreateEmptyFileActivity";
final private ChangeListener mChgeLstnr = new ChangeListener() {
@Override
public void onChange(ChangeEvent event) {
Log.d(TAG, "event: " + event + " resId: " + event.getDriveId().getResourceId());
}
};
@Override
public void onConnected(Bundle connectionHint) { super.onConnected(connectionHint);
MetadataChangeSet meta = new MetadataChangeSet.Builder()
.setTitle("EmptyFile.txt").setMimeType("text/plain")
.build();
Drive.DriveApi.getRootFolder(getGoogleApiClient())
.createFile(getGoogleApiClient(), meta, null)
.setResultCallback(new ResultCallback<DriveFileResult>() {
@Override
public void onResult(DriveFileResult result) {
if (result.getStatus().isSuccess()) {
DriveId driveId = result.getDriveFile().getDriveId();
Log.d(TAG, "Created a empty file: " + driveId);
Drive.DriveApi.getFile(getGoogleApiClient(), driveId).addChangeListener(getGoogleApiClient(), mChgeLstnr);
}
}
});
}
}
......并且正在等待发生一些事情。文件在几秒钟内被愉快地上传到驱动器,但没有onChange()事件。10 分钟,20 分钟,...我找不到任何方法让 ChangeListener 唤醒。
因此,我能想到的唯一其他解决方案是推动 GDAA。所以我实现了一个简单的处理程序扑克,它会处理元数据直到发生某些事情:
public class CreateEmptyFileActivity extends BaseDemoActivity {
private static final String TAG = "CreateEmptyFileActivity";
final private ChangeListener mChgeLstnr = new ChangeListener() {
@Override
public void onChange(ChangeEvent event) {
Log.d(TAG, "event: " + event + " resId: " + event.getDriveId().getResourceId());
}
};
static DriveId driveId;
private static final int ENOUGH = 4; // nudge 4x, 1+2+3+4 = 10seconds
private static int mWait = 1000;
private int mCnt;
private Handler mPoker;
private final Runnable mPoke = new Runnable() { public void run() {
if (mPoker != null && driveId != null && driveId.getResourceId() == null && (mCnt++ < ENOUGH)) {
MetadataChangeSet meta = new MetadataChangeSet.Builder().build();
Drive.DriveApi.getFile(getGoogleApiClient(), driveId).updateMetadata(getGoogleApiClient(), meta).setResultCallback(
new ResultCallback<DriveResource.MetadataResult>() {
@Override
public void onResult(DriveResource.MetadataResult result) {
if (result.getStatus().isSuccess() && result.getMetadata().getDriveId().getResourceId() != null)
Log.d(TAG, "resId COOL " + result.getMetadata().getDriveId().getResourceId());
else
mPoker.postDelayed(mPoke, mWait *= 2);
}
}
);
} else {
mPoker = null;
}
}};
@Override
public void onConnected(Bundle connectionHint) { super.onConnected(connectionHint);
MetadataChangeSet meta = new MetadataChangeSet.Builder()
.setTitle("EmptyFile.txt").setMimeType("text/plain")
.build();
Drive.DriveApi.getRootFolder(getGoogleApiClient())
.createFile(getGoogleApiClient(), meta, null)
.setResultCallback(new ResultCallback<DriveFileResult>() {
@Override
public void onResult(DriveFileResult result) {
if (result.getStatus().isSuccess()) {
driveId = result.getDriveFile().getDriveId();
Log.d(TAG, "Created a empty file: " + driveId);
Drive.DriveApi.getFile(getGoogleApiClient(), driveId).addChangeListener(getGoogleApiClient(), mChgeLstnr);
mCnt = 0;
mPoker = new Handler();
mPoker.postDelayed(mPoke, mWait);
}
}
});
}
}
瞧,4 秒(给或取)后,ChangeListener 提供了一个新的闪亮 ResourceId。当然,ChangeListener 变得过时了,因为扑克程序也获得了 ResourceId。
所以这就是那些等不及 ResourceId 的人的答案。这就引出了后续问题:
当我清楚地看到文件已在很久以前传播并且 GDAA 具有可用的 ResourceId 时,为什么我必须处理元数据(或重新提交内容),很可能会创建不必要的网络流量来获取onChange()事件?
当新创建的资源提交到服务器时,ResourceIds 变得可用。在设备离线的情况下,这可能在初始文件创建之后任意长时间。不过,它会在创建请求后尽快发生,因此您无需执行任何操作来加快它的速度。
如果你真的需要它,你可以想象使用更改通知来监听 resourceId 的更改。