先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
正文
}
@Override
public void onSearchCanceled() {
}
});
如果扫描不出来,可将 targetSdk 调到低于 6.0.
可以随时停止扫描:
mClient.stopSearch();
蓝牙开关
打开关闭蓝牙:
mClient.openBluetooth();
mClient.closeBluetooth();
判断蓝牙是否打开:
mClient.isBluetoothOpened();
蓝牙打开或关闭需要一段时间,可以注册回调监听状态,回调的参数如果是 true 表示蓝牙已打开,false 表示蓝牙关闭
mClient.registerBluetoothStateListener(mBluetoothStateListener);
private final BluetoothStateListener mBluetoothStateListener = new BluetoothStateListener() {
@Override
public void onBluetoothStateChanged(boolean openOrClosed) {
}
};
mClient.unregisterBluetoothStateListener(mBluetoothStateListener);
设备配对
监听设备配对状态变化
private final BluetoothBondListener mBluetoothBondListener = new BluetoothBondListener() {
@Override
public void onBondStateChanged(String mac, int bondState) {
// bondState = Constants.BOND_NONE, BOND_BONDING, BOND_BONDED
}
};
mClient.registerBluetoothBondListener(mBluetoothBondListener);
mClient.unregisterBluetoothBondListener(mBluetoothBondListener);
Beacon 解析
可以在广播中携带设备的自定义数据,用于设备识别,数据广播,事件通知等,这样手机端无需连接设备就可以获取设备推送的数据。
扫描到的 beacon 数据为 byte[],在 SearchResult 的 scanRecord 中,按如下形式生成 Beacon 对象,
Beacon beacon = new Beacon(device.scanRecord);
Beacon 数据结构如下:
public class Beacon {
public byte[] mBytes;
public List mItems;
}
BeaconItem 是按 type 来区分的,
public class BeaconItem {
/**
- 广播中声明的长度
*/
public int len;
/**
- 广播中声明的 type
*/
public int type;
/**
- 广播中的数据部分
*/
public byte[] bytes;
}
然后根据自定义的协议,解析对应的 BeaconItem 中的 bytes,首先创建一个 BeaconParser,传入对应的 BeaconItem,然后根据协议不断读取数据, 如果协议中某个字段占 1 个字节,则调用 readByte,若占用两个字节则调用 readShort,如果要取某个字节的某个 bit 则调用 getBit。注意 parser 每读一次数据,指针就会相应向后移动,可以调用 setPosition 设置当前指针的位置。
BeaconItem beaconItem; // 设置成 beacon 中对应的 item
BeaconParser beaconParser = new BeaconParser(beaconItem);
int firstByte = beaconParser.readByte(); // 读取第 1 个字节
int secondByte = beaconParser.readByte(); // 读取第 2 个字节
int productId = beaconParser.readShort(); // 读取第 3,4 个字节
boolean bit1 = beaconParser.getBit(firstByte, 0); // 获取第 1 字节的第 1bit
boolean bit2 = beaconParser.getBit(firstByte, 1); // 获取第 1 字节的第 2bit
beaconParser.setPosition(0); // 将读取起点设置到第 1 字节处
BLE 设备通信
● 连接
连接过程包括了普通的连接(connectGatt)和发现服务(discoverServices),这里收到回调时表明服务发现已完成。回调参数 BleGattProfile 包括了所有的 service 和 characteristic 的 uuid。返回的 code 表示操作状态,包括成功,失败或超时等,所有常量都在 Constants 类中。
mClient.connect(MAC, new BleConnectResponse() {
@Override
public void onResponse(int code, BleGattProfile profile) {
if (code == REQUEST_SUCCESS) {
}
}
});
可以配置连接参数如下,
BleConnectOptions options = new BleConnectOptions.Builder()
.setConnectRetry(3) // 连接如果失败重试 3 次
.setConnectTimeout(30000) // 连接超时 30s
.setServiceDiscoverRetry(3) // 发现服务如果失败重试 3 次
.setServiceDiscoverTimeout(20000) // 发现服务超时 20s
.build();
mClient.connect(MAC, options, new BleConnectResponse() {
@Override
public void onResponse(int code, BleGattProfile data) {
}
});
● 连接状态
如果要监听蓝牙连接状态可以注册回调,只有两个状态:连接和断开。
mClient.registerConnectStatusListener(MAC, mBleConnectStatusListener);
private final BleConnectStatusListener mBleConnectStatusListener = new BleConnectStatusListener() {
@Override
public void onConnectStatusChanged(String mac, int status) {
if (status == STATUS_CONNECTED) {
} else if (status == STATUS_DISCONNECTED) {
}
}
};
mClient.unregisterConnectStatusListener(MAC, mBleConnectStatusListener);
也可以主动获取连接状态:
int status = mClient.getConnectStatus(MAC);
// Constants.STATUS_UNKNOWN
// Constants.STATUS_DEVICE_CONNECTED
// Constants.STATUS_DEVICE_CONNECTING
// Constants.STATUS_DEVICE_DISCONNECTING
// Constants.STATUS_DEVICE_DISCONNECTED
● 断开连接
mClient.disconnect(MAC);
● 读 Characteristic
mClient.read(MAC, serviceUUID, characterUUID, new BleReadResponse() {
@Override
public void onResponse(int code, byte[] data) {
if (code == REQUEST_SUCCESS) {
}
}
});
● 写 Characteristic
要注意这里写的 byte[]不能超过 20 字节,如果超过了需要自己分成几次写。建议的办法是第一个 byte 放剩余要写的字节的长度。
mClient.write(MAC, serviceUUID, characterUUID, bytes, new BleWriteResponse() {
@Override
public void onResponse(int code) {
if (code == REQUEST_SUCCESS) {
}
}
});
这个写是带了 WRITE_TYPE_NO_RESPONSE 标志的,实践中发现比普通的 write 快 2~3 倍,建议用于固件升级。
mClient.writeNoRsp(MAC, serviceUUID, characterUUID, bytes, new BleWriteResponse() {
@Override
public void onResponse(int code) {
if (code == REQUEST_SUCCESS) {
}
}
});
● 读 Descriptor
mClient.readDescriptor(MAC, serviceUUID, characterUUID, descriptorUUID, new BleReadResponse() {
@Override
public void onResponse(int code, byte[] data) {
}
});
● 写 Descriptor
mClient.writeDescriptor(MAC, serviceUUID, characterUUID, descriptorUUID, bytes, new BleWriteResponse() {
@Override
public void onResponse(int code) {
}
});
● 打开 Notify
这里有两个回调,onNotify 是接收通知的。
mClient.notify(MAC, serviceUUID, characterUUID, new BleNotifyResponse() {
@Override
public void onNotify(UUID service, UUID character, byte[] value) {
}
@Override
public void onResponse(int code) {
if (code == REQUEST_SUCCESS) {
学习分享,共勉
Android高级架构师进阶之路
题外话,我在阿里工作多年,深知技术改革和创新的方向,Android开发以其美观、快速、高效、开放等优势迅速俘获人心,但很多Android兴趣爱好者所需的进阶学习资料确实不太系统,完整。今天我把我搜集和整理的这份学习资料分享给有需要的人
- Android进阶知识体系学习脑图
- Android进阶高级工程师学习全套手册
- 对标Android阿里P7,年薪50w+学习视频
- 大厂内部Android高频面试题,以及面试经历
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
迅速俘获人心,但很多Android兴趣爱好者所需的进阶学习资料确实不太系统,完整。今天我把我搜集和整理的这份学习资料分享给有需要的人
- Android进阶知识体系学习脑图
[外链图片转存中…(img-HEBxmDfB-1713642554709)]
- Android进阶高级工程师学习全套手册
[外链图片转存中…(img-zoKmpgYC-1713642554709)]
- 对标Android阿里P7,年薪50w+学习视频
[外链图片转存中…(img-YnFrAEhD-1713642554710)]
- 大厂内部Android高频面试题,以及面试经历
[外链图片转存中…(img-rml6PIdN-1713642554710)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-Hac2iWIS-1713642554710)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!