Sevices 服务
概念:
是一个组件
特点:
- ==一直在后台运行==,没有UI界面
生命周期:
两种使用模式:
- startSevice() : 开启服务
- bindService():
- 用一个类去继承Sevice
- 在清单文件中注册
- 复写:
- onCreate():第一次创建会执行,只执行一次
- onStartCommand():之后每次打开都会执行
- OnDestroy():服务关闭时调用
- 开启服务也是用Intent.也可以设置字节码文件
- 调用startSevice()生命周期为onCreate()–>onStartCommand()
- 代用stopSevice()关闭服务–>onDestroy(),但是过一会又可以自动有开启服务onCreate()–>onStartCommand()
调用onBind()绑定服务
@Override
public IBinder onBind(Intent intent) {
Log.d("tag", "onBind");
User user = new User();
user.name="王丽丽";
return user;
}
/*
* 调用onBind()方法时,不能直接new,需要创建一个内部类
*/
class User extends Binder{
public String name;
}
绑定服务时:
public void bind(View v) {
Intent service = new Intent();
service.setClass(MainActivity.this, MyService.class);
myServiceConnection = new MyServiceConnection();
<!--参数二是服务连接,需要创建一个类去实现ServiceConnection,把这个子类再传给bindService()-->
bindService(service, myServiceConnection, BIND_AUTO_CREATE);
}
class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
MyService.User user = (User) service;
Toast.makeText(MainActivity.this, name + "获取的数据是" + user.name,
Toast.LENGTH_LONG).show();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
案例-来电监听
- 需求:
- 窃听打入的电话
- 让自己的APP监听开机启动广播
- 当开机启动时,在广播里启动service
- 在service里监听电话状态
- 电话的状态
- 空闲状态:曾经开始录音,停止录音
- 响铃状态:准备录音
- 接听状态:开始录音,把录音放到sd卡
- 业务逻辑
- 创建一个去继承广播
- 在清单文件中注册广播
- 添加开机权限
```
<receiver android:name="com.example.phone.MyBraode">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
```
- 在广播中,执行完onReceive()生命周期就执行完了
- 启动服务
- 创建一个类继承服务
- 复写服务的方法
- 在清单文件中注册服务
- context调用startService()开启服务
- 启动服务
- 在oncreate()创建监听
- 开启电话监听调用:创建TelephonyManage对象 ,调用getSystemService(Telephony_service)
- 监听电话状态:对象调用listen(phoneStartstener监听对象,int FLGE)
- 参数一:传一个phoneStartstener监听对象,在里面复写onCallStartChange(state,incomingNumber)
- 回调方法onCallStartChange(state,incomingNumber)
- 参数一:状态改变的名
- 参数二:电话名称
- 回调方法onCallStartChange(state,incomingNumber)
- 参数二:传一个PhoneStartListener.LISTION_CALL_START监听的事件,一般是int类型常量,这个是系统定义好的,直接写就行
- 在change里做switch判断
- 空闲时:1
- 响铃时:2
- 接听时:3
- 录音实现
@Override
public void onCreate() {
super.onCreate();
// 开启对电话状态的监听
// ConnectivityManager
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
// 监听电话的状态
telephonyManager.listen(new PhoneStateListener() {
private MediaRecorder recorder;
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
// 如果曾经开始录音了,停止录音
if (isStart) {//接听了,然后挂断了
recorder.stop();
recorder.reset(); // You can reuse the object by going back
recorder.release(); // Now the object cannot be reused
recorder = null;
isStart = false;
}else if (recorder!=null) {//响铃了,但是被拒绝了
recorder.reset();
recorder.release();
recorder = null;
}
break;
case TelephonyManager.CALL_STATE_RINGING:
// 准备录音
if (recorder == null) {
recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
}
File file = new File(Environment.getExternalStorageDirectory(),
incomingNumber + "_" + new Date().getTime() + ".3gp");
recorder.setOutputFile(file.getAbsolutePath());
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// 开始录音
try {
recorder.prepare();
recorder.start(); // Recording is now started
isStart = true;
} catch (Exception e) {
e.printStackTrace();
}
break;
default:
break;
}
}
}, PhoneStateListener.LISTEN_CALL_STATE);
}
进程
- 优先级
- 前台进程
- 正在使用的应用,不会被杀死掉
- 可视进程
- 拥有一个暂停onPause()状态的Activity。前台进程没有可用空间才会杀死。
- 服务进程
- 拥有一个处于运行的Service,除非没有足够的内存空间才会被杀死
- 后台进程
- 拥有一个暂停onStop()状态的Activity
- 空进程
- 不拥有任何活动的组件。等死。
bindService(绑定service)的生命周期
- onCreate()
- onBind()
- onUnbind()
- onDestroy()
- 绑定service点击返回键,销毁Activity,bindService也会销毁
- 创建一个类继承service
- 实现各个方法看生命周期
- 绑定service,调用bindService(intent,coon,flags)
- 参数一:intent意图
- 参数二:绑定监听器对象,绑定成功后要调用…方法,
- serviceConnection()的子类
- 顶一个类实现它
- 复写方法连接成功,….
-
- 参数三:当Activity去绑定service自动创建
音乐播放器(Extending the Binder class)绑定service
创建一个内部类实现binder接口调用service的子类方法
Using AIDL:
aidl的使用
定义aidl步骤:- 1、 在需要被调用的那个进程创建一个Service,清单文件中设置intent-filter
- 2、 在需要被调用的那个进程定义一个接口
- 3、 将接口后缀改成.aidl
- 4、 刷新
- 5、 将.aidl文件中的public修饰符删掉,再刷新
- 6、 会在目录下生成一个和src目录一样的aidl文件
- 7、 在gen目录下会生成.java文件,该文件中有一个静态内部类Stub,这个就是要使用的
- 8、 在服务中:
@Override
public IBinder onBind(Intent intent) {
Stub stub = new Apliay.Stub() {
@Override
public String pay(float money) throws RemoteException {
return AlipayService.this.pay(money);
}
};
return stub;
}
- 9、将aidl目录复制到另外一个进程
- 10、在服务进程中生成的aidl就相当于一个中间介,它是跨进程、跨虚拟机的,在第二个应用中不能直接进行强转
@Override
public void onServiceConnected(ComponentName name, IBinder
service) {
//必须使用Alipay.aidl生成的对象身上的工具方法去转换对象
apliay = Apliay.Stub.asInterface(service);
Toast.makeText(MainActivity.this, "绑定远程服务成功",
Toast.LENGTH_SHORT).show();
}
- -
问题:
如果Activity绑定了服务,按返回键返回时,一定要解绑
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(myServiceConnection);
}