Sevices 服务

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)
        • 参数一:状态改变的名
        • 参数二:电话名称
    • 参数二:传一个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);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值