Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8323ea18 authored by Ricki Hirner's avatar Ricki Hirner
Browse files

AccountActivity: finish when account has been removed externally

parent 2f1ee999
Loading
Loading
Loading
Loading
+50 −40
Original line number Diff line number Diff line
@@ -9,11 +9,13 @@
package at.bitfire.davdroid

import android.accounts.Account
import android.app.IntentService
import android.app.PendingIntent
import android.content.ContentResolver
import android.content.Intent
import android.os.Binder
import android.os.Bundle
import androidx.annotation.WorkerThread
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import at.bitfire.dav4jvm.DavResource
@@ -27,9 +29,6 @@ import at.bitfire.davdroid.model.Collection
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.davdroid.ui.DebugInfoActivity
import at.bitfire.davdroid.ui.NotificationUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import java.lang.ref.WeakReference
@@ -37,7 +36,8 @@ import java.util.*
import java.util.logging.Level
import kotlin.collections.*

class DavService: android.app.Service() {
@Suppress("DEPRECATION")
class DavService: IntentService("DavService") {

    companion object {
        const val ACTION_REFRESH_COLLECTIONS = "refreshCollections"
@@ -61,12 +61,23 @@ class DavService: android.app.Service() {

    }

    private val runningRefresh = HashSet<Long>()
    private val refreshingStatusListeners = LinkedList<WeakReference<RefreshingStatusListener>>()
    /**
     * List of [Service] IDs for which the collections are currently refreshed
     */
    private val runningRefresh = Collections.synchronizedSet(HashSet<Long>())

    /**
     * Currently registered [RefreshingStatusListener]s, which will be notified
     * when a collection refresh status changes
     */
    private val refreshingStatusListeners = Collections.synchronizedList(LinkedList<WeakReference<RefreshingStatusListener>>())


    @WorkerThread
    override fun onHandleIntent(intent: Intent?) {
        if (intent == null)
            return

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        intent?.let {
        val id = intent.getLongExtra(EXTRA_DAV_SERVICE_ID, -1)

        when (intent.action) {
@@ -75,13 +86,10 @@ class DavService: android.app.Service() {
                    refreshingStatusListeners.forEach { listener ->
                        listener.get()?.onDavRefreshStatusChanged(id, true)
                    }
                        CoroutineScope(Dispatchers.IO).launch {

                    val db = AppDatabase.getInstance(this@DavService)
                            db.runInTransaction {
                    refreshCollections(db, id)
                }
                        }
                    }

            ACTION_FORCE_SYNC -> {
                val uri = intent.data!!
@@ -95,9 +103,6 @@ class DavService: android.app.Service() {
        }
    }

        return START_NOT_STICKY
    }


    /* BOUND SERVICE PART
       for communicating with the activities
@@ -115,14 +120,17 @@ class DavService: android.app.Service() {
        fun addRefreshingStatusListener(listener: RefreshingStatusListener, callImmediateIfRunning: Boolean) {
            refreshingStatusListeners += WeakReference<RefreshingStatusListener>(listener)
            if (callImmediateIfRunning)
                runningRefresh.forEach { id -> listener.onDavRefreshStatusChanged(id, true) }
                synchronized(runningRefresh) {
                    for (id in runningRefresh)
                        listener.onDavRefreshStatusChanged(id, true)
                }
        }

        fun removeRefreshingStatusListener(listener: RefreshingStatusListener) {
            val iter = refreshingStatusListeners.iterator()
            while (iter.hasNext()) {
                val item = iter.next().get()
                if (listener == item)
                if (item == listener || item == null)
                    iter.remove()
            }
        }
@@ -355,6 +363,7 @@ class DavService: android.app.Service() {
                }
            }

            db.runInTransaction {
                saveHomesets()

                // use refHomeSet (if available) to determine homeset ID
@@ -363,6 +372,7 @@ class DavService: android.app.Service() {
                        collection.homeSetId = homeSet.id
                    }
                saveCollections()
            }

        } catch(e: InvalidAccountException) {
            Logger.log.log(Level.SEVERE, "Invalid account", e)
+2 −4
Original line number Diff line number Diff line
package at.bitfire.davdroid.model

import androidx.lifecycle.LiveData
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
@@ -12,14 +13,11 @@ interface ServiceDao {
    fun getByAccountAndType(accountName: String, type: String): Service?

    @Query("SELECT id FROM service WHERE accountName=:accountName AND type=:type")
    fun getIdByAccountAndType(accountName: String, type: String): Long?
    fun getIdByAccountAndType(accountName: String, type: String): LiveData<Long>

    @Query("SELECT * FROM service WHERE id=:id")
    fun get(id: Long): Service?

    @Query("SELECT * FROM service WHERE type=:type")
    fun getByType(type: String): List<Service>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insertOrReplace(service: Service): Long

+25 −7
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ package at.bitfire.davdroid.ui.account

import android.accounts.Account
import android.accounts.AccountManager
import android.accounts.OnAccountsUpdateListener
import android.app.Application
import android.content.Intent
import android.os.Build
@@ -53,6 +54,11 @@ class AccountActivity: AppCompatActivity() {
        setSupportActionBar(toolbar)
        supportActionBar?.setDisplayHomeAsUpEnabled(true)

        model.accountExists.observe(this, Observer { accountExists ->
            if (!accountExists)
                finish()
        })

        tab_layout.setupWithViewPager(view_pager)
        val tabsAdapter = TabsAdapter(this)
        view_pager.adapter = tabsAdapter
@@ -172,6 +178,7 @@ class AccountActivity: AppCompatActivity() {
                idxWebcal = null
            }

            // reflect changes in UI
            notifyDataSetChanged()
        }

@@ -208,6 +215,9 @@ class AccountActivity: AppCompatActivity() {
            throw IllegalArgumentException()
        }

        // required to reload all fragments
        override fun getItemPosition(obj: Any) = POSITION_NONE

        override fun getPageTitle(position: Int): String =
                when (position) {
                    idxCardDav -> activity.getString(R.string.account_carddav)
@@ -224,7 +234,7 @@ class AccountActivity: AppCompatActivity() {
    class Model(
            application: Application,
            val account: Account
    ): AndroidViewModel(application) {
    ): AndroidViewModel(application), OnAccountsUpdateListener {

        class Factory(
                val application: Application,
@@ -236,20 +246,20 @@ class AccountActivity: AppCompatActivity() {
        }

        private val db = AppDatabase.getInstance(application)
        val accountManager = AccountManager.get(application)
        val accountSettings by lazy { AccountSettings(getApplication(), account) }

        val cardDavService = MutableLiveData<Long>()
        val calDavService = MutableLiveData<Long>()
        val accountExists = MutableLiveData<Boolean>()
        val cardDavService = db.serviceDao().getIdByAccountAndType(account.name, Service.TYPE_CARDDAV)
        val calDavService = db.serviceDao().getIdByAccountAndType(account.name, Service.TYPE_CALDAV)

        val showOnlyPersonal = MutableLiveData<Boolean>()
        val showOnlyPersonal_writable = MutableLiveData<Boolean>()


        init {
            accountManager.addOnAccountsUpdatedListener(this, null, true)
            viewModelScope.launch(Dispatchers.IO) {
                cardDavService.postValue(db.serviceDao().getIdByAccountAndType(account.name, Service.TYPE_CARDDAV))
                calDavService.postValue(db.serviceDao().getIdByAccountAndType(account.name, Service.TYPE_CALDAV))

                accountSettings.getShowOnlyPersonal().let { (value, locked) ->
                    showOnlyPersonal.postValue(value)
                    showOnlyPersonal_writable.postValue(locked)
@@ -257,6 +267,14 @@ class AccountActivity: AppCompatActivity() {
            }
        }

        override fun onCleared() {
            accountManager.removeOnAccountsUpdatedListener(this)
        }

        override fun onAccountsUpdated(accounts: Array<out Account>) {
            accountExists.postValue(accounts.contains(account))
        }

        fun toggleReadOnly(item: Collection) {
            viewModelScope.launch(Dispatchers.IO + NonCancellable) {
                val newItem = item.copy(forceReadOnly = !item.forceReadOnly)
+6 −7
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ import android.provider.CalendarContract
import android.provider.ContactsContract
import android.view.*
import android.widget.PopupMenu
import androidx.annotation.WorkerThread
import androidx.annotation.AnyThread
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
@@ -24,12 +24,10 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import at.bitfire.davdroid.Constants
import at.bitfire.davdroid.DavService
import at.bitfire.davdroid.R
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.model.AppDatabase
import at.bitfire.davdroid.model.Collection
import at.bitfire.davdroid.resource.LocalAddressBook
import at.bitfire.davdroid.resource.TaskUtils
import at.bitfire.davdroid.settings.AccountSettings
import at.bitfire.davdroid.settings.SettingsManager
import kotlinx.android.synthetic.main.account_collections.*
import kotlinx.coroutines.Dispatchers
@@ -314,18 +312,19 @@ abstract class CollectionsFragment: Fragment(), SwipeRefreshLayout.OnRefreshList
            context.startService(intent)
        }

        @WorkerThread
        @AnyThread
        override fun onDavRefreshStatusChanged(id: Long, refreshing: Boolean) {
            if (id == serviceId.value)
                isRefreshing.postValue(refreshing)
        }

        @AnyThread
        override fun onStatusChanged(which: Int) {
            viewModelScope.launch(Dispatchers.Default) {
            checkSyncStatus()
        }
        }

        @AnyThread
        @Synchronized
        private fun checkSyncStatus() {
            if (collectionType == Collection.TYPE_ADDRESSBOOK) {
                val mainAuthority = context.getString(R.string.address_books_authority)