From a50fd73931a1f8a7a6483e9a5828f3ff112dc5e8 Mon Sep 17 00:00:00 2001 From: Dmitriy Bogdanov Date: Wed, 9 Dec 2020 16:19:11 +0400 Subject: [PATCH 01/11] Revert "Replace deprecated method usage" This reverts commit f214a3b165a6fbf690e2a961962dfba39a9fa701. --- .../fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java b/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java index 6ca77994c..f99519847 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java @@ -19,7 +19,6 @@ import android.webkit.ConsoleMessage; import android.webkit.HttpAuthHandler; import android.webkit.WebChromeClient; -import android.webkit.WebResourceRequest; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Button; @@ -677,10 +676,9 @@ public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } + @SuppressWarnings("deprecation") // can't use newer method until API 21 @Override - public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { - String url = request.getUrl().toString(); - + public boolean shouldOverrideUrlLoading(WebView webView, String url) { // If we try to open current URL, do not propose to save it, directly open browser if (url.equals(articleUrl)) { openURL(url); From bc37813728e7bb32ae16d6c73b7642301543e34c Mon Sep 17 00:00:00 2001 From: Dmitriy Bogdanov Date: Wed, 9 Dec 2020 16:20:16 +0400 Subject: [PATCH 02/11] Revert "Simplify some code" This reverts commit 3ac93999b08c2b2901bf6de027219350bd1ae1ab. --- .../events/ConnectivityChangedEvent.java | 16 +++++++- .../apps/Poche/events/EventProcessor.java | 38 +++++++++++++++++-- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/events/ConnectivityChangedEvent.java b/app/src/main/java/fr/gaulupeau/apps/Poche/events/ConnectivityChangedEvent.java index 6db7d1717..3c02adb6a 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/events/ConnectivityChangedEvent.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/events/ConnectivityChangedEvent.java @@ -1,3 +1,17 @@ package fr.gaulupeau.apps.Poche.events; -public class ConnectivityChangedEvent {} +public class ConnectivityChangedEvent { + + private boolean noConnectivity; + + public ConnectivityChangedEvent() {} + + public ConnectivityChangedEvent(boolean noConnectivity) { + this.noConnectivity = noConnectivity; + } + + public boolean isNoConnectivity() { + return noConnectivity; + } + +} diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/events/EventProcessor.java b/app/src/main/java/fr/gaulupeau/apps/Poche/events/EventProcessor.java index 578d38c32..f73dd6b6c 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/events/EventProcessor.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/events/EventProcessor.java @@ -66,6 +66,8 @@ public class EventProcessor { private Handler mainHandler; private NotificationManager notificationManager; + private boolean delayedNetworkChangedTask; + private NotificationCompat.Builder syncQueueNotificationBuilder; private NotificationCompat.Builder updateArticlesNotificationBuilder; private NotificationCompat.Builder sweepDeletedArticlesNotificationBuilder; @@ -118,11 +120,12 @@ public void onAlarmReceivedEvent(AlarmReceivedEvent event) { public void onConnectivityChangedEvent(ConnectivityChangedEvent event) { Log.d(TAG, "onConnectivityChangedEvent() started"); - Settings settings = getSettings(); - if (settings.isOfflineQueuePending() && settings.isConfigurationOk()) { - Log.d(TAG, "networkChanged() requesting SyncQueue operation"); - OperationsHelper.syncQueue(getContext(), true); + if(event.isNoConnectivity()) { + Log.d(TAG, "onConnectivityChangedEvent() isNoConnectivity is true; ignoring event"); + return; } + + networkChanged(false); } @Subscribe @@ -559,6 +562,33 @@ public void onActionResultEvent(ActionResultEvent event) { } } + private void networkChanged(boolean delayed) { + if(!delayed && delayedNetworkChangedTask) return; + + if(!WallabagConnection.isNetworkAvailable()) return; + + Settings settings = getSettings(); + + if(settings.isOfflineQueuePending() && settings.isConfigurationOk()) { + if(delayed) { + Log.d(TAG, "networkChanged() requesting SyncQueue operation"); + + OperationsHelper.syncQueue(getContext(), true); + + delayedNetworkChangedTask = false; + } else { + getMainHandler().postDelayed(new Runnable() { + @Override + public void run() { + networkChanged(true); + } + }, 3000); + + delayedNetworkChangedTask = true; + } + } + } + private void enableConnectivityChangeReceiver(boolean enable) { if(getSettings().isAutoSyncQueueEnabled()) { Log.d(TAG, "enableConnectivityChangeReceiver() enable connectivity change receiver: " + enable); From 6c46aed07aaad1e8e2c27156cb6f0f3dc4e6e6d2 Mon Sep 17 00:00:00 2001 From: Dmitriy Bogdanov Date: Wed, 9 Dec 2020 16:20:32 +0400 Subject: [PATCH 03/11] Revert "Remove some more legacy (API <21) code" This reverts commit de98edc1f4a8f2807e0759943160d5b1e6809040. --- app/src/main/AndroidManifest.xml | 8 +++++++ .../gaulupeau/apps/Poche/data/Settings.java | 7 +++++- .../network/ConnectivityChangeReceiver.java | 24 +++++++++++++++++++ .../Poche/service/WallabagJobService.java | 4 ++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/fr/gaulupeau/apps/Poche/network/ConnectivityChangeReceiver.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1cf7969ae..5004fb5cd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -138,6 +138,14 @@ android:name="android.appwidget.provider" android:resource="@xml/icon_unread_info" /> + + + + + diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/data/Settings.java b/app/src/main/java/fr/gaulupeau/apps/Poche/data/Settings.java index a309162f2..5ed52a175 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/data/Settings.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/data/Settings.java @@ -19,6 +19,7 @@ import fr.gaulupeau.apps.InThePoche.R; import fr.gaulupeau.apps.Poche.App; +import fr.gaulupeau.apps.Poche.network.ConnectivityChangeReceiver; import fr.gaulupeau.apps.Poche.service.WallabagJobService; import fr.gaulupeau.apps.Poche.ui.HttpSchemeHandlerActivity; import fr.gaulupeau.apps.Poche.ui.Sortable; @@ -51,7 +52,11 @@ public static boolean checkFirstRunInit(Context context) { } public static void enableConnectivityChangeReceiver(Context context, boolean enable) { - WallabagJobService.enable(context, enable); + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + enableComponent(context, ConnectivityChangeReceiver.class, enable); + } else { + WallabagJobService.enable(context, enable); + } } // TODO: reuse in setHandleHttpScheme diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/network/ConnectivityChangeReceiver.java b/app/src/main/java/fr/gaulupeau/apps/Poche/network/ConnectivityChangeReceiver.java new file mode 100644 index 000000000..f2326eedf --- /dev/null +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/network/ConnectivityChangeReceiver.java @@ -0,0 +1,24 @@ +package fr.gaulupeau.apps.Poche.network; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.net.ConnectivityManager; +import android.util.Log; + +import fr.gaulupeau.apps.Poche.events.ConnectivityChangedEvent; +import fr.gaulupeau.apps.Poche.events.EventHelper; + +public class ConnectivityChangeReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + if(ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { + Log.d("ConnectivityChangeRcvr", "Connectivity changed"); + + EventHelper.postEvent(new ConnectivityChangedEvent( + intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false))); + } + } + +} diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/service/WallabagJobService.java b/app/src/main/java/fr/gaulupeau/apps/Poche/service/WallabagJobService.java index 3398dbbf5..f466a8e31 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/service/WallabagJobService.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/service/WallabagJobService.java @@ -6,11 +6,15 @@ import android.app.job.JobService; import android.content.ComponentName; import android.content.Context; +import android.os.Build; import android.util.Log; +import androidx.annotation.RequiresApi; + import fr.gaulupeau.apps.Poche.events.ConnectivityChangedEvent; import fr.gaulupeau.apps.Poche.events.EventHelper; +@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public class WallabagJobService extends JobService { private static final int CONNECTIVITY_CHANGE_JOB_ID = 1; From 756ca5e83b1a6433cc4c45f8bf4da4433f824ebf Mon Sep 17 00:00:00 2001 From: Dmitriy Bogdanov Date: Wed, 9 Dec 2020 16:20:43 +0400 Subject: [PATCH 04/11] Revert "Remove some legacy (API <21) code" This reverts commit 93d90d191d7c00c8fb8c6a2f07818043478fa7ed. --- .../gaulupeau/apps/Poche/data/DbConnection.java | 15 +++++++++++++-- .../fr/gaulupeau/apps/Poche/data/dao/FtsDao.java | 10 +++++++--- .../fr/gaulupeau/apps/Poche/tts/TtsService.java | 10 +++++++++- .../Poche/ui/preferences/SettingsActivity.java | 9 +++++++++ 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/data/DbConnection.java b/app/src/main/java/fr/gaulupeau/apps/Poche/data/DbConnection.java index e3692a3c7..130c97673 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/data/DbConnection.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/data/DbConnection.java @@ -1,7 +1,10 @@ package fr.gaulupeau.apps.Poche.data; +import android.database.sqlite.SQLiteDatabase; +import android.os.Build; import android.util.Log; +import org.greenrobot.greendao.database.Database; import org.greenrobot.greendao.query.QueryBuilder; import fr.gaulupeau.apps.InThePoche.BuildConfig; @@ -25,8 +28,16 @@ public static DaoSession getSession() { Log.d(TAG, "creating new db session"); WallabagDbOpenHelper dbHelper = new WallabagDbOpenHelper(App.getInstance(), dbPath, null); - dbHelper.setWriteAheadLoggingEnabled(true); - DaoMaster daoMaster = new DaoMaster(dbHelper.getWritableDb()); + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + dbHelper.setWriteAheadLoggingEnabled(true); + } + Database db = dbHelper.getWritableDb(); + if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { + if(!((SQLiteDatabase)db.getRawDatabase()).enableWriteAheadLogging()) { + Log.w(TAG, "write ahead logging was not enabled"); + } + } + DaoMaster daoMaster = new DaoMaster(db); Holder.session = daoMaster.newSession(); } else { Log.d(TAG, "using existing db session"); diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/data/dao/FtsDao.java b/app/src/main/java/fr/gaulupeau/apps/Poche/data/dao/FtsDao.java index 8ea4040d8..c205b8a95 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/data/dao/FtsDao.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/data/dao/FtsDao.java @@ -1,5 +1,7 @@ package fr.gaulupeau.apps.Poche.data.dao; +import android.os.Build; + import org.greenrobot.greendao.database.Database; import fr.gaulupeau.apps.Poche.App; @@ -51,9 +53,11 @@ public static void deleteAllArticles(Database db) { } private static void createTable(Database db, boolean ifNotExists) { - String options = ", content=\"" + VIEW_FOR_FTS_NAME + "\"" - + ", tokenize=" - + (App.getSettings().isFtsIcuTokenizerEnabled() ? "icu" : "unicode61"); + String options = ", content=\"" + VIEW_FOR_FTS_NAME + "\""; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + options += ", tokenize=" + + (App.getSettings().isFtsIcuTokenizerEnabled() ? "icu" : "unicode61"); + } db.execSQL("create virtual table " + getIfNotExistsConstraint(ifNotExists) + TABLE_NAME + " using fts4(" + diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TtsService.java b/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TtsService.java index ca24c14a5..ccf13c9f1 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TtsService.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TtsService.java @@ -34,6 +34,7 @@ import androidx.core.util.Pair; import androidx.media.session.MediaButtonReceiver; +import java.util.HashMap; import java.util.Locale; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -744,7 +745,14 @@ private void ttsSpeak(CharSequence text, int queueMode, String utteranceId) { Log.v(TAG, "ttsSpeak() speaking " + utteranceId + ": " + text); - tts.speak(text, queueMode, null, utteranceId); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + tts.speak(text, queueMode, null, utteranceId); + } else { + HashMap params = new HashMap<>(2); + params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceId); + //noinspection deprecation + tts.speak(text.toString(), queueMode, params); + } Log.v(TAG, "ttsSpeak() call returned"); } diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/ui/preferences/SettingsActivity.java b/app/src/main/java/fr/gaulupeau/apps/Poche/ui/preferences/SettingsActivity.java index f408fe6ec..461208d00 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/ui/preferences/SettingsActivity.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/ui/preferences/SettingsActivity.java @@ -5,6 +5,7 @@ import android.app.AlarmManager; import android.content.DialogInterface; import android.content.SharedPreferences; +import android.os.Build; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; @@ -174,6 +175,14 @@ public void onCreate(Bundle savedInstanceState) { handleHttpSchemePreference.setOnPreferenceChangeListener(this); } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + CheckBoxPreference ftsIcuTokenizerPreference = (CheckBoxPreference) findPreference( + getString(R.string.pref_key_misc_ftsIcuTokenizer_enabled)); + if (ftsIcuTokenizerPreference != null) { + ftsIcuTokenizerPreference.setEnabled(false); + } + } + ListPreference dbPathListPreference = (ListPreference)findPreference( getString(R.string.pref_key_storage_dbPath)); if(dbPathListPreference != null) { From aa0e9af81f7286ab3de69a455c7fe9e620197f68 Mon Sep 17 00:00:00 2001 From: Dmitriy Bogdanov Date: Mon, 30 Nov 2020 19:19:41 +0400 Subject: [PATCH 05/11] Downgrade deps and minSdk to Android 4 --- app/build.gradle | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d1098bbf0..be21a8902 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { applicationId "fr.gaulupeau.apps.InThePoche" - minSdkVersion 21 + minSdkVersion 14 targetSdkVersion 30 versionCode 228 versionName "2.4.2" @@ -66,12 +66,12 @@ dependencies { implementation 'org.greenrobot:eventbus:3.2.0' implementation 'org.greenrobot:greendao:3.3.0' annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.2.0' - implementation 'com.squareup.okhttp3:okhttp:4.9.0' - implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.9.0' + implementation 'com.squareup.okhttp3:okhttp:3.12.12' + implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.12.12' implementation 'org.conscrypt:conscrypt-android:2.5.1' implementation 'com.facebook.stetho:stetho:1.5.1' implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1' - implementation 'com.mikepenz:aboutlibraries:7.1.0' + implementation 'com.mikepenz:aboutlibraries:6.2.1' implementation 'com.github.di72nn.wallabag-api-wrapper:api-wrapper:v2.0.0-beta.6' implementation 'org.slf4j:slf4j-android:1.7.30' } From c2dc67467f6334c29d336be1ddef8a123ee1821d Mon Sep 17 00:00:00 2001 From: Dmitriy Bogdanov Date: Mon, 30 Nov 2020 19:11:52 +0400 Subject: [PATCH 06/11] Android 4 compatibility --- .../gaulupeau/apps/Poche/service/TaskService.java | 2 +- .../apps/Poche/service/tasks/ActionRequestTask.java | 2 +- .../apps/Poche/service/tasks/SimpleTask.java | 2 +- .../apps/Poche/service/workers/ArticleUpdater.java | 13 +++++++------ .../service/workers/OfflineChangesSynchronizer.java | 5 +++-- .../java/fr/gaulupeau/apps/Poche/tts/TextItem.java | 2 +- .../apps/Poche/ui/ReadArticleActivity.java | 7 +++++-- .../fr/gaulupeau/apps/Poche/utils/TextTools.java | 10 ++++++++++ 8 files changed, 29 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/service/TaskService.java b/app/src/main/java/fr/gaulupeau/apps/Poche/service/TaskService.java index 4b4546693..6ce099f0a 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/service/TaskService.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/service/TaskService.java @@ -191,7 +191,7 @@ private void readyToStop() { private void enqueueTask(ParameterizedRunnable task, boolean ensureStarted) { Log.d(tag, "enqueueTask()"); - Objects.requireNonNull(task, "task is null"); + Objects.requireNonNull(task); Log.v(tag, "enqueueTask() enqueueing task"); taskQueue.add(task); diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/service/tasks/ActionRequestTask.java b/app/src/main/java/fr/gaulupeau/apps/Poche/service/tasks/ActionRequestTask.java index 0e617c5a7..0881b4756 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/service/tasks/ActionRequestTask.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/service/tasks/ActionRequestTask.java @@ -16,7 +16,7 @@ public class ActionRequestTask extends SimpleTask { protected ActionRequest actionRequest; public ActionRequestTask(ActionRequest actionRequest) { - Objects.requireNonNull(actionRequest, "actionRequest is null"); + Objects.requireNonNull(actionRequest); this.actionRequest = actionRequest; } diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/service/tasks/SimpleTask.java b/app/src/main/java/fr/gaulupeau/apps/Poche/service/tasks/SimpleTask.java index 2a8dbd203..17c2f05cf 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/service/tasks/SimpleTask.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/service/tasks/SimpleTask.java @@ -52,7 +52,7 @@ public T createFromParcel(Parcel in) { T instance; try { instance = clazz.newInstance(); - } catch (IllegalAccessException | InstantiationException e) { + } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Uh oh"); } diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/service/workers/ArticleUpdater.java b/app/src/main/java/fr/gaulupeau/apps/Poche/service/workers/ArticleUpdater.java index b78109f2c..2547acab9 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/service/workers/ArticleUpdater.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/service/workers/ArticleUpdater.java @@ -5,6 +5,8 @@ import android.util.Log; import android.util.Pair; +import androidx.core.util.ObjectsCompat; + import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -13,7 +15,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import fr.gaulupeau.apps.Poche.data.DbUtils; @@ -357,15 +358,15 @@ private void processArticle(ArticlesChangedEvent event, boolean full, article.setUpdateDate(apiArticle.updatedAt); articleChanges.add(ChangeType.UPDATED_DATE_CHANGED); } - if (!Objects.equals(article.getPublishedAt(), apiArticle.publishedAt)) { + if (!ObjectsCompat.equals(article.getPublishedAt(), apiArticle.publishedAt)) { article.setPublishedAt(apiArticle.publishedAt); articleChanges.add(ChangeType.PUBLISHED_AT_CHANGED); } - if (!Objects.equals(article.getStarredAt(), apiArticle.starredAt)) { + if (!ObjectsCompat.equals(article.getStarredAt(), apiArticle.starredAt)) { article.setStarredAt(apiArticle.starredAt); articleChanges.add(ChangeType.STARRED_AT_CHANGED); } - if (!Objects.equals(article.getIsPublic(), apiArticle.isPublic)) { + if (!ObjectsCompat.equals(article.getIsPublic(), apiArticle.isPublic)) { article.setIsPublic(apiArticle.isPublic); articleChanges.add(ChangeType.IS_PUBLIC_CHANGED); } @@ -552,11 +553,11 @@ private boolean processAnnotations(wallabag.apiwrapper.models.Article apiArticle annotation.setQuote(apiAnnotation.quote); annotationChanged = true; } - if (!Objects.equals(annotation.getCreatedAt(), apiAnnotation.createdAt)) { + if (!ObjectsCompat.equals(annotation.getCreatedAt(), apiAnnotation.createdAt)) { annotation.setCreatedAt(apiAnnotation.createdAt); annotationChanged = true; } - if (!Objects.equals(annotation.getUpdatedAt(), apiAnnotation.updatedAt)) { + if (!ObjectsCompat.equals(annotation.getUpdatedAt(), apiAnnotation.updatedAt)) { annotation.setUpdatedAt(apiAnnotation.updatedAt); annotationChanged = true; } diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/service/workers/OfflineChangesSynchronizer.java b/app/src/main/java/fr/gaulupeau/apps/Poche/service/workers/OfflineChangesSynchronizer.java index 371931374..e83fe6f60 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/service/workers/OfflineChangesSynchronizer.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/service/workers/OfflineChangesSynchronizer.java @@ -5,11 +5,12 @@ import android.util.Log; import android.util.Pair; +import androidx.core.util.ObjectsCompat; + import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Objects; import fr.gaulupeau.apps.Poche.data.DbUtils; import fr.gaulupeau.apps.Poche.data.QueueHelper; @@ -307,7 +308,7 @@ private void addLink(AddLinkItem item) throws IncorrectConfigurationException, } private void updateGivenUrl(Article article, String givenUrl) { - if (!Objects.equals(article.getGivenUrl(), givenUrl)) { + if (!ObjectsCompat.equals(article.getGivenUrl(), givenUrl)) { article.setGivenUrl(givenUrl); article.update(); } diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TextItem.java b/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TextItem.java index 59db8947f..84565977d 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TextItem.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TextItem.java @@ -29,7 +29,7 @@ static Type getType(String type) { Extra() {} Extra(Extra.Type type, int start, int end) { - this.type = Objects.requireNonNull(type, "type cannot be null"); + this.type = Objects.requireNonNull(type); this.start = start; this.end = end; } diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java b/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java index f99519847..67ef50bda 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java @@ -2,6 +2,7 @@ import android.annotation.SuppressLint; import android.content.Intent; +import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; @@ -63,7 +64,7 @@ import fr.gaulupeau.apps.Poche.tts.TtsFragment; import fr.gaulupeau.apps.Poche.tts.TtsHost; -import static android.text.Html.escapeHtml; +import static fr.gaulupeau.apps.Poche.utils.TextTools.escapeHtml; public class ReadArticleActivity extends BaseActionBarActivity { @@ -160,7 +161,9 @@ public void onCreate(Bundle savedInstanceState) { WallabagConnection.initConscrypt(); if (BuildConfig.DEBUG) { - WebView.setWebContentsDebuggingEnabled(true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + WebView.setWebContentsDebuggingEnabled(true); + } } settings = App.getSettings(); diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/utils/TextTools.java b/app/src/main/java/fr/gaulupeau/apps/Poche/utils/TextTools.java index 4e8eb5629..c22d49433 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/utils/TextTools.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/utils/TextTools.java @@ -4,6 +4,8 @@ import android.text.Html; import android.text.TextUtils; +import androidx.core.text.TextUtilsCompat; + public class TextTools { /** @@ -19,6 +21,14 @@ public static boolean equalOrEmpty(CharSequence s1, CharSequence s2) { || TextUtils.equals(s1, s2); } + public static String escapeHtml(String s) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + return Html.escapeHtml(s); + } else { + return TextUtilsCompat.htmlEncode(s); // not sure + } + } + public static String unescapeHtml(String s) { if (s == null) return null; From bbb813cfd0dcb52c841fea1bed4f4dc560c11802 Mon Sep 17 00:00:00 2001 From: Dmitriy Bogdanov Date: Mon, 30 Nov 2020 20:29:44 +0400 Subject: [PATCH 07/11] Android 4 WebView compatibility --- app/proguard-rules.pro | 3 +++ .../main/assets/annotations-android-app.js | 4 +-- .../apps/Poche/ui/JsActionController.java | 25 +++++++++++++++++++ .../apps/Poche/ui/ReadArticleActivity.java | 21 ++++++++++++---- 4 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/fr/gaulupeau/apps/Poche/ui/JsActionController.java diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 34e8da605..3e4c6c5d9 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -14,6 +14,9 @@ #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} +-keepclassmembers class fr.gaulupeau.apps.Poche.ui.JsActionController { + public *; +} -keepclassmembers class fr.gaulupeau.apps.Poche.ui.JsAnnotationController { public *; } diff --git a/app/src/main/assets/annotations-android-app.js b/app/src/main/assets/annotations-android-app.js index d8592b650..658929639 100644 --- a/app/src/main/assets/annotations-android-app.js +++ b/app/src/main/assets/annotations-android-app.js @@ -6,7 +6,7 @@ document.addEventListener("DOMContentLoaded", function() { }); const authorization = { - permits() { return true; }, + permits: function() { return true; }, }; app.registry.registerUtility(authorization, 'authorizationPolicy'); @@ -46,7 +46,7 @@ document.addEventListener("DOMContentLoaded", function() { app.include(myStorage); - app.start().then(() => { + app.start().then(function() { app.annotations.load({}); }); }); diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/ui/JsActionController.java b/app/src/main/java/fr/gaulupeau/apps/Poche/ui/JsActionController.java new file mode 100644 index 000000000..c18f02776 --- /dev/null +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/ui/JsActionController.java @@ -0,0 +1,25 @@ +package fr.gaulupeau.apps.Poche.ui; + +import android.webkit.JavascriptInterface; + +public class JsActionController { + + public interface Callback { + void selectedText(String text); + } + + private final Callback callback; + + public JsActionController(Callback callback) { + this.callback = callback; + } + + @SuppressWarnings("unused") + @JavascriptInterface + public void selectedText(String text) { + if (callback != null) { + callback.selectedText(text); + } + } + +} diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java b/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java index 67ef50bda..9f09b8f07 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/ui/ReadArticleActivity.java @@ -406,17 +406,21 @@ public void onActionModeStarted(ActionMode mode) { mode.getMenuInflater().inflate(R.menu.read_article_activity, menu); menu.findItem(R.id.menu_tag).setOnMenuItemClickListener(item -> { - webViewContent.evaluateJavascript( - "(function(){return window.getSelection().toString()})()", - this::createTagFromSelection); - mode.finish(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + webViewContent.evaluateJavascript( + "(function(){return window.getSelection().toString()})()", + this::createTagFromSelection); + mode.finish(); + } else { + webViewContent.loadUrl("javascript:hostActionController.selectedText(window.getSelection().toString())"); + } return true; }); MenuItem annotateItem = menu.findItem(R.id.menu_annotate); if (annotationsEnabled) { annotateItem.setOnMenuItemClickListener(i -> { - webViewContent.evaluateJavascript("invokeAnnotator();", null); + webViewContent.loadUrl("javascript:invokeAnnotator()"); // mode.finish(); // seems to reset selection too early (not on emulator though) return true; }); @@ -622,6 +626,7 @@ private void updatePrevNextButtons() { private void initWebView() { webViewContent.getSettings().setJavaScriptEnabled(true); + initJsActionController(); initTtsController(); initAnnotationController(); @@ -790,6 +795,12 @@ public boolean onSingleTapConfirmed(MotionEvent e) { webViewContent.setOnTouchListener((v, event) -> gestureDetector.onTouchEvent(event)); } + private void initJsActionController() { + JsActionController jsActionController = new JsActionController(this::createTagFromSelection); + + webViewContent.addJavascriptInterface(jsActionController, "hostActionController"); + } + private void initTtsController() { // add the controller now even if TTS is not used, // otherwise it won't be possible to enable TTS without content reloading From e2876560a6114b8905b0d1c6f31021a247050ab9 Mon Sep 17 00:00:00 2001 From: Dmitriy Bogdanov Date: Mon, 30 Nov 2020 20:43:52 +0400 Subject: [PATCH 08/11] Android 4 TTS compatibility --- .../gaulupeau/apps/Poche/tts/TtsService.java | 84 ++++++++++--------- .../gaulupeau/apps/Poche/tts/WebViewText.java | 4 +- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TtsService.java b/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TtsService.java index ccf13c9f1..fce4c9ca8 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TtsService.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/tts/TtsService.java @@ -833,55 +833,59 @@ private void onTtsInit(int status) { state = State.CREATED; } - tts.setOnUtteranceProgressListener(new UtteranceProgressListener() { - @Override - public void onStart(String utteranceId) { -// Log.v(TAG, "utteranceProgressListener.onStart()"); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + tts.setOnUtteranceProgressListener(new UtteranceProgressListener() { + @Override + public void onStart(String utteranceId) { + // Log.v(TAG, "utteranceProgressListener.onStart()"); - setCurrentItemProgress(utteranceId, -1, -1); - } + setCurrentItemProgress(utteranceId, -1, -1); + } - @Override - public synchronized void onDone(String utteranceId) { - onSpeakDoneListener(utteranceId); - } + @Override + public synchronized void onDone(String utteranceId) { + onSpeakDoneListener(utteranceId); + } - @Override - public void onError(String utteranceId, int errorCode) { - Log.w(TAG, "utteranceProgressListener.onError() " + utteranceId - + ", errorCode: " + errorCode); - super.onError(utteranceId, errorCode); - } + @Override + public void onError(String utteranceId, int errorCode) { + Log.w(TAG, "utteranceProgressListener.onError() " + utteranceId + + ", errorCode: " + errorCode); + super.onError(utteranceId, errorCode); + } - @Override - public void onError(String utteranceId) { - Log.w(TAG, "utteranceProgressListener.onError() " + utteranceId); + @Override + public void onError(String utteranceId) { + Log.w(TAG, "utteranceProgressListener.onError() " + utteranceId); - resetCurrentItemProgress(); + resetCurrentItemProgress(); - onSpeakDoneListener(utteranceId); - } + onSpeakDoneListener(utteranceId); + } - @Override - public void onStop(String utteranceId, boolean interrupted) { - Log.d(TAG, "utteranceProgressListener.onStop() " + utteranceId - + ", " + interrupted); + @Override + public void onStop(String utteranceId, boolean interrupted) { + Log.d(TAG, "utteranceProgressListener.onStop() " + utteranceId + + ", " + interrupted); - resetCurrentItemProgress(); + resetCurrentItemProgress(); - onSpeakDoneListener(utteranceId); - } + onSpeakDoneListener(utteranceId); + } - @Override - public void onRangeStart(String utteranceId, int start, int end, int frame) { - super.onRangeStart(utteranceId, start, end, frame); + @Override + public void onRangeStart(String utteranceId, int start, int end, int frame) { + super.onRangeStart(utteranceId, start, end, frame); -// Log.v(TAG, String.format("utteranceProgressListener.onRangeStart(%s, %d, %d, %d)", -// utteranceId, start, end, frame)); + // Log.v(TAG, String.format("utteranceProgressListener.onRangeStart(%s, %d, %d, %d)", + // utteranceId, start, end, frame)); - setCurrentItemProgress(utteranceId, start, end); - } - }); + setCurrentItemProgress(utteranceId, start, end); + } + }); + } else { + tts.setOnUtteranceCompletedListener(this::onSpeakDoneListener); + } tts.setLanguage(convertVoiceNameToLocale(ttsVoice)); @@ -942,7 +946,11 @@ public void setEngineAndVoice(String engine, String voice) { final TextToSpeech ttsToShutdown = tts; new Thread(() -> { - ttsToShutdown.setOnUtteranceProgressListener(null); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + ttsToShutdown.setOnUtteranceProgressListener(null); + } else { + ttsToShutdown.setOnUtteranceCompletedListener(null); + } ttsToShutdown.stop(); ttsToShutdown.shutdown(); }).start(); diff --git a/app/src/main/java/fr/gaulupeau/apps/Poche/tts/WebViewText.java b/app/src/main/java/fr/gaulupeau/apps/Poche/tts/WebViewText.java index 3969f6541..2bbb70a92 100644 --- a/app/src/main/java/fr/gaulupeau/apps/Poche/tts/WebViewText.java +++ b/app/src/main/java/fr/gaulupeau/apps/Poche/tts/WebViewText.java @@ -59,8 +59,8 @@ void parseWebViewDocument(Runnable callback) { parsingFinishedCallback = callback; ttsHost.getJsTtsController().setWebViewText(this); - ttsHost.getWebView().evaluateJavascript("javascript:" + JS_PARSE_DOCUMENT_SCRIPT - + ";parseDocumentText();", null); + ttsHost.getWebView().loadUrl("javascript:" + JS_PARSE_DOCUMENT_SCRIPT); + ttsHost.getWebView().loadUrl("javascript:parseDocumentText()"); } void onDocumentParseStart() { From 449482deeb678a745b787ee22952cb197e4f4b57 Mon Sep 17 00:00:00 2001 From: Dmitriy Bogdanov Date: Mon, 30 Nov 2020 20:59:35 +0400 Subject: [PATCH 09/11] Android 4 styles compatibility Partial revert of 05a85e711a0c43f5b86fa96beb7b5aa3eb645a26 --- app/src/main/res/values-v21/styles.xml | 197 +++++++++++++++++++++++++ app/src/main/res/values/styles.xml | 18 +-- 2 files changed, 200 insertions(+), 15 deletions(-) create mode 100644 app/src/main/res/values-v21/styles.xml diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml new file mode 100644 index 000000000..1dc9082f5 --- /dev/null +++ b/app/src/main/res/values-v21/styles.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 4d155b2eb..fe5d947a3 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -50,8 +50,6 @@