Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/206.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_Android Service - Fatal编程技术网

Android 我们如何防止服务被操作系统杀死?

Android 我们如何防止服务被操作系统杀死?,android,android-service,Android,Android Service,我正在我的应用程序中使用服务,它需要运行,直到卸载我的应用程序,但问题是它被操作系统杀死 我们如何防止它被操作系统杀死?或者,如果它被终止,我们可以通过编程方式重新启动该服务吗?您可以使用以下方式运行该服务 前台服务是一种被认为是某种东西的服务 用户主动意识到,因此不是系统的候选者 在内存不足时杀死 但请记住,前台服务必须为状态栏()提供通知,并且除非服务停止或从前台删除,否则不能取消通知 注意:这仍然不能绝对保证在极低内存条件下不会终止服务。这只会降低它被杀死的可能性。使用 @Override

我正在我的应用程序中使用
服务
,它需要运行,直到卸载我的应用程序,但问题是它被操作系统杀死


我们如何防止它被操作系统杀死?或者,如果它被终止,我们可以通过编程方式重新启动该服务吗?

您可以使用以下方式运行该服务

前台服务是一种被认为是某种东西的服务 用户主动意识到,因此不是系统的候选者 在内存不足时杀死

但请记住,前台服务必须为状态栏()提供通知,并且除非服务停止或从前台删除,否则不能取消通知

注意:这仍然不能绝对保证在极低内存条件下不会终止服务。这只会降低它被杀死的可能性。

使用

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    //**Your code **
    // We want this service to continue running until it is explicitly
    // stopped, so return sticky.
    return START_STICKY;
} 
参考服务的生命周期


编辑添加的方法。

我最近对你的问题感到困惑。但现在,我找到了一个好的解决方案。 首先,您应该知道,即使您的服务被OS终止,您的服务的onCreate方法也会在短时间内被OS调用。因此,您可以使用onCreate方法执行以下操作:

@Override
public void onCreate() {
    Log.d(LOGTAG, "NotificationService.onCreate()...");
    //start this service from another class
    ServiceManager.startService();
}
@Override
public void onStart(Intent intent, int startId) {
    Log.d(LOGTAG, "onStart()...");
    //some code of your service starting,such as establish a connection,create a TimerTask or something else
}
“ServiceManager.startService()”的内容是:

但是,此解决方案仅适用于您的服务被GC终止的情况。有时,我们的服务可能被Program Manager的用户终止。在这种情况下,您的进程将被终止,并且您的服务将永远不会被重新实例化。因此,您的服务无法重新启动。 但好消息是,当PM终止您的服务时,它将调用您的onDestroy方法。因此,我们可以使用该方法做一些事情

    @Override
public void onDestroy() {
    Intent in = new Intent();
    in.setAction("YouWillNeverKillMe");
    sendBroadcast(in);
    Log.d(LOGTAG, "onDestroy()...");
}
字符串“YouWillNeverKillMe”是一个自定义操作。 此方法最重要的一点是,在发送广播之前不要添加任何代码。因为系统不会等待onDestroy()的完成,所以必须尽快发送广播。 然后在manifast.xml中注册接收器:

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

希望这能对你有所帮助,并原谅我糟糕的英语写作。

我找到了一个解决办法。。。。迟到的回答,但我想回答

我们可以在服务的ondestroy中发送广播,并创建接收广播并再次启动服务的接收器。。。。当它因任何原因被销毁时…

请尝试以下操作:

final Messenger mMessenger = new Messenger(new IncomingHandler()); 
class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            default:
                super.handleMessage(msg);
            }
        }
}

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


@Override
public IBinder onBind(Intent arg0) {
    return mMessenger.getBinder();
}


private void makeServiceForeground() {
    IActivityManager am = ActivityManagerNative.getDefault();
    try {
        am.setProcessForeground(onBind(null), android.os.Process.myPid(), true);
    } catch (RemoteException e) {
        Log.e("", "cant set to foreground" + e.toString());
    }
}
还需要外接程序manifest.xml

<uses-permission android:name="android.permission.SET_PROCESS_LIMIT"/>

在服务类中重写方法
onStartCommand()
,只需返回
START\u STICKY
(如“它不是空的”所示)。这就是你所需要的。如果运行您的服务的进程被终止(例如,由于内存不足),Android系统将自动重新启动它(通常会有一些延迟,比如5秒)

不要再使用
onStart()
,正如另一个答案中所建议的,它已被弃用

@Override
public void onDestroy() {

    super.onDestroy();
    startService(new Intent(this, YourService.class));

}

在您的服务中写入上述代码,您的服务将永远不会停止,即使用户想要销毁它或他们想要杀死它,它也永远不会停止,直到您的应用程序无法从您的设备上卸载。

您可以尝试重复启动服务,例如每5秒启动一次。 这样,当您的服务运行时,它将每5秒执行一次onStartCommand()。我测试了这个方案,它非常可靠,但不幸的是它略微增加了电话开销。 这是您启动服务的活动中的代码

Intent iFileObserver = new Intent(StartServicesActivity.this, FileObserverService.class);
PendingIntent pendingIntentFileObserver = PendingIntent.getService(StartServicesActivity.this, 0, iFileObserver, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Date now = new Date();

    //start every 5 seconds
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, now.getTime(), 5*1000, pendingIntentFileObserver);
下面是该服务的onStartCommand()

//class variable
public static boolean isStarted = false;

public int onStartCommand(Intent intent, int flags,  int startId) {

    int res = super.onStartCommand(intent, flags, startId);

    //check if your service is already started
    if (isStarted){      //yes - do nothing
        return Service.START_STICKY;
    } else {             //no 
        isStarted = true;
    }


    /**** the rest of your code  ***/

    return Service.START_STICKY;

}
public int onStartCommand(Intent intent, int flags,  int startId) {

    int res = super.onStartCommand(intent, flags, startId);

    /*** Put your code here ***/

    startServiceForeground(intent, flags, startId);

    return Service.START_STICKY;  
}

public int startServiceForeground(Intent intent, int flags, int startId) {

    Intent notificationIntent = new Intent(this, StartServicesActivity.class); 
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    Notification notification = new NotificationCompat.Builder(this)
        .setContentTitle("File Observer Service")
        .setContentIntent(pendingIntent)
        .setOngoing(true)
            .build();

    startForeground(300, notification);

    return START_STICKY;
}

我找到了这个问题的另一个解决方案,它保证您的服务将永远有效。在我的例子中,这个方案也解决了FileObserver的问题,它会在一段时间后停止工作

  • 使用活动(StartServicesActivity)作为前台服务启动服务(FileObserverService)
  • 使用BroadcastReceiver类(例如CommonReceiver)在某些特殊情况下重新启动服务,以防服务被终止 我在我的应用程序“自动发送图片电子邮件”中使用了此代码

    这里是CommonReceiver类

    public class CommonReceiver extends BroadcastReceiver {
    
        public void onReceive(Context paramContext, Intent paramIntent)
        {
            paramContext.startService(new Intent(paramContext, FileObserverService.class));
        }
    }
    
    下面是它在应用程序关闭标记之前的AndroidManifest.xml中的定义

    <receiver android:name="com.alexpap.services.CommonReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.USER_PRESENT"/>
        </intent-filter>
    </receiver>
    
    下面是服务的onStartCommand()方法

    //class variable
    public static boolean isStarted = false;
    
    public int onStartCommand(Intent intent, int flags,  int startId) {
    
        int res = super.onStartCommand(intent, flags, startId);
    
        //check if your service is already started
        if (isStarted){      //yes - do nothing
            return Service.START_STICKY;
        } else {             //no 
            isStarted = true;
        }
    
    
        /**** the rest of your code  ***/
    
        return Service.START_STICKY;
    
    }
    
    public int onStartCommand(Intent intent, int flags,  int startId) {
    
        int res = super.onStartCommand(intent, flags, startId);
    
        /*** Put your code here ***/
    
        startServiceForeground(intent, flags, startId);
    
        return Service.START_STICKY;  
    }
    
    public int startServiceForeground(Intent intent, int flags, int startId) {
    
        Intent notificationIntent = new Intent(this, StartServicesActivity.class); 
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
    
        Notification notification = new NotificationCompat.Builder(this)
            .setContentTitle("File Observer Service")
            .setContentIntent(pendingIntent)
            .setOngoing(true)
                .build();
    
        startForeground(300, notification);
    
        return START_STICKY;
    }
    
    我使用TaskKiller应用程序测试了这段代码,每次服务被终止时,它几乎立即重新启动(执行onStartCommand()。它也会在每次打开手机和重新启动后重新启动。
    我在我的应用程序中使用了这个代码,它通过电子邮件发送你用手机拍摄的每一张照片,以预先定义电子邮件列表。发送电子邮件和接收电子邮件的列表在另一个活动中设置,并存储在共享首选项中。我在几个小时内拍摄了大约100张照片,所有照片都被正确地发送到接收电子邮件。

    据我所知,
    ondestory()
    只有在服务明确停止(强制停止)时才会被调用。但如果操作系统/刷取最近的应用程序列表导致服务终止,则不会调用此方法。在这些情况下,将调用另一个名为
    onTaskRemoved(Intent)
    的事件处理程序。根据链接,这是由于Android 4.3-4.4中存在缺陷所致。请尝试使用以下代码:-

    public void onTaskRemoved(Intent intent){
    super.onTaskRemoved(intent);
    Intent intent=new Intent(this,this.getClass()); 
    startService(intent); 
    }
    

    首先在另一个进程中创建服务,然后编写以递归方式按时间间隔运行的广播器

    protected CountDownTimer rebootService = new CountDownTimer(9000, 9000) {
    
    
        @Override
        public void onTick(long millisUntilFinished) {
    
    
        }
    
        @Override
        public void onFinish() {
    
            sendBroadcast(reboot);
            this.start();
            Log.d(TAG, "rebootService sending PREVENT AUTOREBOT broadcast");
    
    
        }
    
    };
    
    之后,在主进程中注册广播接收器,并使用计时器递归,该计时器递归在服务的第一次广播到达后启动

    protected static class ServiceAutoRebooter extends BroadcastReceiver {
    
        private static   ServiceAutoRebooter instance = null;
        private  RebootTimer rebootTimer = null;
    
        private static ServiceAutoRebooter getInstance() {
    
            if (instance == null) {
    
                instance = new ServiceAutoRebooter();
    
            }
            return instance;
    
        }
    
    
    
    
    
        public class RebootTimer extends CountDownTimer {
    
            private Context _context;
            private Intent _service;
    
    
            public RebootTimer(long millisInFuture, long countDownInterval) {
                super(millisInFuture, countDownInterval);
            }
    
    
            @Override
            public void onTick(long millisUntilFinished) {
    
            }
    
    
            @Override
            public void onFinish() {
    
                _context.startService(_service);
                this.cancel();
                Log.d(TAG, "Service AutoRebooted");
    
    
            }
    
    
        }
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
            if (rebootTimer == null) {
                Log.d(TAG, "rebootTimer == null");
    
                rebootTimer = new RebootTimer(10000, 10000);
                rebootTimer._context = context;
    
                Intent service = new Intent(context, SomeService.class);
                rebootTimer._service = service;
                rebootTimer.start();
    
            } else {
    
                rebootTimer.cancel();
                rebootTimer.start();
                Log.d(TAG, "rebootTimer is restarted");
    
            }
    
    
        }
    
    
    }
    

    如果RebootTimer(主进程)的时间过期,服务将自动重新启动,这意味着服务中的“阻止自动恢复”广播尚未到达

    感谢您的回复Dheeraj,但我不需要服务中的通知。是否有其他方法可以运行服务而不被操作系统杀死。。你知道Wake_Lock吗..我在我的服务中合并了你给我的链接startForeground()的代码。但我的服务有时也会被操作系统扼杀。@Rahul你有什么解决办法吗?这就是方法和方法
    protected static class ServiceAutoRebooter extends BroadcastReceiver {
    
        private static   ServiceAutoRebooter instance = null;
        private  RebootTimer rebootTimer = null;
    
        private static ServiceAutoRebooter getInstance() {
    
            if (instance == null) {
    
                instance = new ServiceAutoRebooter();
    
            }
            return instance;
    
        }
    
    
    
    
    
        public class RebootTimer extends CountDownTimer {
    
            private Context _context;
            private Intent _service;
    
    
            public RebootTimer(long millisInFuture, long countDownInterval) {
                super(millisInFuture, countDownInterval);
            }
    
    
            @Override
            public void onTick(long millisUntilFinished) {
    
            }
    
    
            @Override
            public void onFinish() {
    
                _context.startService(_service);
                this.cancel();
                Log.d(TAG, "Service AutoRebooted");
    
    
            }
    
    
        }
    
    
        @Override
        public void onReceive(Context context, Intent intent) {
    
            if (rebootTimer == null) {
                Log.d(TAG, "rebootTimer == null");
    
                rebootTimer = new RebootTimer(10000, 10000);
                rebootTimer._context = context;
    
                Intent service = new Intent(context, SomeService.class);
                rebootTimer._service = service;
                rebootTimer.start();
    
            } else {
    
                rebootTimer.cancel();
                rebootTimer.start();
                Log.d(TAG, "rebootTimer is restarted");
    
            }
    
    
        }
    
    
    }