android 蓝牙通讯测试工具,Android Bluetooth 学习(2)应用层实现蓝牙设备查找、tcp_ip通信...
Bluetooth结构
1、JAVA层frameworks/base/core/java/android/bluetooth/
包含了bluetooth的JAVA类。
2、JNI层
frameworks/base/core/jni/android_bluetooth_开头的文件
定义了bluez通过JNI到上层的接口。
frameworks/base/core/jni/android_server_bluetoothservice.cpp
调用硬件适配层的接口system/bluetooth/bluedroid/bluetooth.c
3、bluez库
external/bluez/
这是bluez用户空间的库,开源的bluetooth代码,包括很多协议,生成libbluetooth.so。
4、硬件适配层
system/bluetooth/bluedroid/bluetooth.c
包含了对硬件操作的接口
system/bluetooth/data/*
一些配置文件,复制到/etc/bluetooth/。
还有其他一些测试代码和工具。
一、简略介绍Bluetooth开发使用到的类
1、BluetoothAdapter,蓝牙适配器,可判断蓝牙设备是否可用等功能。
常用方法列举如下:
cancelDiscovery() ,取消搜索过程,在进行蓝牙设备搜索时,如果调用该方法会停止搜索。(搜索过程会持续12秒)
disable()关闭蓝牙,也就是我们常说的禁用蓝牙。
enable()打开蓝牙,这个方法打开蓝牙但不会弹出提示,正常流程操作下,我们会让系统提示用户是否打开蓝牙设备。如下两行代码可轻松搞定。
Intent enabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler,reCode);//同startActivity(enabler);(在主Activity启动一个二级Activity,reCode一般等于3,一定记得要在AndroidManifest.xml里面添加蓝牙权限)
getAddress()获取本地蓝牙地址
getDefaultAdapter()获取默认BluetoothAdapter,实际上,也只有这一种方法获取BluetoothAdapter
getName()获取本地蓝牙名称
getRemoteDevice(String address)根据蓝牙地址获取远程蓝牙设备
getState()获取本地蓝牙适配器当前状态(感觉可能调试的时候更需要)
isDiscovering()判断当前是否正在查找设备,是返回true
isEnabled()判断蓝牙是否打开,已打开返回true,否则,返回false
listenUsingRfcommWithServiceRecord(String name,UUID uuid)根据名称,UUID创建并返回
BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步
startDiscovery()开始搜索,这是搜索的第一步
2.BluetoothDevice看名字就知道,这个类描述了一个蓝牙设备
createRfcommSocketToServiceRecord(UUIDuuid)根据UUID创建并返回一个BluetoothSocket
这个方法也是我们获取BluetoothDevice的目的——创建BluetoothSocket
这个类其他的方法,如getAddress(),getName(),同BluetoothAdapter
这个类有几个隐藏方法,涉及到蓝牙的自动配对,setPin,createBond,cancelPairingUserInput,等方法(需要通过java的反射,调用这几个隐藏方法)
3.BluetoothServerSocket如果去除了Bluetooth相信大家一定再熟悉不过了,既然是Socket,方法就应该都差不多,
这个类一种只有三个方法
两个重载的accept(),accept(inttimeout)两者的区别在于后面的方法指定了过时时间,需要注意的是,执行这两个方法的时候,直到接收到了客户端的请求(或是过期之后),都会阻塞线程,应该放在新线程里运行!
还有一点需要注意的是,这两个方法都返回一个BluetoothSocket,最后的连接也是服务器端与客户端的两个BluetoothSocket的连接
close()关闭!
4.BluetoothSocket,跟BluetoothServerSocket相对,是客户端
一共5个方法,不出意外,都会用到
close(),关闭
connect()连接
getInptuStream()获取输入流
getOutputStream()获取输出流
getRemoteDevice()获取远程设备,这里指的是获取bluetoothSocket指定连接的那个远程蓝牙设备
二、蓝牙设备的发现、查找。
1.基于安全性考虑,设置开启可被搜索后,Android系统会默认给出120秒的时间,其他设备能在这120秒内搜索到它。
Intent enable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(enalbe,REQUEST_DISCOVERABLE);
2.搜索蓝牙设备
BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter();
_bluetooth.startDiscovery();
3.关闭蓝牙设备
BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter();
_bluetooth.disable();
4.创建蓝牙客户端
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(UUID.fromString(UUID号));
socket.connect();
4.创建蓝牙服务端
BluetoothServerSocket _serverSocket = _bluetooth.listenUsingRfcommWithServiceRecord(服务端名称,UUID.fromeString(UUID号));
BluetoothSocket socket = _serverSocket.accept();
InputStream inputStream = socket.getInputStream();
三、相关代码实现注:tcp_ip模块需要在系统setting模块中,完成蓝牙的配对,只有配对成功的,才能进行socket通信(具体如何配对和如何自动配对,将在bluetoot3或者4中进行讲解)
AndridManifest.xml
package="com.example.thecaseforbluetooth"
android:versionCode="1"
android:versionName="1.0" >
android:minSdkVersion="8"
android:targetSdkVersion="15" />
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
android:name=".BluetoothActivity"
android:label="@string/title_activity_bluetooth" >
main.xml
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnSearch"
android:text="查找设备"
/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnExit"
android:text="退出应用"
/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnDis"
android:text="设置可被发现"
/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btnserver"
android:text="启动服务端"
/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/tbtnSwitch"
android:text="开/关 蓝牙设备"
/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/lvDevices"
/>
BluetoothActivity.java
package com.example.thecaseforbluetooth;
import java.util.ArrayList;
import java.util.Set;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.ToggleButton;
public class BluetoothActivity extends Activity {
public Button searchBtn;//搜索蓝牙设备
public Button exitBtn;//退出应用
public Button discoverBtn;//设置可被发现
public ToggleButton openBtn;//开关蓝牙设备
public Button serverbtn;
public ListView listView;//蓝牙设备清单
public ArrayAdapter adapter;
public ArrayList list =new ArrayList();
private BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set bondDevices ;
public Context context ;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
searchBtn = (Button)findViewById(R.id.btnSearch);
exitBtn = (Button)findViewById(R.id.btnExit);
discoverBtn = (Button)findViewById(R.id.btnDis);
openBtn = (ToggleButton)findViewById(R.id.tbtnSwitch);
serverbtn = (Button)findViewById(R.id.btnserver);
listView = (ListView)findViewById(R.id.lvDevices);
context = getApplicationContext();
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,list);
listView.setAdapter(adapter);
openBtn.setChecked(false);
//注册广播接收信号
IntentFilter intent = new IntentFilter();
intent.addAction(BluetoothDevice.ACTION_FOUND);// 用BroadcastReceiver来取得搜索结果
intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); //每当扫描模式变化的时候,应用程序可以为通过ACTION_SCAN_MODE_CHANGED值来监听全局的消息通知。比如,当设备停止被搜寻以后,该消息可以被系统通知給应用程序。
intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); //每当蓝牙模块被打开或者关闭,应用程序可以为通过ACTION_STATE_CHANGED值来监听全局的消息通知。
registerReceiver(searchReceiver, intent);
//显示已配对设备以及搜索未配对设备
searchBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(bluetoothAdapter.isDiscovering()){
bluetoothAdapter.cancelDiscovery();
}
list.clear();
bondDevices = bluetoothAdapter.getBondedDevices();
for(BluetoothDevice device : bondDevices) {
String str = "已配对完成" + device.getName() +""
+ device.getAddress();
list.add(str);
adapter.notifyDataSetChanged();
}
bluetoothAdapter.startDiscovery();
}
});
//退出应用
exitBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
BluetoothActivity.this.finish();
}
});
//设置蓝牙设备可发现
discoverBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent discoverIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverIntent);
}
});
//开关蓝牙设备
openBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(openBtn.isChecked() == true){
bluetoothAdapter.disable();
}
else if(openBtn.isChecked() == false){
bluetoothAdapter.enable();
}
}
});
//作为服务端开启
serverbtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
ServerThread serverThread = new ServerThread(bluetoothAdapter, context);
Toast.makeText(context, "server 端启动", 5000).show();
serverThread.start();
}
});
listView.setOnItemClickListener(new ItemClickListener());
}
@Override
public void onStart() {
super.onStart();
// If BT is not on, request that it be enabled.
if(bluetoothAdapter == null){
Toast.makeText(context, "蓝牙设备不可用", 5000).show();
}
if (!bluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, 3);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private final BroadcastReceiver searchReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
BluetoothDevice device = null;
if(BluetoothDevice.ACTION_FOUND.equals(action)){
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() == BluetoothDevice.BOND_NONE) {
Toast.makeText(context, device.getName()+"", 5000).show();
String str = "未配对完成" + device.getName() +""
+ device.getAddress();
if (list.indexOf(str) == -1)// 防止重复添加
list.add(str);
}
adapter.notifyDataSetChanged();
}
}
};
public class ItemClickListener implements OnItemClickListener {
@Override
public void onItemClick(AdapterView> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
if(bluetoothAdapter.isDiscovering())
bluetoothAdapter.cancelDiscovery();
String str = list.get(arg2);
String address = str.substring(str.length() - 17);
BluetoothDevice btDev = bluetoothAdapter.getRemoteDevice(address);
ClientThread clientThread = new ClientThread(btDev, context);
clientThread.start();
}}
} Bluetoothprotocol.java
package com.example.thecaseforbluetooth;
public interface Bluetoothprotocol {
public static final String PROTOCOL_SCHEME_L2CAP = "btl2cap";
public static final String PROTOCOL_SCHEME_RFCOMM = "btspp";
public static final String PROTOCOL_SCHEME_BT_OBEX = "btgoep";
public static final String PROTOCOL_SCHEME_TCP_OBEX = "tcpobex";
} ServerThread.java
package com.example.thecaseforbluetooth;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;
public class ServerThread extends Thread {
public BluetoothServerSocket mserverSocket;
public BluetoothAdapter bluetoothAdapter;
public BluetoothSocket socket;
public Context context;
public ServerThread(BluetoothAdapter bluetoothAdapter,Context context) {
this.bluetoothAdapter = bluetoothAdapter;
this.context = context;
}
public void run() {
try {
/* 创建一个蓝牙服务器
* 参数分别:服务器名称、UUID */
mserverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(Bluetoothprotocol.PROTOCOL_SCHEME_RFCOMM,
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
///* 接受客户端的连接请求 */
socket = mserverSocket.accept();
//下面代码作者偷懒,读写另外起一个线程最好
//接收数据
byte[] buffer = new byte[1024];
int bytes;
InputStream mmInStream = null;
try {
mmInStream = socket.getInputStream();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("zhoulc server");
while(true){
if( (bytes = mmInStream.read(buffer)) > 0 )
{
byte[] buf_data = new byte[bytes];
for(int i=0; i
{
buf_data[i] = buffer[i];
}
String s = new String(buf_data);
System.out.println(s+"zhoulc server is in");
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} ClientThread.java
package com.example.thecaseforbluetooth;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.widget.Toast;
public class ClientThread extends Thread {
public BluetoothSocket socket;
public BluetoothDevice device;
public Context context;
public ClientThread(BluetoothDevice device,Context context){
this.device = device;
this.context = context;
}
public void run() {
try {
//创建一个Socket连接:只需要服务器在注册时的UUID号
socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
//连接
socket.connect();
//下面代码作者偷懒,读写另外起一个线程最好
//发送数据
if (socket == null)
{
Toast.makeText(context, "链接失败", 5000).show();
return;
}
System.out.println("zhoulc client");
while(true){
try {
System.out.println("zhoulc client is in");
String msg = "hello everybody I am client";
OutputStream os = socket.getOutputStream();
os.write(msg.getBytes());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
android 蓝牙通讯测试工具,Android Bluetooth 学习(2)应用层实现蓝牙设备查找、tcp_ip通信...相关推荐
- android服务器压力测试工具,Android自动化压力测试图解教程——Monkey工具
有时候我们需要对一个软件进行压力测试,检查该软件的性能.如果是人工进行测试的话,效率会低很多,而且会比较枯燥.这时,中的一个命令行工具Monkey就可以为我们减轻很多重复而又繁琐的工作. 一.Monk ...
- android手机版tcp或者udp通讯测试工具,可以用于工业设备或者系统开发时间测试tcp或是udp连接通讯是否正常工作
TUtool 介绍 由于工作需要一款安卓的tcp udp测试工具,而市场里没有或者不好用,或者都是广告,现在个人开发者又不让发布应用了,小巧好用不收集用户信息的不收费没有广告的小工具只能自己用,哈哈. ...
- android 测试 大赛,轻量级android应用自动测试工具-2017全国大学生软件测试大赛.pdf...
轻量级android应用自动测试工具-2017全国大学生软件测试大赛 DroidBot: A Lightweight Android App Testing Bot 轻量级Android应用自动测试工 ...
- Android 开源安全测试工具 Drozer,安装过程中的问题
Android 开源安全测试工具 Drozer,安装过程中的问题 记录安装过程中出现的问题 Android 开源安全测试工具 Drozer,安装过程中的问题 错误一 错误二 错误三 错误四 错误五 错 ...
- Android内存压力测试工具(memtester移植)
该文章转载于: android用memtester内存压力测试_W歹匕示申W的博客-CSDN博客 Android内存压力测试工具(memtester移植)_甜牛奶蛋糕的博客-CSDN博客_androi ...
- android启动界面修改工具,Android 系统界面调节工具使用及功能
Android 系统界面调节工具(Android System UI Tuner)是个隐藏功能,里面有一些实验性功能,可以辅助平时开发. 1. 打开 系统界面调节工具是个隐藏功能,打开他说简单也简单, ...
- 智能水表自动抄表协议cjt188远传协议,支持地址自动分配检查,灵活好用、Mbus通讯测试工具是一款水表等设备的测试工具
智能水表自动抄表协议cjt188远传协议,支持地址自动分配检查,灵活好用.Mbus通讯测试工具是一款水表等设备的测试工具,真实有效可靠,可读取写入表计地址,发送标准188读计量数据.控制码等命令,可设 ...
- 通讯测试工具和博图仿真机的连接教程
一.软件准备 1.博图v15,TIA_Portal_STEP_7_Pro_WINCC_Pro_V15: 2.博图仿真机,SIMATIC_S7PLCSIM_V15: 3.西门子密钥激活,Sim_EKB ...
- android 蓝牙通讯编程 备忘
1.启动App后: 判断->蓝牙是否打开(所有功能必须在打牙打开的情况下才能用) 已打开: 启动代码中的蓝牙通讯Service 未打开: 发布 打开蓝牙意图(系统),根据Activity返回进场 ...
- Android 开发、测试工具资源汇总
Android Tools Android SDK在线更新镜像服务器 中国科学院开源协会镜像站地址: IPV4/IPV6: http://mirrors.opencas.cn 端口:80 IPV4/I ...
最新文章
- animate默认时长所带来的问题及解决
- Leangoo产品白皮书
- Java synchronized 中的 while 和 notifyAll
- python 函数参数前面两个星号_Python中参数前面一个星号两个星号(*参数,**参数)起什么作用呢?...
- vector动态数组
- Vue.js学习系列(二十八)-- 计算属性(二)
- C++之函数指针实现函数回调
- torch版ResNet50(带有多输出)转c++ tensorrt
- 【Java】Date类和Calendar类必知必会
- 【WebGIS bug】WARNING: Too many active WebGL contexts. Oldest context will be lost.
- webUploader.js 文件上传插件简用!
- 北京市朝阳区 办理 驾驶证期满换证 自助体检 的流程
- 【7gyy】让Win7系统下的硬盘不在狂闪的诀窍
- 生死看淡,不服就GAN(五)----用DCGAN生成MNIST手写体
- 【Flink】需求实现之独立访客数量的计算 和 布隆过滤器的原理及使用
- 数据库DDL数据定义语言
- 支付宝重启免费时代, 让天下没有难做的生意!
- 华为云·云享专家李万龙: IoT 梦想,从0到1的实现
- 免费ARP(Gratuitousnbsp;ARP)简析
- 装箱和拆箱分别什么意思?