2012-09-13 30 views
9

該應用程序已在「Google API控制檯」中註冊爲「已安裝的應用程序」 - 似乎這是Android應用程序的正確設置,不是嗎?如何在Android應用內設置Google Drive憑據?

所以我有一個客戶端ID和沒有祕密ID。要說清楚:它不是Web應用程序,也不是Google Drive-App - 這是一款Android應用程序,用於訪問Google雲端硬盤中的其他用戶數據。

在應用程序中獲取帳戶(作品),我確實請求令牌(作品)。現在我想用該令牌和客戶端ID連接到Google雲端硬盤。結果是「401,無效憑證」。這段代碼有什麼問題?

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

我不得不說,這是一大堆爛攤子。網上有很多頁面只顯示部分內容,並且有太多頁面使用不贊成,缺少或不同的方法來做同樣的事情。在我看來,沒有兩頁顯示的是從Android應用程序中獲取Google雲端硬盤數據的相同方式。

任何幫助,高度讚賞。

編輯:我可以自己解決它。這是不同的變化的組合:

  • 必須設置機器人:的minSdkVersion =「11」作爲一項要求
  • 只好用該電流庫:谷歌-API客戶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-客戶1.11.0-beta.jar,GSON-2.1.jar,番石榴11.0.1.jar,傑克遜 - 核 - 2.0.5.jar,jsr305-1.3.9.jar

這是現金t部獲得驅動對象:

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) { 
    } 

回答

3

呀,文檔是非常難趕上。

只要改變

new GoogleKeyInitializer(CLIENT_ID) 

new GoogleKeyInitializer(SIMPLE_API_ACCESS_KEY) 

,它應該工作。

你可以找到你SIMPLE_API_ACCESS_KEY在谷歌的APIs ConsoleAPI訪問網頁(API key)的簡單API訪問部分。如果此部分不可用,則必須先在服務頁面上激活Drive API訪問權限。

+0

對不起,也沒有工作。同樣的錯誤:401,無效的憑據。簡單的API關鍵部分提到了「...當你不需要訪問用戶數據...」,但是這對我的Android應用程序是正確的。我不明白。是否沒有人成功創建了一個Android應用程序,該應用程序代表通過AccountManager和Google Credentials授權的用戶連接到Google Drive數據? –

+0

那麼你的代碼和[Tasks 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)然後,我看到他們在構建任務後調用credential.setAccessToken(authToken)* *實例。所以也許交換這兩條線是否有訣竅? –

+0

沒有運氣。似乎有什麼東西壞了。不管怎麼說,還是要謝謝你。 –

0

我嘗試了所有這些,最終發現這個代碼與谷歌日曆api一起工作。每次我使用GoogleCredentials並將其傳遞到構建版本時,我都會使用401。

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

感謝您的答案。它沒有工作。我使用簡單的API密鑰 - > 401嘗試了您的確切代碼。我的應用程序是一個「安裝的應用程序」,帶有從API控制檯獲取的客戶端ID。我懷疑一個簡單的API密鑰與「已安裝的應用程序」結合使用。 –

1

存在2個與您所包含的代碼相關的問題。

  1. 取出由的AccountManager新authToken之前,您必須無效舊的authToken。

    AccountManager.get(activity).invalidateAuthToken("com.google", authToken); 
    accountManager.getAuthToken(...); 
    
  2. setJsonHttpRequestInitializer調用必須使用API​​控制檯爲您的項目申報的簡單API密鑰。

    • 它可以通過訪問APIs Console獲得。
    • 點擊左側菜單上的API訪問
    • 尋找簡單API訪問,並複製API密鑰
    • 構建Drive對象時設置API密鑰。

      .setJsonHttpRequestInitializer(新GoogleKeyInitializer(KEY))

有一個小樣本演示令牌無效點擊這裏:http://chiarg.com/?p=429

+0

您是否設法制作了可從Google雲端硬盤下載文件的Android應用?如果是這樣,你會介意分享它的代碼嗎?據我所知,我有最完整的Drive應用程序不是來自Google的Android應用程序,我無法獲取文件下載工作(我總是收到401錯誤......不知何故,我有權刪除完整的文件,或完全更改其內容,但不下載當前內容?)我的代碼在這裏:http://stackoverflow.com/questions/12164024/android-open-and-save-files-to-from-google-drive- SDK/12321331#12321331 – ArtOfWarfare

0

我給了一個廣泛的答案在Android設備上使用谷歌驅動器在這裏:

Android Open and Save files to/from Google Drive SDK

使用我在這個問題的答案鋪陳的方法,我可以確認,你能做到以下幾點:

  • 設置和訪問元數據
  • 上傳文件
  • 下載文件
  • 在Google雲端硬盤目錄之間移動文件
  • 完全刪除驅動器中的文件