Risultato imprevedibile di DriveId.getResourceId () nell’API Android di Google Drive

Il problema è che il ‘resourceID’ da ‘ DriveId.getResourceId () ‘ non è disponibile (restituisce NULL) sui file appena creati (prodotto di ‘ DriveFolder.createFile (GAC, meta, cont) ‘). Se il file viene recuperato da una lista regolare o da una procedura di interrogazione, il ‘resourceID’ è corretto.

Ho il sospetto che si tratti di un problema di temporizzazione / latenza, ma non è chiaro se vi sia un’azione dell’applicazione che impone l’aggiornamento. ” Drive.DriveApi.requestSync (GAC) ” sembra non avere alcun effetto.

AGGIORNAMENTO (22/07/2015)
Grazie alla pronta risposta di Steven Bazyl (vedi commenti sotto), finalmente ho una soluzione soddisfacente usando gli eventi di completamento . Ecco due snippet di codice minified che recapitano ResourceId all’app non appena il file appena creato viene propagato nell’unità:

Creazione di file, aggiunta di una modifica:

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

Event Service, prende il completamento:

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

In circostanze normali (wifi), ottengo quasi immediatamente ResourceId .

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

… fatto per ora.

ORIGINAL POST, deprecato, lasciato qui per riferimento.

Lascio questa risposta per un anno sperando che GDAA sviluppi una soluzione che funzioni . La ragione del mio fastidioso è semplice. Se la mia app crea un file, deve trasmettere questo fatto ai suoi amici (altri dispositivi, ad esempio) con un ID significativo (ovvero ResourceId). È un’attività semplice sotto REST Api dove ResourceId viene restituito non appena il file viene creato correttamente.

Aghi per dire che capisco la filosofia GDAA di schermare l’app da primitive di rete, cache, batching … Ma chiaramente, in questa situazione, il ResourceID è disponibile molto prima che venga consegnato all’app.

Inizialmente, ho implementato il suggerimento di Cheryl Simon e aggiunto un ChangeListener su un file appena creato, sperando di ottenere il ResourceID quando il file viene propagato. Usando il classico CreateEmptyFileActivity da Android- Demos , ho trovato il seguente codice di test:

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

… e stavo aspettando che succedesse qualcosa. Il file è stato felicemente caricato nell’unità in pochi secondi, ma nessun evento onChange () . 10 minuti, 20 minuti, … Non sono riuscito a trovare alcun modo su come fare in modo che ChangeListener si attivi.

Quindi l’unica altra soluzione, potrei venire a spingere la GDAA. Così ho implementato un semplice handler-poker che solletica i metadati fino a quando succede qualcosa:

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

E voilà, 4 secondi (dare o avere) in seguito, il ChangeListener offre un nuovo ResourceId shiny. Ovviamente, ChangeListener diventa quindi obsoleto, poiché anche la routine del poker ottiene ResourceId.

Quindi questa è la risposta per coloro che non possono aspettare l’IdRe. Che solleva la domanda di follow-up:

Perché devo solleticare i metadati (o re-commit del contenuto), molto probabilmente creando traffico di rete non necessario, per ottenere l’evento onChange () , quando vedo chiaramente che il file è stato propagato molto tempo fa e GDAA ha il ResourceId disponibile ?

ResourceIds diventano disponibili quando la risorsa appena creata è impegnata sul server. Nel caso di un dispositivo non in linea, questo potrebbe essere arbitrariamente molto lungo dopo la creazione iniziale del file. Accadrà il prima ansible dopo la richiesta di creazione, quindi non devi fare nulla per accelerarlo.

Se ne hai davvero bisogno subito, potresti usare le notifiche di modifica per ascoltare la modifica della risorsa.