diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a7bdf862067406ba26803706100c91216fa85a46..5b46c8ad26cf74c2bc95fd6e1e4a6ba40f775faa 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,6 +16,7 @@ android:name=".ui.chat.ChatActivity" android:exported="false" android:label="@string/app_name" + android:launchMode="singleInstance" android:windowSoftInputMode="adjustResize" /> <activity android:name=".ui.setup.accounts.AccountSetupActivity" @@ -33,7 +34,7 @@ android:name=".ui.settings.SettingsActivity" android:exported="false" android:label="@string/label_settings" - android:parentActivityName=".ui.chat.ChatActivity" + android:parentActivityName=".ui.setup.accounts.AccountSelectionActivity" android:windowSoftInputMode="adjustResize" /> <activity android:name=".ui.setup.accounts.AccountSelectionActivity" diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt index 7783f763f3ca5e3dce215f7f81342e8b0da4dfad..4b12192c4cbdce451abcaa4bbeb4fcdb549e9de8 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/service/QuasselService.kt @@ -17,8 +17,9 @@ import de.kuschku.quasseldroid_ng.persistence.QuasselDatabase import de.kuschku.quasseldroid_ng.ui.settings.data.ConnectionSettings import de.kuschku.quasseldroid_ng.ui.settings.data.Settings import de.kuschku.quasseldroid_ng.util.AndroidHandlerThread -import de.kuschku.quasseldroid_ng.util.NotificationManager +import de.kuschku.quasseldroid_ng.util.QuasseldroidNotificationManager import de.kuschku.quasseldroid_ng.util.compatibility.AndroidHandlerService +import de.kuschku.quasseldroid_ng.util.helper.editApply import de.kuschku.quasseldroid_ng.util.helper.sharedPreferences import de.kuschku.quasseldroid_ng.util.helper.toLiveData import io.reactivex.Observable @@ -60,8 +61,8 @@ class QuasselService : LifecycleService(), private var accountId: Long = -1 private var reconnect: Boolean = false - private lateinit var notificationManager: NotificationManager - private var notificationHandle: NotificationManager.Handle? = null + private lateinit var notificationManager: QuasseldroidNotificationManager + private var notificationHandle: QuasseldroidNotificationManager.Handle? = null private var progress = Triple(ConnectionState.DISCONNECTED, 0, 0) private fun updateNotificationStatus() { @@ -75,7 +76,23 @@ class QuasselService : LifecycleService(), } } - private fun updateNotification(handle: NotificationManager.Handle) { + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + val result = super.onStartCommand(intent, flags, startId) + handleIntent(intent) + return result + } + + private fun handleIntent(intent: Intent?) { + if (intent?.getBooleanExtra("disconnect", false) == true) { + sharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE) { + editApply { + putBoolean(Keys.Status.reconnect, false) + } + } + } + } + + private fun updateNotification(handle: QuasseldroidNotificationManager.Handle) { val (state, progress, max) = this.progress when (state) { ConnectionState.DISCONNECTED -> { @@ -103,10 +120,10 @@ class QuasselService : LifecycleService(), private fun updateConnection(accountId: Long, reconnect: Boolean) { handler.post { - val account = if (accountId == -1L || !reconnect) { - null - } else { + val account = if (accountId != -1L && reconnect) { AccountDatabase.Creator.init(this).accounts().findById(accountId) + } else { + null } if (account == null) { @@ -192,19 +209,15 @@ class QuasselService : LifecycleService(), override fun disconnect(forever: Boolean) { handler.post { backendImplementation.disconnect(forever) - if (forever) + if (forever) { stopSelf() + } } } override fun sessionManager() = backendImplementation.sessionManager() } - override fun onDestroy() { - handler.onDestroy() - super.onDestroy() - } - private lateinit var database: QuasselDatabase private val receiver = object : BroadcastReceiver() { @@ -263,12 +276,28 @@ class QuasselService : LifecycleService(), registerReceiver(receiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)) - notificationManager = NotificationManager(this) + notificationManager = QuasseldroidNotificationManager(this) notificationManager.init() update() } + override fun onDestroy() { + sharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE) { + unregisterOnSharedPreferenceChangeListener(this@QuasselService) + } + sharedPreferences { + unregisterOnSharedPreferenceChangeListener(this@QuasselService) + } + + unregisterReceiver(receiver) + + notificationHandle?.let { notificationManager.remove(it) } + + handler.onDestroy() + super.onDestroy() + } + override fun onBind(intent: Intent?): QuasselBinder { super.onBind(intent) return QuasselBinder(asyncBackend) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt index a5f4eb6fac183ccec97c4d82536e5207937864e1..3b1f64e2ec9f3d72abbbf1ac6c497292f1299b51 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChatActivity.kt @@ -5,7 +5,10 @@ import android.arch.lifecycle.Observer import android.arch.lifecycle.ViewModelProviders import android.content.Context import android.content.Intent +import android.content.SharedPreferences +import android.os.Build import android.os.Bundle +import android.os.PersistableBundle import android.support.design.widget.Snackbar import android.support.v4.widget.DrawerLayout import android.support.v7.app.ActionBarDrawerToggle @@ -38,7 +41,7 @@ import de.kuschku.quasseldroid_ng.util.helper.sharedPreferences import de.kuschku.quasseldroid_ng.util.service.ServiceBoundActivity import de.kuschku.quasseldroid_ng.util.ui.MaterialContentLoadingProgressBar -class ChatActivity : ServiceBoundActivity() { +class ChatActivity : ServiceBoundActivity(), SharedPreferences.OnSharedPreferenceChangeListener { @BindView(R.id.drawerLayout) lateinit var drawerLayout: DrawerLayout @@ -129,8 +132,8 @@ class ChatActivity : ServiceBoundActivity() { drawerToggle = ActionBarDrawerToggle( this, drawerLayout, - R.string.label_drawer_open, - R.string.label_drawer_close + R.string.label_open, + R.string.label_close ) drawerToggle.syncState() @@ -171,11 +174,27 @@ class ChatActivity : ServiceBoundActivity() { outState?.putInt("OPEN_BUFFER", viewModel.getBuffer().value ?: -1) } + override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) { + super.onSaveInstanceState(outState, outPersistentState) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + outPersistentState?.putInt("OPEN_BUFFER", viewModel.getBuffer().value ?: -1) + } + } + override fun onRestoreInstanceState(savedInstanceState: Bundle?) { super.onRestoreInstanceState(savedInstanceState) viewModel.setBuffer(savedInstanceState?.getInt("OPEN_BUFFER", -1) ?: -1) } + override fun onRestoreInstanceState(savedInstanceState: Bundle?, + persistentState: PersistableBundle?) { + super.onRestoreInstanceState(savedInstanceState, persistentState) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + val fallback = persistentState?.getInt("OPEN_BUFFER", -1) ?: -1 + viewModel.setBuffer(savedInstanceState?.getInt("OPEN_BUFFER", fallback) ?: fallback) + } + } + override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.activity_main, menu) return super.onCreateOptionsMenu(menu) diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/NotificationManager.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/QuasseldroidNotificationManager.kt similarity index 69% rename from app/src/main/java/de/kuschku/quasseldroid_ng/util/NotificationManager.kt rename to app/src/main/java/de/kuschku/quasseldroid_ng/util/QuasseldroidNotificationManager.kt index 74b7ad5384d3d251824e8994b030b94cf6c8527b..b5dca3a8f37a3376ddff3318a7353949742ea799 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/NotificationManager.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/QuasseldroidNotificationManager.kt @@ -10,12 +10,13 @@ import android.os.Build import android.support.v4.app.NotificationCompat import android.support.v4.app.NotificationManagerCompat import de.kuschku.quasseldroid_ng.R -import de.kuschku.quasseldroid_ng.ui.setup.accounts.AccountSelectionActivity +import de.kuschku.quasseldroid_ng.service.QuasselService +import de.kuschku.quasseldroid_ng.ui.chat.ChatActivity import de.kuschku.quasseldroid_ng.util.helper.editApply import de.kuschku.quasseldroid_ng.util.helper.sharedPreferences import de.kuschku.quasseldroid_ng.util.helper.systemService -class NotificationManager(private val context: Context) { +class QuasseldroidNotificationManager(private val context: Context) { fun init() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) prepareChannels() @@ -50,16 +51,23 @@ class NotificationManager(private val context: Context) { } fun notificationBackground(): Handle { + val intentOpen = Intent(context.applicationContext, ChatActivity::class.java) + intentOpen.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP + val pendingIntentOpen = PendingIntent.getActivity(context.applicationContext, 0, intentOpen, 0) + + val intentDisconnect = Intent(context, QuasselService::class.java) + intentDisconnect.putExtra("disconnect", true) + val pendingIntentDisconnect = PendingIntent.getService( + context, 0, intentDisconnect, PendingIntent.FLAG_UPDATE_CURRENT + ) + val notification = NotificationCompat.Builder( context.applicationContext, context.getString(R.string.notification_channel_background) ) - .setContentIntent( - PendingIntent.getActivity( - context.applicationContext, 0, - Intent(context.applicationContext, AccountSelectionActivity::class.java), 0 - ) - ) + .setContentIntent(pendingIntentOpen) + .addAction(0, context.getString(R.string.label_open), pendingIntentOpen) + .addAction(0, context.getString(R.string.label_disconnect), pendingIntentDisconnect) .setSmallIcon(R.mipmap.ic_launcher_recents) .setPriority(NotificationCompat.PRIORITY_MIN) return Handle(BACKGROUND_NOTIFICATION_ID, notification) @@ -69,6 +77,10 @@ class NotificationManager(private val context: Context) { NotificationManagerCompat.from(context).notify(handle.id, handle.builder.build()) } + fun remove(handle: Handle) { + NotificationManagerCompat.from(context).cancel(handle.id) + } + companion object { val BACKGROUND_NOTIFICATION_ID = Int.MAX_VALUE } diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt b/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt index 66ba271fe6246df7c5ca034b2ccc1fa5eb3e8e88..7a500a5436f0b0952b3961bdec1e7a6f68027542 100644 --- a/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt +++ b/app/src/main/java/de/kuschku/quasseldroid_ng/util/service/ServiceBoundActivity.kt @@ -1,7 +1,9 @@ package de.kuschku.quasseldroid_ng.util.service +import android.app.Activity import android.arch.lifecycle.LiveData import android.content.Context +import android.content.SharedPreferences import android.os.Bundle import android.support.annotation.ColorRes import android.support.annotation.DrawableRes @@ -12,9 +14,11 @@ import de.kuschku.quasseldroid_ng.R import de.kuschku.quasseldroid_ng.ui.settings.data.AppearanceSettings import de.kuschku.quasseldroid_ng.ui.settings.data.ConnectionSettings import de.kuschku.quasseldroid_ng.ui.settings.data.Settings +import de.kuschku.quasseldroid_ng.util.helper.sharedPreferences import de.kuschku.quasseldroid_ng.util.helper.updateRecentsHeaderIfExisting -abstract class ServiceBoundActivity : AppCompatActivity() { +abstract class ServiceBoundActivity : AppCompatActivity(), + SharedPreferences.OnSharedPreferenceChangeListener { @DrawableRes protected val icon: Int = R.mipmap.ic_launcher_recents @ColorRes @@ -54,13 +58,33 @@ abstract class ServiceBoundActivity : AppCompatActivity() { if (Settings.appearance(this) != appearanceSettings) { recreate() } + sharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE) { + registerOnSharedPreferenceChangeListener(this@ServiceBoundActivity) + } connection.bind() + checkConnection() super.onStart() } override fun onStop() { super.onStop() connection.unbind() + sharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE) { + unregisterOnSharedPreferenceChangeListener(this@ServiceBoundActivity) + } + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + checkConnection() + } + + private fun checkConnection() { + if (!sharedPreferences(Keys.Status.NAME, Context.MODE_PRIVATE) { + getBoolean(Keys.Status.reconnect, false) + }) { + setResult(Activity.RESULT_OK) + finish() + } } protected fun stopService() { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 96a8e3ab66e7476d32851a536d810e3970af4f36..62902007f8b1ae7d0f3782e5ef3f1785fe155102 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -8,8 +8,8 @@ <string name="label_clear_backlog">Clear Backlog</string> <string name="label_delete">Delete</string> <string name="label_disconnect">Disconnect</string> - <string name="label_drawer_close">Close</string> - <string name="label_drawer_open">Open</string> + <string name="label_close">Close</string> + <string name="label_open">Open</string> <string name="label_filter_messages">Filter Messages</string> <string name="label_input_history">Input History</string> <string name="label_placeholder">Write a messageā¦</string>