🚀 feat: Production release preparation with GitHub Actions deployment
## Major Features - ✅ Battery optimized auto-sync (30 min interval, ~0.4%/day) - ✅ BuildConfig.DEBUG conditional logging (Logger.kt) - ✅ Settings UI cleanup (SSID field removed) - ✅ Interactive notifications (click opens app) - ✅ Post-reboot auto-sync (BootReceiver) - ✅ GitHub Actions deployment workflow ## Implementation Details ### Auto-Sync Architecture - WorkManager PeriodicWorkRequest (30 min intervals) - Gateway IP detection via network interface enumeration - Smart sync only when on home network - BootReceiver restarts monitoring after device reboot ### Logging System - Logger.kt object with BuildConfig.DEBUG checks - Debug logs only in DEBUG builds - Error/warning logs always visible - All components updated (NetworkMonitor, SyncWorker, WebDavSyncService, etc.) ### UI Improvements - Removed confusing SSID field from Settings - Gateway detection fully automatic - Material Design 3 info boxes - Cleaner, simpler user interface ### Notifications - PendingIntent opens MainActivity on click - setAutoCancel(true) for auto-dismiss - Broadcast receiver for UI refresh on sync ### GitHub Actions - Automated APK builds on push to main - Signed releases with proper keystore - 3 APK variants (universal, arm64-v8a, armeabi-v7a) - Semantic versioning: YYYY.MM.DD + build number - Comprehensive release notes with installation guide ## Documentation - README.md: User-friendly German guide - DOCS.md: Technical architecture documentation - GITHUB_ACTIONS_SETUP.md: Deployment setup guide ## Build Configuration - Signing support via key.properties - APK splits for smaller downloads - ProGuard enabled with resource shrinking - BuildConfig generation for DEBUG flag
This commit is contained in:
@@ -1,19 +1,25 @@
|
||||
package dev.dettmer.simplenotes
|
||||
|
||||
import android.Manifest
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import dev.dettmer.simplenotes.utils.Logger
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import dev.dettmer.simplenotes.adapters.NotesAdapter
|
||||
import dev.dettmer.simplenotes.storage.NotesStorage
|
||||
import dev.dettmer.simplenotes.sync.SyncWorker
|
||||
import dev.dettmer.simplenotes.utils.NotificationHelper
|
||||
import dev.dettmer.simplenotes.utils.showToast
|
||||
import android.widget.TextView
|
||||
@@ -34,9 +40,28 @@ class MainActivity : AppCompatActivity() {
|
||||
private val storage by lazy { NotesStorage(this) }
|
||||
|
||||
companion object {
|
||||
private const val TAG = "MainActivity"
|
||||
private const val REQUEST_NOTIFICATION_PERMISSION = 1001
|
||||
}
|
||||
|
||||
/**
|
||||
* BroadcastReceiver für Background-Sync Completion
|
||||
*/
|
||||
private val syncCompletedReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
val success = intent?.getBooleanExtra("success", false) ?: false
|
||||
val count = intent?.getIntExtra("count", 0) ?: 0
|
||||
|
||||
Logger.d(TAG, "📡 Sync completed broadcast received: success=$success, count=$count")
|
||||
|
||||
// UI refresh
|
||||
if (success && count > 0) {
|
||||
loadNotes()
|
||||
Logger.d(TAG, "🔄 Notes reloaded after background sync")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
@@ -56,9 +81,25 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
// Register BroadcastReceiver für Background-Sync
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(
|
||||
syncCompletedReceiver,
|
||||
IntentFilter(SyncWorker.ACTION_SYNC_COMPLETED)
|
||||
)
|
||||
Logger.d(TAG, "📡 BroadcastReceiver registered")
|
||||
|
||||
loadNotes()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
|
||||
// Unregister BroadcastReceiver
|
||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(syncCompletedReceiver)
|
||||
Logger.d(TAG, "📡 BroadcastReceiver unregistered")
|
||||
}
|
||||
|
||||
private fun findViews() {
|
||||
recyclerViewNotes = findViewById(R.id.recyclerViewNotes)
|
||||
textViewEmpty = findViewById(R.id.textViewEmpty)
|
||||
|
||||
Reference in New Issue
Block a user