From 20b218648e1caa45c132d2f3789bf6c14e7fd998 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 1 Nov 2017 14:48:32 +0300 Subject: offline: properly track and sync back modification of all relevant fields (unread, marked, published) offline: better reporting on upload failure, allow retrying in notification --- org.fox.ttrss/src/main/AndroidManifest.xml | 4 +- .../org/fox/ttrss/offline/OfflineActivity.java | 8 +- .../ttrss/offline/OfflineHeadlinesFragment.java | 10 +- .../fox/ttrss/offline/OfflineUploadService.java | 188 ++++++++++----------- .../java/org/fox/ttrss/util/DatabaseHelper.java | 6 +- org.fox.ttrss/src/main/res/values/strings.xml | 1 + 6 files changed, 105 insertions(+), 112 deletions(-) (limited to 'org.fox.ttrss/src') diff --git a/org.fox.ttrss/src/main/AndroidManifest.xml b/org.fox.ttrss/src/main/AndroidManifest.xml index 9ccb17a7..7da0802a 100755 --- a/org.fox.ttrss/src/main/AndroidManifest.xml +++ b/org.fox.ttrss/src/main/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="458" + android:versionName="1.224"> diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineActivity.java index 0a0c3787..ce243d1e 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineActivity.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineActivity.java @@ -437,7 +437,7 @@ public class OfflineActivity extends CommonActivity { int articleId = oap.getSelectedArticleId(); SQLiteStatement stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, marked = NOT marked WHERE " + "UPDATE articles SET modified = 1, modified_marked = 1, marked = NOT marked WHERE " + BaseColumns._ID + " = ?"); stmt.bindLong(1, articleId); stmt.execute(); @@ -478,7 +478,7 @@ public class OfflineActivity extends CommonActivity { if (getSelectedArticleCount() > 0) { SQLiteStatement stmt = getDatabase() .compileStatement( - "UPDATE articles SET modified = 1, marked = NOT marked WHERE selected = 1"); + "UPDATE articles SET modified = 1, modified_marked = 1, marked = NOT marked WHERE selected = 1"); stmt.execute(); stmt.close(); @@ -489,7 +489,7 @@ public class OfflineActivity extends CommonActivity { if (getSelectedArticleCount() > 0) { SQLiteStatement stmt = getDatabase() .compileStatement( - "UPDATE articles SET modified = 1, published = NOT published WHERE selected = 1"); + "UPDATE articles SET modified = 1, modified_published = 1, published = NOT published WHERE selected = 1"); stmt.execute(); stmt.close(); @@ -501,7 +501,7 @@ public class OfflineActivity extends CommonActivity { int articleId = oap.getSelectedArticleId(); SQLiteStatement stmt = getDatabase().compileStatement( - "UPDATE articles SET modified = 1, published = NOT published WHERE " + "UPDATE articles SET modified = 1, modified_published = 1, published = NOT published WHERE " + BaseColumns._ID + " = ?"); stmt.bindLong(1, articleId); stmt.execute(); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesFragment.java index 92d6e3c0..2d701d62 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineHeadlinesFragment.java @@ -821,8 +821,9 @@ public class OfflineHeadlinesFragment extends Fragment implements OnItemClickLis @Override public void onClick(View v) { - SQLiteStatement stmtUpdate = m_activity.getDatabase().compileStatement("UPDATE articles SET modified = 1, marked = NOT marked " + - "WHERE " + BaseColumns._ID + " = ?"); + SQLiteStatement stmtUpdate = m_activity.getDatabase() + .compileStatement("UPDATE articles SET modified = 1, modified_marked = 1, marked = NOT marked " + + "WHERE " + BaseColumns._ID + " = ?"); stmtUpdate.bindLong(1, articleId); stmtUpdate.execute(); @@ -851,8 +852,9 @@ public class OfflineHeadlinesFragment extends Fragment implements OnItemClickLis @Override public void onClick(View v) { - SQLiteStatement stmtUpdate = m_activity.getDatabase().compileStatement("UPDATE articles SET modified = 1, published = NOT published " + - "WHERE " + BaseColumns._ID + " = ?"); + SQLiteStatement stmtUpdate = m_activity.getDatabase() + .compileStatement("UPDATE articles SET modified = 1, modified_published = 1, published = NOT published " + + "WHERE " + BaseColumns._ID + " = ?"); stmtUpdate.bindLong(1, articleId); stmtUpdate.execute(); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineUploadService.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineUploadService.java index 04effd7f..cba0914c 100644 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineUploadService.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/offline/OfflineUploadService.java @@ -21,7 +21,9 @@ import org.fox.ttrss.OnlineActivity; import org.fox.ttrss.R; import org.fox.ttrss.util.DatabaseHelper; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; public class OfflineUploadService extends IntentService { private final String TAG = this.getClass().getSimpleName(); @@ -54,7 +56,7 @@ public class OfflineUploadService extends IntentService { } @SuppressWarnings("deprecation") - private void updateNotification(String msg, int progress, int max, boolean showProgress) { + private void updateNotification(String msg, int progress, int max, boolean showProgress, boolean isError) { PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, OnlineActivity.class), 0); @@ -63,11 +65,10 @@ public class OfflineUploadService extends IntentService { .setContentTitle(getString(R.string.notify_uploading_title)) .setContentIntent(contentIntent) .setWhen(System.currentTimeMillis()) - .setProgress(0, 0, true) .setSmallIcon(R.drawable.ic_cloud_upload) .setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.ic_launcher)) - .setOngoing(true) + .setOngoing(!isError) .setOnlyAlertOnce(true) .setVibrate(new long[0]); @@ -77,14 +78,15 @@ public class OfflineUploadService extends IntentService { builder.setCategory(Notification.CATEGORY_PROGRESS) .setVisibility(Notification.VISIBILITY_PUBLIC) .setColor(0x88b0f0) - .setGroup("org.fox.ttrss"); + .setGroup("org.fox.ttrss") + .addAction(R.drawable.ic_launcher, getString(R.string.offline_sync_try_again), contentIntent); } m_nmgr.notify(NOTIFY_UPLOADING, builder.build()); } - private void updateNotification(int msgResId, int progress, int max, boolean showProgress) { - updateNotification(getString(msgResId), progress, max, showProgress); + private void updateNotification(int msgResId, int progress, int max, boolean showProgress, boolean isError) { + updateNotification(getString(msgResId), progress, max, showProgress, isError); } private void initDatabase() { @@ -94,47 +96,12 @@ public class OfflineUploadService extends IntentService { private synchronized SQLiteDatabase getDatabase() { return m_databaseHelper.getWritableDatabase(); } - - private void uploadRead() { - Log.d(TAG, "syncing modified offline data... (read)"); - - final String ids = getModifiedIds(ModifiedCriteria.READ); - - if (ids.length() > 0) { - ApiRequest req = new ApiRequest(getApplicationContext()) { - @Override - protected void onPostExecute(JsonElement result) { - if (result != null) { - uploadMarked(); - } else { - updateNotification(getErrorMessage(), 0, 0, false); - uploadFailed(); - } - } - }; - - @SuppressWarnings("serial") - HashMap map = new HashMap() { - { - put("sid", m_sessionId); - put("op", "updateArticle"); - put("article_ids", ids); - put("mode", "0"); - put("field", "2"); - } - }; - req.execute(map); - } else { - uploadMarked(); - } - } - private enum ModifiedCriteria { - READ, MARKED, PUBLISHED + READ, MARKED, UNMARKED, PUBLISHED, UNPUBLISHED } - private String getModifiedIds(ModifiedCriteria criteria) { + private List getModifiedIds(ModifiedCriteria criteria) { String criteriaStr = ""; @@ -143,67 +110,34 @@ public class OfflineUploadService extends IntentService { criteriaStr = "unread = 0"; break; case MARKED: - criteriaStr = "marked = 1"; + criteriaStr = "modified_marked = 1 AND marked = 1"; + break; + case UNMARKED: + criteriaStr = "modified_marked = 1 AND marked = 0"; break; case PUBLISHED: - criteriaStr = "published = 1"; + criteriaStr = "modified_published = 1 AND published = 1"; + break; + case UNPUBLISHED: + criteriaStr = "modified_published = 1 AND published = 0"; break; } Cursor c = getDatabase().query("articles", null, "modified = 1 AND " + criteriaStr, null, null, null, null); - String tmp = ""; + List tmp = new ArrayList<>(); while (c.moveToNext()) { - tmp += c.getInt(0) + ","; + tmp.add(c.getInt(0)); } - tmp = tmp.replaceAll(",$", ""); - c.close(); return tmp; } - private void uploadMarked() { - Log.d(TAG, "syncing modified offline data... (marked)"); - - final String ids = getModifiedIds(ModifiedCriteria.MARKED); - - if (ids.length() > 0) { - ApiRequest req = new ApiRequest(getApplicationContext()) { - @Override - protected void onPostExecute(JsonElement result) { - if (result != null) { - uploadPublished(); - } else { - updateNotification(getErrorMessage(), 0, 0, false); - uploadFailed(); - } - } - }; - - @SuppressWarnings("serial") - HashMap map = new HashMap() { - { - put("sid", m_sessionId); - put("op", "updateArticle"); - put("article_ids", ids); - put("mode", "1"); - put("field", "0"); - } - }; - - req.execute(map); - } else { - uploadPublished(); - } - } - private void uploadFailed() { - // TODO send notification to activity? - m_uploadInProgress = false; } @@ -228,20 +162,27 @@ public class OfflineUploadService extends IntentService { m_nmgr.cancel(NOTIFY_UPLOADING); } - - private void uploadPublished() { - Log.d(TAG, "syncing modified offline data... (published)"); - final String ids = getModifiedIds(ModifiedCriteria.PUBLISHED); + interface CriteriaCallback { + void onUploadSuccess(); + } - if (ids.length() > 0) { + private void uploadByCriteria(final ModifiedCriteria criteria, final CriteriaCallback callback) { + + final List ids = getModifiedIds(criteria); + + Log.d(TAG, "syncing modified offline data for " + criteria + ": " + ids); + + if (ids.size() > 0) { ApiRequest req = new ApiRequest(getApplicationContext()) { @Override protected void onPostExecute(JsonElement result) { if (result != null) { - uploadSuccess(); + callback.onUploadSuccess(); } else { - updateNotification(getErrorMessage(), 0, 0, false); + Log.d(TAG, "syncing failed: " + getErrorMessage()); + + updateNotification(getErrorMessage(), 0, 0, false, true); uploadFailed(); } } @@ -252,19 +193,39 @@ public class OfflineUploadService extends IntentService { { put("sid", m_sessionId); put("op", "updateArticle"); - put("article_ids", ids); - put("mode", "1"); - put("field", "1"); + put("article_ids", android.text.TextUtils.join(",", ids)); + + switch (criteria) { + case READ: + put("mode", "0"); + put("field", "2"); + break; + case PUBLISHED: + put("mode", "1"); + put("field", "1"); + break; + case UNPUBLISHED: + put("mode", "0"); + put("field", "1"); + break; + case MARKED: + put("mode", "1"); + put("field", "0"); + break; + case UNMARKED: + put("mode", "0"); + put("field", "0"); + break; + } } }; req.execute(map); } else { - uploadSuccess(); + callback.onUploadSuccess(); } } - @Override protected void onHandleIntent(Intent intent) { try { @@ -278,9 +239,36 @@ public class OfflineUploadService extends IntentService { if (!m_uploadInProgress) { m_uploadInProgress = true; - updateNotification(R.string.notify_uploading_sending_data, 0, 0, true); + updateNotification(R.string.notify_uploading_sending_data, 0, 0, true, true); - uploadRead(); + uploadByCriteria(ModifiedCriteria.READ, new CriteriaCallback() { + @Override + public void onUploadSuccess() { + uploadByCriteria(ModifiedCriteria.MARKED, new CriteriaCallback() { + @Override + public void onUploadSuccess() { + uploadByCriteria(ModifiedCriteria.UNMARKED, new CriteriaCallback() { + @Override + public void onUploadSuccess() { + uploadByCriteria(ModifiedCriteria.PUBLISHED, new CriteriaCallback() { + @Override + public void onUploadSuccess() { + uploadByCriteria(ModifiedCriteria.UNPUBLISHED, new CriteriaCallback() { + @Override + public void onUploadSuccess() { + Log.d(TAG, "upload complete"); + + uploadSuccess(); + } + }); + } + }); + } + }); + } + }); + } + }); } } catch (Exception e) { e.printStackTrace(); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/util/DatabaseHelper.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/util/DatabaseHelper.java index 114f598b..e80f7116 100644 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/util/DatabaseHelper.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/util/DatabaseHelper.java @@ -12,7 +12,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { @SuppressWarnings("unused") private final String TAG = this.getClass().getSimpleName(); public static final String DATABASE_NAME = "OfflineStorage.db"; - public static final int DATABASE_VERSION = 4; + public static final int DATABASE_VERSION = 5; private static DatabaseHelper m_instance; private Context m_context; @@ -67,7 +67,9 @@ public class DatabaseHelper extends SQLiteOpenHelper { "content TEXT, " + "author TEXT, " + "selected BOOLEAN, " + - "modified BOOLEAN" + + "modified BOOLEAN," + + "modified_published BOOLEAN," + + "modified_marked BOOLEAN" + ");"); db.execSQL("CREATE TRIGGER articles_set_modified UPDATE OF marked, published, unread ON articles " + diff --git a/org.fox.ttrss/src/main/res/values/strings.xml b/org.fox.ttrss/src/main/res/values/strings.xml index dd6f6fed..00f43b22 100755 --- a/org.fox.ttrss/src/main/res/values/strings.xml +++ b/org.fox.ttrss/src/main/res/values/strings.xml @@ -256,5 +256,6 @@ This interval is imprecise due to Android limitations Group headlines by feeds Reload + Try again Tap to switch offline -- cgit v1.2.3