Android_黑马视频学习_day08

一、进程概念介绍

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

  【2】服务是在后台运行  可以理解为是没有界面的activity


进程的优先级

  【1】Foreground process 前台进程  优先级最高  相当于activity进行了onResume 方法  用户用户交互

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

  【3】service process 服务进程  通过startService 方法开启了一个服务

  【4】background process后台进程  相当于activity  执行了onStop方法  界面不可见  但activity并没有被销毁

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


二、start方式开启服务的特点

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

  【2】定义一个类继承Service

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

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

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


补充:股票应用  实时去服务器去数据更新


三、电话窃听器案例

  【1】SmsManager

  【2】TelephoneManager


实现步骤

  【1】定义一个服务  开启服务  记得在清单文件配置服务

  【2】在服务的onCreate方法里面  获取TelephoneManager

//[1]获取telephonemanager的实例
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);

  【3】注册电话的监听

//[2]注册电话的监听
tm.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
  【4】定义一个类用来监听电话的状态
//定义一个类来监听电话的状态
private class MyPhoneStateListener extends PhoneStateListener{

    //当电话设置状态发生改变的时候调用
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {

        //[3]具体判断一下电话的状态
        switch (state){
            case TelephonyManager.CALL_STATE_IDLE:  //空闲状态
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:   //接听状态
                System.out.println("开始录");
                break;
            case TelephonyManager.CALL_STATE_RINGING:   //响铃状态
                System.out.println("准备一个录音机");
                break;
            default:
                break;
        }

        super.onCallStateChanged(state, incomingNumber);
    }
}

  【5】准备一个录音机

//[1]创建MediaRecorder 实例
recorder = new MediaRecorder();
//[2]设置音频的来源
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
//[3]设置输出的格式
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
//[4]设置音频的编码方式
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
//[5]设置存放的路径
recorder.setOutputFile("/mnt/sdcard/luyin.3gp");
try {
    recorder.prepare();
} catch (IOException e) {
    e.printStackTrace();
}
recorder.start();
if(recorder!=null){
    recorder.stop();    //停止录音
    recorder.reset();   //重置
    recorder.release(); //释放资源
}

  【6】把开启服务的逻辑放到手机重启的广播中

public class BootRecevier extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        //把服务开启
        Intent intent1 = new Intent(context, PhoneService.class);
        context.startService(intent1);
    }
}


四、使用服务注册特殊的广播接受者

操作特别频繁的广播事件  比如屏幕的解锁和锁屏

实现步骤

  【1】定义广播接受者  接受屏幕解锁和锁屏的事件

public class ScreenReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        //获取当前事件类型
        String action = intent.getAction();
        if ("android.intent.action.SCREEN_OFF".equals(action)) {
            System.out.println("说明屏幕锁屏了");
        } else if ("android.intent.action.SCREEN_ON".equals(action)) {
            System.out.println("~~~~~~~~~~~~");
        }

    }
}
  【2】写一个服务  用来注册广播接受者

public class ScreenService extends Service {

    private ScreenReceiver receiver;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        //[1]创建ScreenReceiver 实例
        receiver = new ScreenReceiver();
        //[2]获取IntentFilter 实例  目的是添加action
        IntentFilter filter = new IntentFilter();
        //[3]添加action
        filter.addAction("android.intent.action.SCREEN_OFF");
        filter.addAction("android.intent.action.SCREEN_ON");
        //[4]动态接受广播接受者
        registerReceiver(receiver, filter);
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        //当服务销毁的时候 取消注册广播接受者
        unregisterReceiver(receiver);
        super.onDestroy();
    }
}
  【3】在mainActivity的onCreate方法里面开启服务

//开启服务
Intent intent = new Intent(this, ScreenService.class);
startService(intent);
  【4】一定要记得配置服务


五、bindService开启服务特点

10-07 03: 11:29.715: E/ ActivityThread(7787) :
android.app.ServiceConnect ionLeaked: Activity
com.itheima.servicedemo.MainAct ivity has leaked ServiceConnection
com.itheima.servicedemo.MainActivity$MyConn@b6487788 that was original ly bound here
[1] 第一次点击按钮会执行服务的onCreate方法和onBind方法
[2] 当onBind方法返回为null 的时候onServiceConnected方法是不执行的
[3]第二次点击按钮服务没有响应
[4]不求后时生 但求后时死  指的是调用者(activity)和服务之间
[5]服务不可以多次解绑多次解绑会报异常  相当于是一个隐形的服务
[6]通过bind方式开启服务服务不能在设置页面找到

六、为什么要引入bindService

目的是为了调服务里的方法


七、通过bindService方式调用服务方法里面的过程

[1]在服务的内部定义一个方法  让activity去调用
//办证的方法
public void banZheng(int money) {
    if(money > 1000) {
        Toast.makeText(getApplicationContext(), "我是领导 把证给你办了", Toast.LENGTH_LONG).show();
    } else {
        Toast.makeText(getApplicationContext(), "就这点钱 还想办事...", Toast.LENGTH_LONG).show();
    }
}
[2]在服务的内容定义一个中间人对象(IBinder)
//[1]定义中间人对象(IBinderpublic class MyBinder extends Binder {
    public void callBanZheng(int money){
        //调用办证的方法
        banZheng(money);
    }
}
[3]把我定义的中间人对象 在onBind方法返回
//把我定义的中间人对象返回
@Nullable
@Override
public IBinder onBind(Intent intent) {
    return new MyBinder();
}
[4]在mainActivity的onCreate方法里面调用bindservice 的目的是为了获取我们定义的中间人对象
Intent intent = new Intent(this, BanZhengService.class);
//连接服务
conn = new MyConn();
bindService(intent, conn, BIND_AUTO_CREATE);

[5]获取中间人对象

//监视服务的状态
private class MyConn implements ServiceConnection{

    //当服务连接成功
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {

        //获取中间人对象
        myBinder = (BanZhengService.MyBinder) iBinder;

    }

    //失去连接
    @Override
    public void onServiceDisconnected(ComponentName componentName) {

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

[7]当Activity销毁的时候 解绑服务


八、通过接口方式调用服务方法里面的方法

 接口可以隐藏代码内部的细节让程序员暴露自己只想暴露的方法
[1]定义一个接口把想暴露的方法都定义在接口里面
[2]我们定义的中间人对象实现我们自己定义的接口
[3]在获取中间人对象的时候
//获取中间人对象
myBinder= (Iservice) service;

补充:混合方式开启服务
    需求:我既想让服务在后台长期运行  我又想调用服务里面的方法

[1]先调用startService 方法开启服务 能够保证服务在后台长期运行
[2]调用bindService方法去获取中间人对象
[3] 调用unbindService 解绑服务
[4] 调用stopService

九、百度音乐盒框架


十、aidl介绍

本地服务:运行自己应用里面的服务
远程服务:运行在其他应用里面的服务
实现进程间通信IPC
 aidl :专门是用来解决进程间通信

总结:使用aid1的步骤
[1]把Iservice.java文件变成一个aid1文件
[2]adil这个语言不认识public 把public给我去掉
[3]自动生成一个Iservice.java文件系统自动帮助我们生成了一个类Stub
public static abstract class Stub extends android.os.Binder implements com.example.wzy.a9_remoteservice.IService
{
private static final java.lang.String DESCRIPTOR = "com.example.wzy.a9_remoteservice.IService";
[4]我们自己定义的中间人对象直接继承Stub 就可以了
[5]保证2应用的aidl文件是同一个  保证aidl文件所在的包名相同
[6]获取中间人对象的方式不一样了
//获取中间人对象 注意这里面在获取中间人对象的方式变了 和之前不一样
    iService = IService.Stub.asInterface(iBinder);

十一、aidl的应用场景

支付宝 和 捕鱼达人  买豆


你可能感兴趣的:(Android)