安卓通讯开发——蓝牙的开启,搜索与传输

Posted I_wen.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓通讯开发——蓝牙的开启,搜索与传输相关的知识,希望对你有一定的参考价值。

蓝牙信息传输的关键步骤

1.首先开启蓝牙
2.搜索可用设备
3.创建蓝牙socket,获取输入输出流
4.读取和写入数据
5.断开连接关闭蓝牙

蓝牙设备操作

权限

要在应用中使用蓝牙功能,必须声明蓝牙权限 BLUETOOTH。您需要此权限才能执行任何蓝牙通信,例如请求连接、接受连接和传输数据等。

如果您希望您的应用启动设备发现或操作蓝牙设置,则还必须声明 BLUETOOTH_ADMIN 权限。 大多数应用需要此权限仅仅为了能够发现本地蓝牙设备。 除非该应用是将要应用户请求修改蓝牙设置的“超级管理员”,否则不应使用此权限所授予的其他能力。 注:如果要使用 BLUETOOTH_ADMIN 权限,则还必须拥有 BLUETOOTH 权限。

    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.READ_CONTACTS"/>

打开操作

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) 
    // Device does not support Bluetooth

 
if (!mBluetoothAdapter.isEnabled()) 
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

关闭操作

BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter(); 
_bluetooth.disable ():

搜索操作

BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter();
_bluetooth.startDiscovery();

UUID

蓝牙设备进行连接,需要一个唯一的UUID,在本案例中填写为6ee26c8e-a2ab-4291-adf3-8a679123616b,需要保证两个设备是相同的。

客户端与服务端

客户端

public class Client extends AppCompatActivity 
    private static final int CONN_SUCCESS = 0x1;
    private static final int CONN_FAIL = 0x2;
    private static final int RECEIVER_INFO = 0x3;
    private static final int SET_EDITTEXT_NULL = 0x4;

    private static Button send;
    private static TextView client_state;
    private static EditText client_send;

    BluetoothAdapter bluetooth = null;//本地蓝牙设备
    BluetoothDevice device = null;//远程蓝牙设备
    BluetoothSocket socket = null;//蓝牙设备Socket客户端

    //输入输出流
    PrintStream out;
    BufferedReader in;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);
        setTitle("蓝牙客户端");



        client_state = findViewById(R.id.client_state);
        client_send =  findViewById(R.id.client_send);
        send = findViewById(R.id.send);
        init();
    

    //创建蓝牙客户端端的Socket
    private void init() 
        client_state.setText("客户端已启动,正在等待连接...\\n");
        new Thread(new Runnable() 
            @Override
            public void run() 
                //1.得到本地蓝牙设备的默认适配器
                bluetooth = BluetoothAdapter.getDefaultAdapter();
                //2.通过本地蓝牙设备得到远程蓝牙设备,把“输入服务器端的设备地址”换成另一台手机的mac地址
                device = bluetooth.getRemoteDevice("02:00:00:00:00:00");
                //3.根据UUID创建并返回一个BoluetoothSocket
                try 
                    socket = device.createRfcommSocketToServiceRecord(UUID.fromString("6ee26c8e-a2ab-4291-adf3-8a679123616b"));
                    if (socket != null) 
                        // 连接
                        socket.connect();
                        //处理客户端输出流
                        out = new PrintStream(socket.getOutputStream());
                        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                    
                    handler.sendEmptyMessage(CONN_SUCCESS);
                 catch (IOException e) 
                    e.printStackTrace();
                    Message msg = handler.obtainMessage(CONN_FAIL, e.getLocalizedMessage());
                    handler.sendMessage(msg);

                

            
        ).start();
    

    //防止内存泄漏 正确的使用方法
    private final MyHandler handler = new MyHandler(this);

    public class MyHandler extends Handler 
        //软引用
        WeakReference<Client> weakReference;

        public MyHandler(Client activity) 
            weakReference = new WeakReference<Client>(activity);
        

        @Override
        public void handleMessage(Message msg) 
            super.handleMessage(msg);
            Client activity = weakReference.get();
            if (activity != null) 
                switch (msg.what) 
                    case RECEIVER_INFO:
                        setInfo(msg.obj.toString() + "\\n");
                        break;
                    case SET_EDITTEXT_NULL:
                        client_send.setText("");
                        break;
                    case CONN_SUCCESS:
                        setInfo("连接成功!\\n");
                        send.setEnabled(true);
                        System.out.println("name" + device.getName());
                        System.out.println("Uuids" + device.getUuids());
                        System.out.println("Address" + device.getAddress());
                        new Thread(new ReceiverInfoThread()).start();
                        break;
                    case CONN_FAIL:
                        setInfo("连接失败!\\n");
                        setInfo(msg.obj.toString() + "\\n");
                        break;
                    default:
                        break;
                
            
        
    


    private boolean isReceiver = true;

    //接收信息的线程
    class ReceiverInfoThread implements Runnable 
        @Override
        public void run() 
            String info = null;
            while (isReceiver) 
                try 
                    System.out.println("--ReceiverInfoThread start --");
                    info = in.readLine();
                    System.out.println("--ReceiverInfoThread read --");
                    Message msg = handler.obtainMessage(RECEIVER_INFO, info);
                    handler.sendMessage(msg);
                 catch (IOException e) 
                    e.printStackTrace();
                
            
        
    


    public void send(View v) 
        final String content = client_send.getText().toString();
        if (TextUtils.isEmpty(content)) 
            Toast.makeText(this, "不能发送空消息", Toast.LENGTH_LONG).show();
            return;
        
        new Thread(new Runnable() 
            @Override
            public void run() 
                out.println(content);
                out.flush();
                handler.sendEmptyMessage(SET_EDITTEXT_NULL);
            
        ).start();
    

    private void setInfo(String info) 
        StringBuffer sb = new StringBuffer();
        sb.append(client_state.getText());
        sb.append(info);
        client_state.setText(sb);
    

activity_client.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"


xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Client">

<TextView
    android:id="@+id/client_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:text="客户端"
    android:textSize="33sp"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/client_state"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:text="当前未执行任何操作"
    android:textSize="22sp"
    app:layout_constraintBottom_toTopOf="@+id/client_send"
    app:layout_constraintTop_toBottomOf="@+id/client_text" />

<EditText
    android:id="@+id/client_send"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:hint="请输入要发送的内容"
    app:layout_constraintBottom_toTopOf="@+id/send" />

<Button
    android:id="@+id/send"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:onClick="send"
    android:text="发送"
    app:layout_constraintBottom_toBottomOf="parent" />



</androidx.constraintlayout.widget.ConstraintLayout>


服务端


public class Server extends AppCompatActivity 
    private static final int CONN_SUCCESS = 0x1;
    private static final int CONN_FAIL = 0x2;
    private static final int RECEIVER_INFO = 0x3;
    private static final int SET_EDITTEXT_NULL = 0x4;
    private static Button send;
    private static TextView server_state;
    private static EditText server_send;

    BluetoothAdapter bluetooth = null;//本地蓝牙设备
    BluetoothServerSocket serverSocket = null;//蓝牙设备Socket服务端
    BluetoothSocket socket = null;//蓝牙设备Socket客户端

    //输入输出流
    PrintStream out;
    BufferedReader in;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_server);
        setTitle("蓝牙服务端");
        server_state = (TextView) findViewById(R.id.server_state);
        server_send = (EditText) findViewById(R.id.server_send);
        send = (Button) findViewById(R.id.send);
        init();
    

    //创建蓝牙服务器端的Socket
    private void init() 
        server_state.setText("服务器已启动,正在等待连接...\\n");
        new Thread(new Runnable() 
            @Override
            public void run() 
                //1.得到本地设备
                bluetooth = BluetoothAdapter.getDefaultAdapter();
                //2.创建蓝牙Socket服务器
                try 
                    serverSocket = bluetooth.listenUsingRfcommWithServiceRecord("text", UUID.fromString("6ee26c8e-a2ab-4291-adf3-8a679123616b"));
                    //3.阻塞等待Socket客户端请求
                    socket = serverSocket.accept();
                    if (socket != null) 
                        out = new PrintStream(socket.getOutputStream());
                        in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                    
                    handler.sendEmptyMessage(CONN_SUCCESS);
                 catch (IOException e) 
                    e.printStackTrace();
                    Message msg = handler.obtainMessage(CONN_FAIL, e.getLocalizedMessage());
                    handler.sendMessage(msg);
                

            
        ).start();

    

    //防止内存泄漏 正确的使用方法
    private final MyHandler handler = new MyHandler(this);

    public class MyHandler extends Handler 
        //软引用
        WeakReference<Server> weakReference;

        public MyHandler(Server activity) 
            weakReference = new WeakReference<Server>(activity);
        

        @Override
        public void handleMessage(Message msg) 
            super.handleMessage(msg);
            Server activity = weakReference.get();
            if (activity != null) 
                switch (msg.what) 
                    case RECEIVER_INFO:
                        setInfo(msg.obj.toString() + "\\n");
                        break;
                    case SET_EDITTEXT_NULL:
                        server_send.setText("");
                        break;
                    case CONN_SUCCESS:
                        setInfo("连接成功!\\n");
                        send.setEnabled(true);
                        new Thread(new ReceiverInfoThread()).start();
                        break;
                    case CONN_FAIL:
                        setInfo("连接失败!\\n");
                        setInfo(msg.obj.toString() + "\\n");
                        break;
                    default:
                        break;
                
            
        
    

    private boolean isReceiver = true;

    class ReceiverInfoThread implements Runnable 
        @Override
        public void run() 
            String info = null;
            while (isReceiver) 
                try 
                    info Android 蓝牙设备通讯的开发(配对/连接/传输数据)

安卓蓝牙实现即时通讯功能

解决 安卓小程序蓝牙 重连失败的问题

android 蓝牙开发---与蓝牙模块进行通讯 基于eclipse项目

lesimpleble如何开启蓝牙

怎么通过蓝牙实现安卓手机与全站仪的通讯?