1

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

我知道,要将服务置于前台,必须显示通知。我试图这样做,但是当活动被破坏时,我无法获得通知显示或服务在前台工作。

由于通知渠道,看起来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; 
     } 
    } 
} 
+0

你似乎没有调用'startTracking()'。 – CommonsWare

+0

当按钮被按下时,它从活动中调用。 – KOB

+0

如果您的'targetSdkVersion'为26或更高,则需要定义通知通道(如果您之前没有定义),并在构建器中使用该通道ID。你也可以考虑切换到'NotificationCompat.Builder'。 – CommonsWare

回答

4

试图改变自己使用此代码的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版本是奥利奥(或更高版本)通知通道将被创建,否则不会。

+0

感谢它的工作,对代码进行了小幅更新,而不是使用26,您可以使用Build.VERSION_CODES.O,这会增加代码的可读性。 –

1

节目的通知之前,你必须创建通知通道:

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)