Add ACCESS_BACKGROUND_LOCATION permission required by Android 11.

This commit is contained in:
azuo 2021-09-13 19:28:47 +08:00
parent 8c84913cd8
commit d3b623cf13
7 changed files with 87 additions and 75 deletions

View File

@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.android.vending.BILLING" /> <uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
@ -13,6 +14,7 @@
<uses-permission android:name="android.gms.permission.ACTIVITY_RECOGNITION"/> <uses-permission android:name="android.gms.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" /> <uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
<application <application
android:allowBackup="true" android:allowBackup="true"
@ -24,24 +26,24 @@
android:usesCleartextTraffic="true" android:usesCleartextTraffic="true"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
tools:ignore="LockedOrientationActivity"> tools:ignore="LockedOrientationActivity">
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait"> <activity android:name=".ui.activities.MainActivity" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".ui.activities.tabs.ChooseApplicationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.ChooseApplicationActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.CustomFontActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.CustomFontActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.CustomLocationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.CustomLocationActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.WeatherProviderActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.WeatherProviderActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.settings.SupportDevActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.settings.SupportDevActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.CustomDateActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.CustomDateActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.settings.IntegrationsActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.settings.IntegrationsActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.MusicPlayersFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.MusicPlayersFilterActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.AppNotificationsFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.AppNotificationsFilterActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.MediaInfoFormatActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.MediaInfoFormatActivity" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.TimeZoneSelectorActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.TimeZoneSelectorActivity" android:screenOrientation="portrait" />
<receiver android:name=".ui.widgets.MainWidget"> <receiver android:name=".ui.widgets.MainWidget">
<intent-filter> <intent-filter>

View File

@ -21,11 +21,20 @@ object WeatherHelper {
suspend fun updateWeather(context: Context) { suspend fun updateWeather(context: Context) {
Kotpref.init(context) Kotpref.init(context)
val networkApi = WeatherNetworkApi(context)
if (Preferences.customLocationAdd != "") { if (Preferences.customLocationAdd != "") {
networkApi.updateWeather() WeatherNetworkApi(context).updateWeather()
} else if (context.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) { } else if (context.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) &&
(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R ||
context.checkGrantedPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION))
) {
LocationService.requestNewLocation(context) LocationService.requestNewLocation(context)
} else {
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_missing_location)
Preferences.weatherProviderError = ""
removeWeather(context)
org.greenrobot.eventbus.EventBus.getDefault().post(
com.tommasoberlose.anotherwidget.ui.fragments.MainFragment.UpdateUiMessageEvent()
)
} }
} }

View File

@ -42,6 +42,13 @@ class WeatherNetworkApi(val context: Context) {
Constants.WeatherProvider.YR -> useYrProvider(context) Constants.WeatherProvider.YR -> useYrProvider(context)
} }
} else { } else {
if (!Preferences.showWeather)
Preferences.weatherProviderError = context.getString(R.string.show_weather_not_visible)
else {
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_missing_location)
Preferences.weatherProviderError = ""
}
WeatherHelper.removeWeather( WeatherHelper.removeWeather(
context context
) )

View File

@ -18,6 +18,7 @@ import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import kotlinx.coroutines.* import kotlinx.coroutines.*
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import java.lang.Exception import java.lang.Exception
@ -37,10 +38,9 @@ class LocationService : Service() {
startForeground(LOCATION_ACCESS_NOTIFICATION_ID, getLocationAccessNotification()) startForeground(LOCATION_ACCESS_NOTIFICATION_ID, getLocationAccessNotification())
job?.cancel() job?.cancel()
job = GlobalScope.launch(Dispatchers.IO) { job = GlobalScope.launch(Dispatchers.IO) {
if (ActivityCompat.checkSelfPermission( if (checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) &&
this@LocationService, (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R ||
Manifest.permission.ACCESS_FINE_LOCATION checkGrantedPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION))
) == PackageManager.PERMISSION_GRANTED
) { ) {
if (com.google.android.gms.common.GoogleApiAvailability.getInstance() if (com.google.android.gms.common.GoogleApiAvailability.getInstance()
.isGooglePlayServicesAvailable(this@LocationService) .isGooglePlayServicesAvailable(this@LocationService)

View File

@ -46,11 +46,16 @@ class CustomLocationActivity : AppCompatActivity() {
adapter = SlimAdapter.create() adapter = SlimAdapter.create()
adapter adapter
.register<String>(R.layout.custom_location_item) { _, injector -> .register<String>(R.layout.custom_location_item) { _, injector ->
injector injector.text(R.id.text, getString(R.string.custom_location_gps))
.text(R.id.text, getString(R.string.custom_location_gps)) injector.clicked(R.id.text) {
.clicked(R.id.text) { Preferences.bulk {
requirePermission() remove(Preferences::customLocationLat)
remove(Preferences::customLocationLon)
remove(Preferences::customLocationAdd)
} }
setResult(Activity.RESULT_OK)
finish()
}
} }
.register<Address>(R.layout.custom_location_item) { item, injector -> .register<Address>(R.layout.custom_location_item) { item, injector ->
injector.text(R.id.text, item.getAddressLine(0) ?: "") injector.text(R.id.text, item.getAddressLine(0) ?: "")
@ -59,9 +64,9 @@ class CustomLocationActivity : AppCompatActivity() {
customLocationLat = item.latitude.toString() customLocationLat = item.latitude.toString()
customLocationLon = item.longitude.toString() customLocationLon = item.longitude.toString()
customLocationAdd = item.getAddressLine(0) ?: "" customLocationAdd = item.getAddressLine(0) ?: ""
setResult(Activity.RESULT_OK)
finish()
} }
setResult(Activity.RESULT_OK)
finish()
} }
} }
.attachTo(binding.listView) .attachTo(binding.listView)
@ -115,36 +120,6 @@ class CustomLocationActivity : AppCompatActivity() {
}) })
} }
private fun requirePermission() {
Dexter.withContext(this)
.withPermissions(
Manifest.permission.ACCESS_FINE_LOCATION
).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let {
if (report.areAllPermissionsGranted()){
Preferences.bulk {
remove(Preferences::customLocationLat)
remove(Preferences::customLocationLon)
remove(Preferences::customLocationAdd)
}
setResult(Activity.RESULT_OK)
finish()
}
}
}
override fun onPermissionRationaleShouldBeShown(
permissions: MutableList<PermissionRequest>?,
token: PermissionToken?
) {
// Remember to invoke this method when the custom rationale is closed
// or just by default if you don't want to use any custom rationale.
token?.continuePermissionRequest()
}
})
.check()
}
private fun setupListener() { private fun setupListener() {
binding.actionBack.setOnClickListener { binding.actionBack.setOnClickListener {
onBackPressed() onBackPressed()

View File

@ -127,11 +127,11 @@ class WeatherProviderActivity : AppCompatActivity() {
private fun subscribeUi(viewModel: WeatherProviderViewModel) { private fun subscribeUi(viewModel: WeatherProviderViewModel) {
viewModel.weatherProviderError.observe(this) { viewModel.weatherProviderError.observe(this) {
updateListItem() binding.listView.postDelayed({ updateListItem() }, 300)
} }
viewModel.weatherProviderLocationError.observe(this) { viewModel.weatherProviderLocationError.observe(this) {
updateListItem() binding.listView.postDelayed({ updateListItem() }, 300)
} }
} }

View File

@ -91,16 +91,17 @@ class WeatherFragment : Fragment() {
viewModel.weatherProvider.observe(viewLifecycleOwner) { viewModel.weatherProvider.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
binding.labelWeatherProvider.text = WeatherHelper.getProviderName(requireContext(), Constants.WeatherProvider.fromInt(it)!!) binding.labelWeatherProvider.text = WeatherHelper.getProviderName(requireContext(), Constants.WeatherProvider.fromInt(it)!!)
checkWeatherProviderConfig()
} }
} }
viewModel.weatherProviderError.observe(viewLifecycleOwner) { viewModel.weatherProviderError.observe(viewLifecycleOwner) {
checkWeatherProviderConfig() checkWeatherProviderConfig()
checkLocationPermission()
} }
viewModel.weatherProviderLocationError.observe(viewLifecycleOwner) { viewModel.weatherProviderLocationError.observe(viewLifecycleOwner) {
checkWeatherProviderConfig() checkWeatherProviderConfig()
checkLocationPermission()
} }
viewModel.customLocationAdd.observe(viewLifecycleOwner) { viewModel.customLocationAdd.observe(viewLifecycleOwner) {
@ -108,6 +109,7 @@ class WeatherFragment : Fragment() {
binding.labelCustomLocation.text = binding.labelCustomLocation.text =
if (it == "") getString(R.string.custom_location_gps) else it if (it == "") getString(R.string.custom_location_gps) else it
} }
checkWeatherProviderConfig()
checkLocationPermission() checkLocationPermission()
} }
@ -116,43 +118,50 @@ class WeatherFragment : Fragment() {
binding.tempUnit.text = binding.tempUnit.text =
if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius) if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius)
} }
checkLocationPermission()
} }
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner) { viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
binding.labelWeatherRefreshPeriod.text = getString(SettingsStringHelper.getRefreshPeriodString(it)) binding.labelWeatherRefreshPeriod.text = getString(SettingsStringHelper.getRefreshPeriodString(it))
} }
checkLocationPermission()
} }
viewModel.weatherIconPack.observe(viewLifecycleOwner) { viewModel.weatherIconPack.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
binding.labelWeatherIconPack.text = getString(R.string.settings_weather_icon_pack_default).format((it + 1)) binding.labelWeatherIconPack.text = getString(R.string.settings_weather_icon_pack_default).format((it + 1))
} }
checkLocationPermission()
} }
} }
private fun checkLocationPermission() { private fun checkLocationPermission() {
if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) { if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) &&
(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R ||
requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION))
) {
binding.locationPermissionAlert.isVisible = false binding.locationPermissionAlert.isVisible = false
WeatherReceiver.setUpdates(requireContext()) } else if (Preferences.customLocationAdd == "") {
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
binding.locationPermissionAlert.isVisible = true binding.locationPermissionAlert.isVisible = true
binding.locationPermissionAlert.setOnClickListener { binding.locationPermissionAlert.setOnClickListener {
requirePermission() requirePermission()
} }
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R &&
requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)
) {
val text = getString(R.string.action_grant_permission) + " - " +
requireContext().packageManager.backgroundPermissionOptionLabel
binding.locationPermissionAlert.text = text
}
binding.weatherProviderLocationError.isVisible = false
} else { } else {
binding.locationPermissionAlert.isVisible = false binding.locationPermissionAlert.isVisible = false
} }
} }
private fun checkWeatherProviderConfig() { private fun checkWeatherProviderConfig() {
binding.weatherProviderError.isVisible = Preferences.showWeather && Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-" binding.weatherProviderError.isVisible = Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-"
binding.weatherProviderError.text = Preferences.weatherProviderError binding.weatherProviderError.text = Preferences.weatherProviderError
binding.weatherProviderLocationError.isVisible = Preferences.showWeather && Preferences.weatherProviderLocationError != "" binding.weatherProviderLocationError.isVisible = Preferences.weatherProviderLocationError != ""
binding.weatherProviderLocationError.text = Preferences.weatherProviderLocationError binding.weatherProviderLocationError.text = Preferences.weatherProviderLocationError
} }
@ -177,11 +186,11 @@ class WeatherFragment : Fragment() {
.addItem(getString(R.string.celsius), "C") .addItem(getString(R.string.celsius), "C")
.addOnSelectItemListener { value -> .addOnSelectItemListener { value ->
if (value != Preferences.weatherTempUnit) { if (value != Preferences.weatherTempUnit) {
Preferences.weatherTempUnit = value
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
WeatherHelper.updateWeather(requireContext()) WeatherHelper.updateWeather(requireContext())
} }
} }
Preferences.weatherTempUnit = value
}.show() }.show()
} }
@ -193,7 +202,10 @@ class WeatherFragment : Fragment() {
} }
dialog dialog
.addOnSelectItemListener { value -> .addOnSelectItemListener { value ->
Preferences.weatherRefreshPeriod = value if (value != Preferences.weatherRefreshPeriod) {
Preferences.weatherRefreshPeriod = value
WeatherReceiver.setUpdates(requireContext())
}
}.show() }.show()
} }
@ -206,12 +218,12 @@ class WeatherFragment : Fragment() {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
when (requestCode) { when (requestCode) {
Constants.RESULT_CODE_CUSTOM_LOCATION -> { Constants.RESULT_CODE_CUSTOM_LOCATION -> {
WeatherReceiver.setUpdates(requireContext()) viewLifecycleOwner.lifecycleScope.launch {
checkLocationPermission() WeatherHelper.updateWeather(requireContext())
} }
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
checkLocationPermission()
} }
//RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
//}
} }
} }
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
@ -220,12 +232,19 @@ class WeatherFragment : Fragment() {
private fun requirePermission() { private fun requirePermission() {
Dexter.withContext(requireContext()) Dexter.withContext(requireContext())
.withPermissions( .withPermissions(
Manifest.permission.ACCESS_FINE_LOCATION if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R &&
requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION))
Manifest.permission.ACCESS_BACKGROUND_LOCATION
else
Manifest.permission.ACCESS_FINE_LOCATION
).withListener(object: MultiplePermissionsListener { ).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) { override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let { report?.let {
if (report.areAllPermissionsGranted()){ if (report.areAllPermissionsGranted()) {
checkLocationPermission() checkLocationPermission()
viewLifecycleOwner.lifecycleScope.launch {
WeatherHelper.updateWeather(requireContext())
}
} }
} }
} }