├── .gitignore ├── LICENSE ├── README.md ├── README_CN.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── zqs │ │ └── app │ │ └── ExampleInstrumentedTest.kt │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ ├── QsBleApplicaion.kt │ │ └── zqs │ │ ├── BleDeviceInfoActivity.kt │ │ ├── Exp.kt │ │ ├── LoadingDialog.kt │ │ ├── QsBleIndexActivity.kt │ │ └── utils │ │ └── UtilsExp.kt │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ ├── activity_ble_device_info.xml │ ├── activity_ble_index.xml │ ├── activity_main.xml │ ├── activity_main2.xml │ ├── dialog_loading.xml │ └── item_scan_device.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-mdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ ├── mipmap-xxxhdpi │ ├── ic_launcher.png │ └── ic_launcher_round.png │ └── values │ ├── colors.xml │ ├── strings.xml │ └── themes.xml ├── ble ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── zqs │ │ └── ble │ │ ├── BaseChain.java │ │ ├── BleChain.java │ │ ├── BleChainBuilder.java │ │ ├── ChainMessage.java │ │ ├── QsBle.java │ │ ├── impl │ │ ├── DefaultBleCallbackManage.java │ │ ├── DefaultBleMessageSender.java │ │ ├── DefaultBleOption.java │ │ └── HandleMessageLooper.java │ │ ├── lifecycle │ │ └── DestroyLifecycleObserver.java │ │ └── message │ │ ├── builder │ │ ├── CancelNotifyChainBuilder.java │ │ ├── ConnectChainBuilder.java │ │ ├── DisconnectChainBuilder.java │ │ ├── OpenNotifyChainBuilder.java │ │ ├── ReadChacChainBuilder.java │ │ ├── ReadDescChainBuilder.java │ │ ├── ReadPhyChainBuilder.java │ │ ├── ReadRssiChainBuilder.java │ │ ├── RequestMtuChainBuilder.java │ │ ├── SetConnectionPriorityChainBuilder.java │ │ ├── SetPhyChainBuilder.java │ │ ├── StartScanChainBuilder.java │ │ ├── StopScanChainBuilder.java │ │ ├── WriteByLockChacChainBuilder.java │ │ ├── WriteByLockNoRspChacChainBuilder.java │ │ ├── WriteChacChainBuilder.java │ │ ├── WriteDescChainBuilder.java │ │ └── WriteNoRspChacChainBuilder.java │ │ ├── exception │ │ ├── ChainHandleCancelException.java │ │ └── ChainHandleTimeoutException.java │ │ ├── ota │ │ ├── IOtaUpdateCallback.java │ │ └── WriteFileMessage.java │ │ └── pojo │ │ └── Entry.java │ └── res │ └── values │ └── strings.xml ├── ble_core ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── zqs │ └── ble │ └── core │ ├── BleConst.java │ ├── BleDebugConfig.java │ ├── BleDevice.java │ ├── BleGlobalConfig.java │ ├── SimpleBle.java │ ├── api │ ├── BaseMultiPackageAssembly.java │ ├── DefaultMultiPackageAssembly.java │ ├── IBleCallback.java │ ├── IBleMessageSender.java │ ├── IBleOption.java │ ├── IMessageLooper.java │ ├── IMessageSender.java │ └── IMultiPackageAssembly.java │ ├── callback │ ├── BleGattCallback.java │ ├── GlobalBleCallback.java │ ├── abs │ │ ├── IBleMultiPkgsCallback.java │ │ ├── IBleOptionCallback.java │ │ ├── IBlueStatusCallback.java │ │ ├── IChacChangeCallback.java │ │ ├── IChacReadCallback.java │ │ ├── IChacWriteCallback.java │ │ ├── IConnectStatusChangeCallback.java │ │ ├── IConnectionUpdatedCallback.java │ │ ├── IDescReadCallback.java │ │ ├── IDescWriteCallback.java │ │ ├── IMtuChangeCallback.java │ │ ├── INotifyFailCallback.java │ │ ├── INotifyStatusChangedCallback.java │ │ ├── IPhyReadCallback.java │ │ ├── IPhyUpdateCallback.java │ │ ├── IReadRssiCallback.java │ │ ├── IScanCallback.java │ │ ├── IScanErrorCallback.java │ │ ├── IScanStatusCallback.java │ │ └── IServicesDiscoveredCallback.java │ └── scan │ │ ├── BleJellyBeanScanCallback.java │ │ ├── BleLollipopScanCallback.java │ │ ├── BleScanOption.java │ │ └── SimpleScanConfig.java │ ├── deamon │ ├── AbsBleMessage.java │ ├── AbsMessage.java │ ├── DefaultMessageLooper.java │ └── message │ │ ├── callback │ │ ├── ICallbackMessage.java │ │ ├── OnBlueStatusChangedMessage.java │ │ ├── OnCharacteristicChangedMessage.java │ │ ├── OnCharacteristicReadMessage.java │ │ ├── OnCharacteristicWriteMessage.java │ │ ├── OnConnectionStateMessage.java │ │ ├── OnConnectionUpdatedMessage.java │ │ ├── OnDescriptorReadMessage.java │ │ ├── OnDescriptorWriteMessage.java │ │ ├── OnMtuChangedMessage.java │ │ ├── OnPhyReadMessage.java │ │ ├── OnPhyUpdateMessage.java │ │ ├── OnReadRemoteRssiMessage.java │ │ └── OnServicesDiscoveredMessage.java │ │ ├── option │ │ ├── ConnectMessage.java │ │ ├── DisconnectMessage.java │ │ ├── DiscoverServiceMessage.java │ │ ├── IOptionMessage.java │ │ ├── ReadChacMessage.java │ │ ├── ReadDescMessage.java │ │ ├── ReadPhyMessage.java │ │ ├── ReadRssiMessage.java │ │ ├── RequestMtuMessage.java │ │ ├── SetConnectionPriorityMessage.java │ │ ├── SetNotificationMessage.java │ │ ├── SetPhyMessage.java │ │ ├── WriteChacLockMessage.java │ │ ├── WriteChacMessage.java │ │ └── WriteDescMessage.java │ │ ├── order │ │ ├── FrontMessage.java │ │ └── IFrontMessage.java │ │ └── scan │ │ ├── IBleScanMessage.java │ │ ├── StartScanMessage.java │ │ └── StopScanMessage.java │ └── utils │ ├── BleLog.java │ ├── Utils.java │ └── fun │ ├── BooleanFunction.java │ ├── DebugFunction.java │ ├── Function1.java │ ├── Function2.java │ ├── Function3.java │ ├── IMessageOption.java │ └── VoidFunction.java ├── ble_coroutines ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── zqs │ └── ble │ └── coroutines │ └── await │ ├── Await.kt │ ├── BleLifeScope.kt │ └── Flow.kt ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screen └── app-debug.apk └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | .idea 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # IntelliJ 40 | *.iml 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/assetWizardSettings.xml 45 | .idea/dictionaries 46 | .idea/libraries 47 | # Android Studio 3 in .gitignore file. 48 | .idea/caches 49 | .idea/modules.xml 50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 51 | .idea/navEditor.xml 52 | 53 | # Keystore files 54 | # Uncomment the following lines if you do not want to check your keystore files in. 55 | #*.jks 56 | #*.keystore 57 | 58 | # External native build folder generated in Android Studio 2.2 and later 59 | .externalNativeBuild 60 | .cxx/ 61 | 62 | # Google Services (e.g. APIs or Firebase) 63 | # google-services.json 64 | 65 | # Freeline 66 | freeline.py 67 | freeline/ 68 | freeline_project_description.json 69 | 70 | # fastlane 71 | fastlane/report.xml 72 | fastlane/Preview.html 73 | fastlane/screenshots 74 | fastlane/test_output 75 | fastlane/readme.md 76 | 77 | # Version control 78 | vcs.xml 79 | 80 | # lint 81 | lint/intermediates/ 82 | lint/generated/ 83 | lint/outputs/ 84 | lint/tmp/ 85 | # lint/reports/ 86 | 87 | # Android Profiling 88 | *.hprof -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | id 'kotlin-android-extensions' 5 | id 'kotlin-kapt' 6 | } 7 | 8 | android { 9 | compileSdkVersion 30 10 | buildToolsVersion "30.0.0" 11 | 12 | defaultConfig { 13 | applicationId "com.zqs.app" 14 | minSdkVersion 18 15 | targetSdkVersion 30 16 | versionCode 1 17 | versionName "1.0" 18 | 19 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 20 | } 21 | 22 | buildTypes { 23 | release { 24 | minifyEnabled false 25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 26 | } 27 | } 28 | compileOptions { 29 | sourceCompatibility JavaVersion.VERSION_1_8 30 | targetCompatibility JavaVersion.VERSION_1_8 31 | } 32 | kotlinOptions { 33 | jvmTarget = '1.8' 34 | } 35 | 36 | } 37 | 38 | dependencies { 39 | 40 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 41 | implementation 'androidx.core:core-ktx:1.2.0' 42 | implementation 'androidx.appcompat:appcompat:1.0.0' 43 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 44 | implementation 'com.google.android.material:material:1.4.0' 45 | testImplementation 'junit:junit:4.+' 46 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 47 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 48 | implementation 'com.leon:lfilepickerlibrary:1.8.0' 49 | //FastJson依赖 50 | api 'com.alibaba:fastjson:1.1.72.android' 51 | api "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2" 52 | api "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2" 53 | 54 | 55 | //rxhttp依赖 https://github.com/liujingxing/okhttp-RxHttp 56 | implementation 'com.ljx.rxhttp:rxhttp:2.5.7' 57 | implementation 'com.squareup.okhttp3:okhttp:4.9.1' //rxhttp v2.2.2版本起,需要手动依赖okhttp 58 | kapt 'com.ljx.rxhttp:rxhttp-compiler:2.5.7' //生成RxHttp类,纯Java项目,请使用annotationProcessor代替kapt 59 | implementation 'com.ljx.rxlife:rxlife-coroutine:2.0.1' //管理协程生命周期,页面销毁,关闭请求 60 | implementation 'com.ljx.rxhttp:converter-fastjson:2.5.7' 61 | api project(':ble_coroutines') 62 | 63 | api project(':ble') 64 | } -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/androidTest/java/com/zqs/app/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.zqs.app 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import androidx.test.platform.app.InstrumentationRegistry 5 | import org.junit.Assert.assertEquals 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | /** 10 | * Instrumented test, which will execute on an Android device. 11 | * 12 | * See [testing documentation](http://d.android.com/tools/testing). 13 | */ 14 | @RunWith(AndroidJUnit4::class) 15 | class ExampleInstrumentedTest { 16 | @Test 17 | fun useAppContext() { 18 | // Context of the app under test. 19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 20 | assertEquals("com.zqs.app", appContext.packageName) 21 | } 22 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 30 | 31 | 34 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/QsBleApplicaion.kt: -------------------------------------------------------------------------------- 1 | package com 2 | 3 | import android.app.Application 4 | import com.zqs.ble.QsBle 5 | import com.zqs.ble.core.BleDebugConfig 6 | import com.zqs.ble.core.BleGlobalConfig 7 | import com.zqs.ble.core.callback.scan.SimpleScanConfig 8 | 9 | /* 10 | * @author zhangqisheng 11 | * @date 2022-08-06 16:20 12 | * @description 13 | */ 14 | class QsBleApplicaion: Application() { 15 | 16 | override fun onCreate() { 17 | super.onCreate() 18 | QsBle.getInstance().init(this) 19 | QsBle.getInstance().setDebug(true) 20 | } 21 | 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zqs/Exp.kt: -------------------------------------------------------------------------------- 1 | package com.zqs 2 | 3 | import android.app.Activity 4 | import com.zqs.ble.QsBle 5 | 6 | /* 7 | * @author zhangqisheng 8 | * @date 2022-08-06 16:32 9 | * @description 10 | */ 11 | 12 | val Activity.ble: QsBle 13 | get() = QsBle.getInstance() -------------------------------------------------------------------------------- /app/src/main/java/com/zqs/LoadingDialog.kt: -------------------------------------------------------------------------------- 1 | package com.zqs 2 | 3 | import android.os.Bundle 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.TextView 8 | import androidx.fragment.app.DialogFragment 9 | import com.zqs.app.R 10 | 11 | /* 12 | * @author zhangqisheng 13 | * @date 2022-08-06 21:22 14 | * @description 15 | */ 16 | class LoadingDialog:DialogFragment() { 17 | 18 | override fun onCreateView( 19 | inflater: LayoutInflater, 20 | container: ViewGroup?, 21 | savedInstanceState: Bundle? 22 | ): View? { 23 | return LayoutInflater.from(context).inflate(R.layout.dialog_loading, container, false) 24 | } 25 | 26 | fun setText(text:String){ 27 | view?.findViewById(R.id.title)?.text=text 28 | } 29 | 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/zqs/utils/UtilsExp.kt: -------------------------------------------------------------------------------- 1 | package com.zqs.utils 2 | 3 | import com.alibaba.fastjson.JSON 4 | 5 | /* 6 | * @author zhangqisheng 7 | * @date 2022-07-22 8 | * @description 9 | */ 10 | 11 | fun Any.toJson(): String { 12 | return JSON.toJSONString(this) 13 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_ble_index.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 23 | 24 | 29 | 30 | 35 | 36 | 42 | 43 | 48 | 49 | 50 | 57 | 58 | 63 | 64 | 65 | 71 | 72 |