diff --git a/.bundle/.gitignore b/.bundle/.gitignore new file mode 100644 index 0000000..5657f6e --- /dev/null +++ b/.bundle/.gitignore @@ -0,0 +1 @@ +vendor \ No newline at end of file diff --git a/.bundle/config b/.bundle/config new file mode 100644 index 0000000..3f4e4f3 --- /dev/null +++ b/.bundle/config @@ -0,0 +1,2 @@ +--- +BUNDLE_PATH: ".bundle/vendor" diff --git a/.gitignore b/.gitignore index 0bed683..7a6e365 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,7 @@ fastlane_secret_keys.json # App /app/debug -/app/release \ No newline at end of file +/app/release + +# Fastlane / Ruby +/vendor \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index e9e0c31..9b4bb4b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -8,23 +8,23 @@ GEM artifactory (3.0.15) atomos (0.1.3) aws-eventstream (1.2.0) - aws-partitions (1.543.0) - aws-sdk-core (3.125.0) + aws-partitions (1.615.0) + aws-sdk-core (3.131.6) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.525.0) aws-sigv4 (~> 1.1) - jmespath (~> 1.0) - aws-sdk-kms (1.53.0) - aws-sdk-core (~> 3, >= 3.125.0) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.58.0) + aws-sdk-core (~> 3, >= 3.127.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.110.0) - aws-sdk-core (~> 3, >= 3.125.0) + aws-sdk-s3 (1.114.0) + aws-sdk-core (~> 3, >= 3.127.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.4) - aws-sigv4 (1.4.0) + aws-sigv4 (1.5.1) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) - claide (1.0.3) + claide (1.1.0) colored (1.2) colored2 (3.1.2) commander (4.6.0) @@ -34,19 +34,20 @@ GEM rake (>= 12.0.0, < 14.0.0) domain_name (0.5.20190701) unf (>= 0.0.5, < 1.0.0) - dotenv (2.7.6) + dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.89.0) - faraday (1.8.0) + excon (0.92.4) + faraday (1.10.0) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) faraday-excon (~> 1.1) - faraday-httpclient (~> 1.0.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) faraday-net_http (~> 1.0) - faraday-net_http_persistent (~> 1.1) + faraday-net_http_persistent (~> 1.0) faraday-patron (~> 1.0) faraday-rack (~> 1.0) - multipart-post (>= 1.2, < 3) + faraday-retry (~> 1.0) ruby2_keywords (>= 0.0.4) faraday-cookie_jar (0.0.7) faraday (>= 0.8.0) @@ -55,14 +56,17 @@ GEM faraday-em_synchrony (1.0.0) faraday-excon (1.1.0) faraday-httpclient (1.0.1) + faraday-multipart (1.0.4) + multipart-post (~> 2) faraday-net_http (1.0.1) faraday-net_http_persistent (1.2.0) faraday-patron (1.0.0) faraday-rack (1.0.0) + faraday-retry (1.0.3) faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.2.6) - fastlane (2.199.0) + fastlane (2.208.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -102,9 +106,9 @@ GEM xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.14.0) - google-apis-core (>= 0.4, < 2.a) - google-apis-core (0.4.1) + google-apis-androidpublisher_v3 (0.25.0) + google-apis-core (>= 0.7, < 2.a) + google-apis-core (0.7.0) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.16.2, < 2.a) httpclient (>= 2.8.1, < 3.a) @@ -113,40 +117,40 @@ GEM retriable (>= 2.0, < 4.a) rexml webrick - google-apis-iamcredentials_v1 (0.9.0) - google-apis-core (>= 0.4, < 2.a) - google-apis-playcustomapp_v1 (0.6.0) - google-apis-core (>= 0.4, < 2.a) - google-apis-storage_v1 (0.10.0) - google-apis-core (>= 0.4, < 2.a) + google-apis-iamcredentials_v1 (0.13.0) + google-apis-core (>= 0.7, < 2.a) + google-apis-playcustomapp_v1 (0.10.0) + google-apis-core (>= 0.7, < 2.a) + google-apis-storage_v1 (0.17.0) + google-apis-core (>= 0.7, < 2.a) google-cloud-core (1.6.0) google-cloud-env (~> 1.0) google-cloud-errors (~> 1.0) - google-cloud-env (1.5.0) - faraday (>= 0.17.3, < 2.0) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) google-cloud-errors (1.2.0) - google-cloud-storage (1.35.0) + google-cloud-storage (1.38.0) addressable (~> 2.8) digest-crc (~> 0.4) google-apis-iamcredentials_v1 (~> 0.1) - google-apis-storage_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.17.0) google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (1.1.0) - faraday (>= 0.17.3, < 2.0) + googleauth (1.2.0) + faraday (>= 0.17.3, < 3.a) jwt (>= 1.4, < 3.0) memoist (~> 0.16) multi_json (~> 1.11) os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) highline (2.0.3) - http-cookie (1.0.4) + http-cookie (1.0.5) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.1) - json (2.6.1) - jwt (2.3.0) + json (2.6.2) + jwt (2.4.1) memoist (0.16.2) mini_magick (4.11.0) mini_mime (1.1.2) @@ -157,9 +161,9 @@ GEM optparse (0.1.1) os (1.1.4) plist (3.6.0) - public_suffix (4.0.6) + public_suffix (4.0.7) rake (13.0.6) - representable (3.1.1) + representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) @@ -169,9 +173,9 @@ GEM ruby2_keywords (0.0.5) rubyzip (2.3.2) security (0.1.3) - signet (0.16.0) + signet (0.17.0) addressable (~> 2.8) - faraday (>= 0.17.3, < 2.0) + faraday (>= 0.17.5, < 3.a) jwt (>= 1.5, < 3.0) multi_json (~> 1.10) simctl (1.6.8) @@ -188,12 +192,12 @@ GEM uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.8) - unf_ext (0.0.8-x64-mingw32) + unf_ext (0.0.8.2) + unf_ext (0.0.8.2-x64-mingw32) unicode-display_width (1.8.0) webrick (1.7.0) word_wrap (1.0.0) - xcodeproj (1.21.0) + xcodeproj (1.22.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) @@ -213,4 +217,4 @@ DEPENDENCIES fastlane BUNDLED WITH - 2.2.32 + 2.3.18 diff --git a/README.md b/README.md index e386356..3367922 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ No Ads are served through this app. Permissions requests are for specifics usage and are only requests the first time they are needed: | Permission | Why is it requested | -| :--------------------: | :--------------------------------------------------------------- | +| :--------------------: |:-----------------------------------------------------------------| | ACCESS_FINE_LOCATION | Google Fit Extension Requirement (maybe not, still have to test) | | ACCESS_COARSE_LOCATION | Same as above | | ACTIVITY_RECOGNITION | Device Steps Usage | diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index 9b94921..0000000 --- a/app/build.gradle +++ /dev/null @@ -1,166 +0,0 @@ -plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' - id 'kotlin-kapt' - id 'dagger.hilt.android.plugin' - - // Safe Navigation - id 'androidx.navigation.safeargs' -} - -android { - - signingConfigs { - - release { - - def keystorePropertiesFile = rootProject.file("./keystore.properties") - def keystoreProperties = new Properties() - try { - keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) - } catch (FileNotFoundException ignored) { - keystoreProperties = null - } - - if (keystoreProperties != null) { - storePassword keystoreProperties["storePassword"] - keyPassword keystoreProperties["keyPassword"] - keyAlias keystoreProperties["keyAlias"] - storeFile file(keystoreProperties["storeFile"]) - } - } - } - - compileSdk 32 - - defaultConfig { - // App ID - applicationId "com.dzeio.openhealth" - - // Android 5 Lollipop - minSdk 21 - - // Android 12 - targetSdk 32 - - // Semantic Versioning - versionName "1.0.0" - versionCode 1 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - - // Languages - def locales = ["en", "fr"] - - buildConfigField "String[]", "LOCALES", "new String[]{\""+locales.join("\",\"")+"\"}" - resConfigs locales - } - - buildTypes { - - release { - // Slimmer version - minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - signingConfig signingConfigs.release - } - - debug { - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - applicationIdSuffix ".dev" - versionNameSuffix '-dev' - debuggable true - - // make it debuggable - renderscriptDebuggable true - - // Optimization Level - renderscriptOptimLevel 0 - } - } - - // Compile using JAVA 8 - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - // Enable View Binding and Data Binding - buildFeatures { - viewBinding true - dataBinding true - } -} - -dependencies { - // Dzeio Charts - implementation project(path: ":charts") - - // Core dependencies - implementation 'androidx.core:core-ktx:1.8.0' - implementation 'androidx.appcompat:appcompat:1.4.2' - implementation 'javax.inject:javax.inject:1' - implementation 'com.google.android.material:material:1.7.0-alpha03' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' - implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.0' - implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.0' - - // Coroutines - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.3" - - // Settings - implementation "androidx.preference:preference-ktx:1.2.0" - - // DataStore - implementation "androidx.datastore:datastore:1.0.0" - - // Navigation - implementation 'androidx.navigation:navigation-fragment-ktx:2.5.0' - implementation 'androidx.navigation:navigation-ui-ktx:2.5.0' - - // Paging - implementation "androidx.paging:paging-runtime:3.1.1" - implementation "androidx.paging:paging-runtime-ktx:3.1.1" - - - // Services - implementation 'androidx.work:work-runtime-ktx:2.7.1' - - // Tests - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - - // Graph - implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' - - // Graphs test 2 - implementation 'com.github.HackPlan:AndroidCharts:1.0.4' - - // Hilt - implementation 'com.google.dagger:hilt-android:2.43' - kapt 'com.google.dagger:hilt-compiler:2.43' - - // Google Fit - implementation "com.google.android.gms:play-services-fitness:21.1.0" - implementation "com.google.android.gms:play-services-auth:20.2.0" - - // Samsung Health - implementation files('libs/samsung-health-data-1.5.0.aar') - implementation 'com.google.code.gson:gson:2.9.0' - - // ROOM - implementation "androidx.room:room-runtime:2.4.2" - kapt "androidx.room:room-compiler:2.4.2" - implementation "androidx.room:room-ktx:2.4.2" - testImplementation "androidx.room:room-testing:2.4.2" - - // Futures - implementation 'com.google.guava:guava:31.1-jre' - implementation "androidx.concurrent:concurrent-futures:1.1.0" - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.3' -} diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..37b25ea --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,174 @@ +import java.util.Properties + +plugins { + id("com.android.application") + kotlin("android") + kotlin("kapt") + id("dagger.hilt.android.plugin") + + // Safe Navigation + id("androidx.navigation.safeargs") +} + +android { + + signingConfigs { + + create("release") { + + val keystoreProperties = Properties().apply { + load(rootProject.file("./keystore.properties").reader()) + } + + if (keystoreProperties.isNotEmpty()) { + storePassword = keystoreProperties["storePassword"] as String + keyPassword = keystoreProperties["keyPassword"] as String + keyAlias = keystoreProperties["keyAlias"] as String + storeFile = file(keystoreProperties["storeFile"] as String) + } + } + } + + compileSdk = 33 + + defaultConfig { + // App ID + applicationId = "com.dzeio.openhealth" + + // Android 5 Lollipop + minSdk = 21 + + // Android 12 + targetSdk = 33 + + // Semantic Versioning + versionName = "1.0.0" + versionCode = 1 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + // Languages + val locales = listOf("en", "fr") + + buildConfigField( + "String[]", + "LOCALES", + "new String[]{\"" + locales.joinToString("\",\"") + "\"}" + ) + resourceConfigurations += locales + } + + buildTypes { + + getByName("release") { + // Slimmer version + isMinifyEnabled = true + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + signingConfig = signingConfigs.getByName("release") + } + + getByName("debug") { + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + applicationIdSuffix = ".dev" + versionNameSuffix = "-dev" + isDebuggable = true + + // make it debuggable + isRenderscriptDebuggable = true + + // Optimization Level + renderscriptOptimLevel = 0 + } + } + + // Compile using JAVA 8 + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" + } + + // Enable View Binding and Data Binding + buildFeatures { + viewBinding = true + dataBinding = true + } + namespace = "com.dzeio.openhealth" +} + +dependencies { + // Dzeio Charts + implementation(project(":charts")) +// implementation(project(":CrashHandler")) + + implementation("com.dzeio:crashhandler:1.0.1") + + // Core dependencies + implementation("androidx.core:core-ktx:1.8.0") + implementation("androidx.appcompat:appcompat:1.6.0-alpha05") + implementation("javax.inject:javax.inject:1") + implementation("com.google.android.material:material:1.7.0-alpha03") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.5.1") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1") + +// implementation("com.github.Aviortheking:crashhandler:0.2.3") + + // Coroutines + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4") + + // Settings + implementation("androidx.preference:preference-ktx:1.2.0") + + // DataStore + implementation("androidx.datastore:datastore:1.0.0") + + // Navigation + implementation("androidx.navigation:navigation-fragment-ktx:2.5.1") + implementation("androidx.navigation:navigation-ui-ktx:2.5.1") + + // Paging + implementation("androidx.paging:paging-runtime:3.1.1") + implementation("androidx.paging:paging-runtime-ktx:3.1.1") + + + // Services + implementation("androidx.work:work-runtime-ktx:2.7.1") + + // Tests + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") + + // Graph + implementation("com.github.PhilJay:MPAndroidChart:v3.1.0") + + // Graphs test 2 + implementation("com.github.HackPlan:AndroidCharts:1.0.4") + + // Hilt + implementation("com.google.dagger:hilt-android:2.43.2") + kapt("com.google.dagger:hilt-compiler:2.43.2") + + // Google Fit + implementation("com.google.android.gms:play-services-fitness:21.1.0") + implementation("com.google.android.gms:play-services-auth:20.2.0") + + // Samsung Health + implementation(files("libs/samsung-health-data-1.5.0.aar")) + implementation("com.google.code.gson:gson:2.9.1") + + // ROOM + implementation("androidx.room:room-runtime:2.4.3") + kapt("androidx.room:room-compiler:2.4.3") + implementation("androidx.room:room-ktx:2.4.3") + testImplementation("androidx.room:room-testing:2.4.3") + + // Futures + implementation("com.google.guava:guava:31.1-jre") + implementation("androidx.concurrent:concurrent-futures:1.1.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.4") +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb43..ff59496 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html diff --git a/app/src/debug/res/drawable-v24/ic_launcher_foreground.xml b/app/src/debug/res/drawable-v24/ic_launcher_foreground.xml index 5ec3d6a..f46d79a 100644 --- a/app/src/debug/res/drawable-v24/ic_launcher_foreground.xml +++ b/app/src/debug/res/drawable-v24/ic_launcher_foreground.xml @@ -1,7 +1,7 @@ - - + + + diff --git a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 7353dbd..0000000 --- a/app/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index c334358..0000000 Binary files a/app/src/debug/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 3d45a57..0000000 Binary files a/app/src/debug/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 24fde3b..0000000 Binary files a/app/src/debug/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 32e2771..0000000 Binary files a/app/src/debug/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 8c77946..0000000 Binary files a/app/src/debug/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/debug/res/values/strings.xml b/app/src/debug/res/values/strings.xml index 84cd8f4..90bcf03 100644 --- a/app/src/debug/res/values/strings.xml +++ b/app/src/debug/res/values/strings.xml @@ -1,4 +1,4 @@ - OpenHealth - Debug + Open Health - Debug diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9b99bee..598e614 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,9 @@ - + + + + @@ -15,11 +18,11 @@ @@ -44,14 +47,22 @@ - - - + + + + + + diff --git a/app/src/main/java/com/dzeio/openhealth/Application.kt b/app/src/main/java/com/dzeio/openhealth/Application.kt index 38ae96d..491b442 100644 --- a/app/src/main/java/com/dzeio/openhealth/Application.kt +++ b/app/src/main/java/com/dzeio/openhealth/Application.kt @@ -1,16 +1,13 @@ package com.dzeio.openhealth import android.app.Application -import android.content.Intent -import android.content.SharedPreferences -import android.os.Process -import android.util.Log +import android.content.Context import androidx.preference.PreferenceManager +import com.dzeio.crashhandler.CrashHandler import com.dzeio.openhealth.ui.ErrorActivity +import com.dzeio.openhealth.utils.LocaleUtils import com.google.android.material.color.DynamicColors import dagger.hilt.android.HiltAndroidApp -import java.util.Locale -import kotlin.system.exitProcess @HiltAndroidApp class Application : Application() { @@ -20,42 +17,24 @@ class Application : Application() { override fun onCreate() { - // Application Error Handling - Thread.setDefaultUncaughtExceptionHandler { paramThread, paramThrowable -> - //Log error to logcat if it wasn't done before - Log.e(TAG, "En error was detected in the Thread ${paramThread.id}, trying to go to ErrorActivity") + val prefs = PreferenceManager.getDefaultSharedPreferences(this) - // send use to the Error Activity - val intent = Intent(applicationContext, ErrorActivity::class.java) - - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) - intent.putExtra("error", paramThrowable.stackTraceToString()) - intent.putExtra("threadId", paramThread.id) - startActivity(intent) - Log.e(TAG, "Activity should have started") - - Process.killProcess(Process.myPid()) - exitProcess(10) - } + CrashHandler.Builder() + .withActivity(ErrorActivity::class.java) + .withPrefs(prefs) + .witheErrorReporterCrashKey(R.string.error_reporter_crash) + .withPrefsKey(Settings.CRASH_LAST_TIME) + .withPrefix("${BuildConfig.APPLICATION_ID} v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})") + .build() + .setup(this) // Android Dynamics Colors DynamicColors.applyToActivitiesIfAvailable(this) - // Change application Language based on setting - val preferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) - val lang = preferences.getString("global_language", Locale.getDefault().language) - if (lang == null) { - Log.e(TAG, "lang is null") - } else { - val locale = Locale(lang) - Locale.setDefault(locale) - } - -// val overrideConfiguration = baseContext.resources.configuration -// overrideConfiguration.locale = locale -// val context: Context = createConfigurationContext(overrideConfiguration) -// val resources: Resources = context.resources - super.onCreate() } + + override fun attachBaseContext(base: Context) { + super.attachBaseContext(LocaleUtils.onAttach(base)) + } } diff --git a/app/src/main/java/com/dzeio/openhealth/Settings.kt b/app/src/main/java/com/dzeio/openhealth/Settings.kt new file mode 100644 index 0000000..7f23c07 --- /dev/null +++ b/app/src/main/java/com/dzeio/openhealth/Settings.kt @@ -0,0 +1,19 @@ +package com.dzeio.openhealth + +object Settings { + + /** + * get the last time the Application has crashed + * + * type: Long + */ + const val CRASH_LAST_TIME = "com.dzeio.open-health.crash.last_time" + + /** + * The software override application language + * + * note: also change it in `preferences.xml` + */ + const val APP_LANGUAGE = "com.dzeio.open-health.app.language" + +} \ No newline at end of file diff --git a/app/src/main/java/com/dzeio/openhealth/data/step/StepSource.kt b/app/src/main/java/com/dzeio/openhealth/data/step/StepSource.kt index 79a8e6c..f8a2d1e 100644 --- a/app/src/main/java/com/dzeio/openhealth/data/step/StepSource.kt +++ b/app/src/main/java/com/dzeio/openhealth/data/step/StepSource.kt @@ -10,8 +10,6 @@ import android.util.Log import androidx.preference.PreferenceManager import com.dzeio.openhealth.Application import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.runBlocking class StepSource( @@ -78,7 +76,9 @@ class StepSource( timeSinceLastRecord = timeSinceLastBoot runBlocking { - events.send(diff) + if (events != null) { + events.send(diff) + } } callback?.invoke(diff) } diff --git a/app/src/main/java/com/dzeio/openhealth/services/OpenHealthService.kt b/app/src/main/java/com/dzeio/openhealth/services/OpenHealthService.kt index 70c4a48..461da37 100644 --- a/app/src/main/java/com/dzeio/openhealth/services/OpenHealthService.kt +++ b/app/src/main/java/com/dzeio/openhealth/services/OpenHealthService.kt @@ -120,9 +120,9 @@ class OpenHealthService : Service() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_IMMUTABLE else 0 val intent = NavDeepLinkBuilder(this) .setGraph(R.navigation.mobile_navigation) - .setDestination(R.id.nav_home) - // Will nav to water home when there will be a way to add it there -// .setDestination(R.id.nav_water_home) +// .setDestination(R.id.nav_home) +// Will nav to water home when there will be a way to add it there + .setDestination(R.id.nav_steps_home) .createTaskStackBuilder() .getPendingIntent(0, flag) diff --git a/app/src/main/java/com/dzeio/openhealth/ui/ErrorActivity.kt b/app/src/main/java/com/dzeio/openhealth/ui/ErrorActivity.kt index 676df6f..77dcfd6 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/ErrorActivity.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/ErrorActivity.kt @@ -17,7 +17,7 @@ import kotlin.system.exitProcess class ErrorActivity : BaseActivity() { companion object { - const val TAG = "${Application.TAG}/ErrorActivity" + const val TAG = "${Application.TAG}/ErrorActivit" } override val bindingInflater: (LayoutInflater) -> ActivityErrorBinding = diff --git a/app/src/main/java/com/dzeio/openhealth/ui/MainActivity.kt b/app/src/main/java/com/dzeio/openhealth/ui/MainActivity.kt index aee042b..302b907 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/MainActivity.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/MainActivity.kt @@ -1,6 +1,5 @@ package com.dzeio.openhealth.ui -import android.app.ActivityManager import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context @@ -12,7 +11,9 @@ import android.util.Log import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem +import android.view.WindowManager import androidx.core.view.WindowCompat +import androidx.core.view.updatePadding import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.AppBarConfiguration @@ -26,8 +27,8 @@ import com.dzeio.openhealth.core.BaseActivity import com.dzeio.openhealth.databinding.ActivityMainBinding import com.dzeio.openhealth.interfaces.NotificationChannels import com.dzeio.openhealth.services.OpenHealthService +import com.dzeio.openhealth.utils.ServiceUtils import com.dzeio.openhealth.workers.WaterReminderWorker -import com.google.android.material.color.MaterialColors import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -55,28 +56,52 @@ class MainActivity : BaseActivity() { setSupportActionBar(binding.toolbar) - window.navigationBarColor = MaterialColors.getColor( - window.decorView, - com.google.android.material.R.attr.colorSecondaryContainer - ) - window.statusBarColor = MaterialColors.getColor( - window.decorView, - com.google.android.material.R.attr.colorSecondaryContainer - ) + // Comportement chelou API 28- + // Comportement normal 31+ - when (this.resources.configuration.uiMode.and(Configuration.UI_MODE_NIGHT_MASK)) { - Configuration.UI_MODE_NIGHT_YES -> { - WindowCompat.getInsetsController(window, window.decorView).apply { - isAppearanceLightNavigationBars = true - isAppearanceLightStatusBars = false - } - } - Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_UNDEFINED -> { - WindowCompat.getInsetsController(window, window.decorView).apply { - isAppearanceLightNavigationBars = false - isAppearanceLightStatusBars = true + // do not do the cool status/navigation bars for API 29 & 30 + if (Build.VERSION.SDK_INT != Build.VERSION_CODES.R && Build.VERSION.SDK_INT != Build.VERSION_CODES.Q) { + // allow to put the content behind the status bar & Navigation bar (one of them at least lul) + // ALSO: make the status/navigation bars semi-transparent + window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) + window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) + + // Make the color of the navigation bar semi-transparent +// window.navigationBarColor = Color.TRANSPARENT + // Make the color of the status bar transparent +// window.statusBarColor = Color.TRANSPARENT + // Apply the previous changes +// window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + + // Update toolbar height with the statusbar size included + // ALSO: make both the status/navigation bars transparent (WHYYYYYYY) + val toolbarHeight = binding.toolbar.layoutParams.height + window.decorView.setOnApplyWindowInsetsListener { _, insets -> + val statusBarSize = insets.systemWindowInsetTop + // Add padding to the toolbar (YaY I know how something works) + binding.toolbar.updatePadding(top = statusBarSize) + binding.toolbar.layoutParams.height = toolbarHeight + statusBarSize + return@setOnApplyWindowInsetsListener insets + } + + // normally makes sure icons are at the correct color but idk if it works + when (this.resources.configuration.uiMode.and(Configuration.UI_MODE_NIGHT_MASK)) { + Configuration.UI_MODE_NIGHT_YES -> { + WindowCompat.getInsetsController(window, window.decorView).apply { + // force to display the bars in light color + isAppearanceLightNavigationBars = true + isAppearanceLightStatusBars = false // WHY + } + } + Configuration.UI_MODE_NIGHT_NO, Configuration.UI_MODE_NIGHT_UNDEFINED -> { + WindowCompat.getInsetsController(window, window.decorView).apply { + // force to display the bars in dark color + isAppearanceLightNavigationBars = false + isAppearanceLightStatusBars = true // WHY + } } } + } val navHostFragment = @@ -108,20 +133,9 @@ class MainActivity : BaseActivity() { WaterReminderWorker.setup(this) // StepCountService.setup(this) - this.betterStartService(OpenHealthService::class.java) + ServiceUtils.startService(this, OpenHealthService::class.java) } - private fun betterStartService(service: Class) { - val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager - for (runninService in activityManager.getRunningServices(Integer.MAX_VALUE)) { - if (service.name.equals(runninService.service.className)) { - Log.w(TAG, "Service already existing, not starting again") - return - } - } - Log.i(TAG, "Starting service ${service.name}") - Intent(this, service).also { intent -> startService(intent) } - } override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) diff --git a/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseFragment.kt index b8110dd..c62e087 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/browse/BrowseFragment.kt @@ -31,9 +31,9 @@ class BrowseFragment : private lateinit var button: MaterialCardView private val activityResult = registerForActivityResult( - ActivityResultContracts.RequestPermission() + ActivityResultContracts.RequestMultiplePermissions() ) { - if (!it) { + if (it.containsValue(false)) { // TODO: Show a popup with choice to change it Toast.makeText(requireContext(), R.string.permission_declined, Toast.LENGTH_LONG).show() return@registerForActivityResult @@ -55,14 +55,29 @@ class BrowseFragment : binding.steps.setOnClickListener { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - val hasPermission = PermissionsManager.hasPermission( + val activityPermission = PermissionsManager.hasPermission( requireContext(), Manifest.permission.ACTIVITY_RECOGNITION ) - if (!hasPermission) { + val notificationPermission = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && PermissionsManager.hasPermission( + requireContext(), + Manifest.permission.POST_NOTIFICATIONS + ) + + val permissionsToAsk = arrayListOf() + + if (!activityPermission) { + permissionsToAsk.add(Manifest.permission.ACTIVITY_RECOGNITION) + } + + if (!notificationPermission && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + permissionsToAsk.add(Manifest.permission.POST_NOTIFICATIONS) + } + + if (permissionsToAsk.isNotEmpty()) { button = binding.steps - activityResult.launch(Manifest.permission.ACTIVITY_RECOGNITION) + activityResult.launch(permissionsToAsk.toTypedArray()) return@setOnClickListener } } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt index 1e33b0c..1aef91b 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/home/HomeFragment.kt @@ -5,9 +5,7 @@ import android.content.SharedPreferences import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.RectF -import android.os.Bundle import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController @@ -37,9 +35,8 @@ class HomeFragment : BaseFragment(HomeViewMo PreferenceManager.getDefaultSharedPreferences(requireContext()) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - + override fun onStart() { + super.onStart() // Bindings binding.addWeight.setOnClickListener { AddWeightDialog().show(requireActivity().supportFragmentManager, null) @@ -56,10 +53,12 @@ class HomeFragment : BaseFragment(HomeViewMo viewModel.updateWater(water) } } + val waterUnit = + UnitFactory.volume(settings.getString("water_unit", "milliliter") ?: "Milliliter") binding.fragmentHomeWaterTotal.text = String.format( - resources.getString(viewModel.waterUnit.unit), + resources.getString(waterUnit.unit), viewModel.dailyWaterIntake ) @@ -94,6 +93,21 @@ class HomeFragment : BaseFragment(HomeViewMo com.google.android.material.R.attr.colorOnBackground ) ) + + lifecycleScope.launchWhenStarted { + viewModel.fetchWeights().collectLatest { + updateGraph(it) + } + updateWater(0) + } + + viewModel.water.observe(viewLifecycleOwner) { + if (it != null) { + updateWater(it.value) + } else { + updateWater(0) + } + } } private fun updateGraph(list: List) { @@ -119,25 +133,6 @@ class HomeFragment : BaseFragment(HomeViewMo // } } - override fun onStart() { - super.onStart() - - lifecycleScope.launchWhenStarted { - viewModel.fetchWeights().collectLatest { - updateGraph(it) - } - updateWater(0) - } - - viewModel.water.observe(viewLifecycleOwner) { - if (it != null) { - updateWater(it.value) - } else { - updateWater(0) - } - } - } - private var oldValue = 0f private fun updateWater(newValue: Int) { @@ -151,6 +146,12 @@ class HomeFragment : BaseFragment(HomeViewMo (newValue * waterUnit.modifier).toInt() ) + binding.fragmentHomeWaterTotal.text = + String.format( + resources.getString(waterUnit.unit), + viewModel.dailyWaterIntake + ) + var width = 1500 var height = 750 diff --git a/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt index f6a29b3..5fc4988 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/settings/SettingsFragment.kt @@ -1,7 +1,7 @@ package com.dzeio.openhealth.ui.settings import android.content.SharedPreferences -import android.content.res.Configuration +import android.os.Build import android.os.Bundle import android.text.InputType import android.util.Log @@ -9,13 +9,20 @@ import androidx.preference.EditTextPreference import androidx.preference.ListPreference import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceManager +import com.dzeio.openhealth.Application import com.dzeio.openhealth.BuildConfig import com.dzeio.openhealth.R +import com.dzeio.openhealth.Settings import com.dzeio.openhealth.units.UnitFactory +import com.dzeio.openhealth.utils.LocaleUtils import java.util.Locale class SettingsFragment : PreferenceFragmentCompat() { + private companion object { + const val TAG = "${Application.TAG}/SttngsFrgmnt" + } + val settings: SharedPreferences by lazy { PreferenceManager.getDefaultSharedPreferences(requireContext()) } @@ -71,8 +78,8 @@ class SettingsFragment : PreferenceFragmentCompat() { } } - val languagesPreference = findPreference("global_language") - Log.d("TAG", Locale.getDefault().language) + val languagesPreference = findPreference(Settings.APP_LANGUAGE) + Log.d(TAG, Locale.getDefault().language) languagesPreference?.apply { entries = BuildConfig.LOCALES entryValues = BuildConfig.LOCALES @@ -81,17 +88,10 @@ class SettingsFragment : PreferenceFragmentCompat() { // Update App Locale languagesPreference?.setOnPreferenceChangeListener { _, newValue -> - val locale = Locale(newValue as String) - Locale.setDefault(locale) - val config = Configuration() - config.locale = locale - - requireActivity().baseContext.resources.updateConfiguration( - config, - requireActivity().baseContext.resources.displayMetrics - ) - - requireActivity().recreate() + LocaleUtils.setLanguage(requireContext(), newValue as String) + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + requireActivity().recreate() + } return@setOnPreferenceChangeListener true } diff --git a/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt b/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt index 0d166b6..434b4b0 100644 --- a/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt +++ b/app/src/main/java/com/dzeio/openhealth/ui/steps/StepsHomeFragment.kt @@ -13,9 +13,6 @@ import com.dzeio.openhealth.core.BaseFragment import com.dzeio.openhealth.databinding.FragmentStepsHomeBinding import com.google.android.material.color.MaterialColors import dagger.hilt.android.AndroidEntryPoint -import java.text.DateFormat -import java.util.Date -import java.util.Locale @AndroidEntryPoint class StepsHomeFragment : @@ -50,66 +47,64 @@ class StepsHomeFragment : val chart = binding.chart - val serie = BarSerie() + val serie = BarSerie(chart) chart.series = arrayListOf(serie) viewModel.items.observe(viewLifecycleOwner) { list -> adapter.set(list) -// chart.debug = true - - chart.xAxis.entriesDisplayed = 10 -// chart.numberOfLabels = 2 + chart.debug = true // chart.animation.enabled = false - chart.animation.refreshRate = 60 - chart.animation.duration = 300 +// chart.animation.refreshRate = 60 +// chart.animation.duration = 300 - chart.scroller.zoomEnabled = false +// chart.scroller.zoomEnabled = false - chart.xAxis.labels.color = MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorOnBackground - ) +// chart.xAxis.labels.color = MaterialColors.getColor( +// requireView(), +// com.google.android.material.R.attr.colorOnBackground +// ) - chart.xAxis.labels.size = 32f +// chart.xAxis.labels.size = 32f chart.yAxis.apply { - color = MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorPrimary - ) - textPaint.color = MaterialColors.getColor( + setYMin(0f) + textLabel.color = MaterialColors.getColor( requireView(), com.google.android.material.R.attr.colorOnBackground ) - linePaint.color = MaterialColors.getColor( - requireView(), - com.google.android.material.R.attr.colorOutline - ) - onValueFormat = onValueFormat@{ value, short -> - if (short) { - return@onValueFormat value.toInt().toString() - } else { - return@onValueFormat "${value.toInt()} steps" - } - } +// linePaint.color = MaterialColors.getColor( +// requireView(), +// com.google.android.material.R.attr.colorOutline +// ) +// onValueFormat = onValueFormat@{ value, short -> +// if (short) { +// return@onValueFormat value.toInt().toString() +// } else { +// return@onValueFormat "${value.toInt()} steps" +// } +// } } - serie.datas = list.reversed().map { + serie.entries = list.reversed().map { return@map Entry(it.timestamp.toDouble(), it.value.toFloat()) } as ArrayList - chart.xAxis.onValueFormat = onValueFormat@{ - val formatter = DateFormat.getDateTimeInstance( - DateFormat.SHORT, - DateFormat.SHORT, - Locale.getDefault() - ) - return@onValueFormat formatter.format(Date(it.toLong())) + chart.xAxis.apply { + increment = (1000 * 60 * 60).toDouble() + displayCount = 24 * 7 + x = serie.entries.first().x } -// chart.yAxis.max = (total / list.size).toInt() +// chart.xAxis.onValueFormat = onValueFormat@{ +// val formatter = DateFormat.getDateTimeInstance( +// DateFormat.SHORT, +// DateFormat.SHORT, +// Locale.getDefault() +// ) +// return@onValueFormat formatter.format(Date(it.toLong())) +// } chart.refresh() } diff --git a/app/src/main/java/com/dzeio/openhealth/utils/LocaleUtils.kt b/app/src/main/java/com/dzeio/openhealth/utils/LocaleUtils.kt new file mode 100644 index 0000000..70819d5 --- /dev/null +++ b/app/src/main/java/com/dzeio/openhealth/utils/LocaleUtils.kt @@ -0,0 +1,76 @@ +package com.dzeio.openhealth.utils + +import android.app.LocaleManager +import android.content.Context +import android.content.res.Configuration +import android.os.Build +import android.os.LocaleList +import android.util.Log +import androidx.preference.PreferenceManager +import com.dzeio.openhealth.Settings +import java.util.Locale + + +/** + * Utils object for [Locale] + * + * @see https://github.com/gunhansancar/ChangeLanguageExample/blob/master/app/src/main/java/com/gunhansancar/changelanguageexample/helper/LocaleHelper.java + */ +object LocaleUtils { + fun onAttach(context: Context): Context { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + val lang = getPersistedData(context) + return setLanguage(context, lang) + } + return context + } + + fun getLanguage(context: Context): String { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + return context.getSystemService(LocaleManager::class.java) + .applicationLocales.get(0).language + } + return getPersistedData(context) + } + + fun setLanguage(context: Context, language: String): Context { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + context.getSystemService(LocaleManager::class.java) + .applicationLocales = + LocaleList.forLanguageTags(language) + } + persist(context, language) + return updateResources(context, language) + } + + private fun getPersistedData(context: Context): String { + val preferences = PreferenceManager.getDefaultSharedPreferences(context) + return preferences.getString(Settings.APP_LANGUAGE, Locale.getDefault().language) + ?: Locale.getDefault().language + } + + private fun persist(context: Context, language: String?) { + val preferences = PreferenceManager.getDefaultSharedPreferences(context) + preferences.edit().putString(Settings.APP_LANGUAGE, language).apply() + } + + private fun updateResources(context: Context, language: String): Context { + Log.d("LocaleUtils", language) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + val locale = Locale(language) + Locale.setDefault(locale) + val configuration = context.resources.configuration + configuration.setLocale(locale) + configuration.setLayoutDirection(locale) + return context.createConfigurationContext(configuration) + } + val locale = Locale(language) + Locale.setDefault(locale) + val resources = context.resources + val configuration: Configuration = resources.configuration + configuration.locale = locale + configuration.setLayoutDirection(locale) + resources.updateConfiguration(configuration, resources.displayMetrics) + return context + } +} \ No newline at end of file diff --git a/app/src/main/java/com/dzeio/openhealth/utils/PermissionsManager.kt b/app/src/main/java/com/dzeio/openhealth/utils/PermissionsManager.kt index 0014a1e..a8c6a76 100644 --- a/app/src/main/java/com/dzeio/openhealth/utils/PermissionsManager.kt +++ b/app/src/main/java/com/dzeio/openhealth/utils/PermissionsManager.kt @@ -2,10 +2,20 @@ package com.dzeio.openhealth.utils import android.content.Context import android.content.pm.PackageManager +import android.os.Build +import androidx.core.content.ContextCompat object PermissionsManager { - fun hasPermission(context: Context, permission: String): Boolean = context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED + fun hasPermission(context: Context, permission: String): Boolean = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED + } else { + ContextCompat.checkSelfPermission( + context, + permission + ) == PackageManager.PERMISSION_GRANTED + } fun hasPermission(context: Context, permissions: Array): Boolean { for (permission in permissions) { diff --git a/app/src/main/java/com/dzeio/openhealth/utils/ServiceUtils.kt b/app/src/main/java/com/dzeio/openhealth/utils/ServiceUtils.kt new file mode 100644 index 0000000..4413afe --- /dev/null +++ b/app/src/main/java/com/dzeio/openhealth/utils/ServiceUtils.kt @@ -0,0 +1,21 @@ +package com.dzeio.openhealth.utils + +import android.app.ActivityManager +import android.content.Context +import android.content.Intent +import android.util.Log +import com.dzeio.openhealth.ui.MainActivity + +object ServiceUtils { + fun startService(context: Context, service: Class) { + val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + for (runninService in activityManager.getRunningServices(Integer.MAX_VALUE)) { + if (service.name.equals(runninService.service.className)) { + Log.w(MainActivity.TAG, "Service already existing, not starting again") + return + } + } + Log.i(MainActivity.TAG, "Starting service ${service.name}") + Intent(context, service).also { intent -> context.startService(intent) } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 2ffcc7d..be7f15c 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -2,6 +2,7 @@ @@ -14,28 +15,32 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" + android:fitsSystemWindows="false" tools:context=".ui.MainActivity"> + android:layout_height="wrap_content" + android:fitsSystemWindows="false"> + android:fitsSystemWindows="false" + android:background="@android:color/transparent" + app:titleCentered="true" + app:layout_collapseMode="pin" + android:elevation="0dp" /> @@ -59,6 +64,7 @@ + android:layout_marginBottom="16dp" + app:cardBackgroundColor="?attr/colorOnSurfaceInverse"> + android:paddingVertical="8dp" + android:src="@drawable/ic_outline_favorite_24" + app:backgroundTint="@android:color/transparent" + app:tint="?attr/colorSurfaceInverse" /> + android:text="Heart Rate" + android:textColor="?attr/colorSurfaceInverse" /> + + + @@ -209,10 +217,9 @@ + app:backgroundTint="@android:color/transparent" + app:tint="?attr/colorSurfaceInverse" /> diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index f775b2c..d949f54 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -17,9 +17,8 @@ style="?attr/materialCardViewFilledStyle" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="16dp" + android:layout_marginHorizontal="16dp" android:layout_marginTop="16dp" - android:layout_marginEnd="16dp" android:layout_weight="1"> + android:orientation="horizontal"> - - - - + @@ -90,17 +82,23 @@ + android:textAlignment="center" + android:textColor="?attr/colorPrimary" /> + @@ -135,6 +133,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -153,9 +258,8 @@ style="?attr/materialCardViewFilledStyle" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginStart="16dp" - android:layout_marginTop="16dp" - android:layout_marginEnd="16dp"> + android:layout_marginHorizontal="16dp" + android:layout_marginTop="16dp"> + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 7353dbd..0000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index a4b162c..0000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index df9c3f2..0000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index ead7fc9..0000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 9bcd797..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index f6274b0..0000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 8043ba8..e28e400 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -170,7 +170,7 @@ app:destination="@id/nav_list_weight" /> + app:destination="@id/nav_steps_home" /> @@ -180,7 +180,7 @@ android:label="@string/menu_activity" tools:layout="@layout/fragment_activity" /> diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index be35cd3..e0f0b41 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -47,4 +47,7 @@ Envoyer par Email Envoyer depuis Github Quitter + Pas pris + Erreur lors de la géneration d\'un rapport d\'erreur + diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index fb9b599..a4e53a7 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -1,3 +1,4 @@ + - -