From 6e96a6b7c2971368bf515ad51796ac5405e4a8d2 Mon Sep 17 00:00:00 2001 From: andrekir Date: Thu, 19 Jan 2023 11:24:42 -0300 Subject: [PATCH] feat: add fdroid and google flavors --- .github/workflows/android.yml | 13 ++- .github/workflows/release.yml | 33 ++++-- app/build.gradle | 24 ++-- .../geeksville/mesh/MeshUtilApplication.kt | 16 +++ .../mesh/analytics/AnalyticsClient.kt | 42 +++++++ .../mesh/analytics/FirebaseAnalytics.kt | 46 ++++++++ .../mesh/android/GeeksvilleApplication.kt | 107 ++++++++++++++++++ .../geeksville/mesh/MeshUtilApplication.kt | 0 .../mesh/analytics/AnalyticsClient.kt | 0 .../mesh/analytics/FirebaseAnalytics.kt | 0 .../mesh/android/GeeksvilleApplication.kt | 0 build.gradle | 8 +- 12 files changed, 267 insertions(+), 22 deletions(-) create mode 100644 app/src/fdroid/java/com/geeksville/mesh/MeshUtilApplication.kt create mode 100644 app/src/fdroid/java/com/geeksville/mesh/analytics/AnalyticsClient.kt create mode 100644 app/src/fdroid/java/com/geeksville/mesh/analytics/FirebaseAnalytics.kt create mode 100644 app/src/fdroid/java/com/geeksville/mesh/android/GeeksvilleApplication.kt rename app/src/{main => google}/java/com/geeksville/mesh/MeshUtilApplication.kt (100%) rename app/src/{main => google}/java/com/geeksville/mesh/analytics/AnalyticsClient.kt (100%) rename app/src/{main => google}/java/com/geeksville/mesh/analytics/FirebaseAnalytics.kt (100%) rename app/src/{main => google}/java/com/geeksville/mesh/android/GeeksvilleApplication.kt (100%) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 364ced3b..1800c695 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -36,9 +36,16 @@ jobs: - name: Build debug APK run: ./gradlew assembleDebug - - name: Upload APK + - name: Upload F-Droid APK uses: actions/upload-artifact@v3 with: - name: app-debug - path: app/build/outputs/apk/debug/app-debug.apk + name: fdroidDebug + path: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk + retention-days: 30 + + - name: Upload Google APK + uses: actions/upload-artifact@v3 + with: + name: googleDebug + path: app/build/outputs/apk/google/debug/app-google-debug.apk retention-days: 30 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a1320702..6caf8485 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -78,11 +78,14 @@ jobs: - name: Validate Gradle wrapper uses: gradle/wrapper-validation-action@v1 - - name: Gradle bundleRelease - run: ./gradlew bundleRelease + - name: Build F-Droid release + run: ./gradlew assembleFdroidRelease - - name: Gradle assembleRelease - run: ./gradlew assembleRelease + - name: Enable Crashlytics + run: sed -i 's/useCrashlytics = false/useCrashlytics = true/g' ./build.gradle + + - name: Build Play Store release + run: ./gradlew bundleGoogleRelease assembleGoogleRelease # - name: Upload Release to Play Store # run: cp ./app/src/main/play/release-notes/en-US/production.txt ./app/src/main/play/release-notes/whatsnew-en-US.txt @@ -108,24 +111,34 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Add AAB to release + - name: Add F-Droid APK to release uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: app/build/outputs/bundle/release/app-release.aab - asset_name: app-release-${{ github.event.inputs.version}}.aab + asset_path: app/build/outputs/apk/fdroid/release/app-fdroid-release.apk + asset_name: fdroidRelease-${{ github.event.inputs.version}}.apk asset_content_type: application/zip - - name: Add APK to release + - name: Add Play Store AAB to release uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: app/build/outputs/apk/release/app-release.apk - asset_name: app-release-${{ github.event.inputs.version}}.apk + asset_path: app/build/outputs/bundle/googleRelease/app-google-release.aab + asset_name: googleRelease-${{ github.event.inputs.version}}.aab + asset_content_type: application/zip + + - name: Add Play Store APK to release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: app/build/outputs/apk/google/release/app-google-release.apk + asset_name: googleRelease-${{ github.event.inputs.version}}.apk asset_content_type: application/zip # - name: Gradle publishBundle diff --git a/app/build.gradle b/app/build.gradle index 403be2a0..e9e88acc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,10 +11,6 @@ plugins { // protobufs id 'com.google.protobuf' - - // Firebase Crashlytics - id 'com.google.gms.google-services' - id 'com.google.firebase.crashlytics' } unMock { @@ -49,6 +45,20 @@ android { // per https://developer.android.com/studio/write/vector-asset-studio vectorDrawables.useSupportLibrary = true } + flavorDimensions 'default' + productFlavors { + fdroid { + dimension = 'default' + } + google { + dimension = 'default' + if (project.findProperty("useCrashlytics") == true) { + println("useCrashlytics plugins $useCrashlytics") + apply plugin: 'com.google.gms.google-services' + apply plugin: 'com.google.firebase.crashlytics' + } + } + } buildTypes { release { if (keystoreProperties['storeFile']) { @@ -195,9 +205,9 @@ dependencies { // implementation 'com.google.android.things:androidthings:1.0' implementation 'com.github.mik3y:usb-serial-for-android:3.4.6' - // Add the Firebase SDK for Crashlytics. - implementation 'com.google.firebase:firebase-crashlytics:18.2.6' - implementation 'com.google.firebase:firebase-analytics:20.1.0' + // For Firebase Crashlytics & Analytics + googleImplementation 'com.google.firebase:firebase-crashlytics:18.2.6' + googleImplementation 'com.google.firebase:firebase-analytics:20.1.0' // barcode support // per https://github.com/journeyapps/zxing-android-embedded#older-sdk-versions for minSdkVersion 21 diff --git a/app/src/fdroid/java/com/geeksville/mesh/MeshUtilApplication.kt b/app/src/fdroid/java/com/geeksville/mesh/MeshUtilApplication.kt new file mode 100644 index 00000000..b5ca0980 --- /dev/null +++ b/app/src/fdroid/java/com/geeksville/mesh/MeshUtilApplication.kt @@ -0,0 +1,16 @@ +package com.geeksville.mesh + +import com.geeksville.mesh.android.GeeksvilleApplication +import com.geeksville.mesh.android.Logging +import dagger.hilt.android.HiltAndroidApp + +@HiltAndroidApp +class MeshUtilApplication : GeeksvilleApplication() { + + override fun onCreate() { + super.onCreate() + + Logging.showLogs = BuildConfig.DEBUG + + } +} \ No newline at end of file diff --git a/app/src/fdroid/java/com/geeksville/mesh/analytics/AnalyticsClient.kt b/app/src/fdroid/java/com/geeksville/mesh/analytics/AnalyticsClient.kt new file mode 100644 index 00000000..77326c26 --- /dev/null +++ b/app/src/fdroid/java/com/geeksville/mesh/analytics/AnalyticsClient.kt @@ -0,0 +1,42 @@ +package com.geeksville.mesh.analytics + +class DataPair(val name: String, valueIn: Any?) { + val value = valueIn ?: "null" + + /// An accumulating firebase event - only one allowed per event + constructor(d: Double) : this("BOGUS", d) + constructor(d: Int) : this("BOGUS", d) +} + +public interface AnalyticsProvider { + + // Turn analytics logging on/off + fun setEnabled(on: Boolean) + + /** + * Store an event + */ + fun track(event: String, vararg properties: DataPair) + + /** + * Only track this event if using a cheap provider (like google) + */ + fun trackLowValue(event: String, vararg properties: DataPair) + + fun endSession() + fun startSession() + + /** + * Set persistent ID info about this user, as a key value pair + */ + fun setUserInfo(vararg p: DataPair) + + /** + * Increment some sort of anyalytics counter + */ + fun increment(name: String, amount: Double = 1.0) + + fun sendScreenView(name: String) + fun endScreenView() + +} diff --git a/app/src/fdroid/java/com/geeksville/mesh/analytics/FirebaseAnalytics.kt b/app/src/fdroid/java/com/geeksville/mesh/analytics/FirebaseAnalytics.kt new file mode 100644 index 00000000..fcac9035 --- /dev/null +++ b/app/src/fdroid/java/com/geeksville/mesh/analytics/FirebaseAnalytics.kt @@ -0,0 +1,46 @@ +package com.geeksville.mesh.analytics + +import android.content.Context +import android.os.Bundle +import com.geeksville.mesh.android.AppPrefs +import com.geeksville.mesh.android.GeeksvilleApplication +import com.geeksville.mesh.android.Logging + +/** + * Implement our analytics API using firebase analtics + */ +class GoogleAnalytics(context: Context) : AnalyticsProvider, Logging { + + init { + } + + override fun setEnabled(on: Boolean) { + } + + override fun endSession() { + } + + override fun trackLowValue(event: String, vararg properties: DataPair) { + } + + override fun track(event: String, vararg properties: DataPair) { + } + + override fun startSession() { + } + + override fun setUserInfo(vararg p: DataPair) { + } + + override fun increment(name: String, amount: Double) { + } + + /** + * Send a google analyics screen view event + */ + override fun sendScreenView(name: String) { + } + + override fun endScreenView() { + } +} diff --git a/app/src/fdroid/java/com/geeksville/mesh/android/GeeksvilleApplication.kt b/app/src/fdroid/java/com/geeksville/mesh/android/GeeksvilleApplication.kt new file mode 100644 index 00000000..9dcdb0b6 --- /dev/null +++ b/app/src/fdroid/java/com/geeksville/mesh/android/GeeksvilleApplication.kt @@ -0,0 +1,107 @@ +package com.geeksville.mesh.android + +import android.app.Activity +import android.app.Application +import android.content.Context +import android.content.SharedPreferences +import android.net.ConnectivityManager +import android.os.Bundle +import android.provider.Settings +import androidx.core.content.edit +import com.geeksville.mesh.analytics.AnalyticsProvider + +fun isGooglePlayAvailable(context: Context): Boolean = false + +open class GeeksvilleApplication : Application(), Logging { + + companion object { + lateinit var analytics: AnalyticsProvider + var currentActivity: Activity? = null + private val backstack = mutableListOf() + } + + private val lifecycleCallbacks = object : ActivityLifecycleCallbacks { + override fun onActivityPaused(activity: Activity) { + } + + override fun onActivityStarted(activity: Activity) { + } + + override fun onActivityDestroyed(activity: Activity) { + if (backstack.contains(activity)) backstack.remove(activity) + currentActivity = backstack.lastOrNull() + } + + override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) { + } + + override fun onActivityStopped(activity: Activity) { + } + + override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { + backstack.add(activity) + currentActivity = backstack.lastOrNull() + } + + override fun onActivityResumed(activity: Activity) { + } + } + + /// Are we running inside the testlab? + val isInTestLab: Boolean + get() { + val testLabSetting = + Settings.System.getString(contentResolver, "firebase.test.lab") ?: null + if(testLabSetting != null) + info("Testlab is $testLabSetting") + return "true" == testLabSetting + } + + private val analyticsPrefs: SharedPreferences by lazy { + getSharedPreferences("analytics-prefs", Context.MODE_PRIVATE) + } + + var isAnalyticsAllowed: Boolean + get() = analyticsPrefs.getBoolean("allowed", true) + set(value) { + analyticsPrefs.edit { + putBoolean("allowed", value) + } + + // Change the flag with the providers + analytics.setEnabled(value && !isInTestLab) // Never do analytics in the test lab + } + + override fun onCreate() { + super.onCreate() + + val googleAnalytics = com.geeksville.mesh.analytics.GoogleAnalytics(this) + analytics = googleAnalytics + + // Set analytics per prefs + isAnalyticsAllowed = isAnalyticsAllowed + + registerActivityLifecycleCallbacks(lifecycleCallbacks) + } + + fun isInternetConnected(): Boolean { + val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + + val activeNetwork = cm.getActiveNetworkInfo(); + val isConnected = activeNetwork != null && + activeNetwork.isConnectedOrConnecting(); + + return isConnected + } + +} + + +fun geeksvilleApp(context: Context) = context.applicationContext as GeeksvilleApplication + + +interface GeeksvilleApplicationClient { + + fun getAnalytics() = GeeksvilleApplication.analytics + +} diff --git a/app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt b/app/src/google/java/com/geeksville/mesh/MeshUtilApplication.kt similarity index 100% rename from app/src/main/java/com/geeksville/mesh/MeshUtilApplication.kt rename to app/src/google/java/com/geeksville/mesh/MeshUtilApplication.kt diff --git a/app/src/main/java/com/geeksville/mesh/analytics/AnalyticsClient.kt b/app/src/google/java/com/geeksville/mesh/analytics/AnalyticsClient.kt similarity index 100% rename from app/src/main/java/com/geeksville/mesh/analytics/AnalyticsClient.kt rename to app/src/google/java/com/geeksville/mesh/analytics/AnalyticsClient.kt diff --git a/app/src/main/java/com/geeksville/mesh/analytics/FirebaseAnalytics.kt b/app/src/google/java/com/geeksville/mesh/analytics/FirebaseAnalytics.kt similarity index 100% rename from app/src/main/java/com/geeksville/mesh/analytics/FirebaseAnalytics.kt rename to app/src/google/java/com/geeksville/mesh/analytics/FirebaseAnalytics.kt diff --git a/app/src/main/java/com/geeksville/mesh/android/GeeksvilleApplication.kt b/app/src/google/java/com/geeksville/mesh/android/GeeksvilleApplication.kt similarity index 100% rename from app/src/main/java/com/geeksville/mesh/android/GeeksvilleApplication.kt rename to app/src/google/java/com/geeksville/mesh/android/GeeksvilleApplication.kt diff --git a/build.gradle b/build.gradle index b439eed8..2821b4dd 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ buildscript { ext { + useCrashlytics = false kotlin_version = '1.6.21' coroutines_version = '1.6.0' lifecycle_version = "2.5.1" @@ -24,8 +25,11 @@ buildscript { // in the individual module build.gradle files // Firebase Crashlytics - classpath 'com.google.gms:google-services:4.3.13' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1' + if (project.findProperty("useCrashlytics") == true) { + println("useCrashlytics classpath $useCrashlytics") + classpath 'com.google.gms:google-services:4.3.13' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1' + } // protobuf plugin - docs here https://github.com/google/protobuf-gradle-plugin classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.18'