Java 为什么我的前台服务会被Android系统杀死?
我的应用程序是一个跟踪应用程序,我想跟踪服务中的用户位置,然后在片段中显示每个位置。 我的后台服务有问题:我的服务在几分钟后停止(有时<10分钟,有时>30分钟)。 我在这个片段中启动了我的位置服务,当我使用我的应用程序时,一切都很顺利。 问题是,当我关闭(而不是关闭)我的应用程序并在手机上启动其他东西(或只是阻止它)时,几分钟后我的服务就停止了,我不知道为什么。Java 为什么我的前台服务会被Android系统杀死?,java,android,service,location,foreground-service,Java,Android,Service,Location,Foreground Service,我的应用程序是一个跟踪应用程序,我想跟踪服务中的用户位置,然后在片段中显示每个位置。 我的后台服务有问题:我的服务在几分钟后停止(有时30分钟)。 我在这个片段中启动了我的位置服务,当我使用我的应用程序时,一切都很顺利。 问题是,当我关闭(而不是关闭)我的应用程序并在手机上启动其他东西(或只是阻止它)时,几分钟后我的服务就停止了,我不知道为什么。 当我的服务运行时,我会显示一个前台通知,但android系统仍然会停止它,我注意到这一点,因为我的通知消失,我的应用程序重新启动 以下是我的服务代码:
当我的服务运行时,我会显示一个前台通知,但android系统仍然会停止它,我注意到这一点,因为我的通知消失,我的应用程序重新启动 以下是我的服务代码:
public class LocationService extends Service {
private static final String TAG = "LocationService";
public static final String NEW_VALUE_INTENT_ACTION = "service_new_value";
public static final String INTENT_LATITUDE = "latitude";
public static final String INTENT_LONGITUDE = "longitude";
public static final String INTENT_SPEED = "speed";
public static final String INTENT_ACCURACY = "accuracy";
private static final long TWO_MINUTES = 1000 * 60 * 2;
private static final long INTERVAL = 5000;
private static final long FASTEST_INTERVAL = 2000;
private int ONGOING_NOTIFICATION = 1111;
private Location currentLocation;
NotificationCompat.Builder builder = null;
private LocationRequest mLocationRequest;
/**
* Provides access to the Fused Location Provider API.
*/
private FusedLocationProviderClient mFusedLocationClient;
/**
* Callback for changes in location.
*/
private LocationCallback mLocationCallback;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
Log.d(LocationService.TAG, "LocationService ---> onCreate()");
super.onCreate();
}
@Override
public void onDestroy() {
Log.d(LocationService.TAG, "LocationService ---> onDestroy()");
super.onDestroy();
stopForeground(true);
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(LocationService.TAG, "LocationService ---> onStartCommand()");
startServiceTask();
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(LocationService.TAG, "LocationService ---> onUnbind()");
return super.onUnbind(intent);
}
private void startServiceTask() {
Log.d(LocationService.TAG, "GpsService ---> Starting ...");
setServiceAsForeground();
initFusedLocationProvider();
Log.d(LocationService.TAG, "MyStartedService ---> Starting ...");
}
private void initFusedLocationProvider() {
mFusedLocationClient = new FusedLocationProviderClient(this);
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
if (currentLocation == null)
currentLocation = locationResult.getLastLocation();
else if (isBetterLocation(locationResult.getLastLocation(), currentLocation)) {
Log.d(TAG, "onLocationChanged(): Updating Location ... " + currentLocation.getProvider());
currentLocation = locationResult.getLastLocation();
}
notifyValueUpdate();
} }, getMainLooper());
}
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use
// the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be
// worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Determine location quality using a combination of timeliness and
// accuracy
if (isMoreAccurate) {
return true;
} else if (isNewer && !isLessAccurate) {
return true;
} else if (isNewer && !isSignificantlyLessAccurate
&& isFromSameProvider) {
return true;
}
return false;
}
/** Checks whether two providers are the same */
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
private void setServiceAsForeground() {
Log.d(LocationService.TAG, "GpsService ---> setServiceAsForeground()");
// Prepare the intent triggered if the notification is selected
Intent intent = new Intent(this, LocationService.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
builder = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel notificationChannel = new NotificationChannel("ID", "Name", importance);
notificationManager.createNotificationChannel(notificationChannel);
builder = new NotificationCompat.Builder(getApplicationContext(), notificationChannel.getId());
} else {
builder = new NotificationCompat.Builder(getApplicationContext());
}
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
//deprecated in API 26
v.vibrate(500);
}
// Build the notification
// Use NotificationCompat.Builder instead of just Notification.Builder to support older Android versions
Notification notification = builder.setContentTitle("MyMovements")
.setContentText("Running ...")
.setSmallIcon(getNotificationIcon())
.setBadgeIconType(getNotificationIcon())
.setContentIntent(pIntent)
.setAutoCancel(true).build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(ONGOING_NOTIFICATION, notification, FOREGROUND_SERVICE_TYPE_LOCATION);
}
else {
startForeground(ONGOING_NOTIFICATION,notification);
}
}
private int getNotificationIcon(){
SharedPreferences settings = this.getSharedPreferences(MainActivity.PREFERENCE,0);
String icon = settings.getString(MapFragment.NOTIFICATION_PREF, " ");
switch (icon) {
case "Walking":
return R.drawable.walk;
case "Public Transportation":
return R.drawable.bus;
case "Driving":
return R.drawable.car;
default:
return 0;
}
}
private void updateNotification(){
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String conc = "Running...\n" + "Lat: " + currentLocation.getLatitude() + " " + "Lng: " + currentLocation.getLongitude();
Notification notification = builder.setStyle(new NotificationCompat.BigTextStyle()
.bigText(conc))
.setContentText(conc).build();
notificationManager.notify(ONGOING_NOTIFICATION, notification);
}
private void notifyValueUpdate(){
Log.d(TAG, "MyStartedService ---> notifyValueUpdate()");
if(currentLocation != null) {
updateNotification();
Log.d(LocationService.TAG, currentLocation.getProvider());
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(NEW_VALUE_INTENT_ACTION);
Bundle bundle = new Bundle();
bundle.putDouble(INTENT_LATITUDE, currentLocation.getLatitude());
bundle.putDouble(INTENT_LONGITUDE, currentLocation.getLongitude());
bundle.putDouble(INTENT_SPEED, currentLocation.getSpeed()*3.6);
bundle.putDouble(INTENT_ACCURACY, currentLocation.getAccuracy());
broadcastIntent.putExtras(bundle);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent);
}
}
公共类定位服务扩展服务{
私有静态最终字符串TAG=“LocationService”;
公共静态最终字符串NEW\u VALUE\u INTENT\u ACTION=“service\u NEW\u VALUE”;
公共静态最终字符串意图_LATITUDE=“LATITUDE”;
公共静态最终字符串意图_longide=“longide”;
公共静态最终字符串意图\u SPEED=“SPEED”;
公共静态最终字符串意图\u accurity=“accurity”;
私人静态最终长两分钟=1000*60*2;
专用静态最终长间隔=5000;
专用静态最终长最快_间隔=2000;
私人int持续_通知=1111;
私人位置;
NotificationCompat.Builder=null;
私人位置请求mLocationRequest;
/**
*提供对融合位置提供程序API的访问。
*/
私有FusedLocationProviderClient mFusedLocationClient;
/**
*位置更改的回调。
*/
私有位置回调mLocationCallback;
@可空
@凌驾
公共IBinder onBind(意向){
返回null;
}
@凌驾
public void onCreate(){
Log.d(LocationService.TAG,“LocationService-->onCreate()”;
super.onCreate();
}
@凌驾
公共空间{
Log.d(LocationService.TAG,“LocationService-->ondestory()”;
super.ondestory();
停止前景(真);
mFusedLocationClient.RemovelocationUpdate(mlLocationCallback);
}
@凌驾
公共int onStartCommand(Intent Intent、int标志、int startId){
Log.d(LocationService.TAG,“LocationService-->onStartCommand()”;
startServiceTask();
返回super.onStartCommand(intent、flags、startId);
}
@凌驾
公共布尔onUnbind(意图){
Log.d(LocationService.TAG,“LocationService-->onUnbind()”;
返回super.onUnbind(intent);
}
私有void startServiceTask(){
Log.d(LocationService.TAG,“GpsService-->Starting…”);
setServicesForeground();
initFusedLocationProvider();
Log.d(LocationService.TAG,“MyStartedService-->Starting…”);
}
私有void initFusedLocationProvider(){
mFusedLocationClient=新FusedLocationProviderClient(此);
mlLocationRequest=新位置请求();
mLocationRequest.setPriority(位置请求.优先级高精度);
mlLocationRequest.setInterval(间隔);
mLocationRequest.SetFastTestInterval(最快间隔);
mFusedLocationClient.RequestLocationUpdate(mlLocationRequest,mlLocationCallback=new LocationCallback(){
@凌驾
public void onLocationResult(LocationResult LocationResult){
super.onLocationResult(定位结果);
如果(currentLocation==null)
currentLocation=locationResult.getLastLocation();
else if(isBetterLocation(locationResult.getLastLocation(),currentLocation)){
Log.d(标记“onLocationChanged():更新位置…”+currentLocation.getProvider());
currentLocation=locationResult.getLastLocation();
}
notifyValueUpdate();
}},getMainLooper());
}
受保护的布尔值isBetterLocation(位置位置,位置currentBestLocation){
如果(currentBestLocation==null){
//新位置总比没有位置好
返回true;
}
//检查新的位置修复程序是较新的还是较旧的
long-timeDelta=location.getTime()-currentBestLocation.getTime();
布尔值isSignificantlyNewer=时间增量>两分钟;
布尔值Issignificantlolder=时间增量<-2_分钟;
布尔值isNewer=timeDelta>0;
//如果距离当前位置已超过两分钟,请使用
//新地点
//因为用户可能已经移动了
如果(非常重要){
返回true;
//如果新位置早于两分钟,则必须
//更糟
}else if(Issignificantlolder){
返回false;
}
//检查新的位置修复是否更精确
int accuracyDelta=(int)(location.getAccuracy()-currentBestLocation
.getaccurity());
布尔值IslesAccurate=accuracyDelta>0;
布尔值IsmorePrecision=精度偏差<0;
布尔值不太精确=精度偏差>200;
//检查新旧位置是否来自同一提供商
布尔值isFromSameProvider=isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
//结合及时性和可靠性确定位置质量
//准确度
如果(更准确){
返回true;
}else if(isNewer&!islesAccurate){
返回true;
}否则,如果(较新的&!不准确的话)
&&isFromSameProvider){
返回true;
}
返回false;
}
/**检查两个提供程序是否相同*/
专用布尔值isSameProvider(字符串提供程序1、字符串提供程序2){
if(provider1==null){
返回provider2==null;
}
返回provider1.equals(provider2);
}
私有void setServicesForeground(){
Log.d(LocationService.TAG,“GpsService-->setServicesForeground()”;
//准备在选择通知时触发的意图
意向意向=新意向(此,LocationService.class);
PendingIntent pIntent=PendingI