Xiaolong的个人博客

每一天都值得被认真对待


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

  • 爱过的人

String中intern方法的作用

发表于 2018-05-23 | 分类于 Java基础

前言

读完这篇文章你可以了解,String对象在虚拟机内存中的存放,intern的作用,这么多String对象的创建到底有什么区别,String 创建的对象有几个!!

进入正题

先科普几个知识点

1.常量池存放于方法区中

2.jdk1.6 方法区放在永久代(java堆的一部分),jdk1.7 特别将字符串常量池移动到了的堆内存中(使用参数-XX:PermSize 和-XX:MaxPermSize指定大小),jdk1.8放在单独的元空间里面(-XX:MaxMetaspaceSzie设定大小),和堆相独立。所以导致string的intern方法因为以上变化在不同版本会有不同表现。

  1. jdk1.6将Hotspot虚拟机使用永久代来实现方法区,因为方法区的内存回收跟堆内存回收其实没什么区别,这样实现可以用垃圾收集器来管理这部分内存,但这样容易导致内存溢出(达到-XX:MaxPermSize)。
    这里写图片描述

JDK1.6,JDK1.7常量池的存放如下都存放于堆内存中
这里写图片描述
JDK1.8常量池的存放如下
这里写图片描述

具体可参考:https://blog.csdn.net/zhyhang/article/details/17246223/

知道了常量池在内存中的存放后,我们需要先了解一下 String str=”abc”;和 String str =new String(“abc”);的区别

1.String str=”abc”;

JDK1.6
(1) 当常量池中不存在”abc”这个字符串的引用,在堆内存中new一个String对象,复制这个对象加入常量池,返回常量池中的对象。
这里写图片描述

(2) 当常量池中存在”abc”这个字符串对象,str指向这个对象的引用;

这里写图片描述

JDK1.7以上
(1) 当常量池中不存在”abc”这个字符串的引用,在堆内存中new一个新的String对象,将这个对象的引用加入常量池。(跟1.6的区别是常量池不再存放对象,只存放引用。)
(2) 当常量池中存在”abc”这个字符串的引用,str指向这个引用;

2.String str =new String(“abc”)则是单纯的在堆内存中new一个String对象,通过StringBuilder 跟StringBuffer 构建的对象也是一样

3.intern方法 (返回常量池中该字符串的引用)

(1) 当常量池中不存在”abc”这个字符串的引用,将这个对象的引用加入常量池,返回这个对象的引用。
(2) 当常量池中存在”abc”这个字符串的引用,返回这个对象的引用;

测试代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
String str1 = "计算机";
String str2 = "计算机";
System.out.println("str1==str2:" + (str1 == str2));
String str3 = new String("计算机");
System.out.println("str1==str3:" + (str1 == str3));
System.out.println("str1==str3.intern():" + (str1 == str3.intern()));
System.out.println("str2==str3.intern():" + (str2 == str3.intern()));
String str4 = new String("计算机");
System.out.println("str3==str4:" + (str3 == str4));
System.out.println("str3.intern()==str4.intern():" + (str3.intern() == str4.intern()));
String str5 = new StringBuilder("软件").append("工程").toString();
System.out.println("str5.intern() == str5:" + (str5.intern() == str5));
String str6 = new String(new StringBuilder("物联网").append("工程").toString());
System.out.println("str6.intern() == str6:" + (str6.intern() == str6));
String str7 = new String("物联网");
System.out.println("str7.intern() == str7:" + (str7.intern() == str7));

JDK1.8输出结果如下:

str1==str2:true
str1==str3:false
str1==str3.intern():true
str2==str3.intern():true
str3==str4:false
str3.intern()==str4.intern():true
str5.intern() == str5:true
str6.intern() == str6:true
str7.intern() == str7:false

这里着重讲解一下为什么str5,str6和str7的结果不一样,

str7直接用new String(”物联网”)创建,”物联网”这字符串在一出现就自动创建成对象存放到常量池中,所以常量池里面存放的是”物联网”字符串的引用,并不是str7创建的对象的引用。

str5是通过StringBuilder构建的 在new StringBuilder(“软件”).append(“工程”).toString方法运行后,”软件工程”这个字符串对象才第一次出现。执行了intern方法后str5才被放到常量池中,此时str5跟str5.intern是同一个对象。

str6是作为对照组出现,这里为了确认StringBuilder 在toString方法执行后会不会把最终字符串放进常量池。很显然并没有,所以str6的intern才会跟str6是同一个对象。同时它也能验证出str7的new String()方式在初始化的时候就会把”物联网”字符串放进常量池中,同理我们可以得出在str5构建的时候常量池里面加入了”软件”,”工程”这两个字符串(可以自己动手去验证一下!!)。

JDK1.7结果如下

str1==str2:true
str1==str3:false
str1==str3.intern():true
str2==str3.intern():true
str3==str4:false
str3.intern()==str4.intern():true
str5.intern() == str5:true
str6.intern() == str6:true
str7.intern() == str7:false

当然JDK1.6我们也能大致明确,输出结果会如下

str1==str2:true
str1==str3:false
str1==str3.intern():true
str2==str3.intern():true
str3==str4:false
str3.intern()==str4.intern():true
str5.intern() == str5:false
str6.intern() == str6:false
str7.intern() == str7:false

分析一下jdk1.6中 str5.intern() == str5的结果为什么为false,这里可以这么看在软件工程这个对象中构建完成之后,常量池里面其实存放的只有“软件”,”工程”这两个字符串,而”软件工程”这个字符串是存放于堆内存中的。所以JDK1.6执行了intern后会把“软件工程”复制到常量池中,并返回常量池中的对象。常量池中的”软件工程”跟堆内存中的软件工程并不是同一个。

因为没有尝试过,如果jdk1.6有不一致的地方欢迎大家指点。

总结

1.String对象可能会在堆内存中分配一块空间创建一个String对象,在常量池中创建该对象的复制jdk 1.6(或引用jdk 1.7及以上),也可能直接指向常量池(永久带)中的引用(例String str=”xxx”)。还有一种可能是直接在堆内存中分配一块空间创建一个String对象(例 String str=new String(xxx))。

2.intern方法可以看成返回常量池中该字符串对象的引用。如果没有该字符串对象就把这个对象(或引用)加到常量池。

3.jdk1.6跟jdk1.7以上的区别是当常量池中不存在这个字符串,jdk1.6是直接复制对象到常量池,而jdk1.7以上是把对象的引用加入常量池。

4.类似于”abc”这样的字符串,在第一次被使用到(比如String a=”abc”或者String a=new String(“abc”)或者”abc”.equals(xxx))后就会被加载到常量池中去。

5.面试问题:

(1)现在当有人问 String str = new String(“abc”);创建了几个对象,常量池有abc字段是1个,常量池没有”abc”字段则是2个。
(2)String str=”abc”;创建了几个对象(如果常量池里面已经有对象了就是0个。如果没有,JDK1.6 2个,JDK1.7以上 1个);
(3)new String(“abc”).intern();创建了几个对象(如果常量池里面已经有该字符串对象了就是1个,如果没有就是两个)

以上是关于String中intern的作用和个人对于内存的一些理解,希望大家有所收获,也期待和大家交流。

RecyclerView的那些事

发表于 2018-05-02 | 分类于 Android

RecyclerView是什么

RecyclerView是V7兼容包下的一个列表布局,可以实现复杂的列表,我们经常拿他与ListView做比较,相较于原来的列表布局实现,RecyclerView提供的方法更加开放,给用户提供了更多的可选择实现方式。
在动画和加载效率方面做了更多优化。

使用RecyclerView 有什么优势?

1.自定义LayoutManager

RecyclcerView不止支持实现ListView结构,也支持实现GridView结构,甚至以前用ListView,GridView实现的瀑布流和一些复杂的样式都能用RecyclcerView来实现。

RecyclerView默认实现了三种LayoutManager(LinearLayoutManager,GridLayoutManager,StaggeredGridLayoutManager)分别用来实现ListView,GridView和瀑布流的效果,如果这些布局效果不满足你的应用,那你可以自己重写LayoutManager写一个你喜欢的样式。

CustomLayoutManage2
CustomLayoutManage2

2.自定义ItemDecoration(分割线)

ListView的实现支持我们设置一个自定义的Drawable,来做分割线。

RecyclerView开放了一个ItemDecoration类,我们可以自己实现这个类来做出花哨的装饰样式,包括分割线。

以前GridView实现不了分割线,RecyclerView可以!!

RecyclerView提供了自带的分割线实现类DividerItemDecoration。
CustomLayoutManage2

3.自定义ItemTouchHelper

RecyclerView支持自己实现ItemTouchHelper,用来做Item的一些移动等手势操作。
MainTouchHelper

4.Adapter中获取item的类型

RecyclerView支持实现getItemViewType根据不同的数据或者某些条件返回不同的itemType,而在Inflate的时候用户可以根据不同的itemType inflate不同的布局。

5.列表局部刷新

RecyclerView提供了局部刷新的接口,通过局部刷新,就能避免调用许多无用的bindView.
rv

(RecyclerView和ListView添加,移除Item效果对比)

结合RecyclerView的缓存机制,看看局部刷新是如何实现的:
以RecyclerView中notifyItemRemoved(1)为例,最终会调用requestLayout(),使整个RecyclerView重新绘制,过程为:
onMeasure()–>onLayout()–>onDraw()

其中,onLayout()为重点,分为三步:

  1. dispathLayoutStep1():记录RecyclerView刷新前列表项ItemView的各种信息,如Top,Left,Bottom,Right,用于动画的相关计算;
  2. dispathLayoutStep2():真正测量布局大小,位置,核心函数为layoutChildren();
  3. dispathLayoutStep3():计算布局前后各个ItemView的状态,如Remove,Add,Move,Update等,如有必要执行相应的动画.

其中,layoutChildren()流程图:
s

s
当调用notifyItemRemoved时,会对屏幕内ItemView做预处理,修改ItemView相应的pos以及flag(流程图中红色部分):
s

当调用fill()中RecyclerView.getViewForPosition(pos)时,RecyclerView通过对pos和flag的预处理,使得bindview只调用一次.

需要指出,ListView和RecyclerView最大的区别在于数据源改变时的缓存的处理逻辑,ListView是”一锅端”,将所有的mActiveViews都移入了二级缓存mScrapViews,而RecyclerView则是更加灵活地对每个View修改标志位,区分是否重新bindView。

6.View缓存

缓存层级

RecyclerView比ListView多两级缓存,支持多个离ItemView缓存,支持开发者自定义缓存处理逻辑,支持所有RecyclerView共用同一个RecyclerViewPool(缓存池)。

具体来说:
ListView(两级缓存):
ListView
RecyclerView(四级缓存):
RecyclerView

ListView和RecyclerView缓存机制基本一致:

1). mActiveViews和mAttachedScrap功能相似,意义在于快速重用屏幕上可见的列表项ItemView,而不需要重新createView和bindView;

2). mScrapView和mCachedViews + mReyclerViewPool功能相似,意义在于缓存离开屏幕的ItemView,目的是让即将进入屏幕的ItemView重用.

3). RecyclerView的优势在于a.mCacheViews的使用,可以做到屏幕外的列表项ItemView进入屏幕内时也无须bindView快速重用;b.mRecyclerPool可以供多个RecyclerView共同使用,在特定场景下,如viewpaper+多个列表页下有优势.客观来说,RecyclerView在特定场景下对ListView的缓存机制做了补强和完善。

缓存方式

1). RecyclerView缓存RecyclerView.ViewHolder,抽象可理解为:
View + ViewHolder(避免每次createView时调用findViewById) + flag(标识状态);
2). ListView缓存View。

缓存不同,二者在缓存的使用上也略有差别,具体来说:
ListView获取缓存的流程:
listview缓存
RecyclerView获取缓存的流程:
recyclerView缓存

1). RecyclerView中mCacheViews(屏幕外)获取缓存时,是通过匹配pos获取目标位置的缓存,这样做的好处是,当数据源数据不变的情况下,无须重新bindView:
ss
而同样是离屏缓存,ListView从mScrapViews根据pos获取相应的缓存,但是并没有直接使用,而是重新getView(即必定会重新bindView)

2). ListView中通过pos获取的是view,即pos–>view;
RecyclerView中通过pos获取的是viewholder,即pos –> (view,viewHolder,flag);
从流程图中可以看出,标志flag的作用是判断view是否需要重新bindView,这也是RecyclerView实现局部刷新的一个核心.

只用一个RecyclerView如何实现复杂布局

有个需求是这样的,我们需要做一个图片列表的展示但是不同的图片我要给他不一样的权重来让他显示不同的占比。比如下图。

imageRecyclerView

如果页面结构比较简单的情况下(默认顶部区域和最底部区域是一样的)可能会把中间那两块区域做成一个特殊的ViewType.只有中间的八个小方格和两个大方格是特殊区域,这个时候就可以把八个小方格做一个特殊的ViewType,两个小方格做一个特殊的ViewType.加载进去。

如果所有的方格都是列表中的一个项,这边有可能需要解决数据源的问题。

但其实这整个布局用一个GridLayoutManager能够一次实现。

这都要归功于GridLayoutManager提供的一个方法setSpanSizeLookup,它提供了一个SpanSizeLookup的抽象,我们可以实现它的getSpanSize方法。
有这个方法,我们可以把不同大小的布局设置不同的ViewType,getSpanSize给不同的ViewType设置不同的占位。最终达到一个RecylcerView实现复杂布局的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
switch (displayAdapter.getItemViewType(position)) {
case 1:
return 4;
case 2:
return 1;
case 3:
return 2;
default:
return 4;
}
}
});

GridLayoutManager其实就是LayoutManager的一个实现,从这个方法可以看出只要我们掌握了自定义的LayoutManager,整个RecyclerView想长什么样子就都掌握在你的手中了。

实现效果

demo地址:https://github.com/guoxiaolongonly/RecyclerViewDemo

参考:

Android ListView与RecyclerView对比浅析–缓存机制:https://blog.csdn.net/tencent_bugly/article/details/52981210

从零开始写一个蓝牙SPP通讯

发表于 2018-04-03 | 分类于 Android蓝牙

流程思考

这边有几个需求点,

1.一个统一的蓝牙管理类,BtManger,针对蓝牙连接和各种数据回调处理。

TIM截图20180330145900.png

变量说明一下,
(1)BluetoothAdapter 是一个本地蓝牙适配器,可以用来查询设备,获取已配对设备列表,通过MAC连接蓝牙设备,做蓝牙接入监听,还有蓝牙开关状态等等。可以通过获取系统的BluetoothManager来获取,也可以直接通过BluetoothAdapter获取一个默认的BluetoothAdapter,

1
2
3
BluetoothManager btManager = (BluetoothManager) context
.getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = btManager.getAdapter;
1
2
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

两种方式的区别在于,第一种方式可以通过btManager来获取蓝牙的一些状态信息,包括已连接的设备列表等…

(2)Context上下文,如果有全局的蓝牙处理需求,建议在Application创建的时候传入应用上下文,这个上下文需要注册广播还有一些其他的功能,如果不是声明周期长的Activiy会导致内存泄露。
(3)BluetoothTransferService 传输服务类,提供设备连接,还有蓝牙Socket数据传输。后面会详细讲到。
(4)BluetoothStatusReceiver 广播接收器,用来接收蓝牙状态的广播,蓝牙开启/关闭。
(5)BluetoothScanRecevier 广播接收器,用来接收蓝牙设备扫描的广播
(6)BtManager 蓝牙管理类的单实例,因为蓝牙SPP对接整个周期只做一个,没必要每次都创建新的连接。
(7)DeviceHandler 这个类用来做跨线程的诸多状态的通信。(整个连接,监听,和传输过程都放在线程中)

2.蓝牙搜索,需要有一个能搜索附近的蓝牙的回调
TIM图片20180328151248.png
整个设计大致如下,BluetoothDevice为蓝牙设备信息,rssi为信号强度,提供单设备扫描,扫描超时,和全部扫描结束列表回调

3.蓝牙对接,需要有一个能让用户知道蓝牙连接状态的回调 成功,失败,中断等..

TIM图片20180328152721.png
四个方法分别 是连接中,已连接,断开连接,等待接入,连接到设备

4.蓝牙数据传输(发送),这个是重点,分析一下这一块需要的功能,(1)发送消息的功能,称之为sendMessage。(2)消息可能是一个文件,可能是一长串字节流,可能是一个int数组,也可能是一串字符串,好了这边这边提供一个抽象。提供一个基础的RequestMessage,和getRequestBody根据不同的文件类型做策略包装。甚至可以提供静态工厂来包装一个这样的对象;

5.蓝牙数据传输(接收),这个也是重点,分析一下这一块需要的功能,(1)接收消息的功能,当消息接收完毕后告诉用户。(2)消息可能是一个文件,可能是一长串字节流,可能是一个int数组等等。提供一个扩展的接口用来做消息处理,针对不同的消息做不同的处理。提供一个基础的 ResponseMessage,getResponseBody也做策略封装。

6.分包传输,分包接收这类的机制。降低仪器数据量大小限制

7.最后针对以上的功能提供一些静态的方法做数据处理,ByteUtil,FileUtil等。

协议定制

需求如下既要考虑到不同文件的传输,又要考虑到文件传输的大小限制。

协议可以这么做

  1. 包头,当接收到头部的时候代表一次请求开始,
  2. 文件名称,如果当前传输为文件的话填入文件名称否则为00 00;
  3. 总包数 针对数据太大的问题采用分包发送,AllPack总包
  4. 分包 当前传出分包
  5. 数据区长度 传输的数据区长度,用来确认接下来需要读取的字节数
  6. 数据 待传输数据,可以为空
  7. 校验和 针对前面传输数据的累加和,取低位

具体内容如下

包头 0x7e 0x7e 两个十六进制数 占两字节

文件名称 00 00 … 占50字节大致能传16个UTF-8中文字符和1个英文字符,或者50个英文字符,扩展名算进去。

总包数 00 01 占两个字节
分包 00 01 占两个字节
数据区域长度 00 01 占两个字节
数据 01 占1-n个字节
校验和 00 占一个字节,取低位 假设文件名为空数据为01 校验和为 7e+7e+01+01+01+01=01 00 取低位得00

一个完整的包如下

7e 7e 00 00… 00(50个00) 00 01 00 01 00 01 00 01 00

完美!!

编码阶段

demo地址:https://github.com/guoxiaolongonly/AndroidBluetooth

实现简单的聊天功能。文件名称也采用跟文件内容一样长度(2字节)加名称(长度字节)。

2017年总结

发表于 2018-03-13 | 分类于 阶段性总结

闲谈

有些时候真的不得不佩服有一些人真的是牛逼,跟我同事对比才发现人家看了编程思想是真的读懂了,我看了编程思想是看了一遍。最近问了他一些问题感觉他都能对答如流,想各种解决方案,不禁感觉自己书是不是白看了。最近重新把java编程思想拿起来看,才发现有很多以前没注意到的细节。书确实要多读,一遍没读透就读两遍,三遍。再困难也不要忘了提升自己!!

反思

这边其实更多的是对去年的反思吧,感觉很多时候基本都是要打脸之后才能明白自己所处的位置。在经过了一轮简历的投递和内推之后发现自己并没有特别多的优势,基本上全军覆没了,连面试机会都没有,这里分析一下问题根本原因,现在Android开发真的是烂大街,作为一个两年工作经验的,想找一份好的工作真的很难。去年一整年也基本没有太大的提升,仅仅是把重复工作做的更加熟练而已,所以也思考出自身的一些问题和解决方案。

问题

  1. 大厂基本都直接校招,社招的要求基本很严格。
  2. 小公司大部分技术不成熟,很多时候一个人要做很多的活,接触的面虽然广,但是不精,这个其实就跟做重复工作没什么区别了。
  3. 个人上跳槽频繁,让HR觉得稳定性不高。
  4. 技术并不是过硬,虽有博客github,并没有多大优势。

解决方案

  1. 了解一线大厂需求,充实简历
  2. 小公司尽量避免不去了。
  3. 找一家的公司稳定待个几年。
  4. 技术充实,每个月一篇博客,每天坚持github push开源
  5. 打好扎实的java基础,多线程编程,网络编程思想,内存管理,java虚拟机

以上!!


2018-03-17 00:44:37

那个…. 找到简历没回复的原因了,个人简历都忘了填联系方式了。一个朋友帮我内推的时候发现的。艾玛,果然本命年!!

2018年3月22日 22:52:52

思考了一下最近面试的一些问题(没回答好的)。

1.如何优化页面加载

在这边其实我一直在View层面考虑这个问题
回答了一些点,比如
1.减少View的层级,尽量不使用背景
2.List中复用View
3.自定义控件开硬件加速(- -!!然后被问了硬件加速原理,呃,这边其实就是想让你知道GPU可以加速绘制)还是没有回答到点,然后面试官引导了一下我,ListView的加载卡顿怎么办。
4.一想就是把耗时操作写到线程中去(还是没get到点)
5.等到滑动结束后再做加载(还是没get到点)
6.最后其实是CPU可能在做一些其他计算也会影响界面的性能。那这里其实可以在页面加载的时候减少一些后台操作。

2.关于性能优化这一块
1.我直接回答MAT,找到一些无法被释放的对象,排查相应的内存泄露原因。
面试官继续问直接用MAT吗?还有其实你这个只是在排查内存溢出的情况,如果是性能优化其实更多的是从一些对象维护了一些冗余的数据。导致这些类没办法做释放,这一块需要考虑到性能优化。
那么这边其实,可以先用Memory Monitor看页面内存结构,有哪一些大对象,System Trace,来看一下哪一些页面启动花时间(耗CPU)。然后再用MAT来分析具体是哪些对象。
性能优化无异于以下几个点
1.从渲染过程优化 View绘制,层级等。
2.一些计算过程可以简化尽量简化
3.内存相关,这个时候就是排查大对象,内存占用。
4.电量相关,啊这个一般没人管。Android8.0对后台进程耗电做了优化。
5.具体可以看看这个 http://hukai.me/android-performance-patterns/ 总共6季

以上是性能优化相关接下来是java基础Android基础和一些数据结构,算法和设计模式了。

java基础

1.接口和抽象的区别

接口 implements 多继承,灵活易扩展组合。

抽象 extends abstracts关键字修饰 单继承 内部可以带有实现。

抽象不易于维护,接口优于抽象

2.集合框架:HashMap的实现原理

散列桶,每个桶都实现了一个链表,如果hash值相等了,那么就往相应链表里加。链表的查询效率是O(n) jdk1.8采用了红黑树结构,当链表长度大于阈值8则转为红黑树 查询效率更高O(lgn)
扩容系数是0.75,2倍扩容,默认大小16。 java建议容器类如果能确定大小需手动指明大小。

hashmap和hashtable 的区别,hashtable的方法带有synchronize关键字,是线程安全的。hashmap不是。
jdk1.4出的ConcurrentUtil包 有一个 ConcurrentHashMap提供了一种分段锁机制,比hashtable更高效。
CopyOnWriteArrayList,CopyOnWriteArraySet这个是concurrent工具包里面的另外两个线程安全的集合。

3.多线程

violate关键字和synchronized 关键字

乐观锁悲观锁,讲一下乐观锁,乐观锁就是不对数据加锁,每次更新拉一个版本,谁先提交算谁赢。
悲观锁则是需要对数据做加锁。以实现资源同步。

Lock和synchronized

这边也没回答好,但其实是Lock更灵活,他可以放在异常捕获finally中来解除资源占用。

5.内存相关

1.内存分区 方法区,虚拟机栈,本地方法栈,堆,程序计数器 他们分别做什么的。这个就答不出来了
2.类引用的引用什么,当然是地址啦。不要覆盖toString方法可以打印的。

算法

几种排序算法还有他们的时间复杂度。 时间按复杂度。。。。

1.选择排序:不稳定,时间复杂度 O(n^2)
2.插入排序:稳定,时间复杂度 O(n^2)
3.冒泡排序:稳定,时间复杂度 O(n^2)
4.堆排序:不稳定,时间复杂度 O(nlog n)
5.归并排序:稳定,时间复杂度 O(nlog n)
6.希尔排序:不稳定,时间复杂度 平均时间 O(nlogn) 最差时间O(n^s) 1<s<2
7.快速排序:不稳定,时间复杂度 最理想 O(nlogn) 最差时间O(n^2)

快排就选取一个点其他数据往两边排,然后两边选点再排,分治思想

设计模式

单例,工厂,享元,策略,装饰器,适配器,建造者,动态代理,代理…等等等

反正我是很容易把策略,装饰器,适配器搞混。。 艾玛24种,这个得整理一下.

被问的一个问题是最快的单例模式,用枚举实现。听的我一脸懵,后面发现Effective Java 上面有相关的内容。

Android基础

老生常谈的那些,Activity启动,数据存储,页面恢复,事件分发,View绘制,三种动画,IPC,多线程的几种方式,Binder,Handler,ThreadLocal。
然后就是个gradle 构建项目
然后就是一些能使用到的技术,插件化,模块化,AOP编程。
然后就是闲谈一些经验了。

TCP/IP

三次握手

IO/NIO

普通IO:直接操作流

NIO:操作数据缓冲区 ,DataBuffer,Channel,Selector

这是两场面试的心得。有没写到的再补充

总结:2年了,还是那么菜。

接下来要看的一些东西

  1. Effective JAVA
  2. JAVA多线程编程
  3. JVM虚拟机
  4. JAVA网络编程
  5. 设计模式
  6. IO/NIO

2018年4月1日 18:17:40

找工作的事情放缓,着手学习,写代码,感谢这次面试经历。特别是美图的Boss!!

By xiaolong:You have a dream,you got to protect it!

写一个旅行青蛙攻略APP

发表于 2018-02-09 | 分类于 个人开源

界面效果如下

启动页
首页
小伙伴
收藏
特产
称号

不要忘了我们的所有数据和界面都可以在github的json文件里面配置有需要的小伙伴自行拿去用吧!!

项目github地址
Apk下载地址

设计意图

最近旅行青蛙很火,我自己也在玩,然后发现一个痛点是每次找小动物喜欢吃什么,每个道具的用途,都需要打开浏览器搜索。实在不能忍,感觉很痛,于是决心自己写一个APP攻略!!

需求分析

1.需要先对界面上的每个功能放一张图解,还有基本玩法操作!!

2.针对出现的每个道具的名称和用途做一个分类查看器,描述名称,用途等… 比如说商城道具和带回来的特产,收藏品,抽奖的奖品等…

3.如果单机版其实就这么考虑。后面觉得应该做一个动态数据的功能。(因为如果游戏有新版本更新了APP也得更新新版本,所以我想给APP一个接口,用来传输每次更新的数据。这样我们就不用每次发一个版本了。 very nice!!)

4.既然需要提供接口,就需要一个服务器了。这边其实是有多种考虑。

  • bomb后端云,这种免费后端数据库可以一键式增删改查,这个可是上上之选。
  • 写个页面,导入jsoup,动态爬数据,技术帝的不二选择,不过网页经常变感觉还是很蛋疼的。
  • 哈哈哈哈哈哈,因为我比较懒,不想再去看文档,所以在github上面写了一个json文件,发现文件在github上的页面结构好像跟平时json请求的一样,试着做了一下请求。发现鸡然可以,那就用github来维护吧,反正博客都github上搭过了)

产品规划

coding之前的一些其他细节,首现是需要什么样的页面,怎样才能长得好看。噗,自己写APP都要兼职PM.UI.UE。 心疼的抱住了自己。  

1.页面既定的规划就是提供一个首页,实现列表对每个模块做划分,

  • 入门操作,因为日版的APP很多东西还是看不懂的,做一个引导用户入门。
  • 商店道具和作用介绍
  • 收藏品介绍
  • 特产介绍
  • 称号介绍
  • 小动物喜欢吃什么
  • 进阶攻略 提供一些骨灰级玩家需要的信息。(比如收割草,给小动物喂食什么合适等等..)
  • 更新数据
  1. 根据需求其实已经很明了了首页6个tab,
    • 入门和进阶
    • 小动物介绍
    • 商店道具介绍
    • 特产介绍
    • 称号介绍
    • 收藏品介绍
    • 另外配置一个侧拉的View用来展示作者介绍,和数据更新,2333,装逼用!!

Then coding

主要是考虑动态配置问题,不同数据分配不同页面

1.首页一个列表用来展示所有模块

2.模块下面可能有子模块,根据类别启动子模块的Activity。

3.功能,不同功能展示的页面效果也不一样。gridView

  • 小动物,中图,中文字描述,点击查看详情gridView
  • 商店道具,中图,中文字描述,点击查看详情gridView
  • 特产,小图,小文字描述,点击查看详情gridView
  • 称号,中图,中文字描述,点击查看详情gridView
  • 收藏品,中图,中文字描述,点击查看详情gridView
  • 入门和进阶,子模块,实现做图右文字列表做选择gridView
  • 详情页大图大文字listView 图片+文字每个段落
  • 预留一个webActivity做web加载。 预留一个TextActivity做文本加载

4.两种类型的模块选择页 ModularGridViewActivity,ModularListViewActivity.

5.三种详情查看页 BigPicDetailActivity,WebActivity,TextActivity

6.两种描述页 MiddleDecribeActivity,SmallDeScribeActivity

7.侧拉菜单

8.关于APP

最近太忙了,没时间写这个,今天花了一天时间把它全部做完了,功能设计什么的都不难,就是界面和一些交互体验,还有素材整理花了点时间。最终实现的结果可能跟之前预想的不太一样。

谈一谈不一样的地方
小动物,商店道具,特产,称号,收藏品,入门和进阶的页面,我写到了一个页面中。
原本预想其实就是分成好几个Activity来写,但是后来想想写了那么多Activity其实参数都一样,逻辑也都一样,就是页面的布局不一样而已。
写那么多的Activity其实可以写成一个Activity,然后Adapter做抽象,实现不同的 Adapter来实现不同的列表。
后面又想了一下,Adapter其实也不用做什么操作,只有布局不一样,点击响应和数据传递都是一样的。就把布局直接传给了Adapter。由数据来确定初始化什么布局,和布局的样式。
最终实现就是这样,但是也看出了这样实现的一些弊端,就是不适合数据量大的场景。不过我们的数据量确实不大,就先这样了!!nice day!!


就写到这里了。攻略也不想整理了!!!! 因为根本就找不到用户 2333!!

By Xiaolong,每一天都值得被认真对待!

蓝牙协议学习整理(四)蓝牙协议规范(irOBEX、BNEP、AVDTP、AVCTP)

发表于 2017-12-29 | 分类于 Android蓝牙

一、IrDA互操作协议

IrOBEX 红外对象交互协议,简称OBEX,使高层协议同时运作在蓝牙和红外的无线链路之上。

这里写图片描述

主要操作指令有:连接操作、断开操作、Put操作、Get操作。

1、连接操作 ,操作码0x80

字节0字节1、2字节3字节4字节5、6字节7~n
0x80连接请求分组长度OBEX版本号标志客户端可接收最大的OBEX分组长度可选头

这里写图片描述

字节0字节1、2字节3字节4字节5、6字节7~n
0x80Connect命令70x10标志65534可选头

连接响应
1

2、断开操作

操作码为0x81

3、Put操作

操作码为0x02

连接成功后,客户端通过Put请求向服务器“推送”对象,如果对象较大,Put请求可以用多个Put请求分组。

这里写图片描述

4、Get操作

操作码为0x03

二、音频与电话控制协议

1、框架部分

这里写图片描述

蓝牙音频如上图协议栈所示:音频通过基带传输同步面向连接分组实现,没有以规范的形式给出,不是协议栈的一部分。
TCS_Binary是一种基于分组电话控制二进制编码指令集,位于L2CAP之上。实现蓝牙无绳电话、对讲机功能。
RFCOMM用于AT指令,拨号上网、蓝牙耳机、耳麦、传真通过AT发送指令控制。

2、音频部分

64kbps电信级语言质量音频流
CVSD continuous variable slope delta 连续可变斜率增量。
PCM pulse code modulation 。
PCM存在斜率效应。CVSD使用音节压缩算法,编码步长根据信号斜率变化自动调整,是现在比较好的编码方案,提高语言的抗干扰能力。

3、电话控制部分

TCS-Binary电话控制部分。

(1)、电话呼叫

呼叫控制、呼叫建立、呼叫拆除;

(2)、组管理

访问权限请求、分布式配置、快速内部成员访问。

三、网络封装协议 BNEP

BNEP BluetoothNetworkEncapsulation Protocol 网络封装协议。
为了使集成蓝牙技术的电脑、电话、PDA、家用电器等网络设备交换信息,需要在网络层统一数据分组。网络封装协议将来自不同网络的数据分组重新封装,通过L2CAP进行传输。这部分协议感觉在现实中用处不大,有更多简单便捷的方法去实现网络功能。
BNEP支持Ipv4、Ipv6、IPX

这里写图片描述

四、音视频分发协议AVDTP

AVDTPAudio/Video Distribution Transport Protocol音视频分发传输协议

这里写图片描述

有关A/V的协议 AVDTP音视频分发传输协议、AVCTP音视频控制传输协议、GAVDP通用音视频分发框架、A2DP高级音频分发框架、AVCRP音视频遥控框架

1、基本概念术语

流stream:流是音视频传输的数据形式,单向传输,在AVDTP中被分为媒介分组。流有句柄HS统一标识。

这里写图片描述

2、信令

AVDTP信令列表

命令信令标识符描述
AVDTP_DISCOVER0x01发现设备中的流端点
AVDTP_GET_CAPABILITIES0x02获得流端点的信息能力
AVDTP_SET_CONFIGURATION0x03对SEP进行配置
AVDTP_GET_CONFIGURATION0x04获取SEP当前配置
AVDTP_RECONFIGURE0x05对SEP重新配置
AVDTP_OPEN0x06成功的配置SEP后,打开流
AVDTP_START0x07流被打开:用于开始形成流;流暂停时:用于重新形成流。
AVDTP_CLOSE0x08对SEP关闭
AVDTP_SUSPEND0x09请求SEP暂停
AVDTP_SECURITY_CONTROL0x0A设置设备内容保护、或者请求设备状况信息
AVDTP_ABORT0x0B中断正在建立或者传输的过程
AVDTP_GET_ALL_CAPABILITIES
AVDTP_DELAYREPORT
这部分信令,实现了蓝牙的A2DP 数据流的控制

(1)、流的信令管理流程

这里写图片描述

这里写图片描述

(2)、get capabilities 获取支持特性

这里写图片描述

(3)、set configuration 配置音频参数

这里写图片描述

其他指令类似去上面两个的操作。

五、音视频控制传输协议AVCTP

这里写图片描述

AVCTP可以使音视频设备同时支持多个应用框架,每个应用框架定义了各自相应的消息格式与应用规则。

这部分操作,在现实的应用中也有不足的地方,蓝牙传输的数据量有限,实现这些功能有一定的不足。随着科学技术的发展,蓝牙在无线通信方面的优点、缺点都凸显出来,找的合适的方向,合理的发展方向是硬道理。

蓝牙芯片厂商:

CSR公司(Cambridge Silicon Radio)(目前最大的蓝牙芯片的全球供应商)

Broadcom公司

ISSC公司

TI公司 (CC2541)

MTK公司(MT6620)

传送门:

(一)蓝牙的概述
(二)蓝牙协议规范(射频、基带链路控制、链路管理)
(三)蓝牙协议规范(HCI、L2CAP、SDP、RFOCMM)
(四)蓝牙协议规范(irOBEX、BNEP、AVDTP、AVCTP)

引用自xubin的博客

By Xiaolong,每一天都值得被认真对待!

蓝牙协议学习整理(三)蓝牙协议规范(HCI、L2CAP、SDP、RFOCMM)

发表于 2017-12-29 | 分类于 Android蓝牙

第三章 蓝牙协议规范(HCI、L2CAP、SDP、RFOCMM)

一、主机控制接口协议 HCI

蓝牙主机-主机控模型
这里写图片描述

蓝牙软件协议栈堆的数据传输过程:
这里写图片描述

1、蓝牙控制器接口数据分组:

指令分组、事件分组、数据分组

(1)、指令分组
这里写图片描述

这里写图片描述

如:Accpet Connection Request

  • Opcode为:0x0409
  • 参数长度为: 07
  • 参数中蓝牙地址为:00:0d:fd:5f:16:9f
  • 角色为:从设备 0x01

大端数据模式

  • 指令为:09 04 07 9f 16 5f fd 0d 00 01

(2)、事件分组
这里写图片描述

这里写图片描述
如上图:

  • Opcode :0x0409
  • 状态: 0x00
  • 总长度: 4字节
  • 命令状态:0x0f

(3)、数据分组
ACL 数据分组

数据…………
连接句柄(12bit)PB(2bit)BC(2bit)数据长度(16bit)
注:PB  Packet_Boundary  BC Broadcast Flag

SCO 数据分组

数据…………
连接句柄(12bit)PB(2bit)BC(2bit)数据长度(16bit)

(4)、RS232分组指示器:

HCI分组类型RS232分组指示器
HCI指令分组0x01
HCIACL数据分组0x02
HCISCO数据分组0x03
HCI事件分组0x04
HCI错误消息分组0x05
HCI协商分组0x06

#### 2、HCI控制命令

(1)、链路控制指令

命令OCF概述
Inquiry0x0001蓝牙设备进入查询模式,搜索临近设备
InquiryCancel0x0002退出查询模式
PeriodicInquiryMode0x0003蓝牙设备在指定周期内自动查询
ExitPeriodicInquiryMode0x0004退出自动查询模式
CreateConnection0x0005按指定蓝牙设备的BD_ADDR创建ACL链路
Disconnect0x0006终止现有连接
AddSCOConnection0x0007利用连接句柄参数指定的ACL连接创建SCO
CancelCreateConnection0x0008
AcceptConnectionRequest0x0009接收新的呼入连接请求
RejectConnectionRequest0x000A拒绝新的呼入连接请求
LinkKeyRequestReply0x000B应答从主机控制器发出的链路密钥请求事件,并指定存储在主机上的链路密钥做为与BD_ADDR指定的蓝牙设备进行连接使用的链路密钥请求事件
LinkKeyRequestNegativeReply0x000C如果主机上没有存储链路密钥,作为与BD_ADDR指定的蓝牙设备进行连接使用的链路密钥,就应答从主机控制器发出的链路密钥请求事件
PINCodeRequestReply0x000D应答从主机控制器发出的PIN请求事件,并指定用于连接的PIN
PINCodeRequestNegativeReply0x000E当主机不能指定连接的PIN时,应回答从机控制器发出的PIN请求事件
ChangeConnectionPacketType0x000F改变正在建立连接的分组类型
AuthenticationRequest0x0011指定连接句柄关联的两个蓝牙设备之间建立身份鉴权
SetConnectionEncryption0x0013建立取消连接加密
ChangeConnectionLinkKey0x0015强制关联了连接句柄的两个设备建立连接,并生成一个新的链路密钥
MasterLinkKey0x0017强制关联了连接句柄的两个设备利用主设备时链路密钥或常规密钥
RemoteNameRequest0x0019获取远端设备的名称
CancelRemoteNameRequest
ReadRemoteSupportedFeatures0x001B请求远端设备所支持的特性列表
ReadRemoteExtendedFeatures
ReadRemoteVersionInformation0x001D从远端设备读取版本信息
ReadClockOffset0x001F读取远端的时钟信息

(2)、链路策略指令

命令OCF简介
HoldMode0x0001改变LM状态和本地及远程设备为主模式的LM位置
SniffMode0x0003改变LM状态和本地及远程设备为呼吸模式的LM位置
ExitSniffMode0x0004结束连接句柄在当前呼吸模式里的呼吸模式
ParkState0x0005改变LM状态和本地及远程设备为休眠模式的LM位置
ExitParkState0x0006切换从休眠模式返回到激活模式的蓝牙设备
QoSSetup0x0007指出连接句柄的服务质量参数
RoleDiscovery0x0009蓝牙设备连接后确定自己的主从角色
SwitchRole0x000B角色互换
ReadLinkPolicySettings0x000C为指定连接句柄读链路策略设置。链路策略设置允许主机控制器指定用于连接句柄的LM连接模式
WriteLinkPolicySettings0x000D为指定连接句柄写链路策略设置。链路策略设置允许主机控制器指定用于连接句柄的LM连接模式
ReadDefaultLinkPolicySettings0x000E
WriteDefaultLinkPolicySettings0x000F
FlowSpecification0X0010

(3)、主机控制器与基带指令

SetEventMark0x0001使能主机过滤HCI产生的事件
Reset0x0003复位蓝牙控制器、链路管理器、基带链路管理器
SetEventFilter0x0005使能主机指定不同事件过滤
Flush0x0008针对指定的蓝牙句柄,放弃所有作为当前待传输数据,甚至当前是属于多个在主机控制器里的L2CAP指令的数据块
ReadPINType0x0009主机读取指定主机的PIN类型是可变的还是固定的
WritePINType0x000A主机写入指定主机的PIN类型是可变的还是固定的
CreateNewUnitKey0x000B创建新的单一密钥
ReadStoredLinkKey0x000D读取存放在蓝牙控制器中的单个或者多个密钥
WriteStoredLinkKey0x0011写入存放在蓝牙控制器中的单个或者多个密钥
DeleteStoredLinkKey0x0012删除存放在蓝牙控制器中的单个或者多个密钥
WriteLocalName0x0013修改蓝牙设备名称
ReadLocalName0x0014读取蓝牙设备名称
ReadConnectionAcceptTimeout0x0015读连接识别超时参数值,定时器终止后蓝牙硬件自动拒绝连接
WriteConnectionAcceptTimeout0x0016写连接识别超时参数值,定时器终止后蓝牙硬件自动拒绝连接
ReadPageTimeout0x0017读寻呼超时参数值,本地设备返回连接失败前,该值是允许蓝牙硬件定义等待远程设备连接申请时间
WritePageTimeout0x0018写寻呼超时参数值,本地设备返回连接失败前,该值是允许蓝牙硬件定义等待远程设备连接申请时间
ReadScanEnable0x0019写出扫描允许参数值—用来控制蓝牙设备周期性查询
WriteScanEnable0x001A读出扫描允许参数值—用来控制蓝牙设备周期性查询
ReadPageScanActivity0x001B读寻呼扫描间隔、寻呼扫描区间参数
WritePageScanActivity0x001C写寻呼扫描间隔、寻呼扫描区间参数
ReadInquiryScanActivity0x001D读查询扫描间隔、查询扫描区间参数
WriteInquiryScanActivity0x001E写查询扫描间隔、查询扫描区间参数
ReadAuthenticationEnable0x001F读取鉴权允许参数—控制蓝牙设备是否对每个连接进行鉴权
WriteAuthenticationEnable0x0020写取鉴权允许参数—控制蓝牙设备是否对每个连接进行鉴权
ReadEncryptionMode0x0021读加密模式数值—控制蓝牙设备是否对每个连接进行加密
WriteEncryptionMode0x0022写加密模式数值—控制蓝牙设备是否对每个连接进行加密
ReadClassOfDevice0x0023读取设备类型参数值,用于区别设备能力
WriteClassOfDevice0x0024写设备类型参数值,用于区别设备能力
ReadVoiceSetting0x0025读取语音设置参数值,控制语音连接的各种设置
WriteVoiceSetting0x0026写语音设置参数值,控制语音连接的各种设置
ReadAutomaticFlushTimeout0x0027对指定句柄,读取刷新超时值
WriteAutomaticFlushTimeout0x0028对指定句柄,写入刷新超时值
ReadNumBroadcastRetransmissions0x0029读取设备的广播重复发送次数,重复发送提高广播消息的可靠性
WriteNumBroadcastRetransmissions0x002A写入设备的广播重复发送次数,重复发送提高广播消息的可靠性
ReadHoldModeActivity0x002B读取HoldModeActivity的参数值,用来确定Hold挂起的时间
WriteHoldModeActivity0x002C写入HoldModeActivity的参数值,用来确定Hold挂起的时间
ReadTransmitPowerLevel0x002D对指定句柄,读取传输功率的参数值
ReadSynchronousFlowControlEnable0x002E读取SCO流量控制设置。通过使用该设置,主机控制器决定是否主机控制器发送与SCO连接句柄相关的完成分组事件的数量
WriteSynchronousFlowControlEnable0x002F读写入SCO流量控制设置。通过使用该设置,主机控制器决定是否主机控制器发送与SCO连接句柄相关的完成分组事件的数量
SetHostControllerToHostFlowControl0x0031主机控制器的打开、关闭,主机控制器到主机的流量控制
HostBufferSize0x0033主机通知主机控制器自己的ACL、SCO数据缓冲区大小。主机控制器分段传输数据,而数据不会超出这个范围
HostNumberOfCompletedPackets0x0035当主机对于任何连接的句柄准备接受较多的HCI指令时,该指令用于通过主机指出主机控制器
ReadLinkSupervisionTimeout0x0036读取连接管理超时参数。主从蓝牙设备用该参数监视链路丢失情况
WriteLinkSupervisionTimeout0x0037写入连接管理超时参数。主从蓝牙设备用该参数监视链路丢失情况
ReadNumberofSupportedIAC0x0038读取查询扫描期间本地蓝牙扫描的查询识别码(ICA)的数值
ReadCurrentIACLAP0x0039读取创建在查询扫描期间本地蓝牙设备正同时扫描的蓝牙识别码的LAP
WriteCurrentIACLAP0x003A写入创建在查询扫描期间本地蓝牙设备正同时扫描的蓝牙识别码的LAP
ReadPageScanPeriodMode0x003B读取本地蓝牙设备的强制寻呼扫描区间模式
WritePageScanPeriodMode0x003C写入本地蓝牙设备的强制寻呼扫描区间模式
ReadPageScanMode0x003D读取本地蓝牙设备的默认寻呼扫描区间模式
WritePageScanMode0x003E写入本地蓝牙设备的默认寻呼扫描区间模式

(4)、信息指令参数

ReadLocalVersionInformation0x0001读取本地蓝牙版本信息
ReadLocalSupportedFeatures0x0003读取本地蓝牙设备特征表
ReadLocalExtendedFeatures0x0004
ReadBufferSize0x0005返回HCI缓冲容量。缓冲容量用于传输缓冲数据
ReadCountryCode[Deprecated]0x0007读取国家代码状态参数值
ReadBDADDR0x0009读取BD_ADDR的参数值

(5)、状态指令参数
ReadFailedContactCount0x0001读取对于其他设备特殊连接的FailedContactCount参数值。FailedContactCount记录在刷新时终止及当前正在传输的L2CAP数据指令被自动刷新后,主单元或从单元不能连续响应事件次数
ResetFailedContactCount0x0002复位时对于其他设备的连接的FailedContactCount的参数值。FailedContactCount记录在刷新时终止及当前正在传输的L2CAP数据指令被自动刷新后,主单元或从单元不能连续响应事件次数
GetLinkQuality0x0003读取指定连接句柄的LinkQuality的值
ReadRSSI0x0005读取对于其他蓝牙设备连接句柄的接收信号强度指示
ReadAFHChannelMap0x0007
ReadBDClock0x0009

(6)、测试指令
ReadLoopbackMode0x0001读取主机端控制器会送模式的设置值。回送模式设置可以确定信息发送路径
WriteLoopbackMode0x0002写入主机控制器会送模式的设置值。回送模式设置可以确定信息发送路径
EnableDeviceUnderTestMode0x0003允许本地蓝牙设备模块通过LMP测试指令接入测试模式。当主机要求本地设备作为待测试设备,实现蓝牙测试模式文件中规定测试场景,则发送该指令

(7)、错误代码

错误代码错误含义错误代码错误含义
0x01位置HCI指令0x14由于另一端引起连接中断:资源限制
0x02不能连接0x15由于另一端引起连接中断:关机
0x03硬件故障0x16本机中断连接
0x04寻呼超时0x17重复尝试
0x05身份验证失败0x18不允许匹配
0x06键丢失0x19未知LMPPDU
0x07存储器已满0x1A不支持远端特性
0x08连接超时0x1B拒绝SCO补偿
0x09最大连接数0x1C拒绝SCO间歇模式
0x0A连接到设备A的最大SCO连接数0x1D拒绝SCO无线模式
0x0BACL连接已存在0x1E非法链路管理参数
0x0C指令非法0x1F未特别指明错误
0x0D由于资源有限,主机被拒绝0x20不支持链路管理器协议参数
0x0E由于安全原因,主机被拒绝0x21不允许角色改变
0x0F由于远端设备单连接设备,主机拒绝0x22链路管理响应超时
0x10主机超时0x23链路管理错误处理事务冲突
0x11不支持特性或参数值0x24不允许LMPPDU
0x12非法主机控制接口指令0x25~0xFF保留
0x13由于另一端引起连接中断:用户中断连接

二、逻辑链路控制与适配协议 L2CAP

L2CAP位于基带之上,将基带的数据分组转换为便于高层应用的数据分组格式,并提供协议复用和服务质量交换等功能。L2CAP只支持ACL数据传输,不支持SCO数据。

L2CAP本身不提供加强信道可靠性和保证数据完整性的机制,其信道的可靠性依靠基带提供。

这里写代码片

1、协议复用:

底层传输协议没有提供对高层协议的复用机制,因而L2CAP支持高层协议复用,L2CAP层可以区分其上的SDP、RFCOMM、TCS等。

2、分段重组:

L2CAP层帮助实现基带的短PDU和高层的长PDU相互传输,L2CAP本身不完成任何PDU的分段重组,具体的分段重组有低层和高层来完成。

3、服务质量

Qualityof Serivce 信息的交换:蓝牙建立连接的过程中,L2CAP允许交互蓝牙所期望的服务质量,建立完成后,通过监视资源的使用情况,来保证服务质量。

###4、组抽象:

L2CAP忽略地址组概念,他只关心数据。
L2CAP信道有三种类型:
A、面向连接信道:Connection-OrientedCO,用于两个设备之间的数据通信。
B、无连接信道:Connection-LessCL,用来向一组设备广播方式传输数据。CID为固定值:0x0002。
C、信令信道:Signaling,用于创建CO通道,可以通过协商改变CO信道的特性。
CL信道的L2CAP_PDU

长度(2bytes)信道ID(0x0002)PSM(最小为2bytes)有效载荷

PSM为 协议/服务复用器Protocol/Service Multiplexer,一般为SDP、RFCOMM、TCS等中介协议复用。小于0x1000的值,0x0001对应SDP,0x0003对应RFCOMM、0x0005对应TCS。

(1)、蓝牙逻辑链路控制与适配协议信令:
L2CAP的信令通道的CID为0x0001
信令指令分组:

L2CAP分组头部分
长度(2byte)CID(0x0001)指令1指令2……………指令n

信令指令格式:

信令指令头
代码(1byte)标识符(1byte)长度(2byte)数据

这里写图片描述

如上图所示,一条L2CAP信令,1为L2CAP分组头,2为信令指令头,3为数据部分。

L2CAP:
Role:Master
Address:11
PDULength: 6 //指令的长度,值为06 00
ChannelID: 0x0001 (Signaling)//L2CAP的信令通道,值为01 00
Code:Information request//信息请求,值为0a
Identifier:1//标识符,值为01
CommandLength: 2//命令长度,值为02 00
InfoType:Extended features supported//02 00
所以这条指令完整的为:
06 00 01 00 0a 01 02 00 02 00

信令的其他操作如下:
这里写图片描述

L2CAP信令指令码:

CodeDescription
0x00RESERVED保留
0x01Commandreject拒绝命令
0x02Connectionrequest连接请求
0x03Connectionresponse连接响应
0x04Configurerequest配置请求
0x05Configureresponse配置响应
0x06Disconnectionrequest断开请求
0x07Disconnectionresponse断开响应
0x08Echorequest
0x09Echoresponse
0x0AInformationrequest信息请求
0x0BInformationresponse信息响应

1)、连接请求Connection_Request Code=0x02

代码(0x02)标识符(1字节)长度(2字节)PSM(2字节)源CID(2字节)

例如:SDP 连接请求

这里写图片描述

如上红框所示:
代码(0x02)标识符(1字节)长度(2字节)PSM(2字节)源CID(2字节)
0x0234SDP0x0040
2)、连接相应Connection_ResponseCode=0x03
代码(0x03)标识符长度目标CID源CID结果状态

例如:SDP请求响应
这里写图片描述
如上面红框所示:
代码(0x03)标识符长度目标CID源CID结果状态
0x03380x00400x00400x0000

(2)、MTU MAXIMUMTRANSMISSION UNIT最大传输单元

MTU最大传输单元,L2CAP应用必须支持最小为48字节的MTU,默认值为672
(3)、QoS 服务质量

三、服务发现协议SDP

SDP两种服务发现模式:
1)、服务搜索:查询具有特定服务属性的服务;
2)、服务浏览:简单的浏览全部可用服务。

1 、PDU 格式:(协议数据单元)

Header
PDUID(1byte)TransactionID(2byte)参数长度(2byte)参数1……参数N

不同PDU ID实现SDP的不同功能,概述如下表格:

ValueParameterDescirption
0x00Reserved保留
0x01SDP_ErrorResponse错误响应
0x02SDP_ServiceSearchRequest服务搜索请求
0x03SDP_ServiceSearchResponse服务搜索响应
0x04SDP_ServiceAttributeRequest服务属性请求
0x05SDP_ServiceAttributeResponse服务属性响应
0x06SDP_ServiceSearchAttributeRequest服务搜索属性请求
0x07SDP_ServiceSearchAttributeResponse服务搜索属性响应
0x08-0xffReserved保留

2、服务记录表

SDP的服务记录表对每一个服务进行描述,每条记录包含服务句柄、一组服务属性:
这里写图片描述

  • Service Record Attributes:服务记录;
  • Service Record Handle 服务句柄;

这里写图片描述

四、串口仿真协议 RFCOMM

为建立在串口之上的传统应用提供环境接口,使他们可以做比较少协议改动就可以在蓝牙无线通信无线链路上工作。多路串口仿真是RFCOMM的重要功能,通过多路复用器(multiplexer),一条L2CAP链路可以同时 多个串行应用。
两台设备间的串口仿真:
这里写图片描述

RFCOMM 两个蓝牙设备之间可以支持多达60多路仿真串口。

RFCOMM帧类型如下:

SABM异步平衡模式设置指令
UA未加编号的确认响应
DM断开连接模式响应
DISC断开连接指令
UIH带头校验的未编号信息命令和响应

这里写图片描述
传送门:
(一)蓝牙的概述
(二)蓝牙协议规范(射频、基带链路控制、链路管理)
(三)蓝牙协议规范(HCI、L2CAP、SDP、RFOCMM)
(四)蓝牙协议规范(irOBEX、BNEP、AVDTP、AVCTP)

引用自xubin的博客

By Xiaolong,每一天都值得被认真对待!

蓝牙协议学习整理(二)蓝牙协议规范(射频、基带链路控制、链路管理)

发表于 2017-12-29 | 分类于 Android蓝牙

第二章 蓝牙协议规范(射频、基带链路控制、链路管理)

这里写图片描述

蓝牙协议是蓝牙设备间交换信息所应该遵守的规则。与开放系统互联(OSI)模型一样,蓝牙技术的协议体系也采用了分层结构,从底层到高层形成了蓝牙协议栈,各层协议定义了所完成的功能和使用数据分组格式,以保证蓝牙产品间的互操作性。

一、射频协议

射频位置如上图红色部分。

1、工作频率

蓝牙工作在2.4GHz ISM频段上,蓝牙采用跳频扩谱技术主动的避免工作频段受干扰(微波炉的工作频率也是2.4GHz)。
这里写图片描述
| 地理位置 | ISM频段范围 | 射频信道频率 |
|—————|—————|———–|
|中国、美国、欧洲 |2400.0~2483.5MHz|F=(2402+k)MHz,k在0、1、……78中随机取值|
| 法国 |2446.5~2483.5MHz|F=(2454+k)MHz,k在0、1、……22中随机取值|
| 日本 |2471.0~2497.0MHz|F=(2473+k)MHz,k在0、1、……22中随机取值|
| 西班牙 |2445.0~2475.0MHz|F=(2449+k)MHz,k在0、1、……22中随机取值|

我国的蓝牙频率在2.402GHz~2.483GHz,蓝牙每个频道的宽度为1MHz,为了减少带外辐射的干扰,保留上、下保护为3.5MHz和2MHz,79个跳频点中至少75个伪随机码跳动,30S内任何一个频点使用时长不能超过0.4S。

2、跳频技术、发射功率、时隙

(1)、发射功率:蓝牙发射功率分三级:一级功率100mW(20dBm);二级功率2.5mW(4dBm);三级功率1mW(0dBm);
(2)、物理信道:蓝牙物理信道有伪随机序列控制的79个跳频点构成,不同跳频序列代表不同的信道。
这里写图片描述

(3)、时隙:蓝牙跳频速率为1600次/s,每个时间为625uS(1S/1600)称为一个时隙;
这里写图片描述

二、基带与链路控制协议

这里写图片描述

蓝牙发送数据时,基带部分将来自高层的数据进行信道编码,向下发给射频进行发送;接收数据时,将解调恢复空中数据并上传给基带,基带进行信道编码传送给上层。

作用:跳频选择、蓝牙编址、链路类型、信道编码、收发规则、信道控制、音频规范、安全设置。

1、蓝牙分组编码为小端模式;

2、蓝牙地址

  • BD_ADDR:BluetoothDevice Address;
  • LAP:LowerAddress Part 低地址部分;
  • UAP: UpperAddress Part 高地址部分;
  • NAP: Non-significantAddress Part 无效地址部分。

这里写图片描述

3、蓝牙时钟

每个蓝牙设备都有一个独立运行的内部系统时钟,称为本地时钟(Local Clock),决定定时器的收发跳频。为了与其他设备同步,本地时钟要加一个偏移量(offset),提供给其他设备同步。

蓝牙基带四个关键周期:312.5uS、625uS、1.25mS、1.28S。

这里写图片描述

  1. CLKN:本地时钟:
  2. CLKE:预计时钟,扫描寻呼过程中用到;
  3. CLK:设备实际运行的时钟频率。

    CLKE、CLK由CLKN加上一个偏移量得到的。

    这里写图片描述

4、蓝牙物理链路:

通信设备间物理层的数据连接通道就是物理链路。

ACL(Asynchronous Connectionless)异步无连接链路;对时间要求不敏感的数据通信,如文件数据、控制信令等。

SCO(Synochronous Connection Oriented)同步面向连接链路;对时间比较敏感的通信,如:语音;最多只支持3条SCO链路,不支持重传。

ACL用于数据传输;

5、蓝牙基带分组:

基带分组至少包括:接入码、分组头、有效载荷;

列表内容

(1)、接入码用于同步、直流、载频泄漏偏置补偿标识;
(2)、分组头包含链路信息,确保纠正较多的错误。
分组类型如下:

分组类别Type(b3b2b1b0)时隙SCOACL
链路控制分组0000 1NULLNULL
0001 POLLPOLL
0010 FHSFHS
0011 DM1DM1
单时隙分组01001未定义NULL
0101HV1
0110HV2
0111HV3
1000DV
1001NULLAUX1
3时隙分组10103未定义DM3
1011DH3
1100未定义
1101
5时隙分组10105未定义DM5
1111

ACL分组形式为:D(M|H)(1|3|5),D代表数据分组,M代表用2/3比例的FEC的中等速率分组;H代表不使用纠错码的高速率分组;1、3、5分别代表分组所占用的时隙数目;
DM1、DM3、DM5、DH1、DH3、DH5

SCO分组形式为:HV(1|2|3)。HV代表高质量语言分组,1、2、3有效载荷所采用的纠错码方法。1为1/3比例FEC,设备2个时隙发送一个单时隙分组;2为2/3比例FEC,设备4个时隙发送一个单时隙分组;3为不使用纠错码,设备6个时隙发送一个单时隙分组

HV1、HV2、HV3

ALC 分组:

类型有效载荷头/字节用户有效载荷/字节FECCRC对称最大速率/kbps非对称速率/kbps
前向后向
DM110~172/3有108.8108.8108.8
DH110~27无有172.8172.8172.8
DM320~1212/3有258.1387.254.4
DH320~183无有390.4585.686.4
DM520~2242/3有286.7477.836.3
MH520~339无有433.9723.257.6
AUX110~29无无185.6185.6185.6

SCO分组:
无240位64
类型有效载荷头/字节用户有效载荷/字节FECCRC有效载荷长度同步速率/kbps占用Tsco数目/语言长度
HV1101/32/1.25ms
HV2202/34/2.5ms
HV330无6/3.75ms
DV1D10+(0-9)D2/3D有D64+57.6D
注释:D 只对数据段有用,DV分组包含数据段,也包含语言段。

(3)、有效载荷 分语言有效载荷、数据有效载荷。

6、蓝牙的逻辑信道

  • 链路控制信道:LinkControl LC
  • 链路管理信道:Link Manage LM
  • 用户异步数据信道:User AsynchronizationUA
  • 用户同步数据信道:UserSynchronization US
  • 用户等时数据信道:UserIsochronous UI UI

7、蓝牙的收发规则

这里写图片描述
上图为RX缓存。
这里写图片描述
上图为TX缓存。
新分组到达时,ACL链路的RX缓存器要流量控制,SCO数据不需要流量控制;

8、蓝牙基带信道和网络控制

(1)、链路控制器状态:
待机、连接
寻呼page、寻呼扫描pagescan、查询inquiry、查询扫描inquiry scan、主设备相应Master Response、从设备相应Slave Response、查询相应inquiry response
(2) 、连接状态
激活模式active、呼吸模式sniff、保持模式hold、休眠模式park。
(3)、待机状态
待机状态是蓝牙设备缺省低功耗状态,此状态下本地时钟以低精度运行。蓝牙从待机转入寻呼扫描状态,对其他寻呼进行响应成为从设备;也可以从待机状态进入查询扫描状态,完成一个完整的寻呼,成为主设备。

9、接入过程

注释:
IAC Inquiry AccessCode 查询接入码;
GIAC:通用查询接入码 DIAC:专用查询接入码;
DAC:DeviceAccess Code 设备接入码;
LAP:
建立连接,必须使用查询、寻呼;查询过程使用IAC,发现覆盖区域内的设备、设备的地址及其时钟;连接过程使用DAC,建立连接的设备处理寻呼过程,成为主设备。

(1)、查询过程
蓝牙设备通过查询来发现通信范围内的其他蓝牙设备。查询信息分为GIAC、DIAC两种。查询发起设备收集所有相应设备的地址、时钟信息。
一设备进入查询状态去发现其他设备,查询状态下连续不断的在不同频点发送查询消息。查询的跳频序列有GIAC的LAP导出。
一设备想被其他设备发现,就要周期性进入 查询扫描状态,以便相应查询消息。如:我们选择设备多长时间可见,其实就是 进入查询扫描状态。
A、查询扫描
查询扫描状态下,接收设备扫描接入码的时间长度,足以完成对16个频率的扫描。扫描区间长度Twindow inquiry scan。扫描在同一个频率上进行,查询过程用32跳专用查询跳频序列,此序列有通用查询的地址决定,相位有本地时钟决定,每隔1.28S变化一次。
B、查询
与寻呼类似,TX用查询跳频序列、RX用查询相应跳频序列。
C、查询相应
从设备响应查询操作。每个设备都有自己的时钟,使用查询序列相位相同的几率比较小。为了避免多个设备在同一查询跳频信道同时激活,从设备查询响应规定:从设备收到查询消息,产生0-1023只觉得额一个随机数,锁定当时相位输入值进行跳频选择,从设备此后的RAND时隙中返回到连接或者待机状态。

(2)、寻呼扫描
DAC:DeviceAccess Code 设备接入码
寻呼扫描状态下的设备扫描窗口Twindowpage scan内监听自己的DAC。监听只在一个跳频点进行。Twindow page scan足够覆盖16个寻呼扫描频点。
寻呼扫描状态,扫描在同一个频率上进行,持续1.28S,在选择另一个不同频率。

SR模式Tpagescan寻呼次数Npage
R0连续>=1
R1<=1.28S>=128
R2<=2.56S>=256
预留––

(3)、寻呼
主设备使用寻呼发起一个主—从设备连接,通过在不同的跳频点上重复发送从设备DAC来扑捉从设备,从设备在寻呼扫描状态被唤醒,接收寻呼。
(4)、寻呼相应过程

三、链路管理器

这里写图片描述
如上图红色部分,负责完成设备:功率管理、链路质量管理、链路控制管理、数据分组管理、链路安全管理。

1、链路管理协议数据单元

蓝牙链路管理器接收到高层的控制信息后,不是向自身的基带部分分发控制信息,就是与另一台设备的链路管理器进行协商管理。这些控制信息封装在链路管理协议数据单元LMP_PDU中,由ACL分组的有效载荷携带。

2、链路管理器协议规范

(1)、设备功率管理
RSSI保持模式、呼吸模式、休眠模式。
(2)、链路质量管理 QoSQuality of Service
A、ACL链路。
B、SCO链路。
(3)、链路控制管理
设备寻呼模式、设备角色转换、时钟计时设置、信息交换:版本信息、支持特性、设备名称;建立连接、链路释放。
(4)、数据分组管理

传送门:
(一)蓝牙的概述
(二)蓝牙协议规范(射频、基带链路控制、链路管理)
(三)蓝牙协议规范(HCI、L2CAP、SDP、RFOCMM)
(四)蓝牙协议规范(irOBEX、BNEP、AVDTP、AVCTP)

引用自xubin的博客

By Xiaolong,每一天都值得被认真对待!

Android 端蓝牙模块的开发

发表于 2017-11-01 | 分类于 Android蓝牙

###背景
因为可穿戴设备等硬件设备的兴起,蓝牙模块的开发已经成为大多数移动开发者必备的技能。
这段时间由于业务需求,花了一阵子的时间在研究蓝牙模块的传输。也整理了一些相关的经验拿出来分享给大家。

简单介绍

在此过程中需要大家先了解一下,在蓝牙开发过程中经常碰到的名词。BLE,SPP,OPP等。

  1. BLE(Bluetooth Low Energy)——蓝牙低功耗技术,这是蓝牙4.0推出的一个低功耗蓝牙部分。低功耗蓝牙适用于实时性要求比较高,但是数据速率比较低的产品,如遥控类的,如鼠标,键盘,遥控鼠标(Air Mouse),传感设备的数据发送,如心跳带,血压计,温度传感器等。
  2. SPP(Serial Port Profile)—— SPP为蓝牙串口传输协议,能在蓝牙设备之间创建串口进行数据传输的协议。蓝牙串口的目的是针对如何在两个不同设备(通信的两端)上的应用之间保证一条完整的通信路径。
    当然SSP还有另外一个名词,简单配对模式(Secure Simple Pairing).
  3. OPP(Object push profile) 面向对象传输协议,用于文件文件传输。
  4. HFP (Hands-free Profile) HFP(Hands-free Profile),让蓝牙设备可以控制电话,如接听、挂断、拒接、语音拨号等,拒接、语音拨号要视蓝牙耳机及电话是否支持

更多蓝牙协议可以到蓝牙协议介绍
大家可以根据需求选择相应的功能做开发。
代码还在github上,有时间继续整理~~ 囧~ 这里会把ble和普通蓝牙spp,文件传输 opp开发做整理。

By Xiaolong,每一天都值得被认真对待!

蓝牙协议学习整理(一)蓝牙的概述

发表于 2017-11-01 | 分类于 Android蓝牙

第一章 蓝牙的概述

一、蓝牙版本信息

蓝牙共有六个版本1.1/1.2/2.0/2.1/3.0/4.0

1、1.1版本

传输率约在748~810kb/s,因是早期设计,容易受到同频率之产品所干扰下影响通讯质量。

2、1.2版本

同样是只有748~810kb/s 的传输率,但在加上了(改善 Software)抗干扰跳频功能。

3、2.0+EDR版本

是1.2的改良提升版,传输率约在1.8M/s~2.1M/s,开始支持双工模式——即一面作语音通讯,同时亦可以传输档案/高质素图片,2.0 版本当然也支持 Stereo 运作。

应用最为广泛的是Bluetooth2.0+EDR标准,该标准在2004年已经推出,支持Bluetooth 2.0+EDR标准的产品也于2006年大量出现。虽然Bluetooth 2.0+EDR标准在技术上作了大量的改进,但从1.X标准延续下来的配置流程复杂和设备功耗较大的问题依然存在。

4、2.1版本

更佳的省电效果:蓝牙2.1版加入了SniffSubrating的功能,透过设定在2个装置之间互相确认讯号的发送间隔来达到节省功耗的目的。

5、3.0+HS版本

2009年4月21日,蓝牙技术联盟(Bluetooth SIG)正式颁布了新一代标准规范”Bluetooth Core Specification Version 3.0 High Speed”(蓝牙核心规范3.0版 ),蓝牙3.0的核心是”GenericAlternate MAC/PHY”(AMP),这是一种全新的交替射频技术,允许蓝牙协议栈针对任一任务动态地选择正确射频。最初被期望用于新规范的技术包括802.11以及UMB,但是新规范中取消了UMB的应用。

6、4.0 版本

蓝牙4.0包括三个子规范,即传统蓝牙技术、高速蓝牙和新的蓝牙低功耗技术。蓝牙 4.0的改进之处主要体现在三个方面,电池续航时间、节能和设备种类上。拥有低成本,跨厂商互操作性,3毫秒低延迟、100米以上超长距离、AES-128加密等诸多特色此外,蓝牙4.0的有效传输距离也有所提升。3.0版本的蓝牙的有效传输距离为10米(约 32英尺),而蓝牙4.0的有效传输距离最高可达到100米(约328英尺)。

7、典型蓝牙与BLE蓝牙对比

蓝牙与BLE对比

二、蓝牙的技术特点

简单地说,蓝牙是一种短程宽带无线电技术,是实现语音和数据无线传输的全球开放性标准。它使用跳频扩谱(FHSS)、时分多址(TDMA)、码分多址(CDMA)等先进技术,在小范围内建立多种通信与信息系统之间的信息传输。

1、Bluetooth的主要技术特点:

(1)、工作频段 :2.4GHz的工科医(ISM)频段,无需申请许可证。大多数国家使用79个频点,载频为(2402+k)MHz(k=0,1, 2…78),载频间隔1MHz。采用TDD时分双工方式。
(2)、传输速率:1Mb/s(V2.0以上版本)
(3)、调试方式:BT=0.5的GFSK调制,调制指数为0.28-0.35。
(4)、采用跳频技术:跳频速率为1600跳/秒,在建链时(包括寻呼和查询)提高为3200跳/秒。蓝牙通过快跳频和短分组技术减少同频干扰,保证传输的可靠性。
(5)、语音调制方式:连续可变斜率增量调制(CVSD,ContinuousVariable Slope Delta Modulation),抗衰落性强,即使误码率达到4%,话音质量也可接受。
(6)、支持电路交换和分组交换业务:蓝牙支持实时的同步定向联接(SCO链路)和非实时的异步不定向联接(ACL链路),前者主要传送语音等实时性强的信息,后者以数据包为主。语音和数据可以单独或同时传输。蓝牙支持一个异步数据通道,或三个并发的同步话音通道,或同时传送异步数据和同步话音的通道。每个话音通道支持64kbps的同步话音;异步通道支持723.2/57.6kbps的非对称双工通信或433.9kbps的对称全双工通信。
(7)、支持点对点及点对多点通信:蓝牙设备按特定方式可组成两种网络:微微网(Piconet)和分布式网络(Scatternet),其中微微网的建立由两台设备的连接开始,最多可由八台设备组成。在一个微微网中,只有一台为主设备(Master),其它均为从设备(Slave),不同的主从设备对可以采用不同的链接方式,在一次通信中,链接方式也可以任意改变。几个相互独立的微微网以特定方式链接在一起便构成了分布式网络。所有的蓝牙设备都是对等的,所以在蓝牙中没有基站的概念。
(8)、工作距离:蓝牙设备分为三个功率等级,分别是:100mW(20dBm)、2.5mW(4dBm)和1mW(0dBm),相应的有效工作范围为:100米、10米和1米。

三、Bluetooth的系统构成

构成

1、无线射频单元(Radio):

负责数据和语音的发送和接收,特点是短距离、低功耗。蓝牙天线一般体积小、重量轻,属于微带天线。

2、基带或链路控制单元(LinkController):

进行射频信号与数字或语音信号的相互转化,实现基带协议和其它的底层连接规程。

3、链路管理单元(LinkManager):

负责管理蓝牙设备之间的通信,实现链路的建立、验证、链路配置等操作。

4、蓝牙软件协议实现:

如上图紫色部分,这个后面我们做详细说明。
这里写图片描述

四、蓝牙协议规范

传输协议、中介协议、应用协议;

1、传输协议

负责蓝牙设备间,互相确认对方的位置,以及建立和管理蓝牙设备间的物理链路;

  • 底层传输协议:蓝牙射频(Radio)部分、基带链路管理控制器(Baseband&Link Controller)、链路管理协议(Link ManagerProtocol LMP)。负责语言、数据无线传输的物理实现以及蓝牙设备间的联网组网。

  • 高层传输协议:逻辑链路控制与适配器(LogicalLink Control and Adaptation Protocol)L2CAP 、主机控制接口(HostControl Interface,HCI)。为高层应用屏蔽了跳频序列选择等底层传输操作,为高层程序提供有效、有利于实现数据分组格式。

2、中介协议

为高层应用协议或者程序,在蓝牙逻辑链路上工作提供必要的支持,为应用提供不同标准接口。

  • 串口仿真协议:RFCOMM、服务发现协议:SDP、互操作协议IrDA、网络访问协议:PPP、IP、TCP、UDP、电话控制协议:TCS、AT指令集。

这里写图片描述

3、应用协议

蓝牙协议栈之上的应用软件和所涉及到的协议,如:拨号上网、语言功能的应用程序。

蓝牙的应用框架如下:

  1. 通用应用类框架:查询、建立连接服务等;
  2. 蓝牙电话应用类框架:电话控制、语言;
  3. 蓝牙连网应用类框架:网络应用相关;
  4. 对象交互服务类框架:IrDA、OBEX;
  5. 蓝牙音视频控制类框架。

五、硬件接口

一般蓝牙芯片通过UART、USB、SDIO、I2S、PcCard和主控芯片通信。如下图所示,通过UART和主控芯片通信。
这里写图片描述

传送门:
(一)蓝牙的概述
(二)蓝牙协议规范(射频、基带链路控制、链路管理)
(三)蓝牙协议规范(HCI、L2CAP、SDP、RFOCMM)
(四)蓝牙协议规范(irOBEX、BNEP、AVDTP、AVCTP)
引用自xubin的博客

By Xiaolong,每一天都值得被认真对待!

12…4
小龙

小龙

程序猿

36 日志
14 分类
23 标签
GitHub CSDN
© 2019 小龙
由 Hexo 强力驱动
主题 - NexT.Pisces