我正在尝试使用Android O中的Fused Location Provider Client在前台服务中获取设备的当前位置。但是,在发出位置请求后,该服务将被终止。我认为服务被终止是因为融合的位置提供程序客户端在另一个后台线程中获取了位置,并且从服务的角度来看,它的任务已经完成。问题是服务销毁后未收到位置更新。在明确停止服务之前,如何使服务保持活动状态?
我的服务类别:
private val TAG = LocationService::class.java.simpleName
companion object {
val STOP_ACTION = "STOP_ACTION"
}
private lateinit var mFusedLocationClient: FusedLocationProviderClient
private lateinit var mLocationCallback: LocationCallback
private lateinit var notificationManager: NotificationManager
private val notificationId = 1
private val UPDATE_INTERVAL_IN_MILLISECONDS = 5000L
private val FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 500L
private val CHANNEL_ID = TAG
override fun onHandleIntent(intent: Intent?) {
Log.d(TAG, "onHandleIntent start")
if (intent?.action.equals(STOP_ACTION)) {
Log.d(TAG, "stop service")
stopForeground(true)
stopSelf()
} else {
Log.d(TAG, "start location update")
createNotificationChannel()
val notificationIntent = Intent(this, OnboardingActivity::class.java)
val pendingIntent = PendingIntent.getActivity(
this,
0, notificationIntent, 0
)
val notification = NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Tracking realtime location")
.setContentText("Tap to open the application")
.setSmallIcon(R.drawable.logo)
.setContentIntent(pendingIntent)
.setOngoing(true)
.build()
startForeground(notificationId , notification)
startLocationUpdates()
}
}
override fun onCreate() {
super.onCreate()
notificationManager =
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult ?: return
for (location in locationResult.locations) {
Log.d(TAG, "$location")
}
}
override fun onLocationAvailability(p0: LocationAvailability?) {
super.onLocationAvailability(p0)
}
}
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.e(TAG, "onStartCommand")
super.onStartCommand(intent, flags, startId)
return START_STICKY
}
override fun onDestroy() {
super.onDestroy()
mFusedLocationClient.removeLocationUpdates(mLocationCallback)
Log.e(TAG, "location service destroyed")
}
private fun startLocationUpdates() {
val mLocationRequest = LocationRequest()
mLocationRequest.interval = UPDATE_INTERVAL_IN_MILLISECONDS
mLocationRequest.fastestInterval = FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS
mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
try {
mFusedLocationClient.requestLocationUpdates(
mLocationRequest,
mLocationCallback,
Looper.myLooper()
)
} catch (e: SecurityException) {
Log.e(TAG, "Lost location permission. Could not request updates. $e")
}
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val nChannel = notificationManager.getNotificationChannel(CHANNEL_ID)
if (nChannel == null) {
val serviceChannel = NotificationChannel(
CHANNEL_ID,
"Foreground Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(serviceChannel)
}
}
}
}
非常感谢您的帮助。
尝试一下
public class BackgroundLocationUpdateService extends Service {
/**
* Author:Hardik Talaviya
* Date: 2019.08.3 2:30 PM
* Describe:
*/
private static final String TAG = "BackgroundLocation";
private Context context;
private FusedLocationProviderClient client;
private LocationCallback locationCallback;
private boolean stopService = false;
private Handler handler;
private Runnable runnable;
private NotificationCompat.Builder builder = null;
private NotificationManager notificationManager;
@Override
public void onCreate() {
Log.e(TAG, "Background Service onCreate :: ");
super.onCreate();
context = this;
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
try {
requestLocationUpdates();
} catch (Exception e) {
e.printStackTrace();
} finally {
handler.postDelayed(this, TimeUnit.SECONDS.toMillis(2));
}
}
};
if (!stopService) {
handler.postDelayed(runnable, TimeUnit.SECONDS.toMillis(2));
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.e(TAG, "onTaskRemoved :: ");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand :: ");
StartForeground();
if (client != null) {
client.removeLocationUpdates(locationCallback);
Log.e(TAG, "Location Update Callback Removed");
}
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "BackgroundService onDestroy :: ");
stopService = true;
if (handler != null) {
handler.removeCallbacks(runnable);
}
if (client != null) {
client.removeLocationUpdates(locationCallback);
Log.e(TAG, "Location Update Callback Removed");
}
}
private void requestLocationUpdates() {
LocationRequest request = new LocationRequest();
request.setFastestInterval(100)
.setInterval(200)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
client = LocationServices.getFusedLocationProviderClient(this);
final int[] permission = {ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)};
if (permission[0] == PackageManager.PERMISSION_GRANTED) {
final Location[] location = {new Location(LocationManager.GPS_PROVIDER)};
locationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
location[0] = locationResult.getLastLocation();
if (location[0] != null) {
Log.d(TAG, "location update " + location[0]);
Log.d(TAG, "location Latitude " + location[0].getLatitude());
Log.d(TAG, "location Longitude " + location[0].getLongitude());
Log.d(TAG, "Speed :: " + location[0].getSpeed() * 3.6);
if (notificationManager != null && client != null && !stopService) {
builder.setContentText("Your current location is " + location[0].getLatitude() + "," + location[0].getLongitude());
notificationManager.notify(101, builder.build());
}
}
}
};
client.requestLocationUpdates(request, locationCallback, null);
}
}
/*-------- For notification ----------*/
private void StartForeground() {
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT);
String CHANNEL_ID = "channel_location";
String CHANNEL_NAME = "channel_location";
notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
notificationManager.createNotificationChannel(channel);
builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID);
builder.setColorized(false);
builder.setChannelId(CHANNEL_ID);
builder.setColor(ContextCompat.getColor(this, R.color.colorPrimaryDark));
builder.setBadgeIconType(NotificationCompat.BADGE_ICON_NONE);
} else {
builder = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID);
}
builder.setOnlyAlertOnce(true);
builder.setContentTitle(context.getResources().getString(R.string.app_name));
builder.setContentText("Your current location is ");
Uri notificationSound = RingtoneManager.getActualDefaultRingtoneUri(this, RingtoneManager.TYPE_NOTIFICATION);
builder.setSound(notificationSound);
builder.setAutoCancel(true);
builder.setSmallIcon(R.mipmap.ic_notification_app_icon);
builder.setContentIntent(pendingIntent);
startForeground(101, builder.build());
}
}
我希望这可以帮助您!