Java Google calendar或Instagram是如何让他们的应用程序在强制停止后一直启动和运行的

Java Google calendar或Instagram是如何让他们的应用程序在强制停止后一直启动和运行的,java,android,android-service,alarmmanager,Java,Android,Android Service,Alarmmanager,看起来强制停止应该可以阻止应用程序运行,甚至可以禁用所有应用程序的警报。然而,我发现谷歌日历中的通知即使在强制停止后仍然显示良好,我一直看到Instagram应用程序在运行,即使我杀死它,它只是自动重新启动,并再次出现 那么,什么是让应用程序持续运行的方法呢?我正在使用提醒功能制作应用程序,需要在特定时间显示通知,而不管应用程序以前是如何关闭的。如果您在应用程序类中启动服务,则您的服务将始终运行,即使用户终止或从任务管理器强制停止,它也将再次运行 要在Android studio中专门创建服务,

看起来强制停止应该可以阻止应用程序运行,甚至可以禁用所有应用程序的警报。然而,我发现谷歌日历中的通知即使在强制停止后仍然显示良好,我一直看到Instagram应用程序在运行,即使我杀死它,它只是自动重新启动,并再次出现


那么,什么是让应用程序持续运行的方法呢?我正在使用提醒功能制作应用程序,需要在特定时间显示通知,而不管应用程序以前是如何关闭的。

如果您在应用程序类中启动服务,则您的服务将始终运行,即使用户终止或从任务管理器强制停止,它也将再次运行

要在Android studio中专门创建服务,请右键单击项目浏览器中的应用程序,然后单击新建>服务>服务

创建服务:

public class ServiceName extends Service {

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
      // do your jobs here
      return super.onStartCommand(intent, flags, startId);
        }
    } 
现在创建一个应用程序类并在应用程序类中启动服务

public class App extends Application {

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

        startService(new Intent(this, ServiceName.class));
    }
}  

我认为有两种选择

第一个是通过Java附带的任何异常处理,它不是来自Android SDK

简而言之,您可以使自定义的
应用程序
类实现
UncaughtExceptionHandler
,并将其注册为应用程序中任何异常的侦听器。一旦发生某些崩溃,将立即启动此回调,您可以在不久的将来延迟作业的发生(例如,spawn
AlarmManager
以在50毫秒内再次启动应用程序)


第二个选项是,您可以在不同的流程中启动组件。发件人:

android:process

要运行服务的进程的名称。通常,应用程序的所有组件都在为应用程序创建的默认进程中运行。它与应用程序包具有相同的名称。元素的流程属性可以为所有组件设置不同的默认值组件可以使用其自己的进程属性覆盖默认值,允许您将应用程序分布到多个进程


在不同进程上发生的崩溃不会使承载UI的进程崩溃。

对于初学者来说,他们有一个作业调度系统,可以调度要执行的作业,这些作业可以停止、启动或恢复。他们实现了一种检测崩溃的机制,比如java脚本,如果应用程序崩溃,它可以重新启动(nodemon或forever),在android中有服务,可以启动或恢复,有这种特殊的服务行为来重新启动崩溃的服务

START_REDELIVER_INTENT-告诉系统在崩溃后重新启动服务,并重新传递崩溃时出现的意图

Android 5.0棒棒糖(API 21)版本通过JobScheduler类引入了一个作业调度器API。此API允许在设备有更多可用资源时批处理作业。通常,此API可用于调度对用户来说不是时间关键的所有内容

您还可以混合使用警报、广播接收器和线程以及反应式编程来执行此项工作。警报(基于AlarmManager类)为您提供了在应用程序生命周期之外执行基于时间的操作的方法。例如,您可以使用警报启动长时间运行的操作,例如每天启动一次服务以下载天气预报


您可以将可观察对象附加到执行特定操作的特定任务,您可以实现异步i/o、计算操作,甚至“无限”通过设计自己的可观察数据流。

显示通知是Android服务的一项常见功能,如何防止服务停止/或强制关闭已经有很多问题

有关问题如下:

为了总结它们,第一步是实现一个监听
引导\u完成的
广播接收器。这意味着当Android设备打开时,您的服务将处于活动状态。为此,请在清单中放入以下代码:

<receiver android:name=".MyBootCompletedReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>
当您启动服务时,您可以返回,如果在资源有限的情况下被操作系统压扁,将通知Android操作系统重新启动服务:

public class MyLongRunningService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
        //inject dependencies if necessary
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        //setup, then
        return START_STICKY;
    }
}
一般来说,当设备资源不足时,应用程序启动的服务将被Android操作系统停止。返回
START\u STICKY
会告诉操作系统在必须停止服务时重新启动服务。因此,通过确保在设备打开时启动服务,以及在资源不足的情况下停止服务时请求重新启动服务,您已经创建了一个持续运行的服务

这是确保服务(以及应用程序)始终运行的最基本模式,这是您的需求


除此之外,您还可以采取其他措施,这些措施在此处的其他答案中有概述,但它们应被视为对实现在
BOOT\u COMPLETED
上启动并在资源不足的情况下停止时请求重新启动的服务的补充

再加上Sagar Damani的回答,在后台运行长时间的操作需要一个服务调用,但它们也在单独的进程中运行。在androidMenifes.xml中声明服务或活动时,还要添加android:process=”“属性。因此,如果用户杀死/强制停止活动,它将始终保持不变。

根据我的有限知识,您需要使用
AlarmManager
WakefulBroadcastReceiver
并为所有这些后台任务创建
服务
IntentService
。阅读更多关于它的信息。我有一个用于Firebase消息应用程序的服务,它甚至可以正常工作
public class MyBootCompletedReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Intent myService = new Intent(context, MyLongRunningService.class);
        context.startService(myService);
    }
}
public class MyLongRunningService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();
        //inject dependencies if necessary
    }

    public int onStartCommand(Intent intent, int flags, int startId) {
        //setup, then
        return START_STICKY;
    }
}
public class FirebaseHandler {

    private Context context;
    private static final long FIREBASE_ALARM_CYCLE_TIME = 300000;

    // constructors
    public FirebaseHandler(Context context) {
        this.context = context;
    }

    // set alarm
    public void setAlarm() {
        // create pending intent
        Intent intent = new Intent(context, AlarmReceiver.class);
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        final PendingIntent pendingIntent = PendingIntent.getBroadcast(
            context,
            AlarmReceiver.ALARM_REQUEST_CODE,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT);

        // create alarm
        AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarm.setInexactRepeating(
            AlarmManager.ELAPSED_REALTIME_WAKEUP,
            SystemClock.elapsedRealtime() + FIREBASE_ALARM_CYCLE_TIME,
            FIREBASE_ALARM_CYCLE_TIME,
            pendingIntent);
    }
}
public class AlarmReceiver extends WakefulBroadcastReceiver {

    public static final int ALARM_REQUEST_CODE = 12345;

    @Override
    public void onReceive(Context context, Intent wakefulIntent) {
        Intent intent = new Intent(context, FirebaseAlarmService.class);
        startWakefulService(context, intent);
    }
}
public class FirebaseAlarmService extends Service {

    private static final String CLASSNAME = FirebaseAlarmService.class.getSimpleName();
    private HandlerThread handlerThread;

    // onStartCommand
    @Override
    public int onStartCommand(final Intent intent, int flags, final int startId) {
        // start a new thread
        // this depends on your need. I need to do a continuous operation for some time
        // you can use IntentService too
        handlerThread = new HandlerThread(CLASSNAME);
        handlerThread.start();
        Handler handler = new Handler(handlerThread.getLooper());
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
            // all your codes here for the background task...

            // remember to release the wake lock and stop service 
            AlarmReceiver.completeWakefulIntent(wakefulIntent);
            stopSelf();
        } 
        return START_NOT_STICKY;
    }

    // this is the part that does the trick
    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        // when the service is killed, start it again
        new FirebaseHandler(getApplicationContext()).setAlarm();
    }

    // onDestroy
    @Override
    public void onDestroy() {
        super.onDestroy();
        // make sure to quit the thread
        handlerThread.quit();
    }
}
<uses-permission android:name="android.permission.WAKE_LOCK" />
<receiver
    android:name=".receiver.AlarmReceiver"
    android:process=":remote" />
public class BootBroadcastReceiver extends WakefulBroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent wakefulIntent) {
        // check if user is login, then set the alarm
        if (isLogin) {
            new FirebaseHandler(context).setAlarm();
        }

        // remove wake lock
        WakefulBroadcastReceiver.completeWakefulIntent(wakefulIntent);
    }
}
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".receiver.BootBroadcastReceiver">
    <intent-filter>
        <!-- get notified on reboot -->
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <!-- get notified on app updated -->
        <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
    </intent-filter>
</receiver>