2012-09-13 10 views
9

Die App wurde in der "Google API Console" als "installierte Anwendung" registriert - scheint, dass dies die richtige Einstellung für eine Android App ist, nein?Wie richten Sie Google Drive-Anmeldedaten in der Android App ein?

Also ich habe eine Client-ID und keine Secret-ID. Um es klar zu stellen: Es ist keine Web-App und keine Google Drive-App - es ist eine Android-App, die auf andere Nutzerdaten in der Google Drive-Cloud zugreift.

Innerhalb der App hole ich das Konto (funktioniert) und ich fordere ein Token (funktioniert). Jetzt möchte ich mit diesem Token und der Client-ID eine Verbindung zu Google Drive herstellen. Das Ergebnis ist ein "401, ungültiger Berechtigungsnachweis". Was ist mit diesem Code falsch?

public class ActivityMain extends Activity implements DialogInterface.OnClickListener { 

    // https://developers.google.com/drive/scopes 
    private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/drive"; 

    // https://code.google.com/apis/console/ 
    private static final String CLIENT_ID = "999999999999999.apps.googleusercontent.com"; 

    private AccountManager accountManager; 
    private Account[] accounts; 
    private String authName; 
    private String authToken; 

    @Override 
    public void onClick(final DialogInterface dialogInterface, final int item) { 

     processAccountSelected(accounts[item]); 
    } 

    @Override 
    public void onCreate(final Bundle bundle) { 
     super.onCreate(bundle); 

     setContentView(R.layout.activitymain); 

     accountManager = AccountManager.get(this); 
     accounts = accountManager.getAccountsByType("com.google"); 

     if (accounts == null || accounts.length == 0) { 
      // TODO 
     } else if (accounts.length == 1) { 
      processAccountSelected(accounts[0]); 
     } else if (accounts.length > 1) { 
      showDialog(MyConstants.DIALOG_ACCOUNTCHOSER); 
     } 
    } 

    @Override 
    protected Dialog onCreateDialog(final int id) { 
     switch (id) { 
      case MyConstants.DIALOG_ACCOUNTCHOSER: 
       AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); 

       String[] names = new String[accounts.length]; 

       for (int i = 0; i < accounts.length; i++) { 
        names[i] = accounts[i].name; 
       } 

       alertDialogBuilder.setItems(names, this); 
       alertDialogBuilder.setTitle("Select a Google account"); 
       return alertDialogBuilder.create(); 
     } 

     return null; 
    } 

    private void processAccountSelected(final Account account) { 
     if (account != null) { 
      authName = account.name.toString(); 
      if (!Tools.isEmpty(authName)) { 
       Toast.makeText(this, authName, Toast.LENGTH_LONG).show(); 

       accountManager.getAuthToken(account, AUTH_TOKEN_TYPE, null, this, 
         new AccountManagerCallback<Bundle>() { 

          public void run(final AccountManagerFuture<Bundle> future) { 
           try { 
            authToken = future.getResult().getString(
              AccountManager.KEY_AUTHTOKEN); 
            processTokenReceived(); 
           } catch (OperationCanceledException exception) { 
            // TODO 
           } catch (Exception exception) { 
            Log.d(this.getClass().getName(), exception.getMessage()); 
           } 
          } 
         }, null); 
      } 
     } 
    } 

    private void processListFiles(final Drive drive) { 
     List<File> result = new ArrayList<File>(); 
     Files.List request = null; 
     try { 
      request = drive.files().list(); 
     } catch (IOException exception) { 
     } 

     do { 
      try { 
       FileList files = request.execute(); 

       result.addAll(files.getItems()); 
       request.setPageToken(files.getNextPageToken()); 
      } catch (IOException exception) { 
       // --> 401 invalid credentials 
      } 
     } while (request.getPageToken() != null && request.getPageToken().length() > 0); 
    } 

    private void processTokenReceived() { 
     if (!Tools.isEmpty(authToken)) { 
      final HttpTransport transport = AndroidHttp.newCompatibleTransport(); 
      final JsonFactory jsonFactory = new GsonFactory(); 
      GoogleCredential credential = new GoogleCredential(); 
      credential.setAccessToken(authToken); 
      Drive drive = new Drive.Builder(transport, jsonFactory, credential) 
        .setApplicationName(getString(R.string.txt_appname)) 
        .setJsonHttpRequestInitializer(new GoogleKeyInitializer(CLIENT_ID)) 
        .build(); 

      if (drive != null) { 
       processListFiles(drive); 
      } 
     } 
    } 
} 

Ich muss sagen, dass dies eine volle Ladung Chaos ist. Es gibt so viele Seiten im Web, die nur Teile anzeigen und es gibt so viele Seiten, die veraltete, fehlende oder andere Methoden verwenden, um dasselbe zu tun. Es gibt meines Erachtens nicht zwei Seiten, die den gleichen Weg zeigen, Daten von Google Drive aus einer Android-App zu erhalten.

Jede Hilfe wird sehr geschätzt.

EDIT: Ich könnte es selbst lösen. Es war eine Kombination von verschiedenen Veränderungen:

  • Hat Android zu setzen: minSdkVersion = "11" als Voraussetzung
  • haben diese aktuellen Bibliotheken zu verwenden: 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, Guave-11.0.1.jar, Jackson-core-2.0.5.jar, jsr305-1.3.9.jar

Dies ist das Währungspaar t Teil, um das Laufwerk zu bekommen Objekt:

GoogleCredential credential = new GoogleCredential(); 
    credential.setAccessToken(authToken); 

    HttpTransport transport = AndroidHttp.newCompatibleTransport(); 

    JsonFactory jsonFactory = new AndroidJsonFactory(); 

    drive = new Drive.Builder(transport, jsonFactory, credential) 
      .setApplicationName(getString(R.string.txt_appname)) 
      .setJsonHttpRequestInitializer(
        new GoogleKeyInitializer(APIKEY_SIMPLE)) 
      .build(); 
    if (drive != null) { 
    } 

Antwort

3

Ja, die Dokumentation ist ziemlich schwer zu verstehen.

Ändern Sie einfach

new GoogleKeyInitializer(CLIENT_ID) 

zu

new GoogleKeyInitializer(SIMPLE_API_ACCESS_KEY) 

und es sollte funktionieren.

Sie finden Ihre SIMPLE_API_ACCESS_KEY in Googles APIs Console unter dem Simple API-Zugang Abschnitt der API-Zugriff Seite (die API key). Wenn dieser Abschnitt nicht verfügbar ist, müssen Sie zuerst den Drive API-Zugriff auf der Seite Services aktivieren.

+0

Leider hat weder nicht. Gleicher Fehler: 401, ungültiger Berechtigungsnachweis. Der einfache API-Schlüsselabschnitt erwähnt "... wenn Sie nicht auf Benutzerdaten zugreifen müssen ...", aber das gilt auch für meine Android-App. Ich verstehe es nicht. Gibt es niemanden, der erfolgreich eine Android-App erstellt hat, die eine Verbindung zu Google Drive-Daten im Auftrag eines Nutzers herstellt, der die Erlaubnis dazu über AccountManager und Google Credentials erteilt hat? –

+0

Nun, der einzige Unterschied zwischen Ihrem Code und dem [Beispiel für eine Aufgaben-API] (https://code.google.com/p/google-api-java-client/source/browse/tasks-android-sample/src/main/ java/com/google/api/services/samples/tasks/android/TasksSample.java? repo = samples) Ich sehe dann, ist, dass sie 'credential.setAccessToken (authToken)' * nach dem Erstellen der 'Tasks' aufrufen Beispiel. Vielleicht macht der Austausch dieser 2 Linien den Trick? –

+0

Kein Glück. Scheint, dass da etwas kaputt ist. Danke trotzdem. –

0

Ich habe alles versucht und fand diesen Code schließlich mit dem Google Kalender API. Ich habe jedes Mal, wenn ich GoogleCredentials benutzt habe, ein 401 bekommen und es an den Build übergeben.

HttpTransport transport = AndroidHttp.newCompatibleTransport();; 
    JsonFactory jsonFactory = new GsonFactory(); 
    HttpRequestInitializer httpRequestInitializer; 

    Log.i("Reached calendar builder", "Reached calendar builder"+accessToken); 

    //GoogleCredential credential = new GoogleCredential(); 

    httpRequestInitializer = new HttpRequestInitializer(){ 
     public void initialize(HttpRequest request) throws IOException 
     { 
       request.getHeaders().setAuthorization(GoogleHeaders.getGoogleLoginValue(accessToken)); 
     } 
    }; 

    Calendar service = new Calendar.Builder(transport, jsonFactory, httpRequestInitializer) 
    .setApplicationName("Meetrbus/1.0") 
    .setJsonHttpRequestInitializer(new GoogleKeyInitializer("API_KEY")) 
    .build(); 


} 
+0

Danke für Ihre Antwort. Es hat nicht funktioniert. Ich habe Ihren genauen Code mit dem einfachen API-Schlüssel versucht -> 401.Meine App ist eine "installierte Anwendung" mit einer Client-ID, die von der API-Konsole stammt. Ich bezweifle, dass ein einfacher API-Schlüssel in Kombination mit einer "installierten Anwendung" funktioniert. –

1

Es gibt 2 Probleme mit dem Snippet, das Sie enthalten.

  1. Sie müssen die alten authToken ungültig machen, bevor eine neues authToken aus dem Accountmanager holen.

    AccountManager.get(activity).invalidateAuthToken("com.google", authToken); 
    accountManager.getAuthToken(...); 
    
  2. Der Aufruf von setJsonHttpRequestInitializer muss den Simple API-Schlüssel in der APIs-Konsole für Ihr Projekt erklärt verwenden.

    • Es kann durch den Besuch der APIs Console erhalten werden.
    • Klicken Sie auf API Zugriff auf der linken Menüleiste.
    • Suchen Sie nach Einfache API-Zugriff, und kopieren Sie den API-Schlüssel.
    • Legen Sie den API-Schlüssel beim Erstellen des Drive-Objekts fest.

      .setJsonHttpRequestInitializer (neu GoogleKeyInitializer (KEY))

Es gibt eine kleine Probe des Token Ungültigkeits demonstriert hier: http://chiarg.com/?p=429

+0

Haben Sie es geschafft, eine Android-App zu erstellen, die Dateien von Google Drive herunterladen kann? Wenn ja, würden Sie den Code teilen, der das tut? Soweit ich weiß, habe ich die vollständigste Drive-App von Google, die auf Android funktioniert, und ich kann keine Datei herunterladen, um zu arbeiten (ich bekomme immer einen 401-Fehler ... irgendwie habe ich die Erlaubnis, Dateien komplett zu löschen , oder den Inhalt komplett ändern, aber nicht den aktuellen Inhalt herunterladen?) Mein Code ist hier: http://StackOverflow.com/Questions/12164024/android-Open-and-Save-Files-to-from-google-drive- sdk/12321331 # 12321331 – ArtOfWarfare

0

ich auf Google Drive auf Android eine umfangreiche Antwort gab hier:

Android Open and Save files to/from Google Drive SDK

Mit den Methoden, die ich in dieser Antwort auslegen, kann ich bestätigen, dass Sie Folgendes zu tun sind in der Lage:

  • Sets und Access-Meta-Daten
  • Dateien hochladen
  • Download-Dateien
  • verschieben von Dateien zwischen Google Drive Verzeichnissen
  • Löschen von Dateien aus dem Antrieb vollständig