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

我怀疑这是时间/延迟问题,但尚不清楚是否存在会强制刷新的应用程序操作。 “Drive.DriveApi.requestSync(GAC)”似乎无效。

最佳答案

更新(07/22/2015)
感谢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将开发出一种可行的解决方案。我na的原因很简单。如果我的应用程序创建了文件,则它需要使用有意义的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);
          }
        }
      });
  }
}

...并且正在等待某些事情发生。文件在几秒钟内愉快地上传到了Drive,但是没有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会提供一个新的 Shiny ResourceId。当然,ChangeListener变得过时了,因为扑克例程也获得了ResourceId。

因此,这就是那些无法等待ResourceId的人的答案。这就提出了后续问题:

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

关于google-drive-android-api - Google Drive Android API中DriveId.getResourceId()的意外结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22874657/

10-11 07:32