Android学习——蓝牙通讯

 

蓝牙

蓝牙,是一种支持设备短距离通信(一般10m内,且无阻隔媒介)的无线电技术。能在包括移动电话、PDA、无线耳机、笔记本电脑等众多设备之间进行无线信息交换。利用“蓝牙”技术,能够有效的简化移动通信终端设备之间的通信,也能够成功的简化设备与Internet之间的通信,这样数据传输变得更加迅速高效,为无线通信拓宽道路。

注意:Android 2.0 引入蓝牙接口,在开发时,需要真机测试,如果需要数据传输,还需要两台机器,另外蓝牙下哟硬件支持。

蓝牙设备操作

权限:

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

打开蓝牙的方式有两种:

//第一种方法,打开蓝牙设备(提示对话框)
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
//第二种方法,打开蓝牙,静默打开
BluetoothAdapter bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
bluetoothAdapter.enable();

搜索蓝牙设备

//开始扫描蓝牙设备
BluetoothAdapter bluetoothAdapter2=BluetoothAdapter.getDefaultAdapter();
bluetoothAdapter2.startDiscovery();

关闭蓝牙设备

BluetoothAdapter bluetoothAdapter1=BluetoothAdapter.getDefaultAdapter();
bluetoothAdapter1.disable();

 

蓝牙通讯案例

 

MainActivity.java

package com.example.bluetooth;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import java.util.Set;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button open, close,button_scan,button_server,button_client;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        open = findViewById(R.id.open);
        close = findViewById(R.id.close);
        button_scan = findViewById(R.id.button_scan);
        button_server = (Button) findViewById(R.id.button_server);
        button_client = (Button) findViewById(R.id.button_client);
        open.setOnClickListener(this);
        close.setOnClickListener(this);
        button_scan.setOnClickListener(this);
        button_server.setOnClickListener(this);
        button_client.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.open:
                /*//第一种方法,打开蓝牙设备(提示对话框)
                Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                //打开本机蓝牙发现功能
                discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
                startActivity(discoverableIntent);*/

                //第二种方法,打开蓝牙,静默打开
                BluetoothAdapter bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
                bluetoothAdapter.enable();
                break;
            case R.id.close:
                BluetoothAdapter bluetoothAdapter1=BluetoothAdapter.getDefaultAdapter();
                bluetoothAdapter1.disable();
                break;
            case R.id.button_scan:
                //开始扫描蓝牙设备
                BluetoothAdapter bluetoothAdapter2=BluetoothAdapter.getDefaultAdapter();
                bluetoothAdapter2.startDiscovery();
                Log.i("tag","开始扫描蓝牙设备");
                Set<BluetoothDevice> set=bluetoothAdapter2.getBondedDevices();
                for (BluetoothDevice bd:set){
                    Log.i("tag","name:"+bd.getName());
                    Log.i("tag","address:"+bd.getAddress());
                }
                break;
            case R.id.button_server:
                Intent intent = new Intent(this, ServerBluetoothActivity.class);
                startActivity(intent);
                break;
            case R.id.button_client:
                Intent intent1 = new Intent(this, ClientBluetoothActivity.class);
                startActivity(intent1);
                break;
            default:
                break;
        }
    }
}

ServerBluetoothActivity.java

package com.example.bluetooth;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.lang.ref.WeakReference;
import java.util.UUID;

public class ServerBluetoothActivity 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 button_send;
    private static TextView textView_content;
    private static EditText editText_info;
    BluetoothAdapter bluetoothAdapter=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_bluetooth);
        setTitle("蓝牙服务端");
        textView_content= (TextView) findViewById(R.id.textView_content);
        editText_info= (EditText) findViewById(R.id.editText_info);
        button_send= (Button) findViewById(R.id.button_send);
        init();
    }

    //创建蓝牙服务器端的Socket
    private void init() {
        textView_content.setText("服务器已启动,正在等待连接...\n");
        new Thread(new Runnable() {
            @Override
            public void run() {
                //1.得到本地设备
                bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
                //2.创建蓝牙Socket服务器
                try {
                    serverSocket=bluetoothAdapter.listenUsingRfcommWithServiceRecord("text", UUID.fromString("00000000-2527-eef3-ffff-ffffe3160865"));
                    //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<ServerBluetoothActivity> weakReference;

        public MyHandler(ServerBluetoothActivity activity) {
            weakReference=new WeakReference<ServerBluetoothActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            ServerBluetoothActivity activity=weakReference.get();
            if (activity!=null){
                switch (msg.what){
                    case RECEIVER_INFO:
                        setInfo(msg.obj.toString()+"\n");
                        break;
                    case SET_EDITTEXT_NULL:
                        editText_info.setText("");
                        break;
                    case CONN_SUCCESS:
                        setInfo("连接成功!\n");
                        button_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;

    private class ReceiverInfoThread implements Runnable {
        @Override
        public void run() {
            String info=null;
            while (isReceiver){
                try {
                    info=in.readLine();
                    Message msg=handler.obtainMessage(RECEIVER_INFO,info);
                    handler.sendMessage(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void sendClick(View view){
        final String content=editText_info.getText().toString();
        if (TextUtils.isEmpty(content)){
            Toast.makeText(this, "不能发送空消息", Toast.LENGTH_SHORT).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(textView_content.getText());
        sb.append(info);
        textView_content.setText(sb);
    }
}

ClientBluetoothActivity.java

package com.example.bluetooth;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.lang.ref.WeakReference;
import java.util.UUID;

public class ClientBluetoothActivity 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 button_send;
    private static TextView textView_content;
    private static EditText editText_info;

    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_bluetooth);

        setTitle("蓝牙客户端");
        textView_content= (TextView) findViewById(R.id.textView_content);
        editText_info= (EditText) findViewById(R.id.editText_info);
        button_send= (Button) findViewById(R.id.button_send);
        init();
    }

    //创建蓝牙客户端端的Socket
    private void init() {
        textView_content.setText("客户端已启动,正在等待连接...\n");
        new Thread(new Runnable() {
            @Override
            public void run() {
                //1.得到本地蓝牙设备的默认适配器
                bluetooth=BluetoothAdapter.getDefaultAdapter();
                //2.通过本地蓝牙设备得到远程蓝牙设备
                device=bluetooth.getRemoteDevice("22:22:4E:6E:59:86");
                //3.根据UUID创建并返回一个BoluetoothSocket
                try {
                    socket=device.createRfcommSocketToServiceRecord(UUID.fromString("00000000-2527-eef3-ffff-ffffe3160865"));
                    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<ClientBluetoothActivity> weakReference;

        public MyHandler(ClientBluetoothActivity activity) {
            weakReference = new WeakReference<ClientBluetoothActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            ClientBluetoothActivity activity = weakReference.get();
            if (activity!=null){
                switch (msg.what){
                    case RECEIVER_INFO:
                        setInfo(msg.obj.toString() + "\n");
                        break;
                    case SET_EDITTEXT_NULL:
                        editText_info.setText("");
                        break;
                    case CONN_SUCCESS:
                        setInfo("连接成功!\n");
                        button_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 {
                    Log.i("tag","--ReceiverInfoThread start --");
                    info=in.readLine();
                    Log.i("tag","--ReceiverInfoThread read --");
                    Message msg=handler.obtainMessage(RECEIVER_INFO,info);
                    handler.sendMessage(msg);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void sendClick(View v){
        final String content=editText_info.getText().toString();
        if (TextUtils.isEmpty(content)){
            Toast.makeText(this, "不能发送空消息", Toast.LENGTH_SHORT).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(textView_content.getText());
        sb.append(info);
        textView_content.setText(sb);
    }
}

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
1.首先是蓝牙APP, 易安卓编写的,说编写其实我只是修改了其中的一些内容,主要的部分都是易锦老师视频里的那个软件,不过我已经懂得了那些命令,(后面有工程文件,如果不 懂,可以去找易锦老师的视频来看,如果找不到,我这存的有),两张界面和代码截图,非常简单,功能也很简单,程序前后修改了两次主要地方,主要原因是测试 的时候发现第一种程序会出现错误,在单片机哪里会仔细说明! 操作界面,很简单,打开之后打开蓝牙,然后点击搜索设备,找到你的模块名字,点击之后就可以连接了,连接之后下面会显示蓝牙的名称和地址信息 2.单片机程序,这个程序也很简单,只要学过一些单片机程序的人应该都知道吧,串口通信,设置好通信的波特率,初始化工作做好,然后在串口中断程序里写上你要做的事情就可 以了,这里虽然说11.0592的晶振定时器初值为fd,但是如果用12m的晶振也是可以的,差距不多,没有问题。(说的不怎么专业,我也不是很专业的 人,所以请大神误喷,见笑了!)这里是修改前后的程序不一样的地方,前面的程序是单片机没接收到数据之后读取前一次的IO状态,然后改变其状态,但是测试 的时候发现读取状态有错误,估计是我的电路有问题,第一个继电器可以正常工作,第二个和第三个都有问题,当第一个关闭的时候可以打开,但是当打开的了却不 能关闭,只能用关闭所有的命令来关闭,(找了一下午也没发现问题,元件换了几个都没找到,后来放弃了),后来就换了后面程序,直接发送状态命令,不用判断 当前的状态了,我觉得后面这种可能更好!而且实际测试的时候也可以,没有问题。(补充一下,我发现12M的晶振不能用11.0592M的数据,原因是定时 器计数产生的波特率与9600差距有点大,误差到达了8.5%左右,理论上误差要小于4%才能正常通信,所以通信有错误,虽然能通信,但是数据不对,后来 我把晶振换回来就可以了,看来要实践才知道真理。) 第 一、二张是修改之前的程序,有问题,最后一张是修改之后的,没有问题,后来仔细想了一下,后面一种才是正确的,前面一种的改变状态可能会出现错误,就是手 机上显示的开关是关的,然而实际电路中的电路是开着的(这也是没有数据回传的原因吧,现在只是单向的手机发,模块接的形式,以后再研究)!,但是后面一种 不会出现这个问题! 3.实物电路连接,我也是在测试,所以先用LED 等来代替继电器输出,然后才用到继电器上面。单片机直接放在我做的最小系统版上面,然后用导线来连接到蓝牙开关的小板子上,等测试无误之后再安装在上面, 不然不好写程序上去。输出接的是一个小电机,用的一个12v蓄电池代替220V电源,如果要用220V的电源,要注意安全了!提醒一下,绝缘一定要做好, 毕竟不是开玩笑的。简单说一下电路连接,首先你得需要焊接一个51单片机最小系统板,(如果这个都不会,那你需要先学习一下,不然肯定是没办法做的)然后是由三极管驱动继电器的电路,记得加二极管,不然三极管很有几率被击穿,最后是蓝牙模块与单片机的连接,电源接好,一般蓝牙模块都是宽电压的,所以直接接到5V电源上,与单片机共用电源,不用什么电压转换,很方便的,把蓝牙模块的TX与单片机的RX连接,就是P3.0那个引脚,RX接单片机的TX,就是P3.1那个引脚,至于继电器哪里你需要接成常开还是常闭的模式就你自己决定了,当然还要加一点录滤波的,因为继电器启动的一瞬间电流很大,担心是单片机死机!这些就是主要的东西了!) 前一张是之前测试用的,后面一张是后来直接把单片机装上去的,看着没有那么乱了,可以看到,当手机上的开关23打开时,电路板上的灯23也是两的,表明继电器已经被打开了。 4.打完收工,作品完成好 了至此最简单的蓝牙开关就做好了,可以躺在床上遥控在远处的风扇了(好吧你们都用的是空调,当我没说!),定时关机(这个功能没做,不过原理都一样,自由 发挥了),其他神马的!感兴趣的同学可以试一下,比如说高级一点的外网控制的,把电脑作为服务器,把蓝牙模块接好,和控制器连接起来,然后让手机与电脑通 过互联网通信,用手机给电脑发送指令,再通过电脑给蓝牙模块发送指令,比如提前开个空调什么的(提前开风扇没用,还是开你们的空调吧),然后其他什么的东 西就自己发挥了!我想这个应该是属于传说中的物联网吧,虽然没有那么高大上,但是原理是一样的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值