由于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>
主页面效果图
设备管理页面
蓝牙串口接收页面