Android 重复服务 - onCreate 调用一次,onStartCommand 调用多次
Android repeated Service - onCreate called once, onStartCommand called many
我按照基本 android 文档实现了一个 Service
,每 40 秒由 AlarmManager
重复触发。在服务中我注册了 GPS 侦听器,如果我在 30 秒内没有得到修复,我会调用 stopSelf()
,这是为了避免 2 "concurrent" 服务 运行 在一起。但是,如果我确实在不到 30 秒内修复了问题,我会执行一些逻辑,完成后我会调用 stopSelf()
- 假设这一切都将花费不到 40 秒,所以我再次没有 "concurrent" 服务的问题运行...
当我打印各种服务方法的执行顺序时,它没有任何意义:
onCreate
只调用一次,而onStartCommand
每40秒触发一次。
- GPS 从不固定,也许主机
Activity
也注册了 GPS 固定这一事实干扰了这里? (我在户外测试,activity 确实得到修复)
这是我的实现 - 非常简单的谷歌 android 文档:
public class DirectionService extends Service implements Constants {
private LocationManager mLocationManager;
private LocationListener mLocationListeners;
private Context mContext;
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
@Override
public IBinder onBind(Intent arg0) {
return null; //not binding
}
@Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
mContext = getApplicationContext();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//For each start request, send a message to start a job and deliver the start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_STICKY;
}
//Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
/**
* The real work done after we have (first) fixed location and from there we stop the service.
* Therefore we pass the start id.
*/
@Override
public void handleMessage(final Message msg) {
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
mLocationListeners = new LocationListener(msg.arg1);
}
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_UPDATE_TIME, 0, mLocationListeners);
mLocationManager.addGpsStatusListener(mGPSStatusListener);
} catch (Exception e) {
stopSelf(msg.arg1);
}
//Start timer for GPS to get fix location. Else we might have new concurrent instance of service
new CountDownTimer(30000, 15000) {
public void onTick(long millisUntilFinished) {}
public void onFinish() {
stopSelf(msg.arg1);
}
}.start();
}
}
GpsStatus.Listener mGPSStatusListener = new GpsStatus.Listener() {
public void onGpsStatusChanged(int event) {
switch (event)
{
case GpsStatus.GPS_EVENT_FIRST_FIX:
if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) != null) {
isGpsFixed = true;
}
}
break;
default:
break;
}
}
};
private class LocationListener implements android.location.LocationListener {
private int startId;
public LocationListener(int startId) {
this.startId = startId;
}
@Override
public void onLocationChanged(Location location) {
if (isGpsFixed == true && location.getLongitude() != 0.0 && location.getLatitude() != 0.0 && isAlreadySentToCheck == false) {
isAlreadySentToCheck = true;
startLogic(startId);
}
}
@Override
public void onProviderDisabled(String provider) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
private void startLogic(final int startId) {
//...
stopSelf(startId);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mLocationManager != null) {
try {
mLocationManager.removeUpdates(mLocationListeners);
} catch (Exception ex) {}
}
}
你的服务运行很多次因为start_sticky
如果您的服务由于内存不足而被 Android 终止,并且 Android 清除了一些内存,那么...
STICKY:...Android 将重新启动您的服务,因为已设置该特定标志。
NOT_STICKY: ...Android 不会关心重新开始,因为标志告诉 Android 它不应该打扰。
REDELIVER_INTENT:...Android 将重新启动服务并向服务的 onStartCommand() 重新传递相同的意图,因为,同样是标志。
给你的建议start_not_sticky
我按照基本 android 文档实现了一个 Service
,每 40 秒由 AlarmManager
重复触发。在服务中我注册了 GPS 侦听器,如果我在 30 秒内没有得到修复,我会调用 stopSelf()
,这是为了避免 2 "concurrent" 服务 运行 在一起。但是,如果我确实在不到 30 秒内修复了问题,我会执行一些逻辑,完成后我会调用 stopSelf()
- 假设这一切都将花费不到 40 秒,所以我再次没有 "concurrent" 服务的问题运行...
当我打印各种服务方法的执行顺序时,它没有任何意义:
onCreate
只调用一次,而onStartCommand
每40秒触发一次。- GPS 从不固定,也许主机
Activity
也注册了 GPS 固定这一事实干扰了这里? (我在户外测试,activity 确实得到修复)
这是我的实现 - 非常简单的谷歌 android 文档:
public class DirectionService extends Service implements Constants {
private LocationManager mLocationManager;
private LocationListener mLocationListeners;
private Context mContext;
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
@Override
public IBinder onBind(Intent arg0) {
return null; //not binding
}
@Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
mContext = getApplicationContext();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//For each start request, send a message to start a job and deliver the start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_STICKY;
}
//Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
/**
* The real work done after we have (first) fixed location and from there we stop the service.
* Therefore we pass the start id.
*/
@Override
public void handleMessage(final Message msg) {
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
mLocationListeners = new LocationListener(msg.arg1);
}
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_UPDATE_TIME, 0, mLocationListeners);
mLocationManager.addGpsStatusListener(mGPSStatusListener);
} catch (Exception e) {
stopSelf(msg.arg1);
}
//Start timer for GPS to get fix location. Else we might have new concurrent instance of service
new CountDownTimer(30000, 15000) {
public void onTick(long millisUntilFinished) {}
public void onFinish() {
stopSelf(msg.arg1);
}
}.start();
}
}
GpsStatus.Listener mGPSStatusListener = new GpsStatus.Listener() {
public void onGpsStatusChanged(int event) {
switch (event)
{
case GpsStatus.GPS_EVENT_FIRST_FIX:
if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) != null) {
isGpsFixed = true;
}
}
break;
default:
break;
}
}
};
private class LocationListener implements android.location.LocationListener {
private int startId;
public LocationListener(int startId) {
this.startId = startId;
}
@Override
public void onLocationChanged(Location location) {
if (isGpsFixed == true && location.getLongitude() != 0.0 && location.getLatitude() != 0.0 && isAlreadySentToCheck == false) {
isAlreadySentToCheck = true;
startLogic(startId);
}
}
@Override
public void onProviderDisabled(String provider) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
private void startLogic(final int startId) {
//...
stopSelf(startId);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mLocationManager != null) {
try {
mLocationManager.removeUpdates(mLocationListeners);
} catch (Exception ex) {}
}
}
你的服务运行很多次因为start_sticky
如果您的服务由于内存不足而被 Android 终止,并且 Android 清除了一些内存,那么...
STICKY:...Android 将重新启动您的服务,因为已设置该特定标志。
NOT_STICKY: ...Android 不会关心重新开始,因为标志告诉 Android 它不应该打扰。
REDELIVER_INTENT:...Android 将重新启动服务并向服务的 onStartCommand() 重新传递相同的意图,因为,同样是标志。
给你的建议start_not_sticky