一、特点:
1. 是Android的四大组件之一
2. 有生命周期方法
3. 可以在长期在后台进行操作的类
4. 是Context的子类
二、常见作用 :
1. 音乐播放器,可以在服务类中控制并处理音乐的播放
2. 长期在后台下载的操作,如:全选下载40集电视剧
3. 长期在后台处理一些监控类的事情
三、使用方式:
开启服务
通过startService方法启动的服务就叫做开启的服务
特点
1. 即使程序退出,服务也不会销毁 2. 无法得到被启动的Service对象
使用步骤
1. 创建一个Service的子类 2. 清单文件中注册此子类
<!--
注册Service
android:name 用于注册Service子类的具体路径
-->
<service android:name=".MyService"/>
或者:
<!--
在注册service时,也可给当前service配置action动作名称
稍后通过startservice或者bindservice方法启动服务时
可以直接将该action名称传递intent对象
-->
<service android:name=".MusicService"
>
<intent-filter>
<action android:name="com.music"/>
</intent-filter>
</service>
3. 在Service的子类中重写onStartCommand方法
/*
参数1:通过startService方法传递过来的Intent对象,用于携带数据
参数3:给本次启动的服务操作分配一个id标识,简单来说,也可表示时第几次调用了startService方法
参数2: 用于判断本次启动的服务时正常启动的还是系统自动重启的
通常情况下,当正常通过startService方法启动服务时,flags为0
当服务被系统意外回收后,当系统再次自动重启时,flags标识不为0
自动重启时,如果返回值为START_STICKY或者START_STICKY_COMPATIBILITY,那么flags的值为:START_FLAG_RETRY
自动重启时,如果返回值为START_REDELIVER_INTENT,那么flags的值为:START_FLAG_REDELIVERY
返回值: 当服务被系统意外回收后,是否要让当前服务具备自动重启的能力
START_NOT_STICKY 不会自动重启
START_STICKY 会自动重启,当重启的时候,参数intent对象中不携带数据
START_STICKY_COMPATIBILITY 会自动重启,参数intent对象中不携带数据,是START_STICKY的兼容版本,不保证会重启成功
START_REDELIVER_INTENT 会自动重启,参数intent对象中也会携带数据
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand: "+this.hashCode());
//取出在调用startService方法时传递的数据
// String data = intent.getStringExtra("data");
// Log.i(TAG, "onStartCommand: "+data +" "+startId);
Log.i(TAG, "onStartCommand: "+flags);
return START_REDELIVER_INTENT;
}
生命周期:
生命周期方法的运行特点:
1. 当第一次调用startService方法时,运行onCreate—onStartCommand生命周期 2. 当后期重复调用startService方法时,只运行onStartCommand方法,并且重复运行时Service类始终用的是同一个对象 3. 当页面退出时,不会onDestroy方法 4. 当服务通过stopService方法或者stopSelf方法时调用onDestroy方法时才会运行onDestroy方法。
三、绑定服务的使用方式:
绑定服务
通过bindService方法启动的服务叫做绑定的服务
特点
1. 绑定的服务当页面退出后会自动解除绑定 2. 当服务绑定后,通过指定方式可以在页面中直接调用服务中的方法,服务和页面之间的数据传输会比较方便
使用方式
1. 创建Service的子类 2. 清单文件中进行子类的注册 3. 重写Service中的生命周期方法
4. 调用bindService方法绑定服务
/*
参数:
1. Intent对象,用于秒数要绑定的是哪个服务对象
2. ServiceConnection接口,
3. flag标识,用于设置要绑定的Service对象的创建特点
最常用:Context.BIND_AUTO_CREATE
当要绑定服务对象,先判断系统中是否已经存在服务对象,如果已经存在,直接绑定此对象
如果不存在,那么先创建服务对象,然后在进行绑定操作
*/
bindService(new Intent(this,MyBindService.class),
conn,
Context.BIND_AUTO_CREATE);
5. 修改onBind方法的返回值
/*
返回值:
当返回值为null时,绑定操作运行到此结束,绑定失败
只有当返回值不为null时,继续运行ServiceConnection接口中的onServiceConnected方法,绑定成功
*/
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind: ");
return new MyBinder();
}
//Binder是系统提供的IBinder接口的实现子类
/*
该类的作用:将想要开放给页面中调用的方法定义到此类中
*/
class MyBinder extends Binder {
public int sum (int n1,int n2){
return n1+n2;
}
}
6. 在页面的onServiceConnected方法中获取onBind方法的返回值对象,通过此对象调用服务中的方法即可
//初始化接口对象
conn = new ServiceConnection() {
//当页面和服务成功绑定后调用的方法
/*
参数2:就是onBind方法的返回值
*/
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("oye", "onServiceConnected: ");
mb = (MyBindService.MyBinder) service;
}
//当服务被系统意外关闭,页面和服务断开连接后调用的方法
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
- 按钮的点击事件中:
case R.id.button3:
if (mb != null) {
int num = mb.sum(4,5);
Log.i("o", "click: 运算的结果为 : "+num);
}
break;
- 解除绑定:
// 注意此方法不要多次调用
//也不要在没有运行bindService情况下调用此方法
unbindService(conn);
四、IntentService服务的使用方式:
作用
- 当需要Service长期在后台进行下载操作(或其他耗时操作时),由于Service中的代码默认运行在主线程,因此不能够直接的在Service中进行连网操作。
解决方式:
1. 通过属性解决,即将Service中的代码分配在其他进程中运行。
<service android:name=".MyIntentService"
android:enable="true"
android:process="remote"/>
2. 通过在Service中启动子线程,在子线程中进行耗时操作
3. 在通过startService方法启动服务时,直接启动一个IntentService的子类,因该子类中的onHandleIntent方法中的代码默认运行在子线程中。
特点:
1. IntentService的子类只能通过startService方法启动,不能配合bindService方法使用 2. 当onHandleIntent方法中的代码执行完毕后,当前Service会自动销毁
使用方式:
1. 创建一个IntentService的子类 2. 在清单文件中进行注册 3. 在子类中重写onHandleIntent方法,在该方法中处理耗时的操作
/**
* 创建子类后,手动修改构造方法
* 将构造方法的参数列表清空掉
* 在super()中添加任意的字符串参数
* 此参数的作用为:给IntentService中自带的子线程起一个名字
*/
public MyIntentService() {
super("ayy");
}
/*
该方法中的代码默认运行在子线程中,
当调用startService启动当前服务后,会运行此方法
参数中的Intent就是startService方法中传递的Intent对象
*/
@Override
protected void onHandleIntent(Intent intent) {
Log.i("oye", "onHandleIntent: "+Thread.currentThread().getName());
String url = intent.getStringExtra("url");
try {
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setRequestMethod("GET");
conn.connect();
if (conn.getResponseCode() == 200) {
InputStream is = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG,100,bos);
SystemClock.sleep(5000);
//获取图片数据对应的byte数组
img = bos.toByteArray();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 当onHandleIntent方法中的耗时操作执行结束后,当前的IntentService会自动销毁
* 一旦销毁,就会运行onDestroy方法
*/
@Override
public void onDestroy() {
Log.i("oye", "onDestroy: 图片下载结束");
Intent data = new Intent("com.intent.img");
data.putExtra("img",img);
sendBroadcast(data);
super.onDestroy();
}