Android手机蓝牙互联,并传递数据。
今晚整理下,实验室没开门,只好在一教将就一下了
关于蓝牙,看了好些天,但是看完后想想也没啥,都是谷歌做好了的东西,我们只要用用API就ok了,哎。
首先,如果是互相传递数据的,两部android设备各自都必须充当两种角色。
1、服务端 2、客户端。
其实也不难理解,毕竟通信是两者之间建立的,而且必须实现收发并用。所以理所当然了,客户端发送消息给服务端。
两部设备是通过使用相同的UUID建立起一个Rfcomm什么的通道,这个通道连接两台设备以供数据的传递。
当然要如何建立呢?(我也不知道)
我们先分析客户端,他是通过Socket的一个主动连接函数connect()来请求服务端的连接(服务端接收到请求..才会有数据传递 后面再说),那么这个socket是怎样来的呢?
是通过device.createRfcommSocketToServiceRecord(UUID);来的,这个device是由你相连服务端的地址得到的,通过蓝牙适配器mBluetoothAdapter.getRemoteDevice(address);来的。address又是怎么来的呢? 是通过扫描附近蓝牙,被广播接收器接收到的。
好的整理一下,就是通过广播接收器扫描到附近的蓝牙设备(当然机智的你肯定准备好了两台设备) 然后能通过扫描到的设备得到他们的地址。通过这个地址就能实例化出device
然后Socket也就出来了。最后通过Socket.getOutputStream() 得到输出流,想输出流内写入数据 即可完成客户端的任务。
//以下是客户端负责发送消息的代码(布局和manifest文件自己添加以下,很简单)
package com.example.single_bt1;import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;public class AsClient extends Activity implements OnItemClickListener {private static final String TAG = "MainActivity";// 本地蓝牙适配器private BluetoothAdapter mBluetoothAdapter;// 列表private ListView lvDevices;// 存储搜索到的蓝牙private List<String> bluetoothDevices = new ArrayList<String>();// listview的adapterprivate ArrayAdapter<String> arrayAdapter;// UUID.randomUUID()随机获取UUIDprivate final UUID MY_UUID = UUID.fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3");// 连接对象的名称private final String NAME = "LGL";// 这里本身即是服务端也是客户端,需要如下类private BluetoothSocket clientSocket;private BluetoothDevice device;// 输出流_客户端需要往服务端输出private OutputStream os;private EditText et;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView() {// 获取本地蓝牙适配器mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();// 判断手机是否支持蓝牙if (mBluetoothAdapter == null) {Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();finish();}// 判断是否打开蓝牙if (!mBluetoothAdapter.isEnabled()) {// 弹出对话框提示用户是后打开Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(intent, 1);// 不做提示,强行打开
// mBluetoothAdapter.enable();}et = (EditText) findViewById(R.id.edit_input2);// 初始化listviewlvDevices = (ListView) findViewById(R.id.lvDevices);lvDevices.setOnItemClickListener(this);// 获取已经配对的设备Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();// 判断是否有配对过的设备if (pairedDevices.size() > 0) {for (BluetoothDevice device : pairedDevices) {// 遍历到列表中bluetoothDevices.add("已配对\n" + device.getName() + ":"+ device.getAddress());}}// adapterarrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, android.R.id.text1,bluetoothDevices);lvDevices.setAdapter(arrayAdapter);//启动服务/*** 异步搜索蓝牙设备——广播接收*/// 找到设备的广播IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);// 注册广播registerReceiver(receiver, filter);// 搜索完成的广播filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);// 注册广播registerReceiver(receiver, filter);}@Overrideprotected void onDestroy() {super.onDestroy();unregisterReceiver(receiver);}// 广播接收器private final BroadcastReceiver receiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {// 收到的广播类型String action = intent.getAction();// 发现设备的广播if (BluetoothDevice.ACTION_FOUND.equals(action)) {// 从intent中获取设备BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);// 判断是否配对过if (device.getBondState() != BluetoothDevice.BOND_BONDED) {// 添加到列表bluetoothDevices.add("未配对\n" + device.getName() + ":"+ device.getAddress());arrayAdapter.notifyDataSetChanged();}// 搜索完成} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {// 关闭进度条setProgressBarIndeterminateVisibility(true);setTitle("搜索完成!");}}};// 客户端@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {// 先获得蓝牙的地址和设备名String s = arrayAdapter.getItem(position);// 单独解析地址String address = s.substring(s.indexOf(":") + 1).trim();// 主动连接蓝牙try {// 判断是否在搜索,如果在搜索,就取消搜索if (mBluetoothAdapter.isDiscovering()) {mBluetoothAdapter.cancelDiscovery();}try {// 获得远程设备device = mBluetoothAdapter.getRemoteDevice(address);Log.e(TAG, "device:" + device);clientSocket = device.createRfcommSocketToServiceRecord(MY_UUID);// 连接clientSocket.connect();// 获得输出流os = clientSocket.getOutputStream();// 判断是否可以获得if (device == null) {// 获得远程设备device = mBluetoothAdapter.getRemoteDevice(address);Log.e(TAG, "device:" + device);}// 开始连接if (clientSocket == null) {clientSocket = device.createRfcommSocketToServiceRecord(MY_UUID);// 连接clientSocket.connect();// 获得输出流os = clientSocket.getOutputStream();}} catch (Exception e) {}// 如果成功获得输出流if (os != null) {
// os.write("Hello Bluetooth!".getBytes());os.write(et.getText().toString().getBytes("GBK"));Log.e(TAG, "write");et.setText("");}} catch (Exception e) {}}}
接下来就是服务端了,服务端相比来说就稍微省事一点了,坐在那里等人来请求,所以他要一直在那里等,言下之意就是一个耗时操作,所以放在一个新的线程中是自然的事情。通过ServerScoket的accept()会产生一个socket负责与客户端的socket通信, 那么这个serversocket哪来的呢,直接上代码吧:
serverSocket = mBluetoothAdapter .listenUsingRfcommWithServiceRecord(NAME, MY_UUID); name是自己定义的,随便写就好(String类型)
然后就是通过serverSocket.getInputStream() 得到输入流,就能读出数据了。
package com.example.single_bt2_server;import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;public class MainActivity extends Activity {private static final String TAG = "MainActivity";// 本地蓝牙适配器private BluetoothAdapter mBluetoothAdapter;// UUID.randomUUID()随机获取UUIDprivate final UUID MY_UUID = UUID.fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3");// 连接对象的名称private final String NAME = "LGL";//线程类的实例private AcceptThread ac;// private EditText edit_Get;private ListView list_Get;private List<String> content = new ArrayList<String>();private ArrayAdapter<String> adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.received);
// edit_Get = (EditText) findViewById(R.id.edit_get);initView();}private void initView() {list_Get = (ListView) findViewById(R.id.list_get);adapter = new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,content);list_Get.setAdapter(adapter);// 获取本地蓝牙适配器mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();// 判断手机是否支持蓝牙if (mBluetoothAdapter == null) {Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();finish();}// 判断是否打开蓝牙if (!mBluetoothAdapter.isEnabled()) {// 弹出对话框提示用户是后打开Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivityForResult(intent, 1);// 不做提示,强行打开
// mBluetoothAdapter.enable();}ac = new AcceptThread();ac.start();}// 服务端,需要监听客户端的线程类private Handler handler = new Handler() {public void handleMessage(Message msg) {Toast.makeText(MainActivity.this, String.valueOf(msg.obj),Toast.LENGTH_SHORT).show();String result = String.valueOf(msg.obj);
// edit_Get.setText(String.valueOf(msg.obj));content.add(result);adapter.notifyDataSetChanged();Log.e(TAG, msg.obj + ":服务端");super.handleMessage(msg);}};// 线程服务类private class AcceptThread extends Thread {private BluetoothServerSocket serverSocket;private BluetoothSocket socket;// 输入 输出流private OutputStream os;private InputStream is;public AcceptThread() {try {serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}@Overridepublic void run() {// 截获客户端的蓝牙消息try {socket = serverSocket.accept(); // 如果阻塞了,就会一直停留在这里is = socket.getInputStream();os = socket.getOutputStream();while (true) {synchronized (MainActivity.this) {byte[] tt = new byte[is.available()];if (tt.length > 0) {is.read(tt, 0, tt.length);Message msg = new Message();msg.obj = new String(tt, "GBK");Log.e(TAG, msg.obj + ":客户端");handler.sendMessage(msg);}}}} catch (Exception e) {e.printStackTrace();Log.e(TAG, e.getMessage());}}}}
至于两者都有的角色 让我放到文件中吧,是网上参考
Android手机蓝牙互联,并传递数据。相关推荐
- Android 手机蓝牙 (普通蓝牙篇)
Android 手机蓝牙一 (普通蓝牙) hello,大家好有很久没有更新博客了.想写的东西很多,提起笔又觉得无从下笔.可能这就是菜鸟吧!好了废话不多说,进入正题. 本篇讲的是Android手机蓝牙分 ...
- react-native 原生Android界面向rn界面传递数据
react-native 原生Android界面向rn界面传递数据 写在前面:本人因技术有限,写的都是一些自己会的或者是能查到的方法,可能会存在一些瑕疵.如果大家有什么更好的方法,欢迎一起讨论. 在r ...
- Android手机蓝牙连接笔记本电脑蓝牙
1. 实验设备 1.1 笔记电脑 品牌:DELL 蓝牙模块:BCM43142(内置型带蓝牙的无线网卡) 蓝牙驱动:bluetooth_broadcom_6.5.1.6400_w7(通过360驱动大师下 ...
- STM32F103单片机温湿度等监测Android手机蓝牙APP显示控制设计
这次给大家介绍的是一个温湿度,光照烟雾等监测设计,包含开关灯.基于STM32F103单片机(正点原子mini板).蓝牙模块.Android APP完成.软件是Android studio 2021.1 ...
- 美国部分Android手机竟将用户隐私数据回传至上海服务器!
美国出售的Android手机,居然会将用户的个人数据传回到中国上海的服务器?今天美国大量安全媒体就报道了这样一件事,美国人民听来大概是非常惊悚的!Kryptowire安全公司的专家发现美国在售某些品牌 ...
- android fragment传递数据,Android 两个Fragment之间传递数据实例详解
Android 两个Fragment之间如何传递数据 FragmentA启动FragmentB,做一些选择操作后,返回FragmentA,需要把FragmentB里面选择的数据传回来.有什么办法? F ...
- Android 开发中使用Intent传递数据的方法
Activity之间通过Intent传递值,支持基本数据类型和String对象及它们的数组对象byte.byte[].char.char[].boolean.boolean[].short.short ...
- Android 手机获取加速度传感器加速度数据并自定义采样频率
原文链接:http://blog.csdn.net/llp1992/article/details/41786865 因为项目需要利用到了Android手机中的加速度传感器来获取三个加速度轴的加速度大 ...
- android数据线接口定义,制作Android手机可连接普通键盘的数据转接线
在上一篇" 现在市面上的Android手机和Android平板电脑基本上都支持USB OTG技术.这种技术将允许用户将手机或平板电脑通过usb2.0数据线连接到标准USB键盘和鼠标,甚至普通 ...
最新文章
- Android之加载外部dex
- c语言ut8,C语言使用utlist实现的双向链表
- 你可能不知道的switch
- 6.2.2 二叉树的创建
- STM32F1笔记(十二)DAC
- java使用properties_Java中使用Properties配置文件的简单方法
- sql慢查询问题排查
- 10分钟学会数据库压力测试
- svm loss function是什么
- “绿坝-花季护航”软件
- python numpy安装失败_【Python】pip安装numpy安装到一半失败解决办法
- c++ 写并查集算法模板
- 前端JQuery插件distpicker.js的部分操作使用
- cad2016批量修改相关字体,统一文字样式
- 金山毒霸推新产品金山卫士 正面狙击奇虎360
- 一句话道破X64和X86的区别
- 移动硬盘提示格式化解决办法,未正确删除导致不能读取文件提示格式化解决方案
- Vue简单快速上手 idea版
- 三轴加速度传感器BMA250解读
- FreeRTOS中的堆栈计算