I need a service to make a notification whenever the user is in a moving car. I use ActivityRecognition to find out when the user is in a car.the issue is I need my service to run even when the app is destroyed or removed by the user. I tried running the service on a different process but after a few minutes the service stops working.I also tried using foreground service but I had the same issue with that to.
this is my service 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);
}
}
}
I would greatly appreciate if you can help me with my problem
Use foreground service instead of normal service and do the below changes
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;
}
}