驱动器api在服务中不起作用

时间:2015-12-18 06:51:26

标签: android google-drive-api

我做了一项活动和一项服务。刚刚获得授权的活动工作正常,但当我尝试在服务中使用相同的帐户列出文件时它不起作用。

这是 mainactivity

public class MainActivity extends Activity {
GoogleAccountCredential mCredential;
private TextView mOutputText;
ProgressDialog mProgress;

static final int REQUEST_ACCOUNT_PICKER = 1000;
static final int REQUEST_AUTHORIZATION = 1001;
static final int REQUEST_GOOGLE_PLAY_SERVICES = 1002;
private static final String PREF_ACCOUNT_NAME = "accountName";
private static final String[] SCOPES = { DriveScopes.DRIVE_METADATA_READONLY };

/**
 * Create the main activity.
 * @param savedInstanceState previously saved instance data.
 */
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    LinearLayout activityLayout = new LinearLayout(this);
    LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.MATCH_PARENT,
            LinearLayout.LayoutParams.MATCH_PARENT);
    activityLayout.setLayoutParams(lp);
    activityLayout.setOrientation(LinearLayout.VERTICAL);
    activityLayout.setPadding(16, 16, 16, 16);

    ViewGroup.LayoutParams tlp = new ViewGroup.LayoutParams(
            ViewGroup.LayoutParams.WRAP_CONTENT,
            ViewGroup.LayoutParams.WRAP_CONTENT);

    mOutputText = new TextView(this);
    mOutputText.setLayoutParams(tlp);
    mOutputText.setPadding(16, 16, 16, 16);
    mOutputText.setVerticalScrollBarEnabled(true);
    mOutputText.setMovementMethod(new ScrollingMovementMethod());
    activityLayout.addView(mOutputText);

    mProgress = new ProgressDialog(this);
    mProgress.setMessage("Calling Drive API ...");
    mOutputText.setText("hi");
    setContentView(activityLayout);

    // Initialize credentials and service object.
    mCredential = GoogleAccountCredential.usingOAuth2(
            getApplicationContext(), Arrays.asList(SCOPES))
            .setBackOff(new ExponentialBackOff())
            .setSelectedAccountName((null));
}


/**
 * Called whenever this activity is pushed to the foreground, such as after
 * a call to onCreate().
 */
@Override
protected void onResume() {
    super.onResume();
    if (isGooglePlayServicesAvailable()) {
        refreshResults();
    } else {
        mOutputText.setText("Google Play Services required: " +
                "after installing, close and relaunch this app.");
    }
}

/**
 * Called when an activity launched here (specifically, AccountPicker
 * and authorization) exits, giving you the requestCode you started it with,
 * the resultCode it returned, and any additional data from it.
 * @param requestCode code indicating which activity result is incoming.
 * @param resultCode code indicating the result of the incoming
 *     activity result.
 * @param data Intent (containing result data) returned by incoming
 *     activity result.
 */
@Override
protected void onActivityResult(
        int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode) {
        case REQUEST_GOOGLE_PLAY_SERVICES:
            if (resultCode != RESULT_OK) {
                isGooglePlayServicesAvailable();
            }
            break;
        case REQUEST_ACCOUNT_PICKER:
            if (resultCode == RESULT_OK && data != null &&
                    data.getExtras() != null) {
                String accountName =
                        data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                if (accountName != null) {
                    mCredential.setSelectedAccountName(accountName);
                    SharedPreferences settings =
                            PreferenceManager.getDefaultSharedPreferences(this);
                    SharedPreferences.Editor editor = settings.edit();
                    editor.putString(PREF_ACCOUNT_NAME, accountName);
                    editor.apply();
                }
            } else if (resultCode == RESULT_CANCELED) {
                mOutputText.setText("Account unspecified.");
            }
            break;
        case REQUEST_AUTHORIZATION:
            if (resultCode != RESULT_OK) {
                chooseAccount();
            }
            break;
    }

    super.onActivityResult(requestCode, resultCode, data);
}

/**
 * Attempt to get a set of data from the Drive API to display. If the
 * email address isn't known yet, then call chooseAccount() method so the
 * user can pick an account.
 */
private void refreshResults() {
    if (mCredential.getSelectedAccountName() == null) {
        chooseAccount();
    } else {
        if (isDeviceOnline()) {
            new MakeRequestTask(mCredential).execute();
        } else {
            mOutputText.setText("No network connection available.");
        }
    }
}

/**
 * Starts an activity in Google Play Services so the user can pick an
 * account.
 */
private void chooseAccount() {
    startActivityForResult(
            mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
}

/**
 * Checks whether the device currently has a network connection.
 * @return true if the device has a network connection, false otherwise.
 */
private boolean isDeviceOnline() {
    ConnectivityManager connMgr =
            (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    return (networkInfo != null && networkInfo.isConnected());
}

/**
 * Check that Google Play services APK is installed and up to date. Will
 * launch an error dialog for the user to update Google Play Services if
 * possible.
 * @return true if Google Play Services is available and up to
 *     date on this device; false otherwise.
 */
private boolean isGooglePlayServicesAvailable() {
    final int connectionStatusCode =
            GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) {
        showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
        return false;
    } else if (connectionStatusCode != ConnectionResult.SUCCESS ) {
        return false;
    }
    return true;
}

/**
 * Display an error dialog showing that Google Play Services is missing
 * or out of date.
 * @param connectionStatusCode code describing the presence (or lack of)
 *     Google Play Services on this device.
 */
void showGooglePlayServicesAvailabilityErrorDialog(
        final int connectionStatusCode) {
    Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
            connectionStatusCode,
            MainActivity.this,
            REQUEST_GOOGLE_PLAY_SERVICES);
    dialog.show();
}

/**
 * An asynchronous task that handles the Drive API call.
 * Placing the API calls in their own task ensures the UI stays responsive.
 */
private class MakeRequestTask extends AsyncTask<Void, Void, List<String>> {
    private com.google.api.services.drive.Drive mService = null;
    private Exception mLastError = null;

    public MakeRequestTask(GoogleAccountCredential credential) {
        HttpTransport transport = AndroidHttp.newCompatibleTransport();
        JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
        mService = new com.google.api.services.drive.Drive.Builder(
                transport, jsonFactory, credential)
                .setApplicationName("Drive API Android Quickstart")
                .build();
    }

    /**
     * Background task to call Drive API.
     * @param params no parameters needed for this task.
     */
    @Override
    protected List<String> doInBackground(Void... params) {
        try {
            return getDataFromApi();
        } catch (Exception e) {
            mLastError = e;
            cancel(true);
            return null;
        }
    }

    /**
     * Fetch a list of up to 10 file names and IDs.
     * @return List of Strings describing files, or an empty list if no files
     *         found.
     * @throws IOException
     */
        private List<String> getDataFromApi() throws IOException {
            // Get a list of up to 10 files.
            List<String> fileInfo = new ArrayList<String>();
            FileList result = mService.files().list()
                    .setMaxResults(10)
                    .execute();
            List<File> files = result.getItems();
            if (files != null) {
                for (File file : files) {
                    fileInfo.add(String.format("%s (%s)\n",
                            file.getTitle(), file.getId()));
                }
            }
            return fileInfo;
        }


    @Override
    protected void onPreExecute() {
        mOutputText.setText("");
        mProgress.show();
    }

    @Override
    protected void onPostExecute(List<String> output) {
        mProgress.hide();
        if(mCredential.getSelectedAccountName()!=null){
           sendBroadcast(new Intent("account").putExtra("account",mCredential.getSelectedAccountName()));
            finish();}
    }

    @Override
    protected void onCancelled() {
        mProgress.hide();
        if (mLastError != null) {
            if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
                showGooglePlayServicesAvailabilityErrorDialog(
                        ((GooglePlayServicesAvailabilityIOException) mLastError)
                                .getConnectionStatusCode());
            } else if (mLastError instanceof UserRecoverableAuthIOException) {
                startActivityForResult(
                        ((UserRecoverableAuthIOException) mLastError).getIntent(),
                        MainActivity.REQUEST_AUTHORIZATION);
            } else {
                mOutputText.setText("The following error occurred:\n"
                        + mLastError.getMessage());
            }
        } else {
            mOutputText.setText("Request cancelled.");
        }
    }
}
}

这是必需的

服务代码

    void initialize(String id){
        account=id;
        mCredential = GoogleAccountCredential.usingOAuth2(
                this, Arrays.asList(SCOPES))
                .setBackOff(new ExponentialBackOff())
                .setSelectedAccountName(id);
        HttpTransport transport = AndroidHttp.newCompatibleTransport();
        JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
        mService = new com.google.api.services.drive.Drive.Builder(
                transport, jsonFactory, mCredential)
                .setApplicationName("Drive API Android Quickstart")
                .build();
    }
public void listRoot(final com.google.api.services.drive.Drive mService,  final listReturn listReturn) {
        final ArrayList<com.google.api.services.drive.model.File> files = new ArrayList<>();
        if (asyncTask != null && asyncTask.getStatus() == AsyncTask.Status.RUNNING)
            asyncTask.cancel(true);
        asyncTask = new AsyncTask<Void, Integer, Void>() {
            Exception e=null;
            @Override
            public void onProgressUpdate(Integer... v){
                if(v!=null && v[0]==1 && e!=null)listReturn.throwError(e);
                else listReturn.list(files);
            }
            @Override
            protected Void doInBackground(Void... voids) {
                try {
                    String pg = "";
                    for (; ; ) {
                        Drive.Files.List lst = mService
                                .files()
                                .list()
                                .setFields(mFolderFields)
                                .setMaxResults(100);

                        if (!pg.equals(""))
                            lst.setPageToken(pg);
                         FileList fl;
                        try {
                            fl = lst.execute();
                        } catch (Exception e1) {
                            fl=null;
                            e1.printStackTrace();
                        }


                        if (fl.size() == 0)
                            break;
                        for (com.google.api.services.drive.model.File file : fl.getItems()) {
                            if (files.contains(file))
                                continue;
                            else if (isRoot(file)) {
                                files.add(file);
                            }
                        }
                        if (pg.equals(fl.getNextPageToken()))
                            break;
                        pg = fl.getNextPageToken();
                        if (pg == null || pg.equals(""))
                            break;
                    }
                    publishProgress(0);
                } catch (Exception e) {
                    this.e=e;
                    publishProgress(1);

                }
                return null;
            }
        }.execute();
    }

错误排在第

fl=lst.execute();

编辑 - 错误日志

com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException
12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.intercept(GoogleAccountCredential.java:284)
12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at com.amaze.filemanager.driveplugin.DriveUtil$2.doInBackground(DriveUtil.java:119)
12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at com.amaze.filemanager.driveplugin.DriveUtil$2.doInBackground(DriveUtil.java:97)
12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:292)
12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)

12-18 23:35:18.677 12181-12707/com.amaze.filemanager.driveplugin W/System.err: Caused by: com.google.android.gms.auth.UserRecoverableAuthException: NeedPermission
12-18 23:35:18.687 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at com.google.android.gms.auth.GoogleAuthUtil.zza(Unknown Source)
12-18 23:35:18.687 12181-12707/com.amaze.filemanager.driveplugin W/System.err:     at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)

1 个答案:

答案 0 :(得分:0)

此答案是对您的电子邮件的直接反应,指的是RESTDemo Github项目。引用:

  

我检查了你将活动对象传递给的实现   在rest.java中初始化驱动器api。我处在一种我不能解决的境地   发送一个活动对象到这个类。但我有一个活动要获得   authorization.Is有任何方法重新初始化这些驱动对象   没有使用活动对象,因为我已经获得一次授权?

我不得不承认我没有时间分析你问题中的所有代码,所以我会尝试专注于REST单例类。如你所见:

private static com.google.api.services.drive.Drive mGOOSvc;
...
static void init(Activity ctx){
  mGOOSvc = new Drive.Builder(
    AndroidHttp.newCompatibleTransport(), 
    new GsonFactory(),
    GoogleAccountCredential.usingOAuth2(
      ctx,                     // or ctx.getApplicationContext(),
      Collections.singletonList(DriveScopes.DRIVE)
    )
  ).build();
}

需要GoogleAccountCredential的活动上下文(除了应用程序上下文之外)。这将是一次性初始化,只要您的应用程序还活着,您就可以使用静态mGOOSvc

但是,如果execute()失败,还需要活动上下文才能解析UserRecoverableAuthIOException。此异常通过startActivityForResult((((UserRecoverableAuthIOException)ex).getIntent()),...)以及后续onActivityResult()解决。此错误可能随时发生,因为授权可以从外部撤消(http://drive.google.com&gt;设置&gt;管理应用&gt; ...&gt;从驱动器断开连接)。

结论是,如果您决定忽略重新发生UserRecoverableAuthIOException的可能性(您忽略此异常或自己处理),您可以一次性逃脱 - 只需致电 init()。请注意,这正是REST类所做的,它只调用connect()方法一次并忽略后续的execute()错误。请记住,REST是一个单例,只要静态mGOOSvc处于活动状态,您就可以从“活动”或“服务”中解决它。

还有另一种情况需要再次呼叫init()。这是在REQ_ACCPICK路径here中看到的帐户切换的情况。对于新用户,您的应用肯定需要新的mGOOSvc(如果尚未授权,则需要新的授权)。

所以,你可以抢夺REST class,然后将其插入你的代码(非ui线程调用)。如果您不处理多个用户,也可以删除.setSelectedAccountName(email)

祝你好运