Start Magazin Zugriff auf Google Drive aus eigenen Apps

Zugriff auf Google Drive aus eigenen Apps

Der Zugriff auf akuelle Cloud-Speicher wie Google Drive wird bisher von den Entwicklern eher stiefmütterlich mehandelt. Dabei muss das nicht sein. Google bietet eine umfassende Schnittstelle zu seinen Services. Eine Beispiel-App soll zeigen wie es geht.

Quellcode zum Download

Die hier beschriebene App inklusive Quellcode gibt es auf der Android-User-Homepage zum Download. Den passenden Link [3] finden Sie über den QR-Code "Alle Links" am Ende des Artikels.

Ob die Sicherung umfangreicher Datenbestände wie Musik und Dokumente oder die Synchronisation dieser Daten über Geräte unterschiedlicher Plattformen hinweg, Cloud-Speicher sind in aller Munde. Von Dropbox bis SkyDrive, von Wuala bis Google Drive – immer mehr Menschen vertrauen ihre sensiblen Daten der Wolke an. Dabei haben diese Dienste nicht nur Vorteile zu bieten. Der eine Dienst lagert Musik ohne Murren ab verweigert aber das Abspielen von Musiktiteln (Google Drive). Der andere bietet einen äußerst günstigen Tarif (Amazon: 250.000 Dateien für knapp EUR 25/Jahr) treibt die Kunden aber durch die Trennung von Musik-Player und Cloud-Speicher, und der damit einhergehenden Gängelung, in den Wahnsinn.

Wäre es nicht schön wenn man als Entwickler einfach von allen Anbietern die besten Lösungen aufgreifen und die ultimative Android App für den eigenen Cloud-Speicher bauen könnte? Geht nicht? Geht doch!

Google Drive

Am Beispiel von Google Drive soll demonstriert werden das viele Einschränkungen nicht unbedingt ein Systemfehler sind. Vielmehr sind es die Anwendungen der Cloud-Anbieter, deren Apps, die einfachen und praktischen Nutzer-Szenarien verschlossen sind. Der komplette Source-Code dieser Beispiel-App finden Sie auf der Android-User-Homepage zum Download.

Für Kunden des Google Mail Dienstes sind aber die Geschwister Kalender, Kontakte, Picasa oder auch Google Drive die natürliche Auswahl. Google Drive bietet eine Speicherung von bis zu 16TB, wobei 5GB kostenlos sind, über Geräte und Plattformen hinweg. Da auf jedem Gerät individuell eingestellt werden kann, welche Daten durch die Synchronisation lokal abgespeichert werden sollen, lässt sich der Cloud-Speicher als Backup- aber auch als Synchronisationslösung nutzen.

Da Google zum Beispiel keinen Medien-Player für gespeicherte Musik-Tracks anbietet, der Bildbetrachter nur rudimentäre Möglichkeiten bietet und die hauseigene Android Drive App darüber hinaus auch nicht mit weiteren Features glänzt, liegt eine Eigenentwicklung nahe. Here we go.

Voraussetzungen

Der Entwickler kann bei der Kommunikation mit Google Drive aus den Vollen schöpfen. Der Zugriff mittels eines XML API, einer experimentellen JSON-Schnittstelle sowie eines Java-API im Beta-Stadium ist bereits vorgesehen. Für viele aktuelle Programmiersprachen stehen somit alle Möglichkeiten offen.

Das Google Drive Java SDK [1] für Android befindet sich noch in Entwicklung. Google selbst bezeichnet das SDK als Beta. Leider werden in regelmäßigen Abständen Klassen wie Methoden durcheinander gewürfelt. Mit jeder Veröffentlichung kann sich deshalb auch die Methodik der eigenen Anwendung ändern. Dies lässt sich aber mit einer fixen Umgebung bestehend aus einer festgelegten Android-Konfiguration sowie passenden externen Libs lösen. Die aktuelle Version des SDK sehen wir als sehr stabil an.

Entwickelt wird für Android ab Version 11 (3.0). Es geht auch für frühere Android-Versionen aber einige Convenience-Klassen für den bequemen Zugriff funktionieren erst ab dieser Version. Das merkt der Entwickler leider erst wenn die App ausgeführt wird. Die hier genutzten API-Aufrufe schotten mittels Reflection manche Methoden ab, sodas die Probleme nicht gleich während der Entwicklung auftreten. Voraussetzung ist gleichermaßen ein Entwickler-Konto – ohne das geht es einfach nicht.

Anmeldung

Der Entwickler muss seine App zunächst für die Nutzung des Google Drive SDK freischalten. Hierfür ist die API-Console zuständig [2]. Hier müssen Sie unter dem Menüpunkt Services den Zugriff über das Google Drive SDK scharfschalten. Man erkennt gleich, dass mit diesem Service eine Einschränkung verbunden ist: Maximal 500.000 Requests sind pro Tag erlaubt. Das klingt zunächst nach einer Menge Zugriffe. Mit einer erfolgreichen App relativiert sich das aber schnell. An Hand der Reports, die auf dieser Seite ebenfalls eingesehen werden können, ist die Überwachung der Requests möglich und die Umstellung auf ein Bezahlmodell unter Umständen empfehlenswert.

Abbildung 1: Google API Console - Eine Auflistung sämtlicher Dienste.
Abbildung 1: Google API Console – Eine Auflistung sämtlicher Dienste.

Unter dem Menüpunkt API Access steht dem Entwickler sodann ein sogenannter Simple API Key zur Verfügung. Obwohl aus der App heraus mittels eines Java API mit Google Drive kommuniziert werden soll, ist der für Browser-Zugriffe entwickelte Schlüssel vollkommen ausreichend. Entwickler werden oftmals von dieser Möglichkeit verwirrt. Letztendlich führt die Java-Schnittstelle aber auch nur HTTP-Requests aus.

Abbildung 2: Google API Console - API Access zur Identifizierung des Projekts.
Abbildung 2: Google API Console – API Access zur Identifizierung des Projekts.

Von einer App gibt es normalerweise zwei Versionen – eine Debug sowie eine Release Version. Beide besitzen einen Keystore. Aus diesem Grund sollten beide unter API Access in der API Console eingetragen werden. Die in der Abbildung 3 sichtbare Einstellung muss gewählt werden (Installed application, Android). Tragen Sie für beide Versionen (Debug, Release) den gleichen Package-Name ein. Wie Sie den SHA1-Fingerabdruck ermitteln, zeigt Listing 1.

Abbildung 3: Google API Console - Hier legen Sie eine Client ID an.
Abbildung 3: Google API Console – Hier legen Sie eine Client ID an.

Listing 1

Generierung des SHA1 Fingerabdrucks

Debug: keytool -exportcert -alias androiddebugkey -keystore path-to-debug-keystore -list -v
Release: keytool -exportcert -keystore path-to-production-keystore -list -v

Das Passwort für den Debug-Schlüssel lautet wie immer android. Das Passwort für den Release-Schlüssel hat man selbst bei Erzeugung des Keystores vergeben. Von der Ausgabe dieses Befehl ist die SHA1 Zeile relevant. Diese Zeichenfolge wird in das zweite Eingabefeld eingetragen.

Eine Besonderheit gibt es aktuell zu bedenken. Wird mehr mehr als eine App für Google Drive entwickelt, dann kollidieren die Debug-Schlüssel der beiden Apps. Der Debug-Schlüssel ist für zwei unterschiedliche Packages identisch, sodass nur die erste App erfolgreich zum Testen durchgelassen wird.

Projektrahmen

Kopieren Sie bitte das komplette Verzeichnis androidusergdoc von der Android-User-Homepage [3] in Ihren Eclipse Workspace. Importieren Sie dieses Projekt mit File | Import | General | Existing Projects into Workspace. Nach der Einrichtung dieses neuen Android-Projektes in seiner Eclipse Umgebung müssen ganz bestimmte externe Libs diesem Projekt beigefügt werden. Fast alle Libs finden sich in der Datei google-api-services-drive-v2-rev9-1.8.0-beta.zip [4]. Das Drive JAR findet sich im drive-Ordner dieses Archivs, benötigte Standard Libs im Ordner drive/libs. Zu dieser Sammlung gesellt sich noch die Apache commons-io-2.4.jar [5]. Letzteres ist ebenfalls der Bequemlichkeit geschuldet. In der Beispiel-App werden Dateien aus der Wolke als auch in die Wolke kopiert. Die Apache Open Source Library bietet hierzu ein paar interessante Klassen und Methoden.

Die folgenden Dateien aus diesen Paketen kopieren Sie bitte in den von Ihnen anzulegenden libs-Ordner im Projektverzeichnis. Diese Liste enthält reichlich Beta-Material, das zeigt schon die Namensgebung. Zudem muss es exakt diese Kombination aus Libs sein:

Benötigte Libs

commons-io-2.4.jar
google-api-client-1.11.0-beta.jar
google-api-client-android-1.11.0-beta.jar
google-api-services-drive-v2-rev9-1.8.0-beta.jar
google-http-client-1.11.0-beta.jar
google-http-client-android-1.11.0-beta.jar
google-http-client-gson-1.11.0-beta.jar
google-http-client-jackson2-1.11.0-beta.jar
google-oauth-client-1.11.0-beta.jar
gson-2.1.jar
guava-11.0.1.jar
jackson-core-2.0.5.jar
jsr305-1.3.9.jar

Die App benötigt einige Permissions. Diese müssen in der Manifest Datei eingetragen werden, wie in Listing 2 zu sehen.

Listing 2

Benötigte Permissions

android.permission.GET_ACCOUNTS
com.google.android.googleapps.permission.GOOGLE_AUTH
android.permission.INTERNET
android.permission.MANAGE_ACCOUNTS
android.permission.USE_CREDENTIALS
android.permission.WRITE_EXTERNAL_STORAGE

Selbstverständlich benötigt die App den Zugriff auf das Internet und den externen Speicher. Nur so können Dateien in die Wolke und aus der Wolke kopiert werden. Heruntergeladene Dateien werden auf dem externen Speicher abgelegt.

Die weiteren Permissions behandeln das Auslesen und Manipulieren der auf dem Gerät gespeicherten Google-Accounts. Nur mit diesen ist der Zugriff auf Google Drive vorgesehen. Diese Accounts werden dann benutzt um mittels OAuth2 die Kopplung zwischen dem Google-Account auf dem Gerät und dem Account in der Cloud vorzunehmen.

Die Beispiel-App

Die hier vorgestellte Android App besteht aus drei Activities. Im ersten Schritt werden, nach der Accountauswahl, die Wurzelordner von Google Drive in der MainActivity angezeigt.

Abbildung 4: MainActivity - Hier müssen Sie einen Account auswählen.
Abbildung 4: MainActivity – Hier müssen Sie einen Account auswählen.

Abbildung 5: MainActivity - Die Wurzelverzeichnisse von Drive.
Abbildung 5: MainActivity – Die Wurzelverzeichnisse von Drive.

Wird ein Wurzelordner ausgewählt dann verzweigt die App zur DirectoryActivity. Mit der DirectoryActivity kann der Benutzer mehr oder weniger komplett durch die Google Drive Ordnerstruktur wandern. Stehen in Googles Cloud Thumbnails zur Verfügung so werden diese mit einem LazyLoader für Bildmaterial aus dem Web herangezogen. Liegen keine Thumbnails vor so werden eigene Drawables aus dem Standard Android Repository verwendet.

Abbildung 6: DirectoryActivity - Durch die Verzeichnisse navigieren.
Abbildung 6: DirectoryActivity – Durch die Verzeichnisse navigieren.

Mit Hilfe des Menüknopfs auf der DirectoryActivity kann eine Datei vom Gerät in den gerade sichtbaren Google Drive Ordner hochgeladen werden. Um die App nicht allzu sehr zu verkomplizieren, wird in den Assets eine Datei mit ausgeliefert und beim ersten Start der App auf den externen Speicher kopiert. Beim Hochladen einer Datei wird immer diese eine Datei verwendet.

Die DirectoryActivity hält auch ein Context-Menü für die einzelnen Listeneinträge bereit. Dateien können mit Hilfe dieses Menüs heruntergeladen werden. Auch das Löschen von Elementen ist hiermit möglich. Hier wird auch gleich auf eine Besonderheit von Google Drive Rücksicht genommen. Zwei verschiedene Kontextmenü-Einträge erlauben das permanente Löschen aber auch das Verschieben in den Papierkorb. Letztere Daten können über die Web-Oberfläche wieder aus dem Trash zurückgeholt werden.

Ein Klick auf eine Bilddatei erzwingt den Wechsel zur FileActivity in der das ausgewählte Bild angezeigt wird.

Abbildung 7: FileActivity - Ein Bild wird angezeigt.
Abbildung 7: FileActivity – Ein Bild wird angezeigt.

Google Play Services

Ende September 2012 hat Google die Google Play Services eingeführt. Hierbei handelt es sich um eine kleine Library die Entwickler ihren Apps beilegen müssen. Weiterhin handelt es sich um eine Service Komponente die Bestandteil der aktuellen Google Play Store App ist.

Dieser neue Service erlaubt mit Hilfe einiger bequemen Methoden, aus einer App heraus, die Auswahl des Google Accounts und die Beschaffung eines Tokens für die Kommunikation mit den Google Diensten. Dabei werden für die Kommunikation mit dem Benutzer standardisierte Dialoge verwendet und nicht mehr Eigenkreationen jedes Entwicklers benötigt.

Dieser Schritt ist richtig und wichtig – besitzt aber einen gravierenden Nachteil. Die Nutzung dieser neuen Klassen und Methoden ist von der Existenz der Google Play Store App auf dem Gerät des Benutzers und – erschwerend – einer aktuellen Version dieser App abhängig. Diese Voraussetzung ist gerade im Android-Umfeld nicht praktikabel und zeigt einmal mehr wie isoliert von der Android-Realität die Google-Entwickler manchmal agieren. Ein solches zentrales Feature gehört statt dessen in ein Paket ähnlich dem statischen Support-Package welches Android 3.0/Android 4.0 Features auch alten Android-Geräten beibringt. Der Entwickler kann diese Prüfungen (App, App-Version) zwar mit beigefügten API-Aufrufen vornehmen und dem Benutzer die Installation bzw. die Aktualisierung der App anraten. Ob der das dann macht steht auf einem anderen Blatt. Lehnt der Benutzer dies, aus welchen Gründen auch immer, ab oder sollte das genutzte Gerät kein Google-Zertifikat besitzen (Stichwort China-tablet) so muss die App des Entwicklers auf herkömmliche Art mit Google kommunizieren – und genau das zeigen wir in diesem Beitrag.

Erster Start

In der Datei MyConstants.java gibt es einige Konstanten. Eine dieser Konstanten enthält den bereits angesprochenen Simple API Key. Diese Konstante ist nicht gefüllt. Übertragen Sie bitte als erstes, nach dem Kopieren des Sourcecodes und dem Einrichten des Android-Projektes in Eclipse, diesen Key aus Ihrer API Konsole in den String:

public static final String APIKEY_SIMPLE = "";

Weiterhin benötigt die App einige statische Variablen. Bei Android-Apps bietet sich hierfür eine Subclass von Application an (MyApplication). Diese Klasse wird pro App einmal gestartet und ist während der Laufzeit der App immer aktiv – und das auch garantiert nur einmal. Zu den hier abgespeicherten Daten gehört unter anderem nach dessen Erzeugung der Zugriffstoken, der LazyLoader für Bildmaterial aus dem Web aber auch die mit dem Token erstellte Instanz des Drive Objektes. Beim ersten Start wird zudem die bereits erwähnte Testdatei aus dem Assets Ordner auf die externe Speicherkarte kopiert.

Nach dem Durchlaufen von MyApplication startet die erste Activity, die MainActivity. Hier geht es nun richtig los.

Die Authorisierung

Eine App für Google Drive funktioniert nur wenn auf dem Gerät auch Google Accounts eingerichtet sind. Wie man die Liste aller Google Accounts ausliest, zeigt Listing 3. Gibt es mehr als einen Account, dann wird ein Auswahldialog angezeigt, ansonsten wird das eine Konto verwendet.

Listing 3

Auslesen der Google Accounts

// AccountManager und Liste aller Accounts holen
AccountManager accountManager = new GoogleAccountManager(this);
Account[] accounts = accountManager.getAccounts();

Nach der Festlegung des Benutzer-Accounts wird ein Token für den Google Drive Scope oauth2:https://www.googleapis.com/auth/drive erzeugt. Mit diesem Scope sind alle Aktivitäten (Lesen, Schreiben, ?) abgedeckt. Derzeit ermöglicht das Google Drive SDK noch keine feinere Einstellung. Der gezeigte Scope mit globaler Berechtigung ist aber freigeschaltet, wie Listing 4 zeigt.

Listing 4

Zugangstoken

accountManager.getAccountManager().getAuthToken(account,
                MyConstants.AUTHTOKENSCOPE_DRIVE, null,
                this, new AccountManagerCallback<Bundle>() {
                        @Override
                        public void run(AccountManagerFuture<Bundle> future) {
                                try {
                                        // Diesen Token in den Preferences speichern
                                        MyApplication.setAuthToken(future.getResult().getString(
                                                        AccountManager.KEY_AUTHTOKEN));
                                        // Zur Weiterverarbeitung
                                        processTokenReceived();
                                } catch (OperationCanceledException exception) {
                                } catch (AuthenticatorException exception) {
                                } catch (Exception exception) {
                                }
                        }
                }, null);

Der ausgewählter Google Account wird in den Preferences abgespeichert. Beim nächsten Start der App werden dann alle Google Accounts gegen den gespeicherten Account geprüft. Damit ist gewährleistet das die Auswahl des Accounts nur einmal erfolgt auch wenn auf dem Gerät mehrere Google Benutzerkonten eingetragen sind.

Der folgende Schritt ist kritisch. Eine falsche Kombination von Lib-Versionen, Klassen sowie Methoden scheitert exakt jetzt bei den folgenden Aufrufen. Mit Hilfe des Tokens und des Simple API Keys wird nämlich genau an dieser Stelle die App bei Google Drive überprüft:

Listing 5

Authorisierung seitens Google Drive

// Die Google Credentials aufbauen
GoogleCredential credential = new GoogleCredential();
// Den Token setzen
credential.setAccessToken(authToken);
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = new AndroidJsonFactory();
// Eine Instanz von Google Drive erzeugen mit dem "Simple API Key"
MyApplication.setDrive(new Drive.Builder(transport, jsonFactory, credential)
                .setApplicationName(MyApplication.getAppName())
                .setJsonHttpRequestInitializer(
                                new GoogleKeyInitializer(MyConstants.APIKEY_SIMPLE))
                .build());

Nach einem erfolgreichen Durchlauf wurde ein Drive Objekt erzeugt mit dessen Hilfe nun die ganze Welt von Google Drive der App zu Füßen liegt.

Netzwerkverkehr

Mit Android 3.0 "Honeycomb" wurde der StrichtMode eingeführt. Das ist ein kleiner aber bissiger Wachhund der diverse Tests während der Laufzeit einer App durchführt. Verstößt eine App gegen dessen Regeln dann wird sie gnadenlos abgestraft und der Benutzer der App realisiert einen Absturz. Mit Android Version 4 gehört der Netzwerkverkehr einer App zum Überwachungs-Portfolio des StrictMode. Netzwerkverkehr gehört in separate Threads und darf nicht im Haupt-Thread einer App ausgeführt werden. Unter Android bieten sich hierzu unter anderem AsyncTasks an. Mit diesen ist gewährleistet das das User Interface nicht während des Netzwerkverkehrs blockiert wird.

In der Beispiel-App wird selbstverständlich der gesamte Netzwerkverkehr in AsyncTasks ausgeführt – jede Aktion gegen Google Drive besitzt ihren eigenen speziellen AsyncTask. Damit diese so schlank wie möglich bleiben wird mit MyAsyncTask eine Klasse eingeführt die sich um den ProgressDialog während der Wartezeit kümmert. Gleichzeitig bietet diese Klasse den Activities das Abmelden und wieder Anmelden während des OrientationChange – dem Rotieren des Gerätes.

Aufgerufen wird das Laden der Benutzerdaten durch die Befehlsfolge aus Listing 6. In diesem Aufruf wird eine TaskId, der Activity-Context (this) sowie der MyAsyncTaskCompletedListener übermittelt (ebenfalls this). Der Listener in der Activity empfängt nach Laden der Daten das Ergebnis und einen eventuellen Fehlercode. Eine solche typische Aktion reduziert sich durch die generische MyAsyncTask-Klasse auf das Gerüst in Listing 7.

Listing 6

Starten einer Anfrage

aboutTask = new AboutAsyncTask(MyConstants.ASYNCTASK_ABOUT, this, this);
aboutTask.execute();

Listing 7

Die Anfrage im eigenen Thread

public class AboutAsyncTask extends MyAsyncTask<Void, Void, About> {
    public AboutAsyncTask(int taskId, Context context,
            final MyOnAsyncTaskCompletedListener listener) {
        super(taskId, context, listener);
    }
    @Override
    protected About doInBackground(Void... voids) {
        About result = null;
        try {
                        // Benutzerdaten von Google Drive holen
            result = MyApplication.getDrive().about().get().execute();
        } catch (GoogleJsonResponseException exception) {
            GoogleJsonError error = exception.getDetails();
            errorCode = error.getCode();
        } catch (Exception exception) {
                        //
        }
        return result;
    }
}

Hier sind gleich einige Besonderheit zu erkennen. Eventuelle Fehler in der Schnittstelle können bequem mit Hilfe der Exception ausgelesen werden. Diese Fehler lassen sich auf genau drei Fehlercodes reduzieren. 401 bedeutet das der Token abgelaufen ist. Weitere errorCodes zeigen das Überschreiten des Quota, dem Limit der pro Tag erlaubten Request an.

Diese errorCodes werden zusammen mit dem Ergebnis des Aufrufs von MyAsyncTask per Listener an die zuständige Activity weitergeleitet, wie in Listing 8 zu sehen.

Listing 8

Ende der Anfrage

@Override
protected void onPostExecute(C result) {
        if (listener != null) {
                listener.onAsyncTaskCompleted(taskId, errorCode, result);
        }
        // ProgressDialog wegwerfen und Context sowie Listener "nullen"
        detach();
}

In der betreffenden Activity kann dann je nach eintreffendem AsyncTask auf dessen Ergebnis reagiert werden. Im Falle der Benutzerdaten werden diese für die Laufzeit der App gespeichert. Der Name des Benutzers und dessen Email Adresse wird in der Activity angezeigt. Anschließend werden die Wurzel-Verzeichnisse in einem weiteren Thread von Google Drive gelesen. Das Wort root ist dabei ein Alias für die Id des Wurzelverzeichnis.

Listing 9

Die Activity wird vom Thread geweckt

@Override
public void onAsyncTaskCompleted(int taskId, int errorCode, Object taskResult) {
        switch (taskId) {
                // Benutzerdaten wurden abgebfragt
                case MyConstants.ASYNCTASK_ABOUT:
                        if (taskResult != null && errorCode == 0) {
                                MyApplication.setAbout((About) taskResult);
                                processLayout();
                                // Root Verzeichnisliste auslesen
                                filesTask = new FilesAsyncTask(MyConstants.ASYNCTASK_FILES, this, this, "root",
                                                MyConstants.MIMETYPE_DIRECTORY);
                                filesTask.execute();
                        }
                        aboutTask = null;
                        break;
        }
        if (errorCode != 0) {
                processErrorCode(errorCode);
        }
}

Suchen und Filtern

Das Auslesen von Verzeichnisinhalten gestaltet sich etwas umständlich, ist aber der Website von Google Drive geschuldet. Es ist nicht möglich in einem Rutsch den gesamten Inhalt eines größeren Verzeichnis zu ermitteln. Statt dessen muss seitenweise geblättert werden. Der Wert der durch Google Drive zu liefernden Ergebnisse pro Seite ist konfigurierbar, entlässt den Entwickler aber nicht aus der Verantwortung, da niemand weiß wie umfangreich die Dateibestände in Verzeichnissen des Benutzers so sein können.

Listing 10

Einen kompletten Ordner lesen

Files.List request = null;
boolean ok = true;
// Seitenweise einlesen
do {
        try {
                request = MyApplication.getDrive()
                                .files()
                                .list()
                                .setMaxResults(200)
                                .setQ(query);
                FileList files = request.execute();
                result.addAll(files.getItems());
                request.setPageToken(files.getNextPageToken());
        } catch (GoogleJsonResponseException exception) {
                GoogleJsonError error = exception.getDetails();
                errorCode = error.getCode();
        } catch (IOException exception) {
                ok = false;
        } catch (Exception exception) {
                ok = false;
        }
} while (ok && request.getPageToken() != null && request.getPageToken().length() > 0);

Um den Netzwerk-Traffic so gering wie möglich zu halten erlaubt Google Drive das Aufsetzen auf ein bestimmtes Verzeichnis und das Filtern dessen Inhalts. Beides kann mit der Methode setQ() beim Aufruf übergeben werden. Die in Listing 11 gezeigte Befehlsfolge prüft zunächst ob die Alias-ID root irgendwo als Parent eingetragen ist und ob diese Elemente dann auch noch den MimeType=Verzeichnis besitzen. Diese Query liefert alle Wurzelverzeichnisse des betreffenden Users bei Google Drive.

Listing 11

Suchen und filtern

String query = "'root' in parents and trashed=false and mimeType='application/vnd.google-apps.folder'";

Hinweis: Eine Liste der möglichen Suchfelder und Operatoren ist im Web einsehbar [6]. Leider ist nicht jeder Operator mit jedem Feld kombinierbar. Der Regeln erscheinen willkürlich und scheinen sich auch noch in Entwicklung zu befinden. Ein Blick auf das ChangeLog jeder neuen Version des SDK ist aus diesem Grund dringend angeraten.

Im Fehlerfall

Der Fehlerbehandlung sollte man ein paar Augenblicke zugestehen. In der Beispiel-App wurde folgender Ansatz gewählt. Tritt ein Fehler auf, dann wird jede Activity, außer die MainActivity, sofort beendet und der Fehlercode wird an die jeweilige Parent-Activity durchgereicht. Das kann über mehrere Schritte hin bis zur MainActivity erfolgen – der Benutzer merkt das nicht. In der MainActivity werden dann die Fehler an zentraler Stelle bearbeitet (Listing 12 und 13).

Listing 12

Kommunikationsfehler 1

Intent intent = new Intent();
intent.putExtra("ERRORCODE", errorCode);
setResult(RESULT_CANCELED, intent);
finish();

Listing 13

Kommunikationsfehler 2

private void processErrorCode(int errorCode) {
        switch (errorCode) {
                case 401:
                        Toast.makeText(this, getString(R.string.txt_zugriffstokenabgelaufen),
                                        Toast.LENGTH_LONG).show();
                        // Token abgelaufen, neu abfragen mit Obergrenze
                        if (maxTokenRefreshCounter < MyConstants.MAX_TOKENREFRESH_COUNT) {
                                maxTokenRefreshCounter++;
                                processAccountSelected();
                        }
                        break;
                default:
                        Toast.makeText(this, String.valueOf(errorCode), Toast.LENGTH_LONG).show();
                        break;
        }
}

In der Beispiel-App wird nur ein zeitlich abgelaufener Token behandelt, alle anderen Fehler werden dem Benutzer nur ausgegeben. Damit die App nicht Amok läuft, unternimmt sie maximal drei Versuche, den Token zu erneuern.

Fazit

Mit den verfügbaren Schnittstellen zu Google Drive stehen interessierten Entwicklern alle Möglichkeiten offen. Googles eigene Drive App ist nicht gerade mit Features überladen. Dieses Loch können mit Hilfe des API [7] andere Entwickler nun füllen. Obwohl das Google Drive SDK sich noch im Beta Stadium befindet, ist es erstaunlich stabil. Es bleibt hingegen zu hoffen, dass die Klassen und Methoden stabil bleiben. Google ist auf diesem Gebiet als nicht gerade sehr entwicklerfreundlich bekannt. Die grobe Ausrichtung ist aber schon jetzt klar zu erkennen.

Kommentiere den Artikel

Please enter your comment!
Please enter your name here