I got a service that start a new activity, while screen is off.
I want the activity to stay on paused mode, and not get to the stopped mode.
Is there a way to achieve this?
No. You don't have control over the Activity lifecycle. Any processes that you need to run while the screen is off must be executed in a Service. You must rebuild the application state whenever the screen is turned back on. Always assume the Activity can be wiped from memory at any time.
You can't do that. it will be killed anyway.
but you can use a Service to receive Broadcast of Intent.ACTION_SCREEN_ON and relaunch activity from Service.
to restart your Activity from service check here
There is no way to achieve this. Your app is tied to the Activity lifecycle, and has to break down/restore the Activities to work with the lifecycle.
You can't override the onDestroy() method, and each OS version handles how an application is "killed" differently.
The Android developer documentation makes reference to an application being in a “killable” state. While Android tries to keep the process of an application resident even after it has exited (i.e. after onDestroy), it does need to be able to kill these processes in low-resource situations to reclaim memory. The states in which an application is killable differ per OS version. On all versions of Android, applications that have returned from onStop or onDestroy are silently killable. On versions of Android prior to Honeycomb, applications that had returned from onPause were also killable. Being killable simple means that Android reserves the right to terminate your application’s process at any time without running even another instruction of your app’s code. In other words, if you have any state that must be recoverable (such as a player’s game progress, items, awards, etc) you must save those to persistent storage no later than the last callback before entering a killable state.
In addition, while applications can run native threads even when they are in a killable
state and even post-onDestroy, this is to be avoided, since the process kill will also kill those threads. This could cause all manner of corruption and shutdown issues.
Source
I do not exactly now what you mean with paused mode or stopped mode. If you mean that the cpu keep wake up take a look at this.
With partial_wake_look you can have a long running AsyncTask for example also when the screen is of. Dont't forget to release the wakelook.
Why do you need to do this? Maybe best solution is to run it as a service as suggested by #DeeV. However, depending of what you need to do, this could help:
Ask Android to notify you when screen is turned on (and off if required). So your activity can be resumed and started immediately and you can perform any action.
To do that:
Create a class which extends Application
Register it in your Manifest:
In public void onCreate() {..., add this:
IntentFilter ioff = new IntentFilter(Intent.ACTION_SCREEN_OFF);
IntentFilter ion = new IntentFilter(Intent.ACTION_SCREEN_ON);
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
//TODO
} else {
//TODO
}
}
};
context.registerReceiver(broadcastReceiver, ioff);
context.registerReceiver(broadcastReceiver, ion);
in public void onTerminate() {..., add this:
if (broadcastReceiver != null) {
context.unregisterReceiver(broadcastReceiver);
}
Lame hack would be to call onPause() method inside onStop() of activity
Related
I am confused right now , about service concept of running and stopping:
what i want to do:
Start Location service at the very start of application.
Keep getting location updates and store them to shared preference
Stop the service in onDestroy of Application scope!
So far i have searched and studied we can only do following things with service(correct me if i'm wrong):
Stop the service automatically by binding it to related activities/fragments/views , when all of them destroyed service unbind itself automatically so we can call stopself method in unbind
return START_NOT_STICKY in onStartCommand to tell OS , don't recreate it , and create intent local service , after completion of some work it will destroy itself.
Stopping the service manually , by declaring it's intent in some kind of static scope and stopping the service in on onActivityDestroyed of Application class [I am not sure what will happen? , maybe service will destroy each time any activity will be destroyed ? or it will be destroyed only when overall application get's destroyed?]
Either way , i am bit confused and beat , been trying to adjust my Location service with given details for 2 days
If you start your Service using START_NOT_STICKY, then your app will kill your service once your entire application is closed from background i.e. you cleaned your app from home screen.
Here START_NOT_STICKY states that you need not recreate service in case it is been killed.
If this is not the case then you have to manually kill it by your self.
Like
Intent lintent = new Intent(context, LocationService.class);
context.stopService(lintent);
You can use this code at point where your application kills.
That's it. You are good to go with this.
First of all, launch the "LocationService" on your app start:
public class MyApp extends Application {
private static final String TAG = "MyApp";
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "App started up");
startService(new Intent(this, MyLocationService.class));
}
}
Second :
As you said, the Service should better run with the "START_NOT_STICKY" flag
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
Thrid:
Once the system kills your app, the Service will automatically be killed, so no problems at all.
There is no onDestroy() method on the Application object, the only similar event is onTerminated() and it is not being launched on production devices.
onTerminate
Added in API level 1 void onTerminate () This method is for use in
emulated process environments. It will never be called on a production
Android device, where processes are removed by simply killing them; no
user code (including this callback) is executed when doing so.
More information:
https://developer.android.com/reference/android/app/Application.html#onTerminate()
Btw, If you want the MyLocationService to send updates of the location to your app (when it is open), you should consider to use Otto or EventBus (I recommend you this last one because of the simplicity to use it). You can even configure the #Suscriber to receive updates of old retrieved locations if you want.
I will try to explain in a easiest way :)
There are two type of service
IntentService and Service
IntentService when started will kill itself once it treated the content of it onHandleIntent method
as for Service well this one will not end until you give it the command to do so even if your start it using the context of an activity. It will also stop when the application is stopped in an extreme case (by system (Settings/application/YourApp/stop app OR an app crash)
Easiest way is First of all start IntentService with AlarmManager at some repeating time (10 mintutes), then in onHandleIntent() get Location and store into preference.
No Need bind to your activity, the IntentService automatically stops itself after saved in preferences.
Yes you can stop the service in onDestroy() of the activity:
#Override
public void onDestroy(){
Log.v("SERVICE","Service killed");
service.stop();
super.onDestroy();
}
I want to perform some operation when my application gets killed.
Which method can be used for this? I am working on Android 5.0.
The key of this question is that:
you must understand your application whether can receive any
additional callbacks when your application being killed in any kinds of situation.
The following answer is answered by Devunwired in this question:
Android app doens't call "onDestroy()" when killed (ICS)
This will help you more to understand this.
Your application will not receive any additional callbacks if the process it terminated by external means (i.e. killed for memory reasons or the user Force Stops the application). You will have to make do with the callbacks you received when you app went into the background for your application cleanup.
finish() is only called by the system when the user presses the BACK button from your Activity, although it is often called directly by applications to leave an Activity and return to the previous one. This is not technically a lifecycle callback.
onDestroy() only gets called on an Activity as a result of a call to finish(), so mainly only when the user hits the BACK button. When the user hits the HOME button, the foreground Activity only goes through onPause() and onStop().
This means that Android doesn't provide much feedback to an Activity to differentiate a user going Home versus moving to another Activity (from your app or any other); the Activity itself simply knows it's no longer in the foreground. An Android application is more a loose collection of Activities than it is a tightly integrated singular concept (like you may be used to on other platforms) so there are no real system callbacks to know when your application as a whole has been brought forward or moved backward.
Ultimately, I would urge you to reconsider your application architecture if it relies on the knowledge of whether ANY Activity in your application is in the foreground, but depending on your needs, there may be other ways more friendly to the framework to accomplish this. One option is to implement a bound Service inside of your application that every Activity binds to while active (i.e. between onStart() and onStop()). What this provides you is the ability to leverage the fact that a bound Service only lives as long as clients are bound to it, so you can monitor the onCreate() and onDestroy() methods of the Service to know when the current foreground task is not part of your application.
You might also find this article written by Dianne Hackborn to be interesting covering in more detail the Android architecture and how Google thinks it ought to be used.
You have to use Service Class for it like -
public class Myservice extends Service { #Nullable #Override public IBinder onBind(Intent intent) { return null; }
#Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(Constants.TAG, "Service Started"); return START_NOT_STICKY; }
#Override public void onDestroy() { super.onDestroy(); Log.d(Constants.TAG, "Service Destroyed"); }
#Override public void onTaskRemoved(Intent rootIntent) { Log.e(Constants.TAG, "END"); //Perfome here want you want to do when app gets kill stopSelf(); } }
In Manifest -
<service android:name="Myservice"
android:stopWithTask="false" />
In Oncreate of your launcher activity or Application Class to start service -
startService(new Intent(getBaseContext(), OnClearFromRecentService.class));
You can use your activity's onDestroy() method.
I'm using a running service to detect whether network is available or not. When it is not available, it calls an activity to start that displays a blank screen with "no network available" on it. When the network is back, it sends a broadcast to finish this activity.
The only problem is that this activity may start at any time (as a popup), even when using other apps. I want it to start (or be visible) only if the network is out and my app is in the foreground. Any help?
One option would be to have your foreground activity register for the broadcast, and then display the relevant notification from within the activity.
Alternatively you could start your service when your foreground activity starts/resumes (i.e, onResume), and stop it when your activity leaves the foreground.
You can use START_STICKY in your service to ensure it stays around until you stop it, like so:
#Override
public int onStartCommand(Intent intent, int flags, int startId){
//On start work here
return START_STICKY;
}
and then stop the service using stopService when your activity leaves the foreground (i.e onPause).
If you need the former behaviour across multiple activities you can register broadcast receivers programmatically:
BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(MY_ACTION.equals(intent.getAction()))
{
//show appropriate dialog
}
}
};
IntentFilter myIntentFilter = new IntentFilter();
myIntentFilter.addAction(MY_ACTION);
registerReceiver(myBroadcastReceiver,myIntentFilter);
You can unregister like so:
unregisterReceiver(myBroadcastReceiver);
You could extend Activity and make your own custom subclass that reuses similar code to register and unregister whilst entering/leaving the foreground. Or you can extract this into utility methods/classes and call from the appropriate places.
I think you need Shared Preference to do this. store one Boolean value on finish you activity (you can use onpause() or onStop()) and for showing popup check the value and do what you want
for understnding to use sharePreference see this and developer.android.com
Try the following:
Intent intent = new Intent(this, YourActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
This worked in the context of my own app already running, I'm not sure if it will start your app if it is not already running in the background
EDIT: Not sure if I understand your question entirely. If you only want this activity to come to the foreground while your app is in the foreground, get rid of the addFlags line, also you can do some boolean stuff to check if your app is in the foreground like so, this way your code won't even run if the app isn't in the foreground.
EDIT: There are a few ways to check if your app is in the foreground, the link I posted above has one such solution, another one is to create a static boolean isForeground variable: in the onResume() methods of your app set isForeground = true and in onPuase() set isForeground = false. This isn't the best practice, using ActivityManager is better, but for purposes of testing this should be ok.
Then have something like the following:
if(isForeground){
//Start your activity
}
This should be quick to write, if this is the behavior you want, I would recommend replacing the isForeground static variable with the test for foreground provided by ActivityManager in the link I posted.
I have an app that has an Activity, which is used as the regular GUI, and a Service. My activity has two buttons. One button to stop the process and one to kill the process. I use these to methods, respectively, to start and stop my process:
Intent i = null;
Button start;
Button stop;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
i = new Intent(this, Service.class);
start = (Button) findViewbyId(R.id.start_button);
stop = (Button) findViewById(R.id.stop_button);
start.setOnClickListener(new OnClickListener(){
public void onClick(){
startService(i);
}
}
stop.setOnClickListener(new OnClickListener(){
public void onClick(){
stopService(i);
}
}
}
This Service is not bound to the actvivty or app. I have the service configured in the Manifest as so:
<service
android:name="com.example.mypackage.Service"
android:process=":remote">
<intent-filter>
<action
android:name="com.example.mypackage.Service" />
</intent-filter>
</service>
When I start the Service it runs on it's own independent on anything else. Meaning, when I start the service and onDestroy() the app, the service is still running. I can see it is still running because through adb, I run the ps command and it says it is.
The problem is when I call stopService(intent). When I call stopService(intent) from the activity side, it will run the lines of code set in the onDestroy() of the service, but when I run ps through adb, it says that it's still running.
I want to be able to COMPLETELY destroy the service. I'm not sure how services work, so please, don't hesitate to talk remedial. I'm not sure if it has to do with what I'm doing within the service or not. Thanks!
EDIT:
When I start the service, I use the onStartCommand() and run some code there which it does. I also return START_STICKY from onStartCommand(). I also tried returning START_NOT_STICKY and the service is still running after I call startService(intent).
If you want kill service process forcefully, you can use following code:
Process.killProcess(Process.myPid());
Services are stopped after stopService is called. After stop, they are inactive, but cached.
By android documentation they become an empty process:
A process that doesn't hold any active application components. The only reason to keep this kind of process alive is for caching purposes, to improve startup time the next time a component needs to run in it. The system often kills these processes in order to balance overall system resources between process caches and the underlying kernel caches.
Service will remain in cache until it will be called by you app again or sytem cache will not have room for it to keep. RS command does not know difference between active and cache dprocess and allways shows all awailible processes. This behaviour will maintain if you remove :remote(note that separate process will not be created)
I think you could set android:exported="false" in your manifest so that other apps cannot access the service thereby starting the service. I may need to see the full implementation of your code to fully determine the cause of it. I did the same thing and it is working perfectly well.
I have an SMS broadcast receiver in my application with a static boolean value to make the receiver active or not.
public class SmsListener extends BroadcastReceiver {
public static boolean activated = false;
#Override
public void onReceive(Context context, Intent intent)
if (activated){ //do something
}
...
}
}
I have then a widget to activate or not the sms receiver (through this static value). Everything works well but I just noticed that, if the phone memory gets low, the sms listener loses its state and the application doesn't work as expected.
I guess it is related to android lifecycle. I have no service in background and the system kills the process. Should the approach I used be avoided? Should I always start a service only to avoid android process kill?
Thanks
Tobia Loschiavo
The only reliable way I have found to have globals is to put them in a service. The Android way is to use onSaveInstanceState and then recover state in all the various methods that may or may not be called with that state. Even that is not completely reliable, so you can also write state to preferences when in onPause and read them in onResume.
Note also that depending on your manifest anything can kill your activity, such as opening the keyboard or rotating the phone, not just low memory.