I am setting up an App Widget, When the user adds the widget to their home screen, It pops up with my configuration activity.
but now I need my user to login, SO i redirect them to my login activty,
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!isLoggedIn()) {
Intent intent = new Intent(AppWidgetConfigureActivity.this, LoginActivity.class);
intent.putExtra("Source", "widgetConfig");
startActivity(intent);
this.finnish();
}
But now when my login activity has successfully logged in, I need to create my appwidget config intent and start it up again.
But im not sure how to do this, because the config activity contains information like the widget id etc.
How can I start-up my config activity again?
The answer may be as simple as not calling finish(). This will keep you configuration activity on the task stack and when the login activity finishes, the configuration activity will be displayed again.
If you used startActivityForResult, you could use your login activity to get some data that can be used when coming back to your own activity.
Related
I'm new in android development, and there is something about the life cycle activity that I don't understand, especially with the following example of application that i'm working on.
In my app, I have a Login activity and a Main activity.
In my Login activity, with successful attempt, there is a Intent that start the main activity, and finish() the login activity.
==> There, my login activity is destroyed, so this should not show up again.
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("authentResult", tokenDto);
startActivity(intent);
finish(); //destroy activity to not open it with back button`
In my Main activity, I have a disconnect button that create an Intent that start a (new ?) login activity.
==> Until there, everything's normal, and the login activity is displyed.
Intent loginActivity = new Intent(this, LoginActivity.class);
startActivity(loginActivity);
In the login activity, using the Back button should close the app.
To do that, I send an intent with special flag to the main activity to finish it (So the back button will not wake up the main activity), and then I finish the login activity. The onDestroy method is called and I see the login window close itself.
==> From here I expect the app to be closed. But a "new" login activity shows up, and i suspect that it would be the activity of the first point, so I'm a little lost there...
public void onBackPressed() {
Log.d(TAG, "BACK PRESSED - loginActivity");
//Finish MainActivity
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("EXIT", true);
startActivity(intent);
finish(); // finish login activity
}
In the onCreate in the mainActivity, I begin with this :
if (getIntent().getBooleanExtra("EXIT", false)) {
finish();
}
Do anyone could explain to me what I'm missing, or show me a better way to close the app directly ?
Don't hesitate to telle me if something's not clear.
If you declare the Login activity as main activity in the Manifest, if you don't destroy it when you launch the second activity then i think the back button will do all you expect without any additional code, and if you press back key on the login activity it will go to phone home screen
On Android applications is the system that decides when to close/kill application.
I have an app that it password protected to stop unauthorised access to data.
What I need to ask is:
when app is closed using the home button, then reopened I need it to go to the LoginActivity, I think I have sorted this using android:launchMode="singleTask"
But if I press the back button it takes me back to the menu without the need for logging in again - so it bypasses the password?
Can you please help?
On your activity, before it goes to background by pressing home, set a flag that the user has logged out or clear the session.
Then onResume of your activity, detect if the flag for user is still logged in or session is still valid. If not valid. then just send an intent to open your login activity.
So even you press back, that activity that resumed will validate if the user is still logged in or the session is still valid.
Create a custom application class with a flag indicating whether the user is logged in.
public class MyApplication extends Application {
boolean loggedIn;
}
In your activity you can then check if the user is logged in. If they aren't, return them to the login activity.
protected void onCreate(Bundle savedInstanceState) {
MyApplication app = ((MyApplication) getApplicationContext());
if (!app.loggedIn) {
Intent intent = new Intent(this, LoginActivity.class);
//go to old activity
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
}
I have one activity which can be launched from several other activites, along with url filter intents.
On this activity I use the home icon in the actionbar as a back button, bringing the user back to the previous activity (and not as a "home" action). For now I do this by calling the finish() function. This works fine when working from within the application.
However, if launching the activity by an url filter intent, I want the home icon to bring the user to the main activity. Obviously, calling finish() will just close the activity.
So my question is, is there a way to check whether my application stack is empty and then launch the main acivity if true? Or am I attacking this the wrong way?
If your app is launched via url intent filter and it creates its own task, then you can use
if (isTaskRoot()) {
// This activity is at root of task, so launch main activity
} else {
// This activity isn't at root of task, so just finish()
}
EDIT: Added another possible method
If your app is launched into an existing task when it is launched via URL intent filter, then you can do something like the following:
When you launch your activity from other activities in your application, add an EXTRA to the Intent like this:
Intent intent = new Intent(this, MyActivity.class);
intent.putExtra("internal", "true");
startActivity(intent);
When your activity gets launched it can then check for the presence or absence of the EXTRA in the Intent to determine whether it was launched internally or via URL intent-filter, like this:
Intent intent = getIntent();
if (intent.hasExtra("internal")) {
// Launched internally
} else {
// Launched via intent-filter
}
I have an application and every new created activity will start an async task to validate the user session. If the session is valid, the application flows continues. If not, the whole activity stack must be cleared and there should be only the login activity. This activity has a "no history" flag so it is never kept in the stack.
I've been trying some solutions provided here: Android: Clear Activity Stack but with no success.
This must works on the lowest android possible, being the least 2.2
Thanks!
I keep my login Activity on the stack. In the onResume() of the login Activity, I check to see if the user has login credentials and, if so, call startActivity for the next screen presented after login. The user does not see the login screen in this case.
When the user presses the logout button, I clear the user's credentials and then this clears the stack all the way back to the login screen:
Intent intentLaunchLogin = new Intent(this, ActivityLogin.class);
intentLaunchLogin.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intentLaunchLogin);
Also, if the user is on the screen presented after the login and they press the 'back' button, I don't want them to go to the login Activity. This code will send the user to the Home screen as would be expected:
moveTaskToBack(true);
Could you do something like is described here:
http://blog.janjonas.net/2010-12-20/android-development-restart-application-programmatically
basically you create an alarm that starts your intent, then you close your app completely.
This is what I always do and works perfectly.
I start the app with the main activity an check if the user is logged in, if he is not logged in launch the login activity like this
void launchLoginActivity(){
/* Move user to LoginActivity, and remove the backstack */
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
It will not allow u to go back
I have a foreground service that keeps a connection open with the server as long as the user is logged into the application. This is so that the connection is kept alive and can receive messages directly from the server even when the application has been sent into the background by the user pressing Home.
The application has a number of Activities, any of which could be the active one when it is sent into the background.
I would like to allow the user to click on the notification to restore the current Activity. I understand how to restore a particular activity, but wondered if there is a way to restore the last Activity that the user was on? Of course I could keep track of the the last one, and then call that from the Notification callback, but thought there might be a way at a task level?
Thanks for any advice you can offer.
What you need is just a simple Activity that does nothing. Here is an example:
public class NotificationActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Now finish, which will drop the user in to the activity that was at the top
// of the task stack
finish();
}
}
Set up your notification to start this activity. Make sure that in the manifest the task affinity of this activity is the same as the task affinity of the other activities in your application (by default it is, if you haven't explicitly set android:taskAffinity).
When the user selects this notification, if your application is running, then the NotificationActivity will be started on top of the topmost activity in your application's task and that task will be brought to the foreground. When the NotificationActivity finishes, it will simply return the user to the topmost activity in your application (ie: wherever the user left it when it went into the background).
This won't work if your application isn't already running. However, you have 2 options to deal with that:
Make sure the notification isn't present in the notification bar when your application is not running.
In the onCreate() method of the NotificationActivity, check if your application is running, and if it isn't running call startActivity() and launch your application. If you do this, be sure to set the flag Intent.FLAG_ACTIVITY_NEW_TASK when starting the application so that the root activity of the task is not NotificationActivity.
Works very well, thanks David! The following class checks if the application is already running and if not, starts it before finishing (as suggested by David in option 2).
public class NotificationActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// If this activity is the root activity of the task, the app is not running
if (isTaskRoot())
{
// Start the app before finishing
Intent startAppIntent = new Intent(getApplicationContext(), MainActivity.class);
startAppIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(startAppIntent);
}
finish();
}
}
There is a simpler solution that does not require the extra activity. See this post for details. Basically, the notification starts the (possibly existing) task the same way it is started when you click the launcher icon while the app ist in the background.
My solution, which emulates the behaviour of the launcher (bringing up the task to the foreground):
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClassName(MyApplication.class.getPackage().getName(), MainActivity.class.getName());
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
This works, no doubts about it but the problem is when you set your intent as ACTION_MAIN. Then you will not be able to set any bundle to the intent. I mean, your primitive data will not be received from the target activity because ACTION_MAIN can not contain any extra data.
Instead of this, you can just set your activities as singleTask and call your intent normally without setting ACTION_MAIN and receive the intent from onNewIntent() method of your target activity.
But be aware if you call, super.onNewIntent(intent); then a second instance of the activity will be created. Just don't call super method.
I combined David Wasser's and Raginmari's solution by doing that approach to the root activity of your app then it will work for both cases when your app was already started or haven't been started.
public class YourRootActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (!isTaskRoot()) // checks if this root activity is at root, if not, we presented it from notification and we are resuming the app from previous open state
{
val extras = intent.extras // do stuffs with extras.
finish();
return;
}
// OtherWise start the app as usual
}
}