什么是service?
答:service(服务)是一个没有用户界面的长时间的在后台运行应用组件。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。Service有两种状态,“启动的”和“绑定”
1.service的生面周期
启动方式为startService的生命周期:oncreat()-->onStartCommand()-->onDestroy(),当调用者使用stopService调用onDestroy()方法,如果没有调用此方法service一直会在后台运行
启动方法为bindService的生命周期:onCreat()-->onBind()-->onUnbind-->onDestroy(),调用者是通过unbindservice方法来停止service,这是会调用onbUnind()和onDestroy()
方法的使用原则为:oncreat方法只会调用一次,无论你startService或者bindService几次,也就是说如果你先start了,再去bind,service只会onBind(),反之也是一样
如果是以bindService启动的,你用stopService是不会调用onDestroy()方法停止service,只能用unBindService来销毁service.多次使用startService会多次调用onStart(),多次使用onbindService会出现异常
IntentService介绍
IntentService是Service的子类,比普通的Service增加了一些功能。
1.会创建独立的worker线程来处理intent请求
2.会创建独立的workers线程来处理onHandleIntent方法的实现,无需处理多线程;
3.所以请求处理完后IntentService会自动停止,无需调用stopService方法;
4.为service的onBind()方法提供默认实现;
5.为service的onStartCommd()提供默认实现,将请求intent添加到队列中
代码如下:
public class MyIntentService extends IntentService { private String ex = ""; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); Toast.makeText(MyIntentService.this,"-e"+ex,Toast.LENGTH_SHORT).show(); } }; public MyIntentService(String name) { super(name); } @Override protected void onHandleIntent(Intent intent) { /* 模拟耗时任务, 因为在子线程中执行,所以需要handle是跟主线成通讯 */ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } mHandler.sendEmptyMessage(0); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public int onStartCommand(Intent intent, int flags, int startId) { ex=intent.getStringExtra("start"); return super.onStartCommand(intent, flags, startId); } }
重写service的onStartCommand方法。 @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_STICKY; } 简单介绍下这个方法,在Android开发的过程中,每次调用startService(Intent)的时候,都会调用该Service对象的onStartCommand(Intent,int,int)方法,然后在onStartCommand方法中做一些处理。然后我们注意到这个函数有一个int的返回值,这篇文章就是简单地讲讲int返回值的作用。 从Android官方文档中,我们知道onStartCommand有4种返回值: START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。 START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。 START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。 START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。 当然也还有其他解决方案,但是或多或少都会出现一些弊端或者相对来说比较麻烦。在这里举几个最常见的例子: 1.在onDestory方法中重启Service服务,一般来说,这样做是可以的。但是如果这样----》设置-->下载-->强制停止。则不会执行ondestory方法,或者通过别人应用,如360直接kill掉我的应用时,也是不会调用Service的ondestory方法的。 2.修改AndroidManifest.xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:sharedUserId="android.uid.system"> <application android:icon="@drawable/icon" android:label="@string/app_name" android:allowClearUserData="false" android:process="system" android:killAfterRestore="false"> 如果在加入了此部分代码,表示该程序运行在system进程组中,system进程组是没有权限访问sd卡的,而且service是不会自动重启的。 3.提高service的优先级别,不管你service的优先级别有多高,用户都是可以手动杀死的. 等等还有其他很多种方式,这里就不一一列举了。 所以如果要使自己的Service能够一直运行,最简单的方法就是重写onStartCommand方法就好了.但是千万不要做坏事,不要做被用户鄙视的恶意程序