首先感谢这哥们的分享https://blog.csdn.net/napolun007/article/details/82382940,我是在他基础上进行修改,因为调用百度地图或者高德地图时,如果直接使用地图的service,在手机锁屏后 几秒钟就不能记录轨迹和上传数据了。
所以借鉴上面哥们的分享 另起一个播放音乐的service, 在这个service 里面初始化地图定位,同时使用NotificationUtils,适配android8.0 我使用的高德定位 希望对大家有帮助 测试手机为华为荣耀。 但是 如果应用程序在后台时间过长会自动kill 目前没有找到解决办法。 有效果的前提是应用程序必须在第一个活动 即打开应用程序 然后再锁屏,如果使用home建 择不行
//后台服务
public class BackGroundService extends Service {
private MediaPlayer bgmediaPlayer;
private GdlocationListener gdlocationListener;
GdlocationListener.IGdLocationListener listener;
public class BackServiceBinder extends Binder {
public BackGroundService getService(GdlocationListener.IGdLocationListener listener1) {
listener = listener1;
service();
return BackGroundService.this;
}
}
private BackServiceBinder binder = new BackServiceBinder();
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_REDELIVER_INTENT;
}
NotificationUtils mNotificationUtils = null;
Notification notification = null;
private void service() {
//设置后台定位
//android8.0及以上使用NotificationUtils
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
mNotificationUtils = new NotificationUtils(this);
Intent notificationIntent = new Intent(this, BaseActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 3,
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification.Builder builder2 = mNotificationUtils.getAndroidChannelNotification
("后台定位服务", "测试",pendingIntent);
notification = builder2.build();
//startForeground(1, notification);//id must not be 0,即禁止是0
}
if (gdlocationListener == null) {
gdlocationListener = GdlocationListener.getInstance();
}
gdlocationListener.init(this, listener,notification);
//播放无声音乐
if (bgmediaPlayer == null) {
bgmediaPlayer = MediaPlayer.create(this, R.raw.silent);
bgmediaPlayer.start();
bgmediaPlayer.setLooping(true);
bgmediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
bgmediaPlayer.start();
bgmediaPlayer.setLooping(true);
}
});
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public boolean onUnbind(Intent intent) {
return false;
}
@Override
public void onDestroy() {
stopForeground(true);
bgmediaPlayer.release();
stopSelf();
gdlocationListener.stop();
super.onDestroy();
}
private NotificationManager mManager;
public static final String ANDROID_CHANNEL_ID = "12334121";
public static final String ANDROID_CHANNEL_NAME = "ChanneName";
private Context context;
public NotificationUtils(Context base) {
super(base);
this.context = base;
createChannels();
}
public void createChannels() {
// create android channel
NotificationChannel androidChannel = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
androidChannel = new NotificationChannel(ANDROID_CHANNEL_ID,
context.getPackageName(), NotificationManager.IMPORTANCE_HIGH);
// Sets whether notifications posted to this channel should display notification lights
androidChannel.enableLights(false);
// Sets whether notification posted to this channel should vibrate.
androidChannel.enableVibration(false);
androidChannel.setVibrationPattern(new long[]{0});
// Sets the notification light color for notifications posted to this channel
androidChannel.setLightColor(Color.GREEN);
// Sets whether notifications posted to this channel appear on the lockscreen or not
androidChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
getManager().createNotificationChannel(androidChannel);
}
}
private NotificationManager getManager() {
if (mManager == null) {
mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
return mManager;
}
public Notification.Builder getAndroidChannelNotification(String title, String body, PendingIntent pendingIntent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return new Notification.Builder(getApplicationContext(), ANDROID_CHANNEL_ID)
.setContentTitle(title)
.setContentText(body)
.setContentIntent(pendingIntent)
.setSmallIcon(android.R.drawable.stat_notify_more)
.setWhen(System.currentTimeMillis())
.setOngoing(true)
.setChannelId(ANDROID_CHANNEL_ID)
.setAutoCancel(true);
}else{
return new Notification.Builder(getApplicationContext(), ANDROID_CHANNEL_ID);
}
}
@Override
public AMapLocationClient initGdlocation(Context context, AMapLocationClient client, AMapLocationListener listener,Notification notification) {
if(client == null){
client = new AMapLocationClient(context);
}
client.setLocationListener(listener);
if (Build.VERSION.SDK_INT >= 26 && notification != null) {
client.enableBackgroundLocation(Integer.valueOf(NotificationUtils.ANDROID_CHANNEL_ID), notification);// 调起前台定位
}
AMapLocationClientOption option = new AMapLocationClientOption();
//设置定位模式为AMapLocationMode.Hight_Accuracy,高精度模式。
option.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//设置定位间隔,单位毫秒,默认为2000ms,最低1000ms。
option.setInterval(2000);
//设置是否返回地址信息(默认返回地址信息)
option.setNeedAddress(true);
//设置是否允许模拟位置,默认为true,允许模拟位置
option.setMockEnable(true);
//关闭缓存机制
option.setLocationCacheEnable(false);
//设置GPS优先
option.setGpsFirst(false);
//设置定位场景,目前支持三种场景(签到、出行、运动,默认无场景)
option.setLocationPurpose(AMapLocationClientOption.AMapLocationPurpose.Sport);
client.setLocationOption(option);
//设置场景模式后最好调用一次stop,再调用start以保证场景模式生效
client.stopLocation();
client.startLocation();
return client;
}