24

我正在开发一个集成了 google plus 的应用程序。到目前为止它工作正常,我能够检索用户配置文件。

但现在我想做以下事情:

1)我有两个活动signInActivityshareActivity

2)如果用户已经登录使用,signInActivity那么它不应该再次要求登录 shareActivity,应该直接分享内容。

3)如果用户未登录signInActivity并尝试使用共享数据,shareActivity则应用程序应登录用户,然后仅共享数据。在这种情况下,如果用户返回到signInActivity应用程序应该显示“你已经登录”

简而言之,我希望用户登录成为应用程序中的中心,这样如果它已经登录,它应该可以从任何活动中访问。

我听说过访问令牌,但我不知道如何使用它,并且文件说它在一小时内到期,这不是我想要的。

我怎样才能使中央谷歌加登录?可能吗?或者我需要在每个活动中对用户进行身份验证?

4

3 回答 3

37

在每个活动中管理单独的 GoogleApiClient 实例不会导致多次要求用户登录。

Google+ 登录(即 GoogleApiClient)为设备上的 Google 帐户和 Google Play 服务核心服务提供了一个接口——它没有每个 GoogleApiClient 实例的状态。因此,一旦为您的应用程序验证了设备帐户,GoogleApiClient 的新实例将访问相同的状态。GoogleApiClient 专门设计为一种访问由 Google Play 服务管理的中央状态的轻量级方式。

关于访问令牌,您很幸运!Google Play 服务会为您处理所有令牌管理。因此,尽管访问令牌仅持续一小时,正如您所说,如果您尝试使用 PlusClient 访问 Google API 并且您的访问令牌已过期,Google Play 服务将透明地为您请求新的访问令牌并完成调用。

请查看此 Google I/O 演讲的第一部分以了解更多详细信息:

http://www.youtube.com/watch?v=_KBHf1EODuk

于 2013-05-30T09:24:45.593 回答
16

0. 长话短说;博士

对于不耐烦的编码人员,可以在GitHub 上找到以下实现的工作版本。这与另一个Stack Overflow 帖子上写的答案相同。

在许多不同的应用程序中多次重写登录活动代码后,简单(但不那么优雅)的解决方案是将 Google API 客户端创建为应用程序类对象。但是,由于连接状态会影响 UX 流程,我对这种方法从不满意。

仅将我们的问题简化为连接概念,我们可以考虑:

  1. 它隐藏了 Google API 客户端。
  2. 它有有限的状态。
  3. 它是(相当)独特的。
  4. 当前状态会影响应用程序的行为。

1.代理模式

由于Connection封装了GoogleApiClient,它将实现ConnectionCallbacksand OnConnectionFailedListener

@Override
public void onConnected(Bundle hint) {
    changeState(State.OPENED);
}

@Override
public void onConnectionSuspended(int cause) {
    changeState(State.CLOSED);
    connect();
}

@Override
public void onConnectionFailed(ConnectionResult result) {
    if (currentState.equals(State.CLOSED) && result.hasResolution()) {
        changeState(State.CREATED);
        connectionResult = result;
    } else {
        connect();
    }
}

活动可以通过方法connectdisconnect和与 Connection 类进行通信revoke,但它们的行为由当前状态决定。状态机需要以下方法:

protected void onSignIn() {
    if (!googleApiClient.isConnected() && !googleApiClient.isConnecting()) {
        googleApiClient.connect();
    }
}

protected void onSignOut() {
    if (googleApiClient.isConnected()) {
        Plus.AccountApi.clearDefaultAccount(googleApiClient);
        googleApiClient.disconnect();
        googleApiClient.connect();
        changeState(State.CLOSED);
    }
}

protected void onSignUp() {
    Activity activity = activityWeakReference.get();
    try {
        changeState(State.OPENING);
        connectionResult.startResolutionForResult(activity, REQUEST_CODE);
    } catch (IntentSender.SendIntentException e) {
        changeState(State.CREATED);
        googleApiClient.connect();
    }
}

protected void onRevoke() {
    Plus.AccountApi.clearDefaultAccount(googleApiClient);
    Plus.AccountApi.revokeAccessAndDisconnect(googleApiClient);
    googleApiClient = googleApiClientBuilder.build();
    googleApiClient.connect();
    changeState(State.CLOSED);
}

2. 状态模式

这是一种行为模式,允许对象在其内部状态发生变化时改变其行为。GoF 设计模式一书描述了如何用这种模式表示 TCP 连接(这也是我们的例子)。

来自状态机的状态应该是 a singleton,而在 Java 中最简单的方法是创建如下Enum命名:State

public enum State {
    CREATED {
        @Override
        void connect(Connection connection) {
            connection.onSignUp();
        }
        @Override
        void disconnect(Connection connection) {
            connection.onSignOut();
        }
    },
    OPENING {},
    OPENED {
        @Override
        void disconnect(Connection connection) {
            connection.onSignOut();
        }
        @Override
        void revoke(Connection connection) {
            connection.onRevoke();
        }
    },
    CLOSED {
        @Override
        void connect(Connection connection) {
            connection.onSignIn();
        }
    };

void connect(Connection connection) {}
void disconnect(Connection connection) {}
void revoke(Connection connection) {}

该类Connection保存上下文,即当前状态,它定义了Connection方法connect、、disconnectrevoke将如何表现:

public void connect() {
    currentState.connect(this);
}

public void disconnect() {
    currentState.disconnect(this);
}

public void revoke() {
    currentState.revoke(this);
}

private void changeState(State state) {
    currentState = state;
    setChanged();
    notifyObservers(state);
}

3. 单例模式

由于不需要重复重新创建此类,我们将其作为单例提供:

public static Connection getInstance(Activity activity) {
    if (null == sConnection) {
        sConnection = new Connection(activity);
    }

    return sConnection;
}

public void onActivityResult(int result) {
    if (result == Activity.RESULT_OK) {
        changeState(State.CREATED);
    } else {
        changeState(State.CLOSED);
    }
    onSignIn();
}

private Connection(Activity activity) {
    activityWeakReference = new WeakReference<>(activity);

    googleApiClientBuilder = new GoogleApiClient
           .Builder(activity)
           .addConnectionCallbacks(this)
           .addOnConnectionFailedListener(this)
           .addApi(Plus.API, Plus.PlusOptions.builder().build())
           .addScope(new Scope("email"));

    googleApiClient = googleApiClientBuilder.build();
    currentState = State.CLOSED;
}

4. 可观察模式

该类Connection扩展了 Java Observable,因此 1 个或多个活动可以观察状态变化:

@Override
protected void onCreate(Bundle bundle) {
    connection = Connection.getInstance(this);
    connection.addObserver(this);
}

@Override
protected void onStart() {
    connection.connect();
}

@Override
protected void onDestroy() {
    connection.deleteObserver(this);
    connection.disconnect();
}

@Override
protected void onActivityResult(int request, int result, Intent data) {
    if (Connection.REQUEST_CODE == request) {
        connection.onActivityResult(result);
    }
}

@Override
public void update(Observable observable, Object data) {
    if (observable != connection) {
        return;
    }
    // Your presentation logic goes here...
}
于 2015-07-27T23:02:46.827 回答
6

对于阅读此问题的任何人,您还可以查看 Ian Barber 的此答案以及 Lee 回答的以下答案,该答案解释了使用 Google 以及登录和多个活动的三种广泛方式,我发现它们实际上非常有用。

于 2014-04-14T15:38:45.630 回答