1

我正在尝试在我的 android 项目中实现 Google+ 注册。我有一个A带有静态字段loginCredentials和按钮的活动。按下按钮时,L将启动活动并检查是否A.loginCredentials.isLogged() == false使用 Google 登录或在 true 上显示登录/撤销消息。

但是,我需要按两次登录按钮才能登录。这是调试器的日志:第一次单击后:

08-08 10:23:04.925: D/DEBUG(28107): onCreate
08-08 10:23:04.975: D/DEBUG(28107): connection failed
08-08 10:23:04.975: D/DEBUG(28107): connection failed - has resolution
08-08 10:23:04.975: D/DEBUG(28107): startResolutionForResult
08-08 10:23:05.415: D/DEBUG(28107): onStop
08-08 10:23:05.606: D/DEBUG(28107): A - onResume

第二次点击后:

08-08 10:24:39.908: D/DEBUG(28107): onCreate
08-08 10:24:40.288: D/DEBUG(28107): onConnected
08-08 10:24:40.288: D/DEBUG(28107): getAndUseAuthTokenInAsyncTask
08-08 10:24:40.318: D/DEBUG(28107): token = xxxxxxxxxxxxxxx
08-08 10:24:40.318: D/DEBUG(28107): returnResultAndFinish
08-08 10:24:40.368: D/DEBUG(28107): A - onResume
08-08 10:24:40.448: D/DEBUG(28107): onStop

调用startResolutionForResult()等待对话框后显示一秒钟,然后 L 活动神秘地停止,而 A 活动再次处于活动状态。这就是三星 Galaxy S4 的情况。

但是,在 Nexus V7 上它工作得很好,在第一个按钮单击后就是日志:

08-08 12:01:24.967: D/DEBUG(19455): onCreate
08-08 12:01:25.007: D/DEBUG(19455): connection failed
08-08 12:01:25.007: D/DEBUG(19455): connection failed - has resolution
08-08 12:01:25.007: D/DEBUG(19455): startResolutionForResult
08-08 12:01:25.377: D/DEBUG(19455): L: on activity result
08-08 12:01:25.667: D/DEBUG(19455): onConnected
08-08 12:01:25.667: D/DEBUG(19455): getAndUseAuthTokenInAsyncTask
08-08 12:01:25.687: D/DEBUG(19455): token = xxxxxxxx
08-08 12:01:25.687: D/DEBUG(19455): returnResultAndFinish
08-08 12:01:25.717: D/DEBUG(19455): A - onResume

你能给我一些提示吗?我以其他人的方式使用这些方法。这是代码:

一类:

package com.example.googlelogintest;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class A extends Activity implements OnClickListener {
    public static LoginCredentials loginCredentials = new LoginCredentials();
    static final String TAG = "DEBUG";

    static final int CODE_LOGIN = 100;

    Button btnLogin;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_a);

        btnLogin = (Button)findViewById(R.id.btnLogin);
        btnLogin.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        if (v == btnLogin) {
            Intent intent = new Intent(A.this,  L.class);
            startActivityForResult(intent, CODE_LOGIN);
        }
    }

    @Override
    protected void onResume() {
        Log.d(TAG, "A - onResume");
        super.onResume();
        if (loginCredentials.isLogged()) { 
            btnLogin.setText(String.format("Log out (%s)", loginCredentials.getLoggedAs()));
        }
        else {
            btnLogin.setText("Log in");
        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode,
            Intent intent) {
        Log.d(TAG, "A: on activity result");
        if (requestCode == CODE_LOGIN) {
            Log.d(TAG, "A: on activity result CODE_LOGIN, resultCode=" + Integer.toString(resultCode)); 

        }

    }
}

L.类:

package com.example.googlelogintest;

import java.io.IOException;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.GooglePlayServicesAvailabilityException;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.plus.PlusClient;
import com.google.android.gms.plus.PlusClient.OnAccessRevokedListener;

public class L extends Activity implements
        ConnectionCallbacks, OnConnectionFailedListener {

    static final int REQUEST_CODE_RESOLVE_ERR = 100;
    static final int MY_ACTIVITYS_AUTH_REQUEST_CODE = 101;

    static final String TAG = "DEBUG";

    static final String G_PLUS_SCOPE = "oauth2:https://www.googleapis.com/auth/plus.me";
    static final String USERINFO_SCOPE = "https://www.googleapis.com/auth/userinfo.profile";
    static final String EMAIL_SCOPE = "https://www.googleapis.com/auth/userinfo.email";
    static final String SCOPES = G_PLUS_SCOPE + " " + USERINFO_SCOPE + " " + EMAIL_SCOPE;

    LoginCredentials loginCredentials = new LoginCredentials();

    PlusClient plusClient;
    boolean alreadyShown = false,
            alreadyShown2 = false;

    enum Action {
        LOGIN, LOGOUT, REVOKE
    };

    Action action;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_l);

        if (GooglePlayServicesUtil
                .isGooglePlayServicesAvailable(getApplicationContext()) != ConnectionResult.SUCCESS) {
            Toast.makeText(this, "No google services found",
                    Toast.LENGTH_LONG).show();
            returnResultAndFinish();
        }


        plusClient = new PlusClient.Builder(this, this, this)
                .setVisibleActivities("http://schemas.google.com/AddActivity",
                        "http://schemas.google.com/BuyActivity").build();

        Log.d(TAG, "onCreate");

        if (!A.loginCredentials.isLogged()) {
            action = Action.LOGIN;
            plusClient.connect();
        }
        else 
            displLoginRevokeDialog();
    }

    void displLoginRevokeDialog() {
        DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                switch (which){
                case DialogInterface.BUTTON_POSITIVE:
                    action = Action.LOGOUT;
                    break;

                case DialogInterface.BUTTON_NEGATIVE:
                    action = Action.REVOKE;
                    break;
                }
                plusClient.connect();
            }
        };

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("Logout or revoke?").setPositiveButton("logout", dialogClickListener)
            .setNegativeButton("revoke", dialogClickListener).show();
    }

    @Override
    protected void onStop() {
        Log.d(TAG, "onStop");
        super.onStop();
        plusClient.disconnect();
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        // The user clicked the sign-in button already. Start to resolve
        // connection errors. Wait until onConnected() to dismiss the
        // connection dialog.
        Log.d(TAG, "connection failed");

        if (result.hasResolution()) {
            Log.d(TAG, "connection failed - has resolution");
            try {
                Log.d(TAG, "startResolutionForResult");
                result.startResolutionForResult(this, REQUEST_CODE_RESOLVE_ERR);
                alreadyShown2 = true;
            }
            catch (SendIntentException e) {
                Log.d(TAG, "exception");
                plusClient.connect();
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode,
            Intent intent) {
        Log.d(TAG, "L: on activity result");
        if (requestCode == REQUEST_CODE_RESOLVE_ERR && resultCode == RESULT_OK) {
            plusClient.connect();
        }
        else if (requestCode == MY_ACTIVITYS_AUTH_REQUEST_CODE
                && resultCode == RESULT_OK) {
            getAndUseAuthTokenInAsyncTask();
        }
    }

    public void logOut() {
        plusClient.clearDefaultAccount();
        plusClient.disconnect();
        returnResultAndFinish();
    }

    public void logIn() {
        loginCredentials.setLoggedAs(plusClient.getAccountName());
        getAndUseAuthTokenInAsyncTask();
    }

    public void revoke() {
        // Prior to disconnecting, run clearDefaultAccount().
        plusClient.clearDefaultAccount();

        plusClient.revokeAccessAndDisconnect(new OnAccessRevokedListener() {
           @Override
           public void onAccessRevoked(ConnectionResult status) {
               // mPlusClient is now disconnected and access has been revoked.
               // Trigger app logic to comply with the developer policies
               returnResultAndFinish();
           }
        });
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.d(TAG, "onConnected");

        switch (action) {
        case LOGIN:
            action = null;
            logIn();
            break;
        case LOGOUT:
            action = null;
            logOut();
            break;
        case REVOKE:
            action = null;
            revoke();
            break;
        }
    }

    @Override
    public void onDisconnected() {
        Log.d(TAG, "onDisconnected");
    }

    // Example of how to use the GoogleAuthUtil in a blocking, non-main thread
    // context
    String getAndUseAuthTokenBlocking() {
        try {
            // Retrieve a token for the given account and scope. It will always
            // return either
            // a non-empty String or throw an exception.
            final String token = GoogleAuthUtil.getToken(
                    getApplicationContext(), loginCredentials.loggedAs,
                    SCOPES);
            return token;
        }
        catch (GooglePlayServicesAvailabilityException playEx) {
            Dialog alert = GooglePlayServicesUtil.getErrorDialog(
                    playEx.getConnectionStatusCode(), this,
                    MY_ACTIVITYS_AUTH_REQUEST_CODE);
            alert.show();

        }
        catch (UserRecoverableAuthException userAuthEx) {
            if (alreadyShown) {
                return null;
            }

            alreadyShown = true;
            // Start the user recoverable action using the intent returned by
            // getIntent()
            startActivityForResult(userAuthEx.getIntent(),
                    MY_ACTIVITYS_AUTH_REQUEST_CODE);
        }
        catch (IOException transientEx) {
            // network or server error, the call is expected to succeed if you
            // try again later.
            // Don't attempt to call again immediately - the request is likely
            // to
            // fail, you'll hit quotas or back-off.
        }
        catch (GoogleAuthException authEx) {
            // Failure. The call is not expected to ever succeed so it should
            // not be
            // retried.
        }
        return null;
    }

    // Example of how to use AsyncTask to call blocking code on a background
    // thread.
    void getAndUseAuthTokenInAsyncTask() {
        Log.d(TAG, "getAndUseAuthTokenInAsyncTask");
        AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                String token = getAndUseAuthTokenBlocking();
                if (token == null) {
                    loginCredentials.setLogged(false);
                }
                else {
                    loginCredentials.setToken(token);
                    loginCredentials.setLogged(true);
                }

                Log.d(TAG, "token = " + loginCredentials.getToken());
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {
                returnResultAndFinish();
            }
        };
        task.execute();
    }

    void returnResultAndFinish() {
        Log.d(TAG, "returnResultAndFinish");
        A.loginCredentials = loginCredentials;
        finish();
    }


}

登录凭据.java

package com.example.googlelogintest;

public class LoginCredentials {
    boolean isLogged = false;
    String loggedAs = "";
    String token = "";

    public boolean isLogged() {
        return isLogged;
    }
    public void setLogged(boolean isLogged) {
        this.isLogged = isLogged;
    }
    public String getLoggedAs() {
        return loggedAs;
    }
    public void setLoggedAs(String loggedAs) {
        this.loggedAs = loggedAs;
    }
    public String getToken() {
        return token;
    }
    public void setToken(String token) {
        this.token = token;
    }


}
4

0 回答 0