初涉android的蓝牙 *** 作,按照固定MAC地址连接获取Device时,程序始终是异常终止,查了好多天代码都没查出原因。今天改了一下API版本,突然就成功连接了。总结之后发现果然是个坑爹之极的错误。
为了这种错误拼命查原因浪费大把时间是非常不值得的,但是问题不解决更是揪心。可惜我百度了那么多,都没有给出确切原因。今天特此mark,希望后来者遇到这个问题的时候能轻松解决。
下面是我的连接过程,中间崩溃原因及解决办法。
1:用AT指令获得蓝牙串口的MAC地址,地址是简写的,按照常理猜测可得标准格式。
2:开一个String adress= "" //MAC地址, String MY_UUID= ""//UUID根据通信而定,网上都有。
3:取得本地Adapter用getDefaultAdapter(); 远程的则用getRemoteDevice(adress); 之后便可用UUID开socket进行通信。
如果中途各种在getRemoteDevice处崩溃,大家可以查看一下当前的API版本,如果是21或以下版本的话,便能确定是API版本问题,只要换成22或者以上就都可以正常运行了~ 这么坑爹的错误的确很为难初学者。 唉·········· 为这种小trick浪费很多时间真是难过。
(另外有个重要地方,别忘了给manifest里面加以下两个蓝牙 *** 作权限哦~)
<uses-permission android:name="androidpermissionBLUETOOTH"></uses-permission>
<uses-permission android:name="androidpermissionBLUETOOTH_ADMIN"></uses-permission>
下面附上Android蓝牙 *** 作中用固定MAC地址传输信息的模板,通用搜索模式日后再补删模板:
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private InputStream inStream = null;
private static final UUID MY_UUID = UUIDfromString("00001101-0000-1000-8000-00805F9B34FB"); //这条是蓝牙串口通用的UUID,不要更改
private static String address = "00:12:02:22:06:61"; // <==要连接的蓝牙设备MAC地址
/获得通信线路过程/
/1:获取本地BlueToothAdapter/
mBluetoothAdapter = BluetoothAdaptergetDefaultAdapter();
if(mBluetoothAdapter == null)
{
ToastmakeText(this, "Bluetooth is not available", ToastLENGTH_LONG)show();
finish();
return;
}
if(!mBluetoothAdapterisEnabled())
{
ToastmakeText(this, "Please enable your Bluetooth and re-run this program", ToastLENGTH_LONG)show();
finish();
return;
}
/2:获取远程BlueToothDevice/
BluetoothDevice device = mBluetoothAdaptergetRemoteDevice(address);
if(mBluetoothAdapter == null)
{
ToastmakeText(this, "Can't get remote device", ToastLENGTH_LONG)show();
finish();
return;
}
/3:获得Socket/
try {
btSocket = devicecreateRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Loge(TAG, "ON RESUME: Socket creation failed", e);
}
/4:取消discovered节省资源/
mBluetoothAdaptercancelDiscovery();
/5:连接/
try {
btSocketconnect();
Loge(TAG, "ON RESUME: BT connection established, data transfer link open");
} catch (IOException e) {
try {
btSocketclose();
} catch (IOException e2) {
Log e(TAG,"ON RESUME: Unable to close socket during connection failure", e2);
}
}
/此时可以通信了,放在任意函数中/
/ try {
outStream = btSocketgetOutputStream();
inStream = btSocketgetInputStream(); //可在TextView里显示
} catch (IOException e) {
Loge(TAG, "ON RESUME: Output stream creation failed", e);
}
String message = "1";
byte[] msgBuffer = messagegetBytes();
try {
outStreamwrite(msgBuffer);
} catch (IOException e) {
Loge(TAG, "ON RESUME: Exception during write", e);
}
/
通用搜索模式代码模板:
简洁简洁方式1 demo
作用: 用VerticalSeekBar控制一个 LED屏幕的亮暗。
直接上码咯~
package comexampleseed2;
import androidappActivity;
import androidappAlertDialog;
import androidappDialog;
import androidosBundle;
import javaioIOException;
import javaioInputStream;
import javaioOutputStream;
import javautilUUID;
import androidbluetoothBluetoothAdapter;
import androidbluetoothBluetoothDevice;
import androidbluetoothBluetoothSocket;
import androidcontentDialogInterface;
import androidutilLog;
import androidviewKeyEvent;
import androidwidgetToast;
public class MetalSeed extends Activity {
private static final String TAG = "BluetoothTest";
private BluetoothAdapter mBluetoothAdapter = null;
private BluetoothSocket btSocket = null;
private OutputStream outStream = null;
private InputStream inStream = null;
private VerticalSeekBar vskb = null;
private static final UUID MY_UUID = UUIDfromString("00001101-0000-1000-8000-00805F9B34FB"); //这条是蓝牙串口通用的UUID,不要更改
private static String address = "00:12:02:22:06:61"; // <==要连接的蓝牙设备MAC地址
/ Called when the activity is first created /
@Override
public void onCreate(Bundle savedInstanceState) {
superonCreate(savedInstanceState);
setContentView(Rlayoutmain);
thisvskb = (VerticalSeekBar)superfindViewById(Ridmskb);
thisvskbsetOnSeekBarChangeListener(new OnSeekBarChangeListenerX());
mBluetoothAdapter = BluetoothAdaptergetDefaultAdapter();
if(mBluetoothAdapter == null)
{
ToastmakeText(this, "Bluetooth is not available", ToastLENGTH_LONG)show();
finish();
return;
}
if(!mBluetoothAdapterisEnabled())
{
ToastmakeText(this, "Please enable your Bluetooth and re-run this program", ToastLENGTH_LONG)show();
finish();
return;
}
}
private class OnSeekBarChangeListenerX implements VerticalSeekBarOnSeekBarChangeListener {
public void onProgressChanged(VerticalSeekBar seekBar, int progress, boolean fromUser) {
//MainthiscluesetText(seekBargetProgress());
/ String message;
byte [] msgBuffer;
try {
outStream = btSocketgetOutputStream();
} catch (IOException e) {
Loge(TAG,"ON RESUME : Output Stream creation failed", e);
}
message =IntegertoString( seekBargetProgress() );
msgBuffer = messagegetBytes();
try{
outStreamwrite(msgBuffer);
} catch (IOException e) {
Loge (TAG, "ON RESUME : Exception during write", e);
} /
}
public void onStartTrackingTouch(VerticalSeekBar seekBar) {
String message;
byte [] msgBuffer;
try {
outStream = btSocketgetOutputStream();
} catch (IOException e) {
Loge(TAG,"ON RESUME : Output Stream creation failed", e);
}
message =IntegertoString( seekBargetProgress() );
msgBuffer = messagegetBytes();
try{
outStreamwrite(msgBuffer);
} catch (IOException e) {
Loge (TAG, "ON RESUME : Exception during write", e);
}
}
public void onStopTrackingTouch(VerticalSeekBar seekBar) {
String message;
byte [] msgBuffer;
try {
outStream = btSocketgetOutputStream();
} catch (IOException e) {
Loge(TAG,"ON RESUME : Output Stream creation failed", e);
}
message =IntegertoString( seekBargetProgress() );
msgBuffer = messagegetBytes();
try{
outStreamwrite(msgBuffer);
} catch (IOException e) {
Loge (TAG, "ON RESUME : Exception during write", e);
}
}
}
@Override
public void onStart()
{
superonStart();
}
@Override
public void onResume()
{
superonResume();
BluetoothDevice device = mBluetoothAdaptergetRemoteDevice(address);
try {
btSocket = devicecreateRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Loge(TAG, "ON RESUME: Socket creation failed", e);
}
mBluetoothAdaptercancelDiscovery();
try {
btSocketconnect();
Loge(TAG, "ON RESUME: BT connection established, data transfer link open");
} catch (IOException e) {
try {
btSocketclose();
} catch (IOException e2) {
Log e(TAG,"ON RESUME: Unable to close socket during connection failure", e2);
}
}
// Create a data stream so we can talk to server
/ try {
outStream = btSocketgetOutputStream();
inStream = btSocketgetInputStream();
} catch (IOException e) {
Loge(TAG, "ON RESUME: Output stream creation failed", e);
}
String message = "read";
byte[] msgBuffer = messagegetBytes();
try {
outStreamwrite(msgBuffer);
} catch (IOException e) {
Loge(TAG, "ON RESUME: Exception during write", e);
}
int ret = -1;
while( ret != -1)
{
try {
ret = inStreamread();
} catch (IOException e)
{
eprintStackTrace();
}
}
/
}
@Override
普通蓝牙设备官方文档
Android 平台包含蓝牙网络堆栈支持 ,凭借此支持,设备能以无线方式与其他蓝牙设备交换数据。应用框架提供了通过 Android Bluetooth API 访问蓝牙功能的途径。使用 Bluetooth API Android 应用可以执行下面的 *** 作:
传统蓝牙适用于电池使用强度较大的 *** 作,例如 Android 设备之间的流传输和通信等。针对具有低功耗要求的蓝牙设备,Android 43(API 18)中引入了面向低功耗蓝牙的 API 支持。
使用 Android Bluetooth API 来完成使用蓝牙进行通信的四项主要任务: 设置蓝牙 、 查找局部区域内的配对设备或可用设备 、 连接设备 ,以及在 设备之间传输数据 。
关于蓝牙的 API 在 androidbluetooth 包中,下面介绍一下和蓝牙相关的主要类:
在 BluetoothProfile IPC 客户端连接到服务(即,运行特定配置文件的内部服务)或断开服务连接时向其发送通知的接口。
使用蓝牙必须声明权限 BLUETOOTH 才可以执行蓝牙通信。
1、获取蓝牙适配器
例如:我们可以查询所有已配对的设备,然后使用 ArrayAdapter 向用户显示每台设备的名称:
要发起连接仅需要知道目标蓝牙设备的 Mac 地址就可以了。
注意 执行 discovery 对于蓝牙适配器来说是一个非常繁重的过程,并且会消耗大量资源。在找到要连接的设备后, 要确保使用 cancelDiscovery() 来停止发现,然后尝试连接 。如果您已经和某台设备进行连接,那么这个时候执行发现 *** 作会大幅度的减少此连接可用的带宽!因此不应该在处于连接状态的时候执行发现 *** 作!
例如:
在连接之前如果两个设备没有配对,则系统会自动发出配对请求。
服务器套接字接受连接的基本过程
放在子线程中去执行。
例子:
客户端连接的基本过程
调用 connect() 的时候要确保客户端没有执行发现 *** 作。如果执行了会大幅度降低连接的速度,增加失败的可能。
例子
在连接之前调用 cancleDiscovery() 在进行连接之前应该始终调用这个方法,而且调用的时候无需检测是否正在扫描。
过程:
从 Android 30 开始, Bluetooth API 便支持使用蓝牙配置文件。蓝牙配置文件是适用于设备间蓝牙通信的无线接口规范。
1、蓝牙配置文件就是设备间通信(蓝牙设备)的一种规范
免提配置文件便是一个示例,对于连接到无线耳机的手机,两台设备都必须支持免提配置文件。我们也可以通过实现接口 BluetoothProfile 来写入自己的类来支持特定的蓝牙配置文件。Android API 提供了以下的几种蓝牙配置文件的实现:
2、使用配置文件的基本步骤
创建 HDP 应用:
关于普通蓝牙设备和普通蓝牙设备之间的连接通信
关于蓝牙设备和蓝牙仪器(蓝牙耳机、电子秤等等类似产品)
这种之间的通信是通过配置文件代理来实现的。
都有一个对应的配置文件代理类。具体的 *** 作是通过这个对象来完成。
参考: >
/
获取设备的mac地址
@param ac
@param callback
成功获取到mac地址之后会回调此方法
/
public static void getMacAddress(final Activity ac, final SimpleCallback callback) {
final WifiManager wm = (WifiManager) ac getSystemService(ServiceWIFI_SERVICE);
// 如果本次开机后打开过WIFI,则能够直接获取到mac信息。立刻返回数据。
WifiInfo info = wmgetConnectionInfo();
if (info != null && infogetMacAddress() != null) {
if (callback != null) {
callbackonComplete(infogetMacAddress());
}
return;
}
// 尝试打开WIFI,并获取mac地址
if (!wmisWifiEnabled()) {
wmsetWifiEnabled(true);
}
new Thread(new Runnable() {
@Override
public void run() {
int tryCount = 0;
final int MAX_COUNT = 10;
while (tryCount < MAX_COUNT) {
final WifiInfo info = wmgetConnectionInfo();
if (info != null && infogetMacAddress() != null) {
if (callback != null) {
acrunOnUiThread(new Runnable() {
@Override
public void run() {
callbackonComplete(infogetMacAddress());
}
});
}
return;
}
SystemClocksleep(300);
tryCount++;
}
// 未获取到mac地址
if (callback != null) {
callbackonComplete(null);
}
}
})start();
}
获取mac地址的话,可以在命令行窗口获取,代码如下:
Android 底层是 Linux,我们还是用Linux的方法来获取:
1 cpu号:
文件在: /proc/cpuinfo
通过Adb shell 查看:
adb shell cat /proc/cpuinfo
2 mac 地址
文件路径 /sys/class/net/wlan0/address
adb shell cat /sys/class/net/wlan0/address
xx:xx:xx:xx:xx:aa
具体的实现代码为:
public static String getLocalMac() {
String mac=null;
String str = "";
try
{
Process pp = RuntimegetRuntime()exec("cat /sys/class/net/wlan0/address ");
InputStreamReader ir = new InputStreamReader(ppgetInputStream());
LineNumberReader input = new LineNumberReader(ir);
for (; null != str;)
{
str = inputreadLine();
if (str != null)
{
mac = strtrim();// 去空格
break;
}
}
} catch (IOException ex) {
// 赋予默认值
exprintStackTrace();
}
return mac;
}
以上就是关于android_studio手机蓝牙串口通信源代码全部的内容,包括:android_studio手机蓝牙串口通信源代码、Android 蓝牙开发(一)、android开发怎么用脚本获取手机的mac地址等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)