From e74e944d59203b8c0865514c7ad52d027cc87f12 Mon Sep 17 00:00:00 2001 From: althafvly Date: Thu, 22 Jan 2026 22:01:50 +0530 Subject: [PATCH 1/3] Fix minify app crash --- opentasks/proguard.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/opentasks/proguard.cfg b/opentasks/proguard.cfg index a30497d1..88d7f123 100644 --- a/opentasks/proguard.cfg +++ b/opentasks/proguard.cfg @@ -15,6 +15,10 @@ -keep public class * extends android.preference.Preference -keep public class com.android.vending.licensing.ILicensingService +# Keep Carrot templating engine +-keep class au.com.codeka.carrot.** { *; } +-keepclassmembers class au.com.codeka.carrot.** { *; } + -keepclasseswithmembers class * { native ; } -- GitLab From b16eaca3f6b929dc560f4ee2603f3c81c4d288b6 Mon Sep 17 00:00:00 2001 From: althafvly Date: Fri, 23 Jan 2026 11:45:02 +0530 Subject: [PATCH 2/3] Fix PendingIntent mutability for Android 12+ --- .../tasks/TaskProviderBroadcastReceiver.java | 2 +- .../tasks/StaleListBroadcastReceiver.java | 23 ++++++++-------- .../tasks/actions/CancelDelayedAction.java | 2 +- .../org/dmfs/tasks/actions/DelayedAction.java | 2 +- .../org/dmfs/tasks/actions/NotifyAction.java | 27 +++++++++---------- .../homescreen/TaskListWidgetProvider.java | 6 ++--- 6 files changed, 30 insertions(+), 32 deletions(-) diff --git a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProviderBroadcastReceiver.java b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProviderBroadcastReceiver.java index 7a4c6dec..9f62ae99 100644 --- a/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProviderBroadcastReceiver.java +++ b/opentasks-provider/src/main/java/org/dmfs/provider/tasks/TaskProviderBroadcastReceiver.java @@ -52,7 +52,7 @@ public class TaskProviderBroadcastReceiver extends BroadcastReceiver { alarmIntent.setAction(ACTION_NOTIFICATION_ALARM); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, REQUEST_CODE_ALARM, alarmIntent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); // cancel any previous alarm am.cancel(pendingIntent); diff --git a/opentasks/src/main/java/org/dmfs/tasks/StaleListBroadcastReceiver.java b/opentasks/src/main/java/org/dmfs/tasks/StaleListBroadcastReceiver.java index 454cda0d..166b1d05 100644 --- a/opentasks/src/main/java/org/dmfs/tasks/StaleListBroadcastReceiver.java +++ b/opentasks/src/main/java/org/dmfs/tasks/StaleListBroadcastReceiver.java @@ -89,18 +89,17 @@ public final class StaleListBroadcastReceiver extends BroadcastReceiver { Resources.Theme theme = context.getTheme(); theme.applyStyle(context.getApplicationInfo().theme, true); - nm.notify("stale_list_broadacast", 0, - new Notification.Builder(context, "provider_messages") - .setContentText(notificationDescription) - .setContentIntent(PendingIntent.getActivity(context, 0, accountRequestIntent, - PendingIntent.FLAG_UPDATE_CURRENT)) - .addAction(new Notification.Action.Builder(null, "Grant", - PendingIntent.getActivity(context, 0, accountRequestIntent, - PendingIntent.FLAG_UPDATE_CURRENT)) - .build()) - .setColor(new AttributeColor(theme, androidx.appcompat.R.attr.colorPrimary).argb()) - .setColorized(true).setSmallIcon(org.dmfs.tasks.provider.R.drawable.ic_24_opentasks) - .build()); + nm.notify("stale_list_broadacast", 0, new Notification.Builder(context, "provider_messages") + .setContentText(notificationDescription) + .setContentIntent(PendingIntent.getActivity(context, 0, accountRequestIntent, + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)) + .addAction(new Notification.Action.Builder(null, "Grant", + PendingIntent.getActivity(context, 0, accountRequestIntent, + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)) + .build()) + .setColor(new AttributeColor(theme, androidx.appcompat.R.attr.colorPrimary).argb()) + .setColorized(true).setSmallIcon(org.dmfs.tasks.provider.R.drawable.ic_24_opentasks) + .build()); } } } diff --git a/opentasks/src/main/java/org/dmfs/tasks/actions/CancelDelayedAction.java b/opentasks/src/main/java/org/dmfs/tasks/actions/CancelDelayedAction.java index dc5b7994..f79bc29c 100644 --- a/opentasks/src/main/java/org/dmfs/tasks/actions/CancelDelayedAction.java +++ b/opentasks/src/main/java/org/dmfs/tasks/actions/CancelDelayedAction.java @@ -49,6 +49,6 @@ public final class CancelDelayedAction implements TaskAction { ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)) .cancel(PendingIntent.getBroadcast(context, (int) ContentUris.parseId(taskUri), new Intent(context, ActionReceiver.class).setAction(mAction).setData(taskUri), - PendingIntent.FLAG_UPDATE_CURRENT)); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)); } } diff --git a/opentasks/src/main/java/org/dmfs/tasks/actions/DelayedAction.java b/opentasks/src/main/java/org/dmfs/tasks/actions/DelayedAction.java index 99cb64d5..37b5ae5c 100644 --- a/opentasks/src/main/java/org/dmfs/tasks/actions/DelayedAction.java +++ b/opentasks/src/main/java/org/dmfs/tasks/actions/DelayedAction.java @@ -52,6 +52,6 @@ public final class DelayedAction implements TaskAction { AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + mDelayMillis, PendingIntent.getBroadcast(context, (int) ContentUris.parseId(taskUri), new Intent(context, ActionReceiver.class).setAction(mAction).setData(taskUri), - PendingIntent.FLAG_UPDATE_CURRENT)); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)); } } diff --git a/opentasks/src/main/java/org/dmfs/tasks/actions/NotifyAction.java b/opentasks/src/main/java/org/dmfs/tasks/actions/NotifyAction.java index cf0a2ef8..bee0e140 100644 --- a/opentasks/src/main/java/org/dmfs/tasks/actions/NotifyAction.java +++ b/opentasks/src/main/java/org/dmfs/tasks/actions/NotifyAction.java @@ -126,13 +126,13 @@ public final class NotifyAction implements TaskAction { new Intent(context, ActionReceiver.class).setAction( pin ? ActionService.ACTION_OPEN_TASK : ActionService.ACTION_OPEN_TASK_CANCEL_NOTIFICATION) .setData(taskUri), - PendingIntent.FLAG_UPDATE_CURRENT)); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)); // make sure we un-persist the notification when its cancelled builder.setDeleteIntent(PendingIntent.getBroadcast( context, notificationId, new Intent(context, ActionReceiver.class) .setAction(ActionService.ACTION_REMOVE_NOTIFICATION).setData(taskUri), - PendingIntent.FLAG_UPDATE_CURRENT)); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)); if (!new TaskIsClosed(data).value()) { builder.addAction(new NotificationCompat.Action(R.drawable.ic_action_complete, @@ -140,26 +140,25 @@ public final class NotifyAction implements TaskAction { PendingIntent.getBroadcast( context, 1, new Intent(context, ActionReceiver.class) .setAction(ActionService.ACTION_COMPLETE).setData(taskUri), - PendingIntent.FLAG_UPDATE_CURRENT))); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))); if (new TaskDateTime(TaskContract.Tasks.DUE, data).isPresent()) { builder.addAction(new NotificationCompat.Action(R.drawable.ic_detail_delay_1d_inverse, context.getString(R.string.notification_action_delay_1d), - PendingIntent.getBroadcast( - context, 1, new Intent(context, ActionReceiver.class) - .setAction(ActionService.ACTION_DEFER_1D).setData(taskUri), - PendingIntent.FLAG_UPDATE_CURRENT))); + PendingIntent.getBroadcast(context, 1, + new Intent(context, ActionReceiver.class).setAction(ActionService.ACTION_DEFER_1D) + .setData(taskUri), + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))); } } if (pin) { - builder.addAction( - new NotificationCompat.Action(R.drawable.ic_pin_off_white_24dp, - context.getString(R.string.notification_action_unpin), - PendingIntent.getBroadcast( - context, 1, new Intent(context, ActionReceiver.class) - .setAction(ActionService.ACTION_UNPIN).setData(taskUri), - PendingIntent.FLAG_UPDATE_CURRENT))); + builder.addAction(new NotificationCompat.Action(R.drawable.ic_pin_off_white_24dp, + context.getString(R.string.notification_action_unpin), + PendingIntent.getBroadcast( + context, 1, new Intent(context, ActionReceiver.class).setAction(ActionService.ACTION_UNPIN) + .setData(taskUri), + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))); } builder.setOnlyAlertOnce(!mRepost); builder.setOngoing(pin); diff --git a/opentasks/src/main/java/org/dmfs/tasks/homescreen/TaskListWidgetProvider.java b/opentasks/src/main/java/org/dmfs/tasks/homescreen/TaskListWidgetProvider.java index be549287..85df13b3 100644 --- a/opentasks/src/main/java/org/dmfs/tasks/homescreen/TaskListWidgetProvider.java +++ b/opentasks/src/main/java/org/dmfs/tasks/homescreen/TaskListWidgetProvider.java @@ -140,7 +140,7 @@ public class TaskListWidgetProvider extends AppWidgetProvider { Intent tasksAppIntent = new Intent(context, TaskListActivity.class); tasksAppIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent taskAppPI = PendingIntent.getActivity(context, 0, tasksAppIntent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); widget.setOnClickPendingIntent(android.R.id.button1, taskAppPI); /** Add a pending Intent to start new Task Activity on the new Task Button */ @@ -148,7 +148,7 @@ public class TaskListWidgetProvider extends AppWidgetProvider { editTaskIntent.setAction(ACTION_CREATE_TASK); editTaskIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); PendingIntent newTaskPI = PendingIntent.getBroadcast(context, appWidgetIds[i], editTaskIntent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); widget.setOnClickPendingIntent(android.R.id.button2, newTaskPI); /** @@ -160,7 +160,7 @@ public class TaskListWidgetProvider extends AppWidgetProvider { Intent detailIntent = new Intent(Intent.ACTION_VIEW); detailIntent.putExtra(TaskListActivity.EXTRA_FORCE_LIST_SELECTION, true); PendingIntent clickPI = PendingIntent.getActivity(context, 0, detailIntent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); widget.setPendingIntentTemplate(R.id.task_list_widget_lv, clickPI); -- GitLab From e06e855a36b348a8eec2af29c10aac7cd517b88a Mon Sep 17 00:00:00 2001 From: Nishith Khanna Date: Fri, 23 Jan 2026 11:20:53 +0530 Subject: [PATCH 3/3] ci: add jobs so that tasks can be updated via AppLounge --- .gitlab-ci.yml | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9b8999a9..44113f67 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,7 +1,31 @@ image: "registry.gitlab.e.foundation/e/os/docker-android-apps-cicd:latest" +variables: + APK_PATH: "opentasks/build/outputs/apk/release" + UNSIGNED_APK: "opentasks-release.apk" + COMMUNITY_APK: "opentasks-release-community.apk" + OFFICIAL_APK: "opentasks-release-official.apk" + TEST_APK: "opentasks-release-test.apk" + +.rules_protected_ref: + rules: &rules_protected_ref + - if: '$CI_PIPELINE_SOURCE != "schedule" && $CI_COMMIT_REF_PROTECTED == "true"' + - when: never + +.rules_protected_tag: + rules: &rules_protected_tag + - if: '$CI_COMMIT_TAG && $CI_COMMIT_REF_PROTECTED == "true"' + - when: never + +.rules_protected_tag_manual: + rules: &rules_protected_tag_manual + - if: '$CI_COMMIT_TAG && $CI_COMMIT_REF_PROTECTED == "true"' + when: manual + - when: never + stages: - build + - gitlab_release before_script: - export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 @@ -20,3 +44,72 @@ build: artifacts: paths: - opentasks/build/outputs/apk/ + +init_submodules: + stage: gitlab_release + rules: *rules_protected_ref + script: + - | + git clone https://gitlab.e.foundation/e/os/system-apps-update-info.git systemAppsUpdateInfo + artifacts: + paths: + - systemAppsUpdateInfo/scripts/ + +generate-apks: + stage: gitlab_release + rules: *rules_protected_ref + needs: + - job: init_submodules + - job: build + script: + - | + ./systemAppsUpdateInfo/scripts/generate-apks.sh \ + "$APK_PATH" "$UNSIGNED_APK" "$COMMUNITY_APK" "$OFFICIAL_APK" "$TEST_APK" + artifacts: + paths: + - $APK_PATH/$UNSIGNED_APK + - $APK_PATH/$COMMUNITY_APK + - $APK_PATH/$OFFICIAL_APK + - $APK_PATH/$TEST_APK + +create-json-files: + stage: gitlab_release + rules: *rules_protected_tag + needs: + - job: init_submodules + - job: generate-apks + script: + - | + ./systemAppsUpdateInfo/scripts/create-json-files.sh \ + "$APK_PATH" "$UNSIGNED_APK" "$COMMUNITY_APK" "$OFFICIAL_APK" "$TEST_APK" + artifacts: + paths: + - community.json + - official.json + - test.json + +create-test-release: + stage: gitlab_release + rules: *rules_protected_tag_manual + needs: + - job: init_submodules + - job: create-json-files + artifacts: false + script: + - | + ./systemAppsUpdateInfo/scripts/create-test-release.sh \ + "$APK_PATH" "$TEST_APK" + allow_failure: true + +create-release: + stage: gitlab_release + rules: *rules_protected_tag_manual + needs: + - job: init_submodules + - job: create-json-files + artifacts: false + script: + - | + ./systemAppsUpdateInfo/scripts/create-release.sh \ + "$APK_PATH" "$UNSIGNED_APK" "$COMMUNITY_APK" "$OFFICIAL_APK" + allow_failure: true -- GitLab