Sfoglia il codice sorgente

Merge branch 'master' into master1

master
suzhi 1 anno fa
parent
commit
6a35063a49
53 ha cambiato i file con 1919 aggiunte e 0 eliminazioni
  1. 15
    0
      .gitignore
  2. 3
    0
      .idea/.gitignore
  3. 6
    0
      .idea/compiler.xml
  4. 22
    0
      .idea/gradle.xml
  5. 10
    0
      .idea/misc.xml
  6. 1
    0
      app/.gitignore
  7. 51
    0
      app/build.gradle
  8. BIN
      app/libs/BleOtalibrary-1.1.3.aar
  9. 21
    0
      app/proguard-rules.pro
  10. 24
    0
      app/src/androidTest/java/com/elinkthings/elinkhealthringsdkdemo/ExampleInstrumentedTest.kt
  11. 56
    0
      app/src/main/AndroidManifest.xml
  12. BIN
      app/src/main/assets/BR01H1S1.0.0_20230923.img
  13. BIN
      app/src/main/assets/BR01H1S1.0.0_20240125.img
  14. BIN
      app/src/main/assets/Sensor-202312271422-0x0407.bin
  15. BIN
      app/src/main/assets/Sensor-202401021530-0x0408.bin
  16. 48
    0
      app/src/main/java/com/elinkthings/elinkhealthringsdkdemo/BleDataAdapter.kt
  17. 34
    0
      app/src/main/java/com/elinkthings/elinkhealthringsdkdemo/BleLogAdapter.kt
  18. 170
    0
      app/src/main/java/com/elinkthings/elinkhealthringsdkdemo/ElinkBasePermissionActivity.kt
  19. 400
    0
      app/src/main/java/com/elinkthings/elinkhealthringsdkdemo/ElinkHealthRingActivity.kt
  20. 65
    0
      app/src/main/java/com/elinkthings/elinkhealthringsdkdemo/ElinkMainActivity.kt
  21. 30
    0
      app/src/main/res/drawable-v24/ic_launcher_foreground.xml
  22. 170
    0
      app/src/main/res/drawable/ic_launcher_background.xml
  23. 151
    0
      app/src/main/res/layout/activity_elink_health_ring.xml
  24. 36
    0
      app/src/main/res/layout/activity_elink_main.xml
  25. 63
    0
      app/src/main/res/layout/item_ble_data_adapter.xml
  26. 30
    0
      app/src/main/res/layout/item_ble_log_adapter.xml
  27. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher.webp
  28. BIN
      app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
  29. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher.webp
  30. BIN
      app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
  31. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher.webp
  32. BIN
      app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
  33. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
  34. BIN
      app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
  35. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
  36. BIN
      app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
  37. 46
    0
      app/src/main/res/values-zh-rCN/strings.xml
  38. 6
    0
      app/src/main/res/values/colors.xml
  39. 45
    0
      app/src/main/res/values/strings.xml
  40. 12
    0
      app/src/main/res/values/themes.xml
  41. 17
    0
      app/src/test/java/com/elinkthings/elinkhealthringsdkdemo/ExampleUnitTest.kt
  42. 6
    0
      build.gradle
  43. 23
    0
      gradle.properties
  44. BIN
      gradle/wrapper/gradle-wrapper.jar
  45. 6
    0
      gradle/wrapper/gradle-wrapper.properties
  46. 185
    0
      gradlew
  47. 89
    0
      gradlew.bat
  48. 1
    0
      moduleHealthRing/.gitignore
  49. 36
    0
      moduleHealthRing/build.gradle
  50. 0
    0
      moduleHealthRing/consumer-rules.pro
  51. BIN
      moduleHealthRing/libs/AILinkHealthRingSDK.jar
  52. 21
    0
      moduleHealthRing/proguard-rules.pro
  53. 20
    0
      settings.gradle

+ 15
- 0
.gitignore Vedi File

@@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

+ 3
- 0
.idea/.gitignore Vedi File

@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

+ 6
- 0
.idea/compiler.xml Vedi File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>

+ 22
- 0
.idea/gradle.xml Vedi File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="11" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/moduleHealthRing" />
</set>
</option>
</GradleProjectSettings>
</option>
<option name="offlineMode" value="true" />
</component>
</project>

+ 10
- 0
.idea/misc.xml Vedi File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

+ 1
- 0
app/.gitignore Vedi File

@@ -0,0 +1 @@
/build

+ 51
- 0
app/build.gradle Vedi File

@@ -0,0 +1,51 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}

android {
namespace 'com.elinkthings.elinkhealthringsdkdemo'
compileSdk 33

defaultConfig {
applicationId "com.elinkthings.elinkhealthringsdkdemo"
minSdk 21
targetSdk 33
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}

dependencies {

implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.navigation:navigation-fragment-ktx:2.4.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

implementation 'com.github.elinkthings:AILinkSDKRepositoryAndroid:1.14.7'
implementation project(":moduleHealthRing")
implementation files("libs/BleOtalibrary-1.1.3.aar")
}

BIN
app/libs/BleOtalibrary-1.1.3.aar Vedi File


+ 21
- 0
app/proguard-rules.pro Vedi File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

+ 24
- 0
app/src/androidTest/java/com/elinkthings/elinkhealthringsdkdemo/ExampleInstrumentedTest.kt Vedi File

@@ -0,0 +1,24 @@
package com.elinkthings.elinkhealthringsdkdemo

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4

import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.elinkthings.elinkhealthringsdkdemo", appContext.packageName)
}
}

+ 56
- 0
app/src/main/AndroidManifest.xml Vedi File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"><!--兼容6.0以上的手机Ble-->
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"
android:maxSdkVersion="30" />
<!--android12需要增加maxSdkVersion-->
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!--android12还需要增加如下权限,也需求动态申请-->
<uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="s" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!--android10,11需要后台扫描的,需要添加如下权限-->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false" />
<uses-feature
android:name="android.hardware.bluetooth"
android:required="false" />

<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.ElinkHealthRingSDK"
tools:targetApi="31">
<activity
android:name=".ElinkMainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ElinkHealthRingActivity"
android:exported="true" />

<service android:name="com.pingwang.bluetoothlib.server.ELinkBleServer" />
</application>

</manifest>

BIN
app/src/main/assets/BR01H1S1.0.0_20230923.img Vedi File


BIN
app/src/main/assets/BR01H1S1.0.0_20240125.img Vedi File


BIN
app/src/main/assets/Sensor-202312271422-0x0407.bin Vedi File


BIN
app/src/main/assets/Sensor-202401021530-0x0408.bin Vedi File


+ 48
- 0
app/src/main/java/com/elinkthings/elinkhealthringsdkdemo/BleDataAdapter.kt Vedi File

@@ -0,0 +1,48 @@
package com.elinkthings.elinkhealthringsdkdemo

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.elinkthings.healthring.utils.toHex
import com.pingwang.bluetoothlib.bean.BleValueBean

/**
* @author suzy
* @date 2024/3/12 14:33
**/
class BleDataAdapter(
private val list: List<BleValueBean>,
private val onItemClick: (BleValueBean) -> Unit
) : RecyclerView.Adapter<BleDataAdapter.BleDataViewHolder>() {

class BleDataViewHolder(itemView: View) : ViewHolder(itemView) {
val tvName: TextView = itemView.findViewById(R.id.tv_ble_name)
val tvMac: TextView = itemView.findViewById(R.id.tv_ble_mac)
val tvRssi: TextView = itemView.findViewById(R.id.tv_ble_rssi)
val tvBleInfo: TextView = itemView.findViewById(R.id.tv_ble_info)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BleDataViewHolder {
val itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.item_ble_data_adapter, parent, false)
return BleDataViewHolder(itemView)
}

override fun getItemCount(): Int = list.size

override fun onBindViewHolder(holder: BleDataViewHolder, position: Int) {
holder.tvName.text = list[position].name
holder.tvMac.text = list[position].mac
holder.tvRssi.text = list[position].rssi.toString()
val cid = list[position].getCid()
val vid = list[position].getVid()
val pid = list[position].getPid()
holder.tvBleInfo.text = "CID: ${cid.toHex()}($cid), VID: ${vid.toHex()}($vid), PID: ${pid.toHex()}($pid)"
holder.itemView.setOnClickListener {
onItemClick(list[position])
}
}
}

+ 34
- 0
app/src/main/java/com/elinkthings/elinkhealthringsdkdemo/BleLogAdapter.kt Vedi File

@@ -0,0 +1,34 @@
package com.elinkthings.elinkhealthringsdkdemo

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

/**
* @author suzy
* @date 2024/3/13 17:18
**/
class BleLogAdapter(
private val list: List<String>,
) : RecyclerView.Adapter<BleLogAdapter.BleLogViewHolder>() {

class BleLogViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvLog: TextView = itemView.findViewById(R.id.tv_ble_log)
}

override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int,
): BleLogViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_ble_log_adapter, parent, false)
return BleLogViewHolder(itemView)
}

override fun onBindViewHolder(holder: BleLogViewHolder, position: Int) {
holder.tvLog.text = list[position]
}

override fun getItemCount(): Int = list.size
}

+ 170
- 0
app/src/main/java/com/elinkthings/elinkhealthringsdkdemo/ElinkBasePermissionActivity.kt Vedi File

@@ -0,0 +1,170 @@
package com.elinkthings.elinkhealthringsdkdemo

import android.Manifest
import android.app.AlertDialog
import android.content.Intent
import android.content.pm.PackageManager
import android.location.LocationManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.elinkthings.healthring.ElinkBaseBleActivity

/**
* @author suzy
* @date 2024/3/12 11:31
**/
abstract class ElinkBasePermissionActivity : ElinkBaseBleActivity() {

companion object {
private val LOCATION_PERMISSION = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
)
private val BLUETOOTH_PERMISSION = arrayOf(
Manifest.permission.BLUETOOTH_SCAN,
Manifest.permission.BLUETOOTH_ADVERTISE,
Manifest.permission.BLUETOOTH_CONNECT
)

private const val CODE_PERMISSION = 101
private const val CODE_LOCATION_SERVICE = 102
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportActionBar?.title = "${getString(R.string.app_name)}${BuildConfig.VERSION_NAME}"
initPermission()
}

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray,
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
//请求权限被拒绝
if (requestCode != CODE_PERMISSION) {
return
}

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initPermission()
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(
this,
LOCATION_PERMISSION[0]
)
) {
//权限请求失败,但未选中“不再提示”选项,再次请求
ActivityCompat.requestPermissions(this, LOCATION_PERMISSION, CODE_PERMISSION)
} else {
AlertDialog.Builder(this)
.setTitle("提示")
.setMessage("请求开启定位权限")
.setNegativeButton("取消", null)
.setPositiveButton("确定") { _, _ -> startSettingsActivity() }
.show()
}
}
} else {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initPermission()
}
}
}

private fun initPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
onPermissionOk()
return
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
checkLocationPermission()
} else {
checkBluetoothPermission()
}
}

private fun checkLocationPermission() {
if (!checkPermissionOk(LOCATION_PERMISSION[0])) {
ActivityCompat.requestPermissions(this, LOCATION_PERMISSION, CODE_PERMISSION)
} else {
val bleStatus: Boolean = isLocServiceEnable()
if (!bleStatus) {
AlertDialog.Builder(this)
.setTitle("提示")
.setMessage("请开启定位服务")
.setNegativeButton("取消") { _, _ -> checkBluetoothPermission() }
.setPositiveButton("确定") { _, _ -> startLocationActivity() }
.show()
} else {
onPermissionOk()
}
}
}

private fun checkBluetoothPermission() {
if (!checkPermissionOk(BLUETOOTH_PERMISSION[0])) {
ActivityCompat.requestPermissions(this, BLUETOOTH_PERMISSION, CODE_PERMISSION)
} else {
onPermissionOk()
}
}

private fun checkPermissionOk(permission: String): Boolean {
return ContextCompat.checkSelfPermission(
this,
permission
) == PackageManager.PERMISSION_GRANTED
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == CODE_LOCATION_SERVICE) {
//定位服务页面返回
initPermission()
}
}

abstract fun onPermissionOk()

/**
* 手机是否开启位置服务
*/
private fun isLocServiceEnable(): Boolean {
val locationManager = getSystemService(LOCATION_SERVICE) as LocationManager
val gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
val network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
return gps || network
}

/**
* 进入定位服务
*/
private fun startLocationActivity() {
val localIntent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
if (packageManager.resolveActivity(
localIntent,
PackageManager.MATCH_DEFAULT_ONLY
) != null
) {
startActivityForResult(localIntent, CODE_LOCATION_SERVICE)
}
}

/**
* 进入应用设置界面
*
*/
private fun startSettingsActivity() {
val localIntent = Intent()
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
localIntent.action = "android.settings.APPLICATION_DETAILS_SETTINGS"
localIntent.data = Uri.fromParts("package", packageName, null)
startActivity(localIntent)
}
}

+ 400
- 0
app/src/main/java/com/elinkthings/elinkhealthringsdkdemo/ElinkHealthRingActivity.kt Vedi File

@@ -0,0 +1,400 @@
package com.elinkthings.elinkhealthringsdkdemo

import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.MenuItem
import android.widget.Button
import androidx.annotation.IdRes
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.elinkthings.bleotalibrary.listener.OnBleOTAListener
import com.elinkthings.healthring.ElinkHealthRingBleData
import com.elinkthings.healthring.bean.ElinkCheckupRealtimeData
import com.elinkthings.healthring.bean.ElinkRingDeviceStatus
import com.elinkthings.healthring.bean.ElinkRingHistoryData
import com.elinkthings.healthring.config.ElinkCheckupType
import com.elinkthings.healthring.config.ElinkSensorOTAErrorType
import com.elinkthings.healthring.impl.ImplHealthRingResult
import com.elinkthings.healthring.impl.ImplSensorOTA
import com.elinkthings.healthring.utils.toHexString
import com.pingwang.bluetoothlib.bean.BleValueBean
import com.pingwang.bluetoothlib.device.BleDevice
import com.pingwang.bluetoothlib.listener.OnBleVersionListener
import com.pingwang.bluetoothlib.listener.OnCallbackBle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.text.SimpleDateFormat
import java.util.*

/**
* @author suzy
* @date 2024/3/13 16:54
**/
class ElinkHealthRingActivity : ElinkBasePermissionActivity(), OnCallbackBle, OnBleVersionListener,
ImplHealthRingResult {

private val logList = mutableListOf<String>()
private val logAdapter = BleLogAdapter(logList)
private var rvBleLog: RecyclerView? = null
private var ringBleData: ElinkHealthRingBleData? = null

companion object {
private const val EXTRA_MAC = "EXTRA_MAC"
private const val EXTRA_CID = "EXTRA_CID"
private const val EXTRA_VID = "EXTRA_VID"
private const val EXTRA_PID = "EXTRA_PID"

private val SENSOR_OTA_FILES =
arrayOf("Sensor-202312271422-0x0407.bin", "Sensor-202401021530-0x0408.bin")
private val BLE_OTA_FILES =
arrayOf("BR01H1S1.0.0_20230923.img", "BR01H1S1.0.0_20240125.img")

fun start(context: Context, mac: String, cid: Int, vid: Int, pid: Int) =
Intent(context, ElinkHealthRingActivity::class.java).apply {
putExtra(EXTRA_MAC, mac)
putExtra(EXTRA_CID, cid)
putExtra(EXTRA_VID, vid)
putExtra(EXTRA_PID, pid)
context.startActivity(this)
}
}

private val mac: String
get() = intent.getStringExtra(EXTRA_MAC) ?: ""

private val bleData: BleValueBean?
get() {
val cid = intent.getIntExtra(EXTRA_CID, 0)
val vid = intent.getIntExtra(EXTRA_VID, 0)
val pid = intent.getIntExtra(EXTRA_PID, 0)
if (mac.isEmpty()) {
return null
}
return BleValueBean(mac, cid, vid, pid)
}

private val bleDevice: BleDevice?
get() {
return aiLinkBleManager?.getBleDevice(mac)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
setContentView(R.layout.activity_elink_health_ring)
initButton(R.id.btn_health_ring_connect) {
connect()
}
initButton(R.id.btn_health_ring_disconnect) {
aiLinkBleManager?.disconnect(mac)
}
initButton(R.id.btn_health_ring_device_state) {
ringBleData?.getDeviceState()
}
initButton(R.id.btn_health_ring_checkup_duration) {
ringBleData?.getCheckupDuration()
}
initButton(R.id.btn_health_ring_sensor_version) {
ringBleData?.getSensorVersion()
}
initButton(R.id.btn_health_ring_checkup_type) {
ringBleData?.getCheckupType()
}
initButton(R.id.btn_health_ring_auto_checkup) {
ringBleData?.getAutoCheckState()
}
initButton(R.id.btn_health_ring_open_auto_checkup) {
ringBleData?.openAutoCheck()
}
initButton(R.id.btn_health_ring_close_auto_checkup) {
ringBleData?.closeAutoCheck()
}
initButton(R.id.btn_health_ring_close_auto_checkup) {
ringBleData?.closeAutoCheck()
}
initButton(R.id.btn_health_ring_set_checkup_duration) {
showListDialog(getString(R.string.set_checkup_duration), arrayOf("15", "30", "45", "60")) { item, _ ->
ringBleData?.setCheckupDuration(item.toInt())
}
}
initButton(R.id.btn_health_ring_set_checkup_type) {
showListDialog(getString(R.string.set_checkup_type), arrayOf(getString(R.string.checkup_type_complex), getString(R.string.checkup_type_fast))) { _, position ->
ringBleData?.setCheckupType(if (position == 0) ElinkCheckupType.COMPLEX else ElinkCheckupType.FAST)
}
}
initButton(R.id.btn_health_ring_sensor_ota) {
showListDialog(getString(R.string.select_sensor_ota_file), SENSOR_OTA_FILES) { item, _ ->
lifecycleScope.launch {
val fileData = readBytesFromAssets(item)
ringBleData?.startSensorOTA(fileData)
}
}
}
initButton(R.id.btn_health_ring_ble_ota) {
showListDialog(getString(R.string.select_ble_ota_file), BLE_OTA_FILES) { item, _ ->
lifecycleScope.launch {
val file = copyAssetToCache(item)
file?.let {
ringBleData?.startBleOTA(it.path, object : OnBleOTAListener {
override fun onOtaSuccess() {
addLog("${getString(R.string.ble_ota)} onOtaSuccess")
}

override fun onOtaFailure(cmd: Int, err: String?) {
addLog("${getString(R.string.ble_ota)} onOtaFailure: $cmd, $err")
}

override fun onOtaProgress(
progress: Float,
currentCount: Int,
maxCount: Int,
) {
addLog("${getString(R.string.ble_ota)} onOtaProgress: ${progress.toInt()} %, $currentCount, $maxCount")
}

override fun onOtaStatus(status: Int) {
addLog("${getString(R.string.ble_ota)} onOtaStatus: $status")
}

override fun onReconnect(mac: String?) {
addLog("${getString(R.string.ble_ota)} onReconnect: $mac")
}
})
}
}
}
}
initButton(R.id.btn_health_ring_get_history) {
ringBleData?.getHistory()
}
initButton(R.id.btn_health_ring_get_next_history) {
ringBleData?.getNextHistory()
}
initButton(R.id.btn_health_ring_get_history_over) {
ringBleData?.getHistoryOver()
}
initButton(R.id.btn_health_ring_delete_history) {
ringBleData?.deleteHistory()
}
initButton(R.id.btn_health_ring_start_checkup) {
ringBleData?.startCheckup()
}
initButton(R.id.btn_health_ring_stop_checkup) {
ringBleData?.stopCheckup()
}
initButton(R.id.btn_health_ring_sync_unix_time) {
ringBleData?.syncUnixTime()
}
initButton(R.id.btn_health_ring_clear_log) {
logList.clear()
logAdapter.notifyDataSetChanged()
}
rvBleLog = findViewById<RecyclerView>(R.id.rv_ble_log).apply {
layoutManager = LinearLayoutManager(this@ElinkHealthRingActivity)
adapter = logAdapter
}
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
finish()
}
return super.onOptionsItemSelected(item)
}

private fun initButton(@IdRes id: Int, onClick: () -> Unit) {
findViewById<Button>(id).setOnClickListener {
onClick()
}
}

private fun connect() {
bleData?.let {
aiLinkBleManager?.connectDevice(it)
}
}

override fun onPermissionOk() {

}

override fun onBindServiceSuccess() {
aiLinkBleManager?.setOnCallbackBle(this)
connect()
}

override fun onBindServiceFailed() {
aiLinkBleManager?.setOnCallbackBle(null)
}

override fun onBmVersion(version: String) {
addLog("${getString(R.string.ble_firmware_version)}: $version")
}

override fun bleOpen() {
addLog(getString(R.string.ble_open))
}

override fun bleClose() {
aiLinkBleManager?.disconnectAll()
addLog(getString(R.string.ble_close))
}

override fun onConnecting(mac: String?) {
addLog("${getString(R.string.connecting)}(${mac})")
}

override fun onConnectionSuccess(mac: String?) {
addLog("${getString(R.string.connect_success)}(${mac})")
}

override fun onDisConnected(mac: String?, code: Int) {
addLog("${getString(R.string.disconnect)}(${mac}, ${code})")
}

override fun onServicesDiscovered(mac: String?) {
addLog("${getString(R.string.services_discovered)}(${mac})")
bleDevice?.let {
it.setOnBleVersionListener(this)
ringBleData = ElinkHealthRingBleData(it)
ringBleData?.setImplHealthRingResult(this)
ringBleData?.setImplSensorOTA(object : ImplSensorOTA {
override fun onFailure(type: ElinkSensorOTAErrorType) {
addLog("${getString(R.string.sensor_ota)} onFailure: $type")
}

override fun onSuccess() {
addLog("${getString(R.string.sensor_ota)} onSuccess")
ringBleData?.endSensorOTA()
}

override fun onProgress(progress: Int) {
addLog("${getString(R.string.sensor_ota)} onProgress: ${progress}%")
}
})
}
}

private fun addLog(log: String) {
val time = System.currentTimeMillis()
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS", Locale.getDefault())
logList.add("${dateFormat.format(Date(time))}: $log")
logAdapter.notifyItemInserted(logList.size - 1)
rvBleLog?.smoothScrollToPosition(logAdapter.itemCount - 1)
}

override fun onDestroy() {
super.onDestroy()
ringBleData?.setImplHealthRingResult(null)
ringBleData?.setImplSensorOTA(null)
aiLinkBleManager?.setOnCallbackBle(null)
bleDevice?.setOnBleVersionListener(null)
aiLinkBleManager?.disconnect(mac)
}

override fun startCheckup(success: Boolean) {
addLog("${getString(R.string.start_checkup)}: $success")
}

override fun stopCheckup(success: Boolean) {
addLog("${getString(R.string.stop_checkup)}: $success")
}

override fun onGetRealtimeData(data: ElinkCheckupRealtimeData) {
addLog("${getString(R.string.checkup_realtime_data)}: $data")
}

override fun onGetCheckupPackets(data: ByteArray) {
addLog("${getString(R.string.checkup_packets)}: ${data.toHexString()}")
}

override fun onGetCheckupDuration(duration: Int) {
addLog("${getString(R.string.checkup_duration)}: ${duration}${getString(R.string.time_minutes)}")
}

override fun onGetHistory(histories: List<ElinkRingHistoryData>, total: Int, sentCount: Int) {
addLog("${getString(R.string.checkup_history_data)}: $histories, $total, $sentCount, ${sentCount < total}")
}

override fun onGetDeviceStatus(status: ElinkRingDeviceStatus) {
addLog("${getString(R.string.device_status)}: $status")
}

override fun onGetSensorVersion(version: String) {
addLog("${getString(R.string.sensor_version)}: $version")
}

override fun onGetAutoCheckupStatus(open: Boolean) {
addLog("${getString(R.string.auto_checkup_state)}: $open")
}

override fun onGetCheckupType(type: ElinkCheckupType) {
addLog("${getString(R.string.checkup_type)}: $type")
}

override fun onNotifyHistoryGenerated() {
addLog(getString(R.string.history_generated))
}

override fun onSetUnixTimeResult(success: Boolean) {
addLog("${getString(R.string.sync_time)}: $success")
}

private fun showListDialog(
title: String,
items: Array<String>,
callback: (String, Int) -> Unit,
) {
AlertDialog.Builder(this)
.setTitle(title)
.setItems(items) { dialog, which ->
val selectedItem = items[which]
callback.invoke(selectedItem, which)
dialog.dismiss()
}.show()
}

private suspend fun copyAssetToCache(assetFileName: String): File? =
withContext(Dispatchers.IO) {
val outputFile = File(cacheDir, assetFileName)
try {
assets.open(assetFileName).use { inputStream ->
FileOutputStream(outputFile).use { outputStream ->
val buffer = ByteArray(4 * 1024) // 4 KB buffer size
var bytesRead: Int
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
outputStream.write(buffer, 0, bytesRead)
}
outputStream.flush()
}
}
return@withContext outputFile
} catch (e: Exception) {
e.printStackTrace()
return@withContext null
}
}

private suspend fun readBytesFromAssets(fileName: String): ByteArray = withContext(Dispatchers.IO) {
val inputStream: InputStream = assets.open(fileName)
val buffer = ByteArrayOutputStream()
val data = ByteArray(1024)

var bytesRead: Int
while (inputStream.read(data, 0, data.size).also { bytesRead = it } != -1) {
buffer.write(data, 0, bytesRead)
}

buffer.close()
inputStream.close()
return@withContext buffer.toByteArray()
}
}

+ 65
- 0
app/src/main/java/com/elinkthings/elinkhealthringsdkdemo/ElinkMainActivity.kt Vedi File

@@ -0,0 +1,65 @@
package com.elinkthings.elinkhealthringsdkdemo

import android.os.Bundle
import android.widget.Button
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.elinkthings.healthring.ElinkHealthRingBleData
import com.pingwang.bluetoothlib.bean.BleValueBean
import com.pingwang.bluetoothlib.listener.OnCallbackBle
import com.pingwang.bluetoothlib.utils.BleLog

class ElinkMainActivity : ElinkBasePermissionActivity(), OnCallbackBle {

private val bleDataList = mutableListOf<BleValueBean>()
private val bleDataAdapter = BleDataAdapter(bleDataList) {
ElinkHealthRingActivity.start(this@ElinkMainActivity, it.address, it.getCid(), it.getVid(), it.getPid())
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_elink_main)
BleLog.init(true)
with(findViewById<RecyclerView>(R.id.rv_main)) {
layoutManager = LinearLayoutManager(this@ElinkMainActivity)
adapter = bleDataAdapter
}
findViewById<Button>(R.id.btn_main_scan).setOnClickListener {
startScan()
}
findViewById<Button>(R.id.btn_main_stop_scan).setOnClickListener {
stopScan()
}
}

override fun onPermissionOk() {

}

override fun onBindServiceSuccess() {
aiLinkBleManager?.setOnCallbackBle(this)
startScan()
}

override fun onBindServiceFailed() {
stopScan()
}

override fun onScanning(data: BleValueBean) {
if (data.getCid() != ElinkHealthRingBleData.ELINK_HEALTH_RING_CID) return //Filtering device that is not a ring
val filterIndex = bleDataList.indexOfFirst { it.address.equals(data.address) }
if (filterIndex != -1) {
bleDataList[filterIndex].rssi = data.rssi
bleDataAdapter.notifyItemChanged(filterIndex)
} else {
bleDataList.add(data)
bleDataAdapter.notifyItemInserted(bleDataList.size -1)
}
}

override fun onDestroy() {
super.onDestroy()
aiLinkBleManager?.setOnCallbackBle(null)
stopScan()
}
}

+ 30
- 0
app/src/main/res/drawable-v24/ic_launcher_foreground.xml Vedi File

@@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

+ 170
- 0
app/src/main/res/drawable/ic_launcher_background.xml Vedi File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

+ 151
- 0
app/src/main/res/layout/activity_elink_health_ring.xml Vedi File

@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/flow_health_ring"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:constraint_referenced_ids="btn_health_ring_connect, btn_health_ring_disconnect, btn_health_ring_clear_log, btn_health_ring_device_state, btn_health_ring_sync_unix_time, btn_health_ring_sensor_version, btn_health_ring_checkup_duration, btn_health_ring_set_checkup_duration, btn_health_ring_checkup_type, btn_health_ring_set_checkup_type, btn_health_ring_auto_checkup, btn_health_ring_open_auto_checkup, btn_health_ring_close_auto_checkup, btn_health_ring_get_history, btn_health_ring_get_next_history, btn_health_ring_get_history_over, btn_health_ring_delete_history, btn_health_ring_start_checkup, btn_health_ring_stop_checkup, btn_health_ring_sensor_ota, btn_health_ring_ble_ota"
app:flow_wrapMode="chain"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/btn_health_ring_connect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/connect_device" />

<Button
android:id="@+id/btn_health_ring_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/disconnect_device" />

<Button
android:id="@+id/btn_health_ring_device_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/query_device_status" />

<Button
android:id="@+id/btn_health_ring_checkup_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/query_checkup_duration" />

<Button
android:id="@+id/btn_health_ring_sensor_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sensor_version" />

<Button
android:id="@+id/btn_health_ring_checkup_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/checkup_type" />

<Button
android:id="@+id/btn_health_ring_auto_checkup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/auto_checkup_state" />

<Button
android:id="@+id/btn_health_ring_open_auto_checkup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/open_auto_checkup" />

<Button
android:id="@+id/btn_health_ring_close_auto_checkup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/close_auto_checkup" />

<Button
android:id="@+id/btn_health_ring_set_checkup_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/set_checkup_duration" />

<Button
android:id="@+id/btn_health_ring_set_checkup_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/set_checkup_type" />

<Button
android:id="@+id/btn_health_ring_get_history"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/get_history" />

<Button
android:id="@+id/btn_health_ring_get_next_history"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/get_next" />

<Button
android:id="@+id/btn_health_ring_get_history_over"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/get_over" />

<Button
android:id="@+id/btn_health_ring_delete_history"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/delete_history" />

<Button
android:id="@+id/btn_health_ring_start_checkup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/start_checkup" />

<Button
android:id="@+id/btn_health_ring_stop_checkup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stop_checkup" />

<Button
android:id="@+id/btn_health_ring_sync_unix_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sync_time" />

<Button
android:id="@+id/btn_health_ring_sensor_ota"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sensor_ota" />

<Button
android:id="@+id/btn_health_ring_ble_ota"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ble_ota" />

<Button
android:id="@+id/btn_health_ring_clear_log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/clear_log" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_ble_log"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/flow_health_ring" />
</androidx.constraintlayout.widget.ConstraintLayout>

+ 36
- 0
app/src/main/res/layout/activity_elink_main.xml Vedi File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".ElinkMainActivity">

<Button
android:id="@+id/btn_main_scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/start_scan"
app:layout_constraintEnd_toStartOf="@id/btn_main_stop_scan"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/btn_main_stop_scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/stop_scan"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/btn_main_scan"
app:layout_constraintTop_toTopOf="parent" />

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_main"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_main_scan" />

</androidx.constraintlayout.widget.ConstraintLayout>

+ 63
- 0
app/src/main/res/layout/item_ble_data_adapter.xml Vedi File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
android:paddingStart="16dp"
android:paddingTop="16dp"
android:paddingEnd="16dp">

<TextView
android:id="@+id/tv_ble_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/device_name" />

<TextView
android:id="@+id/tv_ble_mac"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textColor="@android:color/darker_gray"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="@id/tv_ble_name"
app:layout_constraintStart_toEndOf="@id/tv_ble_name"
app:layout_constraintTop_toTopOf="@id/tv_ble_name"
tools:text="00:00:00:00:00:00" />

<TextView
android:id="@+id/tv_ble_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textColor="@android:color/darker_gray"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_ble_name"
tools:text="cid: 00, vid: 00, pid: 00" />

<TextView
android:id="@+id/tv_ble_rssi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="-20" />

<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="16dp"
android:background="@android:color/darker_gray"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_ble_info" />
</androidx.constraintlayout.widget.ConstraintLayout>

+ 30
- 0
app/src/main/res/layout/item_ble_log_adapter.xml Vedi File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
android:paddingStart="16dp"
android:paddingTop="16dp"
android:paddingEnd="16dp">

<TextView
android:id="@+id/tv_ble_log"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="设备名称" />

<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="16dp"
android:background="@android:color/darker_gray"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_ble_log" />
</androidx.constraintlayout.widget.ConstraintLayout>

BIN
app/src/main/res/mipmap-hdpi/ic_launcher.webp Vedi File


BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Vedi File


BIN
app/src/main/res/mipmap-mdpi/ic_launcher.webp Vedi File


BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Vedi File


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.webp Vedi File


BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Vedi File


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Vedi File


BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Vedi File


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Vedi File


BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Vedi File


+ 46
- 0
app/src/main/res/values-zh-rCN/strings.xml Vedi File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">易连物联网健康戒指SDK Demo</string>
<string name="start_scan">开始扫描</string>
<string name="stop_scan">停止扫描</string>
<string name="device_name">设备名称</string>
<string name="connect_device">连接设备</string>
<string name="disconnect_device">断开连接</string>
<string name="query_device_status">查询设备状态</string>
<string name="query_checkup_duration">查询监测周期</string>
<string name="sensor_version">传感器版本</string>
<string name="checkup_type">监测模式</string>
<string name="auto_checkup_state">自动监测状态</string>
<string name="open_auto_checkup">开启自动监测</string>
<string name="close_auto_checkup">关闭自动监测</string>
<string name="set_checkup_duration">设置监测周期</string>
<string name="set_checkup_type">设置监测模式</string>
<string name="get_history">获取历史</string>
<string name="get_next">获取下一条</string>
<string name="get_over">获取完毕</string>
<string name="delete_history">删除数据</string>
<string name="start_checkup">开始体检</string>
<string name="stop_checkup">结束体检</string>
<string name="sync_time">同步时间</string>
<string name="sensor_ota">芯片OTA</string>
<string name="ble_ota">蓝牙OTA</string>
<string name="clear_log">清空log</string>
<string name="checkup_realtime_data">实时数据</string>
<string name="checkup_history_data">历史数据</string>
<string name="device_status">设备状态</string>
<string name="checkup_packets">体检包</string>
<string name="checkup_duration">监测周期</string>
<string name="history_generated">有历史数据生成</string>
<string name="time_minutes">分钟</string>
<string name="select_sensor_ota_file">选择芯片OTA文件</string>
<string name="select_ble_ota_file">选择蓝牙OTA文件</string>
<string name="checkup_type_complex">全面监测</string>
<string name="checkup_type_fast">快速监测</string>
<string name="ble_firmware_version">蓝牙固件版本</string>
<string name="ble_open">蓝牙已开启</string>
<string name="ble_close">蓝牙已关闭</string>
<string name="connecting">连接中</string>
<string name="connect_success">连接成功</string>
<string name="disconnect">连接断开</string>
<string name="services_discovered">发现服务</string>
</resources>

+ 6
- 0
app/src/main/res/values/colors.xml Vedi File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
</resources>

+ 45
- 0
app/src/main/res/values/strings.xml Vedi File

@@ -0,0 +1,45 @@
<resources>
<string name="app_name">ElinkHealthRingSDK Demo</string>
<string name="start_scan">Start Scan</string>
<string name="stop_scan">Stop Scan</string>
<string name="device_name">Device Name</string>
<string name="connect_device">Connect</string>
<string name="disconnect_device">Disconnect</string>
<string name="query_device_status">Query Device Status</string>
<string name="query_checkup_duration">Query Check Duration</string>
<string name="sensor_version">Sensor Version</string>
<string name="checkup_type">Checkup Type</string>
<string name="auto_checkup_state">Auto Checkup State</string>
<string name="open_auto_checkup">Turn On Auto Checkup</string>
<string name="close_auto_checkup">Turn Off Auto Checkup</string>
<string name="set_checkup_duration">Set Checkup Duration</string>
<string name="set_checkup_type">Set Checkup Type</string>
<string name="get_history">Get History</string>
<string name="get_next">Get Nex</string>
<string name="get_over">Get Over</string>
<string name="delete_history">Delete History</string>
<string name="start_checkup">Start Checkup</string>
<string name="stop_checkup">Stop Checkup</string>
<string name="sync_time">Sync Time</string>
<string name="sensor_ota">Sensor OTA</string>
<string name="ble_ota">BLE OTA</string>
<string name="clear_log">Clear Log</string>
<string name="checkup_realtime_data">Realtime Data</string>
<string name="checkup_history_data">History Data</string>
<string name="device_status">Device Status</string>
<string name="checkup_packets">Checkup Packets</string>
<string name="checkup_duration">Checkup Duration</string>
<string name="history_generated">History Generated</string>
<string name="time_minutes">min</string>
<string name="select_sensor_ota_file">Select Sensor OTA File</string>
<string name="select_ble_ota_file">Select BLE OTA File</string>
<string name="checkup_type_complex">Comprehensive</string>
<string name="checkup_type_fast">Fast</string>
<string name="ble_firmware_version">Firmware Version</string>
<string name="ble_open">Bluetooth is on</string>
<string name="ble_close">Bluetooth is off</string>
<string name="connecting">Connecting</string>
<string name="connect_success">Connected</string>
<string name="disconnect">Disconnected</string>
<string name="services_discovered">Services discovered</string>
</resources>

+ 12
- 0
app/src/main/res/values/themes.xml Vedi File

@@ -0,0 +1,12 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.ElinkHealthRingSDK" parent="Theme.AppCompat.DayNight.DarkActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>

<style name="Theme.ElinkHealthRingSDK" parent="Base.Theme.ElinkHealthRingSDK" />
</resources>

+ 17
- 0
app/src/test/java/com/elinkthings/elinkhealthringsdkdemo/ExampleUnitTest.kt Vedi File

@@ -0,0 +1,17 @@
package com.elinkthings.elinkhealthringsdkdemo

import org.junit.Test

import org.junit.Assert.*

/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

+ 6
- 0
build.gradle Vedi File

@@ -0,0 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.2' apply false
id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
}

+ 23
- 0
gradle.properties Vedi File

@@ -0,0 +1,23 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true

BIN
gradle/wrapper/gradle-wrapper.jar Vedi File


+ 6
- 0
gradle/wrapper/gradle-wrapper.properties Vedi File

@@ -0,0 +1,6 @@
#Thu Mar 14 17:14:04 CST 2024
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

+ 185
- 0
gradlew Vedi File

@@ -0,0 +1,185 @@
#!/usr/bin/env sh

#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn () {
echo "$*"
}

die () {
echo
echo "$*"
echo
exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar


# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

JAVACMD=`cygpath --unix "$JAVACMD"`

# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option

if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi

# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`

# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

exec "$JAVACMD" "$@"

+ 89
- 0
gradlew.bat Vedi File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem

@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar


@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega

+ 1
- 0
moduleHealthRing/.gitignore Vedi File

@@ -0,0 +1 @@
/build

+ 36
- 0
moduleHealthRing/build.gradle Vedi File

@@ -0,0 +1,36 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}

android {
namespace 'com.elinkthings.healthring'
compileSdk 33

defaultConfig {
minSdk 21
targetSdk 33

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
api files('libs/AILinkHealthRingSDK.jar')
}

+ 0
- 0
moduleHealthRing/consumer-rules.pro Vedi File


BIN
moduleHealthRing/libs/AILinkHealthRingSDK.jar Vedi File


+ 21
- 0
moduleHealthRing/proguard-rules.pro Vedi File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

+ 20
- 0
settings.gradle Vedi File

@@ -0,0 +1,20 @@
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url 'https://jitpack.io'
}
}
}
rootProject.name = "ElinkHealthRingSDKDemo"
include ':app'
include ':moduleHealthRing'

Loading…
Annulla
Salva