Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b552d03 authored by Guillaume Jacquart's avatar Guillaume Jacquart
Browse files

Update fake location demo. Make fakeloc work in standalone mode - basic.

parent 4735ac23
Loading
Loading
Loading
Loading
+14 −15
Original line number Original line Diff line number Diff line
@@ -61,23 +61,15 @@ class FakeLocationStateUseCase(
    private val locationManager: LocationManager
    private val locationManager: LocationManager
        get() = appContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        get() = appContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager


    private fun acquireLocationPermission() {
    private fun acquireLocationPermission(): Boolean {
        if (appContext.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return (appContext.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
            permissionsModule.toggleDangerousPermission(
            || false // TODO : should return true / false. permissionsModule.toggleDangerousPermission(appDesc, android.Manifest.permission.ACCESS_FINE_LOCATION, true)
                appDesc,
                android.Manifest.permission.ACCESS_FINE_LOCATION,
                true
            )
        }
    }
    }


    private fun applySettings(isQuickPrivacyEnabled: Boolean, fakeLocation: Pair<Float, Float>?, isSpecificLocation: Boolean = false) {
    private fun applySettings(isQuickPrivacyEnabled: Boolean, fakeLocation: Pair<Float, Float>?, isSpecificLocation: Boolean = false) {
        _configuredLocationMode.value = computeLocationMode(fakeLocation, isSpecificLocation)
        _configuredLocationMode.value = computeLocationMode(fakeLocation, isSpecificLocation)


        if (isQuickPrivacyEnabled && fakeLocation != null) {
        if (isQuickPrivacyEnabled && fakeLocation != null && acquireMockLocationPermission()) {
            if (permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) != AppOpModes.ALLOWED) {
                permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpModes.ALLOWED)
            }
            fakeLocationModule.startFakeLocation()
            fakeLocationModule.startFakeLocation()
            fakeLocationModule.setFakeLocation(fakeLocation.first.toDouble(), fakeLocation.second.toDouble())
            fakeLocationModule.setFakeLocation(fakeLocation.first.toDouble(), fakeLocation.second.toDouble())
            localStateRepository.locationMode.value = configuredLocationMode.value.first
            localStateRepository.locationMode.value = configuredLocationMode.value.first
@@ -87,6 +79,11 @@ class FakeLocationStateUseCase(
        }
        }
    }
    }


    private fun acquireMockLocationPermission(): Boolean {
        return (permissionsModule.getAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION) == AppOpModes.ALLOWED)
            || permissionsModule.setAppOpMode(appDesc, AppOpsManager.OPSTR_MOCK_LOCATION, AppOpModes.ALLOWED) == null
    }

    fun setSpecificLocation(latitude: Float, longitude: Float) {
    fun setSpecificLocation(latitude: Float, longitude: Float) {
        if (!localStateRepository.isQuickPrivacyEnabled) {
        if (!localStateRepository.isQuickPrivacyEnabled) {
            localStateRepository.setShowQuickPrivacyDisabledMessage(true)
            localStateRepository.setShowQuickPrivacyDisabledMessage(true)
@@ -161,8 +158,11 @@ class FakeLocationStateUseCase(
        }
        }
    }
    }


    fun startListeningLocation() {
    fun startListeningLocation(): Boolean {
        return if (acquireLocationPermission()) {
            requestLocationUpdates(localListener)
            requestLocationUpdates(localListener)
            true
        } else false
    }
    }


    fun stopListeningLocation() {
    fun stopListeningLocation() {
@@ -170,7 +170,6 @@ class FakeLocationStateUseCase(
    }
    }


    fun requestLocationUpdates(listener: LocationListener) {
    fun requestLocationUpdates(listener: LocationListener) {
        acquireLocationPermission()
        try {
        try {
            locationManager.requestLocationUpdates(
            locationManager.requestLocationUpdates(
                LocationManager.NETWORK_PROVIDER, // TODO: tight this with fakelocation module.
                LocationManager.NETWORK_PROVIDER, // TODO: tight this with fakelocation module.
+32 −2
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@


package foundation.e.privacycentralapp.features.location
package foundation.e.privacycentralapp.features.location


import android.Manifest
import android.annotation.SuppressLint
import android.annotation.SuppressLint
import android.content.Context
import android.content.Context
import android.location.Location
import android.location.Location
@@ -24,6 +25,7 @@ import android.os.Bundle
import android.text.Editable
import android.text.Editable
import android.view.View
import android.view.View
import android.widget.Toast
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.NonNull
import androidx.annotation.NonNull
import androidx.core.view.isVisible
import androidx.core.view.isVisible
import androidx.core.widget.addTextChangedListener
import androidx.core.widget.addTextChangedListener
@@ -81,6 +83,16 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)


    private var inputJob: Job? = null
    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 {
    companion object {
        private const val DEBOUNCE_PERIOD = 1000L
        private const val DEBOUNCE_PERIOD = 1000L
    }
    }
@@ -146,6 +158,14 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
                        is FakeLocationViewModel.SingleEvent.LocationUpdatedEvent -> {
                        is FakeLocationViewModel.SingleEvent.LocationUpdatedEvent -> {
                            updateLocation(event.location, event.mode)
                            updateLocation(event.location, event.mode)
                        }
                        }
                        is FakeLocationViewModel.SingleEvent.RequestLocationPermission -> {
                            // TODO rationale dialog
                            //shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)
                            locationPermissionRequest.launch(arrayOf(
                                Manifest.permission.ACCESS_FINE_LOCATION,
                                Manifest.permission.ACCESS_COARSE_LOCATION
                            ))
                        }
                    }
                    }
                }
                }
            }
            }
@@ -158,6 +178,16 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)
        }
        }
    }
    }


    // val locationPermissionRequest = registerForActivityResult(
    //     ActivityResultContracts.RequestMultiplePermissions()
    // ) { permissions ->
    //     if (permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false)
    //         || permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false)
    //     ) {
    //         startLocationUpdates()
    //     }
    // }

    private fun getCoordinatesAfterTextChanged(
    private fun getCoordinatesAfterTextChanged(
        inputLayout: TextInputLayout,
        inputLayout: TextInputLayout,
        editText: TextInputEditText,
        editText: TextInputEditText,
@@ -325,13 +355,13 @@ class FakeLocationFragment : NavToolbarFragment(R.layout.fragment_fake_location)


    override fun onResume() {
    override fun onResume() {
        super.onResume()
        super.onResume()
        viewModel.submitAction(Action.EnterScreen)
        viewModel.submitAction(Action.StartListeningLocation)
        binding.mapView.onResume()
        binding.mapView.onResume()
    }
    }


    override fun onPause() {
    override fun onPause() {
        super.onPause()
        super.onPause()
        viewModel.submitAction(Action.LeaveScreen)
        viewModel.submitAction(Action.StopListeningLocation)
        binding.mapView.onPause()
        binding.mapView.onPause()
    }
    }


+12 −4
Original line number Original line Diff line number Diff line
@@ -86,8 +86,8 @@ class FakeLocationViewModel(


    fun submitAction(action: Action) = viewModelScope.launch {
    fun submitAction(action: Action) = viewModelScope.launch {
        when (action) {
        when (action) {
            is Action.EnterScreen -> fakeLocationStateUseCase.startListeningLocation()
            is Action.StartListeningLocation -> actionStartListeningLocation()
            is Action.LeaveScreen -> fakeLocationStateUseCase.stopListeningLocation()
            is Action.StopListeningLocation -> fakeLocationStateUseCase.stopListeningLocation()
            is Action.SetSpecificLocationAction -> setSpecificLocation(action)
            is Action.SetSpecificLocationAction -> setSpecificLocation(action)
            is Action.UseRandomLocationAction -> fakeLocationStateUseCase.setRandomLocation()
            is Action.UseRandomLocationAction -> fakeLocationStateUseCase.setRandomLocation()
            is Action.UseRealLocationAction ->
            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) {
    private suspend fun setSpecificLocation(action: Action.SetSpecificLocationAction) {
        specificLocationInputFlow.emit(action)
        specificLocationInputFlow.emit(action)
    }
    }


    sealed class SingleEvent {
    sealed class SingleEvent {
        data class LocationUpdatedEvent(val mode: LocationMode, val location: Location?) : SingleEvent()
        data class LocationUpdatedEvent(val mode: LocationMode, val location: Location?) : SingleEvent()
        object RequestLocationPermission: SingleEvent()
        data class ErrorEvent(val error: String) : SingleEvent()
        data class ErrorEvent(val error: String) : SingleEvent()
    }
    }


    sealed class Action {
    sealed class Action {
        object EnterScreen : Action()
        object StartListeningLocation : Action()
        object LeaveScreen : Action()
        object StopListeningLocation : Action()
        object UseRealLocationAction : Action()
        object UseRealLocationAction : Action()
        object UseRandomLocationAction : Action()
        object UseRandomLocationAction : Action()
        data class SetSpecificLocationAction(
        data class SetSpecificLocationAction(
+1 −2
Original line number Original line Diff line number Diff line
@@ -41,7 +41,6 @@ buildscript {
plugins {
plugins {
    id 'com.diffplug.spotless' version '5.12.4'
    id 'com.diffplug.spotless' version '5.12.4'
    id 'com.github.ben-manes.versions' version '0.38.0'
    id 'com.github.ben-manes.versions' version '0.38.0'
    //id 'com.android.library' version '4.1.3' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
    id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}
}


@@ -130,7 +129,7 @@ subprojects {
    tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
    tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
        kotlinOptions {
        kotlinOptions {
            // Treat all Kotlin warnings as errors
            // Treat all Kotlin warnings as errors
            allWarningsAsErrors = true
            //allWarningsAsErrors = true


            freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
            freeCompilerArgs += "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi"
            // Set JVM target to 1.8
            // Set JVM target to 1.8
+1 −0
Original line number Original line Diff line number Diff line
/build
 No newline at end of file
Loading