IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 蓝牙流程(aidl) -> 正文阅读

[移动开发]蓝牙流程(aidl)

说说aidl

百度百科复制一波

什么是AIDL编辑?
Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。
为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。

再说说aidl

草?说的什么鬼,看不懂,aidl就是一个C/S框架嘛,后台跑应用,前端调接口,这样说不好吗?就像linux Bluez后台跑bluetoothd的proxy org.bluez.xxx,都是差不多,TMD发现蓝牙很喜欢这样玩,不管是android还是bluez,就是喜欢后台跑应用,前端来操控,这种玩法类似AMS,am start xxx,还是我个人认知出现问题,其它模块大家都是这么玩的,C/S葛??

自己写个aidl实例先玩一下

Mainactivity

public class MainActivity extends AppCompatActivity {

    private IMyAidlInterface myAidlInterface;
    private String name1;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(MainActivity.this,MyService.class);
        startService(intent);
        doBind();
    }



    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
            final TextView oneView=(TextView)findViewById(R.id.textView3);
            if(myAidlInterface != null)
            {
                try {
                    name1 = myAidlInterface.getname();
                    oneView.setText("get interface success");
                }catch (RemoteException e){
                    e.printStackTrace();
                    oneView.setText("get interface fail");
                }

            } else{
                oneView.setText("bind aidl success");
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private boolean doBind(){
        Intent intent = new Intent(MainActivity.this,MyService.class);
        bindService(intent,conn,0);
        return true;
    }


    public void onbind(View view) {
        final TextView twoView = (TextView) findViewById(R.id.textView4);
        twoView.setText(name1);
    }
}

aidl interface

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    void setname(String name);
    String getname();

}

service

public class MyService extends Service {

    public String name = "interface getname print ok";

    Binder mBinder = new IMyAidlInterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public void setname(String name) throws RemoteException {

        }

        @Override
        public String getname() throws RemoteException {
            return name;
        }
    };

    public MyService() {
    }

    public void onCreate(){

        super.onCreate();

    }
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.

        return mBinder;
    }


    public void setname(String name){


    }

    public String getname(){

        return name;

    }

}

测试效果

按按键可以调用service的接口,可以。

分析

我测了一下,?一定要先startService(intent),才能Bind的到,这完全符合后台启动,前端再跑的玩法,就是这个意思,你不启动,接口不会实体化。

蓝牙aidl

framework==>aidl==>JNI==>BTIF==>BTM==>vendor(初始化和download fw)

我们上层的兄弟写app的时候,直接import framework各种接口,各种tab的补齐写的很爽,但是呢,很多时候,我们的接口是有定制化或者有问题的,需要改,比如蓝牙一个2009的指令下去,要带个scan rsp的UUID,有些SDK接口有限制,玩不动,所以经常也要改接口,aidl、JNI这些就是引子,顺藤摸瓜,有啥不能改?JNI大家已经很熟练了,蓝牙JNI主要就是将callback也要带到BTIF下面去,因为发一个cmd下去要拿到一个event上来,不知道event什么时候能来,所以要callbak,收到callbak再send handle messages异步传过去即可,别罗比缩,赶紧说aidl。

这个是package/app/Bluetooth的service后台部分,接口就是这个,放到GattService.java上去。?

那framework是谁来Bind,这个就是你们听的很多的,就是BluetoothManagerService.java,这个就是主角,BluetoothManagerService.java是Bind的地方,其它上层java就不说了,都要找它拿接口,拿到aidl上的接口。

?搞定,分析完了,就是这样Bind的,对不对,现在知道这么Bind了,那service是怎么启动的呢兄dei???startService启动的呗,哪个地方呢,我发一下。

profile service 后台启动

这个部分有点长,有想看的继续看下去

?

?

?不好意思,有点长,反正就是上层一直调到AdapterService,Adapter再去启动各个service.

 760     @SuppressWarnings("rawtypes")
 761     private void setGattProfileServiceState(Class[] services, int state) {
 762         if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) {
 763             Log.w(TAG,"setGattProfileServiceState(): invalid state...Leaving...");
 764             return;
 765         }
 766
 767         int expectedCurrentState= BluetoothAdapter.STATE_OFF;
 768         int pendingState = BluetoothAdapter.STATE_TURNING_ON;
 769
 770         if (state == BluetoothAdapter.STATE_OFF) {
 771             expectedCurrentState= BluetoothAdapter.STATE_ON;
 772             pendingState = BluetoothAdapter.STATE_TURNING_OFF;
 773         }
 774
 775         for (int i=0; i <services.length;i++) {
 776             String serviceName = services[i].getName();
 777             String simpleName = services[i].getSimpleName();
 778
 779             if (simpleName.equals("GattService")) {
 780                 Integer serviceState = mProfileServicesState.get(serviceName);
 781
 782                 if(serviceState != null && serviceState != expectedCurrentState) {
 783                     debugLog("setProfileServiceState() - Unable to "
 784                         + (state == BluetoothAdapter.STATE_OFF ? "start" : "stop" )
 785                         + " service " + serviceName
 786                         + ". Invalid state: " + serviceState);
 787                         continue;
 788                 }
 789                 debugLog("setProfileServiceState() - "
 790                     + (state == BluetoothAdapter.STATE_OFF ? "Stopping" : "Starting")
 791                     + " service " + serviceName);
 792
 793                 mProfileServicesState.put(serviceName,pendingState);
 794                 Intent intent = new Intent(this,services[i]);
 795                 intent.putExtra(EXTRA_ACTION,ACTION_SERVICE_STATE_CHANGED);
 796                 intent.putExtra(BluetoothAdapter.EXTRA_STATE,state);
 797                 startService(intent);
 798                 return;
 799             }
 800         }
 801     }
 802
 803
 804     @SuppressWarnings("rawtypes")
"packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterService.java" 2555 lines --30%--  

?for (int i=0; i <services.length;i++) {

这里面有个for循环,就是一个一个打开service的,最后调用的是startService(intent);

但是问题又来了,这些service是怎么来的呢,怎么去拿到的,卧槽,你的问题太多了。

profile service启动配置

?

看到那个R.bool.xxx没有,丢,我不想说了,差不多了,Config.java去配置的。

?是这个config.xml,但是要注意overlay,device会覆盖掉

?最后就是在这里去配置打开运行的,很多时候,有些profile不想跑的时候,可以去关闭,完。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-27 11:58:42  更:2021-08-27 12:00:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/31 6:13:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码