4

基本上我有一个运行前台服务的应用程序。当我启动应用程序时,我需要在应用程序的onCreate方法中进行特定于会话的初始化。

当我关闭应用程序时,服务会继续运行(期望的行为),但是,当我从启动器/从我的通知中重新打开应用程序时,应用程序onCreate不会再次被调用。

我的问题是:

  1. onCreate即使有服务正在运行,如何强制再次调用应用程序?(服务可能会保留对应用程序对象的引用,对吧?)
  2. 有没有办法在 Application 类中获取应用程序已重新启动但来自服务的指示?
  3. 您还能想到哪些其他解决方案?

我的服务在AndroidManifest.xml

<service android:name=".MyService"
    android:exported="false"/>

我的服务onStartCommand

    createNotificationChannel();
    Intent notificationIntent = new Intent(this, MyActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("My Service")
            .setContentText("Service")
            .setSmallIcon(R.drawable.ic_android)
            .setContentIntent(pendingIntent)
            .build();
    startForeground(1, notification);
4

5 回答 5

1

您可以创建一个ProcessLifeCycleOwner内部Application并监听生命周期事件。您可能还需要为一个类设置一个标志并从一个方法中获取该值,以检查用户是否在按下主页按钮或使用通知启动应用程序后返回

class MyApp: Application() {

    override fun onCreate() {
        super.onCreate()

        ProcessLifecycleOwner
            .get()
            .lifecycle
            .addObserver(ApplicationObserver())
    }

    inner class ApplicationObserver : LifecycleObserver {

        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        fun onStop() {
        }

        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        fun onStart() {

        }

        @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
        fun onCreate() {

        }


        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun onDestroy() {

        }
    }
}
于 2020-06-30T15:58:50.010 回答
0

Application对象是一个单例。它在创建托管您的应用程序的操作系统进程时被实例化(并被onCreate()调用)。如果您的应用程序托管一个前台Service,那么该操作系统进程将继续存在,因此Application.onCreate()不会被调用。

我不清楚为什么需要调用它,但是您可以在与应用程序的其他组件( , , )Service不同的操作系统进程中运行。在这种情况下,托管前台的操作系统进程将不会被重新创建,但托管您的活动的操作系统进程将被重新创建(如果它被 Android 杀死,如果其中没有运行活动组件,通常会发生这种情况)。由于对象存在于每个 OS 进程中,当重新创建承载活动的 OS 进程时,Android 将实例化一个新对象并在此时调用它。ActivityBroadcastReceiverProviderServiceApplicationApplicationonCreate()

Service在不同的操作系统进程中运行,只需将其添加到<service>清单中的标记中:

android:process=":remote"

注意:您可以使用任何您想要的名称来代替“remote”,只要确保它以冒号(“:”)开头

警告:您需要知道您的应用程序有 2 个操作系统进程并相应地进行计划。在这 2 个进程中运行的代码无法互相看到,因此这可能会导致您的应用出现其他问题。Service您在组件(例如和)之间共享的任何数据Activity都需要放入数据库或共享首选项或其他某种机制中,以便在操作系统进程之间共享它。

于 2020-06-28T23:33:05.730 回答
0

我建议您创建一个包含您的初始化代码的实用程序函数。使用标志查看是否需要运行操作,如果设置了此标志,则不执行任何操作。

由于您遇到的确切问题,请从您的基本活动(而不是应用程序)调用它。它还允许在初始化期间向用户提供反馈。

用户退出后清除标志。

因此,基本上,将您的代码移动到可以一致调用的地方。

于 2020-06-30T10:26:32.743 回答
0

找到找到应用程序启动的方法(至少是第一个活动启动),然后根据需要在onCreate(). 我面临和你一样的情况,应用程序在启动和离开时必须做一些事情。我创建了一个界面来监听应用程序进入前台和后台模式(没有正在运行的活动):

interface IApplicationLifeCycle {
    fun onEnterForeground()
    fun onEnterBackground()
    fun onFirstCreated()
    fun onLastDestroyed()
}

然后我创建一个类来检测应用程序正在进入后台和前台

class AppLifeCycleTracker(private val iApplicationLifeCycle: IApplicationLifeCycle? = null) : Application.ActivityLifecycleCallbacks {
private var aliveActivityCount = 0 // created on destroyed
private var activeActivityCount = 0 // started on stopped
private var liveActivityCount = 0 // resumed on paused

override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
    aliveActivityCount++
    if (aliveActivityCount == 1) {
        iApplicationLifeCycle?.onFirstCreated()
    }
}

override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}

override fun onActivityStarted(activity: Activity) {
    activeActivityCount++
}

override fun onActivityResumed(activity: Activity) {
    liveActivityCount++
    if (liveActivityCount == 1 && activeActivityCount == 1) {
        iApplicationLifeCycle?.onEnterForeground()
    }
}

override fun onActivityPaused(activity: Activity) {
    liveActivityCount--
}

override fun onActivityStopped(activity: Activity) {
    activeActivityCount--
    if (liveActivityCount == 0 && activeActivityCount == 0) {
        iApplicationLifeCycle?.onEnterBackground()
    }
}

override fun onActivityDestroyed(activity: Activity) {
    aliveActivityCount--
    if (aliveActivityCount == 0) {
        iApplicationLifeCycle?.onLastDestroyed()
    }
}

}

在我的申请中

class MyApplication: IApplicationLifeCycle{

    onCreate() {
        super.onCreate() 
        registerActivityLifecycleCallbacks(AppLifeCycleTracker(this))
    }

    override fun onEnterForeground() {
        Log.i("AppVisibility", "onEnterForeground")
        // do action here
    }

    ...
    ...
    ...
}

在被覆盖的方法上,onEnterForeground只做你想做的动作,在这种情况下,你想做一些初始化

于 2020-06-30T16:35:29.083 回答
-2

onCreate 事件在对象创建期间触发。之后有onStart。如果应用程序已关闭,则该对象在内存中仍处于活动状态,如果设备需要更多可用资源,该对象将被销毁。因此,如果您重新打开应用程序,只会触发 onStart 事件。尝试在 onStart 中移动初始化,或者在 onStart 中打勾或类似。

活动的生命周期 https://developer.android.com/guide/components/activities/activity-lifecycle

于 2020-06-21T10:29:12.870 回答