Fix: Add missing permissions and runtime permission handling for auto-sync

Critical fixes for SSID detection on Android 12+:
- Add CHANGE_WIFI_STATE permission (NetworkCallback registration)
- Add ACCESS_BACKGROUND_LOCATION permission (SSID access)
- Add FOREGROUND_SERVICE_DATA_SYNC permission

SettingsActivity improvements:
- Add checkBackgroundLocationPermission() method
- Show dialog explaining need for 'Always allow' location
- Request permission with proper callbacks
- Better user feedback for permission grants/denials

NetworkMonitor improvements:
- Add initial WiFi check in startMonitoring()
- Add NET_CAPABILITY_INTERNET to NetworkRequest
- Better error handling for '<unknown ssid>' cases
- Log warning about missing BACKGROUND_LOCATION permission

This should fix the root cause: SSID was showing as '<unknown ssid>'
because app lacked background location permission on Android 16.
User must select 'Always allow' when prompted for location permission.
This commit is contained in:
inventory69
2025-12-20 21:30:56 +01:00
parent 980343866f
commit 933646f28b
3 changed files with 116 additions and 20 deletions

View File

@@ -5,9 +5,13 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<application
android:name=".SimpleNotesApplication"

View File

@@ -42,6 +42,7 @@ class SettingsActivity : AppCompatActivity() {
companion object {
private const val REQUEST_LOCATION_PERMISSION = 1002
private const val REQUEST_BACKGROUND_LOCATION_PERMISSION = 1003
}
override fun onCreate(savedInstanceState: Bundle?) {
@@ -182,26 +183,6 @@ class SettingsActivity : AppCompatActivity() {
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
REQUEST_LOCATION_PERMISSION -> {
if (grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission granted, try again
detectCurrentSSID()
} else {
showToast("Standort-Berechtigung benötigt um WLAN-Name zu erkennen")
}
}
}
}
private fun onAutoSyncToggled(enabled: Boolean) {
prefs.edit().putBoolean(Constants.KEY_AUTO_SYNC, enabled).apply()
@@ -209,6 +190,8 @@ class SettingsActivity : AppCompatActivity() {
showToast("Auto-Sync aktiviert")
// Check battery optimization when enabling
checkBatteryOptimization()
// Check background location permission (needed for SSID on Android 12+)
checkBackgroundLocationPermission()
} else {
showToast("Auto-Sync deaktiviert")
}
@@ -257,6 +240,102 @@ class SettingsActivity : AppCompatActivity() {
}
}
private fun checkBackgroundLocationPermission() {
// Background location permission only needed on Android 10+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
return
}
// First check if we have foreground location
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
// Request foreground location first
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
REQUEST_LOCATION_PERMISSION
)
return
}
// Now check background location (Android 10+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (ContextCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
showBackgroundLocationDialog()
}
}
}
private fun showBackgroundLocationDialog() {
AlertDialog.Builder(this)
.setTitle("Hintergrund-Standort")
.setMessage(
"Damit die App dein WLAN-Netzwerk erkennen kann, " +
"wird Zugriff auf den Standort im Hintergrund benötigt.\n\n" +
"Dies ist eine Android-Einschränkung ab Version 10.\n\n" +
"Bitte wähle im nächsten Dialog 'Immer zulassen'."
)
.setPositiveButton("Fortfahren") { _, _ ->
requestBackgroundLocationPermission()
}
.setNegativeButton("Später") { dialog, _ ->
dialog.dismiss()
showToast("Auto-Sync funktioniert ohne diese Berechtigung nicht")
}
.setCancelable(false)
.show()
}
private fun requestBackgroundLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION),
REQUEST_BACKGROUND_LOCATION_PERMISSION
)
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
REQUEST_LOCATION_PERMISSION -> {
if (grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Foreground location granted, now request background
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
checkBackgroundLocationPermission()
} else {
// For detectCurrentSSID
detectCurrentSSID()
}
} else {
showToast("Standort-Berechtigung benötigt um WLAN-Name zu erkennen")
}
}
REQUEST_BACKGROUND_LOCATION_PERMISSION -> {
if (grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED) {
showToast("✅ Hintergrund-Standort erlaubt - Auto-Sync sollte jetzt funktionieren!")
} else {
showToast("⚠️ Ohne Hintergrund-Standort kann WLAN nicht erkannt werden")
}
}
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
android.R.id.home -> {

View File

@@ -66,11 +66,17 @@ class NetworkMonitor(private val context: Context) {
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
try {
connectivityManager.registerNetworkCallback(request, networkCallback)
Log.d(TAG, "✅ NetworkCallback registered successfully")
// *** FIX #3: Check if already connected to WiFi ***
Log.d(TAG, "🔍 Performing initial WiFi check...")
checkAndTriggerSync()
} catch (e: Exception) {
Log.e(TAG, "❌ Failed to register NetworkCallback: ${e.message}", e)
}
@@ -134,6 +140,13 @@ class NetworkMonitor(private val context: Context) {
Log.d(TAG, "Current SSID: '$currentSSID', Home SSID: '$homeSSID'")
// *** FIX #4: Better error handling for missing SSID ***
if (currentSSID.isEmpty() || currentSSID == "<unknown ssid>") {
Log.w(TAG, "⚠️ Cannot get SSID - likely missing ACCESS_BACKGROUND_LOCATION permission!")
Log.w(TAG, "⚠️ On Android 12+, apps need 'Allow all the time' location permission")
return false
}
val isHome = currentSSID == homeSSID
Log.d(TAG, "Is home WiFi: $isHome")