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

Commit 87725a3b authored by Ricki Hirner's avatar Ricki Hirner
Browse files

Show a warning when disk space is low, which will stop synchronization...

Show a warning when disk space is low, which will stop synchronization (resolves bitfireAT/davx5#44)
parent 708c80fa
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -73,6 +73,9 @@ class App: Application(), Thread.UncaughtExceptionHandler {
            // check whether a tasks app is currently installed
            TasksWatcher.updateTaskSync(this)

            // watch storage because low storage means synchronization is stopped
            StorageLowReceiver.getInstance(this)

            // check/repair sync intervals
            AccountSettings.repairSyncIntervals(this)

+79 −0
Original line number Diff line number Diff line
/***************************************************************************************************
 * Copyright © All Contributors. See LICENSE and AUTHORS in the root directory for details.
 **************************************************************************************************/

package at.bitfire.davdroid

import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.provider.Settings
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.lifecycle.MutableLiveData
import at.bitfire.davdroid.log.Logger
import at.bitfire.davdroid.ui.NotificationUtils

class StorageLowReceiver private constructor(
        val context: Context
): BroadcastReceiver(), AutoCloseable {

    companion object {
        fun getInstance(context: Context) =
            Singleton.getInstance(context) { StorageLowReceiver(context) }
    }

    val storageLow = MutableLiveData<Boolean>(false)

    init {
        Logger.log.fine("Listening for device storage low/OK broadcasts")
        val filter = IntentFilter().apply {
            addAction(Intent.ACTION_DEVICE_STORAGE_LOW)
            addAction(Intent.ACTION_DEVICE_STORAGE_OK)
        }
        context.registerReceiver(this, filter)
    }

    override fun close() {
        context.unregisterReceiver(this)
    }


    override fun onReceive(context: Context, intent: Intent) {
        when (intent.action) {
            Intent.ACTION_DEVICE_STORAGE_LOW -> onStorageLow()
            Intent.ACTION_DEVICE_STORAGE_OK -> onStorageOk()
        }
    }

    fun onStorageLow() {
        Logger.log.warning("Low storage, sync will not be started by Android!")

        storageLow.postValue(true)

        val notify = NotificationUtils.newBuilder(context, NotificationUtils.CHANNEL_SYNC_ERRORS)
            .setSmallIcon(R.drawable.ic_storage_notify)
            .setCategory(NotificationCompat.CATEGORY_ERROR)
            .setContentTitle(context.getString(R.string.storage_low_notify_title))
            .setContentText(context.getString(R.string.storage_low_notify_text))

        val settingsIntent = Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS)
        if (settingsIntent.resolveActivity(context.packageManager) != null)
            notify.setContentIntent(PendingIntent.getActivity(context, 0, settingsIntent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE))

        val nm = NotificationManagerCompat.from(context)
        nm.notify(NotificationUtils.NOTIFY_LOW_STORAGE, notify.build())
    }

    fun onStorageOk() {
        Logger.log.info("Storage OK again")

        storageLow.postValue(false)

        val nm = NotificationManagerCompat.from(context)
        nm.cancel(NotificationUtils.NOTIFY_LOW_STORAGE)
    }

}
 No newline at end of file
+18 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.view.*
import androidx.core.content.getSystemService
import androidx.fragment.app.Fragment
@@ -29,6 +30,7 @@ import androidx.recyclerview.widget.RecyclerView
import at.bitfire.davdroid.DavUtils
import at.bitfire.davdroid.DavUtils.SyncStatus
import at.bitfire.davdroid.R
import at.bitfire.davdroid.StorageLowReceiver
import at.bitfire.davdroid.databinding.AccountListBinding
import at.bitfire.davdroid.databinding.AccountListItemBinding
import at.bitfire.davdroid.ui.account.AccountActivity
@@ -50,9 +52,23 @@ class AccountListFragment: Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        model.networkAvailable.observe(viewLifecycleOwner, { networkAvailable ->
        model.networkAvailable.observe(viewLifecycleOwner) { networkAvailable ->
            binding.noNetworkInfo.visibility = if (networkAvailable) View.GONE else View.VISIBLE
        })
        }
        binding.manageConnections.setOnClickListener {
            val intent = Intent(Settings.ACTION_WIRELESS_SETTINGS)
            if (intent.resolveActivity(requireActivity().packageManager) != null)
                startActivity(intent)
        }

        StorageLowReceiver.getInstance(requireActivity()).storageLow.observe(viewLifecycleOwner) { storageLow ->
            binding.lowStorageInfo.visibility = if (storageLow) View.VISIBLE else View.GONE
        }
        binding.manageStorage.setOnClickListener {
            val intent = Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS)
            if (intent.resolveActivity(requireActivity().packageManager) != null)
                startActivity(intent)
        }

        val accountAdapter = AccountAdapter(requireActivity())
        binding.list.apply {
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ object NotificationUtils {
    const val NOTIFY_SYNC_ERROR = 10
    const val NOTIFY_INVALID_RESOURCE = 11
    const val NOTIFY_WEBDAV_ACCESS = 12
    const val NOTIFY_LOW_STORAGE = 13
    const val NOTIFY_OPENTASKS = 20
    const val NOTIFY_PERMISSIONS = 21

+59 −10
Original line number Diff line number Diff line
@@ -5,20 +5,69 @@
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical">

    <androidx.appcompat.widget.AppCompatTextView
    <androidx.cardview.widget.CardView
        android:id="@+id/no_network_info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="12dp"
        android:paddingTop="12dp"
        android:layout_margin="8dp"
        app:contentPadding="@dimen/card_padding">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
        android:visibility="gone"
                app:drawableLeftCompat="@drawable/ic_signal_cellular_off"
                app:drawableTint="?android:attr/textColorPrimary"
                android:drawablePadding="8dp"
                style="@style/TextAppearance.MaterialComponents.Body1"
                android:text="@string/account_list_no_internet"/>

            <Button
                android:id="@+id/manage_connections"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                style="@style/Widget.MaterialComponents.Button.TextButton"
                android:text="Manage connections" />

        </LinearLayout>
    </androidx.cardview.widget.CardView>

    <androidx.cardview.widget.CardView
        android:id="@+id/low_storage_info"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        app:contentPadding="@dimen/card_padding">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <androidx.appcompat.widget.AppCompatTextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:visibility="visible"
                app:drawableLeftCompat="@drawable/ic_storage"
                app:drawableTint="?android:attr/textColorPrimary"
                android:drawablePadding="8dp"
                style="@style/TextAppearance.MaterialComponents.Body1"
                android:text="@string/account_list_low_storage"/>

            <Button
                android:id="@+id/manage_storage"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                style="@style/Widget.MaterialComponents.Button.TextButton"
                android:text="Manage storage" />

        </LinearLayout>
    </androidx.cardview.widget.CardView>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@android:id/list"
        android:layout_width="match_parent"
Loading