diff --git a/app/build.gradle b/app/build.gradle
index 42f0a2b..54e7b2b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -23,8 +23,8 @@ android {
minSdkVersion 21
targetSdkVersion 35
compileSdk 35
- versionCode 46
- versionName "0.2.1"
+ versionCode 47
+ versionName "0.2.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt
index 8936675..e5877f5 100644
--- a/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/preferences/Preferences.kt
@@ -10,6 +10,7 @@ import de.jrpie.android.launcher.apps.AbstractAppInfo.Companion.INVALID_USER
import de.jrpie.android.launcher.apps.AppInfo
import de.jrpie.android.launcher.apps.DetailedAppInfo
import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion1
+import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion100
import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion2
import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion3
import de.jrpie.android.launcher.preferences.legacy.migratePreferencesFromVersion4
@@ -21,12 +22,13 @@ import de.jrpie.android.launcher.widgets.DebugInfoWidget
import de.jrpie.android.launcher.widgets.WidgetPanel
import de.jrpie.android.launcher.widgets.WidgetPosition
import de.jrpie.android.launcher.widgets.deleteAllWidgets
+import de.jrpie.android.launcher.widgets.generateInternalId
/* Current version of the structure of preferences.
* Increase when breaking changes are introduced and write an appropriate case in
* `migratePreferencesToNewVersion`
*/
-const val PREFERENCE_VERSION = 100
+const val PREFERENCE_VERSION = 101
const val UNKNOWN_PREFERENCE_VERSION = -1
private const val TAG = "Launcher - Preferences"
@@ -65,6 +67,10 @@ fun migratePreferencesToNewVersion(context: Context) {
migratePreferencesFromVersion4(context)
Log.i(TAG, "migration of preferences complete (4 -> ${PREFERENCE_VERSION}).")
}
+ 100 -> {
+ migratePreferencesFromVersion100(context)
+ Log.i(TAG, "migration of preferences complete (100 -> ${PREFERENCE_VERSION}).")
+ }
else -> {
Log.w(
@@ -91,7 +97,7 @@ fun resetPreferences(context: Context) {
LauncherPreferences.widgets().widgets(
setOf(
ClockWidget(
- (context.applicationContext as Application).appWidgetHost.allocateAppWidgetId(),
+ generateInternalId(),
WidgetPosition(1, 3, 10, 4),
WidgetPanel.HOME.id
)
@@ -103,7 +109,7 @@ fun resetPreferences(context: Context) {
LauncherPreferences.widgets().widgets().also {
it.add(
DebugInfoWidget(
- (context.applicationContext as Application).appWidgetHost.allocateAppWidgetId(),
+ generateInternalId(),
WidgetPosition(1, 1, 10, 4),
WidgetPanel.HOME.id
)
diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version100.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version100.kt
new file mode 100644
index 0000000..43e4bc7
--- /dev/null
+++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version100.kt
@@ -0,0 +1,39 @@
+package de.jrpie.android.launcher.preferences.legacy
+
+import android.content.Context
+import de.jrpie.android.launcher.Application
+import de.jrpie.android.launcher.preferences.LauncherPreferences
+import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION
+import de.jrpie.android.launcher.widgets.ClockWidget
+import de.jrpie.android.launcher.widgets.DebugInfoWidget
+import de.jrpie.android.launcher.widgets.generateInternalId
+import de.jrpie.android.launcher.widgets.updateWidget
+
+fun migratePreferencesFromVersion100(context: Context) {
+ assert(PREFERENCE_VERSION == 101)
+ assert(LauncherPreferences.internal().versionCode() == 100)
+
+ val widgets = LauncherPreferences.widgets().widgets() ?: setOf()
+ widgets.forEach { widget ->
+ when (widget) {
+ is ClockWidget -> {
+ val id = widget.id
+ val newId = generateInternalId()
+ (context.applicationContext as Application).appWidgetHost.deleteAppWidgetId(id)
+ widget.delete(context)
+ widget.id = newId
+ updateWidget(widget)
+ }
+ is DebugInfoWidget -> {
+ val id = widget.id
+ val newId = generateInternalId()
+ (context.applicationContext as Application).appWidgetHost.deleteAppWidgetId(id)
+ widget.delete(context)
+ widget.id = newId
+ updateWidget(widget)
+ }
+ else -> {}
+ }
+ }
+ LauncherPreferences.internal().versionCode(101)
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt
index a9ab3a1..b13978b 100644
--- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version4.kt
@@ -7,19 +7,20 @@ import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION
import de.jrpie.android.launcher.widgets.ClockWidget
import de.jrpie.android.launcher.widgets.WidgetPanel
import de.jrpie.android.launcher.widgets.WidgetPosition
+import de.jrpie.android.launcher.widgets.generateInternalId
fun migratePreferencesFromVersion4(context: Context) {
- assert(PREFERENCE_VERSION == 100)
assert(LauncherPreferences.internal().versionCode() < 100)
LauncherPreferences.widgets().widgets(
setOf(
ClockWidget(
- (context.applicationContext as Application).appWidgetHost.allocateAppWidgetId(),
+ generateInternalId(),
WidgetPosition(1, 3, 10, 4),
WidgetPanel.HOME.id
)
)
)
LauncherPreferences.internal().versionCode(100)
+ migratePreferencesFromVersion100(context)
}
\ No newline at end of file
diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt
index 03c55fc..f3cde9a 100644
--- a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt
@@ -122,7 +122,12 @@ class HomeActivity : UIObject, Activity() {
}
override fun onPause() {
- (application as Application).appWidgetHost.stopListening()
+ try {
+ (application as Application).appWidgetHost.stopListening()
+ } catch (e: Exception) {
+ // Throws a NullPointerException on Android 12 an earlier, see #172
+ e.printStackTrace()
+ }
super.onPause()
}
diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetPanelActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetPanelActivity.kt
index ef7bf25..3c884db 100644
--- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetPanelActivity.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/WidgetPanelActivity.kt
@@ -62,7 +62,12 @@ class WidgetPanelActivity : Activity(), UIObject {
}
override fun onPause() {
- (application as Application).appWidgetHost.stopListening()
+ try {
+ (application as Application).appWidgetHost.stopListening()
+ } catch (e: Exception) {
+ // Throws a NullPointerException on Android 12 an earlier, see #172
+ e.printStackTrace()
+ }
super.onPause()
}
diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt
index 58b47be..953fc28 100644
--- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/ManageWidgetsActivity.kt
@@ -93,7 +93,12 @@ class ManageWidgetsActivity : UIObject, Activity() {
}
override fun onPause() {
- (application as Application).appWidgetHost.stopListening()
+ try {
+ (application as Application).appWidgetHost.stopListening()
+ } catch (e: Exception) {
+ // Throws a NullPointerException on Android 12 an earlier, see #172
+ e.printStackTrace()
+ }
super.onPause()
}
@@ -130,10 +135,6 @@ class ManageWidgetsActivity : UIObject, Activity() {
val appWidgetHost = (application as Application).appWidgetHost
startActivityForResult(
Intent(this, SelectWidgetActivity::class.java).also {
- it.putExtra(
- AppWidgetManager.EXTRA_APPWIDGET_ID,
- appWidgetHost.allocateAppWidgetId()
- )
it.putExtra(
EXTRA_PANEL_ID,
panelId
diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/SelectWidgetActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/SelectWidgetActivity.kt
index 0efdb43..eeb98df 100644
--- a/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/SelectWidgetActivity.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/ui/widgets/manage/SelectWidgetActivity.kt
@@ -14,6 +14,7 @@ import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
+import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.databinding.ActivitySelectWidgetBinding
import de.jrpie.android.launcher.ui.UIObject
@@ -24,7 +25,7 @@ import de.jrpie.android.launcher.widgets.LauncherWidgetProvider
import de.jrpie.android.launcher.widgets.WidgetPanel
import de.jrpie.android.launcher.widgets.WidgetPosition
import de.jrpie.android.launcher.widgets.bindAppWidgetOrRequestPermission
-import de.jrpie.android.launcher.widgets.getAppWidgetHost
+import de.jrpie.android.launcher.widgets.generateInternalId
import de.jrpie.android.launcher.widgets.getAppWidgetProviders
import de.jrpie.android.launcher.widgets.updateWidget
@@ -38,12 +39,13 @@ private const val REQUEST_WIDGET_PERMISSION = 29
*/
class SelectWidgetActivity : AppCompatActivity(), UIObject {
lateinit var binding: ActivitySelectWidgetBinding
- var widgetId: Int = -1
var widgetPanelId: Int = WidgetPanel.HOME.id
private fun tryBindWidget(info: LauncherWidgetProvider) {
when (info) {
is LauncherAppWidgetProvider -> {
+ val widgetId =
+ (applicationContext as Application).appWidgetHost.allocateAppWidgetId()
if (bindAppWidgetOrRequestPermission(
this,
info.info,
@@ -62,7 +64,7 @@ class SelectWidgetActivity : AppCompatActivity(), UIObject {
}
}
is LauncherClockWidgetProvider -> {
- updateWidget(ClockWidget(widgetId, WidgetPosition(0, 4, 12, 3), widgetPanelId))
+ updateWidget(ClockWidget(generateInternalId(), WidgetPosition(0, 4, 12, 3), widgetPanelId))
finish()
}
}
@@ -81,11 +83,7 @@ class SelectWidgetActivity : AppCompatActivity(), UIObject {
setContentView(binding.root)
- widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1)
widgetPanelId = intent.getIntExtra(EXTRA_PANEL_ID, WidgetPanel.HOME.id)
- if (widgetId == -1) {
- widgetId = getAppWidgetHost().allocateAppWidgetId()
- }
val viewManager = LinearLayoutManager(this)
val viewAdapter = SelectWidgetRecyclerAdapter()
diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/ClockWidget.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/ClockWidget.kt
index d0d1c0e..f864ee8 100644
--- a/app/src/main/java/de/jrpie/android/launcher/widgets/ClockWidget.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/widgets/ClockWidget.kt
@@ -12,7 +12,7 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("widget:clock")
class ClockWidget(
- override val id: Int,
+ override var id: Int,
override var position: WidgetPosition,
override val panelId: Int,
override var allowInteraction: Boolean = true
diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/DebugInfoWidget.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/DebugInfoWidget.kt
index 01ecddc..75ae6d0 100644
--- a/app/src/main/java/de/jrpie/android/launcher/widgets/DebugInfoWidget.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/widgets/DebugInfoWidget.kt
@@ -12,7 +12,7 @@ import kotlinx.serialization.Serializable
@Serializable
@SerialName("widget:debuginfo")
class DebugInfoWidget(
- override val id: Int,
+ override var id: Int,
override var position: WidgetPosition,
override val panelId: Int,
override var allowInteraction: Boolean = true
diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt
index 28539a2..fd96f14 100644
--- a/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/widgets/Widget.kt
@@ -27,7 +27,9 @@ sealed class Widget {
abstract fun configure(activity: Activity, requestCode: Int)
fun delete(context: Context) {
- context.getAppWidgetHost().deleteAppWidgetId(id)
+ if (id >= 0) {
+ context.getAppWidgetHost().deleteAppWidgetId(id)
+ }
LauncherPreferences.widgets().widgets(
LauncherPreferences.widgets().widgets()?.also {
diff --git a/app/src/main/java/de/jrpie/android/launcher/widgets/Widgets.kt b/app/src/main/java/de/jrpie/android/launcher/widgets/Widgets.kt
index cded50c..593f3b3 100644
--- a/app/src/main/java/de/jrpie/android/launcher/widgets/Widgets.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/widgets/Widgets.kt
@@ -13,6 +13,7 @@ import android.os.UserManager
import android.util.Log
import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.preferences.LauncherPreferences
+import kotlin.math.min
fun deleteAllWidgets(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@@ -29,12 +30,9 @@ fun deleteAllWidgets(context: Context) {
*
* @return true iff the app widget was bound successfully.
*/
-fun bindAppWidgetOrRequestPermission(activity: Activity, providerInfo: AppWidgetProviderInfo, id: Int, requestCode: Int? = null): Boolean {
- val appWidgetId = if(id == -1) {
- activity.getAppWidgetHost().allocateAppWidgetId()
- } else { id }
+fun bindAppWidgetOrRequestPermission(activity: Activity, providerInfo: AppWidgetProviderInfo, appWidgetId: Int, requestCode: Int? = null): Boolean {
- Log.i("Launcher", "Binding new widget ${appWidgetId}")
+ Log.i("Launcher", "Binding new widget $appWidgetId")
if (!activity.getAppWidgetManager().bindAppWidgetIdIfAllowed(
appWidgetId,
providerInfo.provider
@@ -79,6 +77,13 @@ fun updateWidget(widget: Widget) {
)
}
+
+// TODO: this needs to be improved
+fun generateInternalId(): Int {
+ val minId = min(-5,(LauncherPreferences.widgets().widgets() ?: setOf()).minOfOrNull { it.id } ?: 0)
+ return minId -1
+}
+
fun updateWidgetPanel(widgetPanel: WidgetPanel) {
LauncherPreferences.widgets().customPanels(
(LauncherPreferences.widgets().customPanels() ?: setOf())
@@ -92,4 +97,4 @@ fun Context.getAppWidgetHost(): AppWidgetHost {
}
fun Context.getAppWidgetManager(): AppWidgetManager {
return (this.applicationContext as Application).appWidgetManager
-}
+}
\ 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 10362a0..bca9108 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -302,9 +302,9 @@
Ok
Pannelli widget
- - Contiene %d widget.
- - Contiene %d widget.
- - Contiene %d widget.
+ - Contiene %1$d widget.
+ - Contiene %1$d widget.
+ - Contiene %1$d widget.
Crea nuovo pannello widget
Apri pannello widget
diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml
index 0a45d57..d5c9ecf 100644
--- a/app/src/main/res/values-lt/strings.xml
+++ b/app/src/main/res/values-lt/strings.xml
@@ -1,16 +1,136 @@
+
+ Nepavyksta paleisti programėlės
Norite pakeisti nustatymus?
+
+ Atidarykite nustatymus norėdami pasirinkti šio gesto veiksmą
+
+
Nustatymai
+
Veiksmai
Paleidimo programėlė
Apie
+
+
Atgal
Grįžimo mygtukas / grįžimo gestas
+ Aukštyn
Perbraukimas aukštyn
Bakstelėkite + aukštyn
- Nepavyksta paleisti programėlės
- Atidarykite nustatymus norėdami pasirinkti šio gesto veiksmą
- Aukštyn
Bakstelėjimas ir perbraukimas aukštyn
+ Dvigubai aukštyn
+ Perbraukite aukštyn dviem pirštais
+ Žemyn
+ Perbraukite žemyn
+ Bakstelėkite + žemyn
+ Bakstelėkite ir perbraukite žemyn
+ Dvigubai žemyn
+ Perbraukite dviem pirštais
+ Kairėje
+ Perbraukite į kairę
+ Bakstelėkite + kairę
+ Bakstelėkite ir perbraukite į kairę
+ Dvigubai kairėje
+ Du pirštais perbraukite kairėn
+ Dešinė
+ Perbraukite į dešinę
+ Bakstelėkite + dešinė
+ Bakstelėkite ir perbraukite į dešinę
+ Dviguba dešinė
+ Perbraukite į dešinę dviem pirštais
+ Dešinė (viršuje)
+ Perbraukite tiesiai ekrano viršuje
+ Dešinė (apačia)
+ Perbraukite tiesiai ekrano apačioje
+ Kairė (apačia)
+ Perbraukite į kairę ekrano apačioje
+ Kairė (viršuje)
+ Perbraukite kairėn ekrano viršuje
+ Aukštyn (kairysis kraštas)
+ Perbraukite aukštyn kairiajame ekrano krašte
+ Aukštyn (dešinysis kraštas)
+ Perbraukite aukštyn dešiniajame ekrano krašte
+ Žemyn (kairysis kraštas)
+ Perbraukite žemyn kairiajame ekrano krašte
+ Žemyn (dešinysis kraštas)
+ Žemyn (dešinysis kraštas)
+
+ Garsumo didinimo klavišas
+ Paspauskite mygtuką „Volume Up“
+ Volume žemyn klavišas
+ Paspauskite mygtuką „Volume Down“
+ Dukart spustelėkite
+ Dukart spustelėkite tuščią sritį
+ Ilgas spustelėjimas
+ Ilgai spustelėkite tuščią sritį
+ Data
+ Spustelėkite datą
+ Laikas
+ Spustelėkite laiką
+
+ Tvarkykite valdiklius
+ Tvarkykite valdiklio skydelius
+
+
+ Pasirinkite programą
+
+ Įdiekite programas
+ Parduotuvėje nerasta
+
+
+ Išvaizda
+
+
+ Spalvos tema
+ Numatytasis
+ Tamsu
+ Šviesa
+ Dinaminis
+
+ Teksto šešėlis
+ Fonas (programų sąrašas ir nustatymas)
+ Skaidrus
+ Dim
+ Blur
+ Solidus
+
+
+ Šriftas
+
+
+ Sistemos numatytasis
+ Be serifo
+ Serifas
+ Monoerdvė
+ Serifo monospace
+ Vienspalvių programų piktogramos
+
+
+ Spalva
+ Rodyti laiką
+ Rodyti datą
+ Naudoti lokalizuotą datos formatą
+ Rodyti sekundes
+ Apversti datą ir laiką
+
+ Pasirinkite ekrano foną
+ Ekranas
diff --git a/fastlane/metadata/android/en-US/changelogs/47.txt b/fastlane/metadata/android/en-US/changelogs/47.txt
new file mode 100644
index 0000000..33899dd
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/47.txt
@@ -0,0 +1,10 @@
+ * Fixed a bug related to widget causing crashes on Android 12 and earlier making the app unusable
+ * Fixed some additional bugs related to widgets
+
+ * Improved Lithuanian translation (thank you, wassupluke!)
+ * Improved Arabic translation (thank you, anonymous contributor!)
+ * Improved Chinese translation (thank you, class0068!)
+ * Improved Dutch translation (thank you, renar!)
+ * Improved German translation (thank you, renar!)
+ * Improved Italian translation (thank you, renar!)
+ * Improved Portuguese translation (thank you, anonymous contributor!)