Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adding fdroid flavor to build without GMS and Firebase (WPB-2799) (#2727) cherry pick #2813

Merged
merged 4 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,7 @@ lint/tmp/
# Autogenerated file with git hash information.
app/src/main/assets/version.txt
/intellij.gdsl

# Editor temporary files
*~
\#*#
21 changes: 21 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,29 @@ android {
jniLibs.pickFirsts.add("**/libsodium.so")
}
android.buildFeatures.buildConfig = true

var fdroidBuild = gradle.startParameter.taskRequests.toString().lowercase().contains("fdroid")
sourceSets {
// Add the "foss" sourceSets for the fdroid flavor
if(fdroidBuild) {
getByName("main") {
java.srcDirs("src/foss/kotlin", "src/prod/kotlin")
resources.srcDirs("src/prod/res")
println("Building with FOSS sourceSets")
}
// For all other flavors use the "nonfree" sourceSets
} else {
getByName("main") {
java.srcDirs("src/nonfree/kotlin")
println("Building with non-free sourceSets")
}
}
}
}




dependencies {
implementation("com.wire.kalium:kalium-logic")
implementation("com.wire.kalium:kalium-util")
Expand Down
39 changes: 39 additions & 0 deletions app/src/fdroid/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!--

Wire
Copyright (C) 2018 Wire Swiss GmbH

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.wire.android"
android:sharedUserId="${sharedUserId}">
<application>
<provider
android:name="com.google.firebase.provider.FirebaseInitProvider"
tools:node="remove" />
<meta-data
android:name="com.google.android.gms.version"
tools:node="remove" />
<service
android:name=".services.WireFirebaseMessagingService"
tools:node="remove" />
<meta-data
android:name="com.wire.android.initializer.FirebaseInitializer"
tools:node="remove" />

</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Wire
* Copyright (C) 2024 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.android.ui.home.messagecomposer.location

import android.content.Context
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class LocationPickerHelperFlavor @Inject constructor(context: Context) : LocationPickerHelper(context) {
suspend fun getLocation(onSuccess: (GeoLocatedAddress) -> Unit, onError: () -> Unit) {
getLocationWithoutGms(
onSuccess = onSuccess,
onError = onError
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*
*
*/

package com.wire.android.util.extension

import android.content.Context

fun Context.isGoogleServicesAvailable(): Boolean {
val returnValue: Boolean = false
return returnValue
}

fun Context.initGoogleFirebase() { /* Stub for compatibility */ }
Original file line number Diff line number Diff line change
Expand Up @@ -24,66 +24,15 @@ import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import androidx.core.location.LocationManagerCompat
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import com.google.android.gms.tasks.CancellationTokenSource
import com.wire.android.AppJsonStyledLogger
import com.wire.android.util.extension.isGoogleServicesAvailable
import com.wire.kalium.logger.KaliumLogLevel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.tasks.await
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class LocationPickerHelper @Inject constructor(@ApplicationContext val context: Context) {

suspend fun getLocation(onSuccess: (GeoLocatedAddress) -> Unit, onError: () -> Unit) {
if (context.isGoogleServicesAvailable()) {
getLocationWithGms(
onSuccess = onSuccess,
onError = onError
)
} else {
getLocationWithoutGms(
onSuccess = onSuccess,
onError = onError
)
}
}

/**
* Choosing the best location estimate by docs.
* https://developer.android.com/develop/sensors-and-location/location/retrieve-current#BestEstimate
*/
@SuppressLint("MissingPermission")
private suspend fun getLocationWithGms(onSuccess: (GeoLocatedAddress) -> Unit, onError: () -> Unit) {
if (isLocationServicesEnabled()) {
AppJsonStyledLogger.log(
level = KaliumLogLevel.INFO,
leadingMessage = "GetLocation",
jsonStringKeyValues = mapOf("isUsingGms" to true)
)
val locationProvider = LocationServices.getFusedLocationProviderClient(context)
val currentLocation =
locationProvider.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, CancellationTokenSource().token).await()
val address = Geocoder(context).getFromLocation(currentLocation.latitude, currentLocation.longitude, 1).orEmpty()
onSuccess(GeoLocatedAddress(address.firstOrNull(), currentLocation))
} else {
AppJsonStyledLogger.log(
level = KaliumLogLevel.WARN,
leadingMessage = "GetLocation",
jsonStringKeyValues = mapOf(
"isUsingGms" to true,
"error" to "Location services are not enabled"
)
)
onError()
}
}
open class LocationPickerHelper @Inject constructor(@ApplicationContext val context: Context) {

@SuppressLint("MissingPermission")
private fun getLocationWithoutGms(onSuccess: (GeoLocatedAddress) -> Unit, onError: () -> Unit) {
protected fun getLocationWithoutGms(onSuccess: (GeoLocatedAddress) -> Unit, onError: () -> Unit) {
if (isLocationServicesEnabled()) {
AppJsonStyledLogger.log(
level = KaliumLogLevel.INFO,
Expand Down Expand Up @@ -112,7 +61,7 @@ class LocationPickerHelper @Inject constructor(@ApplicationContext val context:
}
}

private fun isLocationServicesEnabled(): Boolean {
protected fun isLocationServicesEnabled(): Boolean {
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
return LocationManagerCompat.isLocationEnabled(locationManager)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class LocationPickerViewModel @Inject constructor(private val locationPickerHelper: LocationPickerHelper) : ViewModel() {
class LocationPickerViewModel @Inject constructor(private val locationPickerHelper: LocationPickerHelperFlavor) : ViewModel() {

var state: LocationPickerState by mutableStateOf(LocationPickerState())
private set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.wire.android.ui.home.messagecomposer.state

import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.Stable
Expand All @@ -32,7 +33,6 @@ import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.max
import com.google.android.gms.common.util.VisibleForTesting
import com.wire.android.R
import com.wire.android.ui.common.colorsScheme
import com.wire.android.ui.common.textfield.WireTextFieldColors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@

package com.wire.android.ui.home.settings.account

import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.google.android.gms.common.util.VisibleForTesting
import com.wire.android.BuildConfig
import com.wire.android.appLogger
import com.wire.android.navigation.SavedStateViewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
*/
package com.wire.android.ui.home.settings.account.email.updateEmail

import androidx.annotation.VisibleForTesting
import android.util.Patterns
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.text.input.TextFieldValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.android.gms.common.util.VisibleForTesting
import com.wire.kalium.logic.feature.user.GetSelfUserUseCase
import com.wire.kalium.logic.feature.user.UpdateEmailUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
*/
package com.wire.android.ui.home.settings.account.handle

import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.text.input.TextFieldValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.android.gms.common.util.VisibleForTesting
import com.wire.android.ui.authentication.create.common.handle.HandleUpdateErrorState
import com.wire.kalium.logic.feature.auth.ValidateUserHandleResult
import com.wire.kalium.logic.feature.auth.ValidateUserHandleUseCase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,12 @@ import android.content.ContextWrapper
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability

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

fun Context.isGoogleServicesAvailable(): Boolean {
val status = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this)
return status == ConnectionResult.SUCCESS
}

fun Context.getActivity(): AppCompatActivity? = when (this) {
is AppCompatActivity -> this
is ContextWrapper -> baseContext.getActivity()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Wire
* Copyright (C) 2024 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.android.ui.home.messagecomposer.location

import android.annotation.SuppressLint
import android.content.Context
import android.location.Geocoder
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.Priority
import com.google.android.gms.tasks.CancellationTokenSource
import com.wire.android.util.extension.isGoogleServicesAvailable
import javax.inject.Inject
import javax.inject.Singleton
import kotlinx.coroutines.tasks.await

@Singleton
class LocationPickerHelperFlavor @Inject constructor(context: Context) : LocationPickerHelper(context) {

suspend fun getLocation(onSuccess: (GeoLocatedAddress) -> Unit, onError: () -> Unit) {
if (context.isGoogleServicesAvailable()) {
getLocationWithGms(
onSuccess = onSuccess,
onError = onError
)
} else {
getLocationWithoutGms(
onSuccess = onSuccess,
onError = onError
)
}
}

/**
* Choosing the best location estimate by docs.
* https://developer.android.com/develop/sensors-and-location/location/retrieve-current#BestEstimate
*/
@SuppressLint("MissingPermission")
private suspend fun getLocationWithGms(onSuccess: (GeoLocatedAddress) -> Unit, onError: () -> Unit) {
if (isLocationServicesEnabled()) {
val locationProvider = LocationServices.getFusedLocationProviderClient(context)
val currentLocation =
locationProvider.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, CancellationTokenSource().token).await()
val address = Geocoder(context).getFromLocation(currentLocation.latitude, currentLocation.longitude, 1).orEmpty()
onSuccess(GeoLocatedAddress(address.firstOrNull(), currentLocation))
} else {
onError()
}
}
}