Android:尝试使用Google Play服务启动默认播放器选择器大厅,运行NullPointerException

时间:2014-04-03 18:26:23

标签: android android-intent google-api google-play-games google-api-client

过去四天我的Android应用程序一直困在这个问题上。我正在尝试从Google Play服务启动默认的播放器选择器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 个答案:

答案 0 :(得分: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游戏和Cloud Save API。

如果您正在扩展BaseGameActivity类,那么也可以选择不同的选项。在CollectAllTheStars sample中,它们将请求的API传递给BaseGameActivity构造函数:

   public MainActivity() {
        // request that superclass initialize and manage the AppStateClient for us
        super(BaseGameActivity.CLIENT_APPSTATE);
    }

此游戏仅使用Cloud Save,因此它只有CLIENT_APPSTATE标志。