MyApplication.java did not run at the second time app started? - android

I have 1 application custom class MyApplication.java and 1 activity MainActivity.java.
At the first time when I start app, class MyApplication.java run correctly. Then I exit app by finish the activity
MainActivity.this.finish();
Then I click the app icon in screen to start it again. But this time, MyApplication.java do not run. It means that I can't exit app by finishing all activities?
I can't explain why.
P/s: Here is my code
MyApplication.java
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
}
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate: ");
}
#Override
public void onBackPressed() {
this.finish();
}

In the Application class, the onCreate() method is called only if the process was ended when you exited the application. Usually the process is stopped when the system needs memory or if you exit the app using the back button instead of the home button. However, you cannot rely on it being terminated.
If you really want to kill your process when exiting the application, you can call System.exit(0); when the user presses the back key on your first activity.
#Override
public void onBackPressed() {
MainActivity.this.finish();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
getParent().finish();
}
Note: This is definitely not recommended since it means fighting against the way the Android OS works and might cause problems.

it's because this line
MainActivity.this.finish();
will only close the activity but the application is still running as you don't have the privilege to close the app completely and as a prove of that after you click the button which runs MainActivity.this.finish();
try to see the background apps on your device you will see your app Finally the application class runs once the app starts and get along till the app is closed from the device apps stack manually.

Related

Splash Screen appear on resume despite using - finish() - before starting home Activity

In Android, I want to show Splash Screen only when the app is starting fresh and not when it is working on the background and resuming by the user.
So after reading here in Stackoverflow and over the web, I have added finish() before starting my home activity:
#Override
protected void onPostExecute(String s) {
finish();
Intent appStarterIntent = new Intent(StarterActivity.this, HomeActivity.class);
StarterActivity.this.startActivity(appStarterIntent);
}
But Still when I (returning) opening the app from the background I see the Splash screen...
How can I make the plash screen apprear only on fresh start of the app?
Save value 'isFreshStart' into SharedPreferences and start app only if there is no saved value. Remove this flag in onTerminate() method of Application class.
The point is, that Application instance gets destroyed when app is closed coimpletely, so you will know if it is a fresh start.

Exception in one activity doesn't stop other activities

My OnCreate method (in MainActivity):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, DetailsActivity.class);
startActivity(intent);
// This will throw exception
Integer.parseInt("Güzelim");
}
});
}
When a button is clicked, the app crashes; showing the dialog "Unfortunately app has stopped". When I click OK button, the DetailsActivity screen is displayed. Why does this happen? I would like the entire app to crash.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// This will throw exception
Integer.parseInt("Güzelim");
Intent intent = new Intent(MainActivity.this, DetailsActivity.class);
startActivity(intent);
}
});
}
This should crash your whole app.
App is crashing because you are trying to convert String into Integer which is throwing NumberFormatException.
This answer to a similar question might help
For example, a user might be browsing the web, click a youtube link
launching the youtube app, then click a share button to launch their
favorite social networking app and post the video link. This is all
part of the same task; if the user presses back several times they'll
come back to the page in the browser that they started from.
Once you start up the social networking app, the system might decide
that it's running low on memory and it's going to kill off the
browser's process to free up more. (After all, it's not in front and
the user won't notice.) When the user presses the back button to
return to the browser Activity it gets restarted and reconstructs the
last state where the user left it. At worst the user experiences a
short delay while things reinitialize.
But this same sequence of events restoring a previous Activity state
can happen even within the same app in the same process. In your
scenario, Activity B closed as the result of the crash. So the system
does exactly what it always does - it returns to the previous
Activity: Activity A. But Activity A's process isn't still around (it
crashed!) so the system restarts it and it can reconstruct its
previous state.
Crux of discussion: As a philosophy Android tries to give a feel that all the apps are running all the time, as part of this philosophy it tries to restore from neatest point possible.

Android: BackStack misbehaves, if application was started from another app

I have an application, which starts with a SplashScreenActivity. Afterwards, a LoginActivity is shown, or if the user is already logged in, a MainActivity is shown. If the application is already running, SplashScreenActivity is dismissed with the following
//SplashScreenActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Adding this check for following cases
if (!isTaskRoot())
{
String intentAction = getIntent().getAction();
if (getIntent().hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
finish();
return;
}
if(getIntent().getCategories().contains(GCMIntentService.INTENT_CATEGORY_GH_NOTIFICATION)){
finish();
return;
}
}
Problem occurs
If I start the application from another activity like PlayStore, it resumes at the right activity if already running. This is the Intent I'm using to reproduce within a second app
//AnotherApplication.apk
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("my.package.name");
startActivity(launchIntent);
However, this action is somehow breaking the Backstack. Instead of closing the application on backpress in the MainActivity, it restarts the application.
//MainActivity.class
#Override
public void onBackPressed() {
if (getNavDrawerMain().isDrawerOpen()) {
getNavDrawerMain().closeDrawer();
} else {
closeApp();
}
}
protected void closeApp() {
if (doubleBackToExitPressedOnce) {
//super.onBackPressed(); //i tried both, but behaviour is the same
finish();
return;
}
this.doubleBackToExitPressedOnce = true;
new Handler().postDelayed(new Runnable() {
#Override
public void run()
doubleBackToExitPressedOnce = false;
}
}, 500);
}
I used breakpoints and found out that MainActivity:onDestroy() get called, but instead of resuming application to the HomeScreen, it always restarts and I don't know why.
I tried the following:
- Used different launchmodes like singleTask and singleInstance, but it didn't make any difference. onNewIntent is called, but if i call finish, HomeActivity restarts
- as commeted below, i tried moveTaskToBack(true), but Activity is restaring too (and we really want to close the app instead of moving it to the BackStack)
Try with moveTaskToBack(true); instead of finish(); to close the app. It will then go to OnRestart() and then OnStart()->OnResume() (and won't go to OnCreate).
And make sure you don't have the "Don't keep activities" marked at Developer Options in your Android Settings (destroy every activity as soon as the user leaves it).
Trying adding this flag to your intent starting your app: RESET_TASK_IF_NEEDED, URL=http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
What it does:
If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task.
You may also use:
http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_REORDER_TO_FRONT
What it does:
If set in an Intent passed to Context.startActivity(), this flag will cause the launched activity to be brought to the front of its task's history stack if it is already running.
Which one you use depend on the desired end result.
If you can't control who starts you you need to set or launch mode to single task or single instance.
Described here:
http://inthecheesefactory.com/blog/understand-android-activity-launchmode/en
The interesting part:
singleTask
This mode is quite different from standard and singleTop. An Activity with singleTask launchMode is allowed to have only one instance in the system (a.k.a. Singleton). If there is an existed Activity instance in the system, the whole Task hold the instance would be moved to top while Intent would be delivered through onNewIntent() method. Otherwise, new Activity would be created and placed in the proper Task.

Application restart and activity hiding

I have application with two activities: SplashActivity and MainActivity. SplashActivity is the launch activity, it start for few seconds, close and launch MainActivity. MainActivity contains all application logic.
When user minimize application by Home button, then doesn't using application some time and maximize it again, data in my application is expired and I need to restart application. I make it with onStart in MainActivity:
#Override
public void onStart() {
super.onStart();
if (dataIsExpired()) {
finish();
Intent intent = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
}
It working well, but before SplashActivity launched I see MainActivity with old data for few moments. Is there way to restart without previous activity showing?
I don't need to clear it manually, I just need to restart whole app.
You can call finish() your activity in onPause() or onStop() of MainActivity so that it will be removed when minimising the app and will launch fresh.

Android Lifecycle Behavior

Having an issue with lifecycle events and need some help if possible. I have read the other posts with similar issue and error however, still stuck .... Explaination may be a little long.
I have an App that requires the user to login when any 'backgrounding' event occurs (App switch, screen sleep, phone call and so on). Previously I was using the method of 'getRunningTasks' to check is my app is no longer top of stack to trigger the login flags and activity. I am now using a suggested timer method via onPause / onResume in my Application class which works great.
Now the issue at hand, and the questions:
App into background by Device Home button.
App is in the background, all my checks and flags are properly set. When I relaunch the app (Icon press), it loads the last activity, then from the onResume function - performs a startIntent for the login activity - based on the flag set in the timer event. The user logs in, and returns to the activity they were on (Stock List). All Good.
App into background by App Switch
timer event fires and all login flags are properly done as previous example.
--> Click 'device Home'button, then App icon --- App loads properly and loads the Login Activity, users logs in -- all good.
Problem area
2b. App into background by App Switch --> Example, Android pull down menu, jump to device settings - then return to app via the device back button
timer event fires and all login flags are properly done as previous example.
--> Click device 'return/back' button to return directly to the app.
User goes to Login screen, clicks 'Login' button - gets app crash due to :
java.lang.RuntimeException: Performing pause of activity that is not resumed
followed by
java.lang.RuntimeException: Performing stop of activity that is not resumed
My own system Logs in the lifecycle events all seem to fire in the appropriate order.
Basic overview from app re-launch:
-> DashBoard onResume
-> check for login flag and call intent for Login activity
Dashboard onPause
Login onResume
Login - user login hit button
Login onPause --- activity finish
Return to Dashboard onResume
-> Load details
The only diff is in the last senario ... the DashBoard onPause happens after the Login onResume. Not sure if this is the problem, or an Async delay issue with the lifecycle events.
My Manifest includes:
android:minSdkVersion="10" --- Maintaining old API due to clients with older devices
android:targetSdkVersion="19"
Any help or suggestions on what may be out of whack here? or how to avoid this error.
Thanks
--
Some code:
From BaseActivity.java
~~~~~~
private AppPreferences mAppPrefs;
protected MyApplication mMyApp;
#Override
protected void onPause() {
super.onPause();
//start timer
mMyApp.startActivityTransitionTimer();
}
#Override
protected void onResume() {
super.onResume();
//update current Activity Name
mMyApp.setCurrentActivity(this);
mMyApp.stopActivityTransitionTimer();
mAppPrefs = new AppPreferences(getApplicationContext());
if (mAppPrefs.getAppDestroyed() == true
|| mAppPrefs.getExitType() == AppPreferences.EXITTYPE_FULLEXIT) {
// we want to fully exit/close the app
this.finish();
} else {
if (mAppPrefs.getForceLoginState() == true) {
//~~~~ process login events
Intent intent = new Intent(this, LoginScreen.class);
startActivity(intent);
return;
}
}
}
DashboardActivity extends BaseActivity
{
#Override
protected void onPause() {
super.onPause();
if (((MyApplication)this.getApplication()).getProcessingLogout()){
// if we are already processing a login, do not continue here
return;
}
// ~~~ activity specific onPause event such as unregisterReceivers
((MyApplication)this.getApplication()).startActivityTransitionTimer();
}
#Override
protected void onResume() {
super.onResume();
if (((MyApplication)this.getApplication()).getProcessingLogout()){
// if we are already processing a login, do not continue here
return;
}
// ~~~ activity specific onResume events such as registerReceivers
}
}

Categories

Resources