diff --git a/app/build.gradle b/app/build.gradle
index 6a8477c2..dcb832e5 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -12,7 +12,7 @@ android {
defaultConfig {
applicationId "net.vonforst.evmap"
minSdkVersion 21
- targetSdkVersion 30
+ targetSdkVersion 31
versionCode 61
versionName "1.0.0-beta03"
@@ -110,6 +110,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'androidx.core:core-ktx:1.5.0'
+ implementation 'androidx.core:core-splashscreen:1.0.0-alpha01'
implementation "androidx.activity:activity-ktx:1.2.3"
implementation "androidx.fragment:fragment-ktx:1.3.4"
implementation 'androidx.cardview:cardview:1.0.0'
diff --git a/app/src/google/AndroidManifest.xml b/app/src/google/AndroidManifest.xml
index 3e6a6b3c..cebc579e 100644
--- a/app/src/google/AndroidManifest.xml
+++ b/app/src/google/AndroidManifest.xml
@@ -46,6 +46,7 @@
+ android:enabled="true"
+ android:exported="false" />
\ No newline at end of file
diff --git a/app/src/google/java/net/vonforst/evmap/auto/CarAppService.kt b/app/src/google/java/net/vonforst/evmap/auto/CarAppService.kt
index 8463c336..782e3719 100644
--- a/app/src/google/java/net/vonforst/evmap/auto/CarAppService.kt
+++ b/app/src/google/java/net/vonforst/evmap/auto/CarAppService.kt
@@ -1,9 +1,7 @@
package net.vonforst.evmap.auto
-import android.Manifest
import android.content.*
import android.content.pm.ApplicationInfo
-import android.content.pm.PackageManager
import android.location.Location
import android.os.IBinder
import androidx.car.app.CarContext
@@ -18,6 +16,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.localbroadcastmanager.content.LocalBroadcastManager
+import net.vonforst.evmap.utils.checkAnyLocationPermission
interface LocationAwareScreen {
@@ -72,11 +71,7 @@ class EVMapSession(val cas: CarAppService) : Session(), LifecycleObserver {
return WelcomeScreen(carContext, this)
}
- fun locationPermissionGranted() =
- ContextCompat.checkSelfPermission(
- carContext,
- Manifest.permission.ACCESS_FINE_LOCATION
- ) == PackageManager.PERMISSION_GRANTED
+ fun locationPermissionGranted() = carContext.checkAnyLocationPermission()
private val locationReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
diff --git a/app/src/google/java/net/vonforst/evmap/auto/WelcomeScreen.kt b/app/src/google/java/net/vonforst/evmap/auto/WelcomeScreen.kt
index aa8b3632..239bf88f 100644
--- a/app/src/google/java/net/vonforst/evmap/auto/WelcomeScreen.kt
+++ b/app/src/google/java/net/vonforst/evmap/auto/WelcomeScreen.kt
@@ -23,7 +23,10 @@ class WelcomeScreen(ctx: CarContext, val session: EVMapSession) : Screen(ctx), L
PermissionScreen(
carContext,
R.string.auto_location_permission_needed,
- listOf(Manifest.permission.ACCESS_FINE_LOCATION)
+ listOf(
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ )
)
) {
session.bindLocationService()
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3158f168..83ec18ac 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
package="net.vonforst.evmap">
+
@@ -32,7 +33,8 @@
+ android:theme="@style/AppTheme.LaunchScreen"
+ android:exported="true">
@@ -256,6 +258,16 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/net/vonforst/evmap/MapsActivity.kt b/app/src/main/java/net/vonforst/evmap/MapsActivity.kt
index 8de131ae..bf8ffcb1 100644
--- a/app/src/main/java/net/vonforst/evmap/MapsActivity.kt
+++ b/app/src/main/java/net/vonforst/evmap/MapsActivity.kt
@@ -4,12 +4,16 @@ import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
+import android.os.Build
import android.os.Bundle
+import android.os.SystemClock
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.browser.customtabs.CustomTabColorSchemeParams
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.content.ContextCompat
+import androidx.core.splashscreen.SplashScreen
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.drawerlayout.widget.DrawerLayout
@@ -51,9 +55,8 @@ class MapsActivity : AppCompatActivity() {
}
override fun onCreate(savedInstanceState: Bundle?) {
- // set theme to AppTheme to end launch screen
- setTheme(R.style.AppTheme)
super.onCreate(savedInstanceState)
+ val splashScreen = installSplashScreen()
setContentView(R.layout.activity_maps)
@@ -82,8 +85,23 @@ class MapsActivity : AppCompatActivity() {
checkPlayServices(this)
-
if (!prefs.welcomeDialogShown || !prefs.dataSourceSet) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ // wait for splash screen animation to finish on first start
+ splashScreen.setKeepVisibleCondition(object : SplashScreen.KeepOnScreenCondition {
+ var startTime: Long? = null
+
+ override fun shouldKeepOnScreen(): Boolean {
+ val st = startTime
+ if (st == null) {
+ startTime = SystemClock.uptimeMillis()
+ return true
+ } else {
+ return (SystemClock.uptimeMillis() - st) < 1000
+ }
+ }
+ })
+ }
navGraph.startDestination = R.id.onboarding
navController.graph = navGraph
return
diff --git a/app/src/main/java/net/vonforst/evmap/fragment/FavoritesFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/FavoritesFragment.kt
index 492c5fb3..60ee6746 100644
--- a/app/src/main/java/net/vonforst/evmap/fragment/FavoritesFragment.kt
+++ b/app/src/main/java/net/vonforst/evmap/fragment/FavoritesFragment.kt
@@ -1,7 +1,5 @@
package net.vonforst.evmap.fragment
-import android.Manifest
-import android.content.pm.PackageManager
import android.graphics.Canvas
import android.os.Bundle
import android.view.Gravity
@@ -9,7 +7,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
-import androidx.core.content.ContextCompat
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
@@ -30,6 +27,7 @@ import net.vonforst.evmap.adapter.FavoritesAdapter
import net.vonforst.evmap.databinding.FragmentFavoritesBinding
import net.vonforst.evmap.databinding.ItemFavoriteBinding
import net.vonforst.evmap.model.ChargeLocation
+import net.vonforst.evmap.utils.checkAnyLocationPermission
import net.vonforst.evmap.viewmodel.FavoritesViewModel
import net.vonforst.evmap.viewmodel.viewModelFactory
@@ -100,11 +98,7 @@ class FavoritesFragment : Fragment(), LostApiClient.ConnectionCallbacks {
override fun onConnected() {
val context = this.context ?: return
- if (ContextCompat.checkSelfPermission(
- context,
- Manifest.permission.ACCESS_FINE_LOCATION
- ) == PackageManager.PERMISSION_GRANTED
- ) {
+ if (context.checkAnyLocationPermission()) {
val location = LocationServices.FusedLocationApi.getLastLocation(locationClient!!)
if (location != null) {
vm.location.value = LatLng(location.latitude, location.longitude)
diff --git a/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt
index 6521f686..2f56ea40 100644
--- a/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt
+++ b/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt
@@ -1,5 +1,6 @@
package net.vonforst.evmap.fragment
+import android.Manifest.permission.ACCESS_COARSE_LOCATION
import android.Manifest.permission.ACCESS_FINE_LOCATION
import android.annotation.SuppressLint
import android.content.Context
@@ -81,6 +82,8 @@ import net.vonforst.evmap.ui.ClusterIconGenerator
import net.vonforst.evmap.ui.MarkerAnimator
import net.vonforst.evmap.ui.getMarkerTint
import net.vonforst.evmap.utils.boundingBox
+import net.vonforst.evmap.utils.checkAnyLocationPermission
+import net.vonforst.evmap.utils.checkFineLocationPermission
import net.vonforst.evmap.utils.distanceBetween
import net.vonforst.evmap.viewmodel.*
import java.io.IOException
@@ -262,10 +265,8 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
)
vm.reloadPrefs()
- if (requestingLocationUpdates && ContextCompat.checkSelfPermission(
- requireContext(),
- ACCESS_FINE_LOCATION
- ) == PackageManager.PERMISSION_GRANTED && locationClient.isConnected
+ if (requestingLocationUpdates && requireContext().checkAnyLocationPermission()
+ && locationClient.isConnected
) {
requestLocationUpdates()
}
@@ -273,16 +274,14 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
private fun setupClickListeners() {
binding.fabLocate.setOnClickListener {
- if (ContextCompat.checkSelfPermission(
- requireContext(),
- ACCESS_FINE_LOCATION
- ) != PackageManager.PERMISSION_GRANTED
- ) {
- requestPermissions(
- arrayOf(ACCESS_FINE_LOCATION),
+ if (!requireContext().checkFineLocationPermission()) {
+ ActivityCompat.requestPermissions(
+ requireActivity(),
+ arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
- } else {
+ }
+ if (requireContext().checkAnyLocationPermission()) {
enableLocation(moveTo = true, animate = true)
}
}
@@ -883,11 +882,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
}
}
}
- if (ContextCompat.checkSelfPermission(
- requireContext(),
- ACCESS_FINE_LOCATION
- ) == PackageManager.PERMISSION_GRANTED
- ) {
+ if (context?.checkAnyLocationPermission() ?: false) {
enableLocation(!positionSet, false)
positionSet = true
}
@@ -903,7 +898,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
)
}
- @RequiresPermission(ACCESS_FINE_LOCATION)
+ @RequiresPermission(anyOf = [ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION])
private fun enableLocation(moveTo: Boolean, animate: Boolean) {
val map = this.map ?: return
map.setMyLocationEnabled(true)
@@ -917,7 +912,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
}
}
- @RequiresPermission(ACCESS_FINE_LOCATION)
+ @RequiresPermission(anyOf = [ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION])
private fun moveToLastLocation(map: AnyMap, animate: Boolean) {
val location = LocationServices.FusedLocationApi.getLastLocation(locationClient)
if (location != null) {
@@ -1027,7 +1022,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
) {
when (requestCode) {
REQUEST_LOCATION_PERMISSION -> {
- if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
+ if ((grantResults.isNotEmpty() && grantResults.any { it == PackageManager.PERMISSION_GRANTED })) {
enableLocation(moveTo = true, animate = true)
}
}
@@ -1200,11 +1195,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
val map = this.map ?: return
val context = this.context ?: return
if (vm.myLocationEnabled.value == true) {
- if (ActivityCompat.checkSelfPermission(
- context,
- ACCESS_FINE_LOCATION
- ) == PackageManager.PERMISSION_GRANTED
- ) {
+ if (context.checkAnyLocationPermission()) {
moveToLastLocation(map, false)
requestLocationUpdates()
}
diff --git a/app/src/main/java/net/vonforst/evmap/fragment/OnboardingFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/OnboardingFragment.kt
index b12c8945..0bd33526 100644
--- a/app/src/main/java/net/vonforst/evmap/fragment/OnboardingFragment.kt
+++ b/app/src/main/java/net/vonforst/evmap/fragment/OnboardingFragment.kt
@@ -4,11 +4,13 @@ import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Context
+import android.graphics.drawable.AnimatedVectorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
+import android.widget.ImageView
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.viewpager2.widget.ViewPager2
@@ -93,12 +95,18 @@ class WelcomeFragment : OnboardingPageFragment() {
override fun onResume() {
super.onResume()
- binding.animationView.playAnimation()
+ val drawable = (binding.animationView as ImageView).drawable
+ if (drawable is AnimatedVectorDrawable) {
+ drawable.start()
+ }
}
override fun onPause() {
super.onPause()
- binding.animationView.progress = 0f
+ val drawable = (binding.animationView as ImageView).drawable
+ if (drawable is AnimatedVectorDrawable) {
+ drawable.stop()
+ }
}
}
diff --git a/app/src/main/java/net/vonforst/evmap/utils/LocationUtils.kt b/app/src/main/java/net/vonforst/evmap/utils/LocationUtils.kt
index e8f79569..ae13608d 100644
--- a/app/src/main/java/net/vonforst/evmap/utils/LocationUtils.kt
+++ b/app/src/main/java/net/vonforst/evmap/utils/LocationUtils.kt
@@ -1,7 +1,11 @@
package net.vonforst.evmap.utils
+import android.Manifest
+import android.content.Context
import android.content.Intent
+import android.content.pm.PackageManager
import android.location.Location
+import androidx.core.content.ContextCompat
import com.car2go.maps.model.LatLng
import com.car2go.maps.model.LatLngBounds
import kotlin.math.*
@@ -75,3 +79,17 @@ fun boundingBox(pos: LatLng, sizeMeters: Double): LatLngBounds {
pos.plusMeters(sizeMeters, sizeMeters)
)
}
+
+fun Context.checkAnyLocationPermission() = ContextCompat.checkSelfPermission(
+ this,
+ Manifest.permission.ACCESS_FINE_LOCATION
+) == PackageManager.PERMISSION_GRANTED ||
+ ContextCompat.checkSelfPermission(
+ this,
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED
+
+fun Context.checkFineLocationPermission() = ContextCompat.checkSelfPermission(
+ this,
+ Manifest.permission.ACCESS_FINE_LOCATION
+) == PackageManager.PERMISSION_GRANTED
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_appicon_splashscreen.xml b/app/src/main/res/drawable/ic_appicon_splashscreen.xml
deleted file mode 100644
index cc15ae59..00000000
--- a/app/src/main/res/drawable/ic_appicon_splashscreen.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/intro_anim.xml b/app/src/main/res/drawable/intro_anim.xml
new file mode 100644
index 00000000..88210c8c
--- /dev/null
+++ b/app/src/main/res/drawable/intro_anim.xml
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/intro_anim_finished.xml b/app/src/main/res/drawable/intro_anim_finished.xml
new file mode 100644
index 00000000..7f591963
--- /dev/null
+++ b/app/src/main/res/drawable/intro_anim_finished.xml
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/intro_static.xml b/app/src/main/res/drawable/intro_static.xml
new file mode 100644
index 00000000..0fdf5fff
--- /dev/null
+++ b/app/src/main/res/drawable/intro_static.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/launch_screen.xml b/app/src/main/res/drawable/launch_screen.xml
deleted file mode 100644
index 06e1b656..00000000
--- a/app/src/main/res/drawable/launch_screen.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_onboarding_welcome.xml b/app/src/main/res/layout/fragment_onboarding_welcome.xml
index d96054fd..33bddf64 100644
--- a/app/src/main/res/layout/fragment_onboarding_welcome.xml
+++ b/app/src/main/res/layout/fragment_onboarding_welcome.xml
@@ -4,7 +4,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
-
+ app:srcCompat="@drawable/intro_anim_onboarding"
+ android:contentDescription="@string/app_name" />
+
+ #121212
+
\ No newline at end of file
diff --git a/app/src/main/res/values-v31/drawables.xml b/app/src/main/res/values-v31/drawables.xml
new file mode 100644
index 00000000..df61df1a
--- /dev/null
+++ b/app/src/main/res/values-v31/drawables.xml
@@ -0,0 +1,4 @@
+
+
+ @drawable/intro_anim_finished
+
\ No newline at end of file
diff --git a/app/src/main/res/values-v31/styles.xml b/app/src/main/res/values-v31/styles.xml
new file mode 100644
index 00000000..71b76182
--- /dev/null
+++ b/app/src/main/res/values-v31/styles.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index f5ac3830..1c8c9550 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -22,4 +22,5 @@
#546E7A
#00C853
#1F000000
+ #FFFFFF
diff --git a/app/src/main/res/values/drawables.xml b/app/src/main/res/values/drawables.xml
new file mode 100644
index 00000000..636a49c5
--- /dev/null
+++ b/app/src/main/res/values/drawables.xml
@@ -0,0 +1,4 @@
+
+
+ @drawable/intro_anim
+
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 24e03b96..a7e18a56 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -17,8 +17,14 @@
-
+
+