Reputation: 28
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
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