Android蓝牙遥控器
这是以前做的一个手机蓝牙遥控器,原本是用来控制一个微型四旋翼的。四旋翼做了第二版后改NRF2401控制了,所以这个程序最终还是没用,下面介绍一下这个程序的关键代码。
连接的对象是一个蓝牙4.0模块,连接上了之后通过串口对飞机进行控制。说一下蓝牙模块的距离,可能因为是用的是蓝牙4.0的缘故,我在走廊里面测试是33米的距离,还是挺远的,足够了。这个程序连接的上蓝牙模块的是有概率失败的,我使用的魅族手机,失败的概率非常高,但是换成的华为手机后,失败概率就小多了,所以这个成功率还是跟手机厂商的优化有关的,但是连接上了还是非常稳定的。
下面介绍程序功能,该程序该程序包括两个Activity,主Activity如下图所示:
主Activity是一个遥控界面(按钮是随便拉进去的,各种没对齐-_-),点击蓝牙连接按钮,可以跳到第二个Activity,如下图:
这个Activity包括一个ListView,点击开启蓝牙Button查找设备,并把所查找到的设备名称放在ListView里面,点击ListView中要连接的设备,就会跳回主Activity,同时进行蓝牙连接。在屏幕的中间显示连接状态,连接成功后即可传输数据。
总的来说,要使用Android的蓝牙,主要分下面几步:
- 开启蓝牙
- 查找设备
- 蓝牙连接
- 接收或发送数据
因为开启蓝牙Button在从Activity里面,所以开启蓝牙的操作应该是在从Activity中的,因此需要从主Activity切换到从Activity,这里很简单就省略了。下面是开启蓝牙的代码:
Intent enable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
//3600为蓝牙设备可见时间
enable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 3600);
startActivity(enable);
通过Intent开启蓝牙,写到按钮事件中就可以点击按钮开启蓝牙。
开启蓝牙蓝牙之后,就可以调用适配器来查找蓝牙设备了,其代码如下:
private BluetoothAdapter adapter;
private BluetoothReceiver receiver;adapter = BluetoothAdapter.getDefaultAdapter();//得到默认的蓝牙适配器
if (adapter.getState() != BluetoothAdapter.STATE_ON) {// 如果蓝牙还没开启Toast.makeText(MyBlueTooth.this, "请开启蓝牙", Toast.LENGTH_SHORT).show();
}else {adapter.startDiscovery();//开始搜索IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);receiver = new BluetoothReceiver();registerReceiver(receiver, filter);//注册广播
}
首先通过adtapter
查看蓝牙是否开启,如开启则开始搜索,其中adapter.startDiscovery()
是一个异步方法,调用后在后台对周围的蓝牙设备进行搜索,然后将搜索结果通过广播的形式发送,所以这里要注册广播,BluetoothReceiver
是自定义的一个广播接收器,继承自BroadcastReceiver
类,这里定义成了一内部类,代码如下:
private ListView listView;
private List<String> deviceNames;
private List deviceList; listView = (ListView)findViewById(R.id.listView);
deviceNames = new ArrayList<String>();
deviceList = new ArrayList();
//内部类
private class BluetoothReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (BluetoothDevice.ACTION_FOUND.equals(action)) {//发现设备BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (deviceNames.indexOf(device.getName()) == -1) {//列表中没有名字deviceNames.add(device.getName());//添加}deviceList.add(device);}showDevices();}
}
private void showDevices() {ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,deviceNames);listView.setAdapter(adapter);
}
这里涉及到了一些ListView的用法,就不展开了。
前面几步进展地还比较顺利,但到了蓝牙连接这里就出现了很多问题。第一是BluetoothSocket
的两种创建方式,一种是通过特定的UUID来创建,我试了很多次连接都成问题,然后查到了第二种方法,通过调用BlueDevice
的隐藏方法createRfcommSocket()
来创建socket,应用到了Java的反射机制,这种方法只能说能够连上,失败的概率还是很大的(之后测试了其他手机,连接成功率就上去了,可能跟不同的手机厂商的优化有关,问题也可能出在代码本身上)。第二是连接耗时比较长,所以不能放到主线程中,需要新开一个线程进行连接,用Handler
接收连接状态,更新UI界面。第三是前面所有的操作都是在从Activity中完成的,但是蓝牙连接的操作需要放到主Activity中,所以要实现主Activity与从Activity 的数据传输。先说Activity间的数据传输问题,我用了Android的Application类来传输,代码如下:
BluetoothDevice device = deviceList.get(position);//获取蓝牙设备
adapter.cancelDiscovery();//取消搜索
bridge.setDate(device);//传递数据
MainActivity.back = true;
//返回操作界面
Intent backIntent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(backIntent);
需要说明的是,在连接之前需要取消搜索,就是调用cancelDiscovery()
方法,否则连接会变得异常缓慢。其中的 bridge
继承自Application类,用于传递数据,可以看到,这里是把一个BluetoothDevice
的实例化对象传递了过去。然后在主Activity中接收该对象:
public static boolean back = false;
private BluetoothConnect client;
//onCreate()
if(back){//返回后开始读数据device = bridge.getDate();client = new BluetoothConnect(device,handler);client.connect();//开始连接
}
可以看到,这里蓝牙设备的获取是在从Activity中,而创建连接是在主Activity中。在主Activity中接收到了device
,通过device
就可以创建socket进行连接了,这个过程我封装到一个BluetoothConnect
类中,方便以后调用,下面是其中的connect()
方法:
private BluetoothSocket socket;public void connect(){Thread thread = new Thread(new Runnable() {@Overridepublic void run() {Method method;state = CONNECT_SUCCESS;try {//利用反射机制创建socketmethod = device.getClass().getMethod("createRfcommSocket", new Class[]{int.class});socket = (BluetoothSocket) method.invoke(device, 1);socket.connect(); isConnect = ture;} catch (IOException e) {state = CONNECT_FAILED;Log.e("TAG", e.toString());} catch (InvocationTargetException e) {state = CONNECT_FAILED;Log.e("TAG", e.toString());} catch (NoSuchMethodException e) {state = CONNECT_FAILED;Log.e("TAG", e.toString());} catch (IllegalAccessException e) {state = CONNECT_FAILED;Log.e("TAG", e.toString());}//发送连接状态Message msg = handler.obtainMessage();msg.what = state;handler.sendMessage(msg);}});
thread.start();
}
因为连接过程必须放到子线程中,因此这是一个异步方法,该方法中通过调用createRfcommSocket()
方法创建socket,然后向主Activity中的Handler发送消息,需要用到消息机制,主线程接收消息并更新UI,即在屏幕的中间显示连接状态。接下来代码是主Activity中的Handler,作用是更新UI:
private final Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case BluetoothConnect.CONNECT_FAILED:Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_SHORT).show();break;case BluetoothConnect.CONNECT_SUCCESS:Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show();client.receive();//接收数据break;case BluetoothConnect.READ_FAILED:Toast.makeText(MainActivity.this, "读取失败", Toast.LENGTH_SHORT).show();break;case BluetoothConnect.WRITE_FAILED:Toast.makeText(MainActivity.this, "写入失败", Toast.LENGTH_SHORT).show();break;case BluetoothConnect.DATA:Toast.makeText(MainActivity.this, ""+msg.arg1, Toast.LENGTH_SHORT).show();break;}}
};
可以在此Handler中用TextView等来显示连接状态,这里简单起见就用只用了Toast。可以看到这里有一个receive()
方法,这个方法也是封装到BluetoothConnect
中的一个异步方法,该方法如下:
public void receive(){//连接成功则接收数据Thread thread = new Thread(new Runnable() {@Overridepublic void run() {if(isConnect){try {InputStream inputStream = socket.getInputStream();int data;while (true){try {data = inputStream.read();Message msg = handler.obtainMessage();msg.what = BluetoothConnect.DATA;msg.arg1 = data;handler.sendMessage(msg);}catch (IOException e){Log.e("TAG", e.toString());break;}}} catch (IOException e) {Log.e("TAG", e.toString());}}}});thread.start();
主要是通过不断读取输入流的内容来接收数据,可以看到,这里又利用了消息机制,将接收到的数据通过消息打包发回了主线程,在主线程的Handle中接收消息即可更新UI,显示所接收的内容。
最后不要忘了加上相关的蓝牙权限。
<uses-permission android:name="android.permission.BLUETOOTH"/><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
本文参考来源:http://www.cnblogs.com/wenjiang/p/3200138.html#!comments
Android蓝牙遥控器相关推荐
- Android 蓝牙遥控器的连接
项目是TV端的,产品要求不经过设置界面,开机进入引导页,自动搜索蓝牙遥控器并且建立连接. 刚开始接手的时候以为会很快完成,无非就是调用API吗?可是事实不是这样,前后花了一些时间,才解决. 好了,当时 ...
- android 蓝牙 遥控器,Android 蓝牙遥控器的连接
项目是TV端的,产品要求不经过设置界面,开机进入引导页,自动搜索蓝牙遥控器并且建立连接. 刚开始接手的时候以为会很快完成,无非就是调用API吗?可是事实不是这样,前后花了一些时间,才解决. 好了,当时 ...
- android+蓝牙遥控器,一种通过蓝牙遥控安卓设备的方法与流程
本发明涉及安卓系统遥控领域,具体公开了一种通过蓝牙遥控安卓设备的方法. 背景技术: 随着数字技术的发展,人们使用的数字设备日新月异.现在最为常见的个人设备操作系统是安卓系统.对安卓设备控制的方式,最常 ...
- Android蓝牙遥控器(通过手机蓝牙与蓝牙模块通信)
前些天学弟让我给他整理之前一起做项目时的与下位机通信的部分代码.当时使用蓝牙编程,Android端通过蓝牙发送指令到蓝牙模块,硬件那里通过蓝牙模块读取到指令,并执行相应操作.由于那段代码时在工程里的, ...
- Android 蓝牙遥控器调试记录
1.adb连接机器 adb connect 机器IP:5555 2.shell进入 C:\Users\Administrator>adb shell 3.输入getevent查看按键对应值,以及 ...
- Android 11.0 12.0蓝牙遥控器确认键弹不出输入法的解决方法
1.概述 在android11.0 12.0设备定制化开发时,遥控器是使用红外遥控器,也有使用蓝牙遥控器的,所以出现的问题不一定相同,今天遇到个问题就是蓝牙遥控器在输入数据时弹不出输入法的问题 首选排 ...
- android OS系统如何适配蓝牙遥控器
蓝牙遥控器(简称:遥控器)功能介绍 一. 遥控器组合按键功能 遥控器功能除了熟知的丝印按键功能,还有以下两个组合按键: 1. 触发配对信息组合按键,其作用向板端蓝牙发送配对请求,请求与板端蓝牙配对: ...
- Android系统适配蓝牙遥控器键值Hi3798MV100
最近有个项目机顶盒要适配蓝牙遥控器,我们原来的盒子是红外的遥控器. 从某宝买回来几款通用的遥控器,最简单的一款用cat /proc/bus/input/devices 命令查看name是BESCO K ...
- Android 手机蓝牙遥控器解决方案
驱动力(需求): 女朋友觉得躺床上用ipad看电视剧不爽,对睡姿要求太高,还容易砸到自己,所以提出需求,没辙,搞起来: 现有设备: Rk3288 开发版一个,dell 显示器一个,小音箱一对: 思路: ...
最新文章
- 批量导出表数据到CSV文件
- jQuery中的动画
- linux modprobe 内核模块加载卸载命令 简介
- VMware vSphere 4.1虚拟化学习手册6:Distributed vSwitch分布式交换机
- 本地环境和测试环境搭建
- pyqt5中的lineEdit中只输入数字和字母
- 基于IBM Cognos的高级报表制作技巧
- Cache related website
- 策略模式(headfirst设计模式学习笔记)
- leetcode 动态规划 —— 53(最大子序列的和)
- python大作业五子棋人人对战_五子棋总结(人人对战)
- AndroidDeveloper Weekly No.3
- 我在51CTO微职位学PMP_飘过攻略及心得分享
- 手机微信html整人代码大全,2018年微信整人代码有哪些?2018年微信整人代码大全!...
- LaTeX大括号用法
- Swift游戏实战-跑酷熊猫 03 熊猫跑动动画
- vsphere client下载地址
- 湖南师范大学2021年3月25日蓝桥杯热身赛解题报告与标程
- PMP项目管理的就业前景
- Android移动应用技术打地鼠小游戏(简单App实现)——学习成果