From 578bf9d8c49652c923b1250a4dce5e84e86d26fe Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Mon, 3 Oct 2022 22:16:12 -0700 Subject: [PATCH 01/31] bump sdk and version --- app/build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index c6b36e6d..a38c173e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,13 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 28 + compileSdkVersion 33 defaultConfig { minSdkVersion 14 - targetSdkVersion 28 - versionCode 32 - versionName '1.3.1' + targetSdkVersion 33 + versionCode 33 + versionName '1.3.2' } // conditionally load keystore.properties and configure release signing config From 6da84ef8820a932310774d8dae75640e472ad364 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Tue, 4 Oct 2022 00:52:16 -0700 Subject: [PATCH 02/31] At least it launches --- app/src/main/AndroidManifest.xml | 9 ++++++--- .../ktachibana/cloudemoji/utils/NotificationUtils.java | 9 ++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1d6163b5..2383a8ce 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -35,7 +35,8 @@ + android:launchMode="singleTop" + android:exported="true"> @@ -46,7 +47,8 @@ + android:targetActivity=".activities.MainActivity" + android:exported="true"> @@ -107,7 +109,8 @@ + android:permission="android.permission.BIND_INPUT_METHOD" + android:exported="true"> diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index 53287bcb..b922ea93 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -71,7 +71,14 @@ private static void showQuickTriggerNotification( String title = context.getString(R.string.app_name); String text = context.getString(R.string.touch_to_launch); Intent intent = new Intent(context, MainActivity.class); - PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0); + PendingIntent pIntent; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { + pIntent = PendingIntent.getActivity + (context, 0, intent, PendingIntent.FLAG_MUTABLE); + } else { + pIntent = PendingIntent.getActivity + (context, 0, intent, PendingIntent.FLAG_ONE_SHOT); + } Notification notification = new NotificationCompat.Builder(context, Constants.QUICK_TRIGGER_NOTIFICATION_CHANNEL_ID) .setContentTitle(title) // Title .setContentText(text) // Text From 14aaa6c79444bbaf52365eb51d946bcaa765d6a9 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Sat, 15 Oct 2022 23:28:36 -0700 Subject: [PATCH 03/31] set channel id? --- .../java/org/ktachibana/cloudemoji/utils/NotificationUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index b922ea93..5342a57b 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -86,6 +86,7 @@ private static void showQuickTriggerNotification( .setContentIntent(pIntent) // Intent to launch this app .setWhen(0) // No time to display .setPriority(priority) // Given priority + .setChannelId(Constants.QUICK_TRIGGER_NOTIFICATION_CHANNEL_ID) .build(); notification.flags = Notification.FLAG_NO_CLEAR; notificationManager.notify(Constants.QUICK_TRIGGER_NOTIFICATION_ID, notification); From e43f0b2aea0f1eec2e0e9ea502da60024da01f1e Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Sun, 16 Oct 2022 00:13:24 -0700 Subject: [PATCH 04/31] add notification permissions and small fixes --- app/src/main/AndroidManifest.xml | 3 +-- .../org/ktachibana/cloudemoji/utils/NotificationUtils.java | 2 +- .../java/org/ktachibana/cloudemoji/utils/SystemUtils.java | 4 ++++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2383a8ce..fa472b4a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,8 +13,7 @@ - - + = Build.VERSION_CODES.O) { + if (SystemUtils.aboveOreo()) { NotificationChannel channel = new NotificationChannel( Constants.QUICK_TRIGGER_NOTIFICATION_CHANNEL_ID, context.getString(R.string.quick_trigger_notification_channel_name), diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java index fa381d62..efe1e376 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java @@ -47,4 +47,8 @@ public static boolean belowMarshmallow() { public static boolean aboveMarshmallow() { return !belowMarshmallow(); } + + public static boolean aboveOreo() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; + } } From 8a7a6ff7c8094a2121dfab5764bc5413009c8e00 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Sun, 16 Oct 2022 16:01:18 -0700 Subject: [PATCH 05/31] try to upgrade permissionsdispatcher --- app/build.gradle | 4 ++-- app/src/main/AndroidManifest.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a38c173e..02ddc510 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -73,8 +73,8 @@ dependencies { annotationProcessor 'com.hannesdorfmann.fragmentargs:processor:4.0.0-RC1' implementation "org.parceler:parceler-api:1.1.12" annotationProcessor "org.parceler:parceler:1.1.12" - implementation "org.permissionsdispatcher:permissionsdispatcher:4.7.0" - annotationProcessor "org.permissionsdispatcher:permissionsdispatcher-processor:4.7.0" + implementation "com.github.permissions-dispatcher:permissionsdispatcher:4.9.2" + annotationProcessor "com.github.permissions-dispatcher:permissionsdispatcher-processor:4.9.2" // Debug implementation 'com.facebook.stetho:stetho:1.3.1' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fa472b4a..f76bf30d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,12 +7,12 @@ tools:overrideLibrary="android.support.v14.preference" /> - + Date: Mon, 17 Oct 2022 17:26:57 -0700 Subject: [PATCH 06/31] upgrade lib --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 02ddc510..776d121b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,7 +56,7 @@ dependencies { implementation 'org.greenrobot:eventbus:3.0.0' implementation 'com.jakewharton:butterknife:7.0.1' annotationProcessor 'com.jakewharton:butterknife:7.0.1' - implementation 'com.android.support:design:28.1.1' + implementation 'com.google.android.material:material:1.0.0' implementation 'com.mobeta.android.dslv:library:0.9.0' // Database implementation 'com.github.satyan:sugar:b16e65326a' From bbc49e0d9716d41f143e7b01f69562d4c951d3ec Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Mon, 17 Oct 2022 17:55:37 -0700 Subject: [PATCH 07/31] use easy permission for quick trigger notification in main activity and various cleanups --- app/build.gradle | 1 + .../cloudemoji/activities/MainActivity.java | 39 +++++++++++++++---- .../cloudemoji/utils/CopyUtils.java | 16 ++------ .../cloudemoji/utils/SystemUtils.java | 16 ++------ app/src/main/res/values-zh/strings.xml | 3 +- app/src/main/res/values/strings.xml | 3 +- 6 files changed, 45 insertions(+), 33 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 776d121b..5d041480 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -75,6 +75,7 @@ dependencies { annotationProcessor "org.parceler:parceler:1.1.12" implementation "com.github.permissions-dispatcher:permissionsdispatcher:4.9.2" annotationProcessor "com.github.permissions-dispatcher:permissionsdispatcher-processor:4.9.2" + implementation 'pub.devrel:easypermissions:3.0.0' // Debug implementation 'com.facebook.stetho:stetho:1.3.1' } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java index 33f09c49..d3fec296 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java @@ -1,5 +1,6 @@ package org.ktachibana.cloudemoji.activities; +import android.Manifest; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; @@ -9,11 +10,14 @@ import android.database.sqlite.SQLiteException; import android.net.Uri; import android.os.Bundle; + +import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import android.util.Log; import android.view.Menu; import android.view.MenuItem; +import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.MaterialDialog; import org.apache.commons.io.IOUtils; @@ -35,6 +39,7 @@ import org.ktachibana.cloudemoji.parsing.SourceParsingException; import org.ktachibana.cloudemoji.parsing.SourceReader; import org.ktachibana.cloudemoji.utils.NotificationUtils; +import org.ktachibana.cloudemoji.utils.SystemUtils; import org.parceler.Parcels; import java.io.File; @@ -47,12 +52,15 @@ import java.util.List; import butterknife.ButterKnife; +import pub.devrel.easypermissions.AfterPermissionGranted; +import pub.devrel.easypermissions.EasyPermissions; public class MainActivity extends BaseActivity implements SharedPreferences.OnSharedPreferenceChangeListener { public static final String SOURCE_CACHE_TAG = "sourceCache"; private static final String CURRENT_ITEM_TAG = "currentItem"; private LinkedHashMap sourceCache; private int currentItem; + private static final int RC_POST_NOTIFICATIONS = 123; @Override protected void onCreate(Bundle savedInstanceState) { @@ -93,7 +101,7 @@ private void render() { * Put every source into source cache */ private LinkedHashMap initializeSourceCache() { - LinkedHashMap sourceCache = new LinkedHashMap(); + LinkedHashMap sourceCache = new LinkedHashMap<>(); List allRepositories = Repository.listAll(Repository.class); for (Repository repository : allRepositories) { @@ -114,8 +122,18 @@ private LinkedHashMap initializeSourceCache() { return sourceCache; } + @AfterPermissionGranted(RC_POST_NOTIFICATIONS) private void setupNotification() { - NotificationUtils.setupNotificationWithPref(this, mPreferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY)); + if (SystemUtils.aboveTiramisu()) { + String[] perms = {Manifest.permission.POST_NOTIFICATIONS}; + if (EasyPermissions.hasPermissions(this, perms)) { + NotificationUtils.setupNotificationWithPref(this, mPreferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY)); + } else { + EasyPermissions.requestPermissions(this, getString(R.string.notification_rationale), RC_POST_NOTIFICATIONS, perms); + } + } else { + NotificationUtils.setupNotificationWithPref(this, mPreferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY)); + } } @Override @@ -231,12 +249,12 @@ private void checkVersionCode(boolean success, int latestVersionCode) { } else { // New version available, show dialog new MaterialDialog.Builder(MainActivity.this) - .title(getString(R.string.new_version_available) + String.format(" (%d)", latestVersionCode)) + .title(String.format(getString(R.string.new_version_available), latestVersionCode)) .positiveText(R.string.go_to_play_store) .negativeText(android.R.string.cancel) - .callback(new MaterialDialog.ButtonCallback() { + .onPositive(new MaterialDialog.SingleButtonCallback() { @Override - public void onPositive(MaterialDialog dialog) { + public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { Intent intent = new Intent(); intent.setData(Uri.parse(Constants.PLAY_STORE_URL)); startActivity(intent); @@ -276,6 +294,7 @@ else if (requestCode == Constants.PREFERENCE_REQUEST_CODE) { @Override protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); outState.putParcelable(SOURCE_CACHE_TAG, Parcels.wrap(sourceCache)); outState.putInt(CURRENT_ITEM_TAG, currentItem); } @@ -295,7 +314,6 @@ private void firstTimeCheck() { } } - @SuppressWarnings("unchecked") private void setupDefaultRepoIfNecessary() { if (Repository.listAll(Repository.class).size() != 0) { // If there are already repositories, ignore @@ -370,4 +388,11 @@ private void upgradeFavoriteDatabaseIfExists() { e.printStackTrace(); } } -} \ No newline at end of file + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + + // Forward results to EasyPermissions + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); + }} \ No newline at end of file diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/CopyUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/CopyUtils.java index 7010b0f5..f349c25a 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/CopyUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/CopyUtils.java @@ -1,20 +1,12 @@ package org.ktachibana.cloudemoji.utils; -import android.annotation.TargetApi; import android.content.Context; public class CopyUtils { - @TargetApi(11) public static void copyToClipboard(Context context, String copied) { - if (SystemUtils.belowHoneycomb()) { - android.text.ClipboardManager clipboard - = (android.text.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - clipboard.setText(copied); - } else { - android.content.ClipboardManager clipboard - = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - android.content.ClipData clip = android.content.ClipData.newPlainText("emoji", copied); - clipboard.setPrimaryClip(clip); - } + android.content.ClipboardManager clipboard + = (android.content.ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + android.content.ClipData clip = android.content.ClipData.newPlainText("emoji", copied); + clipboard.setPrimaryClip(clip); } } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java index efe1e376..1e7b70cb 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java @@ -20,18 +20,6 @@ public static boolean networkAvailable() { return (network == NetworkInfo.State.CONNECTED || network == NetworkInfo.State.CONNECTING); } - public static boolean networkUnavailable() { - return !networkAvailable(); - } - - public static boolean belowHoneycomb() { - return Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB; - } - - public static boolean aboveHoneycomb() { - return !belowHoneycomb(); - } - public static boolean belowJellybean() { return Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN; } @@ -51,4 +39,8 @@ public static boolean aboveMarshmallow() { public static boolean aboveOreo() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; } + + public static boolean aboveTiramisu() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU; + } } diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 253560a0..9bc4fbce 100755 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -51,7 +51,7 @@ 检查新版本 检查新版本失败 已经是最新版本 - 有新版本辣! + 有新版本辣!(%d) 去 Play Store 看看 没找到 @@ -86,4 +86,5 @@ 没有收藏 将全部收藏从个人词典中撤出 已将 %d 个收藏从个人词典中撤出 + 需要通知权限,这样的话您可以从通知面板中快速打开 App \ 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 c38c06de..c89e36bd 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -53,7 +53,7 @@ Check for update Failed to check for update Already latest version - New version is available! + New version is available! (%d) Go to Play Store Result not found @@ -87,4 +87,5 @@ No bookmark Reoke all bookmarks from personal dictionary Revoked %d bookmarks from personal dictionary + We need to put a sticky \"quick trigger\" notification so that you can launch Cloud Emoticon conveniently. \ No newline at end of file From 997b2c60b88ed3521de2a89b6db0b7cfe7e28d23 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Mon, 17 Oct 2022 18:32:39 -0700 Subject: [PATCH 08/31] use easy permission for quick trigger notification in bootup activity --- .../activities/BootUpDummyActivity.java | 18 ++++++++++++++++-- .../cloudemoji/activities/MainActivity.java | 3 ++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/BootUpDummyActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/BootUpDummyActivity.java index b1b8c088..4a3831f9 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/BootUpDummyActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/BootUpDummyActivity.java @@ -1,12 +1,19 @@ package org.ktachibana.cloudemoji.activities; +import android.Manifest; import android.app.Activity; import android.content.SharedPreferences; import android.os.Bundle; import android.preference.PreferenceManager; +import androidx.annotation.NonNull; + import org.ktachibana.cloudemoji.Constants; +import org.ktachibana.cloudemoji.R; import org.ktachibana.cloudemoji.utils.NotificationUtils; +import org.ktachibana.cloudemoji.utils.SystemUtils; + +import pub.devrel.easypermissions.EasyPermissions; /** * Dummy activity that shows notification after boot up @@ -19,10 +26,17 @@ protected void onCreate(Bundle savedInstanceState) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); // Show notification according to prefs - Boolean showAfterBootUp = preferences.getBoolean(Constants.PREF_SHOW_AFTER_BOOT_UP, true); + boolean showAfterBootUp = preferences.getBoolean(Constants.PREF_SHOW_AFTER_BOOT_UP, true); String notificationVisibility = preferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY); if (showAfterBootUp) { - NotificationUtils.setupNotificationWithPref(this, notificationVisibility); + if (SystemUtils.aboveTiramisu()) { + String[] perms = {Manifest.permission.POST_NOTIFICATIONS}; + if (EasyPermissions.hasPermissions(this, perms)) { + NotificationUtils.setupNotificationWithPref(this, notificationVisibility); + } + } else { + NotificationUtils.setupNotificationWithPref(this, notificationVisibility); + } } finish(); diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java index d3fec296..c49bd1a3 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java @@ -395,4 +395,5 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis // Forward results to EasyPermissions EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); - }} \ No newline at end of file + } +} \ No newline at end of file From 0cc597ed769b0b2a8d9f08f6e53babaef31f3c24 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Mon, 17 Oct 2022 18:38:20 -0700 Subject: [PATCH 09/31] code cleanup --- .../ktachibana/cloudemoji/activities/BootUpDummyActivity.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/BootUpDummyActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/BootUpDummyActivity.java index 4a3831f9..b8667cfa 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/BootUpDummyActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/BootUpDummyActivity.java @@ -6,10 +6,7 @@ import android.os.Bundle; import android.preference.PreferenceManager; -import androidx.annotation.NonNull; - import org.ktachibana.cloudemoji.Constants; -import org.ktachibana.cloudemoji.R; import org.ktachibana.cloudemoji.utils.NotificationUtils; import org.ktachibana.cloudemoji.utils.SystemUtils; From 233b20bfe895120162c08a7575281cfdd25d4e96 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Mon, 17 Oct 2022 19:35:24 -0700 Subject: [PATCH 10/31] replace bootup activity with just the receiver & code cleanup --- app/src/main/AndroidManifest.xml | 4 -- .../activities/BootUpDummyActivity.java | 48 ------------------- .../cloudemoji/receivers/BootUpReceiver.java | 28 +++++++++-- .../cloudemoji/utils/NotificationUtils.java | 35 +++++++------- .../cloudemoji/utils/SystemUtils.java | 4 ++ 5 files changed, 46 insertions(+), 73 deletions(-) delete mode 100644 app/src/main/java/org/ktachibana/cloudemoji/activities/BootUpDummyActivity.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f76bf30d..ce213ab0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -73,10 +73,6 @@ android:name="android.support.PARENT_ACTIVITY" android:value="org.ktachibana.cloudemoji.activities.MainActivity" /> - = android.os.Build.VERSION_CODES.S) { + if (SystemUtils.aboveS()) { pIntent = PendingIntent.getActivity (context, 0, intent, PendingIntent.FLAG_MUTABLE); } else { diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java index 1e7b70cb..780a328c 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java @@ -40,6 +40,10 @@ public static boolean aboveOreo() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; } + public static boolean aboveS() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S; + } + public static boolean aboveTiramisu() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU; } From 8d2c3d36c8e9aea80eeb8e5e6e423e6a7b64da21 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Mon, 17 Oct 2022 20:28:37 -0700 Subject: [PATCH 11/31] try to fix backup and restore & bunch of refactors --- app/build.gradle | 4 +- .../cloudemoji/activities/MainActivity.java | 20 ++-- .../fragments/PreferenceFragment.java | 103 ++++++++++-------- .../cloudemoji/receivers/BootUpReceiver.java | 40 ++++--- .../cloudemoji/utils/NotificationUtils.java | 4 +- .../utils/PersonalDictionaryUtils.java | 4 +- .../cloudemoji/utils/SystemUtils.java | 22 +--- app/src/main/res/values-zh/strings.xml | 1 - 8 files changed, 103 insertions(+), 95 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 5d041480..21f15313 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,7 +4,7 @@ android { compileSdkVersion 33 defaultConfig { - minSdkVersion 14 + minSdkVersion 19 targetSdkVersion 33 versionCode 33 versionName '1.3.2' @@ -73,8 +73,6 @@ dependencies { annotationProcessor 'com.hannesdorfmann.fragmentargs:processor:4.0.0-RC1' implementation "org.parceler:parceler-api:1.1.12" annotationProcessor "org.parceler:parceler:1.1.12" - implementation "com.github.permissions-dispatcher:permissionsdispatcher:4.9.2" - annotationProcessor "com.github.permissions-dispatcher:permissionsdispatcher-processor:4.9.2" implementation 'pub.devrel:easypermissions:3.0.0' // Debug implementation 'com.facebook.stetho:stetho:1.3.1' diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java index c49bd1a3..5b6de22a 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java @@ -124,18 +124,22 @@ private LinkedHashMap initializeSourceCache() { @AfterPermissionGranted(RC_POST_NOTIFICATIONS) private void setupNotification() { - if (SystemUtils.aboveTiramisu()) { - String[] perms = {Manifest.permission.POST_NOTIFICATIONS}; - if (EasyPermissions.hasPermissions(this, perms)) { - NotificationUtils.setupNotificationWithPref(this, mPreferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY)); - } else { - EasyPermissions.requestPermissions(this, getString(R.string.notification_rationale), RC_POST_NOTIFICATIONS, perms); - } + if (!SystemUtils.aboveTiramisu33()) { + _setupNotification(); + return; + } + String[] perms = {Manifest.permission.POST_NOTIFICATIONS}; + if (EasyPermissions.hasPermissions(this, perms)) { + _setupNotification(); } else { - NotificationUtils.setupNotificationWithPref(this, mPreferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY)); + EasyPermissions.requestPermissions(this, getString(R.string.notification_rationale), RC_POST_NOTIFICATIONS, perms); } } + private void _setupNotification() { + NotificationUtils.setupNotificationWithPref(this, mPreferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY)); + } + @Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { if (Constants.PREF_NOTIFICATION_VISIBILITY.equals(key)) { diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index e8fbe379..248ee584 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -3,19 +3,18 @@ import android.Manifest; import android.content.ComponentName; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; + +import androidx.annotation.NonNull; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceFragmentCompat; -import com.afollestad.materialdialogs.AlertDialogWrapper; - import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.ktachibana.cloudemoji.BuildConfig; @@ -27,23 +26,24 @@ import org.ktachibana.cloudemoji.utils.PersonalDictionaryUtils; import org.ktachibana.cloudemoji.utils.SystemUtils; -import permissions.dispatcher.NeedsPermission; -import permissions.dispatcher.OnShowRationale; -import permissions.dispatcher.PermissionRequest; -import permissions.dispatcher.RuntimePermissions; +import pub.devrel.easypermissions.AfterPermissionGranted; +import pub.devrel.easypermissions.EasyPermissions; -@RuntimePermissions public class PreferenceFragment extends PreferenceFragmentCompat { private static final String CLS_ASSIST_ACTIVITY = "org.ktachibana.cloudemoji.activities.AssistActivity"; SharedPreferences.OnSharedPreferenceChangeListener mSharedPreferenceChangeListener; SharedPreferences mPreferences; + private Context mContext; private EventBus mBus; + private static final int RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_BACKUP = 125; + private static final int RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_RESTORE = 126; @Override public void onAttach(Context context) { super.onAttach(context); mBus = EventBus.getDefault(); mBus.register(this); + mContext = context; } @Override @@ -56,31 +56,6 @@ public void onDetach() { public void handle(EmptyEvent e) { } - @OnShowRationale({Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}) - public void showRationaleForStorage(final PermissionRequest request) { - new AlertDialogWrapper.Builder(getContext()) - .setMessage(R.string.storage_rationale) - .setPositiveButton(R.string.allow, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - request.proceed(); - } - }) - .setNegativeButton(R.string.deny, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - request.cancel(); - } - }) - .show(); - } - - @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - PreferenceFragmentPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults); - } - @Override public void onCreatePreferences(Bundle paramBundle, String rootKey) { // Load the mPreferences from an XML resource @@ -91,14 +66,14 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { Preference navbarGesturePref = findPreference(Constants.PREF_NAVBAR_GESTURE); Preference nowOnTapPref = findPreference(Constants.PREF_NOW_ON_TAP); PreferenceCategory behaviorsPref = (PreferenceCategory) findPreference(Constants.PREF_BEHAVIORS); - if (SystemUtils.belowJellybean()) - navbarGesturePref.setEnabled(false); - if (SystemUtils.belowMarshmallow()) + navbarGesturePref.setEnabled(false); + if (!SystemUtils.aboveMarshmallow23()) { behaviorsPref.removePreference(nowOnTapPref); + } navbarGesturePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - PackageManager packageManager = getActivity().getPackageManager(); + PackageManager packageManager = mContext.getPackageManager(); ComponentName componentName = new ComponentName(getActivity(), CLS_ASSIST_ACTIVITY); int componentState = newValue.equals(true) ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : @@ -110,9 +85,9 @@ public boolean onPreferenceChange(Preference preference, Object newValue) { }); // Now on Tap - if (SystemUtils.aboveMarshmallow()) { + if (SystemUtils.aboveMarshmallow23()) { behaviorsPref.removePreference(navbarGesturePref); - PackageManager packageManager = getActivity().getPackageManager(); + PackageManager packageManager = mContext.getPackageManager(); ComponentName componentName = new ComponentName(getActivity(), CLS_ASSIST_ACTIVITY); packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); @@ -136,7 +111,7 @@ public boolean onPreferenceClick(Preference preference) { importImePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - int numberAdded = PersonalDictionaryUtils.importAllFavorites(getActivity().getContentResolver()); + int numberAdded = PersonalDictionaryUtils.importAllFavorites(mContext.getContentResolver()); showSnackBar(String.format(getString(R.string.imported_into_personal_dict), numberAdded)); return true; } @@ -147,7 +122,7 @@ public boolean onPreferenceClick(Preference preference) { revokeImePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - int numberRevoked = PersonalDictionaryUtils.revokeAllFavorites(getActivity().getContentResolver()); + int numberRevoked = PersonalDictionaryUtils.revokeAllFavorites(mContext.getContentResolver()); showSnackBar(String.format(getString(R.string.revoked_from_personal_dict), numberRevoked)); return true; } @@ -158,7 +133,7 @@ public boolean onPreferenceClick(Preference preference) { backupPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - PreferenceFragmentPermissionsDispatcher.backupFavoritesWithPermissionCheck(PreferenceFragment.this); + backupFavorites(); return true; } }); @@ -168,7 +143,7 @@ public boolean onPreferenceClick(Preference preference) { restorePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - PreferenceFragmentPermissionsDispatcher.restoreFavoritesWithPermissionCheck(PreferenceFragment.this); + restoreFavorites(); return true; } }); @@ -205,8 +180,23 @@ public boolean onPreferenceClick(Preference preference) { versionPref.setSummary(getString(R.string.version_code) + " " + versionCode); } - @NeedsPermission({Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}) + @AfterPermissionGranted(RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_BACKUP) void backupFavorites() { + if (!SystemUtils.aboveMarshmallow23()) { + _backupFavorites(); + return; + } + String[] perms = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; + if (EasyPermissions.hasPermissions(mContext, perms)) { + _backupFavorites(); + } else { + // Do not have permissions, request them now + EasyPermissions.requestPermissions(this, mContext.getString(R.string.storage_rationale), + RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_BACKUP, perms); + } + } + + void _backupFavorites() { boolean success = BackupUtils.backupFavorites(); if (success) { showSnackBar(getString(R.string.backed_up_favorites) + ": " + Constants.FAVORITES_BACKUP_FILE_PATH); @@ -215,8 +205,23 @@ void backupFavorites() { } } - @NeedsPermission({Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}) + @AfterPermissionGranted(RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_RESTORE) void restoreFavorites() { + if (!SystemUtils.aboveMarshmallow23()) { + _restoreFavorites(); + return; + } + String[] perms = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; + if (EasyPermissions.hasPermissions(mContext, perms)) { + _restoreFavorites(); + } else { + // Do not have permissions, request them now + EasyPermissions.requestPermissions(this, mContext.getString(R.string.storage_rationale), + RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_RESTORE, perms); + } + } + + void _restoreFavorites() { boolean success = BackupUtils.restoreFavorites(); if (success) { showSnackBar(R.string.restored_favorites); @@ -238,4 +243,12 @@ private void showSnackBar(String message) { private void showSnackBar(int resId) { showSnackBar(getString(resId)); } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + + // Forward results to EasyPermissions + EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); + } } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java b/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java index 5fb45857..e3d22fc2 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java @@ -19,22 +19,30 @@ public class BootUpReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) { - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - - // Show notification according to prefs - boolean showAfterBootUp = preferences.getBoolean(Constants.PREF_SHOW_AFTER_BOOT_UP, true); - String notificationVisibility = preferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY); - if (showAfterBootUp) { - if (SystemUtils.aboveTiramisu()) { - String[] perms = {Manifest.permission.POST_NOTIFICATIONS}; - if (EasyPermissions.hasPermissions(context, perms)) { - NotificationUtils.setupNotificationWithPref(context, notificationVisibility); - } - } else { - NotificationUtils.setupNotificationWithPref(context, notificationVisibility); - } - } + if (!"android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) { + return; } + + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + + // Show notification according to prefs + boolean showAfterBootUp = preferences.getBoolean(Constants.PREF_SHOW_AFTER_BOOT_UP, true); + if (!showAfterBootUp) { + return; + } + + String notificationVisibility = preferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY); + if (!SystemUtils.aboveTiramisu33()) { + _setupNotification(context, notificationVisibility); + return; + } + String[] perms = {Manifest.permission.POST_NOTIFICATIONS}; + if (EasyPermissions.hasPermissions(context, perms)) { + _setupNotification(context, notificationVisibility); + } + } + + private void _setupNotification(Context context, String notificationVisibility) { + NotificationUtils.setupNotificationWithPref(context, notificationVisibility); } } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index 26b34ef2..f0db5a3d 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -53,7 +53,7 @@ private static void createQuickTriggerNotificationChannel( NotificationManager notificationManager, int importance ) { - if (SystemUtils.aboveOreo()) { + if (SystemUtils.aboveOreo26()) { NotificationChannel channel = new NotificationChannel( Constants.QUICK_TRIGGER_NOTIFICATION_CHANNEL_ID, context.getString(R.string.quick_trigger_notification_channel_name), @@ -75,7 +75,7 @@ private static void showQuickTriggerNotification( String text = context.getString(R.string.touch_to_launch); Intent intent = new Intent(context, MainActivity.class); PendingIntent pIntent; - if (SystemUtils.aboveS()) { + if (SystemUtils.aboveS31()) { pIntent = PendingIntent.getActivity (context, 0, intent, PendingIntent.FLAG_MUTABLE); } else { diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/PersonalDictionaryUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/PersonalDictionaryUtils.java index e282f720..fc620cd7 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/PersonalDictionaryUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/PersonalDictionaryUtils.java @@ -19,9 +19,7 @@ public static int importAllFavorites(ContentResolver contentResolver) { if (!favorite.getShortcut().equals("")) { ContentValues newValue = new ContentValues(); newValue.put(UserDictionary.Words.WORD, favorite.getEmoticon()); - if (SystemUtils.aboveJellybean()) { - newValue.put(UserDictionary.Words.SHORTCUT, favorite.getShortcut()); - } + newValue.put(UserDictionary.Words.SHORTCUT, favorite.getShortcut()); contentResolver.insert(UserDictionary.Words.CONTENT_URI, newValue); counter++; } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java index 780a328c..768f030a 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java @@ -20,31 +20,19 @@ public static boolean networkAvailable() { return (network == NetworkInfo.State.CONNECTED || network == NetworkInfo.State.CONNECTING); } - public static boolean belowJellybean() { - return Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN; + public static boolean aboveMarshmallow23() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; } - public static boolean aboveJellybean() { - return !belowJellybean(); - } - - public static boolean belowMarshmallow() { - return Build.VERSION.SDK_INT < Build.VERSION_CODES.M; - } - - public static boolean aboveMarshmallow() { - return !belowMarshmallow(); - } - - public static boolean aboveOreo() { + public static boolean aboveOreo26() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; } - public static boolean aboveS() { + public static boolean aboveS31() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S; } - public static boolean aboveTiramisu() { + public static boolean aboveTiramisu33() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU; } } diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 9bc4fbce..ce7531e9 100755 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -55,7 +55,6 @@ 去 Play Store 看看 没找到 - 不显示 只在通知面板里显示(Android 3.0 以下及 8.0 以上无效) From 38cf982699f4e0b51e55d92c054cb9bcaf8f989e Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Tue, 18 Oct 2022 07:51:47 -0700 Subject: [PATCH 12/31] reduce permissions for backup/restore --- .../cloudemoji/fragments/PreferenceFragment.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index 248ee584..b605070d 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -35,8 +35,8 @@ public class PreferenceFragment extends PreferenceFragmentCompat { SharedPreferences mPreferences; private Context mContext; private EventBus mBus; - private static final int RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_BACKUP = 125; - private static final int RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_RESTORE = 126; + private static final int RC_WRITE_EXTERNAL_STORAGE_FOR_BACKUP = 123; + private static final int RC_READ_EXTERNAL_STORAGE_FOR_RESTORE = 124; @Override public void onAttach(Context context) { @@ -180,19 +180,19 @@ public boolean onPreferenceClick(Preference preference) { versionPref.setSummary(getString(R.string.version_code) + " " + versionCode); } - @AfterPermissionGranted(RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_BACKUP) + @AfterPermissionGranted(RC_WRITE_EXTERNAL_STORAGE_FOR_BACKUP) void backupFavorites() { if (!SystemUtils.aboveMarshmallow23()) { _backupFavorites(); return; } - String[] perms = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; + String[] perms = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; if (EasyPermissions.hasPermissions(mContext, perms)) { _backupFavorites(); } else { // Do not have permissions, request them now EasyPermissions.requestPermissions(this, mContext.getString(R.string.storage_rationale), - RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_BACKUP, perms); + RC_WRITE_EXTERNAL_STORAGE_FOR_BACKUP, perms); } } @@ -205,19 +205,19 @@ void _backupFavorites() { } } - @AfterPermissionGranted(RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_RESTORE) + @AfterPermissionGranted(RC_READ_EXTERNAL_STORAGE_FOR_RESTORE) void restoreFavorites() { if (!SystemUtils.aboveMarshmallow23()) { _restoreFavorites(); return; } - String[] perms = {Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; + String[] perms = {Manifest.permission.READ_EXTERNAL_STORAGE}; if (EasyPermissions.hasPermissions(mContext, perms)) { _restoreFavorites(); } else { // Do not have permissions, request them now EasyPermissions.requestPermissions(this, mContext.getString(R.string.storage_rationale), - RC_READ_AND_WRITE_EXTERNAL_STORAGE_FOR_RESTORE, perms); + RC_READ_EXTERNAL_STORAGE_FOR_RESTORE, perms); } } From bfc8671f757327a9eaaea3c388a3702198b8ad74 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Wed, 19 Oct 2022 22:02:39 -0700 Subject: [PATCH 13/31] implement backup and restore using document chooser --- app/src/main/AndroidManifest.xml | 2 - .../org/ktachibana/cloudemoji/Constants.java | 2 - .../adapters/RepositoryListViewAdapter.java | 3 +- .../fragments/PreferenceFragment.java | 115 +++++++++--------- .../cloudemoji/parsing/SourceJsonParser.java | 4 + .../cloudemoji/utils/BackupUtils.java | 111 ++++------------- app/src/main/res/values-zh/strings.xml | 2 +- app/src/main/res/values/strings.xml | 3 +- 8 files changed, 91 insertions(+), 151 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ce213ab0..80eb2d8f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,8 +8,6 @@ - - diff --git a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java index 0044e05b..301b9e18 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java @@ -49,8 +49,6 @@ public interface Constants { int REPOSITORY_STORE_REQUEST_CODE = 2; // File - String FAVORITES_BACKUP_FILE_PATH - = Environment.getExternalStorageDirectory().getPath() + File.separator + "ce.json"; String EXPORT_FILE_PATH = Environment.getExternalStorageDirectory().getPath() + File.separator + "%s"; diff --git a/app/src/main/java/org/ktachibana/cloudemoji/adapters/RepositoryListViewAdapter.java b/app/src/main/java/org/ktachibana/cloudemoji/adapters/RepositoryListViewAdapter.java index c5db0a08..a29ca234 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/adapters/RepositoryListViewAdapter.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/adapters/RepositoryListViewAdapter.java @@ -135,7 +135,8 @@ public void onClick(View v) { // Get file and write String filePath = String.format(Constants.EXPORT_FILE_PATH, item.getAlias() + ".json"); File exportFile = new File(filePath); - BackupUtils.writeFileToExternalStorage(json, exportFile); + // TODO +// BackupUtils.writeFileToExternalStorage(json, exportFile); mBus.post(new RepositoryExportedEvent(filePath)); } catch (Exception e) { diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index b605070d..b8c683a8 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -1,20 +1,24 @@ package org.ktachibana.cloudemoji.fragments; -import android.Manifest; +import static android.app.Activity.RESULT_OK; + import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; +import android.os.Environment; import android.preference.PreferenceManager; +import android.provider.DocumentsContract; -import androidx.annotation.NonNull; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceFragmentCompat; +import org.apache.commons.io.IOUtils; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.ktachibana.cloudemoji.BuildConfig; @@ -26,17 +30,23 @@ import org.ktachibana.cloudemoji.utils.PersonalDictionaryUtils; import org.ktachibana.cloudemoji.utils.SystemUtils; -import pub.devrel.easypermissions.AfterPermissionGranted; -import pub.devrel.easypermissions.EasyPermissions; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + public class PreferenceFragment extends PreferenceFragmentCompat { private static final String CLS_ASSIST_ACTIVITY = "org.ktachibana.cloudemoji.activities.AssistActivity"; + private static final String BACKUP_FILE_MIME_TYPE = "application/json"; + private static final String BACKUP_FILENAME = "ce.json"; + private static final int RC_BACKUP = 1; + private static final int RC_RESTORE = 2; + SharedPreferences.OnSharedPreferenceChangeListener mSharedPreferenceChangeListener; SharedPreferences mPreferences; private Context mContext; private EventBus mBus; - private static final int RC_WRITE_EXTERNAL_STORAGE_FOR_BACKUP = 123; - private static final int RC_READ_EXTERNAL_STORAGE_FOR_RESTORE = 124; + private ContentResolver mContentResolver; @Override public void onAttach(Context context) { @@ -44,6 +54,7 @@ public void onAttach(Context context) { mBus = EventBus.getDefault(); mBus.register(this); mContext = context; + mContentResolver = context.getContentResolver(); } @Override @@ -180,53 +191,57 @@ public boolean onPreferenceClick(Preference preference) { versionPref.setSummary(getString(R.string.version_code) + " " + versionCode); } - @AfterPermissionGranted(RC_WRITE_EXTERNAL_STORAGE_FOR_BACKUP) void backupFavorites() { - if (!SystemUtils.aboveMarshmallow23()) { - _backupFavorites(); - return; - } - String[] perms = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; - if (EasyPermissions.hasPermissions(mContext, perms)) { - _backupFavorites(); - } else { - // Do not have permissions, request them now - EasyPermissions.requestPermissions(this, mContext.getString(R.string.storage_rationale), - RC_WRITE_EXTERNAL_STORAGE_FOR_BACKUP, perms); - } - } + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType(BACKUP_FILE_MIME_TYPE); + intent.putExtra(Intent.EXTRA_TITLE, BACKUP_FILENAME); - void _backupFavorites() { - boolean success = BackupUtils.backupFavorites(); - if (success) { - showSnackBar(getString(R.string.backed_up_favorites) + ": " + Constants.FAVORITES_BACKUP_FILE_PATH); - } else { - showSnackBar(R.string.fail); + if (SystemUtils.aboveOreo26()) { + // Optionally, specify a URI for the directory that should be opened in + // the system file picker when your app creates the document. + intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOCUMENTS); } + + startActivityForResult(intent, RC_BACKUP); } - @AfterPermissionGranted(RC_READ_EXTERNAL_STORAGE_FOR_RESTORE) void restoreFavorites() { - if (!SystemUtils.aboveMarshmallow23()) { - _restoreFavorites(); - return; - } - String[] perms = {Manifest.permission.READ_EXTERNAL_STORAGE}; - if (EasyPermissions.hasPermissions(mContext, perms)) { - _restoreFavorites(); - } else { - // Do not have permissions, request them now - EasyPermissions.requestPermissions(this, mContext.getString(R.string.storage_rationale), - RC_READ_EXTERNAL_STORAGE_FOR_RESTORE, perms); + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType(BACKUP_FILE_MIME_TYPE); + + if (SystemUtils.aboveOreo26()) { + intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOCUMENTS); } + // Optionally, specify a URI for the file that should appear in the + // system file picker when it loads. + + startActivityForResult(intent, RC_RESTORE); } - void _restoreFavorites() { - boolean success = BackupUtils.restoreFavorites(); - if (success) { - showSnackBar(R.string.restored_favorites); - } else { - showSnackBar(R.string.fail); + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + OutputStream os = null; + InputStream is = null; + try { + if (resultCode == RESULT_OK) { + if (requestCode == RC_BACKUP) { + os = mContentResolver.openOutputStream(data.getData()); + BackupUtils.writeFavorites(os); + } else if (requestCode == RC_RESTORE) { + is = mContentResolver.openInputStream(data.getData()); + BackupUtils.readFavorites(is); + } + } else { + showSnackBar(getString(R.string.fail)); + } + } catch (IOException e) { + showSnackBar(getString(R.string.fail)); + } finally { + IOUtils.closeQuietly(os); + IOUtils.closeQuietly(is); } } @@ -239,16 +254,4 @@ public void onDestroy() { private void showSnackBar(String message) { mBus.post(new ShowSnackBarOnBaseActivityEvent(message)); } - - private void showSnackBar(int resId) { - showSnackBar(getString(resId)); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - - // Forward results to EasyPermissions - EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this); - } } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/parsing/SourceJsonParser.java b/app/src/main/java/org/ktachibana/cloudemoji/parsing/SourceJsonParser.java index 8cb2da0a..9755ea53 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/parsing/SourceJsonParser.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/parsing/SourceJsonParser.java @@ -12,6 +12,10 @@ public class SourceJsonParser { public Source parse(String alias, Reader reader) throws IOException { String json = IOUtils.toString(reader); + return parse(alias, json); + } + + public Source parse(String alias, String json) throws IOException { Source newSource = new Gson().fromJson(json, Source.class); newSource.setAlias(alias); return newSource; diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/BackupUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/BackupUtils.java index a51e1b72..8a5a9f24 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/BackupUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/BackupUtils.java @@ -1,110 +1,47 @@ package org.ktachibana.cloudemoji.utils; -import android.os.Environment; - import org.apache.commons.io.IOUtils; -import org.ktachibana.cloudemoji.Constants; import org.ktachibana.cloudemoji.models.disk.Favorite; import org.ktachibana.cloudemoji.models.memory.Entry; import org.ktachibana.cloudemoji.models.memory.Source; import org.ktachibana.cloudemoji.parsing.SourceJsonParser; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class BackupUtils { - - public static boolean backupFavorites() { - // If external storage not writable - if (!isExternalStorageWritable()) { - return false; - } - - // Get backup file - File backupFile = new File(Constants.FAVORITES_BACKUP_FILE_PATH); - if (backupFile.exists()) backupFile.delete(); - - // Write to file - try { - String json = new SourceJsonParser().serialize(FavoritesUtils.getFavoritesAsSource()); - writeFileToExternalStorage(json, backupFile); - } catch (IOException e) { - return false; - } - return true; - } - - public static boolean restoreFavorites() { - // If external storage not readable - if (!isExternalStorageReadable()) { - return false; + public static void readFavorites(InputStream is) throws IOException { + // Get backed up favorites + String json = IOUtils.toString(is); + Source source = new SourceJsonParser().parse(null, json); + List backedUpFavorites = source.getCategories().get(0).getEntries(); + + // Get current favorites + List favorites = Favorite.listAll(Favorite.class); + List currentFavorites = new ArrayList<>(); + for (Favorite favorite : favorites) { + currentFavorites.add(new Entry(favorite.getEmoticon(), favorite.getDescription())); } - // Get backup file - File backupFile = new File(Constants.FAVORITES_BACKUP_FILE_PATH); - FileReader fileReader = null; - try { - // Get backed up favorites - fileReader = new FileReader(backupFile); - Source source = new SourceJsonParser().parse(null, fileReader); - List backedUpFavorites = source.getCategories().get(0).getEntries(); + // Merge backed up and current favorites + Set mergedFavorites = new HashSet<>(backedUpFavorites); + mergedFavorites.addAll(currentFavorites); - // Get current favorites - List favorites = Favorite.listAll(Favorite.class); - List currentFavorites = new ArrayList(); - for (Favorite favorite : favorites) { - currentFavorites.add(new Entry(favorite.getEmoticon(), favorite.getDescription())); - } - - // Merge backed up and current favorites - Set mergedFavorites = new HashSet(); - for (Entry backedUp : backedUpFavorites) { - mergedFavorites.add(backedUp); - } - for (Entry current : currentFavorites) { - mergedFavorites.add(current); - } - - // Remove all current favorites and add back merged favorites - Favorite.deleteAll(Favorite.class); - for (Entry entry : mergedFavorites) { - Favorite favorite = new Favorite(entry.getEmoticon(), entry.getDescription(), ""); - favorite.save(); - } - } catch (IOException e) { - return false; - } finally { - IOUtils.closeQuietly(fileReader); - } - return true; - } - - public static void writeFileToExternalStorage(String string, File file) throws IOException { - // If external storage not writable - if (!isExternalStorageWritable()) { - return; + // Remove all current favorites and add back merged favorites + Favorite.deleteAll(Favorite.class); + for (Entry entry : mergedFavorites) { + Favorite favorite = new Favorite(entry.getEmoticon(), entry.getDescription(), ""); + favorite.save(); } - - // Write to file - FileOutputStream outputStream = new FileOutputStream(file); - IOUtils.write(string, outputStream); - IOUtils.closeQuietly(outputStream); - } - - private static boolean isExternalStorageWritable() { - String state = Environment.getExternalStorageState(); - return Environment.MEDIA_MOUNTED.equals(state); } - private static boolean isExternalStorageReadable() { - String state = Environment.getExternalStorageState(); - return Environment.MEDIA_MOUNTED.equals(state) - || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state); + public static void writeFavorites(OutputStream os) throws IOException { + String json = new SourceJsonParser().serialize(FavoritesUtils.getFavoritesAsSource()); + IOUtils.write(json, os); } } diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index ce7531e9..e8c17065 100755 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -70,7 +70,6 @@ 已添加到源 允许 拒绝 - 需要储存权限以备份/恢复收藏 收藏已备份到 收藏已恢复 通知 @@ -86,4 +85,5 @@ 将全部收藏从个人词典中撤出 已将 %d 个收藏从个人词典中撤出 需要通知权限,这样的话您可以从通知面板中快速打开 App + 出错辣!请再试一下 \ 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 c89e36bd..56d1622d 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,7 +6,7 @@ Exit Copied to clipboard Bad connection, please retry - ლ(╹◡╹ლ) + Something went wrong, please try again ╮( ̄▽ ̄")╭ Touch to launch Settings @@ -72,7 +72,6 @@ Added to repositories Allow Deny - We need storage permission in order to backup/restore your bookmarks. Backed up favorites to Restored bookmarks Notification From a134c73bbf157c030322619c0e2b4fa2fd56b61f Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Wed, 19 Oct 2022 22:50:05 -0700 Subject: [PATCH 14/31] implement repo export using document chooser --- .../org/ktachibana/cloudemoji/Constants.java | 4 -- .../activities/RepositoryManagerActivity.java | 52 +++++++++++++++++-- .../adapters/RepositoryListViewAdapter.java | 14 ++--- .../events/RepositoryExportEvent.java | 19 +++++++ .../events/RepositoryExportedEvent.java | 17 ------ app/src/main/res/values-zh/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 7 files changed, 74 insertions(+), 34 deletions(-) create mode 100644 app/src/main/java/org/ktachibana/cloudemoji/events/RepositoryExportEvent.java delete mode 100644 app/src/main/java/org/ktachibana/cloudemoji/events/RepositoryExportedEvent.java diff --git a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java index 301b9e18..680ecc3e 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java @@ -48,10 +48,6 @@ public interface Constants { int PREFERENCE_REQUEST_CODE = 1; int REPOSITORY_STORE_REQUEST_CODE = 2; - // File - String EXPORT_FILE_PATH - = Environment.getExternalStorageDirectory().getPath() + File.separator + "%s"; - // Hacking String PACKAGE_NAME_ANDROID_SETTINGS = "com.android.settings"; String CLASS_NAME_MANAGE_ASSIST_ACTIVITY = "com.android.settings.Settings$ManageAssistActivity"; diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java index 1711e491..ba4f8150 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java @@ -1,16 +1,22 @@ package org.ktachibana.cloudemoji.activities; +import android.content.Intent; import android.os.Bundle; +import android.os.Environment; +import android.provider.DocumentsContract; import android.view.View; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; +import androidx.annotation.Nullable; + import com.afollestad.materialdialogs.MaterialDialog; import com.melnykov.fab.FloatingActionButton; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; import org.greenrobot.eventbus.Subscribe; import org.ktachibana.cloudemoji.BaseActivity; import org.ktachibana.cloudemoji.R; @@ -19,11 +25,14 @@ import org.ktachibana.cloudemoji.events.RepositoryBeginEditingEvent; import org.ktachibana.cloudemoji.events.RepositoryDownloadFailedEvent; import org.ktachibana.cloudemoji.events.RepositoryDownloadedEvent; -import org.ktachibana.cloudemoji.events.RepositoryExportedEvent; +import org.ktachibana.cloudemoji.events.RepositoryExportEvent; import org.ktachibana.cloudemoji.events.RepositoryInvalidFormatEvent; import org.ktachibana.cloudemoji.models.disk.Repository; import org.ktachibana.cloudemoji.ui.MultiInputMaterialDialogBuilder; +import org.ktachibana.cloudemoji.utils.SystemUtils; +import java.io.IOException; +import java.io.OutputStream; import java.util.List; import butterknife.Bind; @@ -43,6 +52,10 @@ public class RepositoryManagerActivity extends BaseActivity { FloatingActionButton mFab; private RepositoryListViewAdapter mAdapter; + private static final String EXPORTED_REPO_MIME_TYPE = "application/json"; + private static final int RC_EXPORT_REPOSITORY = 3; + + private String mCurrentExportingJson; @Override public void onCreate(Bundle savedInstanceBundle) { @@ -154,8 +167,41 @@ public void handle(NetworkUnavailableEvent event) { } @Subscribe - public void handle(RepositoryExportedEvent exportedEvent) { - showSnackBar(exportedEvent.getPath()); + public void handle(RepositoryExportEvent exportedEvent) { + Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType(EXPORTED_REPO_MIME_TYPE); + intent.putExtra(Intent.EXTRA_TITLE, exportedEvent.getAlias() + ".json"); + mCurrentExportingJson = exportedEvent.getJson(); + + if (SystemUtils.aboveOreo26()) { + // Optionally, specify a URI for the directory that should be opened in + // the system file picker when your app creates the document. + intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOCUMENTS); + } + + startActivityForResult(intent, RC_EXPORT_REPOSITORY); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + OutputStream os = null; + try { + if (resultCode == RESULT_OK) { + if (requestCode == RC_EXPORT_REPOSITORY) { + os = getContentResolver().openOutputStream(data.getData()); + IOUtils.write(mCurrentExportingJson, os); + showSnackBar("Exported"); + } + } else { + showSnackBar(getString(R.string.fail)); + } + } catch (IOException e) { + showSnackBar(getString(R.string.fail)); + } finally { + IOUtils.closeQuietly(os); + } } @Subscribe diff --git a/app/src/main/java/org/ktachibana/cloudemoji/adapters/RepositoryListViewAdapter.java b/app/src/main/java/org/ktachibana/cloudemoji/adapters/RepositoryListViewAdapter.java index a29ca234..389a9687 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/adapters/RepositoryListViewAdapter.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/adapters/RepositoryListViewAdapter.java @@ -18,14 +18,13 @@ import org.ktachibana.cloudemoji.events.RepositoryBeginEditingEvent; import org.ktachibana.cloudemoji.events.RepositoryDownloadFailedEvent; import org.ktachibana.cloudemoji.events.RepositoryDownloadedEvent; -import org.ktachibana.cloudemoji.events.RepositoryExportedEvent; +import org.ktachibana.cloudemoji.events.RepositoryExportEvent; import org.ktachibana.cloudemoji.models.disk.Repository; import org.ktachibana.cloudemoji.models.memory.Source; import org.ktachibana.cloudemoji.net.RepositoryDownloaderClient; import org.ktachibana.cloudemoji.parsing.SourceJsonParser; import org.ktachibana.cloudemoji.parsing.SourceReader; import org.ktachibana.cloudemoji.ui.NonCancelableProgressMaterialDialogBuilder; -import org.ktachibana.cloudemoji.utils.BackupUtils; import java.io.File; import java.util.List; @@ -33,10 +32,11 @@ import butterknife.Bind; import butterknife.ButterKnife; -public class RepositoryListViewAdapter extends BaseBaseAdapter { +public class RepositoryListViewAdapter extends BaseBaseAdapter implements Constants { private List mRepositories; private Context mContext; + public RepositoryListViewAdapter(Context context) { this.mRepositories = Repository.listAll(Repository.class); this.mContext = context; @@ -132,13 +132,7 @@ public void onClick(View v) { // Parse Source String json = new SourceJsonParser().serialize(source); - // Get file and write - String filePath = String.format(Constants.EXPORT_FILE_PATH, item.getAlias() + ".json"); - File exportFile = new File(filePath); - // TODO -// BackupUtils.writeFileToExternalStorage(json, exportFile); - - mBus.post(new RepositoryExportedEvent(filePath)); + mBus.post(new RepositoryExportEvent(json, item.getAlias())); } catch (Exception e) { Log.e(Constants.DEBUG_TAG, e.getLocalizedMessage()); } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/events/RepositoryExportEvent.java b/app/src/main/java/org/ktachibana/cloudemoji/events/RepositoryExportEvent.java new file mode 100644 index 00000000..1e7e08c5 --- /dev/null +++ b/app/src/main/java/org/ktachibana/cloudemoji/events/RepositoryExportEvent.java @@ -0,0 +1,19 @@ +package org.ktachibana.cloudemoji.events; + +public class RepositoryExportEvent { + private String json; + private String alias; + + public RepositoryExportEvent(String json, String alias) { + this.json = json; + this.alias = alias; + } + + public String getJson() { + return json; + } + + public String getAlias() { + return alias; + } +} diff --git a/app/src/main/java/org/ktachibana/cloudemoji/events/RepositoryExportedEvent.java b/app/src/main/java/org/ktachibana/cloudemoji/events/RepositoryExportedEvent.java deleted file mode 100644 index dbdc48c9..00000000 --- a/app/src/main/java/org/ktachibana/cloudemoji/events/RepositoryExportedEvent.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.ktachibana.cloudemoji.events; - -public class RepositoryExportedEvent { - private String path; - - public RepositoryExportedEvent(String path) { - this.path = path; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } -} diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index e8c17065..494ee571 100755 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -86,4 +86,5 @@ 已将 %d 个收藏从个人词典中撤出 需要通知权限,这样的话您可以从通知面板中快速打开 App 出错辣!请再试一下 + 源已导出 \ 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 56d1622d..7302cf6c 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -87,4 +87,5 @@ Reoke all bookmarks from personal dictionary Revoked %d bookmarks from personal dictionary We need to put a sticky \"quick trigger\" notification so that you can launch Cloud Emoticon conveniently. + Repo exported \ No newline at end of file From 7a5b9bc46476758d0688401adb939bbc5f95e9cf Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Wed, 19 Oct 2022 22:56:41 -0700 Subject: [PATCH 15/31] add two missing snakbars --- .../org/ktachibana/cloudemoji/fragments/PreferenceFragment.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index b8c683a8..626831e4 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -230,9 +230,11 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RC_BACKUP) { os = mContentResolver.openOutputStream(data.getData()); BackupUtils.writeFavorites(os); + showSnackBar(getString(R.string.backed_up_favorites)); } else if (requestCode == RC_RESTORE) { is = mContentResolver.openInputStream(data.getData()); BackupUtils.readFavorites(is); + showSnackBar(getString(R.string.restored_favorites)); } } else { showSnackBar(getString(R.string.fail)); From 2255b9abdd6b86c0763e5fae8921bdfac528f93c Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Wed, 19 Oct 2022 23:22:00 -0700 Subject: [PATCH 16/31] remove personal dict feature for api 23 and above --- app/src/main/AndroidManifest.xml | 2 +- .../org/ktachibana/cloudemoji/Constants.java | 5 +- .../fragments/PreferenceFragment.java | 90 ++++++++++--------- .../utils/PersonalDictionaryUtils.java | 1 - app/src/main/res/xml/preferences.xml | 1 - 5 files changed, 50 insertions(+), 49 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 80eb2d8f..a3bc5b89 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,7 @@ - + diff --git a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java index 680ecc3e..03019971 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java @@ -1,10 +1,7 @@ package org.ktachibana.cloudemoji; -import android.os.Environment; import androidx.annotation.IntDef; -import java.io.File; - public interface Constants { // Notification int QUICK_TRIGGER_NOTIFICATION_ID = 0; @@ -24,8 +21,8 @@ public interface Constants { String PREF_RESTORE_FAV = "pref_restore_fav"; String PREF_IMPORT_PERSONAL_DICT = "pref_import_into_personal_dict"; String PREF_REVOKE_PERSONAL_DICT = "pref_revoke_from_personal_dict"; - String PREF_BEHAVIORS = "pref_behaviors"; String PREF_NOW_ON_TAP = "pref_now_on_tap"; + String PREF_PERSONAL_DICTIONARY = "pref_ime"; // Repository int FORMAT_TYPE_XML = 0; diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index 626831e4..6e2f367c 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -73,36 +73,35 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { addPreferencesFromResource(R.xml.preferences); mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); - // Navbar Gesture Preference navbarGesturePref = findPreference(Constants.PREF_NAVBAR_GESTURE); Preference nowOnTapPref = findPreference(Constants.PREF_NOW_ON_TAP); - PreferenceCategory behaviorsPref = (PreferenceCategory) findPreference(Constants.PREF_BEHAVIORS); - navbarGesturePref.setEnabled(false); - if (!SystemUtils.aboveMarshmallow23()) { - behaviorsPref.removePreference(nowOnTapPref); - } - navbarGesturePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - PackageManager packageManager = mContext.getPackageManager(); - ComponentName componentName = new ComponentName(getActivity(), CLS_ASSIST_ACTIVITY); - int componentState = newValue.equals(true) ? - PackageManager.COMPONENT_ENABLED_STATE_ENABLED : - PackageManager.COMPONENT_ENABLED_STATE_DISABLED; - packageManager.setComponentEnabledSetting(componentName, componentState, - PackageManager.DONT_KILL_APP); - return true; - } - }); - - // Now on Tap if (SystemUtils.aboveMarshmallow23()) { - behaviorsPref.removePreference(navbarGesturePref); + // Now on Tap + navbarGesturePref.setVisible(false); + PackageManager packageManager = mContext.getPackageManager(); ComponentName componentName = new ComponentName(getActivity(), CLS_ASSIST_ACTIVITY); packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + } else { + navbarGesturePref.setVisible(false); + + // Navbar Gesture + navbarGesturePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + PackageManager packageManager = mContext.getPackageManager(); + ComponentName componentName = new ComponentName(getActivity(), CLS_ASSIST_ACTIVITY); + int componentState = newValue.equals(true) ? + PackageManager.COMPONENT_ENABLED_STATE_ENABLED : + PackageManager.COMPONENT_ENABLED_STATE_DISABLED; + packageManager.setComponentEnabledSetting(componentName, componentState, + PackageManager.DONT_KILL_APP); + return true; + } + }); } + nowOnTapPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { @@ -117,27 +116,34 @@ public boolean onPreferenceClick(Preference preference) { } }); - // Import favorites into personal dictionary - Preference importImePref = findPreference(Constants.PREF_IMPORT_PERSONAL_DICT); - importImePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - int numberAdded = PersonalDictionaryUtils.importAllFavorites(mContext.getContentResolver()); - showSnackBar(String.format(getString(R.string.imported_into_personal_dict), numberAdded)); - return true; - } - }); - // Revoke favorite from personal dictionary - Preference revokeImePref = findPreference(Constants.PREF_REVOKE_PERSONAL_DICT); - revokeImePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - int numberRevoked = PersonalDictionaryUtils.revokeAllFavorites(mContext.getContentResolver()); - showSnackBar(String.format(getString(R.string.revoked_from_personal_dict), numberRevoked)); - return true; - } - }); + PreferenceCategory personalDictionaryPref = (PreferenceCategory) findPreference(Constants.PREF_PERSONAL_DICTIONARY); + if (SystemUtils.aboveMarshmallow23()) { + personalDictionaryPref.setVisible(false); + } else { + // Import favorites into personal dictionary + Preference importImePref = findPreference(Constants.PREF_IMPORT_PERSONAL_DICT); + importImePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + int numberAdded = PersonalDictionaryUtils.importAllFavorites(mContext.getContentResolver()); + showSnackBar(String.format(getString(R.string.imported_into_personal_dict), numberAdded)); + return true; + } + }); + + // Revoke favorite from personal dictionary + Preference revokeImePref = findPreference(Constants.PREF_REVOKE_PERSONAL_DICT); + revokeImePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + int numberRevoked = PersonalDictionaryUtils.revokeAllFavorites(mContext.getContentResolver()); + showSnackBar(String.format(getString(R.string.revoked_from_personal_dict), numberRevoked)); + return true; + } + }); + revokeImePref.setEnabled(false); + } // Backup favorites Preference backupPref = findPreference(Constants.PREF_BACKUP_FAV); diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/PersonalDictionaryUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/PersonalDictionaryUtils.java index fc620cd7..d8d782da 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/PersonalDictionaryUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/PersonalDictionaryUtils.java @@ -4,7 +4,6 @@ import android.content.ContentValues; import android.provider.UserDictionary; -import org.ktachibana.cloudemoji.Constants; import org.ktachibana.cloudemoji.models.disk.Favorite; import java.util.List; diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 9c32b378..ec952e50 100755 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -1,7 +1,6 @@ Date: Wed, 19 Oct 2022 23:29:10 -0700 Subject: [PATCH 17/31] Do not repeatly send quick trigger notification if already presents --- .../cloudemoji/utils/NotificationUtils.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index f0db5a3d..80d9bc5c 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -7,6 +7,8 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.service.notification.StatusBarNotification; + import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; @@ -25,6 +27,10 @@ public class NotificationUtils { public static void setupNotificationWithPref(Context context, String notificationVisibility) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + if (doesQuickTriggerNotificationExist(context)) { + return; + } + // Cancel current notification notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); @@ -48,6 +54,22 @@ public static void setupNotificationWithPref(Context context, String notificatio } } + private static boolean doesQuickTriggerNotificationExist(Context context) { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + + if (!SystemUtils.aboveMarshmallow23()) { + return false; + } + + StatusBarNotification[] notifications = notificationManager.getActiveNotifications(); + for (StatusBarNotification notification : notifications) { + if (notification.getId() == Constants.QUICK_TRIGGER_NOTIFICATION_ID) { + return true; + } + } + return false; + } + private static void createQuickTriggerNotificationChannel( Context context, NotificationManager notificationManager, From 7c06e801f9b1b30e4408af9c252825cb97940aef Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Wed, 19 Oct 2022 23:45:17 -0700 Subject: [PATCH 18/31] refactors in NotificationUtils --- .../org/ktachibana/cloudemoji/Constants.java | 4 ++- .../cloudemoji/activities/MainActivity.java | 8 ++--- .../cloudemoji/receivers/BootUpReceiver.java | 9 ++---- .../cloudemoji/utils/NotificationUtils.java | 30 +++++++++++-------- 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java index 03019971..92778abc 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java @@ -5,7 +5,9 @@ public interface Constants { // Notification int QUICK_TRIGGER_NOTIFICATION_ID = 0; - String QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY = "both"; + String QUICK_TRIGGER_NOTIFICATION_VISIBILITY_BOTH = "both"; + String QUICK_TRIGGER_NOTIFICATION_VISIBILITY_NO = "no"; + String QUICK_TRIGGER_NOTIFICATION_VISIBILITY_PANEL = "panel"; String QUICK_TRIGGER_NOTIFICATION_CHANNEL_ID = "quick_trigger"; // Preferences diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java index 5b6de22a..22784036 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java @@ -125,21 +125,17 @@ private LinkedHashMap initializeSourceCache() { @AfterPermissionGranted(RC_POST_NOTIFICATIONS) private void setupNotification() { if (!SystemUtils.aboveTiramisu33()) { - _setupNotification(); + NotificationUtils.setupNotification(this); return; } String[] perms = {Manifest.permission.POST_NOTIFICATIONS}; if (EasyPermissions.hasPermissions(this, perms)) { - _setupNotification(); + NotificationUtils.setupNotification(this); } else { EasyPermissions.requestPermissions(this, getString(R.string.notification_rationale), RC_POST_NOTIFICATIONS, perms); } } - private void _setupNotification() { - NotificationUtils.setupNotificationWithPref(this, mPreferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY)); - } - @Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { if (Constants.PREF_NOTIFICATION_VISIBILITY.equals(key)) { diff --git a/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java b/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java index e3d22fc2..1aaa3549 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java @@ -31,18 +31,13 @@ public void onReceive(Context context, Intent intent) { return; } - String notificationVisibility = preferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_DEFAULT_VISIBILITY); if (!SystemUtils.aboveTiramisu33()) { - _setupNotification(context, notificationVisibility); + NotificationUtils.setupNotification(context); return; } String[] perms = {Manifest.permission.POST_NOTIFICATIONS}; if (EasyPermissions.hasPermissions(context, perms)) { - _setupNotification(context, notificationVisibility); + NotificationUtils.setupNotification(context); } } - - private void _setupNotification(Context context, String notificationVisibility) { - NotificationUtils.setupNotificationWithPref(context, notificationVisibility); - } } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index 80d9bc5c..baa9a562 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -7,6 +7,8 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; import android.service.notification.StatusBarNotification; import androidx.core.app.NotificationCompat; @@ -19,35 +21,37 @@ /** * Abstract Notification codes from MainActivity to be shared among MainActivity and BootUpReceiver */ -public class NotificationUtils { - +public class NotificationUtils implements Constants { /** * Setup notification with user preference */ - public static void setupNotificationWithPref(Context context, String notificationVisibility) { + public static void setupNotification(Context context) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - if (doesQuickTriggerNotificationExist(context)) { - return; - } - - // Cancel current notification - notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); - + String notificationVisibility = preferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_VISIBILITY_BOTH); switch (notificationVisibility) { - case "no": + case QUICK_TRIGGER_NOTIFICATION_VISIBILITY_NO: // If not showing notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); break; - case "panel": + case QUICK_TRIGGER_NOTIFICATION_VISIBILITY_PANEL: // If only shows in panel + if (doesQuickTriggerNotificationExist(context)) { + break; + } + notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); createQuickTriggerNotificationChannel(context, notificationManager, NotificationManagerCompat.IMPORTANCE_MIN); showQuickTriggerNotification(context, notificationManager, NotificationCompat.PRIORITY_MIN); break; - case "both": + case QUICK_TRIGGER_NOTIFICATION_VISIBILITY_BOTH: // If shows on both panel and status bar + if (doesQuickTriggerNotificationExist(context)) { + break; + } + notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); createQuickTriggerNotificationChannel(context, notificationManager, NotificationManagerCompat.IMPORTANCE_DEFAULT); showQuickTriggerNotification(context, notificationManager, NotificationCompat.PRIORITY_DEFAULT); break; From b9d62a6b89f383e826b8f6b59bfceff5a83cc2dc Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Wed, 19 Oct 2022 23:49:28 -0700 Subject: [PATCH 19/31] refactors in NotificationUtils --- .../cloudemoji/utils/NotificationUtils.java | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index baa9a562..3efe34b3 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -26,38 +26,49 @@ public class NotificationUtils implements Constants { * Setup notification with user preference */ public static void setupNotification(Context context) { - NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); String notificationVisibility = preferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_VISIBILITY_BOTH); switch (notificationVisibility) { case QUICK_TRIGGER_NOTIFICATION_VISIBILITY_NO: - // If not showing - notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); + setupLegacyVisibilityNo(context); break; case QUICK_TRIGGER_NOTIFICATION_VISIBILITY_PANEL: - // If only shows in panel - if (doesQuickTriggerNotificationExist(context)) { - break; - } - notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); - createQuickTriggerNotificationChannel(context, notificationManager, NotificationManagerCompat.IMPORTANCE_MIN); - showQuickTriggerNotification(context, notificationManager, NotificationCompat.PRIORITY_MIN); + setupLegacyVisibilityPanel(context); break; case QUICK_TRIGGER_NOTIFICATION_VISIBILITY_BOTH: - // If shows on both panel and status bar - if (doesQuickTriggerNotificationExist(context)) { - break; - } - notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); - createQuickTriggerNotificationChannel(context, notificationManager, NotificationManagerCompat.IMPORTANCE_DEFAULT); - showQuickTriggerNotification(context, notificationManager, NotificationCompat.PRIORITY_DEFAULT); + setupLegacyVisibilityBoth(context); break; } } + private static void setupLegacyVisibilityNo(Context context) { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); + } + + private static void setupLegacyVisibilityPanel(Context context) { + if (doesQuickTriggerNotificationExist(context)) { + return; + } + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); + createQuickTriggerNotificationChannel(context, NotificationManagerCompat.IMPORTANCE_MIN); + showQuickTriggerNotification(context, NotificationCompat.PRIORITY_MIN); + } + + private static void setupLegacyVisibilityBoth(Context context) { + if (doesQuickTriggerNotificationExist(context)) { + return; + } + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(Constants.QUICK_TRIGGER_NOTIFICATION_ID); + createQuickTriggerNotificationChannel(context, NotificationManagerCompat.IMPORTANCE_DEFAULT); + showQuickTriggerNotification(context, NotificationCompat.PRIORITY_DEFAULT); + } + private static boolean doesQuickTriggerNotificationExist(Context context) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); @@ -76,7 +87,6 @@ private static boolean doesQuickTriggerNotificationExist(Context context) { private static void createQuickTriggerNotificationChannel( Context context, - NotificationManager notificationManager, int importance ) { if (SystemUtils.aboveOreo26()) { @@ -87,6 +97,7 @@ private static void createQuickTriggerNotificationChannel( ); channel.setDescription(context.getString(R.string.quick_trigger_notification_channel_description)); channel.setShowBadge(false); + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel); } } @@ -94,7 +105,6 @@ private static void createQuickTriggerNotificationChannel( @SuppressLint("UnspecifiedImmutableFlag") private static void showQuickTriggerNotification( Context context, - NotificationManager notificationManager, int priority ) { String title = context.getString(R.string.app_name); @@ -118,6 +128,7 @@ private static void showQuickTriggerNotification( .setChannelId(Constants.QUICK_TRIGGER_NOTIFICATION_CHANNEL_ID) .build(); notification.flags = Notification.FLAG_NO_CLEAR; + NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(Constants.QUICK_TRIGGER_NOTIFICATION_ID, notification); } } \ No newline at end of file From 02e456f29e29cc4aab92aa39f102ac46d261707f Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Wed, 19 Oct 2022 23:56:08 -0700 Subject: [PATCH 20/31] renames --- .../main/java/org/ktachibana/cloudemoji/Constants.java | 8 ++++---- .../ktachibana/cloudemoji/activities/MainActivity.java | 2 +- .../ktachibana/cloudemoji/utils/NotificationUtils.java | 8 ++++---- app/src/main/res/values-zh/strings.xml | 4 ++-- app/src/main/res/values/strings.xml | 4 ++-- app/src/main/res/xml/preferences.xml | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java index 92778abc..4419eb0e 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java @@ -5,14 +5,14 @@ public interface Constants { // Notification int QUICK_TRIGGER_NOTIFICATION_ID = 0; - String QUICK_TRIGGER_NOTIFICATION_VISIBILITY_BOTH = "both"; - String QUICK_TRIGGER_NOTIFICATION_VISIBILITY_NO = "no"; - String QUICK_TRIGGER_NOTIFICATION_VISIBILITY_PANEL = "panel"; String QUICK_TRIGGER_NOTIFICATION_CHANNEL_ID = "quick_trigger"; // Preferences String PREF_CLOSE_AFTER_COPY = "pref_close_after_copy"; - String PREF_NOTIFICATION_VISIBILITY = "pref_notification_visibility"; + String PREF_NOTIFICATION_LEGACY_VISIBILITY = "pref_notification_legacy_visibility"; + String QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_BOTH = "both"; + String QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_NO = "no"; + String QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_PANEL = "panel"; String PREF_SHOW_AFTER_BOOT_UP = "pref_show_after_boot_up"; String PREF_VERSION = "pref_version"; String PREF_GIT_HUB_RELEASE = "pref_git_hub_release"; diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java index 22784036..a211fa93 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java @@ -138,7 +138,7 @@ private void setupNotification() { @Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { - if (Constants.PREF_NOTIFICATION_VISIBILITY.equals(key)) { + if (Constants.PREF_NOTIFICATION_LEGACY_VISIBILITY.equals(key)) { setupNotification(); } } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index 3efe34b3..bf978f30 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -28,17 +28,17 @@ public class NotificationUtils implements Constants { public static void setupNotification(Context context) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - String notificationVisibility = preferences.getString(Constants.PREF_NOTIFICATION_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_VISIBILITY_BOTH); + String notificationVisibility = preferences.getString(Constants.PREF_NOTIFICATION_LEGACY_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_BOTH); switch (notificationVisibility) { - case QUICK_TRIGGER_NOTIFICATION_VISIBILITY_NO: + case QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_NO: setupLegacyVisibilityNo(context); break; - case QUICK_TRIGGER_NOTIFICATION_VISIBILITY_PANEL: + case QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_PANEL: setupLegacyVisibilityPanel(context); break; - case QUICK_TRIGGER_NOTIFICATION_VISIBILITY_BOTH: + case QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_BOTH: setupLegacyVisibilityBoth(context); break; } diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 494ee571..79d095ad 100755 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -55,9 +55,9 @@ 去 Play Store 看看 没找到 - + 不显示 - 只在通知面板里显示(Android 3.0 以下及 8.0 以上无效) + 只在通知面板里显示 同时在通知面板和状态栏里显示 个人词典 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7302cf6c..079c0b5b 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -57,9 +57,9 @@ Go to Play Store Result not found - + Don\'t show - Only in notification panel (Only works from Android 3.0 to 7.0) + Only in notification panel Both in notification panel and status bar Personal dictionary diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index ec952e50..3dbacf38 100755 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -4,9 +4,9 @@ android:title="@string/behaviors"> Date: Thu, 20 Oct 2022 00:02:10 -0700 Subject: [PATCH 21/31] strings --- app/src/main/res/values-zh/strings.xml | 9 +++++---- app/src/main/res/values/strings.xml | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 79d095ad..119d68cd 100755 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -19,7 +19,7 @@ 添加到收藏 已添加到收藏 已从收藏中移除 - 通知可见性 + 快捷启动通知的可见性 启动后显示通知 颜文字 描述 @@ -78,13 +78,14 @@ 想要贡献源吗? 这需要最基础的 GitHub, JSON 以及编程知识。你确定要继续吗? 继续 - 快速打开 - 从通知面板中快速打开 App + 快捷启动通知 + 从通知面板中打开 App 云颜文字输入法 没有收藏 将全部收藏从个人词典中撤出 已将 %d 个收藏从个人词典中撤出 - 需要通知权限,这样的话您可以从通知面板中快速打开 App + 需要通知权限,这样的话您可以从通知面板中打开 App 出错辣!请再试一下 源已导出 + 启用快捷启动通知 \ 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 079c0b5b..473409dd 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,8 +21,8 @@ Add to bookmarks Added to bookmarks Removed from bookmarks - Notification visibility - Show notification after boot-up + Quick trigger notification visibility + Show quick trigger notification after boot-up Emoticon Description Edit Repository @@ -81,11 +81,12 @@ It is assumed that you have some minimal knowledge on GitHub, JSON and programming. Do you still want to proceed? Proceed Quick trigger - Quickly trigger the app from notification pannel + Quickly trigger the app from notification panel Cloud Emoticon IME No bookmark Reoke all bookmarks from personal dictionary Revoked %d bookmarks from personal dictionary We need to put a sticky \"quick trigger\" notification so that you can launch Cloud Emoticon conveniently. Repo exported + Show quick trigger notification \ No newline at end of file From 4e350a597cf3be8d580c7f7f6711f37f1f7027b3 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Thu, 20 Oct 2022 00:15:31 -0700 Subject: [PATCH 22/31] different settings for nougat and above --- app/build.gradle | 4 + .../org/ktachibana/cloudemoji/Constants.java | 1 + .../cloudemoji/activities/MainActivity.java | 2 +- .../fragments/PreferenceFragment.java | 119 ++++++++---------- .../cloudemoji/receivers/BootUpReceiver.java | 2 +- .../cloudemoji/utils/NotificationUtils.java | 32 +++-- .../cloudemoji/utils/SystemUtils.java | 8 +- app/src/main/res/xml/preferences.xml | 4 + 8 files changed, 91 insertions(+), 81 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 21f15313..3509cb6b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,6 +39,10 @@ android { zipAlignEnabled true } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { diff --git a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java index 4419eb0e..d4d396b2 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/Constants.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/Constants.java @@ -25,6 +25,7 @@ public interface Constants { String PREF_REVOKE_PERSONAL_DICT = "pref_revoke_from_personal_dict"; String PREF_NOW_ON_TAP = "pref_now_on_tap"; String PREF_PERSONAL_DICTIONARY = "pref_ime"; + String PREF_SHOW_NOTIFICATION = "pref_show_notification"; // Repository int FORMAT_TYPE_XML = 0; diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java index a211fa93..561715fc 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java @@ -124,7 +124,7 @@ private LinkedHashMap initializeSourceCache() { @AfterPermissionGranted(RC_POST_NOTIFICATIONS) private void setupNotification() { - if (!SystemUtils.aboveTiramisu33()) { + if (SystemUtils.belowTiramisu33()) { NotificationUtils.setupNotification(this); return; } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index 6e2f367c..017f4c43 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -73,12 +73,21 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { addPreferencesFromResource(R.xml.preferences); mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); + // Setup notification settings + Preference notificationLegacyVisibilityPref = findPreference(Constants.PREF_NOTIFICATION_LEGACY_VISIBILITY); + Preference showNotificationPref = findPreference(Constants.PREF_SHOW_NOTIFICATION); + if (SystemUtils.aboveNougat24()) { + notificationLegacyVisibilityPref.setVisible(false); + } else { + showNotificationPref.setVisible(false); + } + Preference navbarGesturePref = findPreference(Constants.PREF_NAVBAR_GESTURE); Preference nowOnTapPref = findPreference(Constants.PREF_NOW_ON_TAP); if (SystemUtils.aboveMarshmallow23()) { - // Now on Tap navbarGesturePref.setVisible(false); + // Now on Tap PackageManager packageManager = mContext.getPackageManager(); ComponentName componentName = new ComponentName(getActivity(), CLS_ASSIST_ACTIVITY); packageManager.setComponentEnabledSetting(componentName, @@ -87,33 +96,27 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { navbarGesturePref.setVisible(false); // Navbar Gesture - navbarGesturePref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - PackageManager packageManager = mContext.getPackageManager(); - ComponentName componentName = new ComponentName(getActivity(), CLS_ASSIST_ACTIVITY); - int componentState = newValue.equals(true) ? - PackageManager.COMPONENT_ENABLED_STATE_ENABLED : - PackageManager.COMPONENT_ENABLED_STATE_DISABLED; - packageManager.setComponentEnabledSetting(componentName, componentState, - PackageManager.DONT_KILL_APP); - return true; - } + navbarGesturePref.setOnPreferenceChangeListener((preference, newValue) -> { + PackageManager packageManager = mContext.getPackageManager(); + ComponentName componentName = new ComponentName(getActivity(), CLS_ASSIST_ACTIVITY); + int componentState = newValue.equals(true) ? + PackageManager.COMPONENT_ENABLED_STATE_ENABLED : + PackageManager.COMPONENT_ENABLED_STATE_DISABLED; + packageManager.setComponentEnabledSetting(componentName, componentState, + PackageManager.DONT_KILL_APP); + return true; }); } - nowOnTapPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - Intent intent = new Intent(); - // Didn't found it in android.provider.Settings... Just hardcoded it. - ComponentName componentName = new ComponentName( - Constants.PACKAGE_NAME_ANDROID_SETTINGS, - Constants.CLASS_NAME_MANAGE_ASSIST_ACTIVITY); - intent.setComponent(componentName); - startActivity(intent); - return true; - } + nowOnTapPref.setOnPreferenceClickListener(preference -> { + Intent intent = new Intent(); + // Didn't found it in android.provider.Settings... Just hardcoded it. + ComponentName componentName = new ComponentName( + Constants.PACKAGE_NAME_ANDROID_SETTINGS, + Constants.CLASS_NAME_MANAGE_ASSIST_ACTIVITY); + intent.setComponent(componentName); + startActivity(intent); + return true; }); @@ -123,70 +126,52 @@ public boolean onPreferenceClick(Preference preference) { } else { // Import favorites into personal dictionary Preference importImePref = findPreference(Constants.PREF_IMPORT_PERSONAL_DICT); - importImePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - int numberAdded = PersonalDictionaryUtils.importAllFavorites(mContext.getContentResolver()); - showSnackBar(String.format(getString(R.string.imported_into_personal_dict), numberAdded)); - return true; - } + importImePref.setOnPreferenceClickListener(preference -> { + int numberAdded = PersonalDictionaryUtils.importAllFavorites(mContext.getContentResolver()); + showSnackBar(String.format(getString(R.string.imported_into_personal_dict), numberAdded)); + return true; }); // Revoke favorite from personal dictionary Preference revokeImePref = findPreference(Constants.PREF_REVOKE_PERSONAL_DICT); - revokeImePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - int numberRevoked = PersonalDictionaryUtils.revokeAllFavorites(mContext.getContentResolver()); - showSnackBar(String.format(getString(R.string.revoked_from_personal_dict), numberRevoked)); - return true; - } + revokeImePref.setOnPreferenceClickListener(preference -> { + int numberRevoked = PersonalDictionaryUtils.revokeAllFavorites(mContext.getContentResolver()); + showSnackBar(String.format(getString(R.string.revoked_from_personal_dict), numberRevoked)); + return true; }); revokeImePref.setEnabled(false); } // Backup favorites Preference backupPref = findPreference(Constants.PREF_BACKUP_FAV); - backupPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - backupFavorites(); - return true; - } + backupPref.setOnPreferenceClickListener(preference -> { + backupFavorites(); + return true; }); // Restore favorites Preference restorePref = findPreference(Constants.PREF_RESTORE_FAV); - restorePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - restoreFavorites(); - return true; - } + restorePref.setOnPreferenceClickListener(preference -> { + restoreFavorites(); + return true; }); // GitHub Release Preference gitHubReleasePref = findPreference(Constants.PREF_GIT_HUB_RELEASE); - gitHubReleasePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - Intent intent = new Intent(); - intent.setData(Uri.parse(Constants.GIT_HUB_RELEASE_URL)); - startActivity(intent); - return true; - } + gitHubReleasePref.setOnPreferenceClickListener(preference -> { + Intent intent = new Intent(); + intent.setData(Uri.parse(Constants.GIT_HUB_RELEASE_URL)); + startActivity(intent); + return true; }); // GitHub Repo Preference gitHubRepoPref = findPreference(Constants.PREF_GIT_HUB_REPO); - gitHubRepoPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - Intent intent = new Intent(); - intent.setData(Uri.parse(Constants.GIT_HUB_REPO_URL)); - startActivity(intent); - return true; - } + gitHubRepoPref.setOnPreferenceClickListener(preference -> { + Intent intent = new Intent(); + intent.setData(Uri.parse(Constants.GIT_HUB_REPO_URL)); + startActivity(intent); + return true; }); // Version diff --git a/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java b/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java index 1aaa3549..4d55704b 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java @@ -31,7 +31,7 @@ public void onReceive(Context context, Intent intent) { return; } - if (!SystemUtils.aboveTiramisu33()) { + if (SystemUtils.belowTiramisu33()) { NotificationUtils.setupNotification(context); return; } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index bf978f30..945c5754 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -28,19 +28,31 @@ public class NotificationUtils implements Constants { public static void setupNotification(Context context) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - String notificationVisibility = preferences.getString(Constants.PREF_NOTIFICATION_LEGACY_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_BOTH); - switch (notificationVisibility) { - case QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_NO: + if (SystemUtils.aboveNougat24()) { + boolean visible = preferences.getBoolean(Constants.PREF_SHOW_NOTIFICATION, true); + if (visible) { + setupLegacyVisibilityBoth(context); + } else { setupLegacyVisibilityNo(context); - break; + } + } else { + String legacyVisibility = preferences.getString( + Constants.PREF_NOTIFICATION_LEGACY_VISIBILITY, + Constants.QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_BOTH + ); + switch (legacyVisibility) { + case QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_NO: + setupLegacyVisibilityNo(context); + break; - case QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_PANEL: - setupLegacyVisibilityPanel(context); - break; + case QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_PANEL: + setupLegacyVisibilityPanel(context); + break; - case QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_BOTH: - setupLegacyVisibilityBoth(context); - break; + case QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_BOTH: + setupLegacyVisibilityBoth(context); + break; + } } } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java index 768f030a..176117b2 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java @@ -24,6 +24,10 @@ public static boolean aboveMarshmallow23() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; } + public static boolean aboveNougat24() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; + } + public static boolean aboveOreo26() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; } @@ -32,7 +36,7 @@ public static boolean aboveS31() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S; } - public static boolean aboveTiramisu33() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU; + public static boolean belowTiramisu33() { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU; } } diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 3dbacf38..f0637aa4 100755 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -8,6 +8,10 @@ android:entryValues="@array/notification_options_alias" android:key="pref_notification_legacy_visibility" android:title="@string/notification_visibility" /> + Date: Thu, 20 Oct 2022 00:44:50 -0700 Subject: [PATCH 23/31] show after boot up cannot be true if show notif is false --- .../fragments/PreferenceFragment.java | 50 +++++++++++++++++++ app/src/main/res/values-zh/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index 017f4c43..a50c4781 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -14,6 +14,8 @@ import android.preference.PreferenceManager; import android.provider.DocumentsContract; +import androidx.preference.CheckBoxPreference; +import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceFragmentCompat; @@ -33,6 +35,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Optional; public class PreferenceFragment extends PreferenceFragmentCompat { @@ -74,14 +77,25 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); // Setup notification settings + syncShowAfterBootUpToNotificationVisibility(null); Preference notificationLegacyVisibilityPref = findPreference(Constants.PREF_NOTIFICATION_LEGACY_VISIBILITY); Preference showNotificationPref = findPreference(Constants.PREF_SHOW_NOTIFICATION); if (SystemUtils.aboveNougat24()) { notificationLegacyVisibilityPref.setVisible(false); + showNotificationPref.setOnPreferenceChangeListener((preference, newValue) -> { + syncShowAfterBootUpToNotificationVisibility(newValue); + return true; + }); + } else { showNotificationPref.setVisible(false); + notificationLegacyVisibilityPref.setOnPreferenceChangeListener((preference, newValue) -> { + syncShowAfterBootUpToNotificationVisibility(newValue); + return true; + }); } + // Now on Tap or Navbar Gesture Preference navbarGesturePref = findPreference(Constants.PREF_NAVBAR_GESTURE); Preference nowOnTapPref = findPreference(Constants.PREF_NOW_ON_TAP); if (SystemUtils.aboveMarshmallow23()) { @@ -182,6 +196,42 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { versionPref.setSummary(getString(R.string.version_code) + " " + versionCode); } + private void syncShowAfterBootUpToNotificationVisibility(Object newVisibleOrVisibility) { + CheckBoxPreference showAfterBootUpPref = (CheckBoxPreference) findPreference(Constants.PREF_SHOW_AFTER_BOOT_UP); + + if (SystemUtils.aboveNougat24()) { + CheckBoxPreference showNotificationPref = (CheckBoxPreference) findPreference(Constants.PREF_SHOW_NOTIFICATION); + boolean visible = showNotificationPref.isChecked(); + if (newVisibleOrVisibility != null) { + visible = (boolean) newVisibleOrVisibility; + } + if (!visible) { + SharedPreferences.Editor edit = mPreferences.edit(); + edit.putBoolean(Constants.PREF_SHOW_AFTER_BOOT_UP, false); + edit.apply(); + showAfterBootUpPref.setChecked(false); + showAfterBootUpPref.setEnabled(false); + } else { + showAfterBootUpPref.setEnabled(true); + } + } else { + ListPreference notificationLegacyVisibilityPref = (ListPreference) findPreference(Constants.PREF_NOTIFICATION_LEGACY_VISIBILITY); + String visibility = notificationLegacyVisibilityPref.getValue(); + if (newVisibleOrVisibility != null) { + visibility = (String) newVisibleOrVisibility; + } + if (Constants.QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_NO.equals(visibility)) { + SharedPreferences.Editor edit = mPreferences.edit(); + edit.putBoolean(Constants.PREF_PERSONAL_DICTIONARY, false); + edit.apply(); + showAfterBootUpPref.setChecked(false); + showAfterBootUpPref.setEnabled(false); + } else { + showAfterBootUpPref.setEnabled(true); + } + } + } + void backupFavorites() { Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 119d68cd..2210887e 100755 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -20,7 +20,7 @@ 已添加到收藏 已从收藏中移除 快捷启动通知的可见性 - 启动后显示通知 + 启动后显示 颜文字 描述 编辑源 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 473409dd..f6325191 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -22,7 +22,7 @@ Added to bookmarks Removed from bookmarks Quick trigger notification visibility - Show quick trigger notification after boot-up + Show it after boot-up Emoticon Description Edit Repository From 4fdc167d4cdb06a18c6707089ddfd3bde4dc2bc3 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Thu, 20 Oct 2022 00:50:27 -0700 Subject: [PATCH 24/31] immediately setup notification after pref change --- .../cloudemoji/activities/MainActivity.java | 25 +++---------------- .../fragments/PreferenceFragment.java | 4 ++- .../cloudemoji/receivers/BootUpReceiver.java | 4 +-- .../cloudemoji/utils/NotificationUtils.java | 8 +++++- 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java index 561715fc..28ded806 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java @@ -55,7 +55,7 @@ import pub.devrel.easypermissions.AfterPermissionGranted; import pub.devrel.easypermissions.EasyPermissions; -public class MainActivity extends BaseActivity implements SharedPreferences.OnSharedPreferenceChangeListener { +public class MainActivity extends BaseActivity { public static final String SOURCE_CACHE_TAG = "sourceCache"; private static final String CURRENT_ITEM_TAG = "currentItem"; private LinkedHashMap sourceCache; @@ -125,36 +125,17 @@ private LinkedHashMap initializeSourceCache() { @AfterPermissionGranted(RC_POST_NOTIFICATIONS) private void setupNotification() { if (SystemUtils.belowTiramisu33()) { - NotificationUtils.setupNotification(this); + NotificationUtils.setupNotification(this, null); return; } String[] perms = {Manifest.permission.POST_NOTIFICATIONS}; if (EasyPermissions.hasPermissions(this, perms)) { - NotificationUtils.setupNotification(this); + NotificationUtils.setupNotification(this, null); } else { EasyPermissions.requestPermissions(this, getString(R.string.notification_rationale), RC_POST_NOTIFICATIONS, perms); } } - @Override - public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { - if (Constants.PREF_NOTIFICATION_LEGACY_VISIBILITY.equals(key)) { - setupNotification(); - } - } - - @Override - protected void onResumeFragments() { - super.onResumeFragments(); - mPreferences.unregisterOnSharedPreferenceChangeListener(this); - } - - @Override - protected void onPause() { - super.onPause(); - mPreferences.registerOnSharedPreferenceChangeListener(this); - } - @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index a50c4781..4062ddf7 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -29,13 +29,13 @@ import org.ktachibana.cloudemoji.events.EmptyEvent; import org.ktachibana.cloudemoji.events.ShowSnackBarOnBaseActivityEvent; import org.ktachibana.cloudemoji.utils.BackupUtils; +import org.ktachibana.cloudemoji.utils.NotificationUtils; import org.ktachibana.cloudemoji.utils.PersonalDictionaryUtils; import org.ktachibana.cloudemoji.utils.SystemUtils; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.Optional; public class PreferenceFragment extends PreferenceFragmentCompat { @@ -84,6 +84,7 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { notificationLegacyVisibilityPref.setVisible(false); showNotificationPref.setOnPreferenceChangeListener((preference, newValue) -> { syncShowAfterBootUpToNotificationVisibility(newValue); + NotificationUtils.setupNotification(mContext, newValue); return true; }); @@ -91,6 +92,7 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { showNotificationPref.setVisible(false); notificationLegacyVisibilityPref.setOnPreferenceChangeListener((preference, newValue) -> { syncShowAfterBootUpToNotificationVisibility(newValue); + NotificationUtils.setupNotification(mContext, newValue); return true; }); } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java b/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java index 4d55704b..4c629199 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java @@ -32,12 +32,12 @@ public void onReceive(Context context, Intent intent) { } if (SystemUtils.belowTiramisu33()) { - NotificationUtils.setupNotification(context); + NotificationUtils.setupNotification(context, null); return; } String[] perms = {Manifest.permission.POST_NOTIFICATIONS}; if (EasyPermissions.hasPermissions(context, perms)) { - NotificationUtils.setupNotification(context); + NotificationUtils.setupNotification(context, null); } } } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index 945c5754..ac7e9b9e 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -25,11 +25,14 @@ public class NotificationUtils implements Constants { /** * Setup notification with user preference */ - public static void setupNotification(Context context) { + public static void setupNotification(Context context, Object newVisibleOrVisibility) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); if (SystemUtils.aboveNougat24()) { boolean visible = preferences.getBoolean(Constants.PREF_SHOW_NOTIFICATION, true); + if (newVisibleOrVisibility != null) { + visible = (boolean) newVisibleOrVisibility; + } if (visible) { setupLegacyVisibilityBoth(context); } else { @@ -40,6 +43,9 @@ public static void setupNotification(Context context) { Constants.PREF_NOTIFICATION_LEGACY_VISIBILITY, Constants.QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_BOTH ); + if (newVisibleOrVisibility != null) { + legacyVisibility = (String) newVisibleOrVisibility; + } switch (legacyVisibility) { case QUICK_TRIGGER_NOTIFICATION_LEGACY_VISIBILITY_NO: setupLegacyVisibilityNo(context); From c81177c2862e630938c435affe68f0d30f2bb9c0 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Thu, 20 Oct 2022 00:54:02 -0700 Subject: [PATCH 25/31] comments and version bump --- app/build.gradle | 2 +- .../cloudemoji/fragments/PreferenceFragment.java | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 3509cb6b..d8e67294 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,7 +7,7 @@ android { minSdkVersion 19 targetSdkVersion 33 versionCode 33 - versionName '1.3.2' + versionName '1.4' } // conditionally load keystore.properties and configure release signing config diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index 4062ddf7..76ff7fc0 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -198,6 +198,17 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { versionPref.setSummary(getString(R.string.version_code) + " " + versionCode); } + /** + * This method sync the state of "show it after boot-up" preference + * to the state of "show notification"/"notification visibility" preference + * + * e.g. if "show notification"/"notification visibility" is false or no + * "show it after boot-up" cannot be true + * hence we programmatically set it to false, and disable it + * otherwise, we enable the "show it after boot-up" preference + * + * @param newVisibleOrVisibility + */ private void syncShowAfterBootUpToNotificationVisibility(Object newVisibleOrVisibility) { CheckBoxPreference showAfterBootUpPref = (CheckBoxPreference) findPreference(Constants.PREF_SHOW_AFTER_BOOT_UP); From a68c335784ac27e97f126ecc411c10e26491df97 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Thu, 20 Oct 2022 01:20:57 -0700 Subject: [PATCH 26/31] do not show shortcut related ui if not capable --- .../adapters/FavoriteListViewAdapter.java | 18 ++- .../fragments/FavoriteFragment.java | 104 ++++++++---------- .../ui/MultiInputMaterialDialogBuilder.java | 12 ++ 3 files changed, 71 insertions(+), 63 deletions(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/adapters/FavoriteListViewAdapter.java b/app/src/main/java/org/ktachibana/cloudemoji/adapters/FavoriteListViewAdapter.java index 070b2050..64322c05 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/adapters/FavoriteListViewAdapter.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/adapters/FavoriteListViewAdapter.java @@ -15,6 +15,7 @@ import org.ktachibana.cloudemoji.events.FavoriteDeletedEvent; import org.ktachibana.cloudemoji.models.disk.Favorite; import org.ktachibana.cloudemoji.ui.ScrollableEmoticonMaterialDialogBuilder; +import org.ktachibana.cloudemoji.utils.SystemUtils; import java.util.List; @@ -63,7 +64,7 @@ public View getView(int i, View view, ViewGroup viewGroup) { // Setup contents viewHolder.emoticon.setText(favorite.getEmoticon()); - if (favorite.getDescription().equals("") && favorite.getShortcut().equals("")) { + if (favorite.getDescription().equals("") && (SystemUtils.aboveMarshmallow23() || favorite.getShortcut().equals(""))) { viewHolder.description.setVisibility(View.GONE); } else { viewHolder.description.setVisibility(View.VISIBLE); @@ -71,11 +72,16 @@ public View getView(int i, View view, ViewGroup viewGroup) { favorite.getDescription().equals("") ? "(" + mContext.getString(R.string.no_description) + ")" : favorite.getDescription(); - String shortcutText = - favorite.getShortcut().equals("") - ? "(" + mContext.getString(R.string.no_shortcut) + ")" - : favorite.getShortcut(); - viewHolder.description.setText(descriptionText + " -> " + shortcutText); + + if (SystemUtils.aboveMarshmallow23()) { + viewHolder.description.setText(descriptionText); + } else { + String shortcutText = + favorite.getShortcut().equals("") + ? "(" + mContext.getString(R.string.no_shortcut) + ")" + : favorite.getShortcut(); + viewHolder.description.setText(descriptionText + " -> " + shortcutText); + } } viewHolder.star.setOnClickListener(new View.OnClickListener() { @Override diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/FavoriteFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/FavoriteFragment.java index 4747062b..9b285300 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/FavoriteFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/FavoriteFragment.java @@ -1,15 +1,14 @@ package org.ktachibana.cloudemoji.fragments; +import android.content.Context; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; import android.widget.RelativeLayout; import android.widget.TextView; -import com.afollestad.materialdialogs.MaterialDialog; import com.melnykov.fab.FloatingActionButton; import com.mobeta.android.dslv.DragSortListView; @@ -24,6 +23,7 @@ import org.ktachibana.cloudemoji.models.disk.Favorite; import org.ktachibana.cloudemoji.models.memory.Entry; import org.ktachibana.cloudemoji.ui.MultiInputMaterialDialogBuilder; +import org.ktachibana.cloudemoji.utils.SystemUtils; import java.util.List; @@ -44,11 +44,18 @@ public class FavoriteFragment extends BaseFragment { FloatingActionButton mFab; FavoriteListViewAdapter mAdapter; + private Context mContext; public FavoriteFragment() { // Required empty public constructor } + @Override + public void onAttach(Context context) { + super.onAttach(context); + mContext = context; + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -63,59 +70,45 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, mFavoriteListView .setAdapter(mAdapter); mFavoriteListView - .setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView adapterView, View view, int i, long l) { - Favorite favorite = (Favorite) mAdapter.getItem(i); - Entry entry = new Entry(favorite.getEmoticon(), favorite.getDescription()); - mBus.post(new EntryAddedToHistoryEvent(entry)); - } + .setOnItemClickListener((adapterView, view, i, l) -> { + Favorite favorite = (Favorite) mAdapter.getItem(i); + Entry entry = new Entry(favorite.getEmoticon(), favorite.getDescription()); + mBus.post(new EntryAddedToHistoryEvent(entry)); }); mFab.setImageDrawable(this.getResources().getDrawable(R.drawable.ic_fab_create)); mFab.attachToListView(mFavoriteListView); - mFab.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - popupAddFavoriteDialog(); - } - }); + mFab.setOnClickListener(v -> popupAddFavoriteDialog()); return rootView; } private void popupAddFavoriteDialog() { - new MultiInputMaterialDialogBuilder(getActivity()) - .addInput(null, getString(R.string.emoticon), new MultiInputMaterialDialogBuilder.InputValidator() { - @Override - public CharSequence validate(CharSequence input) { - if (TextUtils.isEmpty(input)) { - return getString(R.string.empty_emoticon); - } else { - List favorites = Favorite.listAll(Favorite.class); - for (Favorite favorite : favorites) { - if (TextUtils.equals(favorite.getEmoticon(), input)) { - return getString(R.string.duplicate_emoticon); - } + new MultiInputMaterialDialogBuilder(mContext) + .addInput(null, getString(R.string.emoticon), input -> { + if (TextUtils.isEmpty(input)) { + return getString(R.string.empty_emoticon); + } else { + List favorites = Favorite.listAll(Favorite.class); + for (Favorite favorite : favorites) { + if (TextUtils.equals(favorite.getEmoticon(), input)) { + return getString(R.string.duplicate_emoticon); } - return null; } + return null; } }) .addInput(null, getString(R.string.description)) - .addInput(null, getString(R.string.shortcut)) - .inputs(new MultiInputMaterialDialogBuilder.InputsCallback() { - @Override - public void onInputs(MaterialDialog dialog, List inputs, boolean allInputsValidated) { - if (allInputsValidated) { - String emoticon = inputs.get(0).toString(); - String description = inputs.get(1).toString(); - String shortcut = inputs.get(2).toString(); - - Favorite favorite = new Favorite(emoticon, description, shortcut); - favorite.save(); - - mAdapter.updateFavorites(); - showSnackBar(emoticon + "\n" + getString(R.string.added_to_fav)); - } + .addInput(null, getString(R.string.shortcut), SystemUtils.aboveMarshmallow23()) + .inputs((dialog, inputs, allInputsValidated) -> { + if (allInputsValidated) { + String emoticon = inputs.get(0).toString(); + String description = inputs.get(1).toString(); + String shortcut = SystemUtils.aboveMarshmallow23() ? "" : inputs.get(2).toString(); + + Favorite favorite = new Favorite(emoticon, description, shortcut); + favorite.save(); + + mAdapter.updateFavorites(); + showSnackBar(emoticon + "\n" + getString(R.string.added_to_fav)); } }) .title(R.string.add_to_fav) @@ -127,22 +120,19 @@ public void onInputs(MaterialDialog dialog, List inputs, boolean a @Subscribe public void handle(FavoriteBeginEditingEvent event) { final Favorite favorite = event.getFavorite(); - new MultiInputMaterialDialogBuilder(getActivity()) + new MultiInputMaterialDialogBuilder(mContext) .addInput(favorite.getDescription(), getString(R.string.description)) - .addInput(favorite.getShortcut(), getString(R.string.shortcut)) - .inputs(new MultiInputMaterialDialogBuilder.InputsCallback() { - @Override - public void onInputs(MaterialDialog dialog, List inputs, boolean allInputsValidated) { - String description = inputs.get(0).toString(); - String shortcut = inputs.get(1).toString(); - - // Get the new favorite and SAVE - favorite.setDescription(description); - favorite.setShortcut(shortcut); - favorite.save(); + .addInput(favorite.getShortcut(), getString(R.string.shortcut), SystemUtils.aboveMarshmallow23()) + .inputs((dialog, inputs, allInputsValidated) -> { + String description = inputs.get(0).toString(); + String shortcut = SystemUtils.aboveMarshmallow23() ? "" : inputs.get(1).toString(); - mAdapter.updateFavorites(); - } + // Get the new favorite and SAVE + favorite.setDescription(description); + favorite.setShortcut(shortcut); + favorite.save(); + + mAdapter.updateFavorites(); }) .title(R.string.edit_favorite) .positiveText(android.R.string.ok) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/ui/MultiInputMaterialDialogBuilder.java b/app/src/main/java/org/ktachibana/cloudemoji/ui/MultiInputMaterialDialogBuilder.java index 1a4aa1ad..3e61b5e5 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/ui/MultiInputMaterialDialogBuilder.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/ui/MultiInputMaterialDialogBuilder.java @@ -53,6 +53,18 @@ public CharSequence validate(CharSequence input) { }); } + public MultiInputMaterialDialogBuilder addInput(CharSequence preFill, CharSequence hint, boolean optional) { + if (optional) { + return this; + } + return addInput(preFill, hint, new InputValidator() { + @Override + public CharSequence validate(CharSequence input) { + return null; + } + }); + } + public MultiInputMaterialDialogBuilder addInput(@StringRes int preFill, @StringRes int hint, @NonNull InputValidator validator) { return addInput( preFill == 0 ? null : mContext.getString(preFill), From 91310524889b96e59ce227cd5e70d1ead42f9e91 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Thu, 20 Oct 2022 01:26:27 -0700 Subject: [PATCH 27/31] capabilities for 23 --- .../adapters/FavoriteListViewAdapter.java | 6 +++--- .../cloudemoji/fragments/FavoriteFragment.java | 10 +++++----- .../fragments/PreferenceFragment.java | 5 +++-- .../cloudemoji/utils/CapabilityUtils.java | 17 +++++++++++++++++ .../cloudemoji/utils/NotificationUtils.java | 2 +- .../cloudemoji/utils/SystemUtils.java | 4 ---- 6 files changed, 29 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/org/ktachibana/cloudemoji/utils/CapabilityUtils.java diff --git a/app/src/main/java/org/ktachibana/cloudemoji/adapters/FavoriteListViewAdapter.java b/app/src/main/java/org/ktachibana/cloudemoji/adapters/FavoriteListViewAdapter.java index 64322c05..a3e7f550 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/adapters/FavoriteListViewAdapter.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/adapters/FavoriteListViewAdapter.java @@ -15,7 +15,7 @@ import org.ktachibana.cloudemoji.events.FavoriteDeletedEvent; import org.ktachibana.cloudemoji.models.disk.Favorite; import org.ktachibana.cloudemoji.ui.ScrollableEmoticonMaterialDialogBuilder; -import org.ktachibana.cloudemoji.utils.SystemUtils; +import org.ktachibana.cloudemoji.utils.CapabilityUtils; import java.util.List; @@ -64,7 +64,7 @@ public View getView(int i, View view, ViewGroup viewGroup) { // Setup contents viewHolder.emoticon.setText(favorite.getEmoticon()); - if (favorite.getDescription().equals("") && (SystemUtils.aboveMarshmallow23() || favorite.getShortcut().equals(""))) { + if (favorite.getDescription().equals("") && (CapabilityUtils.personalDictionaryUnavailable() || favorite.getShortcut().equals(""))) { viewHolder.description.setVisibility(View.GONE); } else { viewHolder.description.setVisibility(View.VISIBLE); @@ -73,7 +73,7 @@ public View getView(int i, View view, ViewGroup viewGroup) { ? "(" + mContext.getString(R.string.no_description) + ")" : favorite.getDescription(); - if (SystemUtils.aboveMarshmallow23()) { + if (CapabilityUtils.personalDictionaryUnavailable()) { viewHolder.description.setText(descriptionText); } else { String shortcutText = diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/FavoriteFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/FavoriteFragment.java index 9b285300..ce2edb30 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/FavoriteFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/FavoriteFragment.java @@ -23,7 +23,7 @@ import org.ktachibana.cloudemoji.models.disk.Favorite; import org.ktachibana.cloudemoji.models.memory.Entry; import org.ktachibana.cloudemoji.ui.MultiInputMaterialDialogBuilder; -import org.ktachibana.cloudemoji.utils.SystemUtils; +import org.ktachibana.cloudemoji.utils.CapabilityUtils; import java.util.List; @@ -97,12 +97,12 @@ private void popupAddFavoriteDialog() { } }) .addInput(null, getString(R.string.description)) - .addInput(null, getString(R.string.shortcut), SystemUtils.aboveMarshmallow23()) + .addInput(null, getString(R.string.shortcut), CapabilityUtils.personalDictionaryUnavailable()) .inputs((dialog, inputs, allInputsValidated) -> { if (allInputsValidated) { String emoticon = inputs.get(0).toString(); String description = inputs.get(1).toString(); - String shortcut = SystemUtils.aboveMarshmallow23() ? "" : inputs.get(2).toString(); + String shortcut = CapabilityUtils.personalDictionaryUnavailable() ? "" : inputs.get(2).toString(); Favorite favorite = new Favorite(emoticon, description, shortcut); favorite.save(); @@ -122,10 +122,10 @@ public void handle(FavoriteBeginEditingEvent event) { final Favorite favorite = event.getFavorite(); new MultiInputMaterialDialogBuilder(mContext) .addInput(favorite.getDescription(), getString(R.string.description)) - .addInput(favorite.getShortcut(), getString(R.string.shortcut), SystemUtils.aboveMarshmallow23()) + .addInput(favorite.getShortcut(), getString(R.string.shortcut), CapabilityUtils.personalDictionaryUnavailable()) .inputs((dialog, inputs, allInputsValidated) -> { String description = inputs.get(0).toString(); - String shortcut = SystemUtils.aboveMarshmallow23() ? "" : inputs.get(1).toString(); + String shortcut = CapabilityUtils.personalDictionaryUnavailable() ? "" : inputs.get(1).toString(); // Get the new favorite and SAVE favorite.setDescription(description); diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index 76ff7fc0..7f8e947e 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -29,6 +29,7 @@ import org.ktachibana.cloudemoji.events.EmptyEvent; import org.ktachibana.cloudemoji.events.ShowSnackBarOnBaseActivityEvent; import org.ktachibana.cloudemoji.utils.BackupUtils; +import org.ktachibana.cloudemoji.utils.CapabilityUtils; import org.ktachibana.cloudemoji.utils.NotificationUtils; import org.ktachibana.cloudemoji.utils.PersonalDictionaryUtils; import org.ktachibana.cloudemoji.utils.SystemUtils; @@ -100,7 +101,7 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { // Now on Tap or Navbar Gesture Preference navbarGesturePref = findPreference(Constants.PREF_NAVBAR_GESTURE); Preference nowOnTapPref = findPreference(Constants.PREF_NOW_ON_TAP); - if (SystemUtils.aboveMarshmallow23()) { + if (CapabilityUtils.nowOnTapAvailable()) { navbarGesturePref.setVisible(false); // Now on Tap @@ -137,7 +138,7 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { PreferenceCategory personalDictionaryPref = (PreferenceCategory) findPreference(Constants.PREF_PERSONAL_DICTIONARY); - if (SystemUtils.aboveMarshmallow23()) { + if (CapabilityUtils.personalDictionaryUnavailable()) { personalDictionaryPref.setVisible(false); } else { // Import favorites into personal dictionary diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/CapabilityUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/CapabilityUtils.java new file mode 100644 index 00000000..4ab5f018 --- /dev/null +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/CapabilityUtils.java @@ -0,0 +1,17 @@ +package org.ktachibana.cloudemoji.utils; + +import android.os.Build; + +public class CapabilityUtils { + public static boolean personalDictionaryUnavailable() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; + } + + public static boolean cannotGetActiveNotifications() { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.M; + } + + public static boolean nowOnTapAvailable() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; + } +} diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index ac7e9b9e..548a9dec 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -90,7 +90,7 @@ private static void setupLegacyVisibilityBoth(Context context) { private static boolean doesQuickTriggerNotificationExist(Context context) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - if (!SystemUtils.aboveMarshmallow23()) { + if (CapabilityUtils.cannotGetActiveNotifications()) { return false; } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java index 176117b2..5bf80a85 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java @@ -20,10 +20,6 @@ public static boolean networkAvailable() { return (network == NetworkInfo.State.CONNECTED || network == NetworkInfo.State.CONNECTING); } - public static boolean aboveMarshmallow23() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; - } - public static boolean aboveNougat24() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; } From f436f8e770c899c9a91b09dd7691b22c23987f1a Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Thu, 20 Oct 2022 01:37:46 -0700 Subject: [PATCH 28/31] rest of capability util --- .../cloudemoji/activities/MainActivity.java | 4 ++-- .../activities/RepositoryManagerActivity.java | 9 -------- .../fragments/PreferenceFragment.java | 19 ++-------------- .../net/RepositoryDownloaderClient.java | 5 ++--- .../net/RepositoryStoreDownloaderClient.java | 4 ++-- .../net/VersionCodeCheckerClient.java | 4 ++-- .../cloudemoji/receivers/BootUpReceiver.java | 4 ++-- .../cloudemoji/utils/CapabilityUtils.java | 16 ++++++++++++++ .../{SystemUtils.java => NetworkUtils.java} | 22 +------------------ .../cloudemoji/utils/NotificationUtils.java | 6 ++--- 10 files changed, 32 insertions(+), 61 deletions(-) rename app/src/main/java/org/ktachibana/cloudemoji/utils/{SystemUtils.java => NetworkUtils.java} (54%) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java index 28ded806..a1ffa85c 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/MainActivity.java @@ -38,8 +38,8 @@ import org.ktachibana.cloudemoji.net.VersionCodeCheckerClient; import org.ktachibana.cloudemoji.parsing.SourceParsingException; import org.ktachibana.cloudemoji.parsing.SourceReader; +import org.ktachibana.cloudemoji.utils.CapabilityUtils; import org.ktachibana.cloudemoji.utils.NotificationUtils; -import org.ktachibana.cloudemoji.utils.SystemUtils; import org.parceler.Parcels; import java.io.File; @@ -124,7 +124,7 @@ private LinkedHashMap initializeSourceCache() { @AfterPermissionGranted(RC_POST_NOTIFICATIONS) private void setupNotification() { - if (SystemUtils.belowTiramisu33()) { + if (CapabilityUtils.doNotNeedRuntimeNotificationPermission()) { NotificationUtils.setupNotification(this, null); return; } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java index ba4f8150..59635411 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java @@ -3,8 +3,6 @@ import android.content.Intent; import android.os.Bundle; -import android.os.Environment; -import android.provider.DocumentsContract; import android.view.View; import android.widget.ListView; import android.widget.RelativeLayout; @@ -29,7 +27,6 @@ import org.ktachibana.cloudemoji.events.RepositoryInvalidFormatEvent; import org.ktachibana.cloudemoji.models.disk.Repository; import org.ktachibana.cloudemoji.ui.MultiInputMaterialDialogBuilder; -import org.ktachibana.cloudemoji.utils.SystemUtils; import java.io.IOException; import java.io.OutputStream; @@ -174,12 +171,6 @@ public void handle(RepositoryExportEvent exportedEvent) { intent.putExtra(Intent.EXTRA_TITLE, exportedEvent.getAlias() + ".json"); mCurrentExportingJson = exportedEvent.getJson(); - if (SystemUtils.aboveOreo26()) { - // Optionally, specify a URI for the directory that should be opened in - // the system file picker when your app creates the document. - intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOCUMENTS); - } - startActivityForResult(intent, RC_EXPORT_REPOSITORY); } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index 7f8e947e..99c8935b 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -10,9 +10,7 @@ import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; -import android.os.Environment; import android.preference.PreferenceManager; -import android.provider.DocumentsContract; import androidx.preference.CheckBoxPreference; import androidx.preference.ListPreference; @@ -32,7 +30,6 @@ import org.ktachibana.cloudemoji.utils.CapabilityUtils; import org.ktachibana.cloudemoji.utils.NotificationUtils; import org.ktachibana.cloudemoji.utils.PersonalDictionaryUtils; -import org.ktachibana.cloudemoji.utils.SystemUtils; import java.io.IOException; import java.io.InputStream; @@ -81,7 +78,7 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { syncShowAfterBootUpToNotificationVisibility(null); Preference notificationLegacyVisibilityPref = findPreference(Constants.PREF_NOTIFICATION_LEGACY_VISIBILITY); Preference showNotificationPref = findPreference(Constants.PREF_SHOW_NOTIFICATION); - if (SystemUtils.aboveNougat24()) { + if (CapabilityUtils.notQuickTriggerNotificationLegacyVisibility()) { notificationLegacyVisibilityPref.setVisible(false); showNotificationPref.setOnPreferenceChangeListener((preference, newValue) -> { syncShowAfterBootUpToNotificationVisibility(newValue); @@ -213,7 +210,7 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { private void syncShowAfterBootUpToNotificationVisibility(Object newVisibleOrVisibility) { CheckBoxPreference showAfterBootUpPref = (CheckBoxPreference) findPreference(Constants.PREF_SHOW_AFTER_BOOT_UP); - if (SystemUtils.aboveNougat24()) { + if (CapabilityUtils.notQuickTriggerNotificationLegacyVisibility()) { CheckBoxPreference showNotificationPref = (CheckBoxPreference) findPreference(Constants.PREF_SHOW_NOTIFICATION); boolean visible = showNotificationPref.isChecked(); if (newVisibleOrVisibility != null) { @@ -252,12 +249,6 @@ void backupFavorites() { intent.setType(BACKUP_FILE_MIME_TYPE); intent.putExtra(Intent.EXTRA_TITLE, BACKUP_FILENAME); - if (SystemUtils.aboveOreo26()) { - // Optionally, specify a URI for the directory that should be opened in - // the system file picker when your app creates the document. - intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOCUMENTS); - } - startActivityForResult(intent, RC_BACKUP); } @@ -266,12 +257,6 @@ void restoreFavorites() { intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType(BACKUP_FILE_MIME_TYPE); - if (SystemUtils.aboveOreo26()) { - intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, Environment.DIRECTORY_DOCUMENTS); - } - // Optionally, specify a URI for the file that should appear in the - // system file picker when it loads. - startActivityForResult(intent, RC_RESTORE); } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/net/RepositoryDownloaderClient.java b/app/src/main/java/org/ktachibana/cloudemoji/net/RepositoryDownloaderClient.java index 5b292ec0..0dfa4c52 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/net/RepositoryDownloaderClient.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/net/RepositoryDownloaderClient.java @@ -5,18 +5,17 @@ import com.loopj.android.http.AsyncHttpResponseHandler; import org.apache.commons.io.IOUtils; -import org.apache.http.Header; import org.ktachibana.cloudemoji.BaseApplication; import org.ktachibana.cloudemoji.BaseHttpClient; import org.ktachibana.cloudemoji.models.disk.Repository; -import org.ktachibana.cloudemoji.utils.SystemUtils; +import org.ktachibana.cloudemoji.utils.NetworkUtils; import java.io.File; import java.io.FileOutputStream; public class RepositoryDownloaderClient extends BaseHttpClient { public void downloadSource(@NonNull final Repository item, @NonNull final ObjectCallback callback) { - if (SystemUtils.networkAvailable()) { + if (NetworkUtils.networkAvailable()) { mClient.get( item.getUrl(), new AsyncHttpResponseHandler() { diff --git a/app/src/main/java/org/ktachibana/cloudemoji/net/RepositoryStoreDownloaderClient.java b/app/src/main/java/org/ktachibana/cloudemoji/net/RepositoryStoreDownloaderClient.java index 0829aad8..8e3da468 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/net/RepositoryStoreDownloaderClient.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/net/RepositoryStoreDownloaderClient.java @@ -10,7 +10,7 @@ import org.ktachibana.cloudemoji.BaseHttpClient; import org.ktachibana.cloudemoji.Constants; import org.ktachibana.cloudemoji.models.memory.StoreRepository; -import org.ktachibana.cloudemoji.utils.SystemUtils; +import org.ktachibana.cloudemoji.utils.NetworkUtils; import java.util.ArrayList; import java.util.List; @@ -19,7 +19,7 @@ public class RepositoryStoreDownloaderClient extends BaseHttpClient { public void downloadRepositoryStore(@NonNull final ListCallback callback) { - if (SystemUtils.networkAvailable()) { + if (NetworkUtils.networkAvailable()) { mClient.get(Constants.STORE_URL, new JsonHttpResponseHandler() { public void onSuccess(int statusCode, Header[] headers, JSONArray response) { List repositories = new ArrayList<>(); diff --git a/app/src/main/java/org/ktachibana/cloudemoji/net/VersionCodeCheckerClient.java b/app/src/main/java/org/ktachibana/cloudemoji/net/VersionCodeCheckerClient.java index 9b5daa4a..24efb38f 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/net/VersionCodeCheckerClient.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/net/VersionCodeCheckerClient.java @@ -8,13 +8,13 @@ import org.json.JSONObject; import org.ktachibana.cloudemoji.BaseHttpClient; import org.ktachibana.cloudemoji.Constants; -import org.ktachibana.cloudemoji.utils.SystemUtils; +import org.ktachibana.cloudemoji.utils.NetworkUtils; import cz.msebera.android.httpclient.Header; public class VersionCodeCheckerClient extends BaseHttpClient { public void checkForLatestVersionCode(@NonNull final IntCallback callback) { - if (SystemUtils.networkAvailable()) { + if (NetworkUtils.networkAvailable()) { mClient.get(Constants.UPDATE_CHECKER_URL, new JsonHttpResponseHandler() { public void onSuccess(int statusCode, Header[] headers, JSONObject response) { try { diff --git a/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java b/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java index 4c629199..7b173771 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/receivers/BootUpReceiver.java @@ -8,8 +8,8 @@ import android.preference.PreferenceManager; import org.ktachibana.cloudemoji.Constants; +import org.ktachibana.cloudemoji.utils.CapabilityUtils; import org.ktachibana.cloudemoji.utils.NotificationUtils; -import org.ktachibana.cloudemoji.utils.SystemUtils; import pub.devrel.easypermissions.EasyPermissions; @@ -31,7 +31,7 @@ public void onReceive(Context context, Intent intent) { return; } - if (SystemUtils.belowTiramisu33()) { + if (CapabilityUtils.doNotNeedRuntimeNotificationPermission()) { NotificationUtils.setupNotification(context, null); return; } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/CapabilityUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/CapabilityUtils.java index 4ab5f018..b6554516 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/CapabilityUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/CapabilityUtils.java @@ -14,4 +14,20 @@ public static boolean cannotGetActiveNotifications() { public static boolean nowOnTapAvailable() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; } + + public static boolean notQuickTriggerNotificationLegacyVisibility() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; + } + + public static boolean needNotificationChannel() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; + } + + public static boolean needPendingIntentMutability() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S; + } + + public static boolean doNotNeedRuntimeNotificationPermission() { + return Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU; + } } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NetworkUtils.java similarity index 54% rename from app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java rename to app/src/main/java/org/ktachibana/cloudemoji/utils/NetworkUtils.java index 5bf80a85..b658f735 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/SystemUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NetworkUtils.java @@ -3,14 +3,10 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.os.Build; import org.ktachibana.cloudemoji.BaseApplication; -/** - * The notorious trash can - */ -public class SystemUtils { +public class NetworkUtils { public static boolean networkAvailable() { Context context = BaseApplication.context(); ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); @@ -19,20 +15,4 @@ public static boolean networkAvailable() { NetworkInfo.State network = info.getState(); return (network == NetworkInfo.State.CONNECTED || network == NetworkInfo.State.CONNECTING); } - - public static boolean aboveNougat24() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; - } - - public static boolean aboveOreo26() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; - } - - public static boolean aboveS31() { - return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S; - } - - public static boolean belowTiramisu33() { - return Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU; - } } diff --git a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java index 548a9dec..78bcefa9 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/utils/NotificationUtils.java @@ -28,7 +28,7 @@ public class NotificationUtils implements Constants { public static void setupNotification(Context context, Object newVisibleOrVisibility) { SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - if (SystemUtils.aboveNougat24()) { + if (CapabilityUtils.notQuickTriggerNotificationLegacyVisibility()) { boolean visible = preferences.getBoolean(Constants.PREF_SHOW_NOTIFICATION, true); if (newVisibleOrVisibility != null) { visible = (boolean) newVisibleOrVisibility; @@ -107,7 +107,7 @@ private static void createQuickTriggerNotificationChannel( Context context, int importance ) { - if (SystemUtils.aboveOreo26()) { + if (CapabilityUtils.needNotificationChannel()) { NotificationChannel channel = new NotificationChannel( Constants.QUICK_TRIGGER_NOTIFICATION_CHANNEL_ID, context.getString(R.string.quick_trigger_notification_channel_name), @@ -129,7 +129,7 @@ private static void showQuickTriggerNotification( String text = context.getString(R.string.touch_to_launch); Intent intent = new Intent(context, MainActivity.class); PendingIntent pIntent; - if (SystemUtils.aboveS31()) { + if (CapabilityUtils.needPendingIntentMutability()) { pIntent = PendingIntent.getActivity (context, 0, intent, PendingIntent.FLAG_MUTABLE); } else { From 77c8fc27a1ae7011a193d9ee4e91ce32da3e3fc8 Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Thu, 20 Oct 2022 13:16:02 -0700 Subject: [PATCH 29/31] string updates --- app/src/main/res/values-zh/strings.xml | 6 +++--- app/src/main/res/values/strings.xml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 2210887e..afb4a22a 100755 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -9,7 +9,7 @@ 触摸以启动 设置 行为 - 复制之后关闭 + 复制之后关闭 App 源URL 关于 GitHub 源 @@ -37,7 +37,7 @@ 重复的颜文字 导航栏手势 从导航栏上划以启动 - 长按 Home 键启动 + 长按 Home 键启动 App 请点击打开系统设置,在「辅助应用」中选择 你没有任何收藏 你没有任何历史 @@ -70,7 +70,7 @@ 已添加到源 允许 拒绝 - 收藏已备份到 + 收藏已备份 收藏已恢复 通知 在跑调试/测试版, 屌屌哒! diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f6325191..de102837 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -11,7 +11,7 @@ Touch to launch Settings Behaviors - Close after copy + Close app after copy Repository URL About GitHub repository @@ -39,7 +39,7 @@ Duplicate emoticon Navigation bar gesture Swipe-up from the navigation bar to start - Hold Home button to startup + Hold Home button to launch app Touch to open system settings, then select "Assist app" You don\'t have any bookmarks You don\'t have any history @@ -72,7 +72,7 @@ Added to repositories Allow Deny - Backed up favorites to + Backed up bookmarks Restored bookmarks Notification Hey running debug/beta versions, cool kid? From d5ed6b92278a2d1c25de752878fab57f1990f6cc Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Thu, 20 Oct 2022 16:47:50 -0700 Subject: [PATCH 30/31] fix bug in now on tap and nav gesture --- .../fragments/PreferenceFragment.java | 25 ++++++++----------- app/src/main/res/values/strings.xml | 2 +- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java index 99c8935b..b238b33d 100755 --- a/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/fragments/PreferenceFragment.java @@ -106,8 +106,18 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { ComponentName componentName = new ComponentName(getActivity(), CLS_ASSIST_ACTIVITY); packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); + nowOnTapPref.setOnPreferenceClickListener(preference -> { + Intent intent = new Intent(); + // Didn't found it in android.provider.Settings... Just hardcoded it. + ComponentName componentName1 = new ComponentName( + Constants.PACKAGE_NAME_ANDROID_SETTINGS, + Constants.CLASS_NAME_MANAGE_ASSIST_ACTIVITY); + intent.setComponent(componentName1); + startActivity(intent); + return true; + }); } else { - navbarGesturePref.setVisible(false); + nowOnTapPref.setVisible(false); // Navbar Gesture navbarGesturePref.setOnPreferenceChangeListener((preference, newValue) -> { @@ -122,18 +132,6 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { }); } - nowOnTapPref.setOnPreferenceClickListener(preference -> { - Intent intent = new Intent(); - // Didn't found it in android.provider.Settings... Just hardcoded it. - ComponentName componentName = new ComponentName( - Constants.PACKAGE_NAME_ANDROID_SETTINGS, - Constants.CLASS_NAME_MANAGE_ASSIST_ACTIVITY); - intent.setComponent(componentName); - startActivity(intent); - return true; - }); - - PreferenceCategory personalDictionaryPref = (PreferenceCategory) findPreference(Constants.PREF_PERSONAL_DICTIONARY); if (CapabilityUtils.personalDictionaryUnavailable()) { personalDictionaryPref.setVisible(false); @@ -153,7 +151,6 @@ public void onCreatePreferences(Bundle paramBundle, String rootKey) { showSnackBar(String.format(getString(R.string.revoked_from_personal_dict), numberRevoked)); return true; }); - revokeImePref.setEnabled(false); } // Backup favorites diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index de102837..2fa43069 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -84,7 +84,7 @@ Quickly trigger the app from notification panel Cloud Emoticon IME No bookmark - Reoke all bookmarks from personal dictionary + Revoke all bookmarks from personal dictionary Revoked %d bookmarks from personal dictionary We need to put a sticky \"quick trigger\" notification so that you can launch Cloud Emoticon conveniently. Repo exported From 325aebc55cf0f9fbafadfe0756715f73ee15155c Mon Sep 17 00:00:00 2001 From: KTachibanaM Date: Thu, 20 Oct 2022 16:54:33 -0700 Subject: [PATCH 31/31] final string fixes --- .../cloudemoji/activities/RepositoryManagerActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java b/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java index 59635411..ea0e7730 100644 --- a/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java +++ b/app/src/main/java/org/ktachibana/cloudemoji/activities/RepositoryManagerActivity.java @@ -183,7 +183,7 @@ protected void onActivityResult(int requestCode, int resultCode, @Nullable Inten if (requestCode == RC_EXPORT_REPOSITORY) { os = getContentResolver().openOutputStream(data.getData()); IOUtils.write(mCurrentExportingJson, os); - showSnackBar("Exported"); + showSnackBar(R.string.exported_repo); } } else { showSnackBar(getString(R.string.fail));