一.蓝牙基础知识

蓝牙(Bluetooth)是一种短距离的无线通信技术标准。这个名子来源于10世纪丹麦国王Harald Blatand,英文名子是Harold Bluetooth。

(一)蓝牙的四层协议

蓝牙协议分为4层,即核心协议层、电缆替代协议层、电话控制协议层和采纳的其它协议层。这4种协议中最重要的是核心协议。蓝牙的核心协议包括基带、链路管理、逻辑链路控制和适应协议四部分。其中链路管理(LMP)负责蓝牙组件间连接的建立。逻辑链路控制与适应协议(L2CAP)位于基带协议层上,属于数据链路层,是一个为高层传输和应用层协议屏蔽基带协议的适配协议。

(二)蓝牙的操作

Android提供蓝牙API来执行这些不同的操作。
1. 开关蓝牙
2. 扫描其他蓝牙设备
3. 获取配对设备列表
4. 连接到通过服务发现其他设备

(三)蓝牙权限

1. android.permission.BLUETOOTH:

允许程序连接到已配对的蓝牙设备,请求连接/接收连接/传输数据需要改权限, 主要用于对配对后进行操作;

2. android.permission.BLUETOOTH_ADMIN :

允许程序发现和配对蓝牙设备, 该权限用来管理蓝牙设备, 有了这个权限, 应用才能使用本机的蓝牙设备, 主要用于对配对前的操作;

(四)BluetoothAdapter

BluetoothAdapter代表了移动设备的本地的蓝牙适配器, 通过该蓝牙适配器可以对蓝牙进行基本操作
BluetoothAdapter.getDefaultAdapter()该静态方法可以获取该适配器对象.

(五)蓝牙的BluetoothAdapter .STATE 状态值 , 即开关状态

1.蓝牙关闭 int STATE_OFF //值为10, 蓝牙模块处于关闭状态;
2.蓝牙打开中 int STATE_TURNING_ON //值为11, 蓝牙模块正在打开;
3.蓝牙开启 int STATE_ON //值为12, 蓝牙模块处于开启状态;
4. 蓝牙开启中 int STATE_TURNING_OFF //值为13, 蓝牙模块正在关闭;
蓝牙开关状态顺序 : STATE_OFF –> STATE_TURNING_ON –> STATE_ON –>STATE_TURNING_OFF –> STATE_OFF;

(六)BluetoothAdapter SCAN_MOD状态值 ,即扫描状态

  1. 无功能状态 : int SCAN_MODE_NONE //值为20, 查询扫描和页面扫描都失效,
    该状态下蓝牙模块既不能扫描其它设备, 也不可见;
  2. 扫描状态 : int SCAN_MODE_CONNECTABLE //值为21, 查询扫描失效, 页面扫描有效,
    该状态下蓝牙模块可以扫描其它设备, 从可见性来说只对已配对的蓝牙设备可见, 只有配对的设备才能主动连接本设备;
  3. 可见状态 : int SCAN_MODE_CONNECTABLE_DISCOVERABLE //值为23, 查询扫描和页
    面扫描都有效;

(七)打开/关闭蓝牙的两种方法:

1.直接调用函数enable()去打开蓝牙设备 ;

2.系统API去打开蓝牙设备,该方式会弹出一个对话框样式的Activity供用户选择是否打开蓝牙设备。

代码示例:

//第一种启动蓝牙的方法,不推荐
//bluetoothAdapter.enable();
//第二种启动蓝牙的方法,推荐
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), REQUEST_ENABLE);
//第二种方法要写数据回调方法
/*** 数据回调方法*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_ENABLE) {if (resultCode == RESULT_OK) {Toast.makeText(this, "蓝牙已开启", Toast.LENGTH_SHORT).show();// getMyBondedDevices();//获取绑定的蓝牙设备adapter.notifyDataSetChanged();//刷新适配器} else {Toast.makeText(this, "蓝牙未开启", Toast.LENGTH_SHORT).show();}}
}

(八)关闭蓝牙,直接调用API 函数即disable()即可。

public boolean disable ()
返回值:该函数会立即返回。
1.true 表示关闭操作成功
2. false 表示蓝牙操作失败 , ①、当前蓝牙已经关闭 ; ②、其他一些异常情况

(九)扫描蓝牙设备

  1.public boolean startDiscovery () 功能: 扫描蓝牙设备的开启注意: 如果蓝牙没有开启,该方法会返回false ,即不会开始扫描过程。2.public  boolean cancelDiscovery ()功能: 取消扫描过程。注意: 如果蓝牙没有开启,该方法会返回false。3.public boolean isDiscovering ()功能: 是否正在处于扫描过程中。注意: 如果蓝牙没有开启,该方法会返回false。

这里要特别注意,蓝牙扫描的时候,它会发出系统的广播,这是我们就要创建广播接收者来接收数据,数据里面就有蓝牙的设备对象和名称等等,广播也是蓝牙知识的重中之重。

(十)蓝牙的广播

Action值 说明
ACTION_STATE_CHANGED 蓝牙状态值发生改变
*ACTION_SCAN_MODE_CHANGED 蓝牙扫描状态(SCAN_MODE)发生改变*
ACTION_DISCOVERY_STARTED 蓝牙扫描过程开始
ACTION_DISCOVERY_FINISHED 蓝牙扫描过程结束
ACTION_LOCAL_NAME_CHANGED 蓝牙设备Name发生改变
ACTION_REQUEST_DISCOVERABLE 请求用户选择是否使该蓝牙能被扫描

PS:如果蓝牙没有开启,用户点击确定后,会首先开启蓝牙,继而设置蓝牙能被扫描。
Action值: ACTION_REQUEST_ENABLE // 请求用户选择是否打开蓝牙
示例:
创建广播接收者:

/*** 广播接收者的创建*/
private BroadcastReceiver receiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {//获取设备的发送的广播//做数据处理}
};

注册广播接收者

/*** 广播的注册,注意这里Action可以添加多个*/
@Override
protected void onResume() {super.onResume();
//添加蓝牙广播的Action,发现蓝牙设备时的ActionIntentFilter intentFilter = new
IntentFilter(BluetoothDevice.ACTION_FOUND);
//添加蓝牙广播的Action,蓝牙设备扫描完毕时的Action
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);registerReceiver(receiver, intentFilter);//注册广播接收者
}

广播的注销

/*** 广播的停止*/
@Override
protected void onPause() {super.onPause();unregisterReceiver(receiver);//取消广播
}

一般监听发现蓝牙和蓝牙扫描完成的广播就可以了。
      通过广播接收数据后,再对数据进行处理。就可以看到我们手机上显示的蓝牙设设备名称和其他信息。

(十一)获取蓝牙的相关信息的方法

1.public String getName ()

功能:获取蓝牙设备Name

2.public String getAddress ()

功能:获取蓝牙设备的硬件地址(MAC地址),例如:00:11:22:AA:BB:CC

3.public boolean setName (String name)

功能:设置蓝牙设备的Name。

4.public SetgetBondedDevices ()

功能:获取与本机蓝牙所有绑定的远程蓝牙信息,以BluetoothDevice类实例(稍后讲到)返回。
注意:如果蓝牙未开启,该函数会返回一个空集合 。

5.public static boolean checkBluetoothAddress (String address)

 功能: 验证蓝牙设备MAC地址是否有效。所有设备地址的英文字母必须大写,48位,形如:00:43:A8:23:10:F1 。

返回值: true 设备地址有效,false 设备地址无效

6.public BluetoothDevice getRemoteDevice (String address)

功能:以给定的MAC地址去创建一个 BluetoothDevice 类实例(代表远程蓝牙实例)。即使该蓝牙地址不可见,也会产生 一个BluetoothDevice 类实例。
返回:BluetoothDevice 类实例 。注意,如果该蓝牙设备MAC地址不能被识别,其蓝牙Name为null。
异常:如果MAC address无效,抛出IllegalArgumentException。

使用上面的方法就可以对蓝牙进行扫描显示。但是要使用蓝牙通信就要使用到Socket编程了。

二.蓝牙Socket通信

关于Socket编程,之前有一篇java的简介和使用示例:
http://blog.csdn.net/wenzhi20102321/article/details/52620323

(一)UUID

在蓝牙中,每个服务和服务属性都唯一地由 全局唯一标识符 ,Universally Unique Identifier(UUID)来校验。正如它的名字所暗示的,每一个这样的标识符都要在时空上保证唯一。UUID类可表现为短整形(16或32位)和长整形(128 位)UUID。他提供了分别利用String和16位或32位数值来创建类的构造函数,提供了一个可以比较两个UUID(如果两个都是128位)的方法,还有一个可以转换一个UUID为一个字符串的方法。UUID实例是不可改变的(immutable),只有被UUID标示的服务可以被发现。
      UUID的格式被分成5段,其中中间3段的字符数相同,都是4个,第1段是8个字符,最后一段是12个字符。所以UUID实际上是8个-4个-4个-4个-12个的字符串。

UUID相当于Socket的端口,而蓝牙地址相当于Socket的IP。两个蓝牙设备进行连接时需要使用同一个UUID, 这是一个服务的唯一标识,而且这个UUID的值必须是
00001101-0000-1000-8000-00805F9B34FB

上面这个UUID,直接复制使用就可以了。

下面是蓝牙Socket使用示例:

三.蓝牙Socket通信示例

程序实现两台手机的蓝牙发送消息,并接受消息。这里的蓝牙是不需要网络支持的。
程序运行后,扫描蓝牙后的界面:

程序进行通信后的界面,要两个手机哦!

      两个手机,其中一个设置为服务器,然后点击连接的手机,就可以进行消息发送和接收了。
上面只是实现文本通信,文本也只是进行简单处理。

程序设计代码:

(一)添加权限

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<!--6.0以上才要加的额外权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

(二)布局文件的设计

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="open"android:text="开启蓝牙" /><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="close"android:text="关闭蓝牙" /><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="found"android:text="暴露自己的设备名称" /><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="scan"android:text="扫描蓝牙设备" /><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="createServer"android:text="设置为蓝牙服务端" /><Button
        android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="listen"android:text="监听数据的接收" /><LinearLayout
        android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><EditText
            android:id="@+id/et_send"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="2"android:singleLine="true" /><Button
            android:id="@+id/btn_send"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="send"android:text="send" /></LinearLayout><ScrollView
        android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayout
            android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextView
                android:id="@+id/tv_show"android:layout_width="match_parent"android:layout_height="wrap_content" /><TextView
                android:id="@+id/tv_show_service"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="right" /><ListView
                android:id="@+id/lv"android:layout_width="match_parent"android:layout_height="200dp" /></LinearLayout></ScrollView>
</LinearLayout>

(三)可读写流的类

package fuxi.bluetooth20;import android.bluetooth.BluetoothSocket;
import android.util.Log;import java.io.InputStream;
import java.io.OutputStream;/*** 在子线程中进行读写操作*/
public class RWStream extends Thread {InputStream is;//输入流OutputStream os;//输出流//蓝牙的Socket对象private final BluetoothSocket socket;//通过构造方法传入Socket对象public RWStream(BluetoothSocket socket) {this.socket = socket;}@Overridepublic void run() {super.run();try {is = socket.getInputStream();//获取Socket的输入流os = socket.getOutputStream();//获取Socket的输出流byte[] buf = new byte[1024];int len = 0;Log.e("TAG", "-----------开始读取----(is==null)   " + (is == null));while (socket.isConnected()) {//当Socket是连接状态时,就一直进行数据的读取while ((len = is.read(buf)) != -1) {String message = new String(buf, 0, len);//获取流里面的数据Log.e("TAG", "----------" + message);//如果在另一端设置的接口对象,那么就传递数据if (dateShow != null) {dateShow.getMessager(message);}}}} catch (Exception e) {Log.e("TAG", "-----------线程异常");}}/*** 数据的写入*/public void write(String msg) {Log.e("TAG", "--------os!=null   " + (os != null));if (os != null) {try {//Socket数据的写入os.write(msg.getBytes());//刷新输出流数据os.flush();} catch (Exception e) {Log.e("TAG", "---写入--------异常" + e.getMessage());}}}/*** 定义接口实现数据回调*/interface DataShow {//返回数据,读取到的字符串,传递过去void getMessager(String message);}//定义接口对象DataShow dateShow;//接口的对象的设置方法public void setDataShow(DataShow dateShow) {this.dateShow = dateShow;}
}

(四)蓝牙服务器端(Socket服务端)的设计

package fuxi.bluetooth20;import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.util.Log;import java.io.IOException;/*** 蓝牙设置的服务器端*/public class BlueServer extends Thread {//可读写数据的对象RWStream rwStream;public RWStream getRwStream() {return rwStream;}//蓝牙设备管理器private final BluetoothAdapter adapter;//通过构造方法传入设置管理器public BlueServer(BluetoothAdapter adapter) {this.adapter = adapter;}//线程内的任务@Overridepublic void run() {super.run();try {//创建蓝牙服务端的Socket,这里第一个参数是服务器的名称,第二个参数是UUID的字符串的值BluetoothServerSocket socket = adapter.listenUsingRfcommWithServiceRecord("server", MainActivity.uuid);Log.e("TAG", "--------------->>开始监听客户端连接");//获取蓝牙客户端对象,这是一个同步方法,用客户端接入才有后面的操作BluetoothSocket client = socket.accept();Log.e("TAG", "--------------->>有客户端接入");//获取可读可写对象rwStream = new RWStream(client);//开始可读可写线程的操作,这里是一直在读取数据的状态rwStream.start();} catch (IOException e) {e.printStackTrace();}}
}

(五)主方法类的设计

package fuxi.bluetooth20;import android.Manifest;
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.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;import static android.util.Log.e;/*** 蓝牙的使用示例*/
public class MainActivity extends AppCompatActivity {//控制蓝牙设备的对象BluetoothAdapter bluetoothAdapter;//布局内的ListView控件ListView listView;TextView tv_show;TextView tv_show_service;EditText et_send;Button btn_send;ArrayAdapter adapter;//适配器对象的定义//蓝牙设备的对象的集合ArrayList<BluetoothDevice> devices = new ArrayList<>();//设备的名称集合ArrayList<String> deviceNames = new ArrayList<>();//手机蓝牙的UUID固定值public static final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");private static final int REQUEST_LOCATION = 1000;//手机动态请求权限的请求码private static final int REQUEST_ENABLE = 1001;//启动蓝牙设备的请求码private static final int REQUEST_DISCOVER_MYSELF = 1002;//设置自身蓝牙设备可被发现的请求码@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//实例化bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();listView = (ListView) findViewById(R.id.lv);tv_show = (TextView) findViewById(R.id.tv_show);tv_show_service = (TextView) findViewById(R.id.tv_show_service);et_send = (EditText) findViewById(R.id.et_send);btn_send = (Button) findViewById(R.id.btn_send);//创建适配器,使用系统布局adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, deviceNames);//给ListView设置适配器listView.setAdapter(adapter);//判断是否有了权限checkPermission();//给ListView设置点击事件,点击对应的条目就创建对应的客户端,并经行数据的读取和写入listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {//连接服务器connServer(devices.get(position));}});}/*** 打开蓝牙设备*/public void open(View view) {//不推荐//bluetoothAdapter.enable();//推荐startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), REQUEST_ENABLE);}/*** 关闭蓝牙设备*/public void close(View view) {bluetoothAdapter.disable();//关闭//擦除页面数据deviceNames.clear();adapter.notifyDataSetChanged();}/*** 扫描蓝牙设备*/public void scan(View view) {if (bluetoothAdapter.isEnabled()) {//先清除页面数据!devices.clear();deviceNames.clear();//使用广播的方法去获取设备,这里就要动态创建广播,并进行接听了//定义一个系统规定action的广播,//当系统没扫描到一个蓝牙设备就会发送一条广播// 当系统做完扫描后,系统会发送广播,你只需在广播接收者做好处理bluetoothAdapter.startDiscovery();} else {Toast.makeText(this, "请先开启蓝牙", Toast.LENGTH_SHORT).show();}}/*** 让自身蓝牙设备可被发现*/public void found(View view) {getMyBondedDevices();if (bluetoothAdapter.isDiscovering()) {//如果蓝牙设置正在扫描Toast.makeText(this, "正在扫描,别急", Toast.LENGTH_SHORT).show();} else {//这里可以设置显示自己蓝牙设备的时间,默认是300秒,也可以自定义单位是秒Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 600);startActivityForResult(intent, REQUEST_DISCOVER_MYSELF);}}/*** 开启蓝牙服务的服务端*/boolean isServer = false;//默认是普通客户端BlueServer server;//创建蓝牙服务器的对象,在服务器做相关操作public void createServer(View view) {server = new BlueServer(bluetoothAdapter);server.start();isServer = true;//设置为服务端}/*** 发送数据*/public void send(View view) {String et = et_send.getText().toString();//获取输入框的数据//给另一端写入数据write(et);}/*** 数据的传递*/public void write(String msg) {if (isServer) {//服务器的写数据btn_send.setText("服务器");handlerSendMessager(1, msg);e("TAG", "----------(server != null && server.getRwStream() != null)  " + (server != null && server.getRwStream() != null));if (server != null && server.getRwStream() != null) {server.getRwStream().write(msg);}} else {//客户端的写数据btn_send.setText("客户端");handlerSendMessager(2, msg);if (client != null) {client.write(msg);}}}/*** 监听数据的接收*/public void listen(View view) {//服务器的监听数据if (server != null) {server.getRwStream().setDataShow(new RWStream.DataShow() {@Overridepublic void getMessager(final String message) {//要在主线程中改变UILog.e("TAG", "-------listen---Service" + message);handlerSendMessager(2, message);}});//客户端的监听数据} else if (client != null) {client.setDataShow(new RWStream.DataShow() {@Overridepublic void getMessager(final String message) {//要在主线程中改变UIe("TAG", "-------listen---client" + message);handlerSendMessager(1, message);}});}}/*** Handler包装类*/private void handlerSendMessager(int what, String messge) {Message msg = Message.obtain();msg.what = what;msg.obj = messge;handler.sendMessage(msg);}/*** 创建Handler对象用于线程间通信*/Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//显示数据在文本中if (msg.what == 1) {//服务器的数据在右边tv_show_service.setTextColor(Color.RED);tv_show_service.setTextSize(20);tv_show_service.append(msg.obj + "\n");} else {//客户端的数据在左边tv_show.setTextColor(Color.BLUE);tv_show.setTextSize(20);tv_show.append(msg.obj + "\n");}}};/*** 客户端连接服务器*/RWStream client;private void connServer(BluetoothDevice device) {try {//创建蓝牙客户端的Socket对象,这里是类BluetoothSocket,服务端是BluetoothServerSocketBluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuid);socket.connect();//连接Socket//创建可读写的客户对象,传入Socket对象client = new RWStream(socket);//开始客户端的线程client.start();} catch (IOException e) {e.printStackTrace();}}/*** 判断是否有蓝牙的权限,如果手机系统是6.0以上的就要动态创建权限*/private void checkPermission() {if (Build.VERSION.SDK_INT >= 23) {//23int check = checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION);if (check != PackageManager.PERMISSION_GRANTED) {//请求权限requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION);}}}/*** 动态请求权限后,返回页面时的回调方法*/@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (requestCode == REQUEST_LOCATION && grantResults[0] == PackageManager.PERMISSION_GRANTED) {Toast.makeText(this, "权限已获取", Toast.LENGTH_SHORT).show();} else {Toast.makeText(this, "权限未获取", Toast.LENGTH_SHORT).show();finish();//关闭页面}}/*** 数据回调方法*/@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_ENABLE) {if (resultCode == RESULT_OK) {Toast.makeText(this, "蓝牙已开启", Toast.LENGTH_SHORT).show();getMyBondedDevices();//获取绑定的蓝牙设备adapter.notifyDataSetChanged();//刷新适配器} else {Toast.makeText(this, "蓝牙未开启", Toast.LENGTH_SHORT).show();}} else {}}/*** 获取已经绑定的蓝牙设置*/private void getMyBondedDevices() {//获取所有已经绑定了的设备deviceNames.clear();//清除设备名称的集合devices.clear();//清除蓝牙设备对象的集合if (bluetoothAdapter.getBondedDevices() != null) {//如果蓝牙适配器对象不为空时//获取里面的数据的对象List<BluetoothDevice> liset = new ArrayList<>(bluetoothAdapter.getBondedDevices());devices.addAll(liset);//拿到适配器对象的名称数据for (BluetoothDevice device : liset) {deviceNames.add(device.getName());}}}/*** 广播的注册*/@Overrideprotected void onResume() {super.onResume();IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);//添加蓝牙广播的ActionintentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);registerReceiver(receiver, intentFilter);//注册广播接收者}/*** 广播的停止*/@Overrideprotected void onPause() {super.onPause();unregisterReceiver(receiver);//取消广播}/*** 广播接收者的创建*/private BroadcastReceiver receiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {//获取设备的发送的广播if (intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {Toast.makeText(context, "蓝牙扫描完毕", Toast.LENGTH_SHORT).show();} else {//获取蓝牙设置对象BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);//把对象和名称放到对应的集合中devices.add(device);deviceNames.add(TextUtils.isEmpty(device.getName()) ? "未命名" : device.getName());adapter.notifyDataSetChanged();}}};}

上面程序运行后就可以完成蓝牙通信了,上面程序设计中显示多个按钮是为了蓝牙的使用示范,实际程序中,可以减少扫描按钮,比如程序运行就打开蓝牙,监听数据的按钮的方法也是可以嵌入到程序当中。
      本程序虽然可以进行简单通信,但是也是有一些bug的,比如没有按照上面的步骤操作,直接点击后面的按钮是会空指针的!逻辑处理没有完善。
      如果要传输文件,或其他数据都是可以的,那就要对输入流和输出流进行设置了。
      这里对Socket编程简单做几句介绍,其实Socket编程并不是很难理解。Socket编程一般需要一个服务端SocketServie和一个或多个客户端Socket,通过SocketService或Socket对象获取它的输入流实现对数据的读取,获取输出流实现对数据的写入。其中数据如果要一直读取就要写一个一直执行的子线程,让它一直在跑。
      而Tcp/Udp编程就要用到ip地址和端口号了。Socket编程可以结合Tcp使用网络。

Android无线蓝牙开发总结相关推荐

  1. Android BLE蓝牙开发知识总结

    Android BLE蓝牙开发知识总结 1.蓝牙介绍 1.1什么是蓝牙?    蓝牙( Bluetooth® ):是一种无线技术标准,可实现固定设备.移动设备和楼宇个人域网之间的短距离数据交换(使用2 ...

  2. Android Ble蓝牙开发总结

    Android Ble蓝牙开发总结 前言 本文总结了ble的搜索,连接,读写操作.以及在开发过程中可能遇到的坑. 首先我们需要知道,什么是ble. 蓝牙发展至今经历了8个版本的更新.1.1.1.2.2 ...

  3. Android经典蓝牙开发全流程

    一.基本介绍   所谓蓝牙(Bluetooth)技术,实际上是一种短距离无线电技术,最初是由爱立信公司公司发明的.技术始于爱立信公司 1994 方案,它是研究在移动电话和其他配件间进行低功耗.低成本无 ...

  4. Android 经典蓝牙开发

    本文主要讲解经典蓝牙的开发,主要包含以下几个知识点: 蓝牙 API 简介 经典蓝牙开发的一般步骤 相信通过以上步骤,您会很快上手一个 Android 经典蓝牙开发的 App. 蓝牙 API 简介 An ...

  5. 【Android】蓝牙开发——经典蓝牙:配对与解除配对 实现配对或连接时不弹出配对框

    目录 一.配对方法 二.解除配对方法 三.配对/解除配对结果 四.justwork配对模式下,不弹出配对框 五.pincode配对模式下,不弹出配对框 六.小结 在之前的文章[Android]蓝牙开发 ...

  6. Android Bluetooth蓝牙开发:发现Bluetooth蓝牙设备(1)

     Android Bluetooth蓝牙开发:发现Bluetooth蓝牙设备(1) Android Bluetooth蓝牙作为设备,要与其他蓝牙设备互联,那么先决条件就是已经被发现,本文先简介An ...

  7. Android 低功耗蓝牙开发

    初识低功耗蓝牙 Android 4.3(API Level 18)开始引入Bluetooth Low Energy(BLE,低功耗蓝牙)的核心功能并提供了相应的 API, 应用程序通过这些 API 扫 ...

  8. 蓝牙配对模式 java_【Android】蓝牙开发—— 经典蓝牙配对介绍(Java代码实现演示)附Demo源码...

    目录 前言 一.连接&配对方法介绍 二.演示:第一次连接蓝牙设备  &  直接与蓝牙设备建立配对 三.总结 四.补充 五.Demo案例源码地址: 前言 前面两篇文章[Android]蓝 ...

  9. 【Android】蓝牙开发—— 经典蓝牙配对介绍(Java代码实现演示)附Demo源码

    目录 前言 一.连接&配对方法介绍 二.演示:第一次连接蓝牙设备  &  直接与蓝牙设备建立配对 三.总结 四.补充 五.Demo案例源码地址: 前言 前面两篇文章[Android]蓝 ...

最新文章

  1. 11. Leetcode 713. 乘积小于K的子数组 (数组-同向双指针-滑动窗口)
  2. 查询分析300万笔记录_一分钟狂销100万件商品!Shopee虾皮双12大促再创记录
  3. OC中使用 static 、 extern、 const使用
  4. mapreduce排序算法_MapReduce算法–二级排序
  5. jaxb 解析list元素_JAXB和根元素
  6. SpringAop @Pointcut(“@annotation“)\@Aspect练习
  7. 将一个二维数组合并成一个一维数组
  8. Nginx设置日志打印post请求参数
  9. 网络请求(HTTP协议)小结
  10. python刷新显示_Python在同一位置刷新显示进度信息
  11. [转帖]九句英语闯天下
  12. 需求分析与建模最佳实践
  13. 101/103/104规约应用典型问题例举
  14. ffmpeg解码H264文件并实时播放
  15. go下载指定版本的依赖包
  16. 光纤上网是如何实现的?—Vecloud微云
  17. 虚拟仿真实验平台服务器需求,虚拟仿真实验中心平台建设方案.pptx
  18. 美服fgo显示服务器异常,FGO日服美服错误代码合集_FGO日服美服错误代码汇总_牛游戏网...
  19. hadoop大数据平台搭建
  20. 如何将amr文件转成mp3格式?

热门文章

  1. ux设计_UX评论模式品牌知道规则并且也打破了规则
  2. mysql innodb 缓冲池_mysql8 参考手册--配置多个InnoDB缓冲池实例
  3. 微信公众号运营,如何有效的推广
  4. C# 读取outlook 本地签名
  5. win10系统更新后底部状态栏经常无响应
  6. 佛说,是我们自己苦了自己~
  7. c语言中void和define,C语言里面的内联函数(inline)与宏定义(#define)探讨
  8. Stderr: VBoxManage.exe: error: VT-x is not available (VERR_VMX_NO_VMX) VBoxM
  9. maven 本地仓库的配置以及如何修改默认.m2仓库位置
  10. Summernote 上传图片至 SMMS 图床 Api