从片段调用 Google Play 游戏服务
Posted
技术标签:
【中文标题】从片段调用 Google Play 游戏服务【英文标题】:Calling Google Play Game Services from a fragment 【发布时间】:2013-06-03 04:41:36 【问题描述】:我已在我的 android 应用程序中将一些 Google Play 游戏服务功能作为单独的 Activity 实现,我现在正尝试将我的代码重写为 (Action Bar Sherlock) 片段。我在片段中使用提供的 GameHelper 代码。
自动登录可以正常工作。用户发起的登录失败,因为 GameHelper 中的 StartResolutionForResult 调用返回到 Activity 的 onActivityResult 而不是片段。我已经使用 Log.D 验证了所有这些。我对此的理解是有限的——我应该怎么做才能解决这个问题?我尝试过传递不同的上下文,但 StartResolutionForResult 似乎只接受一个 Activity 作为其上下文。
【问题讨论】:
【参考方案1】:Google Play 游戏服务 API 应该与 Activity 的生命周期相关联,而不是与 Fragment 的生命周期相关联。如果您的游戏逻辑在 Fragment 中,您可以在 Activity 上实现 onActivityResult 并从那里调用您的 Fragment。看看我们的Type A Number Challenge 示例,它不仅是一款令人兴奋和令人上瘾的游戏,还演示了如何处理片段。 Type A Number 中的每个屏幕都是一个片段,它们根据需要与 Activity 进行通信。
在这种特殊情况下,与游戏 API 的所有交互都是由 Activity 进行的。但是,您也可以让 Activity 将 GamesClient
对象交给 Fragment,以便它可以实现自己的逻辑。
在所有情况下,请记住不要在 Fragment 中保留对 GamesClient
的持久引用超过您需要的时间。最好在需要时从Activity
(例如通过接口)查询它。这是为了防止它在 Activity 的生命周期中泄漏。
【讨论】:
谢谢布鲁诺。事实证明,该解决方案比我预期的要容易。我只是将以下代码添加到我的 onActivityResult 中:fred fragment=(fred)getSupportFragmentManager().findFragmentByTag("tab4"); fragment.onActivityResult(request, response, data); 为什么 API 不应该绑定到 Fragment 的生命周期?为什么是错的?有这方面的文档吗? @osrl 我也有同样的问题。我正在尝试将附近的共享功能封装在我的应用程序中的 DialogFragment 中,该功能仅在显示对话框时发布。无法为结果设置目标 Fragment 意味着我必须在需要此对话框的每个 Activity 中复制相同的 GoogleApiClient 代码,然后在客户端和需要它们的 Fragment 之间手动转发回调。【参考方案2】:不再支持移位 1
您可以尝试通过Fragment
拨打电话
private static final int REQUEST_CHECK_SETTINGS = 0x1;
final ResolvableApiException rae = (ResolvableApiException) e;
startIntentSenderForResult(rae.getResolution().getIntentSender(), REQUEST_CHECK_SETTINGS, null, 0, 0, 0, null);
然后像这样在 Fragment 的 onActivtyResult
上捕获结果:
@Override
public void onActivityResult(final int requestCode, final int resultCode, @Nullable final Intent data)
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode)
// Check for the integer request code originally supplied to startIntentSenderForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode)
case Activity.RESULT_OK:
// Do smth
break;
case Activity.RESULT_CANCELED:
// show Error
break;
break;
【讨论】:
【参考方案3】:您可以将onActivityResult
调用转发到片段,如下所示:
我们应该将请求代码按位移动 16 位。
public static final int REQUEST_CHECK_SETTINGS = 1<<16; //shifted 1 16 bits
将此添加到拥有该片段的活动中。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
注意:我从 FragmentActivity 中onActivityResult
的源代码中发现了这一点。它将 requestCode 向右移动 16 位。
/**
* Dispatch incoming result to the correct fragment.
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
mFragments.noteStateNotSaved();
int index = requestCode>>16;
if (index != 0)
index--;
final int activeFragmentsCount = mFragments.getActiveFragmentsCount();
if (activeFragmentsCount == 0 || index < 0 || index >= activeFragmentsCount)
Log.w(TAG, "Activity result fragment index out of range: 0x"
+ Integer.toHexString(requestCode));
return;
final List<Fragment> activeFragments =
mFragments.getActiveFragments(new ArrayList<Fragment>(activeFragmentsCount));
Fragment frag = activeFragments.get(index);
if (frag == null)
Log.w(TAG, "Activity result no fragment exists for index: 0x"
+ Integer.toHexString(requestCode));
else
frag.onActivityResult(requestCode&0xffff, resultCode, data);
return;
super.onActivityResult(requestCode, resultCode, data);
注意 2:如果有人能告诉我为什么使用这种方法会是一种不好的方法,我会很高兴
【讨论】:
【参考方案4】:我不确定 Games 的 API 与 Nearby 相比有多相似(我认为这应该可以),但是在为 Nearby 创建 GoogleApiClient 时,我发现在错误回调(状态、ConnectionResult)中传递的对象很方便可打包。所以我创建了一个可以启动的 Activity 来处理这些错误,然后将它收到的任何结果传回给调用者。
https://gist.github.com/damien5314/c13ce47bca035c517dfbdfb2af488a73
用法:
Nearby.Messages.publish(mNearbyApi, mMessage)
.setResultCallback(new ResultCallback<Status>()
@Override
public void onResult(@NonNull Status status)
Log.d(TAG, "Nearby publish result: " + getStatusCodeString(status.getStatusCode()));
if (status.getStatusCode() > 0)
Intent intent = ResolveErrorActivity.buildIntent(getContext(), status);
startActivityForResult(intent, ResolveErrorActivity.REQUEST_RESOLVE_ERROR);
);
只要你从一个 Fragment 调用startActivityForResult
,它就应该像往常一样得到结果。
【讨论】:
以上是关于从片段调用 Google Play 游戏服务的主要内容,如果未能解决你的问题,请参考以下文章
Google play 游戏服务再次显示来自 google+ 的登录屏幕
Google play 游戏服务 - 从应用程序以横向模式启动 google+ 登录流程