由于APP软件应用环境的需要,我利用蓝牙芯片HC08实现手机和单片机之间的数据通信,工具包括hc-08蓝牙模块一个,电脑一部,安卓手机一部,相关软件:单片机下位机,串口通讯助手等。从官网上下载《汇承HC-08(V3.1)蓝牙4.0 BLE串口模块使用规格书》可以了解蓝牙的相关指令及使用方法。

参考网上的实例,结合自己的业务,我把主要的内容分享如下:

Mainactivity.xm

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
   <TextView
       android:id="@+id/device_number"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Devices"
       android:textSize="18dp"
       android:layout_alignParentStart="true" />

   <TextView
       android:id="@+id/location"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_below="@id/device_number"
       android:text="@string/server_location"
       android:textSize="10dp" />
   <Button 
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentEnd="true"
       android:text="扫描设备"
       android:id="@+id/scan_dev_btn"
       />

   <ListView
       android:id="@+id/lv"
       android:layout_width="fill_parent"
       android:layout_height="match_parent"
       android:layout_below="@+id/scan_dev_btn"
       android:layout_marginBottom="50dip" >
</ListView>

</RelativeLayout>

Boxactivity.java(安全需要,去掉了部分代码)

package com.blehc08.ui;

import android.app.Activity;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;

import com.blehc08.service.BluetoothLeService;

import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.blehc08.R;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Date;

import static com.blehc08.cFunction.intToHex;
import static com.blehc08.cFunction.intToHexString;

public class Box_Activity extends Activity implements View.OnClickListener {

    private final static String TAG = Ble_Activity.class.getSimpleName();
    public static String HEART_RATE_MEASUREMENT = "0000ffe1-0000-1000-8000-00805f9b34fb";
    public static String EXTRAS_DEVICE_NAME = "DEVICE_NAME";;
    public static String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
    public static String EXTRAS_DEVICE_RSSI = "RSSI";
    //蓝牙连接状态
    private boolean mConnected = false;
    private String status = "disconnected";
    //蓝牙名字
    private String mDeviceName;
    //蓝牙地址
    private String mDeviceAddress;
    //蓝牙信号值
    private String mRssi;
    private Bundle b;
    private String rev_info = ""; //接收到的当前信息
    private String rev_str = "";   //显示当前接收到的信息日志,目的是能够显示每一条指令。

    //蓝牙service,负责后台的蓝牙服务
    private static BluetoothLeService mBluetoothLeService;
    //文本框,显示接受的内容
    private TextView rev_tv, connect_state;

    private String mCommand=""; //发出的指令


    private RadioButton rb_ip1;
    private RadioButton rb_ip2;
    //文本编辑框
    private EditText et_pwd;  //密码输入框
    private ScrollView rev_sv;
    //ip编辑框
    private EditText local_gw_edit_1;
    private EditText local_gw_edit_2;
    private EditText local_gw_edit_3;
    private EditText local_gw_edit_4;
    private EditText local_gw_port;

    private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
    //蓝牙特征值
    private static BluetoothGattCharacteristic target_chara = null;
    private Handler mhandler = new Handler();
    private Handler myHandler = new Handler()    {
        // 2.重写消息处理函数
        public void handleMessage(Message msg)
        {
            switch (msg.what)
            {
                // 判断发送的消息
                case 1:
                {
                    // 更新View
                    String state = msg.getData().getString("connect_state");
                    connect_state.setText(state);

                    break;
                }

            }
            super.handleMessage(msg);
        }

    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.box_activity);
        b = getIntent().getExtras();
        //从意图获取显示的蓝牙信息
        mDeviceName = b.getString(EXTRAS_DEVICE_NAME);
        mDeviceAddress = b.getString(EXTRAS_DEVICE_ADDRESS);
        mRssi = b.getString(EXTRAS_DEVICE_RSSI);

        /* 启动蓝牙service */
        Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
        bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
        init();
    }

    @Override
    protected void onDestroy()    {
        super.onDestroy();
        //解除广播接收器
        unregisterReceiver(mGattUpdateReceiver);
        mBluetoothLeService = null;
    }

    // Activity出来时候,绑定广播接收器,监听蓝牙连接服务传过来的事件
    @Override
    protected void onResume()    {
        super.onResume();
        //绑定广播接收器
        registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
        if (mBluetoothLeService != null)
        {
            //根据蓝牙地址,建立连接
            final boolean result = mBluetoothLeService.connect(mDeviceAddress);
            Log.d(TAG, "Connect request result=" + result);
        }
    }
    private void init() {
        rev_sv = (ScrollView) this.findViewById(R.id.rev_sv);
        rev_tv = (TextView) this.findViewById(R.id.rev_tv);
        connect_state = (TextView) this.findViewById(R.id.connect_state);
        connect_state.setText(status);


        local_gw_edit_1= (EditText) this.findViewById(R.id.local_gw_edit_1);
        local_gw_edit_2= (EditText) this.findViewById(R.id.local_gw_edit_2);
        local_gw_edit_3= (EditText) this.findViewById(R.id.local_gw_edit_3);
        local_gw_edit_4= (EditText) this.findViewById(R.id.local_gw_edit_4);
        local_gw_port= (EditText) this.findViewById(R.id.local_gw_port);

        rb_ip1=(RadioButton) this.findViewById(R.id.rb_ip1);
        rb_ip2=(RadioButton) this.findViewById(R.id.rb_ip2);
        rb_ip1.isChecked();

        et_pwd = (EditText) this.findViewById(R.id.et_pwd);
        btn_getpwd = (Button) this.findViewById(R.id.btn_getpwd);
        btn_getpwd.setOnClickListener(this);

        btn_getip = (Button) this.findViewById(R.id.btn_getip);
        btn_getip.setOnClickListener(this);
        btn_getip.setEnabled(false);

        btn_setip = (Button) this.findViewById(R.id.btn_setip);
        btn_setip.setOnClickListener(this);
        btn_setip.setEnabled(false);


    }
    /* BluetoothLeService绑定的回调函数 */
    private final ServiceConnection mServiceConnection = new ServiceConnection()    {

        @Override
        public void onServiceConnected(ComponentName componentName,
                                       IBinder service)
        {
            mBluetoothLeService = ((BluetoothLeService.LocalBinder) service)
                    .getService();
            if (!mBluetoothLeService.initialize())
            {
                Log.e(TAG, "Unable to initialize Bluetooth");
                finish();
            }
            // Automatically connects to the device upon successful start-up
            // initialization.
            // 根据蓝牙地址,连接设备
            mBluetoothLeService.connect(mDeviceAddress);

        }

        @Override
        public void onServiceDisconnected(ComponentName componentName)
        {
            mBluetoothLeService = null;
        }

    };

    /**
     * 广播接收器,负责接收BluetoothLeService类发送的数据
     */
    private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            final String action = intent.getAction();
            if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action))//Gatt连接成功
            {
                mConnected = true;
                status = "connected";
                //更新连接状态
                updateConnectionState(status);
                System.out.println("BroadcastReceiver :" + "device connected");

            } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED//Gatt连接失败
                    .equals(action))
            {
                mConnected = false;
                status = "disconnected";
                //更新连接状态
                updateConnectionState(status);
                System.out.println("BroadcastReceiver :"
                        + "device disconnected");

            } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED//发现GATT服务器
                    .equals(action))
            {
                // Show all the supported services and characteristics on the
                // user interface.
                //获取设备的所有蓝牙服务
                displayGattServices(mBluetoothLeService.getSupportedGattServices());
                System.out.println("BroadcastReceiver :"
                        + "device SERVICES_DISCOVERED");
            } else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action))//有效数据
            {
                //处理发送过来的数据
                displayData(intent.getExtras().getString(BluetoothLeService.EXTRA_DATA));
                System.out.println("BroadcastReceiver onData:"
                        + intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
            }
        }
    };
    /* 更新连接状态 */
    private void updateConnectionState(String status)    {
        Message msg = new Message();
        msg.what = 1;
        Bundle b = new Bundle();
        b.putString("connect_state", status);
        msg.setData(b);
        //将连接状态更新的UI的textview上
        myHandler.sendMessage(msg);
        System.out.println("connect_state:" + status);

    }

    /* 意图过滤器 */
    private static IntentFilter makeGattUpdateIntentFilter()    {
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
        intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
        intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
        return intentFilter;
    }

    /**
     * @Title: displayData
     * @Description: TODO(接收到的数据在scrollview上显示)
     * @param @param rev_string(接受的数据)
     * @return void
     * @throws
     */
    private void displayData(String rev_string)    {
        rev_info = rev_string;
        rev_str+="Rec:"+rev_string+"\r\n";
        runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                rev_tv.setText(rev_str);
                rev_sv.scrollTo(0, rev_tv.getMeasuredHeight());
                System.out.println("rev:" + rev_str);
                switch (mCommand)
                {
                    case "DQMM":
                        if(et_pwd.getText().toString().equals(rev_info)) {
                            btn_getip.setEnabled(true);
                        }
                        else
                        {
                            btn_getip.setEnabled(false);
                            btn_setip.setEnabled(false);
                        }
                    break;
                }
            }
        });

    }

    /**
     * @Title: displayGattServices
     * @Description: TODO(处理蓝牙服务)
     * @param
     * @return void
     * @throws
     */
    private void displayGattServices(List<BluetoothGattService> gattServices){

        if (gattServices == null)
            return;
        String uuid = null;
        String unknownServiceString = "unknown_service";
        String unknownCharaString = "unknown_characteristic";

        // 服务数据,可扩展下拉列表的第一级数据
        ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();

        // 特征数据(隶属于某一级服务下面的特征值集合)
        ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData = new ArrayList<ArrayList<HashMap<String, String>>>();

        // 部分层次,所有特征值集合
        mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();

        // Loops through available GATT Services.
        for (BluetoothGattService gattService : gattServices)
        {

            // 获取服务列表
            HashMap<String, String> currentServiceData = new HashMap<String, String>();
            uuid = gattService.getUuid().toString();

            // 查表,根据该uuid获取对应的服务名称。SampleGattAttributes这个表需要自定义。

            gattServiceData.add(currentServiceData);

            System.out.println("Service uuid:" + uuid);

            ArrayList<HashMap<String, String>> gattCharacteristicGroupData = new ArrayList<HashMap<String, String>>();

            // 从当前循环所指向的服务中读取特征值列表
            List<BluetoothGattCharacteristic> gattCharacteristics = gattService
                    .getCharacteristics();

            ArrayList<BluetoothGattCharacteristic> charas = new ArrayList<BluetoothGattCharacteristic>();

            // Loops through available Characteristics.
            // 对于当前循环所指向的服务中的每一个特征值
            for (final BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics)
            {
                charas.add(gattCharacteristic);
                HashMap<String, String> currentCharaData = new HashMap<String, String>();
                uuid = gattCharacteristic.getUuid().toString();

                if (gattCharacteristic.getUuid().toString()
                        .equals(HEART_RATE_MEASUREMENT))
                {
                    // 测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()
                    mhandler.postDelayed(new Runnable()
                    {

                        @Override
                        public void run()
                        {
                            // TODO Auto-generated method stub
                            mBluetoothLeService
                                    .readCharacteristic(gattCharacteristic);
                        }
                    }, 200);

                    // 接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()
                    mBluetoothLeService.setCharacteristicNotification(
                            gattCharacteristic, true);
                    target_chara = gattCharacteristic;
                    // 设置数据内容
                    // 往蓝牙模块写入数据
                    // mBluetoothLeService.writeCharacteristic(gattCharacteristic);
                }
                List<BluetoothGattDescriptor> descriptors = gattCharacteristic
                        .getDescriptors();
                for (BluetoothGattDescriptor descriptor : descriptors)
                {
                    System.out.println("---descriptor UUID:"
                            + descriptor.getUuid());
                    // 获取特征值的描述
                    mBluetoothLeService.getCharacteristicDescriptor(descriptor);
                    // mBluetoothLeService.setCharacteristicNotification(gattCharacteristic,
                    // true);
                }

                gattCharacteristicGroupData.add(currentCharaData);
            }
            // 按先后顺序,分层次放入特征值集合中,只有特征值
            mGattCharacteristics.add(charas);
            // 构件第二级扩展列表(服务下面的特征值)
            gattCharacteristicData.add(gattCharacteristicGroupData);

        }
    }

    /*
     * 发送按键的响应事件,主要发送文本框的数据
     */
    @Override
    public void onClick(View v)
    {
        String mCode="";
        switch(v.getId()) {
            case R.id.btn_getpwd:  //读取密码
                mCode="DQMM";
                rev_str+="Send: 读取密码\r\n";
                break;
            case R.id.btn_getip:  //读取IP
                mCommand="READIP";
                if(rb_ip1.isChecked()) {
                    mCode = "0D0A2121E0";
                }else
                {
                    mCode = "0D0A2121E1";
                }
                rev_str+="Send: 读取IP\r\n";
                break;
            default:
                    break;
        }
        byte[] buff = mCode.toString().getBytes();
        int len = buff.length;
        int[] lens = dataSeparate(len);
        for(int i =0;i<lens[0];i++)
        {
            String str = new String(buff, 20*i, 20);
            target_chara.setValue(str);//只能一次发送20字节,所以这里要分包发送
            //调用蓝牙服务的写特征值方法实现发送数据
            mBluetoothLeService.writeCharacteristic(target_chara);
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                Log.e(TAG, e.toString());
            }
        }
        if(lens[1]!=0)
        {
            String str = new String(buff, 20*lens[0], lens[1]);
            target_chara.setValue(str);
            //调用蓝牙服务的写特征值方法实现发送数据
            mBluetoothLeService.writeCharacteristic(target_chara);

        }
        // TODO Auto-generated method stub

    }
    /**
     * 将数据分包
     *
     * **/
    public int[] dataSeparate(int len)    {
        int[] lens = new int[2];
        lens[0]=len/20;
        lens[1]=len-20*lens[0];
        return lens;
    }
}

cFunction.java

package com.blehc08;

import java.nio.charset.StandardCharsets;

public class cFunction {
    /**
     * 字符串转换unicode
     */
    public static String string2Unicode(String string) {
        StringBuffer unicode = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            char c = string.charAt(i);
            unicode.append("\\u" + Integer.toHexString(c));
        }
        return unicode.toString();
    }

    /**
     * 字符串转化成为16进制字符串
     *
     * @param s
     * @return
     */
    public static String strTo16(String s) {
        String str = "";
        for (int i = 0; i < s.length(); i++) {
            int ch = (int) s.charAt(i);
            String s4 = Integer.toHexString(ch);
            str = str + s4;
        }
        return str;
    }

    /**
     * 16进制转换成为string类型字符串
     *
     * @param s
     * @return
     */
    public static String hexStringToString(String s) {
        if (s == null || s.equals("")) {
            return null;
        }
        s = s.replace(" ", "");
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, StandardCharsets.UTF_8);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }

    /**
     * unicode 转字符串
     */
    public static String unicode2String(String unicode) {
        StringBuffer string = new StringBuffer();
        String[] hex = unicode.split("\\\\u");
        for (int i = 1; i < hex.length; i++) {
            // 转换出每一个代码点
            int data = Integer.parseInt(hex[i], 16);
            // 追加成string
            string.append((char) data);
        }
        return string.toString();
    }

    /**
     * 此方法虽然解决了转化过程中中文乱码的问题,但是过于复杂,笔者后来又发现一种新的转化方式,可直接转化,中文不乱码,
     * 字符串转换成为16进制(无需Unicode编码)
     *
     * @param str
     * @return
     */
    public static String str2HexStr(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder();
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
            // sb.append(' ');
        }
        return sb.toString().trim();
    }

    /**
     * 16进制直接转换成为字符串(无需Unicode解码)
     *
     * @param hexStr
     * @return
     */
    public static String hexStr2Str(String hexStr) {
        String str = "0123456789ABCDEF";
        char[] hexs = hexStr.toCharArray();
        byte[] bytes = new byte[hexStr.length() / 2];
        int n;
        for (int i = 0; i < bytes.length; i++) {
            n = str.indexOf(hexs[2 * i]) * 16;
            n += str.indexOf(hexs[2 * i + 1]);
            bytes[i] = (byte) (n & 0xff);
        }
        return new String(bytes);
    }

    /**
     * @param b 字节数组
     * @return 16进制字符串
     * @throws
     * @Title:bytes2HexString
     * @Description:字节数组转16进制字符串
     */
    public static String bytes2HexString(byte[] b) {
        StringBuffer result = new StringBuffer();
        String hex;
        for (int i = 0; i < b.length; i++) {
            hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            result.append(hex.toUpperCase());
        }
        return result.toString();
    }

    /**
     * @param src 16进制字符串
     * @return 字节数组
     * @throws
     * @Title:hexString2Bytes
     * @Description:16进制字符串转字节数组
     */
    public static byte[] hexString2Bytes1(String src) {
        int l = src.length() / 2;
        byte[] ret = new byte[l];
        for (int i = 0; i < l; i++) {
            ret[i] = Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
        }
        return ret;
    }

    /**
     * 将指定字符串src,以每两个字符分割转换为16进制形式
     * 如:"2B44EFD9" --> byte[]{0x2B, 0x44, 0xEF, 0xD9}
     *
     * @param src String
     * @return byte[]
     **/
    public static byte[] HexString2Bytes2(String src) {
        byte[] ret = new byte[src.length() / 2];
        byte[] tmp = src.getBytes();
        for (int i = 0; i < src.length() / 2; i++) {
            ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
        }
        return ret;
    }
    public static byte uniteBytes(byte src0, byte src1) {
        byte _b0 = Byte.decode("0x" + new String(new byte[]{src0})).byteValue();
        _b0 = (byte) (_b0 << 4);
        byte _b1 = Byte.decode("0x" + new String(new byte[]{src1})).byteValue();
        byte ret = (byte) (_b0 ^ _b1);
        return ret;
    }
    /**
     * @param strPart 字符串
     * @return 16进制字符串
     * @throws
     * @Title:string2HexString
     * @Description:字符串转16进制字符串
     */
    public static String string2HexString(String strPart) {
        StringBuffer hexString = new StringBuffer();
        for (int i = 0; i < strPart.length(); i++) {
            int ch = (int) strPart.charAt(i);
            String strHex = Integer.toHexString(ch);
            hexString.append(strHex);
        }
        return hexString.toString();
    }
    /**
     * @param src
     * @return
     * @throws
     * @Title:char2Byte
     * @Description:字符转成字节数据char-->integer-->byte
     */
    public static Byte char2Byte(Character src) {
        return Integer.valueOf((int) src).byteValue();
    }
    /**
     * @param a   转化数据
     * @param len 占用字节数
     * @return
     * @throws
     * @Title:intToHexString
     * @Description:10进制数字转成16进制
     */
    public static String intToHexString(int a, int len) {
        len <<= 1;
        String hexString = Integer.toHexString(a);
        int b = len - hexString.length();
        if (b > 0) {
            for (int i = 0; i < b; i++) {
                hexString = "0" + hexString;
            }
        }
        return hexString;
    }
    public static String intToHex(int n) {
        //StringBuffer s = new StringBuffer();
        StringBuilder sb = new StringBuilder(8);
        String a;
        char []b = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        while(n != 0){
            sb = sb.append(b[n%16]);
            n = n/16;
        }
        a = sb.reverse().toString();
        return a;
    }
}

box_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">
    <!--顶部设置 -->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="状态:"
            android:layout_marginLeft="10dip"
            />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/connect_state"/>

    </LinearLayout>
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="3dp"
        android:background="@drawable/line" />
    <!--中部指令过程信息-->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1">
        <ScrollView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:id="@+id/rev_sv">
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:id="@+id/rev_tv" />
        </ScrollView>
    </LinearLayout>

    <!--底部按钮设置区域    -->
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="bottom|center"
        android:orientation="vertical">

        <!--查询密码区域    -->
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/btn_bg_default"
            android:orientation="horizontal">
            <TextView
                android:id="@+id/tv_pwd"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="16sp"
                android:text="@string/box_activity_tv_pwd"
                android:layout_marginLeft="3dp"
                android:textColor="#ffffff"/>
            <EditText
                android:id="@+id/et_pwd"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:ems="10"
                android:layout_weight="1.0"
                android:inputType="textPassword" />
            <Button
                android:id="@+id/btn_getpwd"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="3dp"
                android:layout_marginRight="3dp"
                android:textSize="16sp"
                android:background="@drawable/btn_selector"
                android:text="@string/box_activity_btn_getpwd"
                android:textColor="#ffffff"/>
        </LinearLayout>
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="2dp"
            android:background="@drawable/line" />
        <!--ip设置区域    -->
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="3dp"
            android:layout_marginRight="3dp"
            android:background="@drawable/btn_bg_default"
            android:orientation="vertical">
            <!--ip地址区域    -->
                <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="left">
                    <RadioGroup
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:id="@+id/rg_ip"
                        android:layout_marginLeft="3dp"
                        android:orientation="vertical">
                        <RadioButton
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="ip1"
                            android:checked="true"
                            android:textColor="#ffffff"
                            android:id="@+id/rb_ip1"/>
                        <RadioButton
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:text="ip2"
                            android:textColor="#ffffff"
                            android:id="@+id/rb_ip2"/>
                    </RadioGroup>
                <EditText
                    android:id="@+id/local_gw_edit_1"
                    android:layout_toRightOf="@id/rg_ip"
                    android:layout_width="50dp"
                    android:layout_height="wrap_content"
                    android:textColor="#000"
                    android:textSize="15sp"
                    android:layout_marginTop="25dp"
                    android:gravity="bottom"
                    android:singleLine="true"
                    android:inputType="number"
                    android:maxLength="3"
                    android:hint="@string/box_activity_default_gw_hint"/>
                <TextView
                    android:id="@+id/dot_1"
                    android:layout_toRightOf="@id/local_gw_edit_1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/box_activity_dot_tv"
                    android:layout_marginTop="25dp"
                    android:textColor="#000"
                    android:textSize="20sp"
                    android:textStyle="bold"
                    android:singleLine="true"
                    android:layout_alignBottom="@id/local_gw_edit_1"
                    />
                <EditText
                    android:id="@+id/local_gw_edit_2"
                    android:layout_toRightOf="@id/dot_1"
                    android:layout_width="50dp"
                    android:layout_height="wrap_content"
                    android:textColor="#000"
                    android:textSize="15sp"
                    android:layout_marginTop="25dp"
                    android:gravity="bottom"
                    android:singleLine="true"
                    android:inputType="number"
                    android:maxLength="3"
                    android:hint="@string/box_activity_default_gw_hint"/>
                <TextView
                    android:id="@+id/dot_2"
                    android:layout_toRightOf="@id/local_gw_edit_2"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/box_activity_dot_tv"
                    android:layout_marginTop="25dp"
                    android:textColor="#000"
                    android:textSize="20sp"
                    android:textStyle="bold"
                    android:singleLine="true"
                    android:layout_alignBottom="@id/local_gw_edit_1"
                    />
                <EditText
                    android:id="@+id/local_gw_edit_3"
                    android:layout_toRightOf="@id/dot_2"
                    android:layout_width="50dp"
                    android:layout_height="wrap_content"
                    android:textColor="#000"
                    android:textSize="15sp"
                    android:layout_marginTop="25dp"
                    android:gravity="bottom"
                    android:singleLine="true"
                    android:inputType="number"
                    android:maxLength="3"
                    android:hint="@string/box_activity_default_gw_hint"/>
                <TextView
                    android:id="@+id/dot_3"
                    android:layout_toRightOf="@id/local_gw_edit_3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="@string/box_activity_dot_tv"
                    android:layout_marginTop="25dp"
                    android:textColor="#000"
                    android:textSize="20sp"
                    android:textStyle="bold"
                    android:singleLine="true"
                    android:layout_alignBottom="@id/local_gw_edit_1" />
                <EditText
                    android:id="@+id/local_gw_edit_4"
                    android:layout_toRightOf="@id/dot_3"
                    android:layout_width="50dp"
                    android:layout_height="wrap_content"
                    android:textColor="#000"
                    android:textSize="15sp"
                    android:layout_marginTop="25dp"
                    android:gravity="bottom"
                    android:singleLine="true"
                    android:inputType="number"
                    android:maxLength="3"
                    android:hint="@string/box_activity_default_gw_hint"/>

            </RelativeLayout>
            <!--ip端口设置    -->
            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal">
                <TextView
                    android:id="@+id/tv_port"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="16sp"
                    android:textColor="#ffffff"
                    android:layout_marginLeft="3dp"
                    android:text="@string/box_activity_tv_port"/>

                <EditText
                    android:id="@+id/local_gw_port"
                    android:layout_width="231dp"
                    android:layout_height="wrap_content"
                    android:inputType="number"
                    android:maxLength="5"
                    android:text="12345"
                    android:textColor="#000"
                    android:textSize="15sp" />
            </LinearLayout>
        </LinearLayout>
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="2dp"
            android:background="@drawable/line" />
        <!--读取ip设置ip区域    -->
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">

            <Button
                android:id="@+id/btn_getip"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="3dp"
                android:layout_marginRight="3dp"
                android:layout_weight="1.0"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:text="@string/box_activity_btn_getip"
                android:textSize="16sp"
                android:textColor="#ffffff"/>
            <Button
                android:id="@+id/btn_setip"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="3dp"
                android:layout_marginRight="3dp"
                android:layout_weight="1.0"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:text="@string/box_activity_btn_setip"
                android:textSize="16sp"
                android:textColor="#ffffff"/>
        </LinearLayout>

        <!--时间设置区域    -->
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="2dp"
            android:background="@drawable/line" />
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">

            <Button
                android:id="@+id/btn_gettime"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="3dp"
                android:layout_marginRight="3dp"
                android:layout_weight="1.0"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:text="@string/box_activity_btn_gettime"
                android:textSize="16sp"
                android:textColor="@color/btn_text_selector"/>
            <Button
                android:id="@+id/btn_settime"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="3dp"
                android:layout_marginRight="3dp"
                android:layout_weight="1.0"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:text="@string/box_activity_btn_settime"
                android:textSize="16sp"
                android:textColor="#ffffff"/>
        </LinearLayout>
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="2dp"
            android:background="@drawable/line" />
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">
            <Button
                android:id="@+id/btn_shuakamode"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="3dp"
                android:layout_marginRight="3dp"
                android:layout_weight="1.0"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:textColor="#ffffff"
                android:textSize="16sp"
                android:text="@string/box_activity_btn_shuakamode" />

            <Button
                android:id="@+id/btn_mimamode"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="3dp"
                android:layout_weight="1.0"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:textColor="#ffffff"
                android:textSize="16sp"
                android:text="@string/box_activity_btn_mimamode" />
        </LinearLayout>
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="2dp"
            android:background="@drawable/line" />
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">
            <Button
                android:id="@+id/btn_shuakamimamode"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="3dp"
                android:layout_marginRight="3dp"
                android:layout_weight="1.0"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:textColor="#ffffff"
                android:textSize="16sp"
                android:text="@string/box_activity_btn_shuakamimamode" />

        </LinearLayout>
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="2dp"
            android:background="@drawable/line" />
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content">

            <Button
                android:id="@+id/btn_quickmode"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="3dp"
                android:layout_marginRight="3dp"
                android:layout_weight="1.0"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:textColor="#ffffff"
                android:textSize="16sp"
                android:text="@string/box_activity_btn_quickmode" />

            <Button
                android:id="@+id/btn_reset"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="3dp"
                android:layout_weight="1.0"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:textColor="#ffffff"
                android:textSize="16sp"
                android:text="@string/box_activity_btn_reset" />
            <Button
                android:id="@+id/btn_cleandata"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="3dp"
                android:layout_weight="1.0"
                android:background="@drawable/btn_selector"
                android:gravity="center"
                android:textColor="#ffffff"
                android:textSize="16sp"
                android:text="@string/box_activity_btn_cleandata" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

主页面效果图

android 蓝牙 串口 安卓 蓝牙串口_android studio

 

 

设备管理页面

android 蓝牙 串口 安卓 蓝牙串口_java_02

 

 

 

 蓝牙串口接收页面

android 蓝牙 串口 安卓 蓝牙串口_android studio_03