remove play services

This commit is contained in:
andrekir
2022-09-05 00:14:08 -03:00
parent f282f3f71e
commit 188d1fddaa
8 changed files with 34 additions and 243 deletions

View File

@@ -33,6 +33,7 @@ import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.android.ServiceClient
import com.geeksville.mesh.concurrent.handledLaunch
import com.geeksville.mesh.android.getMissingPermissions
import com.geeksville.mesh.android.isGooglePlayAvailable
import com.geeksville.mesh.databinding.ActivityMainBinding
import com.geeksville.mesh.model.BTScanModel
import com.geeksville.mesh.model.BluetoothViewModel
@@ -45,8 +46,6 @@ import com.geeksville.mesh.service.*
import com.geeksville.mesh.ui.*
import com.geeksville.mesh.util.Exceptions
import com.geeksville.mesh.util.exceptionReporter
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayoutMediator
@@ -252,15 +251,12 @@ class MainActivity : BaseActivity(), Logging {
private fun askToRate() {
exceptionReporter { // Got one IllegalArgumentException from inside this lib, but we don't want to crash our app because of bugs in this optional feature
val hasGooglePlay = GoogleApiAvailability.getInstance()
.isGooglePlayServicesAvailable(this) != ConnectionResult.SERVICE_MISSING
val rater = AppRate.with(this)
.setInstallDays(10.toByte()) // default is 10, 0 means install day, 10 means app is launched 10 or more days later than installation
.setLaunchTimes(10.toByte()) // default is 10, 3 means app is launched 3 or more times
.setRemindInterval(1.toByte()) // default is 1, 1 means app is launched 1 or more days after neutral button clicked
.setRemindLaunchesNumber(1.toByte()) // default is 0, 1 means app is launched 1 or more times after neutral button clicked
.setStoreType(if (hasGooglePlay) StoreType.GOOGLEPLAY else StoreType.AMAZON)
.setStoreType(StoreType.GOOGLEPLAY)
rater.monitor() // Monitors the app launch times
@@ -310,7 +306,7 @@ class MainActivity : BaseActivity(), Logging {
// Handle any intent
handleIntent(intent)
askToRate()
if (isGooglePlayAvailable(this)) askToRate()
// if (!isInTestLab) - very important - even in test lab we must request permissions because we need location perms for some of our tests to pass
requestPermission()

View File

@@ -10,11 +10,11 @@ import android.provider.Settings
import androidx.core.content.edit
import com.geeksville.mesh.analytics.AnalyticsProvider
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.android.gms.common.GoogleApiAvailabilityLight
fun isGooglePlayAvailable(context: Context): Boolean {
val a = GoogleApiAvailability.getInstance()
val a = GoogleApiAvailabilityLight.getInstance()
val r = a.isGooglePlayServicesAvailable(context)
return r != ConnectionResult.SERVICE_MISSING && r != ConnectionResult.SERVICE_INVALID
}

View File

@@ -1,185 +0,0 @@
package com.geeksville.mesh.android
import android.app.Activity
import android.os.Bundle
import com.google.android.gms.common.api.Api
import com.google.android.gms.common.api.Api.ApiOptions.NotRequiredOptions
import com.google.android.gms.common.api.Scope
import com.google.android.gms.common.api.GoogleApiClient
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GooglePlayServicesUtil
import android.content.IntentSender
import android.content.Intent
import android.util.Log
interface PlayClientCallbacks /* : Activity */ {
/**
* Called to tell activity we've lost connection to play
*/
fun onPlayConnectionSuspended() :Unit
/**
* Called to tell activity we are now connected to play
* Do remaining init here
*/
fun onPlayConnected() : Unit
/**
* Called when this machine does not have a valid form of play.
*/
fun onPlayUnavailable() : Unit
}
/**
* Created by kevinh on 1/5/15.
*/
public class PlayClient(val context: Activity, val playCallbacks: PlayClientCallbacks) : Logging {
var apiClient: GoogleApiClient? = null
var authInProgress: Boolean = false
companion object {
val PLAY_OAUTH_REQUEST_CODE = 901
val AUTH_PENDING = "authPend"
}
/**
* Must be called from onCreate
*/
fun playOnCreate(savedInstanceState: Bundle?, apis: Array<Api<out NotRequiredOptions>>, scopes: Array<Scope> = arrayOf()) {
if(savedInstanceState != null)
authInProgress = savedInstanceState.getBoolean(AUTH_PENDING)
if(hasPlayServices()) {
var builder = GoogleApiClient.Builder(context)
.addConnectionCallbacks(object : GoogleApiClient.ConnectionCallbacks {
override fun onConnected(p0: Bundle?) {
// Connected to Google Play services!
// The good stuff goes here.
playCallbacks.onPlayConnected()
}
override fun onConnectionSuspended(i: Int) {
// If your connection to the sensor gets lost at some point,
// you'll be able to determine the reason and react to it here.
if (i == ConnectionCallbacks.CAUSE_NETWORK_LOST) {
info("Connection lost. Cause: Network Lost.");
} else if (i == ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
info("Connection lost. Reason: Service Disconnected");
} else
errormsg("Unknown play kode $i")
playCallbacks.onPlayConnectionSuspended()
}
})
.addOnConnectionFailedListener(object : GoogleApiClient.OnConnectionFailedListener {
override fun onConnectionFailed(result: ConnectionResult) {
info("Play connection failed $result")
if (!result.hasResolution()) {
showErrorDialog(result.errorCode)
} else {
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization dialog is displayed to the user.
if (!authInProgress) {
try {
info("Attempting to resolve failed connection");
authInProgress = true;
result.startResolutionForResult(context,
PLAY_OAUTH_REQUEST_CODE);
} catch (e: IntentSender.SendIntentException) {
errormsg("Exception while starting resolution activity")
playCallbacks.onPlayUnavailable()
}
}
}
}
})
apis.forEach { api ->
builder = builder.addApi(api)
}
scopes.forEach { s ->
builder = builder.addScope(s)
}
apiClient = builder.build()
}
}
private fun showErrorDialog(code: Int) {
// Show the localized error dialog
GooglePlayServicesUtil.getErrorDialog(code,
context, 0)?.show();
playCallbacks.onPlayUnavailable()
}
fun hasPlayServices(): Boolean {
// Check that Google Play services is available
val resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context)
// For testing
//val resultCode = ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d("Geofence Detection",
"Google Play services is available.");
// getAnalytics().track("Has Play")
// Continue
return true
// Google Play services was not available for some reason
} else {
showErrorDialog(resultCode)
return false
}
}
/**
* Must be called from onActivityResult
* @return true if we handled this
*/
fun playOnActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean =
if (requestCode == PLAY_OAUTH_REQUEST_CODE) {
authInProgress = false;
if (resultCode == Activity.RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!apiClient!!.isConnecting && !apiClient!!.isConnected) {
apiClient!!.connect();
}
}
else {
// User opted to not install play
errormsg("User declined play")
context.finish()
}
true
}
else
false
fun playOnStart() {
if(apiClient != null)
apiClient!!.connect()
}
fun playOnStop() {
if(apiClient != null && apiClient!!.isConnected)
apiClient!!.disconnect()
}
fun playSaveInstanceState(outState: Bundle) {
outState.putBoolean(AUTH_PENDING, authInProgress)
}
}

View File

@@ -3,14 +3,11 @@ package com.geeksville.mesh.repository.location
import android.annotation.SuppressLint
import android.content.Context
import android.location.Location
import android.os.Looper
import android.location.LocationListener
import android.location.LocationManager
import com.geeksville.mesh.android.GeeksvilleApplication
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.android.hasBackgroundPermission
import com.google.android.gms.location.LocationCallback
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationServices
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -35,47 +32,43 @@ class SharedLocationManager constructor(
val receivingLocationUpdates: StateFlow<Boolean> get() = _receivingLocationUpdates
// TODO use positionBroadcastSecs / test locationRequest settings
private val desiredInterval = 1 * 60 * 1000L
// if unset, use positionBroadcastSecs default
// positionBroadcastSecs.takeIf { it != 0L }?.times(1000L) ?: (15 * 60 * 1000L)
// Set up the Fused Location Provider and LocationRequest
private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
private val locationRequest = LocationRequest.create().apply {
interval = desiredInterval
fastestInterval = 30 * 1000L
// smallestDisplacement = 50F // 50 meters
priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
}
private val fastestInterval = 30 * 1000L
private val smallestDisplacement = 50F // 50 meters
@SuppressLint("MissingPermission")
private val _locationUpdates = callbackFlow {
val callback = object : LocationCallback() {
override fun onLocationResult(result: LocationResult) {
// info("New location: ${result.lastLocation}")
trySend(result.lastLocation)
}
val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val callback = LocationListener { location ->
// info("New location: ${result.lastLocation}")
trySend(location)
}
if (!context.hasBackgroundPermission()) close()
info("Starting location requests with interval=${desiredInterval}ms")
info("Starting location updates with minTime=${fastestInterval}ms and minDistance=${smallestDisplacement}m")
_receivingLocationUpdates.value = true
GeeksvilleApplication.analytics.track("location_start") // Figure out how many users needed to use the phone GPS
fusedLocationClient.requestLocationUpdates(
locationRequest,
callback,
Looper.getMainLooper()
).addOnFailureListener { ex ->
errormsg("Failed to listen to GPS error: ${ex.message}")
close(ex) // in case of exception, close the Flow
try {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
fastestInterval,
smallestDisplacement,
callback,
context.mainLooper
)
} catch (e: Exception) {
close(e) // in case of exception, close the Flow
}
awaitClose {
info("Stopping location requests")
_receivingLocationUpdates.value = false
GeeksvilleApplication.analytics.track("location_stop")
fusedLocationClient.removeLocationUpdates(callback) // clean up when Flow collection ends
locationManager.removeUpdates(callback) // clean up when Flow collection ends
}
}.shareIn(
externalScope,

View File

@@ -9,7 +9,6 @@ import androidx.core.content.edit
import com.geeksville.mesh.analytics.DataPair
import com.geeksville.mesh.android.GeeksvilleApplication
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.android.isGooglePlayAvailable
import com.geeksville.mesh.concurrent.handledLaunch
import com.geeksville.mesh.*
import com.geeksville.mesh.MeshProtos.MeshPacket
@@ -153,7 +152,7 @@ class MeshService : Service(), Logging {
// If we're already observing updates, don't register again
if (locationFlow?.isActive == true) return
if (hasBackgroundPermission() && isGooglePlayAvailable(this)) {
if (hasBackgroundPermission()) {
locationFlow = locationRepository.getLocations()
.onEach { location ->
sendPosition(

View File

@@ -16,7 +16,6 @@ import com.geeksville.mesh.analytics.DataPair
import com.geeksville.mesh.android.GeeksvilleApplication
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.android.hideKeyboard
import com.geeksville.mesh.android.isGooglePlayAvailable
import com.geeksville.mesh.MainActivity
import com.geeksville.mesh.R
import com.geeksville.mesh.ConfigProtos
@@ -154,7 +153,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
model.provideLocation.value = false
binding.provideLocationCheckbox.isChecked = false
} else {
binding.provideLocationCheckbox.isEnabled = isGooglePlayAvailable(requireContext())
binding.provideLocationCheckbox.isEnabled = true
}
// update the region selection from the device
@@ -582,7 +581,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
scanModel.setupScan()
// system permissions might have changed while we were away
binding.provideLocationCheckbox.isChecked = myActivity.hasBackgroundPermission() && (model.provideLocation.value ?: false) && isGooglePlayAvailable(requireContext())
binding.provideLocationCheckbox.isChecked = myActivity.hasBackgroundPermission() && (model.provideLocation.value ?: false)
myActivity.registerReceiver(updateProgressReceiver, updateProgressFilter)