安卓服务始终运行,并在需要时通知用户。

huangapple go评论79阅读模式
英文:

android service always running and notify user when needed

问题

以下是你提供的代码部分的中文翻译:

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 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 = &quot;my_channel&quot;;
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&lt;DetectedActivity&gt; detectedActivitiesList) {
Type type = new TypeToken&lt;ArrayList&lt;DetectedActivity&gt;&gt;() {}.getType();
System.out.println(detectedActivitiesList.toString());
if ((detectedActivitiesList.size()&gt;=1)&amp;&amp;(detectedActivitiesList.get(0).getType() == DetectedActivity.STILL) &amp;&amp; (detectedActivitiesList.get(0).getConfidence()) &gt;= 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(&quot;title&quot;)
.setContentText(&quot;text&quot;)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setSmallIcon(R.drawable.mapbox_logo_icon)
.setColor(Color.parseColor(&quot;#00ff00&quot;))
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(70, builder.build());
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.O) {
CharSequence name = &quot;guardian&quot;;
String description = &quot;alerting user&quot;;
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)&amp;&amp;(!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&lt;DetectedActivity&gt; detectedActivities = (ArrayList) result.getProbableActivities();
detectedActivitiesToJson(detectedActivities);
}
}
}

I would greatly appreciate if you can help me with my problem

答案1

得分: 0

你应该使用前台服务(Foreground Service),如果你想让服务在你的应用处于后台或已关闭状态时仍然运行。

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

英文:

You should use Foreground Service if you want service running even your app is in background or closed

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

答案2

得分: 0

使用前台服务代替普通服务,并进行以下更改:

public class SampleService extends Service {

    private NotificationManager mNotificationManager;
    /**
     * 用于前台服务显示通知的标识符。
     */
    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";
            // 创建通知渠道
            NotificationChannel mChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, name,
                    NotificationManager.IMPORTANCE_DEFAULT);
            mChannel.setSound(null, null);
            // 为通知管理器设置通知渠道。
            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");
        String message = intent.getStringExtra("inputExtra");
        startForeground(NOTIFICATION_ID, getNotification(message));
       
       // 这很重要,当您的服务被终止时,它将尝试重新启动服务。
       // 但是一些 Android 厂商的手机限制了此自动启动的行为。
       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();
    }  
    
    /**
     * 如果这是前台服务,则返回 true。
     *
     * @param context {@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;
    }
}
英文:

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(&quot;inputExtra&quot;, 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 &gt;= Build.VERSION_CODES.O){
CharSequence name = &quot;Sample Notification&quot;;
// 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(&quot;Service&quot;, &quot;onCreate&quot;);
createNotificationChannel();
mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(&quot;Service&quot;, &quot;onStartCommand&quot;);
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(&quot;Service&quot;, &quot;Service Destroyed&quot;);
}
@Override
public void onTaskRemoved(Intent rootIntent) {
Log.e(&quot;Service&quot;, &quot;onTaskRemoved&quot;);
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;
}
}

huangapple
  • 本文由 发表于 2020年9月17日 13:01:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/63931542.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定