Google Drive Android API中DriveId.getResourceId()的不可预知的结果
问题是,' DriveId.getResourceId() '的'resourceID'在新创build的文件(' DriveFolder.createFile(GAC,meta,cont) '的产品)上不可用(返回NULL)。 如果文件是通过常规列表或查询过程检索的,则“resourceID”是正确的。
我怀疑这是一个时间/延迟问题,但不清楚是否有一个会强制刷新的应用程序操作。 “ Drive.DriveApi.requestSync(GAC) ”似乎没有效果。
更新(07/22/2015)
感谢Steven Bazyl的快速反应(见下面的评论),我终于有了一个使用完成事件的令人满意的解决scheme。 以下是两个缩小的代码片段,只要新创build的文件传播到驱动器,即可将ResourceId传递到应用程序:
文件创build,添加更改订阅:
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
…现在完成了。
ORIGINAL POST,弃用,留在这里作为参考。
我让这个答案坐了一年,希望GDAA能够开发一个可行的解决scheme。 我唠叨的原因很简单。 如果我的应用程序创build一个文件,它需要将这个事实广播给它的好友(比如其他设备),这个好友的ID是ResourceId。 这是REST Api下的一个简单的任务,ResourceId在文件成功创build后立即返回。
针说,我了解GDAA的原则屏蔽应用程序从networking原语,caching,批处理,…但显然,在这种情况下,ResourceID是很久以前,它被提供给应用程序。
最初,我实现了Cheryl Simon的build议,并在新创build的文件上添加了一个ChangeListener ,希望在文件传播时获取ResourceID 。 从android-demos中使用经典的CreateEmptyFileActivity ,我把下面的testing代码放在一起:
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的人的答案。 提出后续问题:
为什么我不得不使用元数据(或重新提交内容),很可能创build不必要的networkingstream量,当我清楚地看到文件已经传播很久以前,并且GDAA具有可用的ResourceId时,获取onChange()事件?
当新创build的资源提交给服务器时,ResourceIds变为可用。 在设备脱机的情况下,在初始文件创build之后,这可能是任意长的。 尽pipe在创build请求后它会尽快发生,所以你不需要做任何事情来加快速度。
如果您真的需要它,可以想象使用更改通知来监听resourceId的更改。