PS.不知不觉间发现自己已经做了很久很久的Android开发了,过去对知识块的梳理总是放在云笔记里面.主要的原因还是自己的笔记太杂乱,没有脉络.本着开源的精神,也趁着这段时间有空将之前云笔记里面的文章梳理下.同时将一些知识点整理出来和大家共同分享.转载请注明出处:http://blog.csdn.net/unreliable_narrator?viewmode=contents
一.服务的概念.
service就是就是一个没有界面的activity,同属于四大组件之一,使用的时候需要在清单文件中进行配置.service的主要作用就是在后台做一些比较耗时的操作.例如访问网络,后台播放,进行复杂计算等等.一般只要是满足于两个条件就可以使用service了,一是没有界面的交互,二是在后台长时间的运行,services实际上也是运行在ui线程里面的,所以一些比较耗时的操作不要直接写在services里面,而是应该在services再重新开启一个线程来进行耗时的操作.
二.启动方式(三种).
1.Context.startService()方式启动
1.1 代码
Intent startIntent = new Intent(MainActivity.this, MyService.class);
startService(startIntent);
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d("++", "MyService_onBind");
return null;
}
@Override
public boolean onUnbind(Intent intent) {
Log.d("++", "MyService_onUnbind");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
Log.d("++", "MyService_onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("++", "MyService_onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("++", "MyService_onDestroy");
}
}
1.2说明:
直接通过context.startservice()方法来开启服务,这种方式开启的服务,服务会一直在后台运行,可以通过context.stopservice()来将服务进行关闭.如果程序关闭的时候没有将service关闭,那么service还是会继续在后台进行默默的运行.也就是说这种方式开启的服务是和调用者没有任何关系的.如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStartCommand()方法。
这种方式开启的服务,服务会一直在后台运行,可以通过context.stopservice()来将服务进行关闭.如果程序关闭的时候没有将service关闭,那么service还是会继续在后台进行默默的运行.也就是说这种方式开启的服务是和调用者没有任何关系的.
1.3停止服务
- 在外部使用stopService()手动停止。
- 在服务内部(onStartCommand方法内部)使用stopSelf()方法,使服务执行完毕后自动停止。比如说,一个start的Service执行在后台下载或上传一个文件的操作,完成之后,Service应自己停止。
1.4生命周期:
启动时startService –> onCreate() –> onStart()
停止时 stopService –> onDestroy()
在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService(startIntent)方法前服务已经被创建,多次调用startService(startIntent)方法并不会导致多次创建服务,但会导致多次调用onStart()方法。
2.通过Context.bindService()方法来开启服务
2.1.代码实现。
public class MainActivity extends AppCompatActivity {
private MyService mMyService;
public class MyConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMyService = (MyService.MyBinder) service;
mMyService.doOnServices();//调用服务里的方法.
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,MyService.class);
bindService(intent,myConn,BIND_AUTO_CREATE);//绑定服务.
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(myConn);
}
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
MyBinder myBinder = new MyBinder();
Log.d("MyService", "MyService_onBind");
return myBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.d("MyService", "MyService_onUnbind");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService", "MyService_onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "MyService_onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyService", "MyService_onDestroy");
}
/*binder对象
* */
public class MyBinder extends Binder {
public void doBinder() {
doSMinServices();
}
}
/*
* 服务里面的方法
* */
public void doOnServices() {
Toast.makeText(MyService.this, "我是服务中的方法,我被调用了", Toast.LENGTH_SHORT).show();
}
}
2.2 定义
许多的时候我们不但要将服务开启还要调用服务里面的方法,这时候我们就需要使用绑定服务的方式来开启服务了.通过绑定方式开启的服务如果服务的调用者被关闭了,那么服务也会被关闭.需要注意的是任何一个Service在整个应用程序范围内都是通用的,即MyService不仅可以和MainActivity建立关联,还可以和任何一个Activity建立关联,而且在建立关联时它们都可以获取到相同的MyBinder实例。
2.3生命周期:
- 绑定时,bindService -> onCreate() –> onBind();
- 调用者退出了,即解绑定时,Srevice就会unbindService –>onUnbind() –> onDestory();
2.4注意事项:
1、onCreate()、onBind()方法只会在Service第一次被创建的时候调用,多次点击绑定启动不会执行任何方法,onUnbind()、onDestroy()方法会在调用者执行unbindService()方法时执行或者Activity退出时自动执行。
2、如果我们既通过startService()开启Service,又用通过bindService开启,必要unbindService()和stopService()都执行一次(没有先后顺序),Service才会被销毁。
3、如果多次执行unbinsService()方法,程序会异常退出,我们需要在代码中加一个判断是否绑定的标记mBound来解决此问题。
2.5绑定服务和普通开启服务的区别:
- 绑定服务是和他的调用者的生命周期相关的,也就是说当调用者被销毁的时候,绑定服务也会同时被销毁.普通服务的生命周期和他的调用者是没有关系的,也就是说当调用者被关闭的时候服务仍旧是会在后台进行.而不会被销毁.
- 绑定服务是在任务管理器里面不可以看到的.普通服务是可以在任务管理器里面看到的.
- 开启普通服务的调用者是没有办法调用服务里面的相关的方法的.通过绑定服务就可以直接调用服务中的方法.
3.混合开启服务
3.1代码.
public class MainActivity extends AppCompatActivity {
private MyService mMyService;
public class MyConn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMyService = (MyService.MyBinder) service;
mMyService.doOnServices();//调用服务里的方法.
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,MyService.class);
bindService(intent,myConn,BIND_AUTO_CREATE);//绑定服务.
startService(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(myConn);
}
3.2定义.
很多时候我们开启服务以后,不但要调用服务的方法还需要服务一直在后台继续执行,也就是要兼具以上二者的优势,所以需要使用到混合开启服务.
- 通过startService()方式开启服务(只能通过调用stopService停止)
- 通过bindService进行绑定,以进行服务的方法调用(当需要的时候)
- 通过unbindService进行解绑(不需要调用方法了,在UI线程被销毁之前解绑)
- 通过stopService停止服务
3.3注意事项:
1.如果先startService(),再bindService(): 在bind的Activity退出且调用unbindService(myConn)的时候,Service会执行unBind方法而不执行其onDestory方法,因为有startService方法调用过,所以Activity与Service解除绑定后,还是会有一个与调用者没有关连的Service存在。
2.如果先bindService(),再startService(),再调用Context.stopService(), Service的onDestory方法不会立刻执行,因为有一个与Service绑定的Activity,但是在Activity退出的时候,会执行其(Service的)onDestory方法,如果要立刻执行stopService,就得先解除绑定。
3.如果先是bindService(),那么startService()的时候就直接运行Service的onStartCommand()方法,如果先是startService(),那么bindService()的时候就直接运行onBind()方法。
4.当一个服务没被onDestory()销毁之前,只有第一个启动它的客户端能调用它的onBind()和onUnbind()。
二.提高服务的优先级.
方式一:使用notification来使得服务的的优先级扩大.在服务的oncreate()或者是onstartcommed()方法里面调用开启服务.
public class MyService extends Service {
...
@Override
public void onCreate() {
super.onCreate();
//创建通知对象
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentText("测试代码");
builder.setSmallIcon(R.drawable.biaoqin);
Notification build = builder.build();
//调用此方法将通知和服务绑定在一起
startForeground(1, build);
}
}
方式二:在清单文件里面通过对服务的属性进行设置来提高服务的优先级.
<!-- 为了消去加上android:priority="1000"后出现的警告信息,可以设置android:exported属性,指示该服务是否能够被其他应用程序组件调用或跟它交互 -->
<service android:name="com.example.helloandroid.weatherforecast.service.UpdateWidgetService"android:exported="false" >
<!-- 为防止Service被系统回收,可以通过提高优先级解决,1000是最高优先级,数字越小,优先级越低 -->
<intent-filter android:priority="1000"></intent-filter>
</service>