From my MainActivity (Launcher Activity) I press a button to start my GameActivity. I have it so when I hit the Back button in Game Activity, I don't return to my MainActivity and instead return to my home screen. Now when I resume my app it goes to MainActivity instead of returning to GameActivity despite being shown.
Goal
Main Activity -> Game Activity -> Home -> Game Activity
Current Result
Main Activity -> Game Activity -> Home -> Home Activity
A couple things..
It works perfectly when I navigate with my home and menu buttons.
I have no launchMode in my Manifest
So let us see what I have done!
Main Activity Button Click
Button startButton = findViewById(R.id.buttonStart);
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, GameActivity.class);
//stops back button to return to add player screen
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
});
Manifest Simplified
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainPage.MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar"
android:screenOrientation="portrait"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".GamePage.GameActivity"
android:label="#string/title_activity_game"
android:theme="#style/AppTheme.NoActionBar"
android:screenOrientation="portrait" />
</application>
In that case, just call finish() right after launching you GameActivity.
Button startButton = findViewById(R.id.buttonStart);
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, GameActivity.class);
startActivity(intent);
finish();
}
});
Edit: Update launchMode for your GameActivity also:
<activity android:name=".GameActivity" android:launchMode="singleInstance">
when you tap on the back button of device the method onBackPress is called, you can override him to redirect user according your necessity, which mean you can change the action for the Back Button, Code:
//When Back Button on click, it will come to this method.
#Override
public void onBackPressed() {
//Do anything you want here,
}
It doesn't seem like this is possible to do using the conventional back-stack mechanism. You can't return to the home screen using the back button without popping off all the Activities in your back-stack first (hence destroying them, if you have no memory leaks).
Then, when you click the menu button, a screenshot of your last displayed Activity should be shown, but since all of your Activities are destroyed your launcher Activity is loaded.
One way you can handle re-entering the app at the point of your choosing is by implementing a navigation Activity (in many cases this is a splash screen) as the launcher Activity. In this Activity, you would determine (using persistent storage i.e. SharedPreferences) which Activity/back-stack state the app should be set to.
For this example, you could store a boolean with key isInGame in SharedPreferences when you enter GameActivity. Then in the navigation activity, you can retrieve the value and launch GameActivity if true. Obviously, for handling game/app state you will have to store a lot more, but this demonstrates simple navigation.
Related
In my app, I want to prevent the user from going back to login activity after logging in, but I don't want to close the app. For example if the previous activity is login activity, I don't want to do anything when the user presses back, just stay in the current activity/fragment.
add finish(); in login activity and add onBackPressed in your next activity
#Override
public void onBackPressed() {
}
Add android:noHistory="true" in the manifest of your LoginActivity
<activity android:name=".LoginActivity" android:noHistory="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
The correct way to do this is to call finish() in the Login activity when it completes and launches the next activity. For example:
Intent intent = new Intent(LoginActivity.this, NextActivity.class);
startActivity(intent);
finish();
This would prevent the user from going back from NextActivity to LoginActivity since calling finish() destroys LoginActivity and removes it from the back stack.
There is no need to remove onBackPressed from NextActivity, and that may have unintended consequences (for example, if they navigate from Login -> Next -> Other -> Next then click back, they would expect to go back to Other). Disabling onBackPressed in Next would prevent that.
I have an app (lets call it "SendingApp") that is trying to launch my app by calling this on Button A:
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.example.sendingapp");
launchIntent.putExtra("my_extra", "AAAA"));
startActivity(launchIntent);
and this on Button B:
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.example.sendingapp");
launchIntent.putExtra("my_extra", "BBBB"));
startActivity(launchIntent);
In my own app (lets call that the "ReceivingApp") I have a launcher activity defined in the Manifest as such:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
In the onCreate method of my MainActivity class in the ReceivingApp I receive the extra and output it to a TextView like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = getIntent();
if(intent != null) {
Bundle extras = intent.getExtras();
if(extras != null && extras.getString("my_extra") != null){
((TextView)findViewById(R.id.test_text)).setText(extras.getString("my_extra"));
} else {
((TextView)findViewById(R.id.test_text)).setText("NORMAL START");
}
}
}
Starting The ReceivingApp normally by tapping its icon or starting to debug it from Eclipse works fine and the TextView reads "NORMAL START".
When I then close the ReceivingApp by pressing the back button and go to the SendingApp and press Button A, the ReceivingApp starts and displays AAAA as it should. If I go back again and press Button B the ReceivingApp is launched and displays BBBB. So far, so good.
When I force quit the ReceivingApp either in the task list or in the application manager and then go to the SendingApp and press Button A, the ReceivingApp will launch and display AAAA (still correct) but when I then go back and press Button B, the ReceivingApp will launch but not call onCreate and therefor not display BBBB but still show AAAA, just like it had been brought to foreground but had not received any intent. Pressing the back button in the ReceivingApp also shows that no new instance of MainActivity had been put on the stack of Activities.
Closing the ReceivingApp and starting it by clicking its icon fixes this behaviour. But I need it to be able to receive different intents, even when it was not running when it receives the first intent.
Has anyone come across this behaviour before? Is my code to receive the data wrong or could that be an Android bug?
I have a problem with resume Activity. I have a MainActivity which contains other activities. Each one contains a radio station. I have a button (Play) in each activity, and when the user clicks on it, the button changes its function to Stop, so it turns to Stop button. My problem is that when I go for example from Activity(B) to MainActivity and then return to Activity(B) instead of the Stop button, it shows again the Play button, and if the button is pressed, the player plays the same station again at the same moment. I tried to resume the activity using flag, but that didn't work.
My code looks like this:
if (position == 3) {
Intent intent = new Intent(RadioActivity.this, Taraf.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
And the manifest looks like this:
<activity
android:name=".SettingsActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait">
</activity>
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleTop">
</activity>
You should save the status of your button in sharedPreferences, and retrive it when you return to Activity(B), then reset your button according to status of the button saved in sharedpreferences.You can refer to this documentation.
you have to save the state somewhere whether in shared preferences or any other storage.
An d when you are returning to your activity you can retrieve this data.
Hi I have 2 activities,
Activity A and Activity B,
So its Activity A and on a Button click I go to Activity B.
Now I press home button and go and do somany other things. Because of memory issue the task is closed by android. Now when I try to open it again it starts from Activity B. Is this expected?
If yes is there a way to prevent it?
Below is the part of AndroidManifest where both activities are defined
Activity A = MenuActivity, Activity B = AndroidLauncher
<activity
android:name=".AndroidLauncher"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="#string/app_name"
android:finishOnTaskLaunch="true"
android:screenOrientation="portrait" >
</activity>
<activity
android:name=".MenuActivity"
android:clearTaskOnLaunch="true"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Also I am putting the code of onCreate of Activity B
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_view);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
int gameType = getIntent().getIntExtra("GAME_TYPE", 0);
GDXtoAndroidInterface.sharedInstance().activity = this;
TurnBasedHelper.sharedInstance().listener = this;
FrameLayout lg=(FrameLayout)findViewById(R.id.layout);
lg.addView(initializeForView(new LetterPress(GDXtoAndroidInterface.sharedInstance(),gameType), config));
busyDialog = new ProgressDialog(this);
busyDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
busyDialog.setCanceledOnTouchOutside(false);
busyDialog.setCancelable(false);
showBusy("Setting up..");
Log.d("MSG", "on create called launcher");
}
Also the reason why I need this is Activity A is like a login screen and Activity B is based on it. Activity B cannot work alone. User has to move from Activity A to Activity B
Thanks
when I try to open it again it starts from Activity B. Is this expected?
yes, this is the expected behavior.
when you press the home button (not the "back button") the entire task is sent by default to background, and when re-launching it (from recent tasks screen or the app icon at the home screen) it coming back by default to foreground with the same stack state as it was. same behavior applies also if your app was killed by the system while it was in background to preserve memory. the operating system will store the state of each activity in the stack, an restore it when it need to re-created (see this post)
you can think of the home button in relation to Activity like the relation in Windows OS terms as the "minimize" window button, and back button would be like the "close window" (x) button.
there a way to prevent it?
assuming you have good reason to do so and break this consistence expected behavior, you can use all kind of combinations between activity launch mode and intent flags that will give you the behavior you want..
I am developing simple application with only two activities.
Activity C configures application
Activity A for interaction with user when some event occur
It is not possible for user to navigate from the one to the other - this is why I call them independent activities. Further more activity A is being invoked only form event, there is no way for user to do it manually.
Problem. Let's assume that application is properly configured. Some event occurs in the system, so application A is being shown to the user. The user interact with it and activity goes to background. Then the user decides to launch configuration activity C. Activity C is shown to the user. The user uses back button to "close" activity, but instead of android launcher or desktop the user is being shown activity A (taken from history).
Similar scenario might happen the other way. C is being used by user, then taken to background. Some event shows activity A and user using back button goes to C instead of closing activity A.
I have solved the problem, but the solution is pretty dirty. Is there any clean or standard way of solving such problem?
Part of my solution includes what was suggested in one answer:
snippet from AndroidManifest.xml:
<activity
android:name=".C"
android:clearTaskOnLaunch="true"
android:excludeFromRecents="false"
android:launchMode="singleTask"
...
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:exported="false"
android:name=".A"
android:excludeFromRecents="true"
android:noHistory="true"
android:launchMode="singleInstance"
android:clearTaskOnLaunch="true"
....
>
</activity>
snippet from activity A:
public boolean onKeyUp(final int p_keyCode, final KeyEvent p_event) {
switch(p_keyCode) {
case KeyEvent.KEYCODE_ENDCALL:
case KeyEvent.KEYCODE_HOME:
case KeyEvent.KEYCODE_BACK:
case KeyEvent.KEYCODE_MUTE:
case KeyEvent.KEYCODE_POWER:
this.finish();
break;
....
}
return super.onKeyUp(p_keyCode, p_event);
}
snipped from event handler:
public class H extends BroadcastReceiver {
...
Intent intent = new Intent(p_context, A.class);
intent.addFlags(Intent.FLAG_FROM_BACKGROUND);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
p_context.startActivity(intent);
...
}
It works for my application. However I want application (activity C) to appear in Recent application. But once activity A is invoked application is removed from Recent.
I don't know if this is the cleanest way to do this, but you can override the void onBackPressed() activity method. This way you can mannually move your activity to the background, like this, and prevent the previous activity from popping in:
public void onBackPressed () {
moveTaskToBack (true);
}
Edit: Turns out there's a better way to do this:
Open your AndroidManifest.xml, and inside each declaration put the following: `android:noHistory="true"``. Doing so will tell Android that your activity does not leave a history, and therefore, when the user hits back Android will quit the application, since there's no other activity for it to return to.