Android:尝试使用 Google Play 服务启动默认播放器选择器大厅,遇到 NullPointerException
Posted
技术标签:
【中文标题】Android:尝试使用 Google Play 服务启动默认播放器选择器大厅,遇到 NullPointerException【英文标题】:Android: Trying to Launch Default Player Picker Lobby using Google Play Services, running into NullPointerException 【发布时间】:2014-05-15 18:30:05 【问题描述】:在过去的四天里,我一直被这个关于我的 android 应用程序的问题所困扰。我正在尝试从 Google Play 服务启动默认的 Player Picker UI 屏幕,但无论何时我都会遇到 NullPointerException:
04-03 13:12:22.045: E/AndroidRuntime(13042): FATAL EXCEPTION: main
04-03 13:12:22.045: E/AndroidRuntime(13042): java.lang.NullPointerException: Appropriate Api was not requested.
04-03 13:12:22.045: E/AndroidRuntime(13042): at com.google.android.gms.internal.er.b(Unknown Source)
04-03 13:12:22.045: E/AndroidRuntime(13042): at com.google.android.gms.common.api.b.a(Unknown Source)
04-03 13:12:22.045: E/AndroidRuntime(13042): at com.google.android.gms.games.Games.c(Unknown Source)
04-03 13:12:22.045: E/AndroidRuntime(13042): at com.google.android.gms.internal.gn.getSelectOpponentsIntent(Unknown Source)
04-03 13:12:22.045: E/AndroidRuntime(13042): at com.geti.geti.graphics.MultiplayerLobbyView.startInviteGame(MultiplayerLobbyView.java:102)
04-03 13:12:22.045: E/AndroidRuntime(13042): at com.geti.geti.graphics.MultiplayerLobbyView.onClick(MultiplayerLobbyView.java:302)
04-03 13:12:22.045: E/AndroidRuntime(13042): at android.view.View.performClick(View.java:4475)
04-03 13:12:22.045: E/AndroidRuntime(13042): at android.view.View$PerformClick.run(View.java:18786)
04-03 13:12:22.045: E/AndroidRuntime(13042): at android.os.Handler.handleCallback(Handler.java:730)
04-03 13:12:22.045: E/AndroidRuntime(13042): at android.os.Handler.dispatchMessage(Handler.java:92)
04-03 13:12:22.045: E/AndroidRuntime(13042): at android.os.Looper.loop(Looper.java:137)
04-03 13:12:22.045: E/AndroidRuntime(13042): at android.app.ActivityThread.main(ActivityThread.java:5419)
04-03 13:12:22.045: E/AndroidRuntime(13042): at java.lang.reflect.Method.invokeNative(Native Method)
04-03 13:12:22.045: E/AndroidRuntime(13042): at java.lang.reflect.Method.invoke(Method.java:525)
04-03 13:12:22.045: E/AndroidRuntime(13042): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
04-03 13:12:22.045: E/AndroidRuntime(13042): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
04-03 13:12:22.045: E/AndroidRuntime(13042): at dalvik.system.NativeStart.main(Native Method)
我正在关注这个:https://developers.google.com/games/services/android/realtimeMultiplayer。这是我的相关代码(我删除了导入):
public class MainActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener, OnClickListener
private static final int RC_SIGN_IN = 0;
private GoogleApiClient mGoogleApiClient;
private boolean mIntentInProgress;
private boolean mSignInClicked;
private ConnectionResult mConnectionResult;
public void onCreate(Bundle savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API, null)
.addScope(Plus.SCOPE_PLUS_LOGIN)
.build();
findViewById(R.id.sign_in_button).setOnClickListener(this);
findViewById(R.id.sign_out_button).setOnClickListener(this);
findViewById(R.id.goButton).setOnClickListener(this);
public GoogleApiClient getApiClient()
return mGoogleApiClient;
private void resolveSignInError()
if (mConnectionResult.hasResolution())
try
mIntentInProgress = true;
mConnectionResult.startResolutionForResult(this, RC_SIGN_IN);
catch (SendIntentException e)
mIntentInProgress = false;
mGoogleApiClient.connect();
protected void onStart()
super.onStart();
mGoogleApiClient.connect();
protected void onStop()
super.onStop();
if (mGoogleApiClient.isConnected())
mGoogleApiClient.disconnect();
@Override
public void onConnectionFailed(ConnectionResult result)
if (!mIntentInProgress)
mConnectionResult = result;
if (mSignInClicked)
resolveSignInError();
protected void onActivityResult(int requestCode, int responseCode, Intent intent)
if (requestCode == RC_SIGN_IN)
if (requestCode == RC_SIGN_IN)
if (responseCode != RESULT_OK)
mSignInClicked = false;
mIntentInProgress = false;
if (!mGoogleApiClient.isConnecting())
mGoogleApiClient.connect();
@Override
public void onConnected(Bundle connectionHint)
mSignInClicked = false;
if (Plus.PeopleApi.getCurrentPerson(mGoogleApiClient) != null)
Person currentPerson = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
String personName = currentPerson.getDisplayName();
Toast.makeText(this, "User if connected! Welcome " + personName +"!", Toast.LENGTH_LONG).show();
@Override
public void onConnectionSuspended(int cause)
mGoogleApiClient.connect();
@Override
public void onClick(View v)
if (v.getId() == R.id.sign_in_button)
findViewById(R.id.sign_in_button).setVisibility(View.GONE);
findViewById(R.id.sign_out_button).setVisibility(View.VISIBLE);
if (v.getId() == R.id.sign_in_button
&& !mGoogleApiClient.isConnecting())
mSignInClicked = true;
resolveSignInError();
if (v.getId() == R.id.sign_out_button)
if (mGoogleApiClient.isConnected())
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
findViewById(R.id.sign_in_button).setVisibility(View.VISIBLE);
findViewById(R.id.sign_out_button).setVisibility(View.GONE);
if (v.getId() == R.id.goButton)
goToTitleScreen();
@Override
protected void onResume()
super.onResume();
@Override
protected void onPause()
super.onPause();
public void goToTitleScreen()
Intent intent = new Intent(this, TitleScreen.class);
startActivity(intent);
finish();
还有我的多人游戏大厅:
public class MultiplayerLobbyView extends MainActivity implements RoomUpdateListener, RoomStatusUpdateListener, RealTimeMessageReceivedListener
final static int RC_SELECT_PLAYERS = 10000;
final static int RC_WAITING_ROOM = 10002;
boolean mPlaying = false;
final static int MIN_PLAYERS = 2;
@Override
public void onCreate(Bundle savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
super.onCreate(savedInstanceState);
setContentView(R.layout.multiplayer_lobby);
findViewById(R.id.quickGame).setOnClickListener(this);
findViewById(R.id.invitePlayers).setOnClickListener(this);
private RoomConfig.Builder makeBasicRoomConfigBuilder()
RoomConfig.Builder builder = RoomConfig.builder(this);
builder.setRoomStatusUpdateListener(this);
builder.setMessageReceivedListener(this);
return builder;
boolean shouldStartGame(Room room)
int connectedPlayers = 0;
for (Participant p : room.getParticipants())
if (p.isConnectedToRoom())
++connectedPlayers;
return (connectedPlayers >= MIN_PLAYERS);
private void startQuickGame()
// auto-match criteria to invite one random automatch opponent.
// You can also specify more opponents (up to 3).
Bundle am = RoomConfig.createAutoMatchCriteria(1, 1, 0);
// build the room config:
RoomConfig.Builder roomConfigBuilder = makeBasicRoomConfigBuilder();
roomConfigBuilder.setAutoMatchCriteria(am);
RoomConfig roomConfig = roomConfigBuilder.build();
// create room:
Games.RealTimeMultiplayer.create(getApiClient(), roomConfig);
// prevent screen from sleeping during handshake
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// go to game screen
private void startInviteGame()
GoogleApiClient mClient = getApiClient();
Intent intent = Games.RealTimeMultiplayer.getSelectOpponentsIntent(mClient, 1, 4, true);
try
startActivityForResult(intent, RC_SELECT_PLAYERS);
catch (NullPointerException e)
System.out.println("Error.");
public void onActivityResult(int request, int response, Intent data)
if (request == RC_SELECT_PLAYERS)
if (response != Activity.RESULT_OK)
// user canceled
return;
// get the invitee list
Bundle extras = data.getExtras();
final ArrayList<String> invitees =
data.getStringArrayListExtra(Multiplayer.EXTRA_INVITATION);
// get auto-match criteria
Bundle autoMatchCriteria = null;
int minAutoMatchPlayers =
data.getIntExtra(Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
int maxAutoMatchPlayers =
data.getIntExtra(Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);
if (minAutoMatchPlayers > 0)
autoMatchCriteria =
RoomConfig.createAutoMatchCriteria(
minAutoMatchPlayers, maxAutoMatchPlayers, 0);
else
autoMatchCriteria = null;
startQuickGame();
@Override
public void onConnectedToRoom(Room room)
// TODO Auto-generated method stub
@Override
public void onDisconnectedFromRoom(Room room)
@Override
public void onP2PConnected(String participantId)
// TODO Auto-generated method stub
@Override
public void onP2PDisconnected(String participantId)
// TODO Auto-generated method stub
@Override
public void onPeerDeclined(Room room, List<String> peers)
if (!mPlaying && shouldCancelGame(room))
Games.RealTimeMultiplayer.leave(getApiClient(), null, room.getRoomId());
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
private boolean shouldCancelGame(Room room)
// TODO Auto-generated method stub
return false;
@Override
public void onPeerInvitedToRoom(Room arg0, List<String> arg1)
// TODO Auto-generated method stub
@Override
public void onPeerJoined(Room arg0, List<String> arg1)
// TODO Auto-generated method stub
@Override
public void onPeerLeft(Room room, List<String> peers)
if (!mPlaying && shouldCancelGame(room))
Games.RealTimeMultiplayer.leave(getApiClient(),null, room.getRoomId());
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
@Override
public void onPeersConnected(Room room, List<String> peers)
if (mPlaying)
String mNewParticipant = new String();
room.getParticipantIds().add(mNewParticipant);
else if (shouldStartGame(room))
//start
@Override
public void onPeersDisconnected(Room arg0, List<String> arg1)
// TODO Auto-generated method stub
@Override
public void onRoomAutoMatching(Room room)
// TODO Auto-generated method stub
@Override
public void onRoomConnecting(Room room)
// TODO Auto-generated method stub
@Override
public void onJoinedRoom(int statusCode, Room room)
if (statusCode != GamesStatusCodes.STATUS_OK)
Toast.makeText(this, "Error!", Toast.LENGTH_LONG).show();
return;
Intent i = Games.RealTimeMultiplayer.getWaitingRoomIntent(getApiClient(), room, Integer.MAX_VALUE);
startActivityForResult(i, RC_WAITING_ROOM);
@Override
public void onLeftRoom(int statusCode, String roomId)
// TODO Auto-generated method stub
@Override
public void onRoomConnected(int statusCode, Room room)
if (statusCode != GamesStatusCodes.STATUS_OK)
// let screen go to sleep
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// show error message, return to main screen.
Toast.makeText(this, "Error!", Toast.LENGTH_LONG).show();
goToTitleScreen();
@Override
public void onRoomCreated(int statusCode, Room room)
if (statusCode != GamesStatusCodes.STATUS_OK)
Toast.makeText(this, "Error!", Toast.LENGTH_LONG).show();
return;
// get waiting room intent
Intent i = Games.RealTimeMultiplayer.getWaitingRoomIntent(getApiClient(), room, Integer.MAX_VALUE);
startActivityForResult(i, RC_WAITING_ROOM);
@Override
public void onClick(View v)
if (v.getId() == R.id.quickGame)
startQuickGame();
else if (v.getId() == R.id.invitePlayers)
startInviteGame();
@Override
public void onRealTimeMessageReceived(RealTimeMessage message)
// TODO Auto-generated method stub
我发现抛出异常的方法是:
private void startInviteGame()
GoogleApiClient mClient = getApiClient();
Intent intent = Games.RealTimeMultiplayer.getSelectOpponentsIntent(mClient, 1, 4, true);
try
startActivityForResult(intent, RC_SELECT_PLAYERS);
catch (NullPointerException e)
System.out.println("Error.");
我的 GoogleApiClient 是否正确?还是我缺少什么?我认为 MainActivity 中的 getter 足以抓住客户端。
【问题讨论】:
【参考方案1】:我在一分钟前正在玩耍并遇到了同样的错误。这对我有用。查看Accessing the Developer APIs 页面。重要的部分是:
@Override
public void onCreate(Bundle savedInstanceState)
// set requested clients (games and cloud save)
setRequestedClients(BaseGameActivity.CLIENT_GAMES |
BaseGameActivity.CLIENT_APPSTATE);
…
标志 BaseGameActivity.CLIENT_GAMES | BaseGameActivity.CLIENT_APPSTATE 请求 Play Games 和 Cloud Save API。
如果您要扩展 BaseGameActivity 类,还有一个不同的选项可以得到相同的东西。在CollectAllTheStars sample 中,他们将请求的 API 传递给 BaseGameActivity 构造函数:
public MainActivity()
// request that superclass initialize and manage the AppStateClient for us
super(BaseGameActivity.CLIENT_APPSTATE);
此游戏仅使用云保存,因此它只有 CLIENT_APPSTATE 标志。
【讨论】:
以上是关于Android:尝试使用 Google Play 服务启动默认播放器选择器大厅,遇到 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章
无法解决:com.google.android.support.gms:play-services-map:10.2.0
第一次尝试将应用上传到 Google Play 时出现错误“您的 Android App Bundle 使用错误的密钥签名。”
android google play 库使用过多的 CPU 使用率