如何正确使用Google Pluslogin多个活动?

将Google+ api客户端生命周期与多活动应用程序的stream程进行绑定,是一种很好的/推荐的方式? 使活动取决于onConnected API客户端方法触发其function,使用它作为一次只有“激活”的东西,或者可能完全是其他东西?

我目前正在努力了解如何在我的Android应用中正确使用Google+login,该应用有多个活动。

这个想法是,在第一阶段,使用G +login只是为了validation用户,并能够得到她的电子邮件,发送通知和类似的东西。 最终,我打算推出其他Googlefunction,例如Maps或其他Google Play服务,所以我认为它已经可以实现了。

然而,我的应用并没有像预期的那样行事,而且我已经把这个问题缩小到这样一个事实,即当存在多个活动时,我还没有理解G +login应用循环。

什么是正确的或推荐的方式来实现这个authentication方法? 有没有可能引导我朝着正确方向的模式?

例如,我已经find了 api客户端生命周期的一个非常简单的图表 ,但是这与appstream程有什么关系呢?

最初我有一个login活动,在那里我loginbutton。 按照谷歌的指导,我可以login,当onConnected方法被调用时,我开始家庭活动(有点像应用程序的仪表板或主屏幕)。

这有点作用。 例如,如何处理每个活动的onStart和onStop? 我应该每次重新连接并重新validationapi客户端的每一个活动? 所以也许这是一个好主意,让一个BaseActivity来实现这一切。

另一个问题是,我应该使用相同的API客户端对象,并以某种方式传递它,或者可能将其存储在基本活动类? 或者我应该每次创build和初始化一个新的API客户端对象?

只要使用login活动来validationG +,然后获取电子邮件并将其存储在本地数据库中,并将用户标记为“已authentication”或“主动”等,那么该怎么办? 这会阻止我每次closures应用程序或连接中断时都需要重新进行身份validation,甚至可以节省一些电量。

该应用程序并没有真正使用G +发布或任何其他function。 理想情况下,它应该脱机工作,只需要像初始身份validation或其他一次性事物的连接。

任何build议或指针在正确的方向非常赞赏。

编辑:我已经阅读了所有可以find的使用Google+的指南和教程,并且每个人都从单一的活动angular度来解决这个问题。 我认为这是一个普遍的问题,它会受益于一个模式或至less一个一般的指导方针。

重新连接每个活动是绝对好的。 广泛地说,我看到有3种方式实现这个function:

  1. 大部分是以基本活动来实现的,其他的扩展。 这是每个活动的连接/断开,但代码只在一个地方。
  2. 在片段中实现连接/断开连接,并将其包含在需要身份validation的活动中。 如果你已经有了一个你不能扩展的基本function(例如一些游戏例子),这是有帮助的。
  3. 实施服务连接/断开。 如果需要login,则可以触发广播或类似内容。

所有这些工作,我看到他们都在真实世界的应用程序中使用。 需要记住的主要事情是从相对罕见的“现在login”用例中分离出99%的逻辑(用户要么login,要么退出,而且已经被告知)。 所以举例来说,onConnected / onConnection可能会触发很多,但大多数情况下,你忽略了或者只是在应用程序的状态上翻转一下。 只有在loginbutton的屏幕上,你需要连接结果的parsing和onActivityResult的东西。 想想谷歌播放服务连接主要是要求用户的状态,而不是签署他们,你应该没问题。

我同意Ian Barber的回答,但是要进一步解释一下,您的Activity应该被分为两类:解决login的Activity和需要login的活动。

大多数Activity不关心自己的身份validation用户,并将有相同的逻辑在您的应用程序。 他们将创build一个GoogleApiClient ,连接到设备上运行的Google Play服务进程,并读取用户的cachinglogin状态 – 如果用户login,则返回onConnected()否则返回onConnected() 。 如果用户没有login,大部分Activity都将希望重置您的应用程序状态并启动您的LoginActivity 。每个Activity都应该保留自己的GoogleApiClient实例,因为它是一个轻量级对象,用于访问Google Play所拥有的共享状态服务stream程。 例如,可以将此行为封装在共享的BaseActivity类或共享的SignInFragment类中,但每个实例都应该有自己的GoogleApiClient实例。

但是您的LoginActivity需要以不同的方式实现。 它也应该创build一个GoogleApiClient ,但是当它接收到onConnected()指示用户已经login时,它应该为用户启动一个合适的Activityfinish() 。 当LoginActivity收到onConnectionFailed()指示用户未login时,应尝试使用startResolutionForResult()解决login问题。

TL; DR

对于急躁的编码器,可以在GitHub上find以下实现的工作版本。

在许多不同的应用程序中多次重写login活动代码之后,简单(而不那么优雅)的解决scheme就是将Google API客户端创build为Application类对象。 但是,由于连接状态会影响用户体验stream量,所以我从来不喜欢这种方式。

将我们的问题仅仅归结为连接概念 ,我们可能会认为:

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

1.代理模式

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

 @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(); } } 

活动可以通过connectdisconnectrevoke方法与Connection类通信,但其行为由当前状态决定。 状态机需要以下方法:

 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.状态模式

这是一种行为模式,允许对象在其内部状态改变时改变其行为。 GoFdevise模式书描述了如何通过这种模式来表示TCP连接(这也是我们的情况)。

来自状态机的状态应该是一个singleton ,在Java中最简单的做法是创build一个名为State Enum ,如下所示:

 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方法如何connectdisconnectrevoke行为:

 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 ,所以一个或多个活动可以观察状态变化:

 @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... }