1

私は、移動する際にデバイスの位置を追跡するサービスを作成しました。サービスは、そのサービスにバインドされているアクティビティによって開始され、このアクティビティには「追跡開始」ボタンがあります。このボタンを押すと、フォアグラウンドでサービスを開始する必要があります。サービスがバインドされているアクティビティが閉じられていたり、アプリケーションが最小化されていても、デバイスが移動した場所が保存されます。Oreo - フォアグラウンドでサービスを開始する

私は、サービスがフォアグラウンドにあるため、通知を表示する必要があることを理解します。私はそうしようとしましたが、アクティビティが破棄されたときに、表示する通知やフォアグラウンドで作業するサービスを取得できません。

通知チャンネルのためにOreoで通知が変更されたように見えますが、何が違うのかを判断することはできません。私がこれをテストしているデバイスは8.0.0です。あなたは通知チャネル作成する必要がショーの通知前に

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

通知ビルダーを作成する変更があなたを変更してみます。ここ

はMYSサービスですこのコードの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(またはそれ以上)の場合、通知チャンネルが作成されます。

+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) 
関連する問題