Android 即使用户强制关闭服务,如何自动重启服务?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21550204/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:44:11  来源:igfitidea点击:

How to automatically restart a service even if user force close it?

androidservicealarm

提问by Vipul J

I want a service to run all the time in my application. So I want to restart it even if it is force closed by user. There is definitely a way to do it as apps like facebook are doing it.(Its not done using push notification, facebook restarts its service even if internet is off).

我想要一个服务在我的应用程序中一直运行。所以我想重新启动它,即使它被用户强制关闭。肯定有办法做到这一点,因为像 facebook 这样的应用程序正在这样做。(它不是使用推送通知完成的,即使互联网关闭,facebook 也会重新启动其服务)。

Any help would be appreciated. Thanks!

任何帮助,将不胜感激。谢谢!

回答by Mehul Joisar

First of all, it is really very bad patternto run service forcefully against the user's willingness.

首先,违背用户意愿强行运行服务是非常糟糕的模式

Anyways, you can restart it by using a BroadcastReceiverwhich handles the broadcast sent from onDestroy()of your service.

无论如何,您可以通过使用BroadcastReceiver处理从onDestroy()您的服务发送的广播来重新启动它。

StickyService.java

粘滞服务

public class StickyService extends Service
{
    private static final String TAG = "StickyService";


    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        sendBroadcast(new Intent("YouWillNeverKillMe"));
    }

}

RestartServiceReceiver.java

重启ServiceReceiver.java

public class RestartServiceReceiver extends BroadcastReceiver
{

    private static final String TAG = "RestartServiceReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e(TAG, "onReceive");
    context.startService(new Intent(context.getApplicationContext(), StickyService.class));

    }

}

Declare the components in manifestfile:

在清单文件中声明组件

    <service android:name=".StickyService" >
    </service>

    <receiver android:name=".RestartServiceReceiver" >
        <intent-filter>
            <action android:name="YouWillNeverKillMe" >
            </action>
        </intent-filter>
    </receiver>

Start the StickyServicein a Component (i.e. Application, Activity, Fragment):

StickyService在组件中启动(即Application, Activity, Fragment):

startService(new Intent(this, StickyService.class));

OR

或者

sendBroadcast(new Intent("YouWillNeverKillMe"));

回答by Govind

You have to create a sticky servicewith overriding onTaskRemovedmethod, where you can set an alarm service to trigger your code again.

您必须创建一个sticky service覆盖onTaskRemoved方法,您可以在其中设置警报服务以再次触发您的代码。

public class BackgroundService extends Service {

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        //create an intent that you want to start again.
        Intent intent = new Intent(getApplicationContext(), BackgroundService.class);
        PendingIntent pendingIntent = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_ONE_SHOT);
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 5000, pendingIntent);
        super.onTaskRemoved(rootIntent);
    }
}

Also in some devices like Xiaomi, Huwaei the app gets force closed once it's removed from recent apps. This is because the manufacturers have task manager features which improve ram/battery performance.

同样在小米、华为等一些设备中,一旦从最近的应用程序中删除该应用程序,它就会被强制关闭。这是因为制造商具有可提高内存/电池性能的任务管理器功能。

You can check this link for more information: https://stackoverflow.com/a/41360159/2798289

您可以查看此链接以获取更多信息:https: //stackoverflow.com/a/41360159/2798289

回答by Zohra Khan

As per the Android document

根据 Android 文档

Starting from Android 3.1, the system's package manager keeps track of applications 
that are in a stopped state and provides a means of controlling their launch from 
background processes and other applications.

Note that an application's stopped state is not the same as an Activity's stopped
state. The system manages those two stopped states separately.
FLAG_INCLUDE_STOPPED_PACKAGES — Include intent filters of stopped applications in the
list of potential targets to resolve against.

FLAG_EXCLUDE_STOPPED_PACKAGES — Exclude intent filters of stopped applications from the
list of potential targets.

When neither or both of these flags is defined in an intent, the default behavior is to
include filters of stopped applications in the list of potential targets. 

Note that the system adds FLAG_EXCLUDE_STOPPED_PACKAGES to all broadcast intents.
It does this to prevent broadcasts from background services from inadvertently or
unnecessarily launching components of stopped applications. A background service 
or application can override this behavior by adding the FLAG_INCLUDE_STOPPED_PACKAGES
flag to broadcast intents that should be allowed to activate stopped applications.

On Force stop of app, Android just kill the process ID. No warnings, callbacks are given to service/activities. As per the Android document, When the app is killed there are chances that it calls onPause().

在强制停止应用程序时,Android 只会终止进程 ID。没有警告,对服务/活动进行回调。根据 Android 文档,当应用程序被终止时,它可能会调用 onPause()。

When I tried in my app, even onPause() was not called. I think the only way is use to FLAG_INCLUDE_STOPPED_PACKAGESintent flag and send it from another app

当我在我的应用程序中尝试时,甚至没有调用 onPause() 。我认为唯一的方法是使用FLAG_INCLUDE_STOPPED_PACKAGES意图标记并从另一个应用程序发送它

回答by Atish Agrawal

Whenever a service is killed, its onDestroymethod is always called. Its better to use a BroadcastReceiverto start your service when it is killed.

每当服务被终止时,它的onDestroy方法总是被调用。当它被杀死时,最好使用BroadcastReceiver来启动你的服务。

Here is a sample code illustrating its implementation:-

这是一个说明其实现的示例代码:-

@Override
public void onDestroy() {
Intent in = new Intent();
in.setAction("StartkilledService");
sendBroadcast(in);
Log.d("debug", "Service Killed");
}

Then register a receiver in AndroidManifest.xml:-

然后在AndroidManifest.xml以下位置注册接收器:-

<receiver android:name=".app.ServiceDestroyReceiver" >
    <intent-filter>
        <action android:name="StartKilledService" >
        </action>
    </intent-filter>
</receiver>

Finally,create a BroadcastReceiver,and start your service in the onReceivemethod:-

最后,创建一个BroadcastReceiver,并在onReceive方法中启动您的服务:-

@Override
public void onReceive(Context context, Intent intent) {
Log.d("debug", "ServeiceDestroy onReceive...");
Log.d("debug", "action:" + intent.getAction());
Log.d("debug", "Starting Service");
ServiceManager.startService();
}

Hope this helps.

希望这可以帮助。

回答by Bijesh

on the service's startCommand method return START_STICKY. generally it tell the OS to start the service when it is killed.

在服务的 startCommand 方法上返回 START_STICKY。通常它告诉操作系统在它被杀死时启动服务。

回答by marcinj

If I understand correctly, then actually this is not possible, Android feature to force close application was designed to allow user to get rid of unwanted applications, so it disallows any activities from it until user again starts any of its Activity.

如果我理解正确,那么实际上这是不可能的,Android 强制关闭应用程序的功能旨在允许用户摆脱不需要的应用程序,因此它禁止任何活动,直到用户再次启动其任何活动。

Restart the service even if app is force-stopped and Keep running service in background even after closing the app How?

即使应用程序被强制停止,也要重新启动服务,即使关闭应用程序,也要在后台继续运行服务 如何?

回答by da_berni

The only real solution for keeping services alive ist to call Service.startForeground(...)with a provided Notification. This will be the only valid solution, every other one will be very dependent on how Google will change the behaviour of it's system. With every API update, Google could prevent every other hack.

保持服务活跃的唯一真正解决方案是Service.startForeground(...)使用提供的通知进行调用。这将是唯一有效的解决方案,其他所有解决方案都非常依赖于 Google 如何改变其系统的行为。通过每次 API 更新,Google 可以防止其他所有黑客攻击。

This also keeps the user aware, that your app is performing some background task which will keep the app alive and the user has to stop this. If you provide the user the ability to stop it is part of your application, though.

这也让用户意识到你的应用程序正在执行一些后台任务,这将使应用程序保持活动状态,用户必须停止它。但是,如果您为用户提供停止它的能力是您的应用程序的一部分。

See the Documentation:

请参阅文档:

void startForeground (int id, Notification notification)

Make this service run in the foreground, supplying the ongoing notification to be shown to the user while in this state. By default services are background, meaning that if the system needs to kill them to reclaim more memory (such as to display a large page in a web browser), they can be killed without too much harm. You can set this flag if killing your service would be disruptive to the user, such as if your service is performing background music playback, so the user would notice if their music stopped playing.

使此服务在前台运行,在此状态下提供要向用户显示的正在进行的通知。默认情况下服务是后台的,这意味着如果系统需要杀死它们以回收更多内存(例如在 Web 浏览器中显示大页面),它们可以被杀死而不会造成太大伤害。如果终止您的服务会对用户造成干扰,例如您的服务正在播放背景音乐,您可以设置此标志,这样用户就会注意到他们的音乐是否停止播放。

回答by OGP

If the situation allows to use 'root' it's usually possible to implement Humpty-Dumpty paradigm.

如果情况允许使用“root”,通常可以实现 Humpty-Dumpty 范式。

Your application (1st) installs another application (2nd, taking APK from assets) and runs the service of the 2nd app. 2nd app's service bind to the 1st app service and rebinds when disconnected. The 1st app does the same.

您的应用程序(第一个)安装另一个应用程序(第二个,从资产中获取 APK)并运行第二个应用程序的服务。第二个应用程序的服务绑定到第一个应用程序服务并在断开连接时重新绑定。第一个应用程序做同样的事情。

Sure it will not help when all apps are killed by some Free RAM or similar application but when Android kills either of those two, the other one will restart its counterpart.

当然,当所有应用程序都被一些可用 RAM 或类似应用程序杀死时,这将无济于事,但是当 Android 杀死这两个应用程序中的任何一个时,另一个将重新启动其对应的应用程序。

回答by Nami

There is a very hacky solution to keep service running even you force stop it. I do not recommend that because it is against user willingness. You can define a broadcast receiver to receive intent with action X. onStartCommand handler of your service, broadcast X (if the service is not started yet). on broadcast receiver upon receipt of X, first start the service, then, sleep for some minutes, and finally re-broadcast X.

有一个非常hacky的解决方案,即使你强行停止它也能保持服务运行。我不建议这样做,因为这违背了用户的意愿。您可以定义一个广播接收器来接收带有操作 X 的意图。您的服务的 onStartCommand 处理程序,广播 X(如果服务尚未启动)。在广播接收器上收到 X,首先启动服务,然后休眠几分钟,最后重新广播 X。

回答by Megakoresh

I think the only foolproof solution here is to have 2 services in separate processes (android:process="somecustomprocessname"in manifest, in the service entry) that both listen to broadcasts and restart each other, because currently the UI doesn't let users kill multiple processes in one action. You can then set up a pinger thread in each service that checks if the other service is running every 100 milliseconds or so, and if not, attempts to restart it. But this is starting to look more and more like malware...

我认为这里唯一万无一失的解决方案是在单独的进程中(android:process="somecustomprocessname"在清单中,在服务条目中)有 2 个服务,它们都侦听广播并相互重启,因为目前用户界面不允许用户在一个操作中杀死多个进程。然后,您可以在每个服务中设置一个 pinger 线程,以每 100 毫秒左右检查其他服务是否正在运行,如果没有,则尝试重新启动它。但这开始看起来越来越像恶意软件......