I made a simple example in order to test an un-killable service. I'm trying to restart as soon as it is killed by OS.
Everything works well. But, I found that the service was sometimes killed by OS frequently, and re-started again in OS over 6.0. Sometimes, onStartCommand is called in 30 seconds after starting the service. I don't know why.
OS under 6.0 works perfectly well.
My code is simple.
public class DataCollectorService extends Service {
public static BroadcastReceiver broadcastReceiver;
private Intent intent_data_processor;
private PendingIntent sender_data_processor;
private AlarmManager alarmMgr;
private LocalBroadcastManager a_manager;
private String TAG = "DataCollectorService";
private DatabaseReference mFirebaseDatabaseReference;
private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
public void basicTypes(int anInt, long aLong, boolean aBoolean,
float aFloat, double aDouble, String aString) {
// Does nothing
}
};
public DataCollectorService(Context applicationContext) {
super();
Log.i("HERE", "here I am!");
}
public DataCollectorService() {
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
release();
}
#Override
protected void finalize() throws Throwable {
super.finalize();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
Log.e("TAG", "START");
Log.e("TAG", "DataCollectorService onStartCommand");
return START_STICKY;
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
#Override
public boolean onUnbind(Intent arg0) {
return true;
}
#Override
public void onRebind(Intent arg0) {
}
And then I also set up the service like following in Manifest.
android:enabled="true"
android:exported="false"
What is the reason that the service is restarted within a few seconds after the starting?
Related
I am using foreground service in my App to detect shake and launch app from anywhere to MainActivity, After doing on some code now I'm stucked with the problem. I hope someone will come up with the solution or suggest me how to make this work. Yes, I did run the app, after I run whenever I shake my phone the service thus the app gets closed automatically. My service code has been given below
public class ExampleService extends Service {
private SensorManager sensorManager;
private float acelVal;
private float acelLast;
private float shake;
public ExampleService() {
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent notificationIntent=new Intent(this,MainActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(this,0,notificationIntent,0);
Notification notification=new NotificationCompat.Builder(this,CHANNEL_ID)
.setContentTitle("Example service")
.setContentText("Example for shaking")
.setSmallIcon(R.drawable.ic_android)
.setContentIntent(pendingIntent)
.build();
sensorManager=(SensorManager)getSystemService(Context.SENSOR_SERVICE);
sensorManager.registerListener(sensorListener,sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
acelVal=SensorManager.GRAVITY_EARTH;
acelLast=SensorManager.GRAVITY_EARTH;
shake=0.00f;
startForeground(1,notification);
return START_NOT_STICKY;
}
public final SensorEventListener sensorListener= new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
float x=sensorEvent.values[0];
float y=sensorEvent.values[1];
float z=sensorEvent.values[2];
acelLast=acelVal;
acelVal=(float)Math.sqrt((double)(x*x+y*y+z*z));
float delta=acelVal-acelLast;
shake=shake*0.9f+delta;
if(shake>12)
{
Intent intent= new Intent(ExampleService.this,MainActivity.class);
startActivity(intent);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
And the MainActivity code:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent=new Intent(this,ExampleService.class);
startForegroundService(intent);
}
}
Am I on the right path to achieve this? If not suggest me how to solve it
The onBind method is part of the android service lifecycle. It's not an explicit call, the OS automatically calls it for you. The method is useful in some specific use cases (called bound services). In the most simple cases, you can just return a null binder.
So you should replace:
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
by:
#Override
public IBinder onBind(Intent intent) {
return null;
}
I am trying to create a service to keep running even when the application is not at foreground. when it is in foreground, all works well, but after switching away from it, the onLocationChanged is being called once every ~10 minutes (instead of 5 seconds when in foreground).
The goal is to keep scanning the location and send updates for processing even when the application is in background every 5 seconds (I want the service to keep running as long as the UI applications is not being totally closed).
I tried following many guides and posts in the net and none of them helped solving this. in the past it was working fine with android 6.0, but I upgraded to 8.0 and it stopped working.
This is the code I'm using:
public class MainActivity extends AppCompatActivity {
private Intent _scanServiceIntent;
#Override
public void onStart()
{
super.onStart();
_scanServiceIntent = new Intent(this,ScanService.class);
bindService(_scanServiceIntent, m_serviceConnection, BIND_AUTO_CREATE);
}
private ServiceConnection m_serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
_scanService = ((ScanService.ScanServiceBinder)service).getService();
}
public void onServiceDisconnected(ComponentName className) {
Log.v("lsx", "onServiceDisconnected");
_scanService = null;
}
};
}
This is the ScanService class:
public class ScanService extends Service {
private LocationListener _locListener;
private LocationManager _locManager;
private static final String TAG = "locationtrigger";
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.v(TAG, "onBind");
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(TAG, "ScanServiceonStartCommand");
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#SuppressLint("MissingPermission")
#Override
public void onCreate() {
Log.v(TAG, "ScanServiceonCreate - start");
List<UserLocationManager> locationsManagers = GetLocationsManagers();
_locListener = new MyLocationListener(locationsManagers);
_locManager = (LocationManager)getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
_locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, _locListener);
Log.v(TAG, "ScanServiceonCreate - end");
}
#Override
public void onDestroy() {
_locManager.removeUpdates(_locListener);
}
public List<UserLocationManager> GetLocationsManagers(){
// returning some managers
}
public class ScanServiceBinder extends Binder {
public ScanService getService() {
Log.v(TAG, "ScanServiceBinder.getService");
return ScanService.this;
}
}
class MyLocationListener implements LocationListener {
private List<UserLocationManager> _locationManagers;
public MyLocationListener(List<UserLocationManager> locationManagers)
{
_locationManagers = locationManagers;
}
#Override
public void onLocationChanged(Location location)
{
if (location != null)
{
// call managers
}
}
}
}
I'm writing this service but I can't see the log strings when I launch the app.
if I put a Log.i in the method startBeaconDetecting I can see it but after the onCreate() method doesn't start.
Why onCreate doesn't run?
public class ProximityBeacon extends Service
{
private String server;
private String ID;
public ProximityBeacon(String server)
{
this.server=server;
//TODO indirizzo del server
}
public void startBeaconDetecting(String ID, Intent intent, Context context)
{
this.ID=ID;
context.startService(intent);
}
public void stopBeaconDetecting()
{
stopSelf();
onDestroy();
}
public void onCreate()
{
super.onCreate();
Log.i(TAG, "Oncreate");
}
public int onStartCommand(Intent intent, int flag, int startId)
{
Log.i(TAG, "onStartCommand");
return Service.START_STICKY;
}
}
Change your Service class to this:
public class ProximityBeacon extends Service
{
private static final String TAG = "TAG";
private String server;
private String ID;
public ProximityBeacon() {
}
public ProximityBeacon(String server)
{
this.server=server;
//TODO indirizzo del server
}
public void startBeaconDetecting(String ID, Intent intent, Context context)
{
this.ID=ID;
context.startService(intent);
}
public void stopBeaconDetecting()
{
stopSelf();
onDestroy();
}
public void onCreate()
{
super.onCreate();
Log.i(TAG, "ProximityBeacon Oncreate");
}
public int onStartCommand(Intent intent, int flag, int startId)
{
Log.i(TAG, "ProximityBeaconon StartCommand");
return Service.START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
and then call it using this:
new ProximityBeacon("").startBeaconDetecting("" ,new Intent(HomeActivity.this, ProximityBeacon.class) ,mContext) ;
then add it in manifest.xml like this :
<service android:name=".services.ProximityBeacon" />
Output : 19:25:11.873 23002-23002/com.sample.service I/TAG: ProximityBeaconon StartCommand
after startService(service); will run onStartCommand, not onCreate
I have a Service in my android application which stop only when quitting the application.
public class MyService extends Service {
public MyService() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
if(intent != null){
//......
}
} catch (Throwable e) {
}
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onCreate() {
super.onCreate();
//......
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
This service calls its onCreate() method sometimes itself while running.When checking the state of service it is running but its functionalities does not work.I am stuck on this for many hours.What is the problem here?I tried onLowMemory() in this service.But not result.
If you return START_STICKY in the onStartCommand(), the Service gets created again if its killed by system (probably on a low memory condition). The same thing must have happened in your case and onCreate() got called.
I would like to track battery information(is it charging, level etc.) even when my app is not turned on. I think maybe service would be good for it? Or maybe there are other solutions? I'm all ears up.
This is in fact a very old post but since the accepted answer seems like a stub service i think there is the need to go deeper.
You need to declare the service in the android manifest. If you have it in a certain package the declaration would be:
<service android:name="packagename.servicename" />
Then you would need to implement the service class. I have created one for one of my applications. Hope this helps you.
I have this in the context of sensors. sensors are something i want to monitor so i created an interface like the following:
public interface Sensor {
SensorType getSensorType();
SensorName getSensorName();
}
I have to ENUM classes that represent the types and names of sensors i have:
public enum SensorName {
ENVIRONMENTAL_SENSOR, AUDIO_SENSOR, SOUND_SENSOR, SOCIAL_SENSOR,
LOCATION_SENSOR, PHOTO_SENSOR, ACCELEROMETER_SENSOR, BATTERY_SENSOR;
}
public enum SensorType {
HARDWARE_SENSOR, SOFTWARE_SENSOR, HYBRID_SENSOR;
}
Since i have several sensors and i might want to have a listing of all the sensors i needed to implement this interface. Next i created a abstract class to implement behaviours that are similar to all my sensors.
public abstract class SensorElement extends Service implements Sensor{
protected SensorType type;
protected SensorName name;
#Override
public abstract IBinder onBind(Intent arg0);
#Override
public int onStartCommand(Intent intent, int flags, int startId){
return super.onStartCommand(intent, flags, startId);
}
#Override
public abstract void onCreate();
#Override
public void onDestroy(){
super.onDestroy();
}
}
My sensors need this methods to work properly. In my case i only absolutely need the binder to bind the service to my activity.
Now what you want, the battery sensor itself:
public class BatterySensor extends SensorElement {
// Binder given to clients
private final IBinder mBinder = new BatteryLocalBinder();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class BatteryLocalBinder extends Binder {
public BatterySensor getService() {
// Return this instance of MotionLightOrientationSensor so clients
// can call
// public
// methods
return BatterySensor.this;
}
}
private static final String TAG = "BatterySensor";
public static final SensorType type = SensorType.SOFTWARE_SENSOR;
public static final SensorName name = SensorName.BATTERY_SENSOR;
private int status;
private boolean isCharging;
private int chargePlug;
private boolean usbCharge;
private boolean acCharge;
private int level;
private int scale;
private double batteryPct;
private Battery battery;
#Override
public SensorType getSensorType() {
return type;
}
#Override
public SensorName getSensorName() {
return name;
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
#Override
public void onCreate() {
Log.e(TAG, "onCreate");
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(powerconnectionreceiver, ifilter);
battery = new Battery();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
super.onDestroy();
unregisterReceiver(powerconnectionreceiver);
}
private BroadcastReceiver powerconnectionreceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Retrieves a map of extended data from the intent.
status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING
|| status == BatteryManager.BATTERY_STATUS_FULL;
chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
batteryPct = level / (float) scale;
battery.setStatus(status);
battery.setCharging(isCharging);
battery.setChargePlug(chargePlug);
battery.setUsbCharge(usbCharge);
battery.setAcCharge(acCharge);
battery.setLevel(level);
battery.setScale(scale);
battery.setBatteryPct(batteryPct);
}
};
public Battery getBatteryReading() {
return this.battery;
}
public int getStatus() {
return status;
}
public boolean isCharging() {
return isCharging;
}
public int getChargePlug() {
return chargePlug;
}
public boolean isUsbCharge() {
return usbCharge;
}
public boolean isAcCharge() {
return acCharge;
}
public int getLevel() {
return level;
}
public int getScale() {
return scale;
}
}
To access data from this sensor you only need to start it in you activity like this:
private BatterySensor batterySensor;
private boolean mBatteryBound = false;
private Intent intentBattery;
intentBattery = new Intent(this.context, BatterySensor.class);
then i start the service:
context.startService(intentBattery);
and bind it:
if(this.context.bindService(intentBattery, mBatteryConnection, Context.BIND_AUTO_CREATE)){
this.numBoundedSensors++;
}
to bind it you need to have this class in your activity:
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mBatteryConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
BatteryLocalBinder BatteryBinder = (BatteryLocalBinder) service;
batterySensor = BatteryBinder.getService();
mBatteryBound = true;
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBatteryBound = false;
}
};
Then if it succeeded the bind you can call all the methods from the sensor, like this:
public Battery getBatteryData(){
return mBatteryBound ? batterySensor.getBatteryReading() : null;
}
A service needs to be declared in the AndroidManifest.xml and the implementing class must extend the Service class or one of its subclasses. The following code shows an example for a service declaration and its implementation.
<service
android:name="MyService"
android:icon="#drawable/icon"
android:label="#string/service_name"
>
</service>
public class MyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO do something useful
return Service.START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
//TODO for communication return IBinder implementation
return null;
}
}