【问题标题】:How to get rid of java.lang.IllegalStateException while trying to getAuthToken from Account尝试从帐户中获取授权时如何摆脱 java.lang.IllegalStateException
【发布时间】:2013-12-24 02:30:19
【问题描述】:

我正在尝试获取帐户的authToken,但收到此错误:

java.lang.IllegalStateException: calling this from your main thread can lead to deadlock

这就是我获取 AuthToken 的方式:

public class MyAccount {
 private final Account account;
 private final AccountManager manager;
 private final Context context;

 public MyAccount (Context context) {
        this.context = context;
        final Account[] accounts = AccountManager.get(context).getAccountsByType("com.myapp");
        account = accounts.length > 0 ? accounts[0] : null;
        manager = AccountManager.get(context);
 }

    public String getAuthToken() {
        @SuppressWarnings("deprecation")
        AccountManagerFuture<Bundle> future = manager.getAuthToken(account,"com.myapp", false, null, null);

        try {
            //GETTING EXCEPTION HERE
            Bundle result = future.getResult();
            return result != null ? result.getString(KEY_AUTHTOKEN) : null;
        } catch (AccountsException e) {
            Log.e(TAG, "Auth token lookup failed", e);
            return null;
        } catch (IOException e) {
            Log.e(TAG, "Auth token lookup failed", e);
            return null;
        }
    }
}

我从我的 MainActivity 中这样调用它:

 MyAccount account = new MyAccount(getApplicationContext());
 String authtoken = account.getAuthToken());

问题

如何调用MyAccount 获取 authToken 并消除异常?

【问题讨论】:

    标签: android android-context android-account


    【解决方案1】:

    使用AsyncTask,以便这项工作可以在后台线程 (doInBackground) 中完成

    private class FooTask extends AsyncTask<Void, Void, String>{
        /**
         * Override this method to perform a computation on a background thread. The
         * specified parameters are the parameters passed to {@link #execute}
         * by the caller of this task.
         *
         * This method can call {@link #publishProgress} to publish updates
         * on the UI thread.
         *
         * @param params The parameters of the task.
         *
         * @return A result, defined by the subclass of this task.
         *
         * @see #onPreExecute()
         * @see #onPostExecute
         * @see #publishProgress
         */
        @Override
        protected String doInBackground(Void... params) {
            MyAccount account = new MyAccount(getApplicationContext());
            String authtoken = account.getAuthToken());
            return authtoken;
        }
    
        /**
         * <p>Runs on the UI thread after {@link #doInBackground}. The
         * specified result is the value returned by {@link #doInBackground}.</p>
         *
         * <p>This method won't be invoked if the task was cancelled.</p>
         *
         * @param result The result of the operation computed by {@link #doInBackground}.
         *
         * @see #onPreExecute
         * @see #doInBackground
         * @see #onCancelled(Object)
         */
        @Override
        protected void onPostExecute(String token) {
            if (token != null){
                //use token here
            }
        }
    }
    

    用法:new FooTask().execute();

    【讨论】:

      【解决方案2】:

      来自

      "Calling this from your main thread can lead to deadlock and/or ANRs while getting accesToken" from GoogleAuthUtil(Google Plus integration in Android)

      Try it with an AsyncTask like this:
      
              AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
                  @Override
                  protected String doInBackground(Void... params) {
                      String token = null;
      
                      try {
                          token = GoogleAuthUtil.getToken(
                                  MainActivity.this,
                                  mPlusClient.getAccountName(),
                                  "oauth2:" + SCOPES);
                      } catch (IOException transientEx) {
                          // Network or server error, try later
                          Log.e(TAG, transientEx.toString());
                      } catch (UserRecoverableAuthException e) {
                          // Recover (with e.getIntent())
                          Log.e(TAG, e.toString());
                          Intent recover = e.getIntent();
                          startActivityForResult(recover, REQUEST_CODE_TOKEN_AUTH);
                      } catch (GoogleAuthException authEx) {
                          // The call is not ever expected to succeed
                          // assuming you have already verified that 
                          // Google Play services is installed.
                          Log.e(TAG, authEx.toString());
                      }
      
                      return token;
                  }
      
                  @Override
                  protected void onPostExecute(String token) {
                      Log.i(TAG, "Access token retrieved:" + token);
                  }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-04
        • 2019-10-30
        • 2020-07-12
        • 2016-04-29
        • 2011-03-13
        • 1970-01-01
        • 2017-01-19
        相关资源
        最近更新 更多