Display activity as a popup window - java

I have a service that starts an activity as a dialog/popup window from my app. It works generally ok.
When my app is closed (not in recents), the popup will overlay any underlying app with a transparent surrounding background.
But the issue comes when my app was minimized in the background and I'm using another app, then I click on the service button to display the popup, it brings my app back into the front with the popup over my app (not the previous third-party app).
How can I prevent this behavior and make my activity overly any window regardless of my app's state?
This is the theme I'm using
<style name="PopupTheme" parent="Theme.AppCompat.Dialog">
</style>

If the popup dialog has nothing to do with your app (and you want it to be separate and distinct from your app in case your app is already running), then you want to do the following:
In the manifest, set the taskAffinity for this dialog-themed Activity to an empty string, set the excludeFromRecents flag and the noHistory flag like this:
<activity android:name=".DialogThemedActivity"
android:taskAffinity=""
android:excludeFromRecents="true"
android:noHistory="true"
... />
Declaring the Activity like this ensures that it is not associated with any existing task that your app is currently in. It also ensures that this task will not end up in the list of recent tasks (so that the user doesn't accidentally start the Activity again from the list of recent tasks) and that the task will be deleted as soon as the user navigates away from the dialog-themed Activity.
Now, in your Service, make sure that when you launch the Activity you add FLAG_ACTIVITY_NEW_TASK:
Intent intent = new Intent(this, DialogThemedActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
This is the correct way to do this.

Just found it out. Simply adding this flag to the launching intent
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);

Related

How to prevent Activity from staying in the task stack after "quit", without using android:noHistory?

Currently, I have an Activity, which is used to configure home widget. It is shown during
When user place the home widget on desktop for the 1st time.
Or, when user tapped on the already shown home widget.
This is the Manifest for the Activity.
<activity android:name="com.xxx.widget.NoteListAppWidgetConfigureFragmentActivity"
android:taskAffinity="com.xxx.launcher"
android:windowSoftInputMode="stateAlwaysHidden" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
</intent-filter>
</activity>
We specific android:taskAffinity explicitly, as we do not want this configuration activity, interference with our main app flow. Hence, We want this activity to be launched at separate task stack, by using android:taskAffinity.
When user "quit" the configuration Activity, we would like the "com.xxx.launcher" task to be cleared off completely.
Reason is that, without clearing the task, user can always check the recent task list, re-launch the old NoteListAppWidgetConfigureFragmentActivity again and then overwrite current widget settings with old settings. This is an unwanted behaviour.
Currently, there are 2 ways for user to "quit" the NoteListAppWidgetConfigureFragmentActivity
Pressing a Button control of the activity.
Pressing system back button.
Pressing a Button control
We notice by executing finishAndRemoveTask when the Button control pressed, we can clear off the task.
Pressing system back button
We cannot figure out a way to clear off task stack. We even try the following code, but it does NOT work.
#Override
public void onPause() {
super.onPause();
if (isFinishing()) {
this.finishAndRemoveTask();
}
}
We do not want to use android:noHistory="true", because it causes onActivityResult malfunction. We can no longer perform startActivityForResult in NoteListAppWidgetConfigureFragmentActivity
Reference: https://developer.android.com/guide/topics/manifest/activity-element.html
A value of "true" means that the activity will not leave a historical
trace. It will not remain in the activity stack for the task, so the
user will not be able to return to it. In this case,
onActivityResult() is never called if you start another activity for a
result from this activity.
Do you have an idea, how we can prevent Activity from staying in the task stack after "quit", without using android:noHistory?

is the "MainActivity" special kind of activity, does it differ from any other activity?

Except being the first Activity upon the Start of the Application, is there anything else special about main activity?
From:https://developer.android.com/codelabs/android-training-create-an-activity#0
An app usually consists of multiple screens that are loosely bound to
each other. Each screen is an activity. Typically, one activity in an
app is specified as the "main" activity (MainActivity.java), which is
presented to the user when the app is launched. The main activity can
then start other activities to perform different actions.
From the quote above it seems to me that we have following hierarchy:
but then further is said:
Each time a new activity starts, the previous activity is stopped, but
the system preserves the activity in a stack (the "back stack"). When
a new activity starts, that new activity is pushed onto the back stack
and takes user focus. The back stack follows basic "last in, first
out" stack logic. When the user is done with the current activity and
presses the Back button, that activity is popped from the stack and
destroyed, and the previous activity resumes.
Does this also apply to the "MainActivity"? If the "MainActivity" is destroyed does that cause the App to crash i.e does the lifecycle of the MainActivity in any way differs from the lifecycle of any other activity? Is the MainActivity the last activity that is being stopped when the App is exited?
Why do I need this:
I would like to free some resources when the App is exited (in the onStop() Method (because post Honeycomb it is guaranteed that onStop will be called)), especially ExecutorServices, I've read here that even though App is exited there is no guarantee that an ExecutorService will be stopped and will make JVM continue working/running, even though App is closed/killed and will continue to use system resources.
Main Activity is the entry point for your app when user presses the icon for cold launch. You make any of your Activity a main activity in AndroidManifest.xml file via Intent Filter. Intent Filter tells the system which activity is main.
Although main activity is considered first entry point typically, but keep in mind, Main Activity is not always the first activity to be launched, for example there are various intent filters that can be assigned to your other Activity and that activity can be opened directly following the related action. Please read about the Intent-Filter here.
For example, your app is gallery app, typical first screen would be album list. from where you can view individual photo in PhotoActivity. This PhotoActivity can be opened directly via intent from outside apps to view a certain photo without needing to launch the main activity. (Check out google Photos app)
Regarding ExecutorServices or other services lifecycle, few options here:
implement a ownership machanism, ie the activity that starts the service is responsible for closing the service
You can monitor your app's activity stack and kill the service when your Activity stack is empty.
Leverage Application class lifecycle to monitor things.
Reasonable discussion here https://stackoverflow.com/a/5862048/593709

Up Navigation: From Activity to Fragment: Android Studio

The basic navigation of my app is a tab bar within one activity in which each tab is its own fragment. I am trying to get the back button to work to go back to the last tab it was on. I can get the back button to work/appear if the activities are going to the first tab by using this in the java class of the activity:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
and this in the AndroidManifest.xml:
<activity android:name=".CreateNewPost" android:parentActivityName=".MainActivity"></activity>
This works fine, however when I go to a new activity from a button within the other tabs, if I use this same method it goes to tab1. How do I tell it to go to a specific tab or the last active fragment?
Any suggestions would help!
When you launch a new activity the old one either paused or stopped , as in either OnPause() or OnStop() method has been called. Then when you navigate back to a previous activity it is either started (OnStart()) or resuemd (OnResume()). And sometime the activity is destroyed and created again when navigating back to it using OnDestroy() and OnCreate() respectively.
The most guaranteed way that I can think of is to store the state of the first activity somewhere persistently and when the user navigates back to it check what has been stored and show that fragment.
You can use SharedPreferences to store this kind of data, see the google developer documentation on that here. Or onSaveInstanceState(Bundle savedInstanceState) check out this SO question on saving activity state. Although from the answers it is clear that onSaveInstanceState should not work in your specific case, but you should look at it any way because it is useful in other cases like changing screen orientation for example.

Programmatically Exit Android Application Without finish()

Before you tell me that this question has already been asked, let me tell you that none of those questions have an answer that suits me. I have a main Activity for my app. Before it runs, I have a splash screen Activity. If I call finish(), the program returns to my splash screen. I do not want this. Do not tell me to use finish(). I have heard that it is bad practice to not let Android close the app on its own. I know what I am doing...probably....
I want to be able to completely close the application from the second activity. Does anyone know of a way I can do this?
when you want to close your application, you can call
finishAffinity();
or
if you want close it in background also you should write,
android:excludeFromRecents="true"
in AndroidManifest :
<activity
android:name="com.smart.remote.main.SplashActivity"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="portrait"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Use finish() in your splash screen just before you create your second activity, then use finish() is the second activity: that will not bring back the splash screen.
Executing finish() on the splash activity is one solution, but two alternative methods are:
Start the splash activity with android:noHistory="true" in its manifest entry.
Launch the secondary activity with the Intent flag FLAG_ACTIVITY_CLEAR_TOP.
My preference would be the first, as users are unlikely to want to ever see the splash screen in the history stack (or at all, for that matter, but that's a different discussion).
finishAffinity();
This is simply exit from the app
Calling finish() at any Activity will go through its life cycle to destroy it. For sure destroying the fragment will remove it from the back stack.
So, you have to call finish(); method from your splash activity first, then start the MainActivity using intent as following
finish();
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
Yoi can also solve this problem by overriding the method OnBackPressed with an empty one without calling Super.onBackPressed ();
Even if you don't want it, I'm sorry to tell you that the only way of exiting cleanly is using finish(). If you're having some problems closing Activities in the background, there's another solution for it, check this link.
Basically there's no one-click or all-at-once way of accomplishing this, and don't use System.exit(), it's a bad practice, as you may read here.
Finish is the way to go. You can actually close your SplashScreen activity once it is no longer needed. Ie. after SplashScreen is no longer needed, just call finish on it, after starting your main activity.
Also, its not that finish() will close your application, even after calling it process for your app will still exists, all your static variables will be still valid, of course until android decides to kill your app which can happen long after your finish call.
EDIT: just to be clear, this is not the right way of exiting from an application. Use at your own risk. The OP was asking for A way of exiting the application, even though it was not the correct way.
System.exit(0)
Is this what you're looking for?
I totally agree with you that finish() is somehow not practical but anyways you can use it simply and all will be "kosher" with best practices I suppose.
Here is a short tutorial for you to handle "Exit" from any other activity in your app:
I assume that splash screen is the first activity in your app.
If you also have a main/home screen in your app then finish the splash activity right after the main/home has been called with Intent from your Splash activity with e.g.
startActivity(new Intent(getApplication(), Home.class));
Splash.this.finish();}After doing so, follow the step 2. but instead of overriding the onResume in splash screen override it in the Home/Main screen.
2. If your user needs access to the splash screen later, do not finish() your splash screen but override its onResume method as follows:
#Override
protected void onResume() {
super.onResume();
try {
Intent i = getIntent();
Boolean isExit = i.getBooleanExtra("isExitAction",false);
if(isExit){
this.finish();
}
}
catch (Exception e){}
}
3. In the activity from which you want to close the application, use the following code to exit where it suits you the most. Do not forget to substitute for Home.class depending which is your first unfinished activity.
Intent i = new Intent(this, Home.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra("isExitAction", true);
startActivity(i);
WHAT IT DOES: If you press a button from your 5th activity which fires the code in the 3rd step it finishes all previous activities 4,3,2 and "redirects" you to activity 1, which is your Home (or Splash).
After the redirection, the onResume() is called, and it finishes the last remaining activity. The application reaches this.finish() only if isExitAction is true

Android - Activity behaviour?

I have a small Android application with a TabScreen as my main screen. I have a small problem where my application currently loses focus on the last Activity the user was on.
This is the scenario:
User launches application
Application shows login screen
User enters login details and goes to tab screen
User leaves application via home key
User presses application icon to return to app and the login screen displays again
I want the application to return to the last known displayed Activity in this case.
What I do at the minute is launch the login screen as the Main/Launcher Actvitiy, then when correct credentials are entered launch the tab screen activity and finish the Login activity.
Is there a launch mode or something I should be using to achieve this?
EDIT: More info
The Tab screen is launched simply like this:
Intent intentTabActivity = new Intent(getApplicationContext(), TabScreenActivity.class);
startActivity(intentTabActivity);
Leaving the application through the home button.
I intend to persist the login state and bypass the login but on smaller applications I have created the application returns to the last displayed activity automatically and does not return to the initial Launcher screen every time and I was wondering why this is not the same behavior in this application.
Also as per my other question HERE the behavior seems to be different for debug and signed releases.
This has always been tested on real devices.
This is the correct behavior. Essentially what happens is as soon as the activity goes in the background it is on the mercy of Android DVM. If DVM feels it needs space it will essentially go ahead and kill your application. So once you try to start the application from the icon it actually restarts it from scratch.
However to solve your problem, you should have a checkbox like "Automatically login" or "Remember password" on the login screen and when the user checks it everytime the app opens it should automatically log you in and take to the next screen. This behavior needs to be implemented by you using some sort of persistent storage.
Might be because you are using your onPause() so that your tabs does some action when the tab is passed.
So eventually when the home key is pressed onPause() will be called which might lead you to this problem. Maybe you will have to check your onPause() for this case.
on home button only onStop is called, are you doing finish of activity on onStop? If not it preserves what was the activity which is top of the stack.

Categories

Resources