From d682d780e0e36171bb2034e447e1bc6d9e58c478 Mon Sep 17 00:00:00 2001 From: Herbert Reiter <4941275-moasda@users.noreply.gitlab.com> Date: Sun, 27 Dec 2020 22:01:52 +0100 Subject: [PATCH] Update to moasdawiki-server 2.4.1, replace deprecated AsyncTask usage --- .../java/net/moasdawiki/app/MainActivity.java | 144 +++++++----------- .../net/moasdawiki/app/SettingsFragment.java | 52 +++---- .../moasdawiki/app/SynchronizeWikiClient.java | 19 +-- 3 files changed, 89 insertions(+), 126 deletions(-) diff --git a/app/src/main/java/net/moasdawiki/app/MainActivity.java b/app/src/main/java/net/moasdawiki/app/MainActivity.java index 5ebe116..35495ed 100644 --- a/app/src/main/java/net/moasdawiki/app/MainActivity.java +++ b/app/src/main/java/net/moasdawiki/app/MainActivity.java @@ -25,7 +25,6 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; -import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; @@ -73,9 +72,11 @@ import java.util.Calendar; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** - * Steuert das Verhalten des Hauptfensters inkl. eingebettetem Browser. + * Displays the main window with the embedded wiki browser. */ public class MainActivity extends AppCompatActivity { @@ -88,22 +89,22 @@ public class MainActivity extends AppCompatActivity { private RequestDispatcher requestDispatcher; private WebView webview; - private long backButtonPressedTimestamp; + private ExecutorService synchronizationExecutorService; + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); - // AndroidMainService holen WikiEngineApplication app = (WikiEngineApplication) getApplication(); repositoryService = app.getRepositoryService(); settings = app.getSettings(); synchronizeWikiClient = app.getSynchronizeWikiClient(); requestDispatcher = app.getRequestDispatcher(); + synchronizationExecutorService = Executors.newSingleThreadExecutor(); - // eingebetteten Browser konfigurieren initWebView(); EditText searchInput = findViewById(R.id.search_input); @@ -120,31 +121,29 @@ public class MainActivity extends AppCompatActivity { } /** - * Konfiguriert den eingebetteten Browser. + * Configure the embedded web browser. */ @SuppressLint("SetJavaScriptEnabled") private void initWebView() { - // Cookies deaktivieren CookieManager cookieManager = CookieManager.getInstance(); cookieManager.setAcceptCookie(false); - // localhost-URLs in WebView anzeigen webview = findViewById(R.id.web_browser); webview.setWebChromeClient(new WebChromeClient()); webview.setWebViewClient(new WebViewClient() { /** - * Steuert, welche Links im eingebetteten Browser und welche im externen Browser - * geöffnet werden sollen. + * Dispatch URLs the user clicks on. + * External URLs will be shown in an external browser. */ @Override public boolean shouldOverrideUrlLoading(@NotNull WebView view, @NotNull WebResourceRequest webResourceRequest) { Uri uri = webResourceRequest.getUrl(); String host = uri.getHost(); if ("localhost".equals(host)) { - // lokale URL im eingebetteten Browser öffnen + // wiki URL, show in embedded browser return false; } else { - // externe Links im normalen Browser öffnen + // external URL, show in external browser Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); return true; @@ -152,20 +151,21 @@ public class MainActivity extends AppCompatActivity { } /** - * Emuliert den Wikiserver und zu vermeiden, dass ein TCP-Port geöffnet werden muss. + * Resolve internal URLs without running a real HTTP server, + * so we don't have to open a port. */ @Override @Nullable public WebResourceResponse shouldInterceptRequest (@NotNull WebView view, @NotNull WebResourceRequest request) { try { - // URL-Pfad ermitteln + // determine URL path Uri uri = request.getUrl(); String encodedUrl = uri.toString(); String url = URLDecoder.decode(encodedUrl, "UTF-8"); if (!url.startsWith(SERVER_BASE_URL)) { - return null; // Daten per HTTP laden + return null; } - String urlPath = url.substring(SERVER_BASE_URL.length() - 1); // ersten "/" behalten + String urlPath = url.substring(SERVER_BASE_URL.length() - 1); // extract URL path int hashPos = urlPath.indexOf('#'); if (hashPos >= 0) { // cut off anchor beginning with '#' @@ -183,14 +183,14 @@ public class MainActivity extends AppCompatActivity { httpRequest.httpBody = new byte[0]; HttpResponse response = requestDispatcher.handleRequest(httpRequest); - // Antwortdaten einspeisen + // send wiki content to browser InputStream responseData = new ByteArrayInputStream(response.content); return new WebResourceResponse(response.contentType, "UTF-8", responseData); } catch (IOException e) { e.printStackTrace(); } - return null; // Daten per HTTP laden + return null; // load HTTP data } @Override @@ -200,7 +200,6 @@ public class MainActivity extends AppCompatActivity { } }); - // weitere Einstellungen WebSettings webSettings = webview.getSettings(); webSettings.setAllowFileAccess(false); webSettings.setJavaScriptEnabled(true); @@ -241,7 +240,7 @@ public class MainActivity extends AppCompatActivity { int itemId = item.getItemId(); if (itemId == R.id.action_synchronize) { - synchronizeServer(); + synchronizeWithServer(); return true; } else if (itemId == R.id.action_startpage) { loadUrl(SERVER_BASE_URL); @@ -269,7 +268,7 @@ public class MainActivity extends AppCompatActivity { @Override public void onBackPressed() { - // webview.canGoBack() liefert immer false + // webview.canGoBack() always returns false WebBackForwardList backForwardList = webview.copyBackForwardList(); Log.d(TAG, "Back button pressed, backForwardList index == " + backForwardList.getCurrentIndex()); if (backForwardList.getCurrentIndex() > 0) { @@ -294,7 +293,7 @@ public class MainActivity extends AppCompatActivity { } public void onSynchronizeHintClicked(View view) { - synchronizeServer(); + synchronizeWithServer(); } public void onSearch(View view) { @@ -317,8 +316,7 @@ public class MainActivity extends AppCompatActivity { String url = getWikiserverSearchUrl(query); loadUrl(url); - // Der Wartedialog wird nach dem Anzeigen der Suchergebnisse durch Aufruf von - // closeProgressDialog() geschlossen. + // The wait dialoge is closed by closeProgressDialog() after the search result is shown } private void showSettingsDialog() { @@ -327,7 +325,7 @@ public class MainActivity extends AppCompatActivity { } private void showAboutDialog() { - // Versionsnummer einsetzen + // insert version number @SuppressLint("InflateParams") View dialogView = getLayoutInflater().inflate(R.layout.about_layout, null); TextView versionText = dialogView.findViewById(R.id.label_version); @@ -336,7 +334,7 @@ public class MainActivity extends AppCompatActivity { TextView copyrightText = dialogView.findViewById(R.id.label_copyright); copyrightText.setText(getString(R.string.about_copyright, year)); - // Dialog anzeigen + // show dialog AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setView(dialogView); builder.setTitle(R.string.app_name); @@ -346,13 +344,44 @@ public class MainActivity extends AppCompatActivity { dialog.show(); } - private void synchronizeServer() { - SyncNowTask syncNowTask = new SyncNowTask(); - syncNowTask.execute(); + /** + * Called if user presses the synchronization button. + */ + private void synchronizeWithServer() { + synchronizationExecutorService.submit(this::runSynchronizationWithServer); } /** - * Öffnet die angegebene URL im eingebetteten Browser. + * Run synchronization of wiki content with wiki server. + * This method is run in an asynchronous background thread. + */ + private void runSynchronizationWithServer() { + int filesCount; + try { + filesCount = synchronizeWikiClient.synchronizeRepository(this::showProgressBar); + } catch (ServiceException e) { + Log.e(TAG, "Error synchronizing repository with server", e); + showToast(getString(R.string.settings_synchronize_failed)); + return; + } + + if (filesCount > 0) { + showToast(getString(R.string.settings_synchronize_successful, filesCount)); + + WikiEngineApplication app = (WikiEngineApplication) getApplication(); + app.resetServices(); + + CalendarSyncAdapter.requestCalendarSync(this); + } else { + showToast(getString(R.string.settings_synchronize_not_necessary)); + } + + hideProgressBar(); + updateLayoutVisibility(); + } + + /** + * Open a URL in the embedded browser. */ private void loadUrl(@NotNull String url) { Log.d(TAG, "Open URL " + url); @@ -433,59 +462,4 @@ public class MainActivity extends AppCompatActivity { Toast toast = Toast.makeText(this, message, Toast.LENGTH_SHORT); toast.show(); } - - /** - * Synchronisiert mit dem Wikiserver in einem separaten Thread. - */ - private class SyncNowTask extends AsyncTask implements SynchronizeWikiClient.ProgressFeedback { - - @Nullable - @Override - protected Integer doInBackground(Void... params) { - try { - return synchronizeWikiClient.synchronizeRepository(this); - } catch (ServiceException e) { - Log.e(TAG, "Error synchronizing repository", e); - } - return null; - } - - @Override - public void progress(int step, int total) { - ProgressData progressData = new ProgressData(); - progressData.step = step; - progressData.total = total; - publishProgress(progressData); - } - - @Override - protected void onProgressUpdate(ProgressData... progressData) { - showProgressBar(progressData[0].step, progressData[0].total); - } - - @Override - protected void onPostExecute(@Nullable Integer filesCount) { - CalendarSyncAdapter.requestCalendarSync(MainActivity.this); - - if (filesCount == null) { - showToast(getString(R.string.settings_synchronize_failed)); - } else if (filesCount > 0) { - showToast(getString(R.string.settings_synchronize_successful, filesCount)); - - // Reset internal file caches - WikiEngineApplication app = (WikiEngineApplication) getApplication(); - app.resetServices(); - } else { - showToast(getString(R.string.settings_synchronize_not_necessary)); - } - - hideProgressBar(); - updateLayoutVisibility(); - } - } - - private static class ProgressData { - public int step; - public int total; - } } diff --git a/app/src/main/java/net/moasdawiki/app/SettingsFragment.java b/app/src/main/java/net/moasdawiki/app/SettingsFragment.java index 16e5e0e..7b7183e 100644 --- a/app/src/main/java/net/moasdawiki/app/SettingsFragment.java +++ b/app/src/main/java/net/moasdawiki/app/SettingsFragment.java @@ -18,9 +18,7 @@ package net.moasdawiki.app; -import android.annotation.SuppressLint; import android.content.SharedPreferences; -import android.os.AsyncTask; import android.os.Bundle; import android.text.InputFilter; import android.text.InputType; @@ -35,11 +33,11 @@ import androidx.preference.PreferenceFragmentCompat; import net.moasdawiki.base.Settings; import net.moasdawiki.service.repository.RepositoryService; -import org.jetbrains.annotations.NotNull; - import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; public class SettingsFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -47,15 +45,16 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared private SynchronizeWikiClient synchronizeWikiClient; private RepositoryService repositoryService; private Settings settings; + private ExecutorService synchronizationExecutorService; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - //noinspection ConstantConditions WikiEngineApplication app = (WikiEngineApplication) getContext().getApplicationContext(); synchronizeWikiClient = app.getSynchronizeWikiClient(); - repositoryService = app.getServiceLocator().getRepositoryService(); - settings = app.getServiceLocator().getSettings(); + repositoryService = app.getRepositoryService(); + settings = app.getSettings(); + synchronizationExecutorService = Executors.newSingleThreadExecutor(); } @Override @@ -167,37 +166,30 @@ public class SettingsFragment extends PreferenceFragmentCompat implements Shared } } + /** + * Called if the user changes the connection settings to give fast feedback. + */ private void checkServerConnection() { - new ConnectServerTask().execute(); + synchronizationExecutorService.submit(this::runCheckServerConnection); } /** - * Checks the connection to the Wiki server. + * Run server connection check. + * This method is run in an asynchronous background thread. */ - @SuppressLint("StaticFieldLeak") - @SuppressWarnings("NonStaticInnerClassInSecureContext") - private class ConnectServerTask extends AsyncTask { - @Override - @NotNull - protected Boolean doInBackground(Void... params) { - SharedPreferences preferences = getPreferenceManager().getSharedPreferences(); - String host = preferences.getString(Constants.PREFERENCES_SYNC_SERVER_HOST, null); - if (host == null) { - Log.d(TAG, "Cancel ConnectServerTask because server host is not configured"); - return false; - } - - // Connect with server - return synchronizeWikiClient.createAndCheckSession(); + private void runCheckServerConnection() { + SharedPreferences preferences = getPreferenceManager().getSharedPreferences(); + String host = preferences.getString(Constants.PREFERENCES_SYNC_SERVER_HOST, null); + if (host == null) { + Log.d(TAG, "Cancel ConnectServerTask because server host is not configured"); + return; } - @Override - protected void onPostExecute(@NotNull Boolean success) { - updateStatusText(); + boolean success = synchronizeWikiClient.createAndCheckSession(); + updateStatusText(); - if (!success) { - showToast(getString(R.string.settings_search_failed)); - } + if (!success) { + showToast(getString(R.string.settings_search_failed)); } } } diff --git a/app/src/main/java/net/moasdawiki/app/SynchronizeWikiClient.java b/app/src/main/java/net/moasdawiki/app/SynchronizeWikiClient.java index 0c57f74..e88afbf 100644 --- a/app/src/main/java/net/moasdawiki/app/SynchronizeWikiClient.java +++ b/app/src/main/java/net/moasdawiki/app/SynchronizeWikiClient.java @@ -252,7 +252,7 @@ public class SynchronizeWikiClient { return 0; } - for (int i = 0; i < fileCount && !feedback.isCancelled(); i++) { + for (int i = 0; i < fileCount; i++) { feedback.progress(i, fileCount); SingleFileXml serverFile = response.fileList.get(i); try { @@ -268,14 +268,12 @@ public class SynchronizeWikiClient { app.resetServices(); // Update last sync time - if (!feedback.isCancelled()) { - Date currentServerDate = DateUtils.parseUtcDate(response.currentServerTime); - if (currentServerDate != null) { - long newLastSyncServerTimeMs = currentServerDate.getTime(); - SharedPreferences.Editor editor = preferences.edit(); - editor.putLong(Constants.PREFERENCES_SYNC_SERVER_TIME, newLastSyncServerTimeMs); - editor.apply(); - } + Date currentServerDate = DateUtils.parseUtcDate(response.currentServerTime); + if (currentServerDate != null) { + long newLastSyncServerTimeMs = currentServerDate.getTime(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putLong(Constants.PREFERENCES_SYNC_SERVER_TIME, newLastSyncServerTimeMs); + editor.apply(); } return fileCount; @@ -460,9 +458,8 @@ public class SynchronizeWikiClient { * Interface, um den Fortschritt während der Synchronisierung mit dem Server * zurückzuübermitteln. */ + @FunctionalInterface public interface ProgressFeedback { - @SuppressWarnings("BooleanMethodIsAlwaysInverted") - boolean isCancelled(); void progress(int step, int total); } }