remove play services

master
andrekir 2022-09-05 00:14:08 -03:00
rodzic f282f3f71e
commit 188d1fddaa
8 zmienionych plików z 34 dodań i 243 usunięć

Wyświetl plik

@ -3,12 +3,12 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlinx-serialization'
apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.github.triplet.play'
apply plugin: 'de.mobilej.unmock'
// apply plugin: "app.brant.amazonappstorepublisher"
// Apply the Crashlytics Gradle plugin
// Firebase Crashlytics
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
// protobuf
@ -38,11 +38,10 @@ android {
}
compileSdkVersion 31
// leave undefined to use version plugin wants
// buildToolsVersion "30.0.2" // Note: 30.0.2 doesn't yet work on Github actions CI
defaultConfig {
applicationId "com.geeksville.mesh"
minSdkVersion 21 // The oldest emulator image I have tried is 22 (though 21 probably works)
targetSdkVersion 30 // 30 can't work until an explicit location permissions dialog is added
targetSdkVersion 30
versionCode 20339 // format is Mmmss (where M is 1+the numeric major number
versionName "1.3.39"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@ -169,18 +168,10 @@ dependencies {
// implementation 'com.google.android.things:androidthings:1.0'
implementation 'com.github.mik3y:usb-serial-for-android:3.4.6'
// location services
implementation 'com.google.android.gms:play-services-location:19.0.1'
// For Google Sign-In (owner name accesss)
implementation 'com.google.android.gms:play-services-auth:20.2.0'
// Add the Firebase SDK for Crashlytics.
implementation 'com.google.firebase:firebase-crashlytics:18.2.6'
implementation 'com.google.firebase:firebase-analytics:20.1.0'
// geeksville-androidlib
// compileOnly 'com.google.android.gms:play-services-base:17.6.0'
// alas implementation bug deep in the bowels when I tried it for my SyncBluetoothDevice class
// implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3"

Wyświetl plik

@ -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()

Wyświetl plik

@ -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
}

Wyświetl plik

@ -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)
}
}

Wyświetl plik

@ -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,

Wyświetl plik

@ -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(

Wyświetl plik

@ -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)

Wyświetl plik

@ -19,9 +19,7 @@ buildscript {
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
// Add the Crashlytics Gradle plugin.
// Check that you have the Google Services Gradle plugin v4.3.2 or later
// (if not, add it).
// Firebase Crashlytics
classpath 'com.google.gms:google-services:4.3.10'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'