1.Service简单概述
Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件。服务可由其他应用组件启动(如Activity),服务一旦被启动将在后台一直运行,即使启动服务的组件(Activity)已销毁也不受影响。 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。 例如,服务可以处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行:
Service基本上分为两种形式
启动状态
当应用组件(如 Activity)通过调用 startService() 启动服务时,服务即处于“启动”状态。一旦启动,服务即可在后台无限期运行,即使启动服务的组件已被销毁也不受影响,除非手动调用才能停止服务, 已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。
绑定状态
应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。
2.在android studio中创建和配置service
1.使用android studio导航创建service
2.选择是否可编译,是否可实例化
需要在manifests进行配置,如果使用导航创建,会自动配置
<service android:name=".service.MyService" android:enabled="true" //是否可以实例化 android:exported="true"></service> //是否可以被调用
配置参数解释
<service android:enabled=["true" | "false"] android:exported=["true" | "false"] android:icon="drawable resource" android:isolatedProcess=["true" | "false"] android:label="string resource" android:name="string" android:permission="string" android:process="string" > . . . </service>
- android:exported:代表是否能被其他应用隐式调用,其默认值是由service中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。为false的情况下,即使有intent-filter匹配,也无法打开,即无法被其他应用隐式调用。
- android:name:对应Service类名
- android:permission:是权限声明
- android:process:是否需要在单独的进程中运行,当设置为android:process=”:remote”时,代表Service在单独的进程中运行。注意“:”很重要,它的意思是指要在当前进程名称前面附加上当前的包名,所以“remote”和”:remote”不是同一个意思,前者的进程名称为:remote,而后者的进程名称为:App-packageName:remote。
- android:isolatedProcess :设置 true 意味着,服务会在一个特殊的进程下运行,这个进程与系统其他进程分开且没有自己的权限。与其通信的唯一途径是通过服务的API(bind and start)。
- android:enabled:是否可以被系统实例化,默认为 true因为父标签 也有 enable 属性,所以必须两个都为默认值 true 的情况下服务才会被激活,否则不会激活。
3.Service类方法介绍
public class MyService extends Service { public MyService() { } /* * 绑定服务时才会调用 * 必须要实现的方法 */ @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } /* * 首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。 * 如果服务已在运行,则不会调用此方法。该方法只被调用一次 * */ @Override public void onCreate() { super.onCreate(); } /* * 每次通过startService()方法启动Service时都会被回调。 * */ @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } /* * 服务销毁时的回调 * */ @Override public void onDestroy() { super.onDestroy(); } }
- onBind:当另一个组件想通过调用 bindService() 与服务绑定(例如执行 RPC)时,系统将调用此方法。在此方法的实现中,必须返回 一个IBinder 接口的实现类,供客户端用来与服务进行通信。无论是启动状态还是绑定状态,此方法必须重写,但在启动状态的情况下直接返回 null。
- oncreate:首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或onBind() 之前)。如果服务已在运行,则不会调用此方法,该方法只调用一次
- onstartCommand::当另一个组件(如 Activity)通过调用 startService() 请求启动服务时,系统将调用此方法。一旦执行此方法,服务即会启动并可在后台无限期运行。 如果自己实现此方法,则需要在服务工作完成后,通过调用 stopSelf() 或 stopService() 来停止服务。(在绑定状态下,无需实现此方法。)
- onDestroy:当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等,这是服务接收的最后一个调用。
4.startService开启音乐播放器的例子
public class MusicService extends Service { public static boolean isPlay; //记录当前播放状态 private static MediaPlayer player; //记录MediaPlay对象 public MusicService() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate() { //创建的时候把资源文件放进去 player= MediaPlayer.create(this, R.raw.music); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { //判断是否在部分,如果没有就开启播放,然后把播放状态存起来 if(!player.isPlaying()){ player.start(); isPlay = player.isPlaying(); } return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { //销毁的时候停止播放,释放资源 player.stop(); isPlay = player.isPlaying(); player.release();//释放资源 super.onDestroy(); }
5.bound Service 绑定service实现数据交互
例子:
public class BindService extends Service { private MyBinder binder = new MyBinder(); public BindService() { } @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. //throw new UnsupportedOperationException("Not yet implemented"); return binder; //放回MyBinder对象,实现数据 } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } //生成随机数 public List getRandomNum(){ List resArr = new ArrayList(); String strNum;//用于保存随机数 for(int i = 0 ;i<7;i++){ int num = new Random().nextInt(33)+1; if(num<10){ strNum = "0"+String.valueOf(num); }else { strNum = String.valueOf(num); } resArr.add(strNum); } return resArr; } //获取bindService public class MyBinder extends Binder { public BindService getService(){ //创建获取service的方法 return BindService.this; //放回当前的Service类 } } @Override public void onDestroy() {//销毁service super.onDestroy(); } }
在Activity中实现绑定的代码
mBtn_getNum
public class ServiceActivity extends BaseActivity implements View.OnClickListener { private Button mBtn_start; //开启服务 private Button mBtn_stop; //停止服务 private Button mBtn_play; //播放音乐 private Button mBtn_getNum; //随机选号 private Button mBtn_intent; //intentservice private Button mBtn_pt; //普通耗时报错 private BindService bindService; @Override protected int getLayoutId() { return R.layout.activity_service; } @Override protected void initView() { mBtn_start = findViewById(R.id.btn_start); mBtn_stop = findViewById(R.id.btn_stop); mBtn_start.setOnClickListener(this); mBtn_stop.setOnClickListener(this); mBtn_play = findViewById(R.id.btn_play); mBtn_play.setOnClickListener(this); mBtn_getNum = findViewById(R.id.btn_getNum); mBtn_getNum.setOnClickListener(this); mBtn_intent = findViewById(R.id.btn_play); mBtn_intent.setOnClickListener(this); mBtn_pt = findViewById(R.id.btn_getNum); mBtn_pt.setOnClickListener(this); } @Override public void onClick(View v) { Intent intent = new Intent(ServiceActivity.this,MyService.class); Intent intent2 = new Intent(ServiceActivity.this,MusicService.class); switch (v.getId()){ case R.id.btn_start: startService(intent); break; case R.id.btn_stop: stopService(intent); break; case R.id.btn_play: if(MusicService.isPlay==false){ startService(intent2); }else{ stopService(intent2); } break; case R.id.btn_getNum: int[] textId = {R.id.num_1,R.id.num_2,R.id.num_3,R.id.num_4,R.id.num_5,R.id.num_6,R.id.num_7}; List num = bindService.getRandomNum(); for(int i=0;i<num.size();i++){ TextView tv = findViewById(textId[i]); tv.setText(num.get(i).toString()); } break; case R.id.btn_pt: Intent intent3 = new Intent(ServiceActivity.this,PtService.class); startService(intent3); break; case R.id.btn_intent: break; default: break; } } @Override protected void onStart() { super.onStart(); Intent intent = new Intent(this,BindService.class); bindService(intent,con, Service.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); unbindService(con); } //创建一个服务器关联对象 private ServiceConnection con = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { bindService = ((BindService.MyBinder)service).getService(); } @Override public void onServiceDisconnected(ComponentName name) { } }; }
6.Intent Service
对比普通Service:
普通Service不能自动开启线程,自动停止线程 ===》使用场景:进行耗时任务,如果不开启新线程时间超过20s就会出现应用无响应的错误,耗时任务完成,不会自动停止线程需要selfstop实现停止服务
IntentService:可以自动开启线程,自动停止线程 ===》使用场景:进行耗时任务,自动开启线程,耗时任务完成,自动停止线程停止服务