安卓有四大组件,本次学习为service组件。了解service组件的生命周期、使用方法(注册、启动方式、绑定方式、停止方法)、绑定服务等基础性的知识。
实战:启动音乐服务、停止音乐服务、随机数的输出(绑定服务的实现方法)
一、Service简介
1、Service是Android系统的后台服务组件,适用于开发无界面、长时间运行的应用功能。
2、特点:
- 没有用户界面
- 比Activity的优先级高,不会轻易被Android系统终止
- 即使Service被系统终止,在系统资源恢复后Service也将自动恢复运行状态
- 用于进程间通信,解决两个不同Android应用程序之间的调用和通讯问题
二、Service生命周期
1、service生命周期包括:全生命周期 和 活动生命周期
- onCreate()事件回调函数: Service的生命周期开始,完成Service的初始化工作
- onStartCommand()事件回调函数:活动生命周期开始,但没有与之对应的“停止”函数,因此可以近似认为活动生命周期也是以onDestroy()标志结束
- onDestroy()事件回调函数: Service的生命周期结束,释放Service所有占用的资源
2、 Service使用方法: 启动方式 和 绑定方式
(1)启动方式
- 通过调用Context.startService()启动Service
- 通过调用Context.stopService()或Service.stopSelf()停止Service(Service是由其他的组件启动的,但停止过程可以通过其他组件或自身完成)
- 如果仅以启动方式使用的Service,这个Service需要具备自管理的能力,且不需要通过函数调用向外部组件提供数据或功能
(2)绑定方式
- 使用Service的组件通过Context.bindService()建立服务链接
- 通过Context.unbindService()停止服务链接
- 通过服务链接或直接获取Service中状态和数据信息
- 服务链接能够获取Service的对象,因此绑定Service的组件可以调用Service中的实现的函数
- 如果在绑定过程中Service没有启动,Context.bindService()会自动启动Service
- 同一个Service可以绑定多个服务链接,这样可以同时为多个不同的组件提供服务
(3)启动方式和绑定方式的结合
- 这两种使用方法并不是完全独立的,在某些情况下可以混合使用
- 以MP3播放器为例,在后台的工作的Service通过Context.startService()启动某个特定音乐播放,但在播放过程中如果用户需要暂停音乐播放,则需要通过Context.bindService()获取服务链接和Service对象,进而通过调用Service的对象中的函数,暂停音乐播放过程,并保存相关信息。在这种情况下,如果调用Context.stopService()并不能够停止Service,需要在所有的服务链接关闭后,Service才能够真正的停止。
三、服务管理
1、 服务管理主要指服务的启动和停止
2、首先介绍实现Service的最小代码集
- onBind()函数是在Service被绑定后调用的函数,能够返回Service的对象
- Service的最小代码集只有onBind()函数。但是其并不能完成任何实际的功能,需要重载onCreate()、onStartCommand()和onDestroy(),才使Service具有实际意义
- Android系统在创建Service时,会自动调用onCreate() 完成必要的初始化工作
- 在Service没有必要再存在时,系统会自动调用onDestroy(),释放所有占用的资源
- 通过Context.startService(Intent)启动Service时,onStartCommand()则会被系统调用,Intent会传递给Service一些重要的参数
- Service会根据实际情况选择需要重载上面的三个函数
3、注册Service——开发平台自动生成。
4、 启动Service——启动方式:显示启动 和 隐式启动
(1) 显示启动:在Intent中指明Service所在的类,并调用startService(Intent)函数启动Service,示例代码如下:
- 在Intent中指明启动的Service在RandomSerevice.class中
final Intent serviceIntent = new Intent(this, RandomService.class);
startService(serviceIntent);
(2)隐式启动:
- 在注册Service时,声明Intent-filter的action属性
<service android:name=".RandomService">
<intent-filter>
<action android:name="com.asus.RandomService" />
</intent-filter>
</service>
- 设置Intent的action属性,可以在不声明Service所在类的情况下启动服务
- 隐式启动的代码如下
final Intent serviceIntent = new Intent();
serviceIntent.setAction("edu.hrbeu.RandomService");
- 若Service和调用服务的组件在同一个应用程序中,可以使用显式启动或隐式启动,显式启动更加易于使用,且代码简洁
- 若服务和调用服务的组件在不同的应用程序中,则只能使用隐式启动
5、 停止Service
- 将启动Service的Intent传递给stopService(Intent)函数即可,示例代码如下
stopService(serviceIntent);
在调用startService(Intent)函数首次启动Service后,系统会先后调用onCreate()和onStartCommand()
再次调用startService(Intent)函数,系统则仅调用onStartCommand (),而不再调用onCreate()
在调用stopService(Intent)函数停止Service时,系统会调用onDestroy()
无论调用过多少次startService(Intent),在调用stopService (Intent)函数时,系统仅调用onDestroy()一次
四、Bind Service——绑定服务
1、绑定服务是 Service 类的实现,可让其他应用与其绑定和交互。要提供服务绑定,您必须实现 onBind() 回调方法。该方法返回的 IBinder 对象定义了客户端用来与服务进行交互的编程接口.
2、客户端可通过调用 bindService() 绑定到服务。调用时,它必须提供 ServiceConnection 的实现,后者会监控与服务的连接。bindService() 方法会立即无值返回,但当 Android 系统创建客户端与服务之间的连接时,会对 ServiceConnection 调用 onServiceConnected(),向客户端传递用来与服务通信的 IBinder。
3、多个客户端可同时连接到一个服务。不过,只有在第一个客户端绑定时,系统才会调用服务的 onBind() 方法来检索 IBinder。系统随后无需再次调用 onBind(),便可将同一 IBinder 传递至任何其他绑定的客户端。
4、当最后一个客户端取消与服务的绑定时,系统会将服务销毁(除非 startService() 也启动了该服务)。
5、当您实现绑定服务时,最重要的环节是定义您的 onBind() 回调方法返回的接口。
以下是具体的设置方法:
- 在您的服务中,创建一个可满足下列任一要求的 Binder 实例
- 从 onBind() 回调方法返回此 Binder 实例。
- 在客户端中,从 onServiceConnected() 回调方法接收 Binder,并使用提供的方法调用绑定服务
实战
Android6.0以上需要在配置文件中给应用权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
ServiceActivity:连接xml文件,跳转到匹配的service服务
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class ServiceActivity extends AppCompatActivity {
private ServiceConnection serviceConnection;
private MyBindService myBindService;
private boolean binded = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service);
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
MyBindService.MyBinder myBinder = (MyBindService.MyBinder)iBinder;
myBindService = myBinder.getMyService();
binded = true;
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
binded = false;
}
};
}
public void startMyService(View view){
Intent intent = new Intent (this,MyService.class);
startService(intent);
}
public void stopMyService(View view){
Intent intent = new Intent(this,MyService.class);
stopService(intent);
}
public void callMyService(View view){
Toast.makeText(this,myBindService.getRandom()+"",Toast.LENGTH_SHORT).show();
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this,MyBindService.class);
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if(binded){
unbindService(serviceConnection);
}
}
}
MyService:实现音乐播放的开始和停止
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
public class MyService extends Service {
//声明音乐播放对象
private MediaPlayer mediaPlayer;
public MyService() {
}
@Override
public void onCreate() {
//定义音乐播放对象
mediaPlayer = MediaPlayer.create(this, R.raw.wav);
//设置循环播放
mediaPlayer.setLooping(true);
//打印运行了onCreate方法
Log.d(MyService.class.toString(),"onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mediaPlayer.start();
return START_STICKY;
}
@Override
public void onDestroy() {
//打印运行了onDestroy方法
Log.d(MyService.class.toString(),"onDestroy");
mediaPlayer.stop();
}
@Override
public IBinder onBind(Intent intent) {
//在Service被绑定后调用的函数,能够返回Service的对象
return null;
}
}
MyBindService:实现的是随机数的产生
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import java.util.Random;
public class MyBindService extends Service {
private Random random;
private MyBinder myBinder;
public MyBindService() {
}
@Override
public void onCreate() {
random = new Random();
myBinder = new MyBinder();
}
public int getRandom(){
return random.nextInt();
}
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
public class MyBinder extends Binder{
public MyBindService getMyService(){
return MyBindService.this;
}
}
}
以上我做了两个简单的实例:音乐的播放和停止、产生随机数。