Service:服务.---->"在后台运行,没有界面".
特点:①.在后台执行长时间的耗时操作;②.没有提供界面;
分类:①.开启的服务,started:其他的组件可以开启一个服务,那么
该组件与服务本身没有任何关系,即使该组件退出,也不会影响到该服务的运行;
一般用来执行单一的任务,没有返回结果.服务完成自己的任务后,应该
停止自身的运行.
②.绑定的服务,bound:在其他的组件中可以绑定一个服务,那么该组件与服务绑定在一起,
该组件与服务本身是有关系的,当该组件退出后,服务也会退出.
作用:①.执行耗时的网络访问,下载大的电影;②.播放音乐;③.进行比较大的I/O操作;
④.也可以操作内容提供者;⑤.可以实现IPC等等.
Service案例:
public class FirstService extends Service {
// 当第一次创建该服务的时候调用,不要手动的调用该方法.
// 用来创建服务,进行一些初始化的操作.
@Override
public void onCreate() {
Log.i("TAG", "onCreate方法执行了");
super.onCreate();
}
// 该方法会执行多次.也就是没调用一次startService(intent)方法,就会执行一次该方法.不要手动调用该方法.
// 虽然服务本身是用来执行耗时操作的,但是不能直接在里面进行耗时操作,而应该开启新的线程,或者是异步任务.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("TAG", "onStartCommand方法执行了");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.i("TAG", "onBind方法执行了");
return null;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i("TAG", "onUnbind方法执行了");
return super.onUnbind(intent);
}
// 销毁服务的方法.不要手动的调用该方法.通常在该方法中用来执行
// 释放资源的操作,比如释放线程,广播接收器等资源.
@Override
public void onDestroy() {
Log.i("TAG", "onDestroy方法执行了");
super.onDestroy();
}
}
这里可能会出面试题:
onStartCommand方法的返回值:决定了该服务是粘性还是非粘性的.粘性服务和非粘性服务.
粘性服务:如果服务本身因为意外原因(比如内存严重不足)程序崩溃,服务死掉了,此时系统会给该服务一次重生的机会.
// START_STICKY_COMPATIBILITY:兼容模式.无法保证该服务是粘性的.
// START_NOT_STICKY:非粘性服务.
// START_STICKY:粘性服务.服务因意外而死一次后,会重生一次."失忆".
// "出车祸了--->死了--->不幸中的万幸,被救活了--->万幸中的不幸:失忆了"
// START_REDELIVER_INTENT:粘性服务.服务因意外而死一次后,会重生一次."不会失忆".
// "出车祸了--->死了--->不幸中的万幸,被救活了--->没有不幸:没有失忆."
注意:在服务中可以弹toast,但是不能展示其他的UI.
IntentService意图服务:
//IntentService--->Service.
public class LoadService extends IntentService {
private String path = "http://pimg1.126.net/movie/product/movie/144428601165210115_520_692_webp.jpg";
// 必须提供一个无参的构造方法
public LoadService() {
super("");
}
// 处理意图的方法.
// IntentService:①.不用开线程;②.不用停止自身.
// 该方法属于工作线程.每次可以处理一个意图,但是不会造成任何事情的阻塞.
// 该方法执行完毕后会停止服务自身,不需要我们再次调用stopSelf()方法.
@Override
protected void onHandleIntent(Intent intent) {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (conn.getResponseCode() == 200) {
InputStream is = conn.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while ((len = (is.read(buffer))) != -1) {
baos.write(buffer, 0, len);
baos.flush();
}
boolean result = SDUtil.saveDataIntoSDCard(baos.toByteArray(),
"1509", "b.jpg");
if (result) {
Intent broad = new Intent();
broad.setAction("success");
sendBroadcast(broad);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
bindService():
需求: 调用服务中的方法:获取随机数
public void getValue(View v) {
//获取服务对象
LocalService serviceInstance = mBinder.getServiceInstance();
int random = serviceInstance.getRandom();
Toast.makeText(this, "随机数=" + random, Toast.LENGTH_SHORT).show();
}
// 绑定服务
public void bind(View v) {
Intent service = new Intent(this, LocalService.class);
conn = new MyConn();
bindService(service, conn, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (conn != null) {
unbindService(conn);
}
}
// 服务连接
class MyConn implements ServiceConnection {
// 建立连接
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (service instanceof MyBinder) {
mBinder = (MyBinder) service;
}
}
// 失去连接--->当服务所在的进程因为意外的原因而被"杀死或者崩溃".
// 当调用unBindService():是不会执行该方法的.
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
在自定义的Service类中:
//①.既要开启服务;②.又要调用服务中的方法:前提条件是不能new LocalService.
public class LocalService extends Service {
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
// 自定义IBinder对象
class MyBinder extends Binder {
//获取LocalService的实例
public LocalService getServiceInstance() {
return LocalService.this;
}
}
// 生成随机数
public int getRandom() {
return new Random().nextInt(100);
}
}