diff options
author | Guillaume Jacquart <guillaume.jacquart@hoodbrains.com> | 2022-08-17 08:49:03 +0000 |
---|---|---|
committer | Guillaume Jacquart <guillaume.jacquart@hoodbrains.com> | 2022-08-17 08:49:03 +0000 |
commit | c8d88ec3364218802bc48257b7766ad8f19a6e45 (patch) | |
tree | a767b29c62cb88ec39c3475ee579439a25141474 /app | |
parent | 12510a55c9c2b1d21c6e1f45d0058778ddfc9eaa (diff) |
2-Simplify sources modules tree
Diffstat (limited to 'app')
10 files changed, 190 insertions, 78 deletions
diff --git a/app/build.gradle b/app/build.gradle index 5f2b302..61ee623 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,7 +16,10 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - manifestPlaceholders = [ persistent: "false" ] + manifestPlaceholders = [ + persistent: "false", + mainActivityIntentFilterCategory: "android.intent.category.LAUNCHER" + ] resValue("string", "mapbox_key", MAPBOX_KEY) } @@ -47,24 +50,36 @@ android { dimension 'os' minSdkVersion 29 targetSdkVersion 29 + signingConfig signingConfigs.eDebug } e30 { dimension 'os' minSdkVersion 30 targetSdkVersion 30 + signingConfig signingConfigs.eDebug + } + standalone { + dimension 'os' + applicationIdSuffix '.standalone' + minSdkVersion 26 + targetSdkVersion 31 + manifestPlaceholders = [ + persistent: "false", + mainActivityIntentFilterCategory: "android.intent.category.LAUNCHER" + ] + signingConfig signingConfigs.debug } -// google { -// applicationIdSuffix '.google' -// dimension 'os' -// } } buildTypes { debug { - signingConfig null // Set signing config to null as we use signingConfig per variant. + signingConfig null // Set signing config to null as we use signingConfig per variant. } release { - manifestPlaceholders = [ persistent: "true" ] + manifestPlaceholders = [ + persistent: "true", + mainActivityIntentFilterCategory: "android.intent.category.INFO" + ] minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' @@ -78,13 +93,6 @@ android { variant.outputs.all { output -> outputFileName = "Advanced_Privacy-${variant.versionName}-${variant.getFlavorName()}-${variant.buildType.name}.apk" } - if (variant.buildType.name == "debug") { - if (variant.getFlavorName() == "e29" || variant.getFlavorName() == "e30") { - variant.mergedFlavor.signingConfig = signingConfigs.eDebug - } else { - variant.mergedFlavor.signingConfig = signingConfigs.debug - } - } } compileOptions { @@ -103,53 +111,51 @@ android { } dependencies { + implementation project(':api') - compileOnly files('libs/e-ui-sdk-1.0.1-q.jar') - implementation files('libs/lineage-sdk.jar') - // include the google specific version of the modules, just for the google flavor - //googleImplementation project(":privacymodulesgoogle") - // include the e specific version of the modules, just for the e flavor - - implementation 'foundation.e:privacymodule.trackerfilter:0.7.0' - implementation 'foundation.e:privacymodule.api:1.1.0' - e29Implementation 'foundation.e:privacymodule.e-29:0.4.3' - e30Implementation 'foundation.e:privacymodule.e-30:0.4.3' - implementation 'foundation.e:privacymodule.tor:0.2.4' - + standaloneImplementation project(':permissionsstandalone') + e29Implementation('foundation.e:privacymodule.e-29:1.2.0') { + exclude group: 'foundation.e', module: 'privacymodule.api' + } + e30Implementation('foundation.e:privacymodule.e-30:1.2.0') { + exclude group: 'foundation.e', module: 'privacymodule.api' + } - // implementation Libs.Kotlin.stdlib - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$Versions.kotlin" -// implementation Libs.AndroidX.coreKtx - implementation "androidx.core:core-ktx:1.8.0" - -// implementation Libs.AndroidX.Fragment.fragmentKtx - implementation "androidx.fragment:fragment-ktx:$Versions.fragment" + implementation project(':fakelocation') - implementation 'androidx.appcompat:appcompat:1.4.2' -// implementation Libs.AndroidX.Lifecycle.runtime - implementation "androidx.lifecycle:lifecycle-runtime-ktx:$Versions.lifecycle" -// implementation Libs.AndroidX.Lifecycle.viewmodel - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$Versions.lifecycle" + e29CompileOnly files('libs/e-ui-sdk-1.0.1-q.jar') + e29Implementation files('libs/lineage-sdk.jar') - implementation 'androidx.work:work-runtime-ktx:2.7.1' + e30CompileOnly files('libs/e-ui-sdk-1.0.1-q.jar') + e30Implementation files('libs/lineage-sdk.jar') - implementation 'com.google.android.material:material:1.6.1' + implementation project(':trackers') + implementation 'foundation.e:privacymodule.tor:0.2.4' - implementation 'com.squareup.retrofit2:retrofit:2.9.0' - implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' + implementation ( + Libs.Kotlin.stdlib, + Libs.AndroidX.coreKtx, + Libs.AndroidX.appCompat, + Libs.AndroidX.Fragment.fragmentKtx, + Libs.AndroidX.Lifecycle.runtime, + Libs.AndroidX.Lifecycle.viewmodel, + Libs.AndroidX.work, + Libs.material, -// implementation Libs.MapBox.sdk - implementation "com.mapbox.mapboxsdk:mapbox-android-sdk:$Versions.mapbox" - implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + Libs.Retrofit.retrofit, + Libs.Retrofit.scalars, + Libs.MapBox.sdk, + Libs.mpAndroidCharts + ) + debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' - debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' } static def log(Object val) { diff --git a/app/src/google/res/values/strings.xml b/app/src/google/res/values/strings.xml deleted file mode 100644 index ebf51d0..0000000 --- a/app/src/google/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ -<resources> - <string name="app_name">google - PrivacyModulesDemo</string> -</resources> diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d285b6f..d2a824a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,4 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 ECORP + + 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 <https://www.gnu.org/licenses/>. +--> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="foundation.e.privacycentralapp" @@ -33,6 +49,7 @@ > <receiver android:name=".common.BootCompletedReceiver" + android:exported="true" > <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> @@ -53,19 +70,28 @@ android:resource="@xml/widget_info" /> </receiver> - <receiver android:name=".widget.WidgetCommandReceiver"> + <receiver android:name=".widget.WidgetCommandReceiver" + android:exported="true"> <intent-filter> <action android:name="toggle_privacy" /> </intent-filter> </receiver> <activity android:name=".main.MainActivity" - android:launchMode="singleTask"> + android:launchMode="singleTask" + android:exported="true" + > <intent-filter> <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.INFO"/> + <category android:name="${mainActivityIntentFilterCategory}"/> </intent-filter> </activity> + + <service + android:name="org.torproject.android.service.OrbotService" + android:exported="false" + + /> </application> </manifest>
\ No newline at end of file diff --git a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt index 6be3724..a44a00a 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/DependencyContainer.kt @@ -40,16 +40,15 @@ import foundation.e.privacycentralapp.features.location.FakeLocationViewModel import foundation.e.privacycentralapp.features.trackers.TrackersViewModel import foundation.e.privacycentralapp.features.trackers.apptrackers.AppTrackersFragment import foundation.e.privacycentralapp.features.trackers.apptrackers.AppTrackersViewModel +import foundation.e.privacymodules.fakelocation.FakeLocationModule import foundation.e.privacymodules.ipscrambler.IpScramblerModule import foundation.e.privacymodules.ipscramblermodule.IIpScramblerModule -import foundation.e.privacymodules.location.FakeLocationModule import foundation.e.privacymodules.location.IFakeLocationModule import foundation.e.privacymodules.permissions.PermissionsPrivacyModule import foundation.e.privacymodules.permissions.data.ApplicationDescription import foundation.e.privacymodules.trackers.api.BlockTrackersPrivacyModule import foundation.e.privacymodules.trackers.api.TrackTrackersPrivacyModule import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.GlobalScope /** @@ -61,7 +60,7 @@ class DependencyContainer(val app: Application) { val context: Context by lazy { app.applicationContext } // Drivers - private val fakeLocationModule: IFakeLocationModule by lazy { FakeLocationModule(app.applicationContext) } + private val fakeLocationModule: FakeLocationModule by lazy { FakeLocationModule(app.applicationContext) } private val permissionsModule by lazy { PermissionsPrivacyModule(app.applicationContext) } private val ipScramblerModule: IIpScramblerModule by lazy { IpScramblerModule(app.applicationContext) } diff --git a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt index aa4276d..f7b5439 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/domain/usecases/FakeLocationStateUseCase.kt @@ -28,7 +28,7 @@ import android.util.Log import foundation.e.privacycentralapp.data.repositories.LocalStateRepository import foundation.e.privacycentralapp.domain.entities.LocationMode import foundation.e.privacycentralapp.dummy.CityDataSource -import foundation.e.privacymodules.location.IFakeLocationModule +import foundation.e.privacymodules.fakelocation.FakeLocationModule import foundation.e.privacymodules.permissions.PermissionsPrivacyModule import foundation.e.privacymodules.permissions.data.AppOpModes import foundation.e.privacymodules.permissions.data.ApplicationDescription @@ -39,7 +39,7 @@ import kotlinx.coroutines.launch import kotlin.random.Random class FakeLocationStateUseCase( - private val fakeLocationModule: IFakeLocationModule, + private val fakeLocationModule: FakeLocationModule, private val permissionsModule: PermissionsPrivacyModule, private val localStateRepository: LocalStateRepository, private val citiesRepository: CityDataSource, @@ -61,23 +61,15 @@ class FakeLocationStateUseCase( private val locationManager: LocationManager get() = appContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager - private fun acquireLocationPermission() { - if (appContext.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { - permissionsModule.toggleDangerousPermission( - appDesc, - android.Manifest.permission.ACCESS_FINE_LOCATION, - true - ) - } + private fun hasAcquireLocationPermission(): Boolean { + return (appContext.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) + || permissionsModule.toggleDangerousPermission(appDesc, android.Manifest.permission.ACCESS_FINE_LOCATION, true) } private fun applySettings(isQuickPrivacyEnabled: Boolean, fakeLocation: Pair<Float, Float>?, isSpecificLocation: Boolean = false) { _configuredLocationMode.value = computeLocationMode(fakeLocation, isSpecificLocation) - if (isQuickPrivacyEnabled && fakeLocation != null) { - if (permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) != AppOpModes.ALLOWED) { - permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpModes.ALLOWED) - } + if (isQuickPrivacyEnabled && fakeLocation != null && hasAcquireMockLocationPermission()) { fakeLocationModule.startFakeLocation() fakeLocationModule.setFakeLocation(fakeLocation.first.toDouble(), fakeLocation.second.toDouble()) localStateRepository.locationMode.value = configuredLocationMode.value.first @@ -87,6 +79,11 @@ class FakeLocationStateUseCase( } } + private fun hasAcquireMockLocationPermission(): Boolean { + return (permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) == AppOpModes.ALLOWED) + || permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpModes.ALLOWED) + } + fun setSpecificLocation(latitude: Float, longitude: Float) { if (!localStateRepository.isQuickPrivacyEnabled) { localStateRepository.setShowQuickPrivacyDisabledMessage(true) @@ -161,8 +158,11 @@ class FakeLocationStateUseCase( } } - fun startListeningLocation() { - requestLocationUpdates(localListener) + fun startListeningLocation(): Boolean { + return if (hasAcquireLocationPermission()) { + requestLocationUpdates(localListener) + true + } else false } fun stopListeningLocation() { @@ -170,7 +170,6 @@ class FakeLocationStateUseCase( } fun requestLocationUpdates(listener: LocationListener) { - acquireLocationPermission() try { locationManager.requestLocationUpdates( LocationManager.NETWORK_PROVIDER, // TODO: tight this with fakelocation module. diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt index 2b858e9..d98cb5d 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationFragment.kt @@ -17,6 +17,7 @@ package foundation.e.privacycentralapp.features.location +import android.Manifest import android.annotation.SuppressLint import android.content.Context import android.location.Location @@ -24,6 +25,7 @@ import android.os.Bundle import android.text.Editable import android.view.View import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.NonNull import androidx.core.view.isVisible import androidx.core.widget.addTextChangedListener @@ -81,6 +83,16 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location) private var inputJob: Job? = null + private val locationPermissionRequest = registerForActivityResult( + ActivityResultContracts.RequestMultiplePermissions() + ) { permissions -> + if (permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) + || permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) + ) { + viewModel.submitAction(Action.StartListeningLocation) + } // TODO: else. + } + companion object { private const val DEBOUNCE_PERIOD = 1000L } @@ -147,6 +159,13 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location) is FakeLocationViewModel.SingleEvent.LocationUpdatedEvent -> { updateLocation(event.location, event.mode) } + is FakeLocationViewModel.SingleEvent.RequestLocationPermission -> { + // TODO for standalone: rationale dialog + locationPermissionRequest.launch(arrayOf( + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION + )) + } } } } @@ -326,13 +345,13 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location) override fun onResume() { super.onResume() - viewModel.submitAction(Action.EnterScreen) + viewModel.submitAction(Action.StartListeningLocation) binding.mapView.onResume() } override fun onPause() { super.onPause() - viewModel.submitAction(Action.LeaveScreen) + viewModel.submitAction(Action.StopListeningLocation) binding.mapView.onPause() } diff --git a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt index af20a72..afba3d0 100644 --- a/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt +++ b/app/src/main/java/foundation/e/privacycentralapp/features/location/FakeLocationViewModel.kt @@ -86,8 +86,8 @@ class FakeLocationViewModel( fun submitAction(action: Action) = viewModelScope.launch { when (action) { - is Action.EnterScreen -> fakeLocationStateUseCase.startListeningLocation() - is Action.LeaveScreen -> fakeLocationStateUseCase.stopListeningLocation() + is Action.StartListeningLocation -> actionStartListeningLocation() + is Action.StopListeningLocation -> fakeLocationStateUseCase.stopListeningLocation() is Action.SetSpecificLocationAction -> setSpecificLocation(action) is Action.UseRandomLocationAction -> fakeLocationStateUseCase.setRandomLocation() is Action.UseRealLocationAction -> @@ -97,18 +97,26 @@ class FakeLocationViewModel( } } + private suspend fun actionStartListeningLocation() { + val started = fakeLocationStateUseCase.startListeningLocation() + if (!started) { + _singleEvents.emit(SingleEvent.RequestLocationPermission) + } + } + private suspend fun setSpecificLocation(action: Action.SetSpecificLocationAction) { specificLocationInputFlow.emit(action) } sealed class SingleEvent { data class LocationUpdatedEvent(val mode: LocationMode, val location: Location?) : SingleEvent() + object RequestLocationPermission: SingleEvent() data class ErrorEvent(val error: String) : SingleEvent() } sealed class Action { - object EnterScreen : Action() - object LeaveScreen : Action() + object StartListeningLocation : Action() + object StopListeningLocation : Action() object UseRealLocationAction : Action() object UseRandomLocationAction : Action() data class SetSpecificLocationAction( diff --git a/app/src/standalone/res/values-night/colors.xml b/app/src/standalone/res/values-night/colors.xml new file mode 100644 index 0000000..079b968 --- /dev/null +++ b/app/src/standalone/res/values-night/colors.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2022 E FOUNDATION + ~ + ~ 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 <https://www.gnu.org/licenses/>. + --> + +<resources> + <!--themable --> + <color name="primary">#272727</color> + <color name="accent">#5DB2FF</color> + + <color name="primary_text">#CCFFFFFF</color> + <color name="secondary_text">#8CFFFFFF</color> + + <color name="background">#121212</color> + +</resources>
\ No newline at end of file diff --git a/app/src/standalone/res/values/colors.xml b/app/src/standalone/res/values/colors.xml new file mode 100644 index 0000000..bd27922 --- /dev/null +++ b/app/src/standalone/res/values/colors.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2022 E FOUNDATION + ~ + ~ 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 <https://www.gnu.org/licenses/>. + --> + +<resources> + <!--themable --> + <color name="primary">#FFFFFF</color> + <color name="accent">#0086FF</color> + + <color name="primary_text">#CC000000</color> + <color name="secondary_text">#8C000000</color> + + <color name="background">#FAFAFA</color> +</resources>
\ No newline at end of file diff --git a/app/src/standalone/res/values/strings.xml b/app/src/standalone/res/values/strings.xml new file mode 100644 index 0000000..7719e7b --- /dev/null +++ b/app/src/standalone/res/values/strings.xml @@ -0,0 +1,3 @@ +<resources> + <string name="app_name">A-P - Standalone</string> +</resources> |