Android SDK says that remote service runs in another process with the application. I thought it mean if the app stops/ is terminated..., then remote service still remains running. But it does not.
For example I have this remote service:
import java.util.Timer;
import java.util.TimerTask;
import android.app.Service;
import android.os.IBinder;
import android.util.Log;
public class WatchDogService extends Service {
private Timer timer = new Timer();
#Override
public void onCreate() {
Log.i(WatchDogService.class.getName(), "WatchDog start");
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
Log.i(WatchDogService.class.getName(), "WatchDog boo boo!!! ^^");
}
}, 0, 5000);
}
#Override
public void onDestroy() {
Log.i(WatchDogService.class.getName(), "WatchDog stop");
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(WatchDogService.class.getName(), "WatchDog has just been called...");
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
}
AndroidManifest.xml:
<service
android:name="WatchDogService"
android:process=":remote" >
<intent-filter>
<action android:name="WatchDogService" />
</intent-filter>
</service>
In another activity I call it as:
startService(new Intent("WatchDogService"));
The service starts ok. But if I go to system apps manager, then stop the app, the service is terminated too.
I want to keep the service running even if the app is terminated. How can I do that?
I want to keep the service running even if the app is terminated. How can I do that?
You don't. If the user terminates your app, your app is terminated, period. The user is in control of their Android device, not you.
Please respect the user's wishes, and try not to build apps that the user will want to force-stop, task-kill, or otherwise get rid of.
Instead of a service you may create a separate application and invoke it or
Instead of a service you may create a separate background application using AIDL described in this link:
http://developer.android.com/guide/components/aidl.html
Note that the AIDL should register a notification with an intent to start the original app when it is done and ask the user if he wishes to act on it.
I expected that "service" means service, not "application". I mean, I want something like "Service manager". But I forgot that the Applications settings in Android is for end-users, not coder.
So far, I got my answer.
Related
I have made an app in which a service runs in the background. But if the android system requires resources, it will stop the service. However I may still require my service to run.
Is it a bad practice to restart the service (if condition relevant to my app still holds true) in the onDestroy method of my service?
How can I make sure my service runs indefinitely (if condition relevant to my app still holds true)? Or atleast on high priority?
Probably the best you can do is use the START_STICKY flag, which tells Android to attempt to restart the service if it has stopped. Beyond that ensure that it consumes as few resources as possible, so that it is less likely to be destroyed.
Android prioritizes the UI over everything. Then processes that are related to the UI. Then processes that are consuming the least amount of resources. A Service runs in the background, so unless it has resources that are also in use on the UI or connected to the UI in some way, it should be a lower priority.
Also you cannot tell Android how to prioritize your Service (everyone would make theirs the "highest priority" right?). So it goes by how well you minimize the impact on overall resources - why kill 3 Services when it could kill 1 and regain all the resources it needs?
To help understand how to manage memory better: http://developer.android.com/training/articles/memory.html
set it START_STICKY. It Causes after killing service the service will restart again. it is my code :
android manifest :
<application
....
<service android:name=".UpdateService" />
</application>
service class :
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class UpdateService extends Service {
BroadcastReceiver mReceiver;
#Override
public void onCreate() {
super.onCreate();
// register receiver that handles screen on and screen off logic
IntentFilter filter = new IntentFilter(Intent.....);
filter.addAction(Intent....);
mReceiver = new MyReceiver();
registerReceiver(mReceiver, filter);
}
#Override
public void onDestroy() {
unregisterReceiver(mReceiver);
Log.i("onDestroy Reciever", "Called");
super.onDestroy();
}
#Override
public void onStart(Intent intent, int startId) {
Log.i("log", "action Called");
}
}
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return Service.START_STICKY;
}
}
receiver class :
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Log", "recevid");
}
}
in StartupActivity :
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Context context = getApplicationContext();
Intent service = new Intent(context, UpdateService.class);
context.startService(service);
}
I know this is a basic question, I am new to android service. I have done research on Google and StackOverflow. There are many question in stackoverflow related to or similar to my topic, But I couldn't able to get the proper answer and I am being diverted to different topics.
This is the simple test code I am running.
public class Service extends android.app.Service {
private Handler mHandler;
private void ping() {
try {
Log.e("Tag", "Success");
Toast.makeText(getApplicationContext(), "Service Ping", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
Log.e("Error", "In onStartCommand");
e.printStackTrace();
}
scheduleNext();
}
private void scheduleNext() {
mHandler.postDelayed(new Runnable() {
public void run() { ping(); }
}, 3000);
}
public int onStartCommand(Intent intent, int x, int y) {
mHandler = new android.os.Handler();
ping();
return START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
In this a Toast message pops up and Log message printed for every 3 seconds, It works even when the app is minimized. But when i completely quit the app, There is no Toast or Log printed. In this SO ANSWER in clearly says why Toast message cannot called without the UI. And I cannot print the LOG as the process is being killed.
Basically, I want the service to run in background for every 5 min and need to get the data from online. How should I implement the service? and any example code or tutorials are appreciated?
When you start a Service, by default it runs in the same process as whatever component started it. When the process that component is running in quits, so too does the Service. In order to start a Service in its own process, you need to do the following in the manifest:
<service
android:name=".Service"
android:enabled="true"
android:exported="false"
android:process=":separate_service_process"
android:stopWithTask="false" >
</service>
Putting a colon in front of the label for the android:process attribute tells the system to start the service in a separate process, and the android:stopWithTask attribute will tell the system to keep the service alive even when the component that started it stops. See http://developer.android.com/guide/topics/manifest/service-element.html for more information on the manifest settings (the stopWithTask attribute is part of the ServiceInfo class).
Now start your service using startService(Intent) and you should be all set. Good luck!
PS--I'd recommend renaming your Service class to something unique to avoid confusion with the base Service class.
i created a simple services, its job is to handle the incoming call. I created a services like below
public class CalldetectorService extends Service {
private CallHelper callHelper;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
int res = super.onStartCommand(intent, flags, startId);
callHelper = new CallHelper(this);
return res;
}
#Override
public void onDestroy() {
super.onDestroy();
//callHelper.stop();
}
}
Inside the helper, i m handling the call. This service is not running in background continuously. after some time, its getting halted. It works pretty well when i open app & move to background for some time, later on it wont work.
How to make my service to work in background always and catch the incoming calls
If you don't want the service to be killed by the OS: A started service can use the startForeground(int, Notification) API to put the service in a foreground state, where the system considers it to be something the user is actively aware of and thus not a candidate for killing when low on memory. (It is still theoretically possible for the service to be killed under extreme memory pressure from the current foreground application, but in practice this should not be a concern.)
In your case, 'catching' incoming calls is best achieved with a Broadcast Receiver, registered in the manifest for intent: <action android:name="android.intent.action.PHONE_STATE" />
the answer is you dont, The OS can kill a service at anytime it needs to. you can return START_STICKY which will flag you service to be restarted when it can but there is no way to make a service run forever
i am trying to write a sample Android service code to test whether , the service stop itself or not after returning START_NOT_STICKY to onStartCommand. But i whenever , i closed my app , the service stop itself , whereas according to the rule START_NOT_STICKY will not allow to stop the service automatically.
MyCode :
ServiceDemo.java
package com.example.servicedemo;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent in = new Intent(this,TrackService.class);
startService(in);
}}
TrackService.java
package com.example.servicedemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class TrackService extends Service
{
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags , int startId)
{
return START_NOT_STICKY;
}
#Override
public boolean onUnbind(Intent intent)
{
return super.onUnbind(intent);
}}
this my above code , whenever i close my app , the app service stops itself , please help me out , how can i restrict my service to stop or restart itself.
close my app means , pressing home and from slide menu swipe up app to close completely
That means that you are terminating your background process. At that point, your service is gone, and since you are returning START_NOT_STICKY, it will not automatically restart.
In other words, what is happening is perfectly normal.
Close with swipe won't kill this code.
It's a service that runs in the foreground so android treats it as if it is on the screen. It runs in a seperate process so the main process can be killed. It shows a custom notification to the user when its running so its completely ligit and it is written.
Note Eclipse ADK Users only put the service in a different process when your done debugging it.
manifest
<service
android:name="com.gosylvester.bestrides.ServiceLocationRecorder"
android:process=":myService" >
</service>
</application>
MyService class
private boolean isRecording = false;
public int onStartCommand(Intent intent, int flags, int startId) {
boolean isTrackerMarker = SettingMarker.TRACKER_MARKER_DEFAULT;
if (intent != null) {
isRecording = intent.getBooleanExtra("isrecording", isRecording);
startRecording(isRecording);
}
//if isRecording keep the service running else let os know service can be killed
if (isRecording) {
startForeground(R.id.action_record, getMyCustomNotification());
return Service.START_STICKY;
} else {
stopForeground(true);
return Service.START_NOT_STICKY;
}
}
The service does get re-created, just not re-started.
If you override the onCreate and do a Log.d or a Toast, you will see that onCreate gets called after your activity and app is destroyed and even the service onDestroy is called.
So the trick to keep it running after it is re-created is to put your code on the onCreate method and use the onStartCommand just to return START_STICKY.
Note: onCreate is called before onStartCommand, so your code will run both when it is started by startService and from the system self re-creation.
I'm developing an Air (Flex) Mobile application for Android, which uses Air Native Extension (ANE) to take advantage of some platform functions that otherwise could not be used (at least to my knowledge). One of the platform functions that I want to use are services, specifically services that run as Foreground processes (using the startForeground() method).
When I invoke the service from my ANE everything works like a charm, the service is started correctly and it does what it needs to do but the problem is that Android seems to be trying to start it independently from my code, which, of course, results in errors that appear in the LogCat.
When I launch the application in debug mode in Flash Builder, and I use it for a while checking that the service works perfectly and no errors are thrown, after I close it from the Flash Builder (not from Eclipse ADT, which I also could) a couple of seconds later, the following errors appear:
01-16 10:56:06.953: E/AndroidRuntime(9757): java.lang.RuntimeException: Unable to start service com.mycompany.myextension.services.MyService#41594a50 with Intent { cmp=air.QOE.debug/com.mycompany.myextension.services.MyService }: java.lang.NullPointerException
01-16 10:56:06.953: E/AndroidRuntime(9757): at com.mycompany.myextension.services.MyService.onStartCommand(MyService.java:37)
It seems to be clear that Android tries to start the service but since its design to work inside the ANE -the extension is initialized but its context was already disposed- it crashes because it cannot reach the variables that are initialized within the context, therefore, ending in a crash or error the first time the code uses a context variable (line 37).
I would think that this has to do with the way I declared the service in my Android Manifest file. Next is part of the XML:
<application android:debuggable="true">
<service android:enabled="true" android:exported="true" android:name="com.mycompany.myextension.services.MyService">
<intent-filter>
<action android:name="air.com.mycompany.myextension.DO_CUSTOM_ACTION"/>
</intent-filter>
</service>
</application>
I hope you can tell me if I’m declaring the service incorrectly or if I’m making a mistake elsewhere. I appreciate the help.
EDIT: Service code
package com.mydomain.myapplicationextension.services;
import java.util.Timer;
import com.adobe.fre.FREContext;
import com.mydomain.myapplicationextension.myapplicationextension;
import com.mydomain.myapplicationextension.components.HttpServiceTask;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
public class MyApplicationService extends Service {
private Timer timer;
#Override
public IBinder onBind(Intent arg0) {
// Log.d("MyApplicationService", "onBind()");
return null;
}
#Override
public void onCreate() {
// Log.d("MyApplicationService", "onCreate()");
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Log.d("MyApplicationService", "onStartCommand(): " + myapplicationextension.applicationID);
Context appContext = myapplicationextension.applicationContext;
Intent launchIntent = appContext.getPackageManager().getLaunchIntentForPackage(myapplicationextension.appPackageName);
PendingIntent pendingLaunchIntent = PendingIntent.getActivity(appContext, 0, launchIntent, 0);
FREContext extContext = myapplicationextension.extensionContext;
int icon = extContext.getResourceId("drawable.notification_icon");
Notification notification = new Notification.Builder(appContext)
.setContentTitle(myapplicationextension.applicationID)
.setContentText(myapplicationextension.notificationMessage)
.setSmallIcon(icon)
.setContentIntent(pendingLaunchIntent)
.build();
startForeground(1,notification);
// Log.d("MyApplicationService", "startForegroundService()");
if(myapplicationextension.checkStatus)
{
timer = new Timer("Printer");
HttpServiceTask serviceTask = new HttpServiceTask(timer, launchIntent,myapplicationextension.statusServiceURL, myapplicationextension.triggerResponse);
timer.schedule(serviceTask, 0, 2000);
// Log.d("MyApplicationService", "startTimer()");
}
return START_STICKY;
}
#Override
public void onDestroy() {
// Log.d("MyApplicationService", "onDestroy():");
if(myapplicationextension.checkStatus)
{
timer.cancel();
timer = null;
// Log.d("MyApplicationService", "onDestroy(): timer.cancel():");
}
super.onDestroy();
}
}
When the phone runs out of memory and kills the service before it finishes executing. START_STICKY tells the OS to recreate the service after it has enough memory and call onStartCommand() again with a null intent. START_NOT_STICKY tells the OS to not bother recreating the service again. There is also a third code START_REDELIVER_INTENT that tells the OS to recreate the service AND redelivery the same intent to onStartCommand().
START_STICKY and START_NOT_STICKY
I have an ANE using START_STICKY that keeps launching the service