Failed to exclude SDK action on Google Drive

I am trying to implement the Google Drive Stephen Wylie example ( here ). Here is my code:

package com.googledrive.googledriveapp; // For Google Drive / Play Services // Version 1.1 - Added new comments & removed dead code // Stephen Wylie - 10/20/2012 import java.io.IOException; import java.util.ArrayList; import android.accounts.Account; import android.accounts.AccountManager; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import com.google.android.gms.auth.GoogleAuthException; import com.google.android.gms.auth.GoogleAuthUtil; import com.google.android.gms.auth.UserRecoverableAuthException; import com.google.android.gms.common.AccountPicker; import com.google.api.client.auth.oauth2.BearerToken; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.android2.AndroidHttp; import com.google.api.client.googleapis.extensions.android2.auth.GoogleAccountManager; import com.google.api.client.http.HttpRequestFactory; import com.google.api.client.http.HttpTransport; import com.google.api.client.http.json.JsonHttpRequest; import com.google.api.client.http.json.JsonHttpRequestInitializer; import com.google.api.client.json.jackson.JacksonFactory; import com.google.api.services.drive.Drive; import com.google.api.services.drive.Drive.Apps.List; import com.google.api.services.drive.Drive.Files; import com.google.api.services.drive.DriveRequest; import com.google.api.services.drive.DriveScopes; import com.google.api.services.drive.model.File; import com.google.api.services.drive.model.FileList; public class MainActivity extends Activity { private static final int CHOOSE_ACCOUNT=0; private static String accountName; private static int REQUEST_TOKEN=0; private Button btn_drive; private Context ctx = this; private Activity a = this; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // set up the GUI layout setContentView(R.layout.activity_main); // set the variables to access the GUI controls btn_drive = (Button) findViewById(R.id.btn_drive); btn_drive.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { chooseAccount(); } }); } public void chooseAccount() { Intent intent = AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"}, false, null, null, null, null); startActivityForResult(intent, CHOOSE_ACCOUNT); } // Fetch the access token asynchronously. void getAndUseAuthTokenInAsyncTask(Account account) { AsyncTask<Account, String, String> task = new AsyncTask<Account, String, String>() { ProgressDialog progressDlg; AsyncTask<Account, String, String> me = this; @Override protected void onPreExecute() { progressDlg = new ProgressDialog(ctx, ProgressDialog.STYLE_SPINNER); progressDlg.setMax(100); progressDlg.setTitle("Validating..."); progressDlg.setMessage("Verifying the login data you entered...\n\nThis action will time out after 10 seconds."); progressDlg.setCancelable(false); progressDlg.setIndeterminate(false); progressDlg.setOnCancelListener(new android.content.DialogInterface.OnCancelListener() { public void onCancel(DialogInterface d) { progressDlg.dismiss(); me.cancel(true); } }); progressDlg.show(); } @Override protected String doInBackground(Account... params) { return getAccessToken(params[0]); } @Override protected void onPostExecute(String s) { if (s == null) { // Wait for the extra intent } else { accountName = s; getDriveFiles(); } progressDlg.dismiss(); } }; task.execute(account); } /** * Fetches the token from a particular Google account chosen by the user. DO NOT RUN THIS DIRECTLY. It must be run asynchronously inside an AsyncTask. * @param activity * @param account * @return */ private String getAccessToken(Account account) { try { return GoogleAuthUtil.getToken(ctx, account.name, "oauth2:" + DriveScopes.DRIVE_READONLY); // IMPORTANT: DriveScopes must be changed depending on what level of access you want } catch (UserRecoverableAuthException e) { // Start the Approval Screen intent, if not run from an Activity, add the Intent.FLAG_ACTIVITY_NEW_TASK flag. a.startActivityForResult(e.getIntent(), REQUEST_TOKEN); e.printStackTrace(); return null; } catch (GoogleAuthException e) { e.printStackTrace(); return null; } catch (IOException e) { e.printStackTrace(); return null; } } private Drive getDriveService() { HttpTransport ht = AndroidHttp.newCompatibleTransport(); // Makes a transport compatible with both Android 2.2- and 2.3+ JacksonFactory jf = new JacksonFactory(); // You need a JSON parser to help you out with the API response Credential credential = new Credential(BearerToken.authorizationHeaderAccessMethod()).setAccessToken(accountName); HttpRequestFactory rf = ht.createRequestFactory(credential); Drive.Builder b = new Drive.Builder(ht, jf, null); b.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() { @Override public void initialize(JsonHttpRequest request) throws IOException { DriveRequest driveRequest = (DriveRequest) request; driveRequest.setPrettyPrint(true); driveRequest.setOauthToken(accountName); } }); return b.build(); } /** * Obtains a list of all files on the signed-in user Google Drive account. */ private void getDriveFiles() { Drive service = getDriveService(); Log.d("SiteTrack", "FUNCTION getDriveFiles()"); Files.List request; try { request = service.files().list(); // .setQ("mimeType=\"text/plain\""); } catch (IOException e) { e.printStackTrace(); return; } do { FileList files; try { Log.d("SiteTrack", request.toString()); files = request.execute(); } catch (IOException e) { e.printStackTrace(); Log.d("SiteTrack", "Exception"); return; } ArrayList<File> fileList = (ArrayList<File>) files.getItems(); Log.d("SiteTrack", "Files found: " + files.getItems().size()); for (File f : fileList) { String fileId = f.getId(); String title = f.getTitle(); Log.d("SiteTrack", "File " + fileId + ": " + title); } request.setPageToken(files.getNextPageToken()); } while (request.getPageToken() != null && request.getPageToken().length() >= 0); } protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { if (requestCode == CHOOSE_ACCOUNT && resultCode == RESULT_OK) { accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); GoogleAccountManager gam = new GoogleAccountManager(this); getAndUseAuthTokenInAsyncTask(gam.getAccountByName(accountName)); Log.d("SiteTrack", "CHOOSE_ACCOUNT"); } else if (requestCode == REQUEST_TOKEN && resultCode == RESULT_OK) { accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME); Log.d("SiteTrack", "REQUEST_TOKEN"); } } } 

Here is my manifest:

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.googledrive.googledriveapp" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="android.app.ActivityGroup" /> </activity> </application> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.INTERNET" /> </manifest> 

Here is my activity_main.xml:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/btn_drive" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Connect to Google Drive" /> </LinearLayout> 

And here is the LogCat error that I get. This happens when the button is pressed:

 10-28 00:25:28.637: E/AndroidRuntime(842): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.google.android.gms.common.account.CHOOSE_ACCOUNT (has extras) } 10-28 00:25:28.637: E/AndroidRuntime(842): at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1512) 10-28 00:25:28.637: E/AndroidRuntime(842): at android.app.Instrumentation.execStartActivity(Instrumentation.java:1384) 10-28 00:25:28.637: E/AndroidRuntime(842): at android.app.Activity.startActivityForResult(Activity.java:3190) 10-28 00:25:28.637: E/AndroidRuntime(842): at com.googledrive.googledriveapp.MainActivity.chooseAccount(MainActivity.java:67) 10-28 00:25:28.637: E/AndroidRuntime(842): at com.googledrive.googledriveapp.MainActivity$1.onClick(MainActivity.java:60) 10-28 00:25:28.637: E/AndroidRuntime(842): at android.view.View.performClick(View.java:3511) 10-28 00:25:28.637: E/AndroidRuntime(842): at android.view.View$PerformClick.run(View.java:14105) 10-28 00:25:28.637: E/AndroidRuntime(842): at android.os.Handler.handleCallback(Handler.java:605) 10-28 00:25:28.637: E/AndroidRuntime(842): at android.os.Handler.dispatchMessage(Handler.java:92) 10-28 00:25:28.637: E/AndroidRuntime(842): at android.os.Looper.loop(Looper.java:137) 10-28 00:25:28.637: E/AndroidRuntime(842): at android.app.ActivityThread.main(ActivityThread.java:4424) 10-28 00:25:28.637: E/AndroidRuntime(842): at java.lang.reflect.Method.invokeNative(Native Method) 10-28 00:25:28.637: E/AndroidRuntime(842): at java.lang.reflect.Method.invoke(Method.java:511) 10-28 00:25:28.637: E/AndroidRuntime(842): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 10-28 00:25:28.637: E/AndroidRuntime(842): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 10-28 00:25:28.637: E/AndroidRuntime(842): at dalvik.system.NativeStart.main(Native Method) 

Can anyone help?

+6
source share
2 answers

The Google Drive API (according to Google people) only works on a real device, in the Emulator it will crash with this error.

So my advice is, try a real device.

+7
source

We experimented, and our current theory is that the new Google OAuth library depends on the latest version of Google Play.

We found that if your device still has an Android Marketplace or an older Google Play, we cannot get OAuth to work.

So, you can try to open the Android Marketplace or the Google Play application to start the update.

Open the Android Marketplace, Accept the update on Google Play. Close the Marketplace and open the Google Play app. Accept the Google Play Terms of Service. Wait a few seconds, sacrifice a chicken, and then you can launch Google OAuth.

EDIT: It looks like Google is providing some recommendations on what your application should do if your users lack the correct version of Google Play. See: https://developer.android.com/google/play-services/setup.html#ensure

+8
source

All Articles