I am writing an InputMethodService, basically just a soft keyboard, from which I start another activity:
class Foo extends InputMethodService {
// ...
private void startNewActivity() {
Intent i = new Intent(this, NewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
// ...
}
But when I do this, the user will be in the process of typing. For example, the user presses the 'a' key to start the new activity. Is there a way, when the user finishes the new activity, that I can return them to typing and put the keyboard back as it were?
It is up the the application in which you are typing to store the data you've typed during it's onPause() and related methods. Then the app should restore its state in onResume(). Notice neither of these can be controlled by your keyboard.
One thing you might be able to do (depending on the nature of the activity you are starting) is let the activity be a dialog. Then it will appear over the current activity, and when the dialog is closed (back button pressed or you call finish()) everything returns to how it was.
Related
I have an activity that handles users login.
When user logs in he is forwarded to another activity. But when he presses "back" button he is back to login screen despite he is logged already. How can I avoid that behaviour?
Clear activity stack after user is logged in or use noHistory flag. Start login activity with intent that has these flags : http://developer.android.com/reference/android/content/Intent.html
Here is one way to do it
Intent afterLogin = new Intent(this, AfterLoginActivity.class);
login.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(afterLogin);
You just add this function in your second activity it will give your desired...All the best it will work 100% All the best
#Override
public void onBackPressed() {
// You should write the super function or finish() here...
}
I'm creating a Wizard-style application, where I need to keep the user data between activities A and B alive. A has a Next soft button and B has a Back soft button.
When using FLAG_ACTIVITY_REORDER_TO_FRONT I can keep the user data alive when the soft buttons are used, because each activity is reused.
But, when the user presses the Back hard button from B, B dies, due to that hard button uses finish() implicitly.
Then, I tried overriding onBackPressed in B, adding to it the same behavior as my Back soft button, thinking that the Back hard button will behave exactly like the former button (not finish B).
Now, getting back from B to A with Back hard key, everything is fine. At this point with the focus in A, when the user presses the back hard button again, the expected behavior is that the application leaves.
The problem is that expected behavior does not occur, given that B is still alive; so that overriden onBackPressed in B is still listening, and some other behavior ocurr instead.
How can I finish listening with the overriden onBackPressed in B, so that when the focus is in A the application leaves?
Thanks in advance.
Consider doing as Krylez's comment. Or you might want to use fragments. If you target SDKs which are older than 3.x, see support library.
There are sample projects inside SDK folder, which use wizard style.
Well, I could solved my problem with a natural Android solution:
Following the Krylez tip, I've stopped using FLAG_ACTIVITY_REORDER_TO_FRONT, so I don't have conflicts with the hard button anymore, and now I'm recycling the Intent which starts my wizard.
In A, I have a very common method which is called when the user presses the continue soft button to go to B. Activity A is just informative, so it doesn't need to put Intent's extras with user's data when going to B, like this:
/** Called when the user presses the Continue button*/
public void continueButtonOnClick(View view) {
Intent intent = this.getIntent();
intent.setClass(this, StepOneRegisterWizardActivity.class);
startActivity(intent);
}
When activity B starts, it always must seek if there are user's data available in Intent's extras, like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_step_one_register_wizard);
// Get the components of the content layout
usernameEditText = (EditText)findViewById(R.id.usernameEditText);
passwordEditText = (EditText)findViewById(R.id.passwordEditText);
getIntentExtras();
}
private void getIntentExtras() {
Intent intent = this.getIntent();
Bundle bundle = intent.getExtras();
if (bundle != null) {
usernameEditText.setText(bundle.getCharSequence("usernameEditText"));
passwordEditText.setText(bundle.getCharSequence("passwordEditText"));
}
}
Now, maybe from B, the user presses any back button available (soft or hard) to back to A. In this case, we need to put the user's data in Intent's extras, like this:
/** Called when the user presses the Back soft button*/
public void backButtonOnClick(View view) {
onBackPressed();
}
#Override
/** Called when the user presses the Back hard button*/
public void onBackPressed() {
finish();
Intent intent = this.getIntent();
intent.setClass(this, StepZeroRegisterWizardActivity.class);
intent.putExtra("usernameEditText", usernameEditText.getText());
intent.putExtra("passwordEditText", passwordEditText.getText());
startActivity(intent);
}
Finally, when the user presses the continue soft button again, the new Activity B will have the data that user entered las time.
I hope it helps someone.
I have a message notification, when user select the notificaton, a message display activity will show.
When user read the message and press back key to close the activity, I want to check if the previous activity is the same app's, if so, just go ahead, if not, I want to start the home activity for this app.
How can I do that?
How about this: Have the notification launch the Home Activity in a state that immediately has the Home Activity launch the MessageDisplayActivity. That is: (1) The intent that the notification sends should target the HomeActivity and include an extra flag identifying the Intent as being from the notification. (2) The HomeActivity, in onCreate(), upon finding that flag then simply launches the MesssageDisplayActivity.
Thus the HomeActivity will exist for a brief moment of time, but probably not long enough to be visible. It will then remain upon the back stack so that the back key will bring you there.
You should consider changing the launch mode of your Activity, so that you never have this problem - using singleTask or singleInstance should make this Activity always be the only one open for your app.
Have Intents within your app that call the message display activity (MDA) pass a boolean value of "true" that's extracted and stored in a field in the MDA. Have the field set by default to "false." Thus, if the MDA is called from an activity within your app, the field will have a boolean value of "true," if it's called from anywhere else (such as a notification), it will be set to false.
Override public void onBackPressed() in the MDA as follows:
public void onBackPressed() {
if (wasCalledFromYourApp == true) {
super.onBackPressed();
} else {
//[code that launches your app's home activity here]
}
}
(This is assuming the notification will only be created by one app).
Let's consider simple DB access application with two activities:
A - list of entries from DB
B - input form to enter new data to DB, with two buttons: Save / Cancel
Application starts with A (list) and from A user may go to B (input form).
To make entering new data more efficient I created a widget to jump directly to B (PendingIntent).
The observed behaviour of the application is like that:
If the first action of the user is widget (empty back stack) => the application opens B and when user click Save or Cancel activity is finished and focus goes back to Android desktop.
If main application was started before (A is on back stack) => B is still properly opened from widget however when user click Save or Cancel focus goes back to A
The behaviour described in 2 is OK when user starts B from A. However I would like to avoid it when B is started from widget.
Any hints ?
I have a situation where I need to do something similar. My quick fix was to add a "EXTRA_LAUNCHED_BY_WIDGET" Extra to the Intent launched by the widget. Then, in my Activity I treat that as a special case.
I needed to override the Back button behaviour, but you could just as easily use this case elsewhere, e.g. in other overridden Activity methods.
#Override
public void onBackPressed()
{
Bundle extras = getIntent().getExtras();
boolean launchedFromWidget = false;
if (extras.containsKey("EXTRA_LAUNCHED_BY_WIDGET"))
{
launchedFromWidget = extras.getBoolean("EXTRA_LAUNCHED_BY_WIDGET");
}
if (launchedFromWidget)
{
// Launched from widget, handle as special case
}
else
{
// Not launched from widget, handle as normal
}
}
My application starts with a welcome screen Activity, but that screen has an option to skip that screen altogether in future launches.
What's the proper Android way to do this? Initially, I just automatically detected the skipWelcome preference and switched to the 2nd activity from Welcome. But this had the effect of allowing the user to hit the back button to the welcome screen we promised never to show again.
Right now, in the Welcome activity, I read the preference and call finish() on the current activity:
SharedPreferences preferences = getPreferences(MODE_PRIVATE);
boolean skipWelcome = preferences.getBoolean("skipWelcome", false);
if (skipWelcome) {
this.finish();
}
And then I implement onDestroy to move on to the next Activity:
#Override
public void onDestroy() {
super.onDestroy();
startActivity(new Intent(Welcome.this, StartFoo.class));
}
But this makes for some weird visual transitions. I'm starting to think that I need a base Activity that pops open Welcome only if proper, and then goes to StartFoo.
I can't comment on Mayra's answer or I would (not enough rep), but that's the correct approach.
Hidden in the Android documentation is this important phrase for Activity.startActivityForResult(),
"As a special case, if you call
startActivityForResult() with a
requestCode >= 0 during the initial
onCreate(Bundle
savedInstanceState)/onResume() of your
activity, then your window will not be
displayed until a result is returned
back from the started activity. This
is to avoid visible flickering when
redirecting to another activity."
Another important note is that this call does not block and execution continues, so you need to stop execution of the onCreate by returning
if (skipWelcome) {
// Create intent
// Launch intent with startActivityForResult()
return;
}
The final piece is to call finish immediately in the welcome activity's onActivityResult as Mayra says.
There are a few solutions to this.
Did you try just launching the activity and finishing? I vauguely remember that working, but I could be wrong.
More correctly, in if(skipWelcome) you can start the new activity for result, then when onActivityResult is called, immidiately finish the welcome activity.
Or, you can have your launcher activity not have a view (don't set content), and launch either the welcome activity or StartFoo.