UPDATE (2015.07.22)
Dank der prompte Antwort von Steven Bazyl (siehe Kommentare unten), ich habe endlich eine befriedigende Lösung mit Completion Events. Hier sind zwei minified Code-Schnipsel, die die ResourceId an die App liefern, sobald die neu erstellte Datei auf dem Laufwerk propagiert wird:
Dateierstellung, fügen Veränderung Abonnement:
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());
}
}
});
}
}
Event Service Fänge die Fertigstellung:
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;
}
}
}
Unter normalen Umständen (wifi), erhalte ich die ResourceId fast sofort.
20:40:53.247﹕Created a empty file: DriveId:CAESABiiAiDGsfO61VMoAA==
20:40:54.305: onComplete, ResourceId: 0BxOS7mTBMR_bMHZRUjJ5NU1ZOWs
... für jetzt erledigt.
ORIGINAL POST, veraltet, hier als Referenz.
Ich lasse diese Antwort für ein Jahr sitzen in der Hoffnung, dass GDAA eine Lösung entwickeln wird, die funktioniert. Der Grund für mein Nörgeln ist einfach. Wenn meine App eine Datei erstellt, muss sie diese Tatsache an ihre Buddys (z. B. andere Geräte) mit einer ID senden, die aussagekräftig ist (also ResourceId). Es ist eine triviale Aufgabe unter der REST Api, wo ResourceId zurückkommt, sobald die Datei erfolgreich erstellt wurde.
Nadeln zu sagen, dass ich die GDAA-Philosophie der Abschirmung der App von Netzwerk-Primitiven, Caching, Batching verstehen, ... Aber klar, in dieser Situation ist die ResourceID verfügbar, lange bevor es an die App geliefert wird.
Ursprünglich setzte ich Cheryl Simons Vorschlag und fügte eine Change auf eine neu erstellte Datei, zu erhalten hofft die ResourceID, wenn die Datei ausbreitet.Mit klassischen CreateEmptyFileActivity von android-Demo, ich klatschte zusammen den folgenden Testcode:
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);
}
}
});
}
}
... und warte darauf, dass etwas passiert. Die Datei wurde innerhalb von Sekunden in die Drive hochgeladen, aber keine onChange() Ereignis. 10 Minuten, 20 Minuten, ... Ich konnte keinen Weg finden, den ChangeListener aufzuwecken.
Also die einzige andere Lösung, die ich heraufkommen könnte, war, den GDAA zu stupsen. So implementiert ich ein einfaches Handler-Poker, die die Metadaten kitzeln, bis etwas passiert:
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);
}
}
});
}
}
Und voila, 4 Sekunden (mehr oder weniger) später die Change liefern eine neue glänzende ResourceId. Der ChangeListener wird damit natürlich überflüssig, da die Pokerroutine auch die ResourceId bekommt.
Das ist also die Antwort für diejenigen, die nicht auf die ResourceId warten können. Das bringt die Follow-up-Frage:
Warum muss ich Metadaten kitzeln (oder Inhalt wieder begehen), sehr wahrscheinlich unnötigen Netzwerkverkehr zu schaffen, onChange() Ereignis zu bekommen, wenn ich deutlich sehen, dass die Datei wurde vor langer Zeit verbreitet, und GDAA hat die ResourceId verfügbar?
Für Ihren Anwendungsfall denke ich, dass Sie eher nach einem Abschlusshörer als nach einem Änderungshörer suchen. Die Ergebnisse, die Sie mit einem Change-Listener sehen, werden erwartet. Sie fügen den Änderungslistener erst nach dem Ergebnisrückruf hinzu * nachdem * Sie die Änderung vorgenommen haben. Also, bis zum * nächsten * Mal, an dem du die Datei kitzelst, wirst du keine Updates erhalten. Unter https://developers.google.com/drive/android/completion erfahren Sie, wie Sie benachrichtigt werden, wenn eine Änderung an den Server weitergegeben wurde. Das ist das Ereignis, an dem Sie interessiert sind, wenn Sie die zugrunde liegende Laufwerksdatei-ID abrufen möchten. –
Danke, Entschuldigung, ich wusste nicht über "Vervollständigungen", es gab nicht, als ich dieses Problem ursprünglich hatte. Und seitdem bin ich im "REST Api-Universum" gewesen, also habe ich es verpasst. Werde es versuchen. – seanpj