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" 服务的问题运行...

当我打印各种服务方法的执行顺序时,它没有任何意义:

  1. onCreate只调用一次,而onStartCommand每40秒触发一次。
  2. 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