Google Drive Android API中DriveId.getResourceId()的不可预知的结果

sea*_*npj 7 google-drive-android-api

问题是来自' DriveId.getResourceId() ' 的'resourceID' 在新创建的文件(' DriveFolder.createFile(GAC,meta,cont) '的产品)上不可用(返回NULL ).如果通过常规列表或查询过程检索文件,则'resourceID'是正确的.

我怀疑这是一个时间/延迟问题,但目前尚不清楚是否存在强制刷新的应用程序操作." Drive.DriveApi.requestSync(GAC) "似乎没有任何效果.

sea*_*npj 15

更新(
2015年7月22日)由于Steven Bazyl的迅速回应(见下面的评论),我终于使用完成事件获得了满意的解决方案.以下是两个缩小的代码片段,一旦新创建的文件传播到云端硬盘,就会将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());
          }
        }
      });
  }
}
Run Code Online (Sandbox Code Playgroud)

活动服务,完成:

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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

在正常情况下(wifi),我几乎立即获得ResourceId.

20:40:53.247?Created a empty file: DriveId:CAESABiiAiDGsfO61VMoAA==
20:40:54.305: onComplete, ResourceId: 0BxOS7mTBMR_bMHZRUjJ5NU1ZOWs
Run Code Online (Sandbox Code Playgroud)

......现在就完成了.

ORIGINAL POST,已弃用,留待此处参考.

我让这个答案坐了一年,希望GDAA能够开发出有效的解决方案.我唠叨的原因很简单.如果我的应用程序创建了一个文件,它需要将这个事实广播给其伙伴(例如其他设备),其ID值是有意义的(即ResourceId).REST Api 下的一项简单任务是,一旦文件成功创建,ResourceId就会恢复.

有人说,我理解GDAA的理念是屏蔽应用程序免受网络原语,缓存,批处理......但很明显,在这种情况下,ResourceID在交付给应用程序之前很久就可用了.

最初,我实现了Cheryl Simon的建议,并在新创建的文件中添加了ChangeListener,希望在文件传播时获取ResourceID.采用经典CreateEmptyFileActivityAndroid系统的演示,我拍了拍在一起下面的测试代码:

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);
          }
        }
      });
  }
}
Run Code Online (Sandbox Code Playgroud)

......正在等待一些事情发生.文件很快就被上传到云端硬盘,但没有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);
          }
        }
      });
  }
}
Run Code Online (Sandbox Code Playgroud)

瞧,4秒(给或拿)以后,ChangeListener提供了一个新的闪亮的ResourceId.当然,ChangeListener因此变得过时,因为扑克例程也获得了ResourceId.

所以这是那些不能等待ResourceId的人的答案.这提出了后续问题:

为什么我必须搔痒元数据(或重新提交内容),很可能创建不必要的网络流量,以获得onChange()事件,当我清楚地看到文件已经很久以前传播,并且GDAA有ResourceId可用时?


Che*_*mon 9

当新创建的资源提交到服务器时,ResourceIds变为可用.如果设备处于脱机状态,则在创建初始文件后,这可能是任意长的.它会在创建请求后尽快发生,因此您不需要做任何事情来加速它.

如果你真的需要它,你可以想象使用更改通知来监听resourceId的变化.