2014-04-04 1 views
7

문제는 'DriveId.getResourceId()'에서 '에서 resourceID은'(새로 생성 된 파일에 을 '의 제품 (NULL을 반환)를 사용할 수없는 것입니다 DriveFolder.createFile (GAC, meta, cont) '). 파일이 일반 목록이나 쿼리 프로 시저에 의해 검색되면 'resourceID'가 올바른 것입니다.예측할 수없는 결과가

타이밍/대기 시간 문제라고 생각되지만 새로 고칠 수있는 응용 프로그램 작업이 있는지는 확실하지 않습니다. 'Drive.DriveApi.requestSync (GAC)'은 아무 효과가없는 것 같습니다.

답변

15

UPDATE 스티븐 Bazyl에서 프롬프트 응답 (아래 설명 참조) (2015년 7월 22일)
덕분에, 나는 마지막으로 Completion Events을 사용하여 만족스러운 해결책을 가지고 있습니다.

파일 생성, 변경 등록을 추가합니다 :

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()); 
      } 
     } 
     }); 
    } 
} 

이벤트 서비스, 어획량을 여기에 즉시 새로 생성 된 파일을 드라이브로 전달 될 때 응용 프로그램에 에 ResourceId을 제공하는 두 개의 축소 된 코드 조각은 완료 : 정상적인 상황 (와이파이)에서

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; 
    } 
    } 
} 

, 나는 거의 즉시 에 ResourceId를 얻을.

20:40:53.247﹕Created a empty file: DriveId:CAESABiiAiDGsfO61VMoAA== 
20:40:54.305: onComplete, ResourceId: 0BxOS7mTBMR_bMHZRUjJ5NU1ZOWs 

... 지금 완료되었습니다.

ORIGINAL POST, 더 이상 사용되지 않으므로 여기를 참조하십시오.

저는이 답변을 GDAA이 효과가있는 해결책을 개발하기를 기대하면서 1 년 동안 기다리게했습니다. 내 잔소리에 대한 이유는 간단합니다. 내 응용 프로그램에서 파일을 만드는 경우이 사실을 해당 ID (예 : ResourceId)가 포함 된 친구 (예 : 다른 장치)에 브로드 캐스팅해야합니다. REST Api에서 파일을 성공적으로 생성하자마자 ResourceId가 돌아 오는 것은 쉬운 일이 아닙니다.

바늘은 네트워크 프리미티브, 캐싱, 일괄 처리에서 앱을 차폐한다는 GDAA의 철학을 이해한다고 바꿔 말할 수 있습니다.하지만 분명히이 상황에서는 앱에 전달되기 훨씬 전에 ResourceID를 사용할 수 있습니다.

원래, 나는 셰릴 사이먼의 제안을 구현 파일이 전달 될 때 을 RESOURCEID 얻을 수 있었으면, 새로 생성 된 파일에 ChangeListener의을 추가했다.고전 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); 
      } 
     } 
     }); 
    } 
} 

그리고 짜잔, 사초 (제공 또는 소요) 후, ChangeListener의 새로운 반짝의 ResourceId을 제공합니다 : 그래서 뭔가가 일어날 때까지 메타 데이터를 간지럽 간단한 핸들러 - 포커를 구현했습니다. 물론 ChangeListener는 쓸모 없게됩니다. 포커 루틴은 ResourceId도 가져옵니다.

ResourceId를 기다릴 수없는 사람들을위한 답변입니다. 어떤 후속 질문을 불러옵니다 :

변경() 이벤트를 얻으려면 불필요한 네트워크 트래픽을 생성 할 가능성이있는 메타 데이터를 간지럽 히거나 (콘텐츠를 다시 작성해야하는 이유는 무엇입니까? 파일은 오랜 전에 전파되었으며, GDAA는 ResourceId를 사용할 수 있습니까?

+0

당신의 경우에, 당신은 청취자 대신 청취자를 더 찾고 있다고 생각합니다. 변경 리스너와 함께보고있는 결과가 예상됩니다. 결과 콜백, * after * 변경을 할 때까지 변경 리스너를 추가하지 않습니다. 그래서, 네가 파일을 간질 나기 전까지는 업데이트를 얻지 못할 것이다. 변경 사항이 서버에 전파되었을 때 알림을받는 방법은 https://developers.google.com/drive/android/completion을 참조하십시오. 기본 드라이브 파일 ID를 얻으려는 경우 관심있는 이벤트입니다. –

+0

고마워, 미안해. 내가이 문제가 원래 있었을 때 주변에 없었던 'completions'에 대해 몰랐다. 나는 'REST Api universe'에 있었으므로 놓쳤습니다. 그것을 시도 할 것이다. – seanpj

9

ResourceIds는 새로 생성 된 리소스가 서버에 커밋 될 때 사용할 수있게됩니다. 오프라인 상태 인 장치의 경우 초기 파일을 만든 후 임의로 오래 걸릴 수 있습니다. 생성 요청 후에 가능한 한 빨리 발생하므로 속도를 높이려면 아무 것도 할 필요가 없습니다.

정말 필요한 경우 change notifications을 사용하여 변경할 resourceId를 수신 할 수 있습니다.

+0

새 항목이 아니더라도 감사합니다. RESTFul과 GDAA를 섞어 야하기 때문에 이러한 재치의 대부분이 발생합니다. (예를 들어 GDAA에 파일을 만들고 RESTful을 통해 '설명'을 업로드해야하지만 주변에 resID는 업로드하지 않아야합니다.) 코드는 지금 당황 스럽지만, 최소한 나는 모든 기반을 덮었습니다. 여러분이 물건을 추가 할 때, 여기에서 내리막 길 인 것처럼 보입니다. – seanpj

+0

커밋하는 데 시간이 얼마나 걸립니까? – Nabin