diff --git a/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt b/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt
index 368c89a3c97baed45e11851f772c24498fac62b0..2a4ee09891f02fecbfd545080095a7a45ee3fe2b 100644
--- a/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt
+++ b/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt
@@ -34,6 +34,7 @@ import foundation.e.apps.install.pkg.PkgManagerModule
import foundation.e.apps.install.updates.UpdatesWorkManager
import foundation.e.apps.install.workmanager.InstallWorkManager
import foundation.e.apps.ui.setup.tos.TOS_VERSION
+import foundation.e.apps.utils.CustomUncaughtExceptionHandler
import foundation.e.lib.telemetry.Telemetry
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.MainScope
@@ -59,10 +60,15 @@ class AppLoungeApplication : Application(), Configuration.Provider {
@Inject
lateinit var preferenceManagerModule: PreferenceManagerModule
+ @Inject
+ lateinit var uncaughtExceptionHandler: CustomUncaughtExceptionHandler
+
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
override fun onCreate() {
super.onCreate()
+ Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler)
+
InstallWorkManager.context = this
// Register broadcast receiver for package manager
val pkgManagerBR = object : PkgManagerBR() {}
diff --git a/app/src/main/java/foundation/e/apps/MainActivity.kt b/app/src/main/java/foundation/e/apps/MainActivity.kt
index 5b94937da6fd831fd324523609f4c110a596b53b..a2715a1e8f85e1d3af8c817ceb0be60908207e13 100644
--- a/app/src/main/java/foundation/e/apps/MainActivity.kt
+++ b/app/src/main/java/foundation/e/apps/MainActivity.kt
@@ -40,8 +40,8 @@ import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import foundation.e.apps.data.fusedDownload.models.FusedDownload
import foundation.e.apps.data.login.AuthObject
-import foundation.e.apps.data.login.PlayStoreAuthenticator
import foundation.e.apps.data.login.LoginViewModel
+import foundation.e.apps.data.login.PlayStoreAuthenticator
import foundation.e.apps.data.login.exceptions.GPlayValidationException
import foundation.e.apps.data.preference.PreferenceManagerModule
import foundation.e.apps.databinding.ActivityMainBinding
diff --git a/app/src/main/java/foundation/e/apps/install/workmanager/InstallAppWorker.kt b/app/src/main/java/foundation/e/apps/install/workmanager/InstallAppWorker.kt
index e26c1df66d9f63153b1249ed7529599a2be09818..286c2727d138e28f925f5cb529be7906e7f8666a 100644
--- a/app/src/main/java/foundation/e/apps/install/workmanager/InstallAppWorker.kt
+++ b/app/src/main/java/foundation/e/apps/install/workmanager/InstallAppWorker.kt
@@ -72,24 +72,26 @@ class InstallAppWorker @AssistedInject constructor(
private fun createForegroundInfo(progress: String): ForegroundInfo {
val title = applicationContext.getString(R.string.app_name)
val cancel = applicationContext.getString(R.string.cancel)
+ val channelId = context.getString(R.string.basic_notification_channel_id)
+
// This PendingIntent can be used to cancel the worker
val intent = WorkManager.getInstance(applicationContext)
- .createCancelPendingIntent(getId())
+ .createCancelPendingIntent(id)
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as
- NotificationManager
+ NotificationManager
// Create a Notification channel if necessary
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val mChannel = NotificationChannel(
- "applounge_notification",
+ channelId,
title,
NotificationManager.IMPORTANCE_LOW
)
notificationManager.createNotificationChannel(mChannel)
}
- val notification = NotificationCompat.Builder(applicationContext, "applounge_notification")
+ val notification = NotificationCompat.Builder(applicationContext, channelId)
.setContentTitle(title)
.setTicker(title)
.setContentText(progress)
diff --git a/app/src/main/java/foundation/e/apps/utils/CustomUncaughtExceptionHandler.kt b/app/src/main/java/foundation/e/apps/utils/CustomUncaughtExceptionHandler.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b280350f8ba73b00df98dd38650ff17a9175ef46
--- /dev/null
+++ b/app/src/main/java/foundation/e/apps/utils/CustomUncaughtExceptionHandler.kt
@@ -0,0 +1,97 @@
+/*
+ * Apps Quickly and easily install Android apps onto your device!
+ * Copyright (C) 2023 MURENA SAS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package foundation.e.apps.utils
+
+import android.Manifest
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.content.Context
+import android.content.pm.PackageManager
+import android.database.sqlite.SQLiteFullException
+import android.os.Build
+import androidx.annotation.StringRes
+import androidx.core.app.ActivityCompat
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import dagger.hilt.android.qualifiers.ApplicationContext
+import foundation.e.apps.R
+import timber.log.Timber
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class CustomUncaughtExceptionHandler @Inject constructor(
+ @ApplicationContext private val context: Context
+) : Thread.UncaughtExceptionHandler {
+
+ companion object {
+ private const val NOTIFICATION_ID = 404
+ }
+
+ override fun uncaughtException(thread: Thread, throwable: Throwable) {
+ Timber.e(throwable, "unhandled exception is caught at thread: ${thread.name}")
+
+ if (throwable is SQLiteFullException || throwable.cause is SQLiteFullException) {
+ showNotification(R.string.notification_content_full_db)
+ }
+ }
+
+ private fun showNotification(@StringRes contentId: Int) {
+ if (ActivityCompat.checkSelfPermission(
+ context, Manifest.permission.POST_NOTIFICATIONS
+ ) != PackageManager.PERMISSION_GRANTED
+ ) {
+ return
+ }
+
+ createNotificationChannel()
+
+ val notification = getNotification(contentId)
+ NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, notification)
+ }
+
+ private fun getNotification(@StringRes contentId: Int): Notification {
+ val content = context.getString(contentId)
+ val channelId = context.getString(R.string.warning_notification_channel_id)
+ val title = context.getString(R.string.app_name)
+
+ return NotificationCompat.Builder(context, channelId)
+ .setSmallIcon(R.drawable.app_lounge_notification_icon)
+ .setContentTitle(title)
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+ .setAutoCancel(true)
+ .setContentText(content).build()
+ }
+
+ private fun createNotificationChannel() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val id = context.getString(R.string.warning_notification_channel_id)
+ val title = context.getString(R.string.warning_notification_channel_title)
+
+ val channel = NotificationChannel(
+ id, title, NotificationManager.IMPORTANCE_DEFAULT
+ )
+
+ val notificationManager: NotificationManager =
+ context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+ notificationManager.createNotificationChannel(channel)
+ }
+ }
+}
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index aafa2cb17d8e926650d38f08b02d34bf1909485d..4f17154f8f3a179de425a9316cede279cd053789 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -169,4 +169,6 @@
Aktualisierungen werden überprüft …
Das anonyme Konto, das von Ihnen genutzt wird, ist nicht verfügbar. Bitte erneuern (refresh) Sie die Sitzung, um ein neues anonymes Konto zu erhalten.
SITZUNG ERNEUERN
+
+ Bitte etwas Platz auf dem Telefon freimachen, damit die App Lounge ordnungsgemäß funktionieren kann.
\ No newline at end of file
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index ac0af2df98976529b486815962fef5fca1274939..6ed760d132b78a7877560ceccc93de7799a9da41 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -155,4 +155,6 @@
PWA y aplicaciones de código abierto
O mostrar sólo
Libera %1$s en tu teléfono para recibir las últimas actualizaciones.
+
+ Por favor, libera algo de espacio en tu teléfono para que App Lounge funcione correctamente.
\ No newline at end of file
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 7ec04744cb76218a6088e045d9eb7a38b43afb12..fcb3a6babbd97a9243e4f5c52587c11f9c32d2c5 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -166,4 +166,6 @@
\n\t• limiter le micro-ciblage
\n\t• limiter les impacts au cas où ce compte serait restreint par Google
Libérez %1$s sur votre téléphone afin de bénéficier des dernières mises à jour.
+
+ Merci de libérer de l\'espace sur votre téléphone pour qu\'App Lounge puisse fonctionner correctement.
\ No newline at end of file
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 537c56f538459b9d299cc21a6cb519913afaf0fe..21908d07f4ad9c8a601f311f4c1190644d774b87 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -166,4 +166,6 @@
\n\t• ridurre il micro-targeting
\n\t• limitare l\'impatto nel caso in cui l\'account venga bloccato da Google
Per scaricare l\'aggiornamento, devi liberare %1$s di spazio sullo smartphone.
+
+ Ti invitiamo a liberare un pò di spazio sul telefono in modo che App Lounge possa funzionare correttamente.
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c404c57a8a2786baf15288be3751a73491c97e4b..3b2fd32fa11dc16e4192ba675cb597343560f15d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -20,6 +20,11 @@
App Lounge
+ applounge_notification
+
+ applounge_warning_notification
+ Warning
+
Home
Categories
@@ -234,4 +239,6 @@
Clicking on \"%1$s\" will open a tab in your browser with the app\'s package name prefilled.<br /><br />Click on \"Perform analysis\" to start the analysis by Exodus.<br /><br />When the button \"See the report\" is displayed (it can take a while depending on the app) you can close the tab and go back to the app description in %2$s where you should see the Privacy Score. Sometimes Exodus can fail to analyze the app.<br /><br />NB: it can take up to 10 min for the score to be displayed in the app description.
Free up %1$s on your phone to get the latest updates.
+
+ Please free up some space on your phone so App Lounge can work properly.