如何在睡眠模式下通过移动网络运行后台服务?

时间:2019-06-18 17:41:34

标签: java android

我正在创建后台服务以更新位置。它可以在睡眠模式下与wifi配合使用,但是当我在睡眠模式下使用移动网络时,我的后台服务无法更新位置。我应该怎么做才能在睡眠模式下通过移动网络运行后台服务?

我使用服务库并将位置更新到服务器。

import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

public class LocationService extends Service {

double latitude=0f;
double longitude=0f;
private LocationManager locationManager = null;
int LOCATION_INTERVAL = 300000;
float LOCATION_DISTANCE = 0f;
public ServerHelper serverHelper = new ServerHelper();

@Override
public void onCreate() {
    Log.d("onCreate: ", "create");
    initializeLocationManager();

    try {
            locationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER,
                    LOCATION_INTERVAL,
                    LOCATION_DISTANCE,
                    locationListeners[0]);

    } catch (java.lang.SecurityException ex) {
    } catch (IllegalArgumentException ex) {
    }
}


@Nullable
@Override
public IBinder onBind(Intent intent) {
    Log.d("onBind: ", "bind");
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d("onStartCommand: ", "startcommand");
    super.onStartCommand(intent,flags,startId);
    return START_STICKY;
}

@Override
public void onDestroy() {
    Log.d("onDestroy: ", "destroy");
    super.onDestroy();
    if (locationManager != null) {
        for (LocationListener locationListener : locationListeners) 
{
            try {
                if (ActivityCompat.checkSelfPermission(this, 
Manifest.permission.ACCESS_FINE_LOCATION) != 
PackageManager.PERMISSION_GRANTED
                        && ActivityCompat.checkSelfPermission(this, 
Manifest.permission.ACCESS_COARSE_LOCATION) != 
PackageManager.PERMISSION_GRANTED) {
                    return;
                }
                locationManager.removeUpdates(locationListener);
            } catch (Exception ex) {
            }
        }
    }
}
private class LocationListener implements 
android.location.LocationListener {
    Location mLocation;
    Calendar calendar;
    DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss", 
Locale.getDefault());

    @Override
    public void onLocationChanged(Location location) {
        Log.d("onLocationChanged: ", "locationChange");
        calendar  = Calendar.getInstance();
        Date date = calendar.getTime();
        String time = dateFormat.format(date);

        mLocation.set(location);
        latitude = location.getLatitude();
        longitude = location.getLongitude();

        String latlng = latitude+","+longitude;
serverHelper.updateLocation(getApplicationContext(),latlng,time);
    }
    @Override
    public void onStatusChanged(String provider, int status, Bundle 
extras) {
        Log.d("onStatusChanged: ", "status");
    }
    @Override
    public void onProviderEnabled(String provider) {
        Log.d("onProviderEnabled: ", "proEnabled");
    }
    @Override
    public void onProviderDisabled(String provider) {
        Log.d("onProviderDisabled: ", "proDisabled");
    }
    LocationListener(String provider) {
        mLocation = new Location(provider);
    }
}
LocationListener[] locationListeners = new LocationListener[] {
        //new LocationListener(LocationManager.GPS_PROVIDER),
        new LocationListener(LocationManager.NETWORK_PROVIDER)
};
private void initializeLocationManager() {
    if (locationManager == null) {
        locationManager = (LocationManager) 
getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
    }
}
}

当我在睡眠模式下使用移动网络时。 onLocationChanged无法调用

1 个答案:

答案 0 :(得分:0)

您不应将后台服务用于此类用途。现代Android版本将在15分钟后终止该服务,除非您的应用程序在前台运行,否则您将无法重新启动该服务。 Android会尝试保留电池寿命,您应该尝试支持它。

以下是可能的解决方案:

  1. 使用AlarmManager设置重复警报。 Android可能会决定在某些情况下延迟您的闹钟,例如如果手机正在休眠。

  2. 使用JobScheduler计划更新位置的重复作业。这需要Android L。

  3. 使用Android Jetpack WorkManager。这结合了以上两种解决方案,并在引擎盖下选择了最佳方法。这是首选的解决方案。检查this page out,了解如何安排重复工作。

  4. 如果您真的想使用后台服务来不断更新位置,则需要通过在服务中调用startForeground()并传递通知来创建前台服务。只要您的服务正在运行,该通知就会显示给用户,但Android不会终止它。不建议使用此解决方案,因为它会更快耗尽电池电量,并且由于正在进行的通知,用户会注意到。

主要模式是:不要让您的应用程序运行,而是使用上述解决方案之一安排位置更新。在过去的两个版本中,Android对后台服务的限制非常严格,除非您的应用程序处于前台,否则您将通过终止后台服务并不允许您重启它们来迫使您采用新机制。这样可以节省电池。我建议不要每15分钟更新一次位置。