代码之家  ›  专栏  ›  技术社区  ›  KOB

Oreo-在前台启动服务

  •  9
  • KOB  · 技术社区  · 8 年前

    我创建了一个服务,在设备移动时跟踪其位置。服务由绑定到它的活动启动,在该活动中有一个“开始跟踪”按钮。当按下这个按钮时,我需要该服务在前台启动,以便它存储设备移动到的位置,即使绑定到它的活动已关闭,或者应用程序已最小化。

    我理解,为了使服务处于前台,必须显示通知。我已经尝试过这样做,但当活动被破坏时,我无法在前台显示通知或服务。

    由于通知渠道的原因,Oreo中的通知似乎发生了变化,但我不知道需要做哪些不同的事情。我正在测试的设备是8.0.0版本。

    这是mys服务:

    public class LocationTrackerService extends Service {
    
        private LocationListener locationListener;
        private LocationManager locationManager;
        private IBinder binder = new LocalBinder();
        private boolean isTracking;
        private ArrayList<Location> trackedWaypoints;
        private String bestProvider;
        private Timer timer;
        private Distance distance;
    
        @SuppressLint("MissingPermission")
        @Override
        public void onCreate() {
            super.onCreate();
    
            locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
            Criteria criteria = new Criteria();
            bestProvider = locationManager.getBestProvider(criteria, true);
    
            isTracking = false;
    
            locationListener = new LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    Intent intent = new Intent("location_update");
                    intent.putExtra("latitude", location.getLatitude());
                    intent.putExtra("longitude", location.getLongitude());
                    sendBroadcast(intent);
                    if (isTracking) {
                        if (trackedWaypoints.size() > 1) {
                            distance.add(trackedWaypoints.get(trackedWaypoints.size() - 1).distanceTo(location));
                        }
                        trackedWaypoints.add(location);
                    }
                }
    
                @Override
                public void onStatusChanged(String s, int i, Bundle bundle) { }
    
                @Override
                public void onProviderEnabled(String s) { }
    
                @Override
                public void onProviderDisabled(String s) {
                    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                }
            };
    
            locationManager.requestLocationUpdates(bestProvider, 0, 0, locationListener);
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            if (locationManager != null) {
                locationManager.removeUpdates(locationListener);
            }
        }
    
        public void startTracking() {
            trackedWaypoints = new ArrayList<Location>();
            timer = new Timer();
            distance = new Distance();
            timer.start();
            isTracking = true;
            startInForeground();
        }
    
        private void startInForeground() {
            Intent notificationIntent = new Intent(this, WorkoutActivity.class);
            PendingIntent pendingIntent =
                    PendingIntent.getActivity(this, 0, notificationIntent, 0);
    
            Notification notification =
                    new Notification.Builder(this)
                            .setContentTitle("TEST")
                            .setContentText("HELLO")
                            .setSmallIcon(R.drawable.ic_directions_run_black_24dp)
                            .setContentIntent(pendingIntent)
                            .setTicker("TICKER")
                            .build();
    
            startForeground(101, notification);
        }
    
        public void stopTracking() {
            isTracking = false;
            stopForeground(true);
        }
    
        public boolean isTracking() {
            return isTracking;
        }
    
        public ArrayList<Location> getTrackedWaypoints() {
            return trackedWaypoints;
        }
    
        public Timer getTime() {
            timer.update();
            return timer;
        }
    
        public Distance getDistance() {
            return distance;
        }
    
        public int getSteps() {
            return 0;
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    
        public class LocalBinder extends Binder {
            public LocationTrackerService getLocationTrackerInstance() {
                return LocationTrackerService.this;
            }
        }
    }
    
    2 回复  |  直到 8 年前
        1
  •  19
  •   colens    8 年前

    尝试使用以下代码更改startInForeground()方法:

    private void startInForeground() {
            Intent notificationIntent = new Intent(this, WorkoutActivity.class);
            PendingIntent pendingIntent=PendingIntent.getActivity(this,0,notificationIntent,0);
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this,NOTIFICATION_CHANNEL_ID)
                    .setSmallIcon(R.drawable.shsl_notification)
                    .setContentTitle("TEST")
                    .setContentText("HELLO")
                    .setTicker("TICKER") 
                    .setContentIntent(pendingIntent);
            Notification notification=builder.build();
            if(Build.VERSION.SDK_INT>=26) {
                NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
                channel.setDescription(NOTIFICATION_CHANNEL_DESC);
                NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                notificationManager.createNotificationChannel(channel);
            }
            startForeground(NOTIFICATION_ID, notification);
    }
    

    所以,当你的Android版本是Oreo(或更高版本)时,会创建通知通道,否则不会。

        2
  •  2
  •   mac229    8 年前

    在显示通知之前,您必须创建通知通道:

    private void createNotificationChannel() {
        if (Build.VERSION_CODES.O <= Build.VERSION.SDK_INT) {
            NotificationChannel notificationChannel =
                    new NotificationChannel(PRIMARY_CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
            notificationManager.createNotificationChannel(notificationChannel);
        }
    }
    

    然后更改创建通知生成器

    new Notification.Builder(context, PRIMARY_CHANNEL_ID)