【问题标题】:How to automatically restart a service even if user force close it?即使用户强制关闭服务,如何自动重启服务?
【发布时间】:2014-02-28 06:54:08
【问题描述】:

我希望服务始终在我的应用程序中运行。所以我想重新启动它,即使它被用户强制关闭。绝对有办法做到这一点,因为像 facebook 这样的应用程序正在这样做。使用推送通知没有完成,即使互联网关闭,facebook也会重新启动其服务。

【问题讨论】:

  • 你在使用后台服务吗...
  • 创建另一个服务,它将启动第一个服务,或者创建一个接收器,在任何事件中检查该服务是否可用,如果不可用,它将启动它。
  • 您可能希望您的服务一直运行,但您的用户强制关闭它的事实意味着他们没有。如果该应用是供公众使用的,请重新考虑此要求
  • 哪个答案最终解决了您的问题?
  • 你解决了吗?

标签: android service alarm


【解决方案1】:

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

无论如何,您可以使用BroadcastReceiver 重新启动它,该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

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));

    }

}

在清单文件中声明组件:

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

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

在组件中启动StickyService(即ApplicationActivityFragment):

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

sendBroadcast(new Intent("YouWillNeverKillMe"));

【讨论】:

  • 据我所知,如果用户强制停止应用程序 BroadcastReceivers 将不再工作
  • @sjkm 这不是电池杀手吗?
  • 当用户强制关闭应用程序时不起作用。 onDestroy 未被调用。
  • "首先,违背用户意愿强行运行服务确实是非常糟糕的模式。" -> 这就是谷歌一直在做的事情......
  • 在一些手机,如小米和vivo,我们必须更改设置,并赋予应用特殊权限,以便从设置应用在后台运行。即使您设置了在应用关闭时自动重启的服务,该服务也不会运行,除非您在手机的设置应用中设置权限。
【解决方案2】:

您必须创建一个 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);
    }
}

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

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

【讨论】:

    【解决方案3】:

    根据 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.
    

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

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 它是,正如我提到的其他应用程序正在这样做
      • 看来奇巧在这件事上带来了一些变化,看这里:groups.google.com/forum/#!topic/android-developers/H-DSQ4-tiac。作者的解决方法是:“我使用的解决方法非常简单:我从 onTaskRemoved 创建一个透明的活动来重新启动我的服务。它有多脏?”
      【解决方案5】:

      每当一个服务被杀死时,它的onDestroy 方法总是被调用。 最好使用 BroadcastReceiver 在服务被杀死时启动它。

      下面是一个示例代码来说明它的实现:-

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

      然后在AndroidManifest.xml注册一个receiver:-

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

      最后,创建一个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();
      }
      

      希望这会有所帮助。

      【讨论】:

      • onDestroy() 不会每次都被调用。试过了。
      • 如果你强制停止你的服务,进程会立即被杀死,并且不会向它发送回调。所以 onDestroy 没有被调用。
      • 在应用程序被终止时调用 stopService(即在应用程序的 onDestroy 方法上)。这将工作
      • "每当一个服务被杀死时,它的 onDestroy 方法总是被调用。" - 这是一个谎言
      【解决方案6】:

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

      【讨论】:

      • 这行得通,它是 android 杀死服务,而不是当我们强制关闭它时。
      【解决方案7】:

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

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

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

      【讨论】:

      • github.com/sms2000/GPSToggler3
      • 这是 2020 年可行的解决方案吗?
      【解决方案8】:

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

      这也让用户知道,您的应用正在执行一些后台任务,这将使应用保持活动状态,用户必须停止此操作。但是,如果您向用户提供停止它的能力,则属于您的应用程序的一部分。

      See the Documentation:

      void startForeground (int id, Notification notification)
      

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

      【讨论】:

        【解决方案9】:

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

        【讨论】:

          【解决方案10】:

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

          【讨论】:

          • 这是从第一天开始的恶意软件。你根本不应该那样做。使用前台服务进行长期后台工作。
          • @da_berni 我认为人们应该在投票之前阅读问题、回复和日期。
          猜你喜欢
          • 2011-11-07
          • 2015-09-18
          • 1970-01-01
          • 1970-01-01
          • 2013-11-15
          • 1970-01-01
          • 1970-01-01
          • 2017-12-29
          • 1970-01-01
          相关资源
          最近更新 更多