radek606
radek606

Reputation: 28

What's the reason of activity self duplication after some action in handler?

I'm developing a game that uses Bluetooth to connect with other devices. It's standard client-server scheme application.

When player, whom device is acting as a server, starts the game, an Activity is started. In its onCreate method I set up and show an ProgressDialog. This dialog is appearing until other player connects. In this Activity there is also Handler which receives a messages from background thread which manages Bluetooth connections. When first player is joining the game, handler receive proper message, and then i started initializing game, which means I dismiss ProgressDialog and load layout in setContendView(View v). And there is the problem because usually it works fine, but sometimes new instance of activity is created (while original one still exists) and it takes over game management. And this wouldn't be a major problem, but when game ends, and this new activity is finished, original one gets on top and when i try to close it, app is crashing.

I thought it's because of usage of setContendView(View v) in wrong place, but this happened even if another player is joining during game's term (then setContendView(View v) is not called again) so in extreme case three instances of activity are existing at the same time, causing a mess and crash for most of the players.

Code sample:

public void onCreate(Bundle savedInstanceState) {
    pDialog = new ProgressDialog(this);

    pDialog.setMessage("...");
    pDialog.setCancelable(false);
    pDialog.setCanceledOnTouchOutside(false);
    pDialog.setButton(DialogInterface.BUTTON_NEGATIVE, 
        context.getString(R.string.alert_button_cancel), 
        new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                pDialog.dismiss();
                finishActivity();
            }
        });
    pDialog.show();
}

and handler:

public void handleMessage(Message message) {
    if(message.what == Constants.MESSAGE_NEW_PLAYER) {
        NewPlayerMessage m = (NewPlayerMessage) message.obj;
        if(pDialog != null && pDialog.isShowing()) {
            pDialog.dismiss();
        }
        BluetoothService.broadcast(new PlayersUpdateMessage(game.getAllPlayersFields()));
        BluetoothService.broadcast(game.addMessage(new ChatMessage(m.getAddress(), ChatMessage.PLAYER_JOIN)));
        if (game.getDrawingPlayerAddr().equals("")){
            game.setDrawingPlayerAddr(BluetoothService.MY_ADDRESS);
            //...
            setGameMode(true);
            setGameTimer(game.getRoundTime());
        }
    }
    //...
}

where setGameMode() contains mentioned setContendView(View v) and initialization of buttons and other layout elements.

I have no idea what's the reason of this strange behaviour. It seems like it's totally random. I only noticed that it's more probable on some less powerfull devices.

Upvotes: 0

Views: 62

Answers (1)

Joel
Joel

Reputation: 838

To evade creating duplicate activities you should set the property launchMode to

   android:launchMode="singleTask"

Here is another example:

  <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTask" />

this will create the activity at the root of a new task and will route the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one

Detailed information for each of the available options are in:

http://developer.android.com/guide/topics/manifest/activity-element.html

Upvotes: 1

Related Questions