智能电视硬件配置硬件创业的人员配置,怎么才算完善

如果你还没有看上一篇 手把手教你Android手机与BLE终端通信--搜索,你就先看看吧,因为这一篇要接着讲搜索到蓝牙后的连接,和连接后的发送和接收数据。
评论里有很多人问如果一条信息特别长,怎么不丢包,或者怎么判断一个完整的信息发送完了呢。我写的时候连的串口是我们公司硬件工程师设计的,他定义好了信息的格式,什么字符开头,什么字符结尾,中间哪几位代表什么意思,我如果不能成功取到一对开头和结尾并且长度也符合我就会丢弃那点信息,取得的完整信息则会根据硬件工程师的文档取出app相应地方用到的相应信息,嗯,就是这样。如果你不知道一个串口发给你什么信息,那一定是你拿来玩的串口,工作中用到的都是定制的,不然连接串口干什么呢。
我的基本实现就是所有蓝牙操作都写在BluetoothController中,他有消息要发送时发送到BLEService中,service再发广播提示MainActivity更新页面。好了,切入正题。。
首先点击搜索到的蓝牙的listview,连接点击的那个蓝牙:
[html] view plain copy
listview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView arg0, View arg1, int index,
long arg3) {
BluetoothController.getInstance().connect(list.get(index));
connect方法仍然写在controller中,那个与蓝牙控制类。
[html] view plain copy
* 连接蓝牙设备
* @param device
待连接的设备
public void connect(EntityDevice device) {
deviceAddress=device.getAddress();
deviceName=device.getName();
BluetoothDevice localBluetoothDevice = bleAdapter
.getRemoteDevice(device.getAddress());
if (bleGatt != null) {
bleGatt.disconnect();
bleGatt.close();
bleGatt = localBluetoothDevice.connectGatt(App.app, false,
bleGattCallback);
bleGatt是与蓝牙沟通的控制类,系统自带的BluetoothGatt类,它可以连接,断开某设备,或者获取服务,写数据。蓝牙有很多服务,但我们要找那个可读写的服务,下面会有查找服务。
你应该注意到bleGattCallback,BluetoothGattCallback,也是系统自带的类,是连接回调类,连接后出现什么情况怎么处理就在这里了。它有很多方法需要重写,我们只重写两三个。关于连接我们需要重写的是onConnectionStateChange(BluetoothGatt paramAnonymousBluetoothGatt, int oldStatus,int newStatus),第一个参数不用管,我也不知道是什么,第二个参数是原来的状态,第三个参数是后来的状态,这本来就是状态改变回调方法嘛。对了,0表示未连接上,2表示已连接设备。当成功连接后我们要更新界面,未连接也要更新,因为可能是连接过程中意外中断,也可能有意中断,提醒下亲爱的用户还是比较好的。
[html] view plain copy
* 连接状态改变
public void onConnectionStateChange(
BluetoothGatt paramAnonymousBluetoothGatt, int oldStatus,
int newStatus) {
if (newStatus == 2)// 已连接状态,表明连接成功
Message msg=new Message();
msg.what=ConstantUtils.WM_BLE_CONNECTED_STATE_CHANGE;
Bundle bundle=new Bundle();
bundle.putString("address", deviceAddress);
bundle.putString("name", deviceName);
serviceHandler.sendMessage(msg);
paramAnonymousBluetoothGatt.discoverServices();
//连接到蓝牙后查找可以读写的服务,蓝牙有很多服务
if (newStatus == 0)// 断开连接或未连接成功
serviceHandler.sendEmptyMessage(ConstantUtils.WM_STOP_CONNECT);
paramAnonymousBluetoothGatt.disconnect();
paramAnonymousBluetoothGatt.close();
这样连接状态改变的消息就发到了service, service接收到消息后发广播提醒界面更新
[html] view plain copy
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case ConstantUtils.WM_BLE_CONNECTED_STATE_CHANGE:// 连接上某个设备的消息
Bundle bundle = (Bundle) msg.
String address = bundle.getString("address");
String name = bundle.getString("name");
// 连接状态改变广播
Bundle bundle1 = new Bundle();
bundle1.putString("address", address);
bundle1.putString("name", name);
Intent intentDevice = new Intent(
ConstantUtils.ACTION_CONNECTED_ONE_DEVICE);
intentDevice.putExtras(bundle1);
sendBroadcast(intentDevice);
case ConstantUtils.WM_STOP_CONNECT:
Intent stopConnect = new Intent(
ConstantUtils.ACTION_STOP_CONNECT);
sendBroadcast(stopConnect);
然后主界面MainActivity接收到广播后更新页面。如果是连接就把连接的设备地址打印出来,如果是断开了,就清除打印并且弹一个toast.当然这些代码在一个receiver中。
[html] view plain copy
else if (intent.getAction().equalsIgnoreCase(ConstantUtils.ACTION_CONNECTED_ONE_DEVICE)){
connectedDevice.setText("连接的蓝牙是:"+intent.getStringExtra("address"));
else if (intent.getAction().equalsIgnoreCase(ConstantUtils.ACTION_STOP_CONNECT)){
connectedDevice.setText("");
toast("连接已断开");
为了测试断开,我关了蓝牙,你可以试试。
2,接收数据
首先你需要下载一个串口助手,可以看到串口接收到的数据,也可以通过串口发送数据到跟他连接的设备。
查看接收到的数据只需要重写上面串口回调BluetoothGattCallback的一个方法,public void onCharacteristicChanged(BluetoothGatt paramAnonymousBluetoothGatt,
BluetoothGattCharacteristic paramAnonymousBluetoothGattCharacteristic)
[html] view plain copy
* 与蓝牙通信回调
public BluetoothGattCallback bleGattCallback = new BluetoothGattCallback() {
* 收到消息
public void onCharacteristicChanged(
BluetoothGatt paramAnonymousBluetoothGatt,
BluetoothGattCharacteristic paramAnonymousBluetoothGattCharacteristic) {
byte[] arrayOfByte = paramAnonymousBluetoothGattCharacteristic
.getValue();
if(BluetoothController.this.serviceHandler!=null){
Message msg=new Message();
msg.what=ConstantUtils.WM_RECEIVE_MSG_FROM_BLE;
//byte数组转换为十六进制字符串
msg.obj=ConvertUtils.getInstance().bytesToHexString(arrayOfByte);
BluetoothController.this.serviceHandler.sendMessage(msg);
//也可以先打印出来看看
Log.i("TEST",ConvertUtils.getInstance().bytesToHexString(arrayOfByte));
接下来的操作还是一样,接受到数据发消息到service,service发广播更新到activity界面。
byteToHexString是把byte数组转化成16进制的数值的字符串。
3,发送数据
在输入框上填入要发送的数据,点按钮发送数据
[html] view plain copy
btnSend.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
String str=editSend.getText().toString();
if(str!=null&&str.length()>0){
controller.write(str.getBytes());
toast("请填上要发送的内容");
发送方法也在controller中
[html] view plain copy
* 传输数据
* @param byteArray
public boolean write(byte byteArray[]) {
if (bleGattCharacteristic == null)
if (bleGatt == null)
bleGattCharacteristic.setValue(byteArray);
return bleGatt.writeCharacteristic(bleGattCharacteristic);
* 传输数据
* @param byteArray
public boolean write(String str) {
if (bleGattCharacteristic == null)
if (bleGatt == null)
bleGattCharacteristic.setValue(str);
return bleGatt.writeCharacteristic(bleGattCharacteristic);
这里又用来了一个新类,BluetoothGattCharacteristic,他封装了要发送数据,通过bleGatt发送就可以了,bleGatt管的就是连接,断开连接和发送。
最后,一定不要忘了蓝牙的服务,蓝牙有很多服务,要找到我们要的,你怎么知道要那个服务呢,把每个服务的属性都打印出来,你就发现只有一个服务的属性是可读可写的,找到它赋值给数据封装类bleGattCharacteristic就行了。
重写回调的onServicesDiscovered(BluetoothGatt paramAnonymousBluetoothGatt, int paramAnonymousInt)方法发现服务。
[html] view plain copy
public void onServicesDiscovered(
BluetoothGatt paramAnonymousBluetoothGatt, int paramAnonymousInt) {
BluetoothController.this.findService(paramAnonymousBluetoothGatt
.getServices());
[html] view plain copy
* 搜索服务
* @param paramList
public void findService(List paramList) {
Iterator localIterator1 = paramList.iterator();
while (localIterator1.hasNext()) {
BluetoothGattService localBluetoothGattService = (BluetoothGattService) localIterator1
if (localBluetoothGattService.getUuid().toString()
.equalsIgnoreCase(ConstantUtils.UUID_SERVER)) {
List localList = localBluetoothGattService.getCharacteristics();
Iterator localIterator2 = localList.iterator();
while (localIterator2.hasNext()) {
BluetoothGattCharacteristic localBluetoothGattCharacteristic = (BluetoothGattCharacteristic) localIterator2
if (localBluetoothGattCharacteristic.getUuid().toString()
.equalsIgnoreCase(ConstantUtils.UUID_NOTIFY)) {
bleGattCharacteristic = localBluetoothGattC
bleGatt.setCharacteristicNotification(bleGattCharacteristic, true);
[html] view plain copy
public final static
String UUID_SERVER="0000ffe0-00-fb";
public final static
String UUID_NOTIFY="0000ffe1-00-fb";
到哪儿都一样。
如果你看到这儿了,恭喜你,下面都是必备干货:
代码就是这样,包括上次的搜索都在下面的连接里,里面有.apk文件,你先跑跑看效果,还有串口助手exe文件,还有es里的代码,还有串口怎样使用,怎样配置,我真是太贴心了吐舌头。
/s/1geCKYJL
(不要忘了在manifest中加一个权限,为了兼容6.0以上手机:
对了,前几篇文章怎么没人拍砖呢,让我看看哪里不对了好改呀,实在找不到不对的,怎么也没人说句好听的呢?
位网友中有 <span class="font_color" id="vup 位认为值得!
先说自己的解决办法:
(Gradle分两个,一个是本地构建用的构建工具,另一个是Android Studio中的插件,用来调用本地的工具,这里说的是插件)
一、先看看自己的gradle插件版本,项目的build.gradle中gradle:后面为版本号,例:
classpath 'com.android.tools.build:gradle:2.0.0-beta7'
二、在这个网址中找到更高级别的版本号,替换原来的版本号
/com/android/tools/build/gradle/
三、点击Sync Now就会自动下载更新版本
但对于国内来说自动更新貌似有些困难,于是镜像就不可避免了,参考下面网址:
/ 中的腾讯镜像使用方法 http://android-mirror.:8080/include/usage.html
我自己的AS出现Plugin is too old的原因:
1、升级了Android Studio
2、升级了SDK
---------------------------------------------------------------------------
这几天还用的好好的Android Studio突然昨天(日)报错提示BUILD FAILED Plugin is too old
Error:(1, 0) Plugin is too old, please update to a more recent version, or set ANDROID_DAILY_OVERRIDE environment variable to "bdee0ef8"
&a href="fixGradleElements"&Fix plugin version and sync project&/a&&br&&a href="openFile:D:\AndroidStudioProjects\AppTest\app\build.gradle"&Open File&/a&
而当时查看我的插件版本是
classpath 'com.android.tools.build:gradle:2.0.0-alpha7'
网上找了好几种方法都不管用,包括将插件版本提高到2.10或2.+、降低版本为1.2.3、clean后rebuild然后重启、Gradle换成本地等等
后来找到一种方法:升级Android Studio到最新版。于是下载2.0 Beta 6,成功运行,但还是没有明白原因,因为提示错误是插件太旧,那跟AS版本又有什么关系呢?
今天,打开AS运行的时候又报错提示BUILD FAILED,一看还是同昨天一样的问题,我的天哪,瞬间感觉济南的冬天又回来了,今天可是有23度啊。没办法,只好把昨天的坑填上了,这次没办法靠升级AS解决问题了,但从网上搜到的都是和昨天差不多的方法,也有很多Stack Overflow上问同样问题的给的答案只能看懂一部分,那就只好自己分析解决了。
根据提示,是Gradle plugin版本太低的原因。Gradle有两个,一个是本地Gradle,一个是Android Studio中的Gradle plugin也就是AS中的插件。
Gradle plugin版本太低,也就是上图第二行的2.0.0-alpha7这个版本太低了,那就需要换个更高的版本。网上能查到的方法就是下载更高版本的插件放到C:\Users\Administrator\.gradle\wrapper\dists\gradle-2.10-all\a4w5fzrkeut1ox71xslb49gst文件夹中,我去找了,文件都在,如图
但不论我把插件版本换成这三个中的哪一个都会出现以下问题
Error:Could not find com.android.tools.build:gradle:2.10.
Searched in the following locations:
file:/D:/Android/android-studio/gradle/m2repository/com/android/tools/build/gradle/2.10/gradle-2.10.pom
file:/D:/Android/android-studio/gradle/m2repository/com/android/tools/build/gradle/2.10/gradle-2.10.jar
/com/android/tools/build/gradle/2.10/gradle-2.10.pom
/com/android/tools/build/gradle/2.10/gradle-2.10.jar
Required by:
:AppTest:unspecified
找不到,它竟然说找不到,但是明明都在的啊。于是我发现了一个问题:2.0.0-alpha7不在,可是我以前都是用2.0.0-alpha7的,也就是说路径不对。
这时万能的Everything出场了
然后我进入路径发现了这个
于是,一切都明白了,解决方法就是把Gradle插件版本换成2.0.0-beta6就可以了
classpath 'com.android.tools.build:gradle:2.0.0-beta6'
PS:换成1.2.3会报这个错
Error:Gradle version 2.2 is required. Current version is 2.10. If using the gradle wrapper, try editing the distributionUrl in D:\AndroidStudioProjects\AppTest\gradle\wrapper\gradle-wrapper.properties to gradle-2.2-all.zip.
Please fix the project's Gradle settings.
&a href="fixGradleVersionInWrapper"&Fix Gradle wrapper and re-import project&/a&&br&&a href="openGradleSettings"&Gradle settings&/a&
也就是说需要Gradle2.2版本,我现在的版本是2.10(读二点十,不知道Gradle团队怎么想的)版本比它高(现在看来如果你用的还是Gradle2.2之前的版本那么之前改成1.2.3的方法在某些情况下是管用的)。
总结:如果出现了版本太低的错误,用Everything或其他文件查找工具找到你现在在用的版本的位置,然后里面应该有更高版本等着你替换。当然现在我也不甚懂为什么是这个路径,或许又为以后留了个坑,希望知道的大神留言解惑。如果本文有写的不对的地方欢迎指正,多谢。
位网友中有 <span class="font_color" id="vup 位认为值得!
一、关于蓝牙4.0
蓝牙4.0标准包含两个蓝牙标准,准确的说,是一个双模的标准,它包含传统蓝牙部分(也有称之为经典蓝牙Classic Bluetooth)和低功耗蓝牙部分(Bluetooth Low Energy)。这两个部分适用于不同的应用或者应用条件。传统蓝牙是在之前的1.0.1.2,2.0+EDR,2.1+EDR,3.0+EDR等基础上发展和完善起来的,低功耗蓝牙是Nokia的Wibree标准上发展起来的。
传统蓝牙可以用与数据量比较大的传输,如语音,音乐,较高数据量传输等,低功耗蓝牙这样应用于实时性要求比较高,但是数据速率比较低的产品,如遥控类的,如鼠标,键盘,遥控鼠标(Air Mouse),传感设备的数据发送,如心跳带,血压计,温度传感器等。传统蓝牙有3个功率级别,Class1,Class2,Class3,分别支持100m,10m,1m的传输距离,而低功耗蓝牙无功率级别,一般发送功率在7dBm,一般在空旷距离,达到20m应该是没有问题的。
所以蓝牙4.0是集成了传统蓝牙和低功耗蓝牙两个标准的,并不只是低功耗蓝牙。
蓝牙4.0是蓝牙3.0+HS规范的补充,专门面向对成本和功耗都有较高要求的无线方案,较3.0版本更省电、低成本和跨厂商互操作性、3毫秒低延迟、超长有效连接距离、AES-128加密等;蓝牙4.0可广泛用于卫生保健、体育健身、家庭娱乐、安全保障等诸多领域。通常用在蓝牙耳机、蓝牙音箱、计步器、心律监视器、智能仪表、传感器物联网等设备上,大大扩展蓝牙技术的应用范围。该技术拥有极低的运行和待机功耗,使用一粒纽扣电池甚至可连续工作数年之久。
蓝牙4.0支持两种部署方式:双模式和单模式。
双模式中低功耗蓝牙功能集成在现有的经典蓝牙控制器中,或再在现有经典蓝牙技术(2.1+EDR/3.0+HS)芯片上增加低功耗堆栈,整体架构基本不变,因此成本增加有限。
单模式面向高度集成、紧凑的设备,使用一个轻量级连接层(Link Layer)提供超低功耗的待机模式操作、简单设备恢复和可靠的点对多点数据传输,还能让联网传感器在蓝牙传输中安排好低功耗蓝牙流量的次序,同时还有高级节能和安全加密连接。超低的峰值、平均和待机模式功耗。
?速度:支持1Mbps数据传输率下的超短数据包,最少8个八组位,最多27个。所有连接都使用蓝牙2.1加入的减速呼吸模式(sniff subrating)来达到超低工作循环。
?跳频:使用所有蓝牙规范版本通用的自适应跳频,最大程度地减少和其他2.4GHz ISM频段无线技术的串扰。
?主控制:更加智能,可以休眠更长时间,只在需要执行动作的时候才唤醒。
?延迟:最短可在3毫秒内完成连接设置并开始传输数据。
?范围:提高调制指数,最大范围可超过100米(根据不同应用领域, 距离不同)。
?健壮性:所有数据包都使用24-bitCRC校验,确保最大程度抵御干扰。
?安全:使用AES-128 CCM加密算法进行数据包加密和认证。
?拓扑:每个数据包的每次接收都使用32位寻址,理论上可连接数十亿设备;针对一对一连接优化,并支持星形拓扑的一对多连接;使用快速连接和断开,数据可以再网状拓扑内转移而无需维持复杂的网状网络。
二、关于蓝牙BLE
BLE是蓝牙低能耗的简称(Bluetooh Low Energy)。蓝牙低能耗(BLE)技术是低成本、短距离、可互操作的鲁棒性无线技术,工作在免许可的2.4GHz ISM射频频段。它从一开始就设计为超低功耗(ULP)无线技术。它利用许多智能手段最大限度地降低功耗。
蓝牙低能耗架构共有两种芯片构成:单模芯片和双模芯片。蓝牙单模芯片可以和其它单模芯片及双模芯片通信,此时后者需要使用自身架构中的蓝牙低能耗技术部分进行收发数据。双模芯片也能与标准蓝牙技术及使用传统蓝牙架构的其它双模芯片通信。
双模芯片可以在目前使用标准蓝牙芯片的任何场合使用。这样安装有双模芯片的手机、PC、个人导航设备(PND)或其它应用就可以和市场上已经在用的所有传统标准蓝牙设备以及所有未来的蓝牙低能耗设备通信。然而,由于这些设备要求执行标准蓝牙和蓝牙低能耗任务,因此双模芯片针对ULP操作的优化程度没有像单模芯片那么高。
单模芯片可以用单节钮扣电池(如3V、220mAh的CR2032)工作很长时间(几个月甚至几年)。相反,标准蓝牙技术(和蓝牙低能耗双模器件)通常要求使用至少两节AAA电池(电量是钮扣电池的10至12倍,可以容忍高得多的峰值电流),并且更多情况下最多只能工作几天或几周的时间(取决于具体应用)。注意,也有一些高度专业化的标准蓝牙设备,它们可以使用容量比AAA电池低的电池工作。
位网友中有 <span class="font_color" id="vup 位认为值得!
由于Android蓝牙的通信都需要用到UUID,如果由手机发起搜索,当搜索到电脑的蓝牙时,能够得到蓝牙的地址(address),但通信时需要得到BluetoothSocket,而BluetoothSocket则需要电脑蓝牙的UUID,请问这个是怎么样得到的呢?
在蓝牙中,每个服务和服务属性都唯一地由"全球唯一标识符" (UUID)来校验。正如它的名字所暗示的,每一个这样的标识符都要在时空上保证唯一。UUID类可表现为短整形(16或32位)和长整形(128 位)UUID。他提供了分别利用String和16位或32位数值来创建类的构造函数,提供了一个可以比较两个UUID(如果两个都是128位)的方法,还有一个可以转换一个UUID为一个字符串的方法。UUID实例是不可改变的(immutable),只有被UUID标示的服务可以被发现。
在Linux下你用一个命令uuidgen -t可以生成一个UUID值;在Windows下则执行命令uuidgen 。UUID看起来就像如下的这个形式:2dfb-47c2-8d9f-10b8ec891363。当使用生成的UUID去创建一个 UUID对象,你可以去掉连字符。
我搞定了电脑和android手机的蓝牙通信问题:
首先解答几个问题
1.两边的UUID必须是一样的,这是一个服务的唯一标识,而且这个UUID的值必须是
0-805F9B34FB。为什么呢?因为这个是android的API上面说明的,用于普通蓝牙适配器和android手机蓝牙模块连接的,请大家自己看一下android有关bluetooth的API。
2.在连接的时候,如果电脑作为server(一直监听是否有服务连接),android手机作为client(主动和电脑建立连接),则需要在手机端调用这样一行代码:mmSocket.connect();
其中mmSocket是一个BluetoothSocket类,在这句话之前请确定你已经把手机和电脑进行了配对,而且那些乱七八糟的设置都搞定了。
/reference/android/bluetooth/BluetoothDevice.html
public BluetoothSocket createInsecureRfcommSocketToServiceRecord (UUID uuid)
Since: API Level 10Create an RFCOMM BluetoothSocket socket ready to start an insecure outgoing connection to this remote device using SDP lookup of uuid.
The communication channel will not have an authenticated link key i.e it will be subject to man-in-the-middle attacks. For Bluetooth 2.1 devices, the link key will be encrypted, as encryption is mandatory. For legacy devices (pre Bluetooth 2.1 devices) the link key will be not be encrypted. UsecreateRfcommSocketToServiceRecord(UUID) if an encrypted and authenticated communication channel is desired.
This is designed to be used with listenUsingInsecureRfcommWithServiceRecord(String, UUID) for peer-peer Bluetooth applications.
Use connect() to initiate the outgoing connection. This will also perform an SDP lookup of the given uuid to determine which channel to connect to.
The remote device will be authenticated and communication on this socket will be encrypted.
Hint: If you are connecting to a Bluetooth serial board then try using the well-known SPP UUID 0-805F9B34FB. However if you are connecting to an Android peer then please generate your own unique UUID.
位网友中有 <span class="font_color" id="vup 位认为值得!
——UUID是“Universally Unique Identifier”的简称,通用唯一识别码的意思。对于蓝牙设备,每个服务都有通用、独立、唯一的UUID与之对应。也就是说,在同一时间、同一地点,不可能有两个相同的UUID标识的不同服务。
以上的文字主要是起到一个明白概念的作用。在Android手机方面不必过多考虑这点在这一点,因为几乎没有哪个手机会同时装两块蓝牙芯片~~~~~
以下是转载……
中可能用到的各种蓝牙服务对于的UUID码
ServiceDiscoveryServerServiceClassID_UUID = ‘{0-805F9B34FB}’
BrowseGroupDescriptorServiceClassID_UUID = ‘{0-805F9B34FB}’
PublicBrowseGroupServiceClass_UUID = ‘{0-805F9B34FB}’
#蓝牙串口服务
SerialPortServiceClass_UUID = ‘{0-805F9B34FB}’
LANAccessUsingPPPServiceClass_UUID = ‘{0-805F9B34FB}’
#拨号网络服务
DialupNetworkingServiceClass_UUID = ‘{0-805F9B34FB}’
#信息同步服务
IrMCSyncServiceClass_UUID = ‘{0-805F9B34FB}’
SDP_OBEXObjectPushServiceClass_UUID = ‘{0-805F9B34FB}’
#文件传输服务
OBEXFileTransferServiceClass_UUID = ‘{0-805F9B34FB}’
IrMCSyncCommandServiceClass_UUID = ‘{0-805F9B34FB}’
SDP_HeadsetServiceClass_UUID = ‘{0-805F9B34FB}’
CordlessTelephonyServiceClass_UUID = ‘{0-805F9B34FB}’
SDP_AudioSourceServiceClass_UUID = ‘{00-805F9B34FB}’
SDP_AudioSinkServiceClass_UUID = ‘{00-805F9B34FB}’
SDP_AVRemoteControlTargetServiceClass_UUID = ‘{00-805F9B34FB}’
SDP_AdvancedAudioDistributionServiceClass_UUID = ‘{00-805F9B34FB}’
SDP_AVRemoteControlServiceClass_UUID = ‘{00-805F9B34FB}’
VideoConferencingServiceClass_UUID = ‘{00-805F9B34FB}’
IntercomServiceClass_UUID = ‘{0-805F9B34FB}’
#蓝牙传真服务
FaxServiceClass_UUID = ‘{0-805F9B34FB}’
HeadsetAudioGatewayServiceClass_UUID = ‘{0-805F9B34FB}’
WAPServiceClass_UUID = ‘{0-805F9B34FB}’
WAPClientServiceClass_UUID = ‘{0-805F9B34FB}’
#个人局域网服务
PANUServiceClass_UUID = ‘{0-805F9B34FB}’
#个人局域网服务
NAPServiceClass_UUID = ‘{0-805F9B34FB}’
#个人局域网服务
GNServiceClass_UUID = ‘{0-805F9B34FB}’
DirectPrintingServiceClass_UUID = ‘{0-805F9B34FB}’
ReferencePrintingServiceClass_UUID = ‘{0-805F9B34FB}’
ImagingServiceClass_UUID = ‘{00-805F9B34FB}’
ImagingResponderServiceClass_UUID = ‘{00-805F9B34FB}’
ImagingAutomaticArchiveServiceClass_UUID = ‘{00-805F9B34FB}’
ImagingReferenceObjectsServiceClass_UUID = ‘{00-805F9B34FB}’
SDP_HandsfreeServiceClass_UUID = ‘{00-805F9B34FB}’
HandsfreeAudioGatewayServiceClass_UUID = ‘{00-805F9B34FB}’
DirectPrintingReferenceObjectsServiceClass_UUID = ‘{0-805F9B34FB}’
ReflectedUIServiceClass_UUID = ‘{0-805F9B34FB}’
BasicPringingServiceClass_UUID = ‘{0-805F9B34FB}’
PrintingStatusServiceClass_UUID = ‘{0-805F9B34FB}’
#人机输入服务
HumanInterfaceDeviceServiceClass_UUID = ‘{0-805F9B34FB}’
HardcopyCableReplacementServiceClass_UUID = ‘{0-805F9B34FB}’
#蓝牙打印服务
HCRPrintServiceClass_UUID = ‘{0-805F9B34FB}’
HCRScanServiceClass_UUID = ‘{0-805F9B34FB}’
CommonISDNAccessServiceClass_UUID = ‘{0-805F9B34FB}’
VideoConferencingGWServiceClass_UUID = ‘{0-805F9B34FB}’
UDIMTServiceClass_UUID = ‘{00-805F9B34FB}’
UDITAServiceClass_UUID = ‘{00-805F9B34FB}’
AudioVideoServiceClass_UUID = ‘{00-805F9B34FB}’
SIMAccessServiceClass_UUID = ‘{00-805F9B34FB}’
PnPInformationServiceClass_UUID = ‘{0-805F9B34FB}’
GenericNetworkingServiceClass_UUID = ‘{0-805F9B34FB}’
GenericFileTransferServiceClass_UUID = ‘{0-805F9B34FB}’
GenericAudioServiceClass_UUID = ‘{0-805F9B34FB}’
GenericTelephonyServiceClass_UUID = ‘{0-805F9B34FB}’
转载请注明出处: /archives/1176
位网友中有 <span class="font_color" id="vup 位认为值得!
浏览:1,580
最近项目中使用到蓝牙SPP协议通信,然后在网上看了很多资料,进行学习使用,为了加深印象,做个简单的整理。
1、使用蓝牙权限
& uses-permission :name="android.permission.BLUETOOTH" /&
& uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /&
2、蓝牙核心类BluetoothAdapter
代表本地的蓝牙适配器设备。BluetoothAdapter类让用户能执行基本的蓝牙任务。例如:初始化设备的搜索,查询可匹配的设备集,使用一个已知的MAC地址来初始化一个BluetoothDevice类,创建一个 BluetoothServerSocket类以监听其它设备对本机的连接请求等。
  为了得到这个代表本地蓝牙适配器的 BluetoothAdapter类,调用getDefaultAdapter()这一静态方法。这是所有蓝牙动作使用的第一步。当拥有本地适配器以后,用户可以获得一系列的BluetoothDevice对象,这些对象代表所有拥有getBondedDevice()方法的已经匹配的设备;用 startDiscovery()方法来开始设备的搜寻;或者创建一个BluetoothServerSocket类,通过 listenUsingRfcommWithServiceRecord(String, UUID)方法来监听新来的连接请求。
打开系统的蓝牙设置面板
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(intent);
adapter.enable();
adapter.disable();
设置对别的设备可见
Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//设置持续时间(最多300秒)
adapter.startDiacovery(),当在代码中调用了该方法时,系统会发送广播ACTION_FOUND:找到设备,我们可以在代码中注册一个广播,用来接受系统发送的广播。
// 注册BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // 不要忘了之后解除绑定
// 创建一个接收ACTION_FOUND广播的BroadcastReceiver
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// 发现设备
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// 从Intent中获取设备对象
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 将设备名称和地址放入array adapter,以便在ListView中显示
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
位网友中有 <span class="font_color" id="vup 位认为值得!
1、基本的绘制图片方法
//Bitmap:图片对象,left:偏移左边的位置,top: 偏移顶部的位置
drawBitmap(Bitmap bitmap, float left, float top, Paint paint)
2、对图片剪接和限定显示区域
drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint);
Rect src: 是对图片进行裁截,若是空null则显示整个图片
RectF dst:是图片在Canvas画布中显示的区域,
大于src则把src的裁截区放大,
小于src则把src的裁截区缩小。
位网友中有 <span class="font_color" id="vup 位认为值得!
Android是通过graphics类来显示2D图形的。其中graphics中包括了Canvas、Paint、Color、Bitmap等类。graphics具有绘制点、线、颜色、2D几何图形、图像处理等功能。其中Color和Bitmap是很常用的类,我要讲的是Canvas和Paint。顾名思义就是画布和画笔。接下来我将通过绘制太极图来学习Android绘图机制。
Paint类   和日常绘图一样,要绘制图形,首先得选择合适的画笔。那么同理android中绘图首先得调整画笔,按照自己的需要设置画笔的相关属性,系统给我提供的常用API如下:   setColor(); //设置画笔的颜色   setAntiAlias(); //设置画笔的锯齿效果   setARGB(); //设置画笔的A、R、G、B值   setAlpha(); //设置画笔的Alpha值   setTextSize(); //设置字体的尺寸   setStyle(); //设置画笔的风格(空心或实心)   setStrokeWidth(); //设置空心边框的宽度   getColor(); //获取画笔的颜色
  Canvas   Canvas即画布,我们需要做的就是使用之前设置好的Paint来绘制图形。那么我们先看看系统给我们提供的方法:   canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint);//绘制直线   canvas.drawRect(float left, float top, float right, float bottom, Paint paint);//绘制矩形   canvas.drawCircle(float cx, float cy, float radius, Paint paint);//绘制圆   canvas.drawArc(float cx, float cy, float radius, Paint paint);//绘制弧形、和扇形  
canvas.drawText(String text, float x, float y, Paint paint);// 绘制字符   canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint);//绘制Bitmap
介绍完这些函数,下面通过绘制太极图来看看怎么使用它们:   先看看太极图:
现在就要开始一步一步的将他画出来, 我们可以借鉴图层的概念。首先绘制最底部的图层,为了方便我们将其左,右两边分别设置白色和黑色:
图中(x,y)是圆心坐标。这里我设置的x=getWidth() / 2;y=getHeight() / 2;半径r=getHeight() / 2;   现在我们就来看看代码,在定义View的OnDraw(Canvas canvas)方法中:
//绘制最外层大圆
mPaint.setColor(Color.BLACK);//设置画笔颜色为黑色
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//设置画笔style实心
RectF rect= new RectF(getWidth() / 2 - getHeight() / 2,
0, getWidth() / 2 + getHeight() / 2, getHeight());//圆弧的外接矩形
canvas.drawArc(rect, 270, 180, false, mPaint);
mPaint.setColor(Color.WHITE);//设置画笔颜色为白色
canvas.drawArc(rect, 90, 180, false, mPaint);
代码中rect即圆的外接四边形,其构造函数RectF(float left, float top, float right, float bottom)的四个参数分别对应四边形最左边的x坐标值;左上边的y坐标值;最右边的x坐标值;最下边的y坐标值。可以看出代码中:
left=getWidth() / 2 - getHeight() / 2;
right=getWidth() / 2 + getHeight() / 2;
bottom=getHeight();
四个值确定了圆的外接四边形。   canvas.drawArc(rect, 90, 180, false, mPaint);第一个参数即是我们上边确定的区域,第二个参数是开始绘制的角度(90度,x轴方向顺时针旋转),第三个参数扫描的度数,第四个参数设置好的画笔Paint。   接下来我们要着手绘制中间图层,中间图层可以看做是两个上下外切的半圆,上边白色右半圆,下边黑色左半圆:
同理,我们应该也是先确定外接四边形的区域,然后在画圆弧这里就不再详述。
//绘制中间层上边圆
mPaint.setColor(Color.BLACK);
rect= new RectF(getWidth()/2-getHeight()/4,0,getWidth() / 2 + getHeight() / 4, getHeight() /2);
canvas.drawArc(rect, 90, 180, false, mPaint);
//绘制中间层下边圆
mPaint.setColor(Color.WHITE);
rect= new RectF(getWidth()/2-getHeight() / 4, getHeight() / 2, getWidth() / 2 + getHeight() / 4, getHeight());
canvas.drawArc(rect, 270, 180, false, mPaint);
最后,最上边图层上下两个小圆
//绘制最上层白色小圆
mPaint.setColor(Color.WHITE);
canvas.drawCircle(getWidth() / 2, getHeight() / 4, getHeight() / 10, mPaint);
//绘制最上层黑色小圆
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(getWidth() / 2, getHeight() * 3 / 4, getHeight() / 10, mPaint);
canvas.drawCircle是用来画圆的,第一个参数是圆心x坐标值,第二个参数是y坐标值,第三个坐标是圆的半径,第四个是设置的画笔。   到此就画出了一个太极图。
附上自定义View的代码 :
package com.chuck.mobile.changecountview.
import android.content.C
import android.graphics.C
import android.graphics.C
import android.graphics.P
import android.graphics.P
import android.graphics.RectF;
import android.util.AttributeS
import android.view.V
* 项目名称:changecountview
* 类描述:
* 创建人:Administrator
* 创建时间: 16:37
* 修改人:Administrator
* 修改时间: 16:37
* 修改备注:
public class CustomeView extends View{
private Paint mPaint=new Paint();
private Path path=new Path();
private float degress=90;
public CustomeView(Context context) {
super(context);
public CustomeView(Context context, AttributeSet attrs) {
super(context, attrs);
public CustomeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
protected void onDraw(Canvas canvas) {
//绘制最外层大圆
mPaint.setColor(Color.BLACK);//设置画笔颜色为黑色
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//设置画笔style实心
RectF rect= new RectF(getWidth() / 2 - getHeight() / 2,
0, getWidth() / 2 + getHeight() / 2, getHeight());//圆弧的外接矩形
canvas.drawArc(rect, 270, 180, false, mPaint);
mPaint.setColor(Color.WHITE);//设置画笔颜色为白色
canvas.drawArc(rect, 90, 180, false, mPaint);
//绘制中间层上边圆
mPaint.setColor(Color.BLACK);
rect= new RectF(getWidth()/2-getHeight()/4,0,getWidth() / 2 + getHeight() / 4, getHeight() /2);
canvas.drawArc(rect, 90, 180, false, mPaint);
//绘制中间层下边圆
mPaint.setColor(Color.WHITE);
rect= new RectF(getWidth()/2-getHeight() / 4, getHeight() / 2, getWidth() / 2 + getHeight() / 4, getHeight());
canvas.drawArc(rect, 270, 180, false, mPaint);
//绘制最上层白色小圆
mPaint.setColor(Color.WHITE);
canvas.drawCircle(getWidth() / 2, getHeight() / 4, getHeight() / 10, mPaint);
//绘制最上层黑色小圆
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(getWidth() / 2, getHeight() * 3 / 4, getHeight() / 10, mPaint);
然后在布局文件中使用自定义View
&com.chuck.mobile.changecountview.widget.CustomeView
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@color/gray"/&
如果想让这个太极图转起来,方法有很多,可以使用动画也可以通过旋转画布的方式实现。我自己使用了通过线程在旋转画布的方法。大家掌握了Android 2D绘图技巧就可以绘制自己感兴趣的图案。
Android是通过graphics类来显示2D图形的。其中graphics中包括了Canvas、Paint、Color、Bitmap等类。graphics具有绘制点、线、颜色、2D几何图形、图像处理等功能。其中Color和Bitmap是很常用的类,我要讲的是Canvas和Paint。顾名思义就是画布和画笔。接下来我将通过绘制太极图来学习Android绘图机制。
Paint类   和日常绘图一样,要绘制图形,首先得选择合适的画笔。那么同理android中绘图首先得调整画笔,按照自己的需要设置画笔的相关属性,系统给我提供的常用API如下:   setColor(); //设置画笔的颜色   setAntiAlias(); //设置画笔的锯齿效果   setARGB(); //设置画笔的A、R、G、B值   setAlpha(); //设置画笔的Alpha值   setTextSize(); //设置字体的尺寸   setStyle(); //设置画笔的风格(空心或实心)   setStrokeWidth(); //设置空心边框的宽度   getColor(); //获取画笔的颜色
  Canvas   Canvas即画布,我们需要做的就是使用之前设置好的Paint来绘制图形。那么我们先看看系统给我们提供的方法:   canvas.drawLine(float startX, float startY, float stopX, float stopY, Paint paint);//绘制直线   canvas.drawRect(float left, float top, float right, float bottom, Paint paint);//绘制矩形   canvas.drawCircle(float cx, float cy, float radius, Paint paint);//绘制圆   canvas.drawArc(float cx, float cy, float radius, Paint paint);//绘制弧形、和扇形  
canvas.drawText(String text, float x, float y, Paint paint);// 绘制字符   canvas.drawBitmap(Bitmap bitmap, float left, float top, Paint paint);//绘制Bitmap
介绍完这些函数,下面通过绘制太极图来看看怎么使用它们:   先看看太极图:
现在就要开始一步一步的将他画出来, 我们可以借鉴图层的概念。首先绘制最底部的图层,为了方便我们将其左,右两边分别设置白色和黑色:
图中(x,y)是圆心坐标。这里我设置的x=getWidth() / 2;y=getHeight() / 2;半径r=getHeight() / 2;   现在我们就来看看代码,在定义View的OnDraw(Canvas canvas)方法中:
//绘制最外层大圆
mPaint.setColor(Color.BLACK);//设置画笔颜色为黑色
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//设置画笔style实心
RectF rect= new RectF(getWidth() / 2 - getHeight() / 2,
0, getWidth() / 2 + getHeight() / 2, getHeight());//圆弧的外接矩形
canvas.drawArc(rect, 270, 180, false, mPaint);
mPaint.setColor(Color.WHITE);//设置画笔颜色为白色
canvas.drawArc(rect, 90, 180, false, mPaint);
代码中rect即圆的外接四边形,其构造函数RectF(float left, float top, float right, float bottom)的四个参数分别对应四边形最左边的x坐标值;左上边的y坐标值;最右边的x坐标值;最下边的y坐标值。可以看出代码中:
left=getWidth() / 2 - getHeight() / 2;
right=getWidth() / 2 + getHeight() / 2;
bottom=getHeight();
四个值确定了圆的外接四边形。   canvas.drawArc(rect, 90, 180, false, mPaint);第一个参数即是我们上边确定的区域,第二个参数是开始绘制的角度(90度,x轴方向顺时针旋转),第三个参数扫描的度数,第四个参数设置好的画笔Paint。   接下来我们要着手绘制中间图层,中间图层可以看做是两个上下外切的半圆,上边白色右半圆,下边黑色左半圆:
同理,我们应该也是先确定外接四边形的区域,然后在画圆弧这里就不再详述。
//绘制中间层上边圆
mPaint.setColor(Color.BLACK);
rect= new RectF(getWidth()/2-getHeight()/4,0,getWidth() / 2 + getHeight() / 4, getHeight() /2);
canvas.drawArc(rect, 90, 180, false, mPaint);
//绘制中间层下边圆
mPaint.setColor(Color.WHITE);
rect= new RectF(getWidth()/2-getHeight() / 4, getHeight() / 2, getWidth() / 2 + getHeight() / 4, getHeight());
canvas.drawArc(rect, 270, 180, false, mPaint);
最后,最上边图层上下两个小圆
//绘制最上层白色小圆
mPaint.setColor(Color.WHITE);
canvas.drawCircle(getWidth() / 2, getHeight() / 4, getHeight() / 10, mPaint);
//绘制最上层黑色小圆
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(getWidth() / 2, getHeight() * 3 / 4, getHeight() / 10, mPaint);
canvas.drawCircle是用来画圆的,第一个参数是圆心x坐标值,第二个参数是y坐标值,第三个坐标是圆的半径,第四个是设置的画笔。   到此就画出了一个太极图。
附上自定义View的代码 :
package com.chuck.mobile.changecountview.
import android.content.C
import android.graphics.C
import android.graphics.C
import android.graphics.P
import android.graphics.P
import android.graphics.RectF;
import android.util.AttributeS
import android.view.V
* 项目名称:changecountview
* 类描述:
* 创建人:Administrator
* 创建时间: 16:37
* 修改人:Administrator
* 修改时间: 16:37
* 修改备注:
public class CustomeView extends View{
private Paint mPaint=new Paint();
private Path path=new Path();
private float degress=90;
public CustomeView(Context context) {
super(context);
public CustomeView(Context context, AttributeSet attrs) {
super(context, attrs);
public CustomeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
protected void onDraw(Canvas canvas) {
//绘制最外层大圆
mPaint.setColor(Color.BLACK);//设置画笔颜色为黑色
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//设置画笔style实心
RectF rect= new RectF(getWidth() / 2 - getHeight() / 2,
0, getWidth() / 2 + getHeight() / 2, getHeight());//圆弧的外接矩形
canvas.drawArc(rect, 270, 180, false, mPaint);
mPaint.setColor(Color.WHITE);//设置画笔颜色为白色
canvas.drawArc(rect, 90, 180, false, mPaint);
//绘制中间层上边圆
mPaint.setColor(Color.BLACK);
rect= new RectF(getWidth()/2-getHeight()/4,0,getWidth() / 2 + getHeight() / 4, getHeight() /2);
canvas.drawArc(rect, 90, 180, false, mPaint);
//绘制中间层下边圆
mPaint.setColor(Color.WHITE);
rect= new RectF(getWidth()/2-getHeight() / 4, getHeight() / 2, getWidth() / 2 + getHeight() / 4, getHeight());
canvas.drawArc(rect, 270, 180, false, mPaint);
//绘制最上层白色小圆
mPaint.setColor(Color.WHITE);
canvas.drawCircle(getWidth() / 2, getHeight() / 4, getHeight() / 10, mPaint);
//绘制最上层黑色小圆
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(getWidth() / 2, getHeight() * 3 / 4, getHeight() / 10, mPaint);
然后在布局文件中使用自定义View
&com.chuck.mobile.changecountview.widget.CustomeView
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@color/gray"/&
如果想让这个太极图转起来,方法有很多,可以使用动画也可以通过旋转画布的方式实现。我自己使用了通过线程在旋转画布的方法。大家掌握了Android 2D绘图技巧就可以绘制自己感兴趣的图案。
位网友中有 <span class="font_color" id="vup 位认为值得!
近半个月来一直在搞android蓝牙这方面,主要是项目需要与蓝牙模块进行通信。开头的进展很顺利,但因为蓝牙模块不在我这里,所以只能用手机测试。一开头就发现手机的蓝牙不能用,为了证明这点,我刷了四次不同不同系统的官方包,正式宣布手机的蓝牙报销了,于是和朋友换手机。在测试的过程中也是非常痛苦,放假了,同学都几乎回家了,剩下的同学中竟然80%都是用非android手机!我和我的小伙伴都吓呆了!!就算借来了手机,测试过程中老是有人打电话过来,严重影响我的开发!!于是,我果断催促对方快点把蓝牙模块寄过来,等模块寄过来后,半个小时内就搞定了!!
于是,我得到了很好的教训:请确保项目中的最关键因素是否在我们的掌握中。像是蓝牙模块这种东西,应该今早催促对方拿过来才是,而不是自己一个人在那边瞎搞。
唠叨话就先到这里,正篇正式开始。
android蓝牙这方面还是很好搞的,因为大家的方式都是差不多的。先说说如何开启蓝牙设备和设置可见时间:
private void search() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (!adapter.isEnabled()) {
adapter.enable();
Intent enable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
enable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 3600); //3600为蓝牙设备可见时间
startActivity(enable);
Intent searchIntent = new Intent(this, ComminuteActivity.class);
startActivity(searchIntent);
首先,需要获得一个BluetoothAdapter,可以通过getDefaultAdapter()获得系统默认的蓝牙适配器,当然我们也可以自己指定,但这个真心没有必要,至少我是不需要的。然后我们检查手机的蓝牙是否打开,如果没有,通过enable()方法打开。接着我们再设置手机蓝牙设备的可见,可见时间可以自定义。
完成这些必要的设置后,我们就可以正式开始与蓝牙模块进行通信了:
public class ComminuteActivity extends Activity {
private BluetoothR
private BluetoothAdapter bluetoothA
private List
private List deviceL
private final String lockName = "BOLUTEK";
private String message = "000001";
private ListView listV
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_layout);
listView = (ListView) this.findViewById(R.id.list);
deviceList = new ArrayList();
devices = new ArrayList();
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
bluetoothAdapter.startDiscovery();
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
receiver = new BluetoothReceiver();
registerReceiver(receiver, filter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView parent, View view, int position, long id) {
setContentView(R.layout.connect_layout);
BluetoothDevice device = deviceList.get(position);
client = new Bluetooth(device, handler);
client.connect(message);
} catch (Exception e) {
Log.e("TAG", e.toString());
protected void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case Bluetooth.CONNECT_FAILED:
Toast.makeText(ComminuteActivity.this, "连接失败", Toast.LENGTH_LONG).show();
client.connect(message);
} catch (Exception e) {
Log.e("TAG", e.toString());
case Bluetooth.CONNECT_SUCCESS:
Toast.makeText(ComminuteActivity.this, "连接成功", Toast.LENGTH_LONG).show();
case Bluetooth.READ_FAILED:
Toast.makeText(ComminuteActivity.this, "读取失败", Toast.LENGTH_LONG).show();
case Bluetooth.WRITE_FAILED:
Toast.makeText(ComminuteActivity.this, "写入失败", Toast.LENGTH_LONG).show();
case Bluetooth.DATA:
Toast.makeText(ComminuteActivity.this, msg.arg1 + "", Toast.LENGTH_LONG).show();
private class BluetoothReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (isLock(device)) {
devices.add(device.getName());
deviceList.add(device);
showDevices();
private boolean isLock(BluetoothDevice device) {
boolean isLockName = (device.getName()).equals(lockName);
boolean isSingleDevice = devices.indexOf(device.getName()) == -1;
return isLockName &#038;& isSingleD
private void showDevices() {
ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,
listView.setAdapter(adapter);
要想与任何蓝牙模块进行通信,首先得搜到该设备:
private class BluetoothReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (isLock(device)) {
devices.add(device.getName());
deviceList.add(device);
showDevices();
在这之前,我们得先调用一个方法:
bluetoothAdapter.startDiscovery();
startDiscovery()方法是一个异步方法,它会对其他蓝牙设备进行搜索,持续时间为12秒。搜索过程其实是在System Service中进行,我们可以通过cancelDiscovery()方法来停止这个搜索。在系统搜索蓝牙设备的过程中,系统可能会发送以下三个广播:ACTION_DISCOVERY_START(开始搜索),ACTION_DISCOVERY_FINISHED(搜索结束)和ACTION_FOUND(找到设备)。ACTION_FOUND这个才是我们想要的,这个Intent中包含两个extra fields:EXTRA_DEVICE和EXTRA_CLASS,包含的分别是BluetoothDevice和BluetoothClass,BluetoothDevice中的EXTRA_DEVICE就是我们搜索到的设备对象。 确认搜索到设备后,我们可以从得到的BluetoothDevice对象中获得设备的名称和地址。
在android中使用广播需要我们注册,这里也不例外:
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
receiver = new BluetoothReceiver();
registerReceiver(receiver, filter);
广播注册后需要我们撤销,这个可以放在这里进行:
protected void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
这样在Activity结束的时候就会自动撤销该广播,而不需要我们手动执行。
我这里使用一个ListView来显示搜索到的蓝牙设备,但因为需要只限定一个蓝牙设备,所以这里进行了检查,检查该设备是否是我们的目标设备,如果是,就添加。当然,为了防止重复添加,有必要增加这么一句:
boolean isSingleDevice = devices.indexOf(device.getName()) == -1;
搜索到该设备后,我们就要对该设备进行连接。
public void connect(final String message) {
Thread thread = new Thread(new Runnable() {
public void run() {
BluetoothSocket tmp =
method = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
tmp = (BluetoothSocket) method.invoke(device, 1);
} catch (Exception e) {
setState(CONNECT_FAILED);
Log.e("TAG", e.toString());
socket.connect();
isConnect =
} catch (Exception e) {
setState(CONNECT_FAILED);
Log.e("TAG", e.toString());
连接设备之前需要UUID,所谓的UUID,就是用来进行配对的,全称是Universally Unique Identifier,是一个128位的字符串ID,用于进行唯一标识。网上的例子,包括谷歌的例子,它们的UUID都是说能用但是我用不了的,都会报出这样的错误:
Service discovery failed
原因可能是作为唯一标识的UUID没有发挥作用,所以,我就利用反射的原理,让设备自己提供UUID。
这个错误在我们把手机既当做客户端有当做服务端的时候,同样也有可能出现,因为作为服务器的时候,我们需要的也是同一个UUID:
mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
作为客户端是这样的:
device.createRfcommSocketToServiceRecord(MY_UUID);
当两个UUID想同时建立Rfcomm的通道时,我们的选择都是在两个线程中分别实现,但是忽略了一件最重要的事情:同一个时间只能充当一个角色!所以,解决这个问题的方法就是在我们相连接的设备上也安装同样的应用程序,谁先发起连接谁就是客户端,但我这里是蓝牙模块啊!!怎么能安装我的应用程序呢!!解决办法就在下面的通信中。
连接设备之前还有一件事必须确保:
bluetoothAdapter.cancelDiscovery();
这是为了停掉搜索设备,否则连接可能会变得非常慢并且容易失败。
有关于Socket的编程都需要我们设置一些状态值来标识通信的状态,以方便我们调错,而且连接应该放在一个线程中进行,要让该线程与我们程序的主线程进行通信,我们需要使用Handle,关于Handle的使用,可以参考我的另一篇博客/wenjiang/p/3180324.html,这里不多讲。
在使用Socket中,我注意到一个方法:isConnect(),它返回的是布尔值,但是根本就不需要使用到这个方法,Socket的连接如果没有报错,说明是已经连接上了。
在谷歌提供的例子中,我们可以看到谷歌的程序员的程序水平很高,一些好的编码习惯我们可以学习一下,像是在try..catch中才定义的变量,我们应该在try...catch之前声明一个临时变量,然后再在try...catch后赋值给我们真正要使用的变量。这种做法的好处就是:如果我们直接就是使用真正的变量,当出现异常的时候,该变量的使用就会出现问题,而且很难进行排查,如果是临时变量,我么可以通过检查变量的值来确定是否是赋值时出错。
谷歌的例子中最大的感想就是满满的异常检查,但也是因为这个,导致它的可读性不高。java的异常处理机制有时候对于代码的阅读真的不是一件舒服的事情,能避免就尽量避免。
如果连接没有问题,我们就可以和蓝牙模块进行通信:
if (isConnect) {
OutputStream outStream = socket.getOutputStream();
outStream.write(getHexBytes(message));
} catch (IOException e) {
setState(WRITE_FAILED);
Log.e("TAG", e.toString());
InputStream inputStream = socket.getInputStream();
while (true) {
data = inputStream.read();
Message msg = handler.obtainMessage();
msg.what = DATA;
msg.arg1 =
handler.sendMessage(msg);
} catch (IOException e) {
setState(READ_FAILED);
Log.e("TAG", e.toString());
} catch (IOException e) {
setState(WRITE_FAILED);
Log.e("TAG", e.toString());
if (socket != null) {
socket.close();
} catch (IOException e) {
Log.e("TAG", e.toString());
这里包括写入和读取,用法和基本的Socket是一样的,但是写入的时候,需要将字符串转化为16进制:
private byte[] getHexBytes(String message) {
int len = message.length() / 2;
char[] chars = message.toCharArray();
String[] hexStr = new String[len];
byte[] bytes = new byte[len];
for (int i = 0, j = 0; j < i += 2, j++) {
hexStr[j] = "" + chars[i] + chars[i + 1];
bytes[j] = (byte) Integer.parseInt(hexStr[j], 16);
当然,这里只是将手机当做客户端,但是接收蓝牙模块发送过来的信息是没有必要特意创建服务端的,我们只要一个不断监听并读取对方消息的循环就行。
很简单的程序就能实现像是蓝牙串口助手的功能,由于是项目的代码,不能贴完整的代码,但是基本上都在上面了,大家可以参考一下。要想使用蓝牙,相应的权限也是必不可少的:
代码放在github上:/wenjiang/Bluetooth2.git
位网友中有 <span class="font_color" id="vup 位认为值得!
更新方法:
第一步:在你所在项目文件夹下:你项目根目录\gradle\wrapper\gradle-wrapper.properties
修改gradle-wrapper.properties最后一行的地址(我的是:distributionUrl=http\://services.gradle.org/distributions/gradle-2.1-all.zip),最新gradle地址从官方下载的地方有。比如目前最新的版本是:gradle-2.13-rc-1-all。然后将上面的distributionUrl=http\://services.gradle.org/distributions/gradle-2.1-all.zip替换成:distributionUrl=http\://services.gradle.org/distributions/gradle-2.13-rc-1-all.zip就行。
第二步;在Android studio的终端Terminal输入gradlew build执行命令,等一会出现BUILD SUCCESSFUL,说明更新成功。
如下载慢,可参考如下一些方法,但是本人未亲测:
1.http://ask.android-studio.org/?/question/70
2。http://blog.csdn.NET/u/article/details/
附上官网地址和gradle各版本下载地址:
官网:http://gradle.org/release-candidate/
各版本下载地址:http://services.gradle.org/distributions
位网友中有 <span class="font_color" id="vup 位认为值得!
验证码:6 + 9

我要回帖

更多关于 智能电视硬件配置 的文章

 

随机推荐