Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/182.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 即使用户强制关闭服务,如何自动重新启动服务?_Android_Service_Alarm - Fatal编程技术网

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

Android 即使用户强制关闭服务,如何自动重新启动服务?,android,service,alarm,Android,Service,Alarm,我希望服务在我的应用程序中始终运行。所以我想重新启动它,即使它被用户强制关闭。确实有一种方法可以做到这一点,因为像facebook这样的应用程序正在这样做。(不是使用推送通知,即使互联网关闭,facebook也会重新启动服务) 任何帮助都将不胜感激。谢谢 在服务的startCommand方法上返回START\u STICKY。通常,它会告诉操作系统在服务被终止时启动服务 如果我理解正确,那么实际上这是不可能的,Android强制关闭应用程序的功能是为了让用户摆脱不需要的应用程序,所以在用户再次启

我希望服务在我的应用程序中始终运行。所以我想重新启动它,即使它被用户强制关闭。确实有一种方法可以做到这一点,因为像facebook这样的应用程序正在这样做。(不是使用推送通知,即使互联网关闭,facebook也会重新启动服务)


任何帮助都将不胜感激。谢谢

在服务的startCommand方法上返回START\u STICKY。通常,它会告诉操作系统在服务被终止时启动服务

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


每当服务被终止时,总是调用它的
onDestroy
方法。 最好使用广播接收器在服务被终止时启动服务

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

@Override
public void onDestroy() {
Intent in = new Intent();
in.setAction("StartkilledService");
sendBroadcast(in);
Log.d("debug", "Service Killed");
}
然后在
AndroidManifest.xml
中注册接收者:-

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

希望这有帮助。

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

无论如何,您可以使用
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"));
    }

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

    }

}
RestartServiceReceiver.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"));
    }

}
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>


根据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()。我认为唯一的方法是使用
标记\u包括\u STOPPED\u包
intent标记并从另一个应用程序发送它

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

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

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


当然,当所有应用程序都被某个免费RAM或类似的应用程序杀死时,它不会有帮助,但当Android杀死这两个应用程序中的任何一个时,另一个将重新启动它的对应程序。

我认为这里唯一简单的解决方案是在单独的进程中有两个服务(
Android:process=“somecustomprocessname”
在manifest中,在服务条目中),两者都侦听广播并重新启动,因为当前UI不允许用户在一个操作中杀死多个进程。然后,您可以在每个服务中设置一个pinger线程,检查另一个服务是否每100毫秒左右运行一次,如果没有,则尝试重新启动它。但是这看起来越来越像恶意软件了……

保持服务活动的唯一真正解决方案是调用
Service.startForeground(…)
,并提供通知。这将是唯一有效的解决方案,其他任何解决方案都将取决于谷歌将如何改变其系统的行为。通过每一次API更新,谷歌都可以防止任何其他黑客攻击

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

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


您必须使用重写的
onTaskRemoved
方法创建一个
sticky服务
,在该方法中,您可以设置报警服务以再次触发代码

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);
    }
}
此外,在小米、Huwaei等一些设备中,一旦从最近的应用程序中删除,该应用程序就会被强制关闭。这是因为制造商具有任务管理器功能,可提高ram/电池性能


您可以查看此链接以了解更多信息:

您是否使用后台服务…创建另一个服务以启动第一个服务,或者创建一个接收器,在任何事件中检查服务是否可用,如果不可用,它将启动它。您可能希望您的服务一直运行,但事实上,你的用户正在强制关闭它,这意味着他们没有。如果应用程序是供公众使用的,请重新考虑此要求哪个答案最终解决了您的问题?您解决了吗?onDestroy()不会每次都被调用。尝试过。尝试此链接如果您强制停止服务,进程将立即终止,并且不会向其发送回调。因此,当应用程序被终止时(即,在应用程序的onDestroy方法上),不会调用onDestroy.call stopService。这将起作用“每当服务被终止,它的onDestroy方法总是被调用。”-这是一个谎言,正如我提到的,其他应用程序正在这样做。看起来KitKat在这个问题上带来了一些变化,请看这里:。作家作品
void startForeground (int id, Notification notification)
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);
    }
}