喂鱼设置状态修改
This commit is contained in:
parent
e49b5b2bf4
commit
28adf72331
|
|
@ -26,5 +26,5 @@ android.enableJetifier=true
|
|||
android.useAndroidX=true
|
||||
android.useDeprecatedNdk=true
|
||||
|
||||
versionCode=43
|
||||
versionName=4.11.3
|
||||
versionCode=45
|
||||
versionName=4.11.5
|
||||
|
|
@ -194,6 +194,12 @@
|
|||
android:exported="false"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/Transparent" />
|
||||
|
||||
<activity
|
||||
android:name=".BlueTooth2Activity"
|
||||
android:exported="false"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/Transparent" />
|
||||
<activity
|
||||
android:name=".NewBindDeviceChoiceActivity"
|
||||
android:exported="false"
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import java.util.ArrayList;
|
|||
* @date 2016-5-20 下午5:29:10
|
||||
*/
|
||||
public class BindTwoDeviceActivity extends BaseActivity {
|
||||
private ImageView iv_camera, iv_device, iv_more, iv_hot, iv_pet,iv_bluetooth;
|
||||
private ImageView iv_camera, iv_device, iv_more, iv_hot, iv_pet,iv_bluetooth,iv_bluetooth2;
|
||||
private int width, height;
|
||||
private WifiAdmin wifiAdmin;
|
||||
private String wifissid = "";
|
||||
|
|
@ -82,6 +82,7 @@ public class BindTwoDeviceActivity extends BaseActivity {
|
|||
iv_hot = findMyViewById(R.id.iv_hot);
|
||||
iv_pet = findMyViewById(R.id.iv_pet);
|
||||
iv_bluetooth = findMyViewById(R.id.iv_bluetooth);
|
||||
iv_bluetooth2 = findMyViewById(R.id.iv_bluetooth2);
|
||||
//得到屏幕宽度按照比例为控件设置高度
|
||||
// double f=width/1.432;
|
||||
// height=(int)f;
|
||||
|
|
@ -100,6 +101,12 @@ public class BindTwoDeviceActivity extends BaseActivity {
|
|||
iv_hot.setOnClickListener(this);
|
||||
iv_pet.setOnClickListener(this);
|
||||
iv_bluetooth.setOnClickListener(this);
|
||||
iv_bluetooth2.setOnClickListener(this);
|
||||
|
||||
if (BuildConfig.DEBUG){
|
||||
iv_bluetooth.setVisibility(View.VISIBLE);
|
||||
iv_bluetooth2.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -249,6 +256,18 @@ public class BindTwoDeviceActivity extends BaseActivity {
|
|||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case R.id.iv_bluetooth2:{
|
||||
Intent intent1 = new Intent();
|
||||
intent1.setClass(BindTwoDeviceActivity.this, BluetoothActivity.class);
|
||||
intent1.putExtra("devicetype", "bluetooth");
|
||||
intent1.putExtra("title", "蓝牙插座");
|
||||
startActivity(intent1);
|
||||
AnimationUtil.startAnimation(BindTwoDeviceActivity.this);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +278,7 @@ public class BindTwoDeviceActivity extends BaseActivity {
|
|||
|
||||
private void toBlueTooth(){
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(BindTwoDeviceActivity.this, BluetoothActivity.class);
|
||||
intent.setClass(BindTwoDeviceActivity.this, BlueTooth2Activity.class);
|
||||
intent.putExtra("devicetype", "bluetooth");
|
||||
intent.putExtra("title", "蓝牙插座");
|
||||
startActivity(intent);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,697 @@
|
|||
package com.ifish.activity;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.ifish.baseclass.BaseActivity;
|
||||
import com.ifish.bluetooth.ClsUtils;
|
||||
import com.ifish.bluetooth.ConnectThread;
|
||||
import com.ifish.bluetooth.ConnectedThread;
|
||||
import com.ifish.bluetooth.LVDevicesAdapter;
|
||||
import com.ifish.utils.L;
|
||||
|
||||
|
||||
public class BlueTooth2Activity extends BaseActivity implements View.OnClickListener {
|
||||
|
||||
private static final String TAG = "BtMain";
|
||||
|
||||
private static final int CONNECT_SUCCESS = 0x01;
|
||||
private static final int CONNECT_FAILURE = 0x02;
|
||||
private static final int DISCONNECT_SUCCESS = 0x03;
|
||||
private static final int SEND_SUCCESS = 0x04;
|
||||
private static final int SEND_FAILURE= 0x05;
|
||||
private static final int RECEIVE_SUCCESS= 0x06;
|
||||
private static final int RECEIVE_FAILURE =0x07;
|
||||
private static final int START_DISCOVERY = 0x08;
|
||||
private static final int STOP_DISCOVERY = 0x09;
|
||||
private static final int DISCOVERY_DEVICE = 0x0A;
|
||||
private static final int DEVICE_BOND_NONE= 0x0B;
|
||||
private static final int DEVICE_BONDING = 0x0C;
|
||||
private static final int DEVICE_BONDED = 0x0D;
|
||||
|
||||
private Button btSearch;
|
||||
private TextView tvCurConState;
|
||||
private TextView tvCurBondState;
|
||||
private TextView tvName;
|
||||
private TextView tvAddress;
|
||||
private Button btConnect;
|
||||
private Button btDisconnect;
|
||||
private Button btBound;
|
||||
private Button btDisBound;
|
||||
private EditText etSendMsg;
|
||||
private Button btSend;
|
||||
private TextView tvSendResult;
|
||||
private TextView tvReceive;
|
||||
private LinearLayout llDeviceList;
|
||||
private LinearLayout llDataSendReceive;
|
||||
private ListView lvDevices;
|
||||
private LVDevicesAdapter lvDevicesAdapter;
|
||||
|
||||
//蓝牙
|
||||
private BluetoothAdapter bluetoothAdapter;
|
||||
private BtBroadcastReceiver btBroadcastReceiver;
|
||||
//连接设备的UUID
|
||||
public static final String MY_BLUETOOTH_UUID = "00001101-0000-1000-8000-00805F9B34FB"; //蓝牙通讯
|
||||
//当前要连接的设备
|
||||
private BluetoothDevice curBluetoothDevice;
|
||||
//发起连接的线程
|
||||
private ConnectThread connectThread;
|
||||
//管理连接的线程
|
||||
private ConnectedThread connectedThread;
|
||||
//当前设备连接状态
|
||||
private boolean curConnState = false;
|
||||
//当前设备与系统配对状态
|
||||
private boolean curBondState = false;
|
||||
|
||||
|
||||
@SuppressLint("HandlerLeak")
|
||||
private Handler mHandler = new Handler(){
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
super.handleMessage(msg);
|
||||
|
||||
switch(msg.what){
|
||||
case START_DISCOVERY:
|
||||
Log.d(TAG, "开始搜索设备...");
|
||||
break;
|
||||
|
||||
case STOP_DISCOVERY:
|
||||
Log.d(TAG, "停止搜索设备...");
|
||||
break;
|
||||
|
||||
case DISCOVERY_DEVICE: //扫描到设备
|
||||
BluetoothDevice bluetoothDevice = (BluetoothDevice) msg.obj;
|
||||
lvDevicesAdapter.addDevice(bluetoothDevice);
|
||||
|
||||
break;
|
||||
|
||||
case CONNECT_FAILURE: //连接失败
|
||||
Log.d(TAG, "连接失败");
|
||||
tvCurConState.setText("连接失败");
|
||||
curConnState = false;
|
||||
break;
|
||||
|
||||
case CONNECT_SUCCESS: //连接成功
|
||||
Log.d(TAG, "连接成功");
|
||||
tvCurConState.setText("连接成功");
|
||||
curConnState = true;
|
||||
llDataSendReceive.setVisibility(View.VISIBLE);
|
||||
llDeviceList.setVisibility(View.GONE);
|
||||
break;
|
||||
|
||||
case DISCONNECT_SUCCESS:
|
||||
tvCurConState.setText("断开成功");
|
||||
curConnState = false;
|
||||
|
||||
break;
|
||||
|
||||
case SEND_FAILURE: //发送失败
|
||||
Toast.makeText(BlueTooth2Activity.this, "发送失败", Toast.LENGTH_SHORT).show();
|
||||
break;
|
||||
|
||||
case SEND_SUCCESS: //发送成功
|
||||
String sendResult = (String) msg.obj;
|
||||
tvSendResult.setText(sendResult);
|
||||
break;
|
||||
|
||||
case RECEIVE_FAILURE: //接收失败
|
||||
String receiveError = (String) msg.obj;
|
||||
tvReceive.setText(receiveError);
|
||||
break;
|
||||
|
||||
case RECEIVE_SUCCESS: //接收成功
|
||||
String receiveResult = (String) msg.obj;
|
||||
tvReceive.setText(receiveResult);
|
||||
break;
|
||||
|
||||
case DEVICE_BOND_NONE: //已解除配对
|
||||
tvCurBondState.setText("解除配对成功");
|
||||
curBondState = false;
|
||||
|
||||
break;
|
||||
|
||||
case DEVICE_BONDING: //正在配对
|
||||
tvCurBondState.setText("正在配对...");
|
||||
break;
|
||||
|
||||
case DEVICE_BONDED: //已配对
|
||||
tvCurBondState.setText("配对成功");
|
||||
curBondState = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.layout_blue2);
|
||||
initTitle("蓝牙选择设备");
|
||||
//初始化视图
|
||||
initView();
|
||||
//初始化监听
|
||||
iniListener();
|
||||
//初始化数据
|
||||
initData();
|
||||
//初始化蓝牙
|
||||
initBluetooth();
|
||||
//初始化蓝牙广播
|
||||
initBtBroadcast();
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
|
||||
|
||||
|
||||
lvDevicesAdapter = new LVDevicesAdapter(BlueTooth2Activity.this);
|
||||
lvDevices.setAdapter(lvDevicesAdapter);
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
btSearch = findViewById(R.id.bt_search);
|
||||
tvCurConState = findViewById(R.id.tv_cur_con_state);
|
||||
tvCurBondState = findViewById(R.id.tv_cur_bond_state);
|
||||
btConnect = findViewById(R.id.bt_connect);
|
||||
btDisconnect = findViewById(R.id.bt_disconnect);
|
||||
btBound = findViewById(R.id.bt_bound);
|
||||
btDisBound = findViewById(R.id.bt_disBound);
|
||||
tvName = findViewById(R.id.tv_name);
|
||||
tvAddress = findViewById(R.id.tv_address);
|
||||
etSendMsg = findViewById(R.id.et_send_msg);
|
||||
btSend = findViewById(R.id.bt_to_send);
|
||||
tvSendResult = findViewById(R.id.tv_send_result);
|
||||
tvReceive = findViewById(R.id.tv_receive_result);
|
||||
llDeviceList = findViewById(R.id.ll_device_list);
|
||||
llDataSendReceive = findViewById(R.id.ll_data_send_receive);
|
||||
lvDevices = findViewById(R.id.lv_devices);
|
||||
}
|
||||
|
||||
private void iniListener() {
|
||||
btSearch.setOnClickListener(this);
|
||||
btConnect.setOnClickListener(this);
|
||||
btDisconnect.setOnClickListener(this);
|
||||
btBound.setOnClickListener(this);
|
||||
btDisBound.setOnClickListener(this);
|
||||
btSend.setOnClickListener(this);
|
||||
|
||||
lvDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
BluetoothDevice bluetoothDevice = (BluetoothDevice) lvDevicesAdapter.getItem(i);
|
||||
tvName.setText(bluetoothDevice.getName());
|
||||
tvAddress.setText(bluetoothDevice.getAddress());
|
||||
curBluetoothDevice = bluetoothDevice;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.bt_search: //搜索蓝牙
|
||||
Toast.makeText(BlueTooth2Activity.this,"",Toast.LENGTH_SHORT).show();
|
||||
llDataSendReceive.setVisibility(View.GONE);
|
||||
llDeviceList.setVisibility(View.VISIBLE);
|
||||
searchBtDevice();
|
||||
break;
|
||||
|
||||
case R.id.bt_connect: //连接蓝牙
|
||||
if(!curConnState) {
|
||||
startConnectDevice(curBluetoothDevice, MY_BLUETOOTH_UUID, 10000);
|
||||
}else{
|
||||
Toast.makeText(this, "当前设备已连接", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
break;
|
||||
|
||||
case R.id.bt_disconnect: //断开连接
|
||||
if(curConnState) {
|
||||
clearConnectedThread();
|
||||
}else{
|
||||
Toast.makeText(this, "当前设备未连接", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
break;
|
||||
|
||||
case R.id.bt_bound: //配对设备
|
||||
if(!curBondState) {
|
||||
boundDevice(curBluetoothDevice);
|
||||
}else{
|
||||
Toast.makeText(this, "当前设备已经与系统蓝牙建立配对", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
break;
|
||||
|
||||
case R.id.bt_disBound: //解除配对
|
||||
if(curBondState) {
|
||||
disBoundDevice(curBluetoothDevice);
|
||||
}else{
|
||||
Toast.makeText(this, "当前设备尚未与系统蓝牙建立配对", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
break;
|
||||
|
||||
case R.id.bt_to_send: //发送数据
|
||||
if(curConnState){
|
||||
String sendMsg = etSendMsg.getText().toString();
|
||||
if(sendMsg.isEmpty()){
|
||||
Toast.makeText(this, "发送数据为空!", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
sendData(sendMsg,true); //以16进制字符串形式发送数据
|
||||
}else{
|
||||
Toast.makeText(this, "请先连接当前设备", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////// 搜索设备 /////////////////////////////////////////////////
|
||||
@SuppressLint("MissingPermission")
|
||||
private void searchBtDevice() {
|
||||
if (bluetoothAdapter.isDiscovering()) { //当前正在搜索设备...
|
||||
return;
|
||||
}
|
||||
//开始搜索
|
||||
bluetoothAdapter.startDiscovery();
|
||||
}
|
||||
|
||||
////////////////////////////////// 配对/接触配对设备 ////////////////////////////////////////////
|
||||
/**
|
||||
* 执行绑定 反射
|
||||
* @param bluetoothDevice 蓝牙设备
|
||||
* @return true 执行绑定 false 未执行绑定
|
||||
*/
|
||||
public boolean boundDevice(BluetoothDevice bluetoothDevice){
|
||||
if(bluetoothDevice == null){
|
||||
Log.e(TAG,"boundDevice-->bluetoothDevice == null");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && false) {
|
||||
L.i(bluetoothDevice.getName()+"jjia--------1--------type="+bluetoothDevice.getType());
|
||||
return bluetoothDevice.createBond();
|
||||
}else {
|
||||
L.i(bluetoothDevice.getName()+"jjia--------2--------type="+bluetoothDevice.getType());
|
||||
// return ClsUtils.createBond(BluetoothDevice.class,bluetoothDevice);
|
||||
return ClsUtils.connn(bluetoothDevice,MY_BLUETOOTH_UUID);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行解绑 反射
|
||||
* @param bluetoothDevice 蓝牙设备
|
||||
* @return true 执行解绑 false未执行解绑
|
||||
*/
|
||||
public boolean disBoundDevice(BluetoothDevice bluetoothDevice){
|
||||
if(bluetoothDevice == null){
|
||||
Log.e(TAG,"disBoundDevice-->bluetoothDevice == null");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return ClsUtils.removeBond(BluetoothDevice.class,bluetoothDevice);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////// 连接设备 ///////////////////////////////////////////////
|
||||
/**
|
||||
* 开始连接设备
|
||||
* @param bluetoothDevice 蓝牙设备
|
||||
* @param uuid 发起连接的UUID
|
||||
* @param conOutTime 连接超时时间
|
||||
*/
|
||||
public void startConnectDevice(final BluetoothDevice bluetoothDevice, String uuid, long conOutTime){
|
||||
if(bluetoothDevice == null){
|
||||
Log.e(TAG,"startConnectDevice-->bluetoothDevice == null");
|
||||
return;
|
||||
}
|
||||
if(bluetoothAdapter == null){
|
||||
Log.e(TAG,"startConnectDevice-->bluetooth3Adapter == null");
|
||||
return;
|
||||
}
|
||||
//发起连接
|
||||
connectThread = new ConnectThread(bluetoothAdapter,curBluetoothDevice,uuid);
|
||||
connectThread.setOnBluetoothConnectListener(new ConnectThread.OnBluetoothConnectListener() {
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
public void onStartConn() {
|
||||
Log.d(TAG,"startConnectDevice-->开始连接..." + bluetoothDevice.getName() + "-->" + bluetoothDevice.getAddress());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onConnSuccess(BluetoothSocket bluetoothSocket) {
|
||||
//移除连接超时
|
||||
mHandler.removeCallbacks(connectOuttimeRunnable);
|
||||
Log.d(TAG,"startConnectDevice-->移除连接超时");
|
||||
Log.w(TAG,"startConnectDevice-->连接成功");
|
||||
|
||||
Message message = new Message();
|
||||
message.what = CONNECT_SUCCESS;
|
||||
mHandler.sendMessage(message);
|
||||
|
||||
//标记当前连接状态为true
|
||||
curConnState = true;
|
||||
//管理连接,收发数据
|
||||
managerConnectSendReceiveData(bluetoothSocket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnFailure(String errorMsg) {
|
||||
Log.e(TAG,"startConnectDevice-->" + errorMsg);
|
||||
|
||||
Message message = new Message();
|
||||
message.what = CONNECT_FAILURE;
|
||||
mHandler.sendMessage(message);
|
||||
|
||||
//标记当前连接状态为false
|
||||
curConnState = false;
|
||||
|
||||
//断开管理连接
|
||||
clearConnectedThread();
|
||||
}
|
||||
});
|
||||
|
||||
connectThread.start();
|
||||
//设置连接超时时间
|
||||
mHandler.postDelayed(connectOuttimeRunnable,conOutTime);
|
||||
|
||||
}
|
||||
|
||||
//连接超时
|
||||
private Runnable connectOuttimeRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.e(TAG,"startConnectDevice-->连接超时" );
|
||||
|
||||
Message message = new Message();
|
||||
message.what = CONNECT_FAILURE;
|
||||
mHandler.sendMessage(message);
|
||||
|
||||
//标记当前连接状态为false
|
||||
curConnState = false;
|
||||
//断开管理连接
|
||||
clearConnectedThread();
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////// 断开连接 //////////////////////////////////////////////
|
||||
/**
|
||||
* 断开已有的连接
|
||||
*/
|
||||
public void clearConnectedThread(){
|
||||
Log.d(TAG,"clearConnectedThread-->即将断开");
|
||||
|
||||
//connectedThread断开已有连接
|
||||
if(connectedThread == null){
|
||||
Log.e(TAG,"clearConnectedThread-->connectedThread == null");
|
||||
return;
|
||||
}
|
||||
connectedThread.terminalClose(connectThread);
|
||||
|
||||
//等待线程运行完后再断开
|
||||
mHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
connectedThread.cancel(); //释放连接
|
||||
|
||||
connectedThread = null;
|
||||
}
|
||||
},10);
|
||||
|
||||
Log.w(TAG,"clearConnectedThread-->成功断开连接");
|
||||
Message message = new Message();
|
||||
message.what = DISCONNECT_SUCCESS;
|
||||
mHandler.sendMessage(message);
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////// 管理已有连接、收发数据 //////////////////////////////////
|
||||
|
||||
/**
|
||||
* 管理已建立的连接,收发数据
|
||||
* @param bluetoothSocket 已建立的连接
|
||||
*/
|
||||
public void managerConnectSendReceiveData(BluetoothSocket bluetoothSocket){
|
||||
//管理已有连接
|
||||
connectedThread = new ConnectedThread(bluetoothSocket);
|
||||
connectedThread.start();
|
||||
connectedThread.setOnSendReceiveDataListener(new ConnectedThread.OnSendReceiveDataListener() {
|
||||
@Override
|
||||
public void onSendDataSuccess(byte[] data) {
|
||||
Log.w(TAG,"发送数据成功,长度" + data.length + "->" + bytes2HexString(data,data.length));
|
||||
Message message = new Message();
|
||||
message.what = SEND_SUCCESS;
|
||||
message.obj = "发送数据成功,长度" + data.length + "->" + bytes2HexString(data,data.length);
|
||||
mHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendDataError(byte[] data,String errorMsg) {
|
||||
Log.e(TAG,"发送数据出错,长度" + data.length + "->" + bytes2HexString(data,data.length));
|
||||
Message message = new Message();
|
||||
message.what = SEND_FAILURE;
|
||||
message.obj = "发送数据出错,长度" + data.length + "->" + bytes2HexString(data,data.length);
|
||||
mHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveDataSuccess(byte[] buffer) {
|
||||
Log.w(TAG,"成功接收数据,长度" + buffer.length + "->" + bytes2HexString(buffer,buffer.length));
|
||||
Message message = new Message();
|
||||
message.what = RECEIVE_SUCCESS;
|
||||
message.obj = "成功接收数据,长度" + buffer.length + "->" + bytes2HexString(buffer,buffer.length);
|
||||
mHandler.sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceiveDataError(String errorMsg) {
|
||||
Log.e(TAG,"接收数据出错:" + errorMsg);
|
||||
Message message = new Message();
|
||||
message.what = RECEIVE_FAILURE;
|
||||
message.obj = "接收数据出错:" + errorMsg;
|
||||
mHandler.sendMessage(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
///////////////////////////////// 发送数据 /////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 发送数据
|
||||
* @param data 要发送的数据 字符串
|
||||
* @param isHex 是否是16进制字符串
|
||||
* @return true 发送成功 false 发送失败
|
||||
*/
|
||||
public boolean sendData(String data,boolean isHex){
|
||||
if(connectedThread == null){
|
||||
Log.e(TAG,"sendData:string -->connectedThread == null");
|
||||
return false;
|
||||
}
|
||||
if(data == null || data.length() == 0){
|
||||
Log.e(TAG,"sendData:string-->要发送的数据为空");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isHex){ //是16进制字符串
|
||||
data.replace(" ",""); //取消空格
|
||||
//检查16进制数据是否合法
|
||||
if(data.length() % 2 != 0){
|
||||
//不合法,最后一位自动填充0
|
||||
String lasts = "0" + data.charAt(data.length() - 1);
|
||||
data = data.substring(0,data.length() - 2) + lasts;
|
||||
}
|
||||
Log.d(TAG,"sendData:string -->准备写入:" + data); //加空格显示
|
||||
return connectedThread.write(hexString2Bytes(data));
|
||||
}
|
||||
|
||||
//普通字符串
|
||||
Log.d(TAG,"sendData:string -->准备写入:" + data);
|
||||
return connectedThread.write(data.getBytes());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////// 数据类型转换 //////////////////////////////////////////////
|
||||
/**
|
||||
* 字节数组-->16进制字符串
|
||||
* @param b 字节数组
|
||||
* @param length 字节数组长度
|
||||
* @return 16进制字符串 有空格类似“0A D5 CD 8F BD E5 F8”
|
||||
*/
|
||||
public static String bytes2HexString(byte[] b, int length) {
|
||||
StringBuffer result = new StringBuffer();
|
||||
String hex;
|
||||
for (int i = 0; i < length; i++) {
|
||||
hex = Integer.toHexString(b[i] & 0xFF);
|
||||
if (hex.length() == 1) {
|
||||
hex = '0' + hex;
|
||||
}
|
||||
result.append(hex.toUpperCase()).append(" ");
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* hexString2Bytes
|
||||
* 16进制字符串-->字节数组
|
||||
* @param src 16进制字符串
|
||||
* @return 字节数组
|
||||
*/
|
||||
public static byte[] hexString2Bytes(String src) {
|
||||
int l = src.length() / 2;
|
||||
byte[] ret = new byte[l];
|
||||
for (int i = 0; i < l; i++) {
|
||||
ret[i] = (byte) Integer
|
||||
.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* 初始化蓝牙
|
||||
*/
|
||||
@SuppressLint("MissingPermission")
|
||||
private void initBluetooth() {
|
||||
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (bluetoothAdapter == null) {
|
||||
Toast.makeText(this, "当前手机设备不支持蓝牙", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
//手机设备支持蓝牙,判断蓝牙是否已开启
|
||||
if (bluetoothAdapter.isEnabled()) {
|
||||
Toast.makeText(this, "手机蓝牙已开启", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
//蓝牙没有打开,去打开蓝牙。推荐使用第二种打开蓝牙方式
|
||||
//第一种方式:直接打开手机蓝牙,没有任何提示
|
||||
// bluetoothAdapter.enable(); //BLUETOOTH_ADMIN权限
|
||||
//第二种方式:友好提示用户打开蓝牙
|
||||
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
||||
startActivity(enableBtIntent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化蓝牙广播
|
||||
*/
|
||||
private void initBtBroadcast() {
|
||||
//注册广播接收
|
||||
btBroadcastReceiver = new BtBroadcastReceiver();
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); //开始扫描
|
||||
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//扫描结束
|
||||
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//搜索到设备
|
||||
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //配对状态监听
|
||||
registerReceiver(btBroadcastReceiver,intentFilter);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
//注销广播接收
|
||||
unregisterReceiver(btBroadcastReceiver);
|
||||
}
|
||||
|
||||
/**
|
||||
* 蓝牙广播接收器
|
||||
*/
|
||||
private class BtBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (TextUtils.equals(action, BluetoothAdapter.ACTION_DISCOVERY_STARTED)) { //开启搜索
|
||||
Log.d(TAG,"开启搜索...");
|
||||
Message message = new Message();
|
||||
message.what = START_DISCOVERY;
|
||||
mHandler.sendMessage(message);
|
||||
|
||||
} else if (TextUtils.equals(action, BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {//完成搜素
|
||||
Log.d(TAG,"停止搜索...");
|
||||
Message message = new Message();
|
||||
message.what = STOP_DISCOVERY;
|
||||
mHandler.sendMessage(message);
|
||||
|
||||
} else if (TextUtils.equals(action, BluetoothDevice.ACTION_FOUND)) { //3.0搜索到设备
|
||||
//蓝牙设备
|
||||
BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
//信号强度
|
||||
int rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
|
||||
|
||||
Log.w(TAG, "扫描到设备:" + bluetoothDevice.getName() + "-->" + bluetoothDevice.getAddress());
|
||||
Message message = new Message();
|
||||
message.what = DISCOVERY_DEVICE;
|
||||
message.obj = bluetoothDevice;
|
||||
mHandler.sendMessage(message);
|
||||
|
||||
}else if(TextUtils.equals(action,BluetoothDevice.ACTION_BOND_STATE_CHANGED)){
|
||||
BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
int bondSate = bluetoothDevice.getBondState();
|
||||
L.i(bluetoothDevice.getName()+"jjia----------------bondSate="+bondSate);
|
||||
switch(bondSate) {
|
||||
case BluetoothDevice.BOND_NONE:
|
||||
Log.d(TAG, "已解除配对");
|
||||
Message message1 = new Message();
|
||||
message1.what = DEVICE_BOND_NONE;
|
||||
mHandler.sendMessage(message1);
|
||||
break;
|
||||
|
||||
case BluetoothDevice.BOND_BONDING:
|
||||
Log.d(TAG, "正在配对...");
|
||||
Message message2 = new Message();
|
||||
message2.what = DEVICE_BONDING;
|
||||
mHandler.sendMessage(message2);
|
||||
break;
|
||||
|
||||
case BluetoothDevice.BOND_BONDED:
|
||||
Log.d(TAG, "已配对");
|
||||
Message message3 = new Message();
|
||||
message3.what = DEVICE_BONDED;
|
||||
mHandler.sendMessage(message3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ import android.widget.TextView;
|
|||
|
||||
import com.ifish.adapter.BlueToothController;
|
||||
import com.ifish.baseclass.BaseActivity;
|
||||
import com.ifish.bluetooth.ClsUtils;
|
||||
import com.ifish.utils.BlueToothUtil;
|
||||
import com.ifish.utils.L;
|
||||
import com.ifish.utils.ToastUtil;
|
||||
|
|
@ -26,7 +27,7 @@ import com.ifish.utils.ToastUtil;
|
|||
public class BluetoothActivity extends BaseActivity {
|
||||
|
||||
BlueToothController blueToothController = new BlueToothController();
|
||||
|
||||
public static final String MY_BLUETOOTH_UUID = "00001101-0000-1000-8000-00805F9B34FB"; //蓝牙通讯
|
||||
IntentFilter foundFilter = null;
|
||||
TextView name ;
|
||||
Button tv_pair;
|
||||
|
|
@ -50,7 +51,14 @@ public class BluetoothActivity extends BaseActivity {
|
|||
@Override
|
||||
public void onClick(View view) {
|
||||
if (bluetoothDevice!=null){
|
||||
BlueToothUtil.Companion.boundDevice(bluetoothDevice);
|
||||
try {
|
||||
|
||||
L.i("jjia---------getBondState----"+bluetoothDevice.getBondState());
|
||||
ClsUtils.createBond1( bluetoothDevice);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
// BlueToothUtil.Companion.boundDevice(bluetoothDevice,MY_BLUETOOTH_UUID);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -75,7 +83,7 @@ public class BluetoothActivity extends BaseActivity {
|
|||
if (!TextUtils.isEmpty(deviceName) &&
|
||||
(
|
||||
// deviceName.contains("ifishly") ||
|
||||
deviceName.equals("ifishly-fee0")
|
||||
deviceName.startsWith("ifishly")
|
||||
// deviceName.contains("LE-Bose")
|
||||
|
||||
)
|
||||
|
|
|
|||
|
|
@ -416,22 +416,22 @@ public class FeedFishSettingActivity extends BaseActivity {
|
|||
}else if(v == add_rel_setting){ //添加关联设备
|
||||
showTimeSelected();
|
||||
}else if(v == rl_xunhuan_bang){ //循环泵
|
||||
showOpenOrCloseDialog(4,R.drawable.xunhuanbang,"循环泵",event.isLight_status1());
|
||||
showOpenOrCloseDialog(4,R.drawable.xunhuanbang,"循环泵",event.isLight_status4());
|
||||
}else if(v == rl_zengyang_bang){ //增氧泵
|
||||
String type = Commons.DEVICE.get(Commons.DevicePosition).type;
|
||||
if(Device.TYPE_5F.equals(type)){ //海水
|
||||
showOpenOrCloseDialog(1,R.drawable.addobang,"蛋分器",event.isLight_status2());
|
||||
showOpenOrCloseDialog(1,R.drawable.addobang,"蛋分器",event.isLight_status1());
|
||||
}else{ //淡水
|
||||
showOpenOrCloseDialog(1,R.drawable.addobang,"增氧泵",event.isLight_status2());
|
||||
showOpenOrCloseDialog(1,R.drawable.addobang,"增氧泵",event.isLight_status1());
|
||||
}
|
||||
}else if(v == rl_light1){ //灯光1
|
||||
showOpenOrCloseDialog(2,R.drawable.linght1,"灯光1",event.isLight_status3());
|
||||
showOpenOrCloseDialog(2,R.drawable.linght1,"灯光1",event.isLight_status2());
|
||||
}else if(v == rl_light2){ //灯光2
|
||||
showOpenOrCloseDialog(3,R.drawable.linght2,"灯光2",event.isLight_status4());
|
||||
showOpenOrCloseDialog(3,R.drawable.linght2,"灯光2",event.isLight_status3());
|
||||
}else if(v == rl_zaolangbang){ //造浪泵
|
||||
showOpenOrCloseDialog(6,R.drawable.zaolangbang,"造浪泵",event.isLight_status5());
|
||||
showOpenOrCloseDialog(6,R.drawable.zaolangbang,"造浪泵",event.isLight_status6());
|
||||
}else if(v == rl_shajun_light){ //杀菌灯
|
||||
showOpenOrCloseDialog(5,R.drawable.shajundeng,"杀菌灯",event.isLight_status6());
|
||||
showOpenOrCloseDialog(5,R.drawable.shajundeng,"杀菌灯",event.isLight_status5());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,13 +28,10 @@ public class BlueToothController {
|
|||
}
|
||||
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
public void open(Activity activity) {
|
||||
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
|
||||
if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
||||
|
||||
ToastUtil.show(activity,"请");
|
||||
return;
|
||||
}
|
||||
// Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
|
||||
activity.startActivityForResult(intent, 11);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
package com.ifish.bluetooth;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.util.Log;
|
||||
|
||||
import com.ifish.utils.L;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ClsUtils {
|
||||
|
||||
public static BluetoothDevice remoteDevice = null;
|
||||
|
||||
/**
|
||||
* 与设备配对 参考源码:platform/packages/apps/Settings.git
|
||||
* /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
|
||||
*/
|
||||
@SuppressLint("MissingPermission")
|
||||
static public boolean connn(BluetoothDevice btDevice,String uuid){
|
||||
try {
|
||||
BluetoothSocket socket = btDevice.createInsecureRfcommSocketToServiceRecord(UUID.fromString(uuid));
|
||||
socket.connect();
|
||||
|
||||
return true;
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static public boolean createBond1(BluetoothDevice btDevice)
|
||||
throws Exception {
|
||||
Method createBondMethod = btDevice.getClass().getMethod("createBond");
|
||||
Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
|
||||
return returnValue.booleanValue();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static public boolean createBond(@SuppressWarnings("rawtypes") Class btClass, BluetoothDevice btDevice)
|
||||
throws Exception {
|
||||
Method createBondMethod = btClass.getMethod("createBond");
|
||||
Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
|
||||
return returnValue.booleanValue();
|
||||
}
|
||||
|
||||
//自动配对设置Pin值
|
||||
static public boolean autoBond(Class btClass,BluetoothDevice device,String strPin) throws Exception {
|
||||
Method autoBondMethod = btClass.getMethod("setPin",new Class[]{byte[].class});
|
||||
Boolean result = (Boolean)autoBondMethod.invoke(device,new Object[]{strPin.getBytes()});
|
||||
return result;
|
||||
}
|
||||
|
||||
static public void setPairingConfirmation(BluetoothDevice device){
|
||||
try {
|
||||
Field field = device.getClass().getDeclaredField("sService");
|
||||
field.setAccessible(true);
|
||||
|
||||
Object service = field.get(device);
|
||||
Method method = service.getClass().getDeclaredMethod("setPairingConfirmation",
|
||||
BluetoothDevice.class, boolean.class);
|
||||
method.setAccessible(true);
|
||||
method.invoke(service, device, true);
|
||||
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 与设备解除配对 参考源码:platform/packages/apps/Settings.git
|
||||
* /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static public boolean removeBond(Class btClass, BluetoothDevice btDevice)
|
||||
throws Exception {
|
||||
Method removeBondMethod = btClass.getMethod("removeBond");
|
||||
Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
|
||||
return returnValue.booleanValue();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static public boolean setPin(Class btClass, BluetoothDevice btDevice,
|
||||
String str) throws Exception {
|
||||
try {
|
||||
Method removeBondMethod = btClass.getDeclaredMethod("setPin",
|
||||
new Class[]
|
||||
{byte[].class});
|
||||
Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice,
|
||||
new Object[]
|
||||
{str.getBytes()});
|
||||
} catch (SecurityException e) {
|
||||
// throw new RuntimeException(e.getMessage());
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// throw new RuntimeException(e.getMessage());
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// 取消用户输入
|
||||
//cancelPairingUserInput()取消用户输入密钥框,
|
||||
// 个人觉得一般情况下不要和
|
||||
// setPin(setPasskey、setPairingConfirmation、 setRemoteOutOfBandData)一起用,
|
||||
// 这几个方法都会remove掉map里面的key:value(也就是互斥的 )
|
||||
@SuppressWarnings("unchecked")
|
||||
static public boolean cancelPairingUserInput(Class btClass,
|
||||
BluetoothDevice device)
|
||||
|
||||
throws Exception {
|
||||
Method createBondMethod = btClass.getMethod("cancelPairingUserInput");
|
||||
// cancelBondProcess()
|
||||
Boolean returnValue = (Boolean) createBondMethod.invoke(device);
|
||||
|
||||
return returnValue.booleanValue();
|
||||
}
|
||||
|
||||
// 取消配对
|
||||
@SuppressWarnings("unchecked")
|
||||
static public boolean cancelBondProcess(Class btClass,
|
||||
BluetoothDevice device)
|
||||
throws Exception {
|
||||
Method createBondMethod = btClass.getMethod("cancelBondProcess");
|
||||
Boolean returnValue = (Boolean) createBondMethod.invoke(device);
|
||||
return returnValue.booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clsShow
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static public void printAllInform(Class clsShow) {
|
||||
try {
|
||||
// 取得所有方法
|
||||
Method[] hideMethod = clsShow.getMethods();
|
||||
int i = 0;
|
||||
for (; i < hideMethod.length; i++) {
|
||||
//Log.e("method name", hideMethod.getName() + ";and the i is:"
|
||||
// + i);
|
||||
}
|
||||
// 取得所有常量
|
||||
Field[] allFields = clsShow.getFields();
|
||||
for (i = 0; i < allFields.length; i++) {
|
||||
//Log.e("Field name", allFields.getName());
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
// throw new RuntimeException(e.getMessage());
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// throw new RuntimeException(e.getMessage());
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the internal cache and forces a refresh of the services from the * remote device.
|
||||
*/
|
||||
public static boolean refreshDeviceCache(BluetoothGatt mBluetoothGatt) {
|
||||
if (mBluetoothGatt != null) {
|
||||
try {
|
||||
BluetoothGatt localBluetoothGatt = mBluetoothGatt;
|
||||
Method localMethod = localBluetoothGatt.getClass().getMethod("refresh", new Class[0]);
|
||||
if (localMethod != null) {
|
||||
boolean bool = ((Boolean) localMethod.invoke(localBluetoothGatt, new Object[0])).booleanValue();
|
||||
return bool;
|
||||
}
|
||||
} catch (Exception localException) {
|
||||
Log.i("Config", "An exception occured while refreshing device");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
package com.ifish.bluetooth;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
/**
|
||||
* 发起蓝牙连接
|
||||
*/
|
||||
public class ConnectThread extends Thread {
|
||||
private static final String TAG = "ConnectThread";
|
||||
private final BluetoothAdapter mBluetoothAdapter;
|
||||
private BluetoothSocket mmSocket;
|
||||
private final BluetoothDevice mmDevice;
|
||||
|
||||
public ConnectThread(BluetoothAdapter bluetoothAdapter,BluetoothDevice bluetoothDevice,String uuid) {
|
||||
this.mBluetoothAdapter = bluetoothAdapter;
|
||||
this.mmDevice = bluetoothDevice;
|
||||
|
||||
//使用一个临时变量,等会赋值给mmSocket
|
||||
//因为mmSocket是静态的
|
||||
BluetoothSocket tmp = null ;
|
||||
|
||||
if(mmSocket != null){
|
||||
Log.e(TAG,"ConnectThread-->mmSocket != null先去释放");
|
||||
try {
|
||||
mmSocket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Log.d(TAG,"ConnectThread-->mmSocket != null已释放");
|
||||
|
||||
//1、获取BluetoothSocket
|
||||
try {
|
||||
//建立安全的蓝牙连接,会弹出配对框
|
||||
tmp = mmDevice.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG,"ConnectThread-->获取BluetoothSocket异常!" + e.getMessage());
|
||||
}
|
||||
|
||||
mmSocket = tmp;
|
||||
if(mmSocket != null){
|
||||
Log.w(TAG,"ConnectThread-->已获取BluetoothSocket");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(){
|
||||
|
||||
//连接之前先取消发现设备,否则会大幅降低连接尝试的速度,并增加连接失败的可能性
|
||||
if(mBluetoothAdapter == null){
|
||||
Log.e(TAG,"ConnectThread:run-->mBluetoothAdapter == null");
|
||||
return;
|
||||
}
|
||||
//取消发现设备
|
||||
if(mBluetoothAdapter.isDiscovering()){
|
||||
mBluetoothAdapter.cancelDiscovery();
|
||||
}
|
||||
|
||||
if(mmSocket == null){
|
||||
Log.e(TAG,"ConnectThread:run-->mmSocket == null");
|
||||
return;
|
||||
}
|
||||
|
||||
//2、通过socket去连接设备
|
||||
try {
|
||||
Log.d(TAG,"ConnectThread:run-->去连接...");
|
||||
if(onBluetoothConnectListener != null){
|
||||
onBluetoothConnectListener.onStartConn(); //开始去连接回调
|
||||
}
|
||||
mmSocket.connect(); //connect()为阻塞调用,连接失败或 connect() 方法超时(大约 12 秒之后),它将会引发异常
|
||||
|
||||
if(onBluetoothConnectListener != null){
|
||||
onBluetoothConnectListener.onConnSuccess(mmSocket); //连接成功回调
|
||||
Log.w(TAG,"ConnectThread:run-->连接成功");
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG,"ConnectThread:run-->连接异常!" + e.getMessage());
|
||||
|
||||
if(onBluetoothConnectListener != null){
|
||||
onBluetoothConnectListener.onConnFailure("连接异常:" + e.getMessage());
|
||||
}
|
||||
|
||||
//释放
|
||||
cancel();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放
|
||||
*/
|
||||
public void cancel() {
|
||||
try {
|
||||
if (mmSocket != null && mmSocket.isConnected()) {
|
||||
Log.d(TAG,"ConnectThread:cancel-->mmSocket.isConnected() = " + mmSocket.isConnected());
|
||||
mmSocket.close();
|
||||
mmSocket = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mmSocket != null) {
|
||||
mmSocket.close();
|
||||
mmSocket = null;
|
||||
}
|
||||
|
||||
Log.d(TAG,"ConnectThread:cancel-->关闭已连接的套接字释放资源");
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG,"ConnectThread:cancel-->关闭已连接的套接字释放资源异常!" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private OnBluetoothConnectListener onBluetoothConnectListener;
|
||||
|
||||
public void setOnBluetoothConnectListener(OnBluetoothConnectListener onBluetoothConnectListener) {
|
||||
this.onBluetoothConnectListener = onBluetoothConnectListener;
|
||||
}
|
||||
|
||||
//连接状态监听者
|
||||
public interface OnBluetoothConnectListener{
|
||||
void onStartConn(); //开始连接
|
||||
void onConnSuccess(BluetoothSocket bluetoothSocket); //连接成功
|
||||
void onConnFailure(String errorMsg); //连接失败
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
package com.ifish.bluetooth;
|
||||
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
* 管理连接
|
||||
* 1、发送数据
|
||||
* 2、接收数据
|
||||
*/
|
||||
public class ConnectedThread extends Thread{
|
||||
private static final String TAG = "ConnectedThread";
|
||||
private BluetoothSocket mmSocket;
|
||||
private InputStream mmInStream;
|
||||
private OutputStream mmOutStream;
|
||||
//是否是主动断开
|
||||
private boolean isStop = false;
|
||||
//发起蓝牙连接的线程
|
||||
private ConnectThread connectThread;
|
||||
|
||||
public void terminalClose(ConnectThread connectThread){
|
||||
isStop = true;
|
||||
this.connectThread = connectThread;
|
||||
}
|
||||
|
||||
public ConnectedThread(BluetoothSocket socket){
|
||||
mmSocket = socket;
|
||||
|
||||
InputStream tmpIn = null;
|
||||
OutputStream tmpOut = null;
|
||||
|
||||
//使用临时对象获取输入和输出流,因为成员流是静态类型
|
||||
|
||||
//1、获取 InputStream 和 OutputStream
|
||||
try {
|
||||
tmpIn = socket.getInputStream();
|
||||
tmpOut = socket.getOutputStream();
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG,"ConnectedThread-->获取InputStream 和 OutputStream异常!");
|
||||
}
|
||||
|
||||
mmInStream = tmpIn;
|
||||
mmOutStream = tmpOut;
|
||||
|
||||
if(mmInStream != null){
|
||||
Log.d(TAG,"ConnectedThread-->已获取InputStream");
|
||||
}
|
||||
|
||||
if(mmOutStream != null){
|
||||
Log.d(TAG,"ConnectedThread-->已获取OutputStream");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void run(){
|
||||
//最大缓存区 存放流
|
||||
byte[] buffer = new byte[1024 * 2]; //buffer store for the stream
|
||||
//从流的read()方法中读取的字节数
|
||||
int bytes = 0; //bytes returned from read()
|
||||
|
||||
//持续监听输入流直到发生异常
|
||||
while(!isStop){
|
||||
try {
|
||||
|
||||
if(mmInStream == null){
|
||||
Log.e(TAG,"ConnectedThread:run-->输入流mmInStream == null");
|
||||
break;
|
||||
}
|
||||
//先判断是否有数据,有数据再读取
|
||||
if(mmInStream.available() != 0){
|
||||
//2、接收数据
|
||||
bytes = mmInStream.read(buffer); //从(mmInStream)输入流中(读取内容)读取的一定数量字节数,并将它们存储到缓冲区buffer数组中,bytes为实际读取的字节数
|
||||
byte[] b = Arrays.copyOf(buffer,bytes); //存放实际读取的数据内容
|
||||
Log.w(TAG,"ConnectedThread:run-->收到消息,长度" + b.length + "->" + bytes2HexString(b, b.length)); //有空格的16进制字符串
|
||||
if(onSendReceiveDataListener != null){
|
||||
onSendReceiveDataListener.onReceiveDataSuccess(b); //成功收到消息
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG,"ConnectedThread:run-->接收消息异常!" + e.getMessage());
|
||||
if(onSendReceiveDataListener != null){
|
||||
onSendReceiveDataListener.onReceiveDataError("接收消息异常:" + e.getMessage()); //接收消息异常
|
||||
}
|
||||
//关闭流和socket
|
||||
boolean isClose = cancel();
|
||||
if(isClose){
|
||||
Log.e(TAG,"ConnectedThread:run-->接收消息异常,成功断开连接!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
//关闭流和socket
|
||||
boolean isClose = cancel();
|
||||
if(isClose){
|
||||
Log.d(TAG,"ConnectedThread:run-->接收消息结束,断开连接!");
|
||||
}
|
||||
}
|
||||
|
||||
//发送数据
|
||||
public boolean write(byte[] bytes){
|
||||
try {
|
||||
|
||||
if(mmOutStream == null){
|
||||
Log.e(TAG, "mmOutStream == null");
|
||||
return false;
|
||||
}
|
||||
|
||||
//发送数据
|
||||
mmOutStream.write(bytes);
|
||||
Log.d(TAG, "写入成功:"+ bytes2HexString(bytes, bytes.length));
|
||||
if(onSendReceiveDataListener != null){
|
||||
onSendReceiveDataListener.onSendDataSuccess(bytes); //发送数据成功回调
|
||||
}
|
||||
return true;
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "写入失败:"+ bytes2HexString(bytes, bytes.length));
|
||||
if(onSendReceiveDataListener != null){
|
||||
onSendReceiveDataListener.onSendDataError(bytes,"写入失败"); //发送数据失败回调
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放
|
||||
* @return true 断开成功 false 断开失败
|
||||
*/
|
||||
public boolean cancel(){
|
||||
try {
|
||||
if(mmInStream != null){
|
||||
mmInStream.close(); //关闭输入流
|
||||
}
|
||||
if(mmOutStream != null){
|
||||
mmOutStream.close(); //关闭输出流
|
||||
}
|
||||
if(mmSocket != null){
|
||||
mmSocket.close(); //关闭socket
|
||||
}
|
||||
if(connectThread != null){
|
||||
connectThread.cancel();
|
||||
}
|
||||
|
||||
connectThread = null;
|
||||
mmInStream = null;
|
||||
mmOutStream = null;
|
||||
mmSocket = null;
|
||||
|
||||
Log.w(TAG,"ConnectedThread:cancel-->成功断开连接");
|
||||
return true;
|
||||
|
||||
} catch (IOException e) {
|
||||
// 任何一部分报错,都将强制关闭socket连接
|
||||
mmInStream = null;
|
||||
mmOutStream = null;
|
||||
mmSocket = null;
|
||||
|
||||
Log.e(TAG, "ConnectedThread:cancel-->断开连接异常!" + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 字节数组-->16进制字符串
|
||||
* @param b 字节数组
|
||||
* @param length 字节数组长度
|
||||
* @return 16进制字符串 有空格类似“0A D5 CD 8F BD E5 F8”
|
||||
*/
|
||||
public static String bytes2HexString(byte[] b, int length) {
|
||||
StringBuffer result = new StringBuffer();
|
||||
String hex;
|
||||
for (int i = 0; i < length; i++) {
|
||||
hex = Integer.toHexString(b[i] & 0xFF);
|
||||
if (hex.length() == 1) {
|
||||
hex = '0' + hex;
|
||||
}
|
||||
result.append(hex.toUpperCase()).append(" ");
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private OnSendReceiveDataListener onSendReceiveDataListener;
|
||||
|
||||
public void setOnSendReceiveDataListener(OnSendReceiveDataListener onSendReceiveDataListener) {
|
||||
this.onSendReceiveDataListener = onSendReceiveDataListener;
|
||||
}
|
||||
|
||||
//收发数据监听者
|
||||
public interface OnSendReceiveDataListener{
|
||||
void onSendDataSuccess(byte[] data); //发送数据结束
|
||||
void onSendDataError(byte[] data, String errorMsg); //发送数据出错
|
||||
void onReceiveDataSuccess(byte[] buffer); //接收到数据
|
||||
void onReceiveDataError(String errorMsg); //接收数据出错
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
package com.ifish.bluetooth;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.ifish.activity.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 搜索到的设备列表适配器
|
||||
*/
|
||||
public class LVDevicesAdapter extends BaseAdapter {
|
||||
|
||||
private Context context;
|
||||
private List<BluetoothDevice> list;
|
||||
|
||||
public LVDevicesAdapter(Context context) {
|
||||
this.context = context;
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return list == null ? 0 : list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int i) {
|
||||
if(list == null){
|
||||
return null;
|
||||
}
|
||||
return list.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int i, View view, ViewGroup viewGroup) {
|
||||
DeviceViewHolder viewHolder;
|
||||
if(view == null){
|
||||
view = LayoutInflater.from(context).inflate(R.layout.layout_lv_devices_item,null);
|
||||
viewHolder = new DeviceViewHolder();
|
||||
viewHolder.tvDeviceName = view.findViewById(R.id.tv_device_name);
|
||||
viewHolder.tvDeviceAddress = view.findViewById(R.id.tv_device_address);
|
||||
view.setTag(viewHolder);
|
||||
}else{
|
||||
viewHolder = (DeviceViewHolder) view.getTag();
|
||||
}
|
||||
|
||||
if(list.get(i).getName() == null){
|
||||
viewHolder.tvDeviceName.setText("NULL");
|
||||
}else{
|
||||
viewHolder.tvDeviceName.setText(list.get(i).getName());
|
||||
}
|
||||
|
||||
viewHolder.tvDeviceAddress.setText(list.get(i).getAddress());
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化所有设备列表
|
||||
* @param bluetoothDevices
|
||||
*/
|
||||
public void addAllDevice(List<BluetoothDevice> bluetoothDevices){
|
||||
if(list != null){
|
||||
list.clear();
|
||||
}
|
||||
for (BluetoothDevice bluetoothDevice : bluetoothDevices) {
|
||||
list.add(bluetoothDevice);
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加列表子项
|
||||
* @param bluetoothDevice
|
||||
*/
|
||||
public void addDevice(BluetoothDevice bluetoothDevice){
|
||||
if(list == null){
|
||||
return;
|
||||
}
|
||||
if(!list.contains(bluetoothDevice)){
|
||||
list.add(bluetoothDevice);
|
||||
}
|
||||
notifyDataSetChanged(); //刷新
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空列表
|
||||
*/
|
||||
public void clear(){
|
||||
if(list != null){
|
||||
list.clear();
|
||||
}
|
||||
notifyDataSetChanged(); //刷新
|
||||
}
|
||||
|
||||
class DeviceViewHolder {
|
||||
|
||||
TextView tvDeviceName;
|
||||
TextView tvDeviceAddress;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -8,10 +8,10 @@ class BlueToothUtil {
|
|||
|
||||
companion object{
|
||||
@SuppressLint("MissingPermission")
|
||||
fun boundDevice(devicex: BluetoothDevice?){
|
||||
fun boundDevice(devicex: BluetoothDevice?,ii:String){
|
||||
var method = BluetoothDevice::class.java.getMethod("createBond")
|
||||
method.invoke(devicex)
|
||||
var clientSocket = devicex!!.createRfcommSocketToServiceRecord(UUID.fromString(devicex.address))
|
||||
var clientSocket = devicex!!.createRfcommSocketToServiceRecord(UUID.fromString(ii))
|
||||
clientSocket.connect()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,16 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@drawable/device_petdevice"
|
||||
android:visibility="gone"
|
||||
android:scaleType="fitXY" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_bluetooth2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
android:visibility="gone"
|
||||
android:src="@drawable/device_petdevice"
|
||||
android:scaleType="fitXY" />
|
||||
<ImageView
|
||||
android:id="@+id/iv_more"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,245 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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"
|
||||
android:orientation="vertical"
|
||||
tools:context=".BlueTooth2Activity"
|
||||
android:focusableInTouchMode="true">
|
||||
<include
|
||||
android:id="@+id/in_daohang"
|
||||
layout="@layout/title_layout" />
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/bt_search"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:text="搜索"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="14sp"
|
||||
android:background="@color/blue"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_cur_con_state"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/colorPrimary"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_cur_bond_state"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/colorPrimary"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_toRightOf="@+id/ll_search"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:hint="设备名"
|
||||
android:textColor="@color/white"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:background="@color/blue"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_address"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:hint="设备地址"
|
||||
android:textColor="@color/white"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:paddingLeft="10dp"
|
||||
android:background="@color/blue"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/bt_connect"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:text="连接"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="14sp"
|
||||
android:background="@color/blue"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/bt_disconnect"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:text="断开"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="14sp"
|
||||
android:background="@color/blue"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/bt_bound"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:text="配对"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="14sp"
|
||||
android:background="@color/blue"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/bt_disBound"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:text="解除配对"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="14sp"
|
||||
android:background="@color/blue"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!--搜索设备列表-->
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_device_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="5dp"
|
||||
android:visibility="visible">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/lv_devices"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
</ListView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!--数据收发-->
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_data_send_receive"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:text="设置要发送的数据(十六进制字符串形式)"
|
||||
android:textColor="@color/colorPrimary"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_send_msg"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textColor="#333333"
|
||||
android:padding="10dp"
|
||||
android:hint="在此输入要发送的数据"
|
||||
android:background="@color/blue"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/bt_to_send"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="30dp"
|
||||
android:text="发送"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="14sp"
|
||||
android:background="@color/blue"/>
|
||||
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:text="显示接收的数据操作结果(发送成功/发送失败)"
|
||||
android:textColor="@color/colorPrimary"/>
|
||||
|
||||
<ScrollView
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:background="@color/blue">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_send_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="10dp"
|
||||
android:textSize="14sp"
|
||||
android:hint="此处显示发送数据操作结果"
|
||||
android:textColor="@color/colorPrimary"/>
|
||||
</ScrollView>
|
||||
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:text="显示接收的数据(以十六进制字符串显示)"
|
||||
android:textColor="@color/colorPrimary"/>
|
||||
|
||||
<ScrollView
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:background="@color/blue">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_receive_result"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="10dp"
|
||||
android:textSize="14sp"
|
||||
android:hint="此处显示发送数据操作结果"
|
||||
android:textColor="@color/colorPrimary"/>
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_device_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="5dp"
|
||||
android:textColor="@color/colorPrimary"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_device_address"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="5dp"
|
||||
android:textColor="@color/colorPrimary"
|
||||
android:textSize="16sp"/>
|
||||
|
||||
</LinearLayout>
|
||||
Loading…
Reference in New Issue