android 服务始终 运行 并在需要时通知用户

android service always running and notify user when needed

我需要一项服务,当用户在移动的汽车中时发出通知。 我使用 ActivityRecognition 来查明用户何时处于 car.the 问题是我需要我的服务 运行 即使应用程序被用户销毁或删除也是如此。 我尝试 运行 在不同的进程上连接服务,但几分钟后服务停止 working.I 也尝试使用前台服务,但我遇到了同样的问题。

这是我的服务class。

public class SpeedCheckerService extends Service {
    private final String CHANNEL_ID = "my_channel";

    private static SpeedCheckerService speedCheckerService;
    private ActivityRecognitionClient mActivityRecognitionClient;
    private boolean started = false;
    Date lastNotification;
    CountDownTimer countDownTimer;
    Intent intent;


    @Override
    public void onCreate() {
        createNotificationChannel();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        this.intent=intent;
        countDownTimer = new CountDownTimer(99999999,1000 * 60 * 1) {
            @Override
            public void onTick(long l) {
                recognizeActivity();
            }

            @Override
            public void onFinish() {
                countDownTimer.start();
            }
        }.start();
        return START_STICKY;
    }

    String detectedActivitiesToJson(ArrayList<DetectedActivity> detectedActivitiesList) {
        Type type = new TypeToken<ArrayList<DetectedActivity>>() {}.getType();
        System.out.println(detectedActivitiesList.toString());
        if ((detectedActivitiesList.size()>=1)&&(detectedActivitiesList.get(0).getType() == DetectedActivity.STILL) && (detectedActivitiesList.get(0).getConfidence()) >= 60){
            if(lastNotification!=null){
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(lastNotification);
                calendar.add(Calendar.MINUTE,5);
                Date newDate = calendar.getTime();
                calendar.clear();
                System.out.println(lastNotification.toString());
                System.out.println(newDate.toString());
                if(newDate.after(calendar.getTime()) == true)
                return null;
            }
            speedCheckerService.makeNotification();
            lastNotification = Calendar.getInstance().getTime();
        }
        return new Gson().toJson(detectedActivitiesList, type);
    }

    public void makeNotification() {
        createNotificationChannel();
        Intent intent = new Intent(this, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
                .setContentTitle("title")
                .setContentText("text")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setContentIntent(pendingIntent)
                .setSmallIcon(R.drawable.mapbox_logo_icon)
                .setColor(Color.parseColor("#00ff00"))
                .setAutoCancel(true);
        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
        notificationManager.notify(70, builder.build());
    }

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "guardian";
            String description = "alerting user";
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
            channel.setDescription(description);
            NotificationManager notificationManager = getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }

    public void recognizeActivity() {
        if((mActivityRecognitionClient==null)&&(!started))

        {
            mActivityRecognitionClient = new ActivityRecognitionClient(this);
            mActivityRecognitionClient.requestActivityUpdates(0, PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
            started = true;
        }

        speedCheckerService =this;

        if(ActivityRecognitionResult.hasResult(intent))

        {
            ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
            ArrayList<DetectedActivity> detectedActivities = (ArrayList) result.getProbableActivities();
            detectedActivitiesToJson(detectedActivities);
        }
    }

}

如果你能帮助我解决我的问题,我将不胜感激

如果您需要服务,您应该使用前台服务运行即使您的应用程序处于后台或已关闭

https://androidwave.com/foreground-service-android-example/

使用前台服务而不是普通服务并进行以下更改

public class SampleService extends Service {

  
    private NotificationManager mNotificationManager;
    /**
     * The identifier for the notification displayed for the foreground service.
     */
    private static final int NOTIFICATION_ID = 1231234;
   

    static void startService(Context context, String message) {
        Intent startIntent = new Intent(context, SampleService.class);
        startIntent.putExtra("inputExtra", message);
        ContextCompat.startForegroundService(context, startIntent);

    }

    static void stopService(Context context) {
        Intent stopIntent = new Intent(context, SampleService.class);
        context.stopService(stopIntent);
    }

    private void createNotificationChannel() {
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            CharSequence name = "Sample Notification";
            // Create the channel for the notification
            NotificationChannel mChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name,
                    NotificationManager.IMPORTANCE_DEFAULT);
            mChannel.setSound(null, null);
            // Set the Notification Channel for the Notification Manager.
            notificationManager.createNotificationChannel(mChannel);
        }
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d("Service", "onCreate");
        createNotificationChannel();
        mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
      
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("Service", "onStartCommand");
     
        startForeground(NOTIFICATION_ID, getNotification(message);
       
       **// This is important, When your service got killed it will try to restart //the service. But some android vendor phones are restricted this autostart**

        return START_REDELIVER_INTENT;
    }

    @Override
    public void onDestroy() {
     
        super.onDestroy();

        Log.d("Service", "Service Destroyed");
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        Log.e("Service", "onTaskRemoved");
        super.onTaskRemoved(rootIntent);
    }

    private Notification getNotification(String contentMessage) {
        String title = getString(R.string.notification_title,
                DateFormat.getDateTimeInstance().format(new Date()));
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this,
                NOTIFICATION_CHANNEL_ID).setContentTitle(title).setContentText(contentMessage)
                .setSmallIcon(R.drawable.notification)
                .setOngoing(true)
                .setPriority(Notification.PRIORITY_MAX)
                .setTicker(contentMessage)
                .setAutoCancel(false)
                .setWhen(System.currentTimeMillis());
        return builder.build();
    }  
          
    /**
     * Returns true if this is a foreground service.
     *
     * @param context The {@link Context}.
     */
    public boolean serviceIsRunningInForeground(Context context) {
        ActivityManager manager = (ActivityManager) context.getSystemService(
                Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(
                Integer.MAX_VALUE)) {
            if (getClass().getName().equals(service.service.getClassName())){
                if (service.foreground){
                    return true;
                }
            }
        }
        return false;
    }
}