蓝牙功能添加

This commit is contained in:
jia 2024-09-08 21:50:14 +08:00
parent 9041bb9750
commit e2c7c647d3
20 changed files with 3587 additions and 108 deletions

View File

@ -169,6 +169,7 @@ dependencies {
implementation 'com.tencent:mmkv:1.3.3'
implementation("com.github.bumptech.glide:okhttp3-integration:4.11.0" )
implementation 'com.github.Jasonchenlijian:FastBle:2.4.0'
//
// annotationProcessor 'com.github.bumptech.glide:compiler:3.7.0'

View File

@ -21,6 +21,8 @@
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@ -791,6 +793,10 @@
android:name=".MainSix_4F_ControlActivity"
android:launchMode="singleTop"
android:theme="@style/Transparent" />
<activity
android:name=".MainSix_4F_BlueControlActivity"
android:launchMode="singleTop"
android:theme="@style/Transparent" />
<activity
android:name=".MainFour_3F_ControlActivity"
android:launchMode="singleTop"

View File

@ -620,6 +620,8 @@ public class BlueTooth2Activity extends BaseActivity implements View.OnClickList
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//扫描结束
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//搜索到设备
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //配对状态监听
// 监视蓝牙关闭和打开的状态
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(btBroadcastReceiver,intentFilter);
}

View File

@ -3,6 +3,12 @@ package com.ifish.activity;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -11,105 +17,334 @@ import android.os.Build;
import android.os.Bundle;
import android.os.ParcelUuid;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.RequiresApi;
import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleMtuChangedCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;
import com.clj.fastble.utils.HexUtil;
import com.ifish.adapter.BlueToothController;
import com.ifish.basebean.BaseBean;
import com.ifish.basebean.Device;
import com.ifish.baseclass.BaseActivity;
import com.ifish.bluetooth.ClsUtils;
import com.ifish.tcp.BackFunctionCode7_11;
import com.ifish.tcp.ModelCodec;
import com.ifish.tcp.OrderDeviceConnectModel;
import com.ifish.tcp.OrderModel;
import com.ifish.utils.BlueToothUtil;
import com.ifish.utils.ByteUtil;
import com.ifish.utils.Commons;
import com.ifish.utils.HttpListener;
import com.ifish.utils.HttpManager;
import com.ifish.utils.L;
import com.ifish.utils.ToastUtil;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.UUID;
public class BluetoothActivity extends BaseActivity {
BlueToothController blueToothController = new BlueToothController();
public static final String MY_BLUETOOTH_UUID = "00001101-0000-1000-8000-00805F9B34FB"; //蓝牙通讯
public static final String SERVICE_UUID = "000000ff-0000-1000-8000-00805f9b34fb"; //蓝牙通讯服务
public static final String READ_UUID = "0000ff01-0000-1000-8000-00805f9b34fb"; //读特征
public static final String WRITE_UUID = "0000ff01-0000-1000-8000-00805f9b34fb"; //写特征
IntentFilter foundFilter = null;
TextView name ;
TextView tvname ;
TextView tvname2 ;
Button tv_pair;
BleDevice currentDevice;
@SuppressLint("MissingPermission")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bluetooth);
BleManager.getInstance().init(getApplication());
name = findMyViewById(R.id.tv_name);
UUID[] uuids = {UUID.fromString(SERVICE_UUID)};
BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder()
.setServiceUuids(uuids) // 只扫描指定的服务的设备可选
// .setDeviceName(true, names) // 只扫描指定广播名的设备可选
// .setDeviceMac(mac) // 只扫描指定mac的设备可选
// .setAutoConnect(isAutoConnect) // 连接时的autoConnect参数可选默认false
.setScanTimeOut(20000) // 扫描超时时间可选默认10秒小于等于0表示不限制扫描时间
.build();
BleManager.getInstance().initScanRule(scanRuleConfig);
tvname = findMyViewById(R.id.tv_name);
tvname2 = findMyViewById(R.id.tv_name2);
tv_pair = findMyViewById(R.id.tv_pair);
initTitle("蓝牙选择设备");
foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);//获得扫描结果
foundFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//绑定状态变化
foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//开始扫描
foundFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//扫描结束
Button a1 = findMyViewById(R.id.a1);
Button a2 = findMyViewById(R.id.a2);
Button scan = findMyViewById(R.id.scan);
Button conn = findMyViewById(R.id.conn);
Button write = findMyViewById(R.id.write);
Button nofi = findMyViewById(R.id.nofi);
Button A = findMyViewById(R.id.A);
Button stop = findMyViewById(R.id.stop);
registerReceiver(broadcastReceiver,foundFilter);
blueToothController.find();
tv_pair.setOnClickListener(new View.OnClickListener() {
stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (bluetoothDevice!=null){
try {
int value = currentDevice.getRssi();
int iRssi = Math.abs(value);
double power = (iRssi-50)/(10*3.3);
double aaa = Math.pow(10, power);
tvname2.setText(""+aaa);
}
});
A.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int value = currentDevice.getRssi();
tvname2.setText(""+value);
}
});
initTitle("蓝牙选择设备");
L.i("jjia---------getBondState----"+bluetoothDevice.getBondState());
ClsUtils.createBond1( bluetoothDevice);
} catch (Exception e) {
List<BleDevice> ss = BleManager.getInstance().getAllConnectedDevice();
if (ss!=null){
ToastUtil.show(this,ss.size()+"");
for (BleDevice xx:ss){
if (xx!=null && xx.getDevice()!=null && xx.getDevice().getName()!=null && xx.getDevice().getName().startsWith("ifish")){
currentDevice = xx;
tvname.setText(xx.getDevice().getName()+"已连接");
}
L.i("jjia-----conn----"+xx.getDevice().getName());
}
}
a1.setOnClickListener(view -> {
tvname.setText(String.format("%s", BleManager.getInstance().isSupportBle()));
});
a2.setOnClickListener(view -> {
tvname.setText(String.format("%s", BleManager.getInstance().isBlueEnable()));
});
scan.setOnClickListener(view -> {
BleManager.getInstance().scan(new BleScanCallback() {
@Override
public void onScanFinished(List<BleDevice> scanResultList) {
ToastUtil.show(BluetoothActivity.this,"扫描结束");
}
@Override
public void onScanStarted(boolean success) {
ToastUtil.show(BluetoothActivity.this,"开始扫描");
}
@Override
public void onScanning(BleDevice bleDevice) {
if (bleDevice!=null && bleDevice.getDevice()!=null){
BluetoothDevice bean = bleDevice.getDevice();
if (!TextUtils.isEmpty(bean.getName()) && bean.getName().startsWith("ifish")){
currentDevice = bleDevice;
tvname.setText(bean.getName()+bean.getAddress());
BleManager.getInstance().cancelScan();
}
L.i(bean.getName()+"jjia---------"+bean.getAddress());
}
}
});
});
conn.setOnClickListener(view -> {
BleManager.getInstance().connect(currentDevice.getDevice().getAddress(), new BleGattCallback() {
@Override
public void onStartConnect() {
ToastUtil.show(BluetoothActivity.this,"开始连接");
}
@Override
public void onConnectFail(BleDevice bleDevice, BleException exception) {
ToastUtil.show(BluetoothActivity.this,"连接失败");
tvname.setText("连接失败");
}
@Override
public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
ToastUtil.show(BluetoothActivity.this,"连接成功"+bleDevice.getRssi());
tvname.setText("连接成功"+bleDevice.getRssi());
BleManager.getInstance().setMtu(bleDevice, 512, new BleMtuChangedCallback() {
@Override
public void onSetMTUFailure(BleException exception) {
L.i("jjia-------MTU--"+exception.toString());
}
@Override
public void onMtuChanged(int mtu) {
L.i("jjia-------MTU--"+mtu);
}
});
}
@Override
public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
ToastUtil.show(BluetoothActivity.this,"连接断开了");
tvname.setText("连接断开了");
}
});
});
tv_pair.setOnClickListener(view -> {
doPostBindDevice();
});
nofi.setOnClickListener(view -> {
BleManager.getInstance().notify(currentDevice, SERVICE_UUID, WRITE_UUID, new BleNotifyCallback() {
@Override
public void onNotifySuccess() {
ToastUtil.show(BluetoothActivity.this,"打开通知成功");
tvname.setText("打开通知成功");
}
@Override
public void onNotifyFailure(BleException exception) {
ToastUtil.show(BluetoothActivity.this,"打开通知失败");
tvname.setText("打开通知失败");
}
@Override
public void onCharacteristicChanged(byte[] data) {
if (data!=null && data.length>0){
String ssx = ByteUtil.bytesToHexString(data);
tvname2.setText(ssx);
int check_code = data[1];
int length = data[14];
byte[] dataByte = new byte[length];
for (int i = 0; i < dataByte.length; i++) {
dataByte[i] = data[i];
}
String device_mac = null;
Object object = ModelCodec.deCode(dataByte);
if (object!=null && object instanceof BackFunctionCode7_11){
BackFunctionCode7_11 model = (BackFunctionCode7_11) object;
device_mac = ByteUtil.bytesToHexString(model.getSrc());
tvname2.setText(device_mac);
}else {
//
}
L.i("jjia-------check_code-"+check_code);
L.i("jjia-------length-"+length);
L.i("jjia-------device_mac-"+device_mac);
// L.i("jjia-------通知--"+ss1);
// L.i("jjia-------通知--"+ss2);
// L.i("jjia-------通知--"+ss3);
// L.i("jjia-------通知--"+ss);
}
}
});
});
write.setOnClickListener(view -> {
String ssid = "CMDD";
String pwd = "juanandyo";
OrderDeviceConnectModel model = OrderModel.OrderDeviceConnectModel(ssid, pwd);//设置正式环境域名
byte[] data = ModelCodec.enCode(model);//
// String s = new String(data);
// L.i("jjia-----------111-"+s);
// byte [] xx = HexUtil.hexStringToBytes(s);
//
// L.i("jjia-----------数据大小-"+data.length);
// L.i("jjia-----------222-"+xx.length);
// L.i("jjia-----------222-"+xx);
// try {
// L.i("jjia-----------222-"+new String(xx,"UTF-8"));
// } catch (UnsupportedEncodingException e) {
// throw new RuntimeException(e);
// }
BleManager.getInstance().write(currentDevice, SERVICE_UUID, WRITE_UUID, data,false, new BleWriteCallback() {
@Override
public void onWriteSuccess(int current, int total, byte[] justWrite) {
try {
String aa = new String(justWrite,"UTF-8");
String ssx = ByteUtil.bytesToHexString(justWrite);
L.i(current+"x"+total+"jjia--------------写成功-"+aa +"$"+ssx);
tvname.setText(current+"x"+total+"写成功-"+aa);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
// BlueToothUtil.Companion.boundDevice(bluetoothDevice,MY_BLUETOOTH_UUID);
}
}
@Override
public void onWriteFailure(BleException exception) {
tvname.setText("写失败-"+exception.toString());
}
});
});
}
private void bleNotify(){
BluetoothDevice bluetoothDevice = null;
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@SuppressLint("MissingPermission")
@Override
public void onReceive(Context context, Intent intent) {
if (BluetoothDevice.ACTION_FOUND .equals(intent.getAction())){
BluetoothDevice device = null;
}
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU){
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE,BluetoothDevice.class);
}else {
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
}
if (device!=null && device.getBondState() ==10){
String deviceName= device.getName();
if (!TextUtils.isEmpty(deviceName) &&
(
// deviceName.contains("ifishly") ||
deviceName.startsWith("ifishly")
// deviceName.contains("LE-Bose")
Device deviceObj;
)
){
bluetoothDevice = device;
name.setText(deviceName);
private void doPostBindDevice() {
try {
ParcelUuid[] sss = device.getUuids();
if (sss!=null && sss.length>0){
for (ParcelUuid x:sss){
if (x!=null){
L.i(device.getName()+"蓝牙设备名称--Uuid--"+x.getUuid());
}
}
HttpManager hm = HttpManager.getInstance();
hm.bindDevice(new HttpListener<BaseBean<Device>>() {
private int result;
}else {
L.i("蓝牙设备名称--null0-");
}
L.i("蓝牙设备名称-1-"+device.toString());
@Override
public void success(BaseBean<Device> baseBean) {
result = baseBean.result;
if (result == Commons.NetWork.Success) {
// deviceObj = baseBean.data;
// deviceObj.setMacAddress(currentDevice.getMac());
// /**
// //当服务器返回的设备控制器数和定时器数为null的时候 不跳转进入主界面
// */
// if (deviceObj.getControlAmount() == null || deviceObj.getTimerAmount() == null) {
// L.i("第一次获取空");
//
// }
}
L.i("蓝牙设备名称--"+device.getName());
}
}else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(intent.getAction())){
ToastUtil.show(BluetoothActivity.this,"蓝牙搜索结束");
}
@Override
public void finish() {
}
@Override
public void error(Exception e, String msg) {
result = Commons.NetWork.ERROR;
}
}, Commons.USER.getUserId(), "e4b06318fd98");
} catch (Exception e) {
e.printStackTrace();
}
};
}
}

View File

@ -25,6 +25,7 @@ import android.widget.AdapterView.OnItemClickListener;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.clj.fastble.BleManager;
import com.ifish.adapter.GridViewCameraBaseAdapter;
import com.ifish.adapter.GridViewDeviceBaseAdapter;
import com.ifish.basebean.BaseBean;
@ -369,6 +370,7 @@ public class DeviceCameraListActivity extends BaseActivity {
@Override
public void success(BaseBean<Device> baseBean) {
result = baseBean.result;
BleManager.getInstance().disconnectAllDevice();
}
@Override

View File

@ -150,7 +150,10 @@ public class HotSpotConnentDeviceActivity extends BaseActivity {
Log.i("sssr", "222");
bys = dp.getData();
int check_code = bys[1];
L.i("jjia---------bys--"+new String(bys));
L.i("jjia---------check_code--"+check_code);
int length = bys[14];
L.i("jjia---------length--"+length);
byte[] dataByte = new byte[length];
for (int i = 0; i < dataByte.length; i++) {
dataByte[i] = bys[i];
@ -317,6 +320,9 @@ public class HotSpotConnentDeviceActivity extends BaseActivity {
* @return
*/
public boolean packageData(byte[] bytes, int check_code, String ip) {
L.i("jjia----data"+new String(bytes));
L.i("jjia----check_code"+check_code);
L.i("jjia----ip"+ip);
Object object = ModelCodec.deCode(bytes);
if (object == null) {
return false;

View File

@ -46,6 +46,7 @@ import com.ifish.geewe.DeviceCamera;
import com.ifish.permission.PermissionHelper;
import com.ifish.utils.ActivityManager;
import com.ifish.utils.AnimationUtil;
import com.ifish.utils.AppUtil;
import com.ifish.utils.Commons;
import com.ifish.utils.Commons.LoginSPKey;
import com.ifish.utils.Commons.NetWork;
@ -112,11 +113,19 @@ public class LoadingActivity extends BaseActivityNotAnim {
private static String firstShowPrivacy = "firstShowPrivacy";
String[] permission;
String[] permissionM = new String[]{android.Manifest.permission.CAMERA, android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_PHONE_STATE};
String[] permission13 = new String[]{android.Manifest.permission.CAMERA, android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.READ_PHONE_STATE,
android.Manifest.permission.READ_MEDIA_IMAGES,
android.Manifest.permission.READ_MEDIA_VIDEO};
// String[] permissionM = new String[]{
// android.Manifest.permission.CAMERA,
// android.Manifest.permission.ACCESS_FINE_LOCATION,
// android.Manifest.permission.READ_EXTERNAL_STORAGE,
// Manifest.permission.WRITE_EXTERNAL_STORAGE,
// android.Manifest.permission.READ_PHONE_STATE};
//
// String[] permission13 = new String[]{
// android.Manifest.permission.CAMERA,
// android.Manifest.permission.ACCESS_FINE_LOCATION,
// android.Manifest.permission.READ_PHONE_STATE,
// android.Manifest.permission.READ_MEDIA_IMAGES,
// android.Manifest.permission.READ_MEDIA_VIDEO};
@Override
@ -129,13 +138,7 @@ public class LoadingActivity extends BaseActivityNotAnim {
if (savedInstanceState != null) {
setIntent(new Intent()); // 从堆栈恢复不再重复解析之前的intent
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
permission = permission13;
} else {
permission = permissionM;
}
permission = AppUtil.getPermissionList();
permissionHelper = new PermissionHelper(LoadingActivity.this, permission, 250);
Boolean showPrivacy = SPUtil.getInstance(getApplicationContext()).getBoolean(firstShowPrivacy, false);

File diff suppressed because it is too large Load Diff

View File

@ -368,6 +368,8 @@ public class MainTabActivity extends BaseFragmentActivity {
}
};
private void initView() {
tabHost = (TabHost) findViewById(android.R.id.tabhost);
tabHost.setup();

View File

@ -46,11 +46,13 @@ public class BottomChoiceDialog extends DialogFragment implements View.OnClickLi
}
private TextView tvSmartConfig;
private TextView tvBle;
private TextView tvAP;
private TextView tvAirKiss;
private TextView tvCancel;
private LinearLayout lineAirKiss;
private LinearLayout lineSmartConfig;
private LinearLayout lineBle;
private LinearLayout lineAP;
@Nullable
@ -59,17 +61,20 @@ public class BottomChoiceDialog extends DialogFragment implements View.OnClickLi
View view = inflater.inflate(R.layout.dialog_choose_connect_wifi_type, container, false);
tvSmartConfig = (TextView) view.findViewById(R.id.tv_smartConfig);
tvBle = (TextView) view.findViewById(R.id.tv_ble);
tvAP = (TextView) view.findViewById(R.id.tv_AP);
tvAirKiss = (TextView) view.findViewById(R.id.tv_airkiss);
tvCancel = (TextView) view.findViewById(R.id.tv_cancel);
lineAirKiss = (LinearLayout) view.findViewById(R.id.line_airKiss);
lineSmartConfig = (LinearLayout) view.findViewById(R.id.line_smartConfig);
lineBle = (LinearLayout) view.findViewById(R.id.line_ble);
lineAP = (LinearLayout) view.findViewById(R.id.line_AP);
tvSmartConfig.setOnClickListener(this);
tvAP.setOnClickListener(this);
tvAirKiss.setOnClickListener(this);
tvCancel.setOnClickListener(this);
tvBle.setOnClickListener(this);
switchChooseUI(curType);
return view;
@ -120,6 +125,11 @@ public class BottomChoiceDialog extends DialogFragment implements View.OnClickLi
chooseClickListener.smartConfigConnect();
dismissAllowingStateLoss();
break;
case R.id.tv_ble:
chooseClickListener.bleConnect();
dismissAllowingStateLoss();
break;
case R.id.tv_AP:
chooseClickListener.APConnect();
dismissAllowingStateLoss();
@ -137,12 +147,18 @@ public class BottomChoiceDialog extends DialogFragment implements View.OnClickLi
public void switchChooseUI(ConnectType curConnectType) {
lineAirKiss.setVisibility(View.VISIBLE);
lineAP.setVisibility(View.VISIBLE);
lineSmartConfig.setVisibility(View.VISIBLE);
lineSmartConfig.setVisibility(View.GONE);
lineBle.setVisibility(View.VISIBLE);
switch (curConnectType) {
case SmartConfig:
// 处理SmartConfig逻辑
lineSmartConfig.setVisibility(View.GONE);
break;
case BlueTooth:
// 处理SmartConfig逻辑
lineBle.setVisibility(View.GONE);
break;
case APConnect:
// 处理APConnect逻辑
lineAP.setVisibility(View.GONE);
@ -161,6 +177,7 @@ public class BottomChoiceDialog extends DialogFragment implements View.OnClickLi
void APConnect();//热点连接
void AirKissConnect();//airkiss连接
void bleConnect();//airkiss连接
}
public void setOnChooseClickListener(OnChooseClickListener shareClickListener) {

View File

@ -9,5 +9,6 @@ package com.ifish.activity.newbind;
public enum ConnectType {
APConnect,
SmartConfig,
AirKiss
AirKiss,
BlueTooth
}

View File

@ -0,0 +1,11 @@
package com.ifish.basebean;
public class EventBean {
public String name;
public EventBean(String name){
this.name = name;
}
}

View File

@ -29,6 +29,8 @@ import com.alibaba.sdk.android.push.PushControlService;
import com.alibaba.sdk.android.push.huawei.HuaWeiRegister;
import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory;
import com.alibaba.sdk.android.push.register.MiPushRegister;
import com.clj.fastble.BleManager;
import com.clj.fastble.scan.BleScanRuleConfig;
import com.ifish.activity.BuildConfig;
import com.ifish.utils.ImageDownLoader;
import com.ifish.utils.KVUtil;
@ -43,6 +45,7 @@ import com.umeng.commonsdk.UMConfigure;
import com.umeng.socialize.PlatformConfig;
import java.security.SecureRandom;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
@ -77,7 +80,7 @@ public class BaseApplication extends MultiDexApplication {
public static String BASE = "https://app.ifish7.cn/";//正式环境 接口访问地址
// public static String BASE = "http://139.196.24.156:7080/";//测试环境 接口访问地址
public static String BASE_URL = BASE + "api/";// 接口URL
public static final String SERVICE_UUID = "000000ff-0000-1000-8000-00805f9b34fb";
@Override
public void onCreate() {
super.onCreate();
@ -94,6 +97,18 @@ public class BaseApplication extends MultiDexApplication {
//初始化MMKV
// KVUtil.init(this);
initPicasso();
BleManager.getInstance().init(this);
UUID[] uuids = {UUID.fromString(SERVICE_UUID)};
BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder()
.setServiceUuids(uuids) // 只扫描指定的服务的设备可选
// .setDeviceName(true, names) // 只扫描指定广播名的设备可选
// .setDeviceMac(mac) // 只扫描指定mac的设备可选
// .setAutoConnect(isAutoConnect) // 连接时的autoConnect参数可选默认false
.setScanTimeOut(20000) // 扫描超时时间可选默认10秒小于等于0表示不限制扫描时间
.build();
BleManager.getInstance().initScanRule(scanRuleConfig);
}
/**

View File

@ -9,10 +9,13 @@ package com.ifish.fragment;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.NotificationManager;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@ -50,10 +53,19 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import com.bumptech.glide.Glide;
import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleMtuChangedCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.ifish.activity.BindTwoDeviceActivity;
import com.ifish.activity.BlackListActivity;
import com.ifish.activity.DeviceInstructionActivity;
import com.ifish.activity.InformationListActivity;
import com.ifish.activity.LookFishMineActivity;
import com.ifish.activity.MainEightControlActivity;
import com.ifish.activity.MainFiveBDControlActivity;
import com.ifish.activity.MainFiveControlActivity;
@ -77,6 +89,8 @@ import com.ifish.activity.RecentContactsActivity;
import com.ifish.activity.SignActivity;
import com.ifish.activity.WebViewMessageActivity;
import com.ifish.activity.WebViewTaobaoActivity;
import com.ifish.activity.newbind.ConnectType;
import com.ifish.activity.newbind.NewBindDeviceActivity;
import com.ifish.adapter.CameraFragmentAdapter;
import com.ifish.adapter.DeviceFragmentAdapter;
import com.ifish.adapter.RollViewPagerAdapter;
@ -101,9 +115,15 @@ import com.ifish.geewe.GeeWeUser;
import com.ifish.geewe.P2PListener;
import com.ifish.geewe.SettingListener;
import com.ifish.permission.PermissionHelper;
import com.ifish.tcp.BackFunctionCode7_11;
import com.ifish.tcp.ModelCodec;
import com.ifish.tcp.OrderDeviceConnectModel;
import com.ifish.tcp.OrderModel;
import com.ifish.utils.ActivityManager;
import com.ifish.utils.AnimationUtil;
import com.ifish.utils.AppUtil;
import com.ifish.utils.BLEManger;
import com.ifish.utils.ByteUtil;
import com.ifish.utils.Commons;
import com.ifish.utils.Commons.LoginSPKey;
import com.ifish.utils.Commons.NetWork;
@ -116,6 +136,7 @@ import com.ifish.utils.SPUtil;
import com.ifish.utils.ScreenUtil;
import com.ifish.utils.ToastUtil;
import com.ifish.utils.UnreadCount;
import com.ifish.utils.WifiAdmin;
import com.ifish.view.LevelDialog;
import com.ifish.view.MyBGARefreshLayout;
import com.ifish.view.MyListView;
@ -197,9 +218,9 @@ public class DeviceFragment extends BaseV4Fragment implements ObservableScrollVi
private PermissionHelper permissionHelper;
String[] permission;
String[] permissionM = new String[]{android.Manifest.permission.CAMERA, android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_PHONE_STATE};
String[] permission13 = new String[]{android.Manifest.permission.CAMERA, android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.READ_PHONE_STATE};
// String[] permissionM = new String[]{android.Manifest.permission.CAMERA, android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_PHONE_STATE};
//
// String[] permission13 = new String[]{android.Manifest.permission.CAMERA, android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.READ_PHONE_STATE};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -222,14 +243,9 @@ public class DeviceFragment extends BaseV4Fragment implements ObservableScrollVi
adInfos();
initInformation();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
permission = permission13;
} else {
permission = permissionM;
}
permission = AppUtil.getPermissionList();
permissionHelper = new PermissionHelper(DeviceFragment.this, permission, 250);
initBooth();
return v;
}
@ -237,6 +253,8 @@ public class DeviceFragment extends BaseV4Fragment implements ObservableScrollVi
permissionHelper.request(new PermissionHelper.PermissionCallback() {
@Override
public void onPermissionGranted() {
}
@Override
@ -1153,6 +1171,9 @@ public class DeviceFragment extends BaseV4Fragment implements ObservableScrollVi
Integer controlAmount = Commons.DEVICE.get(Commons.DevicePosition).getControlAmount();
Integer timerAmount = Commons.DEVICE.get(Commons.DevicePosition).getTimerAmount();
String type = Commons.DEVICE.get(Commons.DevicePosition).type;
L.i("jjia----------"+type);
if (Commons.FishKey.On.equals(Commons.DEVICE.get(Commons.DevicePosition).isBlacklist)) {//黑名单
i.setClass(getActivity(), BlackListActivity.class);
} else {
@ -1877,4 +1898,250 @@ public class DeviceFragment extends BaseV4Fragment implements ObservableScrollVi
}
firstResult = firstResult + HttpManager.PAGESIZE;
}
public static final String SERVICE_UUID = "000000ff-0000-1000-8000-00805f9b34fb"; //蓝牙通讯服务
public static final String READ_UUID = "0000ff01-0000-1000-8000-00805f9b34fb"; //读特征
public static final String WRITE_UUID = "0000ff01-0000-1000-8000-00805f9b34fb"; //写特征
String device_mac=null;
private void sendBleData(){
// String ssid = tvWifiName.getText().toString();
// String pwd = tvWifiPwd.getText().toString();
WifiAdmin wifiAdmin = new WifiAdmin(requireContext());
String wifissid = wifiAdmin.getSSID();
L.i("jjia 获取当前连接的wifi:" + wifissid);
wifissid = wifiAdmin.updateSsid(wifissid);
String wifiname = wifissid;
if (TextUtils.isEmpty(wifissid)) {
wifiname = "";
} else {
if ("0x".equals(wifissid)) {//上次连接过wifi但是中途断开则会出现0x
wifiname = "";
}
}
// tvWifiName.setText(wifiname);
L.i("jjia----------------wifiname="+wifiname);
String pwd = null;
if (!TextUtils.isEmpty(wifiname)) {
// String pwd = KVUtil.getString(wifiname, "");
pwd = sp.getString(wifiname, "");
}
L.i(wifiname+"jjia---------name--1-"+pwd);
OrderDeviceConnectModel model = OrderModel.OrderDeviceConnectModel(wifiname, pwd);//设置正式环境域名
byte[] data = ModelCodec.enCode(model);
BleManager.getInstance().write(currentDevice, SERVICE_UUID, WRITE_UUID, data,false, new BleWriteCallback() {
@Override
public void onWriteSuccess(int current, int total, byte[] justWrite) {
L.i("jjia-------------ssid 发送");
}
@Override
public void onWriteFailure(BleException exception) {
}
});
}
private void checkoutMac(String mac){
if (!TextUtils.isEmpty(mac)){
boolean isSameName = false;
devicePosition = 0;
try {
if (Commons.DEVICE != null) {
if (Commons.DEVICE.size() != 0) {
for (int i = 0; i < Commons.DEVICE.size(); i++) {
if (mac.equals(Commons.DEVICE.get(i).getMacAddress())) {
devicePosition = i;
isSameName = true;
break;
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (!isSameName){
L.i("jjia-------------不包含");
requireActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// 检测页面
AlertDialog.Builder dialog = new AlertDialog.Builder(requireContext(), AlertDialog.THEME_HOLO_LIGHT);
dialog.setCancelable(true);
dialog.setTitle("提示");
dialog.setMessage("发现一个新设备是否去添加");
dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
arg0.dismiss();
}
});
dialog.setPositiveButton("确定", (dialog1, which) -> {
dialog1.dismiss();
Intent intent = new Intent();
intent.setClass(requireActivity(), NewBindDeviceActivity.class);
intent.putExtra("title", "连接水族箱");
intent.putExtra("type", "bluetooth");
intent.putExtra("device", currentDevice);
startActivity(intent);
AnimationUtil.finishAnimation(requireActivity());
});
dialog.show();
}
});
}
}
}
private void openNotify(){
BleManager.getInstance().notify(currentDevice, SERVICE_UUID, WRITE_UUID, new BleNotifyCallback() {
@Override
public void onNotifySuccess() {
sendBleData();
}
@Override
public void onNotifyFailure(BleException exception) {
dismissProgressDialogCancelble();
}
@Override
public void onCharacteristicChanged(byte[] data) {
if (data!=null && data.length>0){
int check_code = data[1];
int length = data[14];
byte[] dataByte = new byte[length];
for (int i = 0; i < dataByte.length; i++) {
dataByte[i] = data[i];
}
Object object = ModelCodec.deCode(dataByte);
if (object!=null && object instanceof BackFunctionCode7_11){
BackFunctionCode7_11 model = (BackFunctionCode7_11) object;
device_mac = ByteUtil.bytesToHexString(model.getSrc());
checkoutMac(device_mac);
} else {
}
L.i("jjia-------device_mac-"+device_mac);
}
}
});
}
private void connectBle(){
BleManager.getInstance().connect(currentDevice, new BleGattCallback() {
@Override
public void onStartConnect() {
L.i("jjia---------conne------");
}
@Override
public void onConnectFail(BleDevice bleDevice, BleException exception) {
}
@Override
public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
// ToastUtil.show(NewBindDeviceActivity.this,"蓝牙连接成功");
BleManager.getInstance().setMtu(bleDevice, 512, new BleMtuChangedCallback() {
@Override
public void onSetMTUFailure(BleException exception) {
}
@Override
public void onMtuChanged(int mtu) {
openNotify();
}
});
}
@Override
public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
}
});
}
private void initBooth(){
boolean enable = BleManager.getInstance().isBlueEnable();
if (enable) {
// BLEManger.getInstance().startDiscovery(true);
BleManager.getInstance().scan(new BleScanCallback() {
@Override
public void onScanFinished(List<BleDevice> scanResultList) {
if (currentDevice!=null){ // 扫描结束有设备
L.i("jjia---------scan---end-2--");
connectBle();
}else {
L.i("jjia---------scan---end--1-");
}
}
@Override
public void onScanStarted(boolean success) {
}
@SuppressLint("MissingPermission")
@Override
public void onScanning(BleDevice bleDevice) {
if (bleDevice!=null && bleDevice.getDevice()!=null){
BluetoothDevice bean = bleDevice.getDevice();
if (!TextUtils.isEmpty(bean.getName()) && bean.getName().startsWith("ifish")){
currentDevice = bleDevice;
BleManager.getInstance().cancelScan();
}
L.i(bean.getName()+"jjia------mac---"+bean.getAddress());
}
}
});
}
}
BleDevice currentDevice;
Boolean lifecycle = true;
public void onEventMainThread(BluetoothDevice event) {
L.i("jjia---------home---scan---");
if (BLEManger.getInstance().isHome && event!=null && lifecycle){ // 搜索到蓝牙了
// 检测页面
AlertDialog.Builder dialog = new AlertDialog.Builder(requireContext(), AlertDialog.THEME_HOLO_LIGHT);
dialog.setCancelable(true);
dialog.setTitle("提示");
dialog.setMessage("发现一个新设备是否去添加");
dialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
arg0.dismiss();
}
});
dialog.setPositiveButton("确定", (dialog1, which) -> {
dialog1.dismiss();
Intent intent = new Intent();
intent.setClass(requireActivity(), NewBindDeviceActivity.class);
intent.putExtra("title", "连接水族箱");
intent.putExtra("type", "bluetooth");
startActivity(intent);
AnimationUtil.finishAnimation(requireActivity());
});
dialog.show();
}
}
@Override
public void onPause() {
super.onPause();
lifecycle = false;
}
}

View File

@ -1,13 +1,20 @@
package com.ifish.utils;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import androidx.activity.ComponentActivity;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.List;
public class AppUtil {
@ -141,4 +148,62 @@ public class AppUtil {
toPermission(context);
}
}
/**
* 检测手机是否支持4.0蓝牙
* @param context 上下文
* @return true--支持4.0 false--不支持4.0
*/
private boolean checkBle(Context context){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { //API 18 Android 4.3
BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
if(bluetoothManager == null){
return false;
}
BluetoothAdapter bluetooth4Adapter = bluetoothManager.getAdapter(); //BLUETOOTH权限
if(bluetooth4Adapter == null){
return false;
}else{
L.i("该设备支持蓝牙4.0");
return true;
}
}else{
return false;
}
}
public static String [] getPermissionList(){
List<String> perList = new ArrayList<>();
perList.add(android.Manifest.permission.CAMERA);
perList.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
perList.add(android.Manifest.permission.READ_PHONE_STATE);
perList.add(android.Manifest.permission.BLUETOOTH);
perList.add(android.Manifest.permission.ACCESS_COARSE_LOCATION);
perList.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
perList.add(android.Manifest.permission.READ_MEDIA_IMAGES);
perList.add(android.Manifest.permission.READ_MEDIA_VIDEO);
perList.add(android.Manifest.permission.BLUETOOTH_SCAN);
perList.add(android.Manifest.permission.BLUETOOTH_ADVERTISE);
perList.add(android.Manifest.permission.BLUETOOTH_CONNECT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S){
perList.add(android.Manifest.permission.BLUETOOTH_SCAN);
perList.add(android.Manifest.permission.BLUETOOTH_ADVERTISE);
perList.add(android.Manifest.permission.BLUETOOTH_CONNECT);
perList.add(android.Manifest.permission.READ_EXTERNAL_STORAGE);
perList.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
}else {
perList.add(android.Manifest.permission.READ_EXTERNAL_STORAGE);
perList.add(android.Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
int size = perList.size();
String [] permissions = new String[size];
for (int i = 0;i<size;i++){
permissions[i] = perList.get(i);
}
return permissions;
}
}

View File

@ -0,0 +1,520 @@
package com.ifish.utils;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import com.ifish.activity.BluetoothActivity;
import com.ifish.basebean.EventBean;
import com.ifish.baseclass.BaseApplication;
import com.ifish.bluetooth.ClsUtils;
import java.util.ArrayList;
import java.util.List;
import de.greenrobot.event.EventBus;
public class BLEManger {
BluetoothAdapter bluetoothAdapter;
BluetoothManager bluetoothManager;
BLEManger(){
bluetoothManager = (BluetoothManager) BaseApplication.app.getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();
}
private static BLEManger single=null;
//静态工厂方法
public static BLEManger getInstance() {
if (single == null) {
single = new BLEManger();
}
return single;
}
/**
* 获取蓝牙状态
*/
public boolean isEnable(){
if(bluetoothAdapter == null){
return false;
}
return bluetoothAdapter.isEnabled();
}
/**
* 打开蓝牙
* @param isFast true 直接打开蓝牙 false 提示用户打开
*/
@SuppressLint("MissingPermission")
public void openBluetooth(Context context, boolean isFast){
if(!isEnable()){
if(isFast){
L.i("jjia-----直接打开手机蓝牙");
bluetoothAdapter.enable(); //BLUETOOTH_ADMIN权限
}else{
L.i("jjia-----提示用户去打开手机蓝牙");
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivity(enableBtIntent);
}
}else{
L.i("jjia-----手机蓝牙状态已开");
}
}
public Boolean isHome =false;
@SuppressLint("MissingPermission")
public void startDiscovery(Boolean home){
L.i("jjia---------startDiscovery---init---");
if (bluetoothAdapter!=null){
isHome = home;
bluetoothAdapter.startLeScan(leScanCallback);
}
}
public BluetoothDevice currentDevice;
public int count = 0;
private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
@SuppressLint("MissingPermission")
@Override
public void onLeScan(BluetoothDevice bluetoothDevice, int rssi, byte[] bytes) {
//在onLeScan()回调中尽量做少的操作可以将扫描到的设备扔到另一个线程中处理
if(bluetoothDevice == null){
return;
}
String name = bluetoothDevice.getName();
if (!TextUtils.isEmpty(name) && name.startsWith("ifishly")){
stopScan();
count++;
if (count<1){
}
L.i("---jjia----------匹配到了");
currentDevice = bluetoothDevice;
EventBus.getDefault().post(currentDevice);
L.d(bluetoothDevice.getName() + "--jjia>" + bluetoothDevice.getAddress()+"---"+rssi);
}
// L.d(bluetoothDevice.getName() + "--jjia---toher>" + bluetoothDevice.getAddress()+"---"+rssi);
// BLEDevice bleDevice = new BLEDevice(bluetoothDevice,rssi);
// if(onDeviceSearchListener != null){
// onDeviceSearchListener.onDeviceFound(bleDevice); //扫描到设备回调
// }
}
};
@SuppressLint("MissingPermission")
public void stopScan(){
if (bluetoothAdapter!=null){
bluetoothAdapter.stopLeScan(leScanCallback);
}
}
@SuppressLint("MissingPermission")
public void connect(AppCompatActivity activity){
if (currentDevice!=null){
currentDevice.connectGatt(activity,false,bluetoothGattCallback);
}
}
//连接/通讯结果回调
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private BluetoothGattCallback bluetoothGattCallback = new BluetoothGattCallback() {
//连接状态回调-连接成功/断开连接
@SuppressLint("MissingPermission")
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
L.d("jjia-----status:" + status);
L.d("jjia------newState:" + newState);
// GATT的链接状态回调
switch (newState){
case BluetoothGatt.STATE_CONNECTED:
L.d("jjia----蓝牙连接成功");
gatt.discoverServices(); // 去发现服务
break;
case BluetoothGatt.STATE_DISCONNECTED:
//青空系统缓存
ClsUtils.refreshDeviceCache(gatt);
L.d("jjia----蓝牙连接失败");
gatt.close();//断开连接释放连接
if (status == 133){
L.d("jjia----无法连接");
}else if (status == 62){
L.d("jjia----连接成功服务没有发现");
}else if(status ==0){
L.d("jjia----0正常断开 回调");
}else if(status ==8){
L.d("jjia----距离太远或者无法供电而断开");
}
break;
case BluetoothGatt.STATE_CONNECTING:
L.d("jjia----正在连接中。。。。。");
break;
case BluetoothGatt.STATE_DISCONNECTING:
L.d("jjia----正在断开中。。。。。");
break;
}
BluetoothDevice bluetoothDevice = gatt.getDevice();
L.d("jjia连接的设备" + bluetoothDevice.getName() + " " + bluetoothDevice.getAddress());
// isConnectIng = false;
// //移除连接超时
// mHandler.removeCallbacks(connectOutTimeRunnable);
//
// if(newState == BluetoothGatt.STATE_CONNECTED){
// L.d("jjia连接成功");
// //连接成功去发现服务
// gatt.discoverServices();
// //设置发现服务超时时间
// mHandler.postDelayed(serviceDiscoverOutTimeRunnable,MAX_CONNECT_TIME);
//
// if(onBleConnectListener != null){
// onBleConnectListener.onConnectSuccess(gatt,bluetoothDevice,status); //连接成功回调
// }
// }else if(newState == BluetoothGatt.STATE_DISCONNECTED) {
// //清空系统缓存
// ClsUtils.refreshDeviceCache(gatt);
// Log.e(TAG, "断开连接status:" + status);
// gatt.close(); //断开连接释放连接
//
// if(status == 133){
// //无法连接
// if(onBleConnectListener != null){
// gatt.close();
// onBleConnectListener.onConnectFailure(gatt,bluetoothDevice,"连接异常!",status); //133连接异常 异常断开
// L.d("jjia连接失败status" + status + " " + bluetoothDevice.getAddress());
// }
// }else if(status == 62){
// //成功连接没有发现服务断开
// if(onBleConnectListener != null){
// gatt.close();
// onBleConnectListener.onConnectFailure(gatt,bluetoothDevice,"连接成功服务未发现断开!",status); //62没有发现服务 异常断开
// L.d("jjia连接成功服务未发现断开status:" + status);
// }
//
// }else if(status == 0){
// if(onBleConnectListener != null){
// onBleConnectListener.onDisConnectSuccess(gatt,bluetoothDevice,status); //0正常断开 回调
// }
// }else if(status == 8){
// //因为距离远或者电池无法供电断开连接
// // 已经成功发现服务
// if(onBleConnectListener != null){
// onBleConnectListener.onDisConnectSuccess(gatt,bluetoothDevice,status); //8断电断开 回调
// }
// }else if(status == 34){
// if(onBleConnectListener != null){
// onBleConnectListener.onDisConnectSuccess(gatt,bluetoothDevice,status); //34断开
// }
// }else {
// //其它断开连接
// if(onBleConnectListener != null){
// onBleConnectListener.onDisConnectSuccess(gatt,bluetoothDevice,status); //其它断开
// }
// }
// }else if(newState == BluetoothGatt.STATE_CONNECTING){
// L.d("jjia正在连接...");
// if(onBleConnectListener != null){
// onBleConnectListener.onConnecting(gatt,bluetoothDevice); //正在连接回调
// }
// }else if(newState == BluetoothGatt.STATE_DISCONNECTING){
// L.d("jjia正在断开...");
// if(onBleConnectListener != null){
// onBleConnectListener.onDisConnecting(gatt,bluetoothDevice); //正在断开回调
// }
// }
}
///////////////////////////////////////// 打开通知 //////////////////////////////////////////
/**
* 设置读特征接收通知
* @param enable 为true打开通知
* @param gatt 连接
* @param characteristic 特征
*/
@SuppressLint("MissingPermission")
public void enableNotification(boolean enable, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic){
if(gatt == null){
L.i("jjia------enableNotification-->gatt == null");
return;
}
if(characteristic == null){
L.i("jjia------enableNotification-->characteristic == null");
return;
}
//这一步必须要有否则接收不到通知
gatt.setCharacteristicNotification(characteristic,enable);
}
//发现服务
//获取GATT服务发现后的回调
@SuppressLint("MissingPermission")
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
super.onServicesDiscovered(gatt, status);
if (status == BluetoothGatt.GATT_SUCCESS){
mGatt = gatt;
L.i("jjia------GATT_SUCCESS---services"); //服务发现
if (gatt.getServices()!=null){
L.i("jjia-----find---services"+gatt.getServices().size()); //服务发现
for (BluetoothGattService bluetoothGattService : gatt.getServices()) {
if (bluetoothGattService!=null ){
String UID = bluetoothGattService.getUuid().toString();
if (!TextUtils.isEmpty(UID) && SERVICE_UUID.equals(UID)){
service = bluetoothGattService;
L.i("jjia------Service_UUID:" + bluetoothGattService.getUuid()); // 我们可以遍历到该蓝牙设备的全部Service对象然后通过比较Service的UUID我们可以区分该服务是属于什么业务的
for (BluetoothGattCharacteristic characteristic : bluetoothGattService.getCharacteristics()) {
L.i("jjia------characteristic-UUID:" + characteristic.getUuid());
if (characteristic!=null && !TextUtils.isEmpty(characteristic.getUuid().toString()) && WRITE_UUID.equals(characteristic.getUuid().toString())){
write = characteristic;
read = characteristic;
//打开读通知
enableNotification(true, gatt, read);
//重点中重点需要重新设置
List<BluetoothGattDescriptor> descriptors = write.getDescriptors();
for (BluetoothGattDescriptor descriptor : descriptors) {
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
}
}
}
}
EventBean eventBean = new EventBean("blue_ok");
EventBus.getDefault().post(eventBean);
//
// if (SERVICE_UUID.equals(bluetoothGattService.getUuid().toString())) {
//
// for (BluetoothGattCharacteristic characteristic : bluetoothGattService.getCharacteristics()) {
// L.i("jjia------characteristic-UUID:" + characteristic.getUuid());
//// prepareBroadcastDataNotify(gatt, characteristic); //给满足条件的属性配置上消息通知
// }
// return;//结束循环操作
// }
}
}else {
L.i("jjia------no---services"); //服务发现
}
}
//移除发现服务超时
// mHandler.removeCallbacks(serviceDiscoverOutTimeRunnable);
// L.d("jjia移除发现服务超时");
//
// L.d("jjia发现服务");
//
// //配置服务信息
// if(setupService(gatt,serviceUUID,readUUID,writeUUID)){
// if(onBleConnectListener != null){
// onBleConnectListener.onServiceDiscoverySucceed(gatt,gatt.getDevice(),status); //成功发现服务回调
// }
// }else{
// if(onBleConnectListener != null){
// onBleConnectListener.onServiceDiscoveryFailed(gatt,gatt.getDevice(),"获取服务特征异常"); //发现服务失败回调
// }
// }
}
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
L.d("jjia-------------读status: " + status);
}
//向蓝牙设备写入数据结果回调
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicWrite(gatt, characteristic, status);
byte [] bb = characteristic.getValue();
L.i(characteristic.getUuid()+"jjia---------------向蓝牙设备写入数据结果回调--"+new String(bb));
L.i(status+"jjia---------------向蓝牙设备写入数据结果回调--"+BluetoothGatt.GATT_SUCCESS);
// if(characteristic.getValue() == null){
// L.d("jjiacharacteristic.getValue() == null");
// return;
// }
// //将收到的字节数组转换成十六进制字符串
// String msg = TypeConversion.bytes2HexString(characteristic.getValue(),characteristic.getValue().length);
// if(status == BluetoothGatt.GATT_SUCCESS){
// //写入成功
// L.d("jjia写入成功" + msg);
// if(onBleConnectListener != null){
// onBleConnectListener.onWriteSuccess(gatt,gatt.getDevice(),characteristic.getValue()); //写入成功回调
// }
//
// }else if(status == BluetoothGatt.GATT_FAILURE){
// //写入失败
// L.d("jjia写入失败" + msg);
// if(onBleConnectListener != null){
// onBleConnectListener.onWriteFailure(gatt,gatt.getDevice(),characteristic.getValue(),"写入失败"); //写入失败回调
// }
// }else if(status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED){
// //没有权限
// L.d("jjia没有权限");
// }
}
//读取蓝牙设备发出来的数据回调
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
//接收数据
byte[] bytes = characteristic.getValue();
L.i(characteristic.getUuid()+"jjia---------------读取蓝牙设备发出来的数据回调--");
// Log.w("TAG","收到数据str:" + TypeConversion.bytes2HexString(bytes,bytes.length));
// if(onBleConnectListener != null){
// onBleConnectListener.onReceiveMessage(gatt,gatt.getDevice(),characteristic,characteristic.getValue()); //接收数据回调
// }
}
@Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorRead(gatt, descriptor, status);
}
@Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
super.onDescriptorWrite(gatt, descriptor, status);
}
@Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
super.onReliableWriteCompleted(gatt, status);
L.d("jjiaonReliableWriteCompleted");
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
super.onReadRemoteRssi(gatt, rssi, status);
// if(status == BluetoothGatt.GATT_SUCCESS){
// L.d("jjia读取RSSI值成功RSSI值" + rssi + ",status" + status);
// if(onBleConnectListener != null){
// onBleConnectListener.onReadRssi(gatt,rssi,status); //成功读取连接的信号强度回调
// }
// }else if(status == BluetoothGatt.GATT_FAILURE){
// L.d("jjia读取RSSI值失败status" + status);
// }
}
//修改MTU值结果回调
@Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status);
///设置mtu值即bluetoothGatt.requestMtu()时触发提示该操作是否成功
// if(status == BluetoothGatt.GATT_SUCCESS){ //设置MTU成功
// //MTU默认取的是23当收到 onMtuChanged 会根据传递的值修改MTU注意由于传输用掉3字节因此传递的值需要减3
// //mtu - 3
// L.d("jjia设置MTU成功新的MTU值" + (mtu-3) + ",status" + status);
// if(onBleConnectListener != null){
// onBleConnectListener.onMTUSetSuccess("设置后新的MTU值 = " + (mtu-3) + " status = " + status,mtu - 3); //MTU设置成功
// }
//
// }else if(status == BluetoothGatt.GATT_FAILURE){ //设置MTU失败
// L.d("jjia设置MTU值失败" + (mtu-3) + ",status" + status);
// if(onBleConnectListener != null){
// onBleConnectListener.onMTUSetFailure("设置MTU值失败" + (mtu-3) + " status" + status); //MTU设置失败
// }
// }
}
};
public static final String SERVICE_UUID = "000000ff-0000-1000-8000-00805f9b34fb"; //蓝牙通讯服务
public static final String READ_UUID = "0000ff01-0000-1000-8000-00805f9b34fb"; //读特征
public static final String WRITE_UUID = "0000ff01-0000-1000-8000-00805f9b34fb"; //写特征
BluetoothGattService service;
BluetoothGattCharacteristic read;
BluetoothGattCharacteristic write;
BluetoothGatt mGatt ;
@SuppressLint("MissingPermission")
public void sendData(byte [] data){
if (write!=null){
L.d("jjia------send--------");
write.setValue(data);
mGatt.writeCharacteristic(write);
}
}
//00002b29-0000-1000-8000-00805f9b34fb //
/**
* 设置读特征接收通知
* @param enable 为true打开通知
* @param gatt 连接
* @param characteristic 特征
*/
@SuppressLint("MissingPermission")
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void enableNotification(boolean enable, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic){
if(gatt == null){
L.i("jjia---------enableNotification-->gatt == null");
return;
}
if(characteristic == null){
L.i("jjia--------enableNotification-->characteristic == null");
return;
}
//这一步必须要有否则接收不到通知
gatt.setCharacteristicNotification(characteristic,enable);
}
public static final String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
@SuppressLint("MissingPermission")
private void setAutoReceiveData(BluetoothGatt gatt,BluetoothGattService linkLossService,BluetoothGattCharacteristic data,BluetoothGattDescriptor defaultDescriptor) {
try {
// BluetoothGattService linkLossService = gatt.getService(SERVICE_UUID);
// BluetoothGattCharacteristic data = linkLossService.getCharacteristic(CHARACTERISTIC_UUID);
// BluetoothGattDescriptor defaultDescriptor = data.getDescriptor(UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
if (null != defaultDescriptor) {
defaultDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(defaultDescriptor);
}
gatt.setCharacteristicNotification(data, true);
} catch (Exception e) {
// BleLogUtils.appendLog("setAutoReceiveData:" + e.getMessage());
}
}
}

View File

@ -1,27 +1,20 @@
package com.ifish.utils
import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice
import java.util.UUID
import android.bluetooth.BluetoothAdapter
import android.content.Context
import android.content.Intent
class BlueToothUtil {
companion object{
@SuppressLint("MissingPermission")
fun boundDevice(devicex: BluetoothDevice?,ii:String){
var method = BluetoothDevice::class.java.getMethod("createBond")
method.invoke(devicex)
var clientSocket = devicex!!.createRfcommSocketToServiceRecord(UUID.fromString(ii))
clientSocket.connect()
}
@JvmStatic
@SuppressLint("MissingPermission")
fun boundDevice2(devicex: BluetoothDevice?){
devicex
var method = BluetoothDevice::class.java.getMethod("createBond")
method.invoke(devicex)
var clientSocket = devicex!!.createRfcommSocketToServiceRecord(UUID.randomUUID())
clientSocket.connect()
fun openBlueTooth(context: Context){
L.i("jjia-----提示用户去打开手机蓝牙")
val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
context.startActivity(enableBtIntent)
}
}
}

View File

@ -14,11 +14,59 @@
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tv_name2"
android:layout_width="match_parent"
android:textColor="@color/blue"
android:text="A"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/tv_pair"
android:layout_width="wrap_content"
android:text="蓝牙配对连接"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/a1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="是否支持BLE" />
<Button
android:id="@+id/a2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="蓝牙是否打开" />
<Button
android:id="@+id/scan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开始扫描" />
<Button
android:id="@+id/conn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="连接" />
<Button
android:id="@+id/nofi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="打开通知" />
<Button
android:id="@+id/write"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="发送数据" />
<Button
android:id="@+id/stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="断开" />
<Button
android:id="@+id/A"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="根据距离测试信号强度" />
</LinearLayout>

View File

@ -26,10 +26,32 @@
android:background="#efedee" />
</LinearLayout>
<LinearLayout
android:id="@+id/line_ble"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_ble"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
android:text="蓝牙联网"
android:textColor="#3E3A39"
android:textSize="16sp" />
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#efedee" />
</LinearLayout>
<LinearLayout
android:id="@+id/line_smartConfig"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:orientation="vertical">
<TextView