Android服务

服务 service

--------此笔记根据黑马程序员的授课视频所记录
Activity
网络编程1
网络编程2
广播接收者
服务
内容提供者
多媒体

1.进程概念介绍

【1】Android下四大组件都是运行在主线程中

【2】服务是在后台运行 是没有界面的activity

【3】进程的优先级

​ 1.Foreground process 前台进程 优先级最高 相当于activity执行了onResume方法 用户正在交互

​ 2.Visible process 可视进程 一直影响用户看得见 相当于activity执行了onPause方法

​ 3.Service process 服务进程 通过一个startService 方法开启了一个服务

​ 4.Background process 后台进程 相当于activity执行了onStop方法 界面不可见,但是activity并没有销毁

​ 5.Empty process 空进程 不会维持任何组件运行

2.start方式开启服务的特点

【1】定义四大组件的方式是一样的

【2】定义一个类继承Service

【3】第一次开启点击按钮开启服务 服务执行onCreate方法和onStartCommand方法

【4】第二次点击开始按钮 再次开启服务 服务执行onStartCommand方法

【5】服务一旦被开启 服务就会后台长期运行 直到用户手工停止

3.电话窃听器案例

TelephoneManager 提供关于设备的一些信息

实现步骤

[1]定义一个服务 开启服务 记得在清单文件配置服务(AS直接创建一个服务)

[2]在服务的onCreate方法里获取TelephoneManager

TelephonyManager tm = (TelephonyManager) getSystemService(TELECOM_SERVICE);

[3]注册电话的监听

tm.listen(new MyPhoneListener(), PhoneStateListener.LISTEN_CALL_STATE);

[4]定义一个类来监听电话的状态

public class MyPhoneListener extends PhoneStateListener {
    //当电话设备状态发生改变时调用
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        //具体判断电话的状态
        switch (state) {
            //空闲状态
            case TelephonyManager.CALL_STATE_IDLE:
                
                break;
            //电话接听状态
            case TelephonyManager.CALL_STATE_OFFHOOK:
                
                break;
            //电话响铃状态
            case TelephonyManager.CALL_STATE_RINGING:

                break;
        }
        super.onCallStateChanged(state, incomingNumber);
    }
}

下面代码是加入了真正的录音逻辑

//定义一个类用来监听电话的状态
public class MyPhoneListener extends PhoneStateListener {
    private MediaRecorder recorder;  //创建一个录音机的实例
    //当电话设备状态发生改变时调用
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        //具体判断电话的状态
        switch (state) {
            //空闲状态
            case TelephonyManager.CALL_STATE_IDLE:
                if (recorder!=null){
                    recorder.stop();//停止录音
                    recorder.reset();//重置
                    recorder.release();//释放资源
                }
                break;
            //电话接听状态
            case TelephonyManager.CALL_STATE_OFFHOOK:
                recorder.start();
                break;
            //电话响铃状态
            case TelephonyManager.CALL_STATE_RINGING:
                Log.d("******", "onCallStateChanged: 准备一个录音机");
                //创建实例
                recorder = new MediaRecorder();
                //设置音频来源
                recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);//录制双方通话
                //设置输出的格式
                recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//3gp格式
                //设置音频的编码方式
                recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                //设置存放的文件路径
                recorder.setOutputFile("/mnt/sdcard/luyin.3gp");
                try {
                    //准备录
                    recorder.prepare();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
        }
        super.onCallStateChanged(state, incomingNumber);
    }
}

4.使用服务注册特殊的广播接收者

和在activity中注册特殊的广播接收者一样只是放在了Service的生命周期方法里

	public void onCreate(){
	//创建Receiver对象
        MyReceiver myReceiver = new MyReceiver();
        //创建IntentFliter对象
        IntentFilter intentFilter = new IntentFilter();
        //添加要注册的action
        intentFilter.addAction("android.intent.action.SCREEN_OFF");//锁屏
        intentFilter.addAction("android.intent.action.SCREEN_ON");//解屏
		//动态注册广播接收者
        registerReceiver(myReceiver,intentFilter);
	}

//当Service销毁的时候要取消广播接收者
 @Override
    protected void onDestroy() {
        unregisterReceiver(myReceiver);
        super.onDestroy();
    }

5.bindService开启服务的特点

【1】第一次点击按钮会执行服务的onCreate方法和onBind方法

【2】当onBind方法返回值为null时 onserviceConnected方法时不执行的

【3】第二次点击按钮 服务没有响应

【4】不求同生,但求同死 指的是调用者(activity)和服务之间

【5】服务不可以多次解绑,多次解绑会报异常

【6】通过bind方式开启的服务 服务不能再设置页面找到 相当于是一个隐形的服务

具体的代码开启实现方式

在这里插入图片描述

6.为什么要引入bindService

为了调用服务里的方法

7.通过biandService方式调用服务方法里面的过程

【1】在服务的内部定义一个方法,让activity去调用

【2】在服务的内部定义一个中间人对象(IBinder)

public class MyBinder extends Binder{
    public void Test(){
        //此方法里可以调用需要调用服务的方法
    }
}

【3】把定义的中间人对象在onBind方法里返回

public IBinder onBind(Intent intent) {
    return new MyBinder();
}

【4】在mainActivity的onCreate方法里面调用bindService方法 目的是为了获取我们定义的中间人对象

Intent intent = new Intent(this,DemoService.class);
//连接到DemoService这个服务
conn = new MyConn();
bindService(intent,conn,BIND_AUTO_CREATE);

【5】获取中间人对象

private class MyConn implements ServiceConnection{

    //当服务连接成功时调用此方法
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
       //获取中间人对象
        myBinder  = (DemoService.MyBinder) service;
    }
    //当服务失去来连接时调用
    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
}

【6】拿到了中间人对象就可以间接调用服务里面的方法

public void click7(View view) {
    myBinder.Test();
}

【7】当Activity销毁的时候解绑服务

protected void onDestroy() {
    //当activity销毁的时候解绑服务
    unbindService(conn);
    super.onDestroy();
}

8.通过接口方式调用服务里面的方法

接口可以隐藏代码内部的细节 让程序员暴露自己只想暴露的方法

定义一个接口,把想暴露出去的方法放到接口中去,将原来的MyBinder类变成private私有的。

让MyBinder实现这个接口

注意,此时定义的中间人对象的类型发生了改变,变成了接口的类型,因为Java的多态

9.百度音乐盒框架

补充:混合方式开启服务

​ 需求:我既想让服务在后台长期运行 又想调用服务里的方法

​ [1]先调用startService 方法开启服务 能够保证服务在后台长期运行

​ [2]调用bindService方法获取中间人对象

​ [3]调用unbindService解绑服务

​ [4]调用stopService

public class MusicActivity extends AppCompatActivity {
    Iservice iservice;//定义的中间人对象
    MyConn myConn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_music);

        //开始混合开启服务
        //1.先调用startService 目的是保证服务能在后台长期运行
        Intent intent = new Intent(this,MusicService.class);
        startService(intent);
        myConn = new MyConn();
        bindService(intent,myConn,BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        //销毁时解绑
        unbindService(myConn);
        super.onDestroy();
    }

    //播放音乐
    public void click1(View v){
        iservice.callplayMusic();

    }
    //暂停音乐
    public void click2(View v){
        iservice.callpauseMusic();
    }
    //继续播放音乐
    public void click3(View v){
        iservice.callrePalyMusic();
    }
    //上一首
    public void click4(View v){

    }
    //下一首
    public void click5(View v){

    }

    //用来监听服务的状态
    private class MyConn implements ServiceConnection{

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iservice = (Iservice) service;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }
}
public interface Iservice {
    //把想暴露的方法都放到接口中去
    public void callplayMusic();
    public void callpauseMusic();
    public void callrePalyMusic();
}
public class MusicService extends Service {
    MediaPlayer mediaPlayer;
    public MusicService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }

    @Override
    public void onCreate() {
        
        super.onCreate();
    }

    //播放音乐逻辑
    public void playMusic(){
       

        Log.d("音乐", "playMusic:播放了");
    }
    //暂停音乐逻辑
    public void pauseMusic(){
       
        Log.d("音乐", "playMusic:暂停了");
    }
    //继续播放音乐逻辑
    public void rePalyMusic(){
       
        Log.d("音乐", "playMusic:重新播放了");
    }
    //在服务的内部定义一个中间人对象
    private class MyBinder extends Binder implements Iservice{

        @Override
        public void callplayMusic() {
            playMusic();
        }

        @Override
        public void callpauseMusic() {
            pauseMusic();
        }

        @Override
        public void callrePalyMusic() {
            rePalyMusic();
        }
    }

}

10.aidl介绍

本地服务:运行在自己应用里面的服务

远程服务:运行在其他应用里面 的服务

实现进程间通信(IPC)

AIDL(Android Interface Definition Language)是Android系统自定义的接口描述语言,是Android平台中实现进程间通讯方式一种,属轻量级通讯机制,有着实现简单、效率较高等优点…

总结:使用步骤

[1]把Iservice.java文件变成一个aidl文件

[2]aidl这个语言不认识public 所以把public去掉即可

[3]系统会自动生成一个Iservice.java文件 系统 自动帮助我们生成了一个Stub类
在这里插入图片描述

[4]我们自己定义的中间人MyBinder类对象直接继承Stub类就好了,不用再继承Binder然后再实现IService接口

[5]保证两个应用的aidl文件是同一个 保证aidl文件所在的包名相同

[6]获取中间人对象的方式不一样了

在这里插入图片描述

PS:注意!此时在activity里的onCreate方法里new Intent时不能直接传入参数时用.class的方法了,需要用意图过滤器实现
在这里插入图片描述

11.aidl的应用场景

​ 比如 支付宝应用 调用支付功能

12.今日总结

【1】进程的概念 优先级:前台 可视 服务 后台 空进程(了解)

【2】如何定义服务 定义一个类继承Service

【3】startService开启服务的特点 服务长期在后台运行 直到用户手动停止(必须掌握)

【4】bindService 服务开启的特点 不求同时开始,但求同时结束 Activity销毁了 服务也跟着销毁了(掌握)

【5】电话窃听器实例(掌握)

​ telephoneManager:getSystemService();

​ tm.listen

​ 电话的三种状态 空闲 响铃 接听

​ 录音机:MeidiaRecoder 涉及权限较多

【6】使用服务注册特殊广播接收者:把注册的逻辑放到服务当中(掌握)

【7】使用bindService调用服务方法的流程(掌握)

​ (1)在服务内部定义一个方法

​ (2)定义一个中间人对象(IBinder)

​ (3)在onBind方法返回

​ (4)通过bindService去获取中间人对象

​ (5)通过中间人对象去间接的调用服务里的方法

【8】通过抽取接口的方式调用服务里的方法

【9】混合方式开启服务

​ startService()保证服务在后台长期运行

​ bindService()获取中间人对象 可以调用服务里的方法

​ unbindService()解绑服务

​ stopservice方法关不关闭看情况

【10】aidl 是解决进程间通信的 IPC

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值