【Android服务】制作无法销毁的Service
2016-01-24 20:06
330 查看
今天面试没表现好啊,现在来好好研究下这个问题:如何制作Android无法销毁的Service?(虽然在用户的角度上看,这样的开发显得很无赖,但是很多场景下,需要这样去设计APP,例如某APP每天在某个固定时间段向用户推送信息,那么手机端这个接收推送服务必须要提前启动,所以做这样的事还是很有必要的)
事实上,解决这个还需要一个帮助,运用广播。
在启动Service,调用startService()时,都会调用OnStartCommand(intent,int,int),在其中运行一些方法。来深入了解下OnStartCommand()的四种返回值。
1.第一种:START_STICKY
public static final int START_STICKY = 1;
如果Service服务被销毁掉,那么保留Service的状态为开始状态,但是并不保留intent对象。然后系统会创新创建Service,而且之前状态是被保存的开始状态,所以创建Sevice后一定会调用OnStartCommand(intent,int,int),如果在此期间没有其他操作传递到Service,那么intent会为null(因为之前也为保存intent对象,所以会为空)。
第二种:START_NOT_STICKY
public static final int START_NOT_STICKY = 2;
相当于第一种的对立,“非粘性”,在执行完OnStartCommand后,如服务被异常销毁掉,那么该服务将无法自动重新启动。
第三种:START_REDELIVER_INTENT
public static final int START_REDELIVER_INTENT = 3;
可以从简单的字面上理解,重传intent启动服务,执行完OnStartCommand(intent,int,int)后,如果服务被异常销毁掉,系统会自动重启服务,并将intent对象传入。
第四种:START_STICKY_COMPATIBILITY
public static final int START_STICKY_COMPATIBILITY = 0;
从字面上理解是,是第一种的通用类型,不过并不能完全做到能自动重启服务。
制作一个销毁的Service,也许我们可以不钻牛角尖,做一个可以无限制唤醒的Service,(虽然可被销毁,但服务会再次被创建)
方法一:利用计时,例如60s间隔时间再次启动Service。
如下:
MyService:
MyBroadcastReceiver:
第二种方法:销毁时立刻再次创建:
在MySerice内这么写(相比第一种更灵活):
第三种:类似第二种,我们可以先看张图片:
我们可以注意到微博的方式,不妨做个假设,微博的服务相互监听,微博的服务只要其中一个服务被销毁,另外的服务就立刻创建它,这样的“互助”式监听,在一定程度上可以避免APP服务的异常销毁,造成服务无法重启,引起APP的异常。
以上这些方面当然还无法去做到真正意义上的无法销毁的服务,假设手机重启,所有服务都被销毁了,服务又将如何自启动呢?那么继续往底层深入的探讨这个问题,个人从网上收集了部分资料,“守护进程”深入到C底层的写法了
事实上,解决这个还需要一个帮助,运用广播。
在启动Service,调用startService()时,都会调用OnStartCommand(intent,int,int),在其中运行一些方法。来深入了解下OnStartCommand()的四种返回值。
/** * Constant to return from {@link #onStartCommand}: if this service's * process is killed while it is started (after returning from * {@link #onStartCommand}), then leave it in the started state but * don't retain this delivered intent. Later the system will try to * re-create the service. Because it is in the started state, it will * guarantee to call {@link #onStartCommand} after creating the new * service instance; if there are not any pending start commands to be * delivered to the service, it will be called with a null intent * object, so you must take care to check for this. * * <p>This mode makes sense for things that will be explicitly started * and stopped to run for arbitrary periods of time, such as a service * performing background music playback. */ public static final int START_STICKY = 1;
1.第一种:START_STICKY
public static final int START_STICKY = 1;
如果Service服务被销毁掉,那么保留Service的状态为开始状态,但是并不保留intent对象。然后系统会创新创建Service,而且之前状态是被保存的开始状态,所以创建Sevice后一定会调用OnStartCommand(intent,int,int),如果在此期间没有其他操作传递到Service,那么intent会为null(因为之前也为保存intent对象,所以会为空)。
/** * Constant to return from {@link #onStartCommand}: if this service's * process is killed while it is started (after returning from * {@link #onStartCommand}), and there are no new start intents to * deliver to it, then take the service out of the started state and * don't recreate until a future explicit call to * {@link Context#startService Context.startService(Intent)}. The * service will not receive a {@link #onStartCommand(Intent, int, int)} * call with a null Intent because it will not be re-started if there * are no pending Intents to deliver. * * <p>This mode makes sense for things that want to do some work as a * result of being started, but can be stopped when under memory pressure * and will explicit start themselves again later to do more work. An * example of such a service would be one that polls for data from * a server: it could schedule an alarm to poll every N minutes by having * the alarm start its service. When its {@link #onStartCommand} is * called from the alarm, it schedules a new alarm for N minutes later, * and spawns a thread to do its networking. If its process is killed * while doing that check, the service will not be restarted until the * alarm goes off. */ public static final int START_NOT_STICKY = 2;
第二种:START_NOT_STICKY
public static final int START_NOT_STICKY = 2;
相当于第一种的对立,“非粘性”,在执行完OnStartCommand后,如服务被异常销毁掉,那么该服务将无法自动重新启动。
/** * Constant to return from {@link #onStartCommand}: if this service's * process is killed while it is started (after returning from * {@link #onStartCommand}), then it will be scheduled for a restart * and the last delivered Intent re-delivered to it again via * {@link #onStartCommand}. This Intent will remain scheduled for * redelivery until the service calls {@link #stopSelf(int)} with the * start ID provided to {@link #onStartCommand}. The * service will not receive a {@link #onStartCommand(Intent, int, int)} * call with a null Intent because it will will only be re-started if * it is not finished processing all Intents sent to it (and any such * pending events will be delivered at the point of restart). */ public static final int START_REDELIVER_INTENT = 3;
第三种:START_REDELIVER_INTENT
public static final int START_REDELIVER_INTENT = 3;
可以从简单的字面上理解,重传intent启动服务,执行完OnStartCommand(intent,int,int)后,如果服务被异常销毁掉,系统会自动重启服务,并将intent对象传入。
/** * Constant to return from {@link #onStartCommand}: compatibility * version of {@link #START_STICKY} that does not guarantee that * {@link #onStartCommand} will be called again after being killed. */ public static final int START_STICKY_COMPATIBILITY = 0;
第四种:START_STICKY_COMPATIBILITY
public static final int START_STICKY_COMPATIBILITY = 0;
从字面上理解是,是第一种的通用类型,不过并不能完全做到能自动重启服务。
制作一个销毁的Service,也许我们可以不钻牛角尖,做一个可以无限制唤醒的Service,(虽然可被销毁,但服务会再次被创建)
方法一:利用计时,例如60s间隔时间再次启动Service。
如下:
MyService:
package com.yyc.servicedemo.services; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.widget.Toast; public class MyService extends Service { AlarmManager mAlarmManager = null; PendingIntent mPendingIntent = null; @Override public void onCreate() { //start the service through alarm repeatly Intent intent = new Intent(getApplicationContext(), MyService.class); mAlarmManager = (AlarmManager)getSystemService(ALARM_SERVICE); mPendingIntent = PendingIntent.getService(this, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK); long now = System.currentTimeMillis(); mAlarmManager.setInexactRepeating(AlarmManager.RTC, now, 60000, mPendingIntent); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(getApplicationContext(), "服务启动", Toast.LENGTH_SHORT).show(); return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { Toast.makeText(getApplicationContext(),"服务销毁",Toast.LENGTH_SHORT).show(); // /** // * 第二种方法 // */ // Intent intent = new Intent(); // intent.setClass(this, MyService.class); // 销毁时重新启动Service (虽然方法很流氓) super.onDestroy(); } }
MyBroadcastReceiver:
package com.yyc.servicedemo.broadcastReceivers; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import com.yyc.servicedemo.services.MyService; /** * Created by Administrator on 2016/1/24. */ public class MyBroadcastReceiver extends BroadcastReceiver{ private final String TAG=MyBroadcastReceiver.class.getSimpleName(); @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { Intent startServiceIntent = new Intent(context, MyService.class); startServiceIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startService(startServiceIntent); } } }
第二种方法:销毁时立刻再次创建:
在MySerice内这么写(相比第一种更灵活):
@Override public void onDestroy() { Toast.makeText(getApplicationContext(),"服务销毁",Toast.LENGTH_SHORT).show(); /** * 第二种方法 */ Intent intent = new Intent(); intent.setClass(this, MyService.class); // 销毁时重新启动Service (虽然方法很流氓) super.onDestroy(); }
第三种:类似第二种,我们可以先看张图片:
我们可以注意到微博的方式,不妨做个假设,微博的服务相互监听,微博的服务只要其中一个服务被销毁,另外的服务就立刻创建它,这样的“互助”式监听,在一定程度上可以避免APP服务的异常销毁,造成服务无法重启,引起APP的异常。
以上这些方面当然还无法去做到真正意义上的无法销毁的服务,假设手机重启,所有服务都被销毁了,服务又将如何自启动呢?那么继续往底层深入的探讨这个问题,个人从网上收集了部分资料,“守护进程”深入到C底层的写法了
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories