diff options
| author | hc <haocheng.xie@respiree.com> | 2026-04-10 17:39:12 +0800 |
|---|---|---|
| committer | hc <haocheng.xie@respiree.com> | 2026-04-10 17:39:22 +0800 |
| commit | e4fb9966e762852bf17f21c8406501d42fae0b61 (patch) | |
| tree | 658bbdba977ff7846a17ee94b8ed6b676f6ce9dd /android/app | |
Initial commit: iHealth BLE scanner app with patched SDK v1.5.0
Diffstat (limited to 'android/app')
19 files changed, 264 insertions, 0 deletions
diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..853b346 --- /dev/null +++ b/android/app/build.gradle | |||
| @@ -0,0 +1,120 @@ | |||
| 1 | apply plugin: "com.android.application" | ||
| 2 | apply plugin: "org.jetbrains.kotlin.android" | ||
| 3 | apply plugin: "com.facebook.react" | ||
| 4 | |||
| 5 | /** | ||
| 6 | * This is the configuration block to customize your React Native Android app. | ||
| 7 | * By default you don't need to apply any configuration, just uncomment the lines you need. | ||
| 8 | */ | ||
| 9 | react { | ||
| 10 | /* Folders */ | ||
| 11 | // The root of your project, i.e. where "package.json" lives. Default is '../..' | ||
| 12 | // root = file("../../") | ||
| 13 | // The folder where the react-native NPM package is. Default is ../../node_modules/react-native | ||
| 14 | // reactNativeDir = file("../../node_modules/react-native") | ||
| 15 | // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen | ||
| 16 | // codegenDir = file("../../node_modules/@react-native/codegen") | ||
| 17 | // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js | ||
| 18 | // cliFile = file("../../node_modules/react-native/cli.js") | ||
| 19 | |||
| 20 | /* Variants */ | ||
| 21 | // The list of variants to that are debuggable. For those we're going to | ||
| 22 | // skip the bundling of the JS bundle and the assets. Default is "debug", "debugOptimized". | ||
| 23 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. | ||
| 24 | // debuggableVariants = ["liteDebug", "liteDebugOptimized", "prodDebug", "prodDebugOptimized"] | ||
| 25 | |||
| 26 | /* Bundling */ | ||
| 27 | // A list containing the node command and its flags. Default is just 'node'. | ||
| 28 | // nodeExecutableAndArgs = ["node"] | ||
| 29 | // | ||
| 30 | // The command to run when bundling. By default is 'bundle' | ||
| 31 | // bundleCommand = "ram-bundle" | ||
| 32 | // | ||
| 33 | // The path to the CLI configuration file. Default is empty. | ||
| 34 | // bundleConfig = file(../rn-cli.config.js) | ||
| 35 | // | ||
| 36 | // The name of the generated asset file containing your JS bundle | ||
| 37 | // bundleAssetName = "MyApplication.android.bundle" | ||
| 38 | // | ||
| 39 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' | ||
| 40 | // entryFile = file("../js/MyApplication.android.js") | ||
| 41 | // | ||
| 42 | // A list of extra flags to pass to the 'bundle' commands. | ||
| 43 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle | ||
| 44 | // extraPackagerArgs = [] | ||
| 45 | |||
| 46 | /* Hermes Commands */ | ||
| 47 | // The hermes compiler command to run. By default it is 'hermesc' | ||
| 48 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" | ||
| 49 | // | ||
| 50 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" | ||
| 51 | // hermesFlags = ["-O", "-output-source-map"] | ||
| 52 | |||
| 53 | /* Autolinking */ | ||
| 54 | autolinkLibrariesWithApp() | ||
| 55 | } | ||
| 56 | |||
| 57 | /** | ||
| 58 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode. | ||
| 59 | */ | ||
| 60 | def enableProguardInReleaseBuilds = false | ||
| 61 | |||
| 62 | /** | ||
| 63 | * The preferred build flavor of JavaScriptCore (JSC) | ||
| 64 | * | ||
| 65 | * For example, to use the international variant, you can use: | ||
| 66 | * `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+` | ||
| 67 | * | ||
| 68 | * The international variant includes ICU i18n library and necessary data | ||
| 69 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that | ||
| 70 | * give correct results when using with locales other than en-US. Note that | ||
| 71 | * this variant is about 6MiB larger per architecture than default. | ||
| 72 | */ | ||
| 73 | def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+' | ||
| 74 | |||
| 75 | android { | ||
| 76 | ndkVersion rootProject.ext.ndkVersion | ||
| 77 | buildToolsVersion rootProject.ext.buildToolsVersion | ||
| 78 | compileSdk rootProject.ext.compileSdkVersion | ||
| 79 | |||
| 80 | namespace "com.ihealthscanner" | ||
| 81 | defaultConfig { | ||
| 82 | applicationId "com.ihealthscanner" | ||
| 83 | minSdkVersion rootProject.ext.minSdkVersion | ||
| 84 | targetSdkVersion rootProject.ext.targetSdkVersion | ||
| 85 | versionCode 1 | ||
| 86 | versionName "1.0" | ||
| 87 | } | ||
| 88 | signingConfigs { | ||
| 89 | debug { | ||
| 90 | storeFile file('debug.keystore') | ||
| 91 | storePassword 'android' | ||
| 92 | keyAlias 'androiddebugkey' | ||
| 93 | keyPassword 'android' | ||
| 94 | } | ||
| 95 | } | ||
| 96 | buildTypes { | ||
| 97 | debug { | ||
| 98 | signingConfig signingConfigs.debug | ||
| 99 | } | ||
| 100 | release { | ||
| 101 | // Caution! In production, you need to generate your own keystore file. | ||
| 102 | // see https://reactnative.dev/docs/signed-apk-android. | ||
| 103 | signingConfig signingConfigs.debug | ||
| 104 | minifyEnabled enableProguardInReleaseBuilds | ||
| 105 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" | ||
| 106 | } | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | dependencies { | ||
| 111 | // The version of react-native is set by the React Native Gradle Plugin | ||
| 112 | implementation("com.facebook.react:react-android") | ||
| 113 | implementation project(':ihealthlibrary-react-native') | ||
| 114 | |||
| 115 | if (hermesEnabled.toBoolean()) { | ||
| 116 | implementation("com.facebook.react:hermes-android") | ||
| 117 | } else { | ||
| 118 | implementation jscFlavor | ||
| 119 | } | ||
| 120 | } | ||
diff --git a/android/app/debug.keystore b/android/app/debug.keystore new file mode 100644 index 0000000..364e105 --- /dev/null +++ b/android/app/debug.keystore | |||
| Binary files differ | |||
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro new file mode 100644 index 0000000..11b0257 --- /dev/null +++ b/android/app/proguard-rules.pro | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | # Add project specific ProGuard rules here. | ||
| 2 | # By default, the flags in this file are appended to flags specified | ||
| 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt | ||
| 4 | # You can edit the include path and order by changing the proguardFiles | ||
| 5 | # directive in build.gradle. | ||
| 6 | # | ||
| 7 | # For more details, see | ||
| 8 | # http://developer.android.com/guide/developing/tools/proguard.html | ||
| 9 | |||
| 10 | # Add any project specific keep options here: | ||
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..01db1e9 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| 2 | |||
| 3 | <uses-permission android:name="android.permission.INTERNET" /> | ||
| 4 | <uses-permission android:name="android.permission.BLUETOOTH" /> | ||
| 5 | <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> | ||
| 6 | <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> | ||
| 7 | <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> | ||
| 8 | <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> | ||
| 9 | <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> | ||
| 10 | <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | ||
| 11 | <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> | ||
| 12 | |||
| 13 | <application | ||
| 14 | android:name=".MainApplication" | ||
| 15 | android:label="@string/app_name" | ||
| 16 | android:icon="@mipmap/ic_launcher" | ||
| 17 | android:roundIcon="@mipmap/ic_launcher_round" | ||
| 18 | android:allowBackup="false" | ||
| 19 | android:theme="@style/AppTheme" | ||
| 20 | android:usesCleartextTraffic="${usesCleartextTraffic}" | ||
| 21 | android:supportsRtl="true"> | ||
| 22 | <activity | ||
| 23 | android:name=".MainActivity" | ||
| 24 | android:label="@string/app_name" | ||
| 25 | android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" | ||
| 26 | android:launchMode="singleTask" | ||
| 27 | android:windowSoftInputMode="adjustResize" | ||
| 28 | android:exported="true"> | ||
| 29 | <intent-filter> | ||
| 30 | <action android:name="android.intent.action.MAIN" /> | ||
| 31 | <category android:name="android.intent.category.LAUNCHER" /> | ||
| 32 | </intent-filter> | ||
| 33 | </activity> | ||
| 34 | </application> | ||
| 35 | </manifest> | ||
diff --git a/android/app/src/main/java/com/ihealthscanner/MainActivity.kt b/android/app/src/main/java/com/ihealthscanner/MainActivity.kt new file mode 100644 index 0000000..b22606b --- /dev/null +++ b/android/app/src/main/java/com/ihealthscanner/MainActivity.kt | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | package com.ihealthscanner | ||
| 2 | |||
| 3 | import com.facebook.react.ReactActivity | ||
| 4 | import com.facebook.react.ReactActivityDelegate | ||
| 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled | ||
| 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate | ||
| 7 | |||
| 8 | class MainActivity : ReactActivity() { | ||
| 9 | |||
| 10 | /** | ||
| 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule | ||
| 12 | * rendering of the component. | ||
| 13 | */ | ||
| 14 | override fun getMainComponentName(): String = "iHealthScanner" | ||
| 15 | |||
| 16 | /** | ||
| 17 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] | ||
| 18 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] | ||
| 19 | */ | ||
| 20 | override fun createReactActivityDelegate(): ReactActivityDelegate = | ||
| 21 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) | ||
| 22 | } | ||
diff --git a/android/app/src/main/java/com/ihealthscanner/MainApplication.kt b/android/app/src/main/java/com/ihealthscanner/MainApplication.kt new file mode 100644 index 0000000..c079966 --- /dev/null +++ b/android/app/src/main/java/com/ihealthscanner/MainApplication.kt | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | package com.ihealthscanner | ||
| 2 | |||
| 3 | import android.app.Application | ||
| 4 | import com.facebook.react.PackageList | ||
| 5 | import com.facebook.react.ReactApplication | ||
| 6 | import com.facebook.react.ReactHost | ||
| 7 | import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative | ||
| 8 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost | ||
| 9 | import com.ihealth.ihealthlibrary.iHealthDeviceManagerPackage | ||
| 10 | |||
| 11 | class MainApplication : Application(), ReactApplication { | ||
| 12 | |||
| 13 | override val reactHost: ReactHost by lazy { | ||
| 14 | getDefaultReactHost( | ||
| 15 | context = applicationContext, | ||
| 16 | packageList = | ||
| 17 | PackageList(this).packages.apply { | ||
| 18 | // Packages that cannot be autolinked yet can be added manually here: | ||
| 19 | add(iHealthDeviceManagerPackage()) | ||
| 20 | }, | ||
| 21 | ) | ||
| 22 | } | ||
| 23 | |||
| 24 | override fun onCreate() { | ||
| 25 | super.onCreate() | ||
| 26 | loadReactNative(this) | ||
| 27 | } | ||
| 28 | } | ||
diff --git a/android/app/src/main/res/drawable/rn_edit_text_material.xml b/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 0000000..5c25e72 --- /dev/null +++ b/android/app/src/main/res/drawable/rn_edit_text_material.xml | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | <?xml version="1.0" encoding="utf-8"?> | ||
| 2 | <!-- Copyright (C) 2014 The Android Open Source Project | ||
| 3 | |||
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | you may not use this file except in compliance with the License. | ||
| 6 | You may obtain a copy of the License at | ||
| 7 | |||
| 8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | |||
| 10 | Unless required by applicable law or agreed to in writing, software | ||
| 11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | See the License for the specific language governing permissions and | ||
| 14 | limitations under the License. | ||
| 15 | --> | ||
| 16 | <inset xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 17 | android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material" | ||
| 18 | android:insetRight="@dimen/abc_edit_text_inset_horizontal_material" | ||
| 19 | android:insetTop="@dimen/abc_edit_text_inset_top_material" | ||
| 20 | android:insetBottom="@dimen/abc_edit_text_inset_bottom_material" | ||
| 21 | > | ||
| 22 | |||
| 23 | <selector> | ||
| 24 | <!-- | ||
| 25 | This file is a copy of abc_edit_text_material (https://bit.ly/3k8fX7I). | ||
| 26 | The item below with state_pressed="false" and state_focused="false" causes a NullPointerException. | ||
| 27 | NullPointerException:tempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable(android.content.res.Resources)' | ||
| 28 | |||
| 29 | <item android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/> | ||
| 30 | |||
| 31 | For more info, see https://bit.ly/3CdLStv (react-native/pull/29452) and https://bit.ly/3nxOMoR. | ||
| 32 | --> | ||
| 33 | <item android:state_enabled="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/> | ||
| 34 | <item android:drawable="@drawable/abc_textfield_activated_mtrl_alpha"/> | ||
| 35 | </selector> | ||
| 36 | |||
| 37 | </inset> | ||
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a2f5908 --- /dev/null +++ b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png | |||
| Binary files differ | |||
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..1b52399 --- /dev/null +++ b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png | |||
| Binary files differ | |||
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..ff10afd --- /dev/null +++ b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png | |||
| Binary files differ | |||
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..115a4c7 --- /dev/null +++ b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png | |||
| Binary files differ | |||
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..dcd3cd8 --- /dev/null +++ b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png | |||
| Binary files differ | |||
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 --- /dev/null +++ b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png | |||
| Binary files differ | |||
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..8ca12fe --- /dev/null +++ b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png | |||
| Binary files differ | |||
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e19b41 --- /dev/null +++ b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png | |||
| Binary files differ | |||
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b824ebd --- /dev/null +++ b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png | |||
| Binary files differ | |||
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..4c19a13 --- /dev/null +++ b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png | |||
| Binary files differ | |||
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..23d685f --- /dev/null +++ b/android/app/src/main/res/values/strings.xml | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | <resources> | ||
| 2 | <string name="app_name">iHealthScanner</string> | ||
| 3 | </resources> | ||
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..7ba83a2 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | <resources> | ||
| 2 | |||
| 3 | <!-- Base application theme. --> | ||
| 4 | <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar"> | ||
| 5 | <!-- Customize your theme here. --> | ||
| 6 | <item name="android:editTextBackground">@drawable/rn_edit_text_material</item> | ||
| 7 | </style> | ||
| 8 | |||
| 9 | </resources> | ||
