mirror of
https://github.com/viq/NewsBlur.git
synced 2025-09-18 21:43:31 +00:00
Merge pull request #367 from ojiikun/master
Android: Mark Read by Hash, Refactoring, Bugfixes
This commit is contained in:
commit
51a5d955e5
20 changed files with 156 additions and 261 deletions
|
@ -106,6 +106,9 @@
|
|||
|
||||
<string name="toast_story_unread">Story marked as unread</string>
|
||||
<string name="toast_story_unread_error">Error marking story as unread</string>
|
||||
|
||||
<string name="toast_feed_deleted">Feed deleted</string>
|
||||
<string name="toast_feed_delete_error">There was an error deleting the feed.</string>
|
||||
|
||||
<string name="logout_warning">Are you sure you want to log out?</string>
|
||||
|
||||
|
@ -117,7 +120,6 @@
|
|||
<string name="menu_mark_all_as_read">Mark all as read</string>
|
||||
<string name="menu_logout">Log out</string>
|
||||
|
||||
<string name="error_deleting_feed">There was an error deleting the feed.</string>
|
||||
<string name="login_registration_register">Register</string>
|
||||
<string name="login_google_reader">Google Reader</string>
|
||||
<string name="login_add_sites_from_google_reader">Import your sites from Google Reader</string>
|
||||
|
|
|
@ -66,7 +66,7 @@ public class AllSharedStoriesItemsList extends ItemsList {
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_MULTISOCIALFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.MULTISOCIALFEED_UPDATE);
|
||||
|
||||
String[] feeds = new String[feedIds.size()];
|
||||
feedIds.toArray(feeds);
|
||||
|
|
|
@ -79,7 +79,7 @@ public class AllSharedStoriesReading extends Reading {
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_MULTISOCIALFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.MULTISOCIALFEED_UPDATE);
|
||||
|
||||
String[] feeds = new String[feedIds.size()];
|
||||
feedIds.toArray(feeds);
|
||||
|
|
|
@ -69,7 +69,7 @@ public class AllStoriesItemsList extends ItemsList implements MarkAllReadDialogL
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_MULTIFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.MULTIFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_MULTIFEED_IDS, new String[0]); // the API will return all feeds if no IDs are passed
|
||||
intent.putExtra(SyncService.EXTRA_TASK_PAGE_NUMBER, Integer.toString(page));
|
||||
intent.putExtra(SyncService.EXTRA_TASK_ORDER, getStoryOrder());
|
||||
|
|
|
@ -76,7 +76,7 @@ public class AllStoriesReading extends Reading {
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_MULTIFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.MULTIFEED_UPDATE);
|
||||
|
||||
String[] feeds = new String[feedIds.size()];
|
||||
feedIds.toArray(feeds);
|
||||
|
|
|
@ -129,7 +129,7 @@ public class FeedItemsList extends ItemsList {
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_FEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.FEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_PAGE_NUMBER, Integer.toString(page));
|
||||
intent.putExtra(SyncService.EXTRA_TASK_FEED_ID, feedId);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_ORDER, getStoryOrder());
|
||||
|
|
|
@ -96,7 +96,7 @@ public class FeedReading extends Reading {
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_FEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.FEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_FEED_ID, feedId);
|
||||
if (page > 1) {
|
||||
intent.putExtra(SyncService.EXTRA_TASK_PAGE_NUMBER, Integer.toString(page));
|
||||
|
|
|
@ -87,7 +87,7 @@ public class FolderItemsList extends ItemsList implements MarkAllReadDialogListe
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_MULTIFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.MULTIFEED_UPDATE);
|
||||
String[] feeds = new String[feedIds.size()];
|
||||
feedIds.toArray(feeds);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_MULTIFEED_IDS, feeds);
|
||||
|
|
|
@ -54,7 +54,7 @@ public class FolderReading extends Reading {
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_MULTIFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.MULTIFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_MULTIFEED_IDS, feedIds);
|
||||
|
||||
if (page > 1) {
|
||||
|
|
|
@ -77,7 +77,7 @@ public class Main extends NbFragmentActivity implements StateChangedListener, Sy
|
|||
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_FOLDER_UPDATE_TWO_STEP);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.FOLDER_UPDATE_TWO_STEP);
|
||||
startService(intent);
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ public class Main extends NbFragmentActivity implements StateChangedListener, Sy
|
|||
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_FOLDER_UPDATE_WITH_COUNT);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.FOLDER_UPDATE_WITH_COUNT);
|
||||
startService(intent);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ public class SavedStoriesItemsList extends ItemsList {
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_STARRED_STORIES_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.STARRED_STORIES_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_PAGE_NUMBER, Integer.toString(page));
|
||||
startService(intent);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ public class SavedStoriesReading extends Reading {
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_STARRED_STORIES_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.STARRED_STORIES_UPDATE);
|
||||
if (page > 1) {
|
||||
intent.putExtra(SyncService.EXTRA_TASK_PAGE_NUMBER, Integer.toString(page));
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ public class SocialFeedItemsList extends ItemsList {
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_SOCIALFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.SOCIALFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_SOCIALFEED_ID, userId);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_PAGE_NUMBER, Integer.toString(page));
|
||||
intent.putExtra(SyncService.EXTRA_TASK_SOCIALFEED_USERNAME, username);
|
||||
|
|
|
@ -64,7 +64,7 @@ public class SocialFeedReading extends Reading {
|
|||
setSupportProgressBarIndeterminateVisibility(true);
|
||||
final Intent intent = new Intent(Intent.ACTION_SYNC, null, this, SyncService.class);
|
||||
intent.putExtra(SyncService.EXTRA_STATUS_RECEIVER, syncFragment.receiver);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_SOCIALFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_TYPE, SyncService.TaskType.SOCIALFEED_UPDATE);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_SOCIALFEED_ID, userId);
|
||||
if (page > 1) {
|
||||
intent.putExtra(SyncService.EXTRA_TASK_PAGE_NUMBER, Integer.toString(page));
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.newsblur.R;
|
|||
import com.newsblur.activity.Main;
|
||||
import com.newsblur.database.FeedProvider;
|
||||
import com.newsblur.network.APIManager;
|
||||
import com.newsblur.util.FeedUtils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
|
@ -24,8 +25,6 @@ public class DeleteFeedFragment extends DialogFragment {
|
|||
private static final String FEED_NAME = "feed_name";
|
||||
private static final String FOLDER_NAME = "folder_name";
|
||||
|
||||
private APIManager apiManager;
|
||||
|
||||
public static DeleteFeedFragment newInstance(final long feedId, final String feedName, final String folderName) {
|
||||
DeleteFeedFragment frag = new DeleteFeedFragment();
|
||||
Bundle args = new Bundle();
|
||||
|
@ -53,57 +52,27 @@ public class DeleteFeedFragment extends DialogFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
final String deleteFeedString = getResources().getString(R.string.delete_feed_message);
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
|
||||
apiManager = new APIManager(getActivity());
|
||||
View v = inflater.inflate(R.layout.fragment_confirm_dialog, null);
|
||||
TextView messageView = (TextView) v.findViewById(R.id.dialog_message);
|
||||
messageView.setText(String.format(deleteFeedString, getArguments().getString(FEED_NAME)));
|
||||
messageView.setText(String.format(getResources().getString(R.string.delete_feed_message), getArguments().getString(FEED_NAME)));
|
||||
|
||||
Button okayButton = (Button) v.findViewById(R.id.dialog_button_okay);
|
||||
okayButton.setOnClickListener(new OnClickListener() {
|
||||
okayButton.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(final View v) {
|
||||
v.setEnabled(false);
|
||||
FeedUtils.deleteFeed(getArguments().getLong(FEED_ID), getArguments().getString(FOLDER_NAME), getActivity(), new APIManager(getActivity()));
|
||||
// if called from main view then refresh otherwise it was
|
||||
// called from the feed view so finish
|
||||
Activity activity = DeleteFeedFragment.this.getActivity();
|
||||
if (activity instanceof Main) {
|
||||
((Main)activity).updateAfterSync();
|
||||
} else {
|
||||
activity.finish();
|
||||
}
|
||||
DeleteFeedFragment.this.dismiss();
|
||||
}
|
||||
|
||||
new AsyncTask<Void, Void, Boolean>() {
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... arg) {
|
||||
long feedId = getArguments().getLong(FEED_ID);
|
||||
String folderName = getArguments().getString(FOLDER_NAME);
|
||||
if (apiManager.deleteFeed(feedId, folderName)) {
|
||||
Uri feedUri = FeedProvider.FEEDS_URI.buildUpon().appendPath(Long.toString(feedId)).build();
|
||||
DeleteFeedFragment.this.getActivity().getContentResolver().delete(feedUri, null, null);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
Activity activity = DeleteFeedFragment.this.getActivity();
|
||||
if (result) {
|
||||
Toast.makeText(activity, "Deleted feed", Toast.LENGTH_SHORT).show();
|
||||
DeleteFeedFragment.this.dismiss();
|
||||
// if called from main view then refresh otherwise it was
|
||||
// called from the feed view so finish
|
||||
if (activity instanceof Main) {
|
||||
((Main)activity).updateAfterSync();
|
||||
}
|
||||
else {
|
||||
activity.finish();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(activity, getResources().getString(R.string.error_deleting_feed), Toast.LENGTH_LONG).show();
|
||||
DeleteFeedFragment.this.dismiss();
|
||||
}
|
||||
};
|
||||
}.execute();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Button cancelButton = (Button) v.findViewById(R.id.dialog_button_cancel);
|
||||
|
|
|
@ -34,38 +34,35 @@ public class SyncUpdateFragment extends Fragment implements Receiver {
|
|||
|
||||
@Override
|
||||
public void onReceiverResult(int resultCode, Bundle resultData) {
|
||||
switch (resultCode) {
|
||||
case SyncService.STATUS_FINISHED:
|
||||
final SyncService.SyncStatus resultStatus = SyncService.SyncStatus.values()[resultCode];
|
||||
switch (resultStatus) {
|
||||
case STATUS_FINISHED:
|
||||
syncRunning = false;
|
||||
if (getActivity() != null) {
|
||||
((SyncUpdateFragmentInterface) getActivity()).updateAfterSync();
|
||||
}
|
||||
break;
|
||||
case SyncService.STATUS_PARTIAL_PROGRESS:
|
||||
case STATUS_PARTIAL_PROGRESS:
|
||||
syncRunning = true;
|
||||
if (getActivity() != null) {
|
||||
((SyncUpdateFragmentInterface) getActivity()).updatePartialSync();
|
||||
}
|
||||
break;
|
||||
case SyncService.STATUS_FINISHED_CLOSE:
|
||||
case STATUS_FINISHED_CLOSE:
|
||||
syncRunning = false;
|
||||
if (getActivity() != null) {
|
||||
((SyncUpdateFragmentInterface) getActivity()).closeAfterUpdate();
|
||||
}
|
||||
break;
|
||||
case SyncService.STATUS_RUNNING:
|
||||
case STATUS_RUNNING:
|
||||
syncRunning = true;
|
||||
break;
|
||||
case SyncService.STATUS_NO_MORE_UPDATES:
|
||||
case STATUS_NO_MORE_UPDATES:
|
||||
syncRunning = false;
|
||||
if (getActivity() != null) {
|
||||
((SyncUpdateFragmentInterface) getActivity()).setNothingMoreToUpdate();
|
||||
}
|
||||
break;
|
||||
case SyncService.STATUS_ERROR:
|
||||
syncRunning = false;
|
||||
Log.e(this.getClass().getName(), "Sync completed with an error.");
|
||||
break;
|
||||
default:
|
||||
syncRunning = false;
|
||||
Log.e(this.getClass().getName(), "Sync completed with an unknown result.");
|
||||
|
|
|
@ -22,22 +22,17 @@ public class APIConstants {
|
|||
public static final String URL_FEED_COUNTS = "http://newsblur.com/reader/refresh_feeds/";
|
||||
public static final String URL_MARK_FEED_AS_READ = "http://newsblur.com/reader/mark_feed_as_read/";
|
||||
public static final String URL_MARK_ALL_AS_READ = "http://newsblur.com/reader/mark_all_as_read/";
|
||||
public static final String URL_MARK_STORY_AS_READ = "http://newsblur.com/reader/mark_story_as_read/";
|
||||
public static final String URL_MARK_FEED_STORIES_AS_READ = "http://newsblur.com/reader/mark_feed_stories_as_read/";
|
||||
public static final String URL_MARK_SOCIALSTORY_AS_READ = "http://newsblur.com/reader/mark_social_stories_as_read/";
|
||||
public static final String URL_MARK_STORIES_READ = "http://newsblur.com/reader/mark_story_hashes_as_read/";
|
||||
public static final String URL_SHARE_STORY = "http://newsblur.com/social/share_story";
|
||||
public static final String URL_MARK_STORY_AS_STARRED = "http://newsblur.com/reader/mark_story_as_starred/";
|
||||
public static final String URL_MARK_STORY_AS_UNREAD = "http://newsblur.com/reader/mark_story_as_unread/";
|
||||
public static final String URL_STARRED_STORIES = "http://newsblur.com/reader/starred_stories";
|
||||
|
||||
public static final String URL_FEED_AUTOCOMPLETE = "http://newsblur.com/rss_feeds/feed_autocomplete";
|
||||
|
||||
public static final String URL_LIKE_COMMENT = "http://newsblur.com/social/like_comment";
|
||||
public static final String URL_UNLIKE_COMMENT = "http://newsblur.com/social/remove_like_comment";
|
||||
public static final String URL_REPLY_TO = "http://newsblur.com/social/save_comment_reply";
|
||||
public static final String URL_ADD_FEED = "http://newsblur.com/reader/add_url";
|
||||
public static final String URL_DELETE_FEED = "http://newsblur.com/reader/delete_feed";
|
||||
|
||||
public static final String URL_CLASSIFIER_SAVE = "http://newsblur.com/classifier/save";
|
||||
|
||||
public static final String PARAMETER_FEEDS = "feeds";
|
||||
|
@ -47,6 +42,7 @@ public class APIConstants {
|
|||
public static final String PARAMETER_EMAIL = "email";
|
||||
public static final String PARAMETER_USERID = "user_id";
|
||||
public static final String PARAMETER_STORYID = "story_id";
|
||||
public static final String PARAMETER_STORY_HASH = "story_hash";
|
||||
public static final String PARAMETER_FEEDS_STORIES = "feeds_stories";
|
||||
public static final String PARAMETER_FEED_SEARCH_TERM = "term";
|
||||
public static final String PARAMETER_FOLDER = "folder";
|
||||
|
|
|
@ -119,16 +119,14 @@ public class APIManager {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean markSocialStoryAsRead(final String updateJson) {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_MARKSOCIAL_JSON, updateJson);
|
||||
final APIResponse response = post(APIConstants.URL_MARK_SOCIALSTORY_AS_READ, values);
|
||||
if (!response.isError()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public NewsBlurResponse markStoriesAsRead(List<String> storyHashes) {
|
||||
ValueMultimap values = new ValueMultimap();
|
||||
for (String storyHash : storyHashes) {
|
||||
values.put(APIConstants.PARAMETER_STORY_HASH, storyHash);
|
||||
}
|
||||
APIResponse response = post(APIConstants.URL_MARK_STORIES_READ, values, false);
|
||||
return response.getResponse(gson, NewsBlurResponse.class);
|
||||
}
|
||||
|
||||
public NewsBlurResponse markStoryAsStarred(final String feedId, final String storyId) {
|
||||
final ValueMultimap values = new ValueMultimap();
|
||||
|
@ -653,15 +651,6 @@ public class APIManager {
|
|||
return (!response.isError());
|
||||
}
|
||||
|
||||
public boolean markMultipleStoriesAsRead(ContentValues values) {
|
||||
final APIResponse response = post(APIConstants.URL_MARK_FEED_STORIES_AS_READ, values);
|
||||
if (!response.isError()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addFeed(String feedUrl, String folderName) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_URL, feedUrl);
|
||||
|
@ -684,14 +673,14 @@ public class APIManager {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean deleteFeed(long feedId, String folderName) {
|
||||
public NewsBlurResponse deleteFeed(long feedId, String folderName) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_FEEDID, Long.toString(feedId));
|
||||
if (!TextUtils.isEmpty(folderName)) {
|
||||
if ((!TextUtils.isEmpty(folderName)) && (!folderName.equals(AppConstants.ROOT_FOLDER))) {
|
||||
values.put(APIConstants.PARAMETER_IN_FOLDER, folderName);
|
||||
}
|
||||
final APIResponse response = post(APIConstants.URL_DELETE_FEED, values);
|
||||
return (!response.isError());
|
||||
APIResponse response = post(APIConstants.URL_DELETE_FEED, values);
|
||||
return response.getResponse(gson, NewsBlurResponse.class);
|
||||
}
|
||||
|
||||
/* HTTP METHODS */
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.newsblur.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.app.IntentService;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
|
@ -22,15 +24,15 @@ import com.newsblur.util.ReadFilter;
|
|||
import com.newsblur.util.StoryOrder;
|
||||
|
||||
/**
|
||||
* The SyncService is based on an app architecture that tries to place network calls
|
||||
* (especially larger calls or those called regularly) on independent services, making the
|
||||
* activity / fragment a passive receiver of its updates. This, along with data fragments for
|
||||
* handling UI updates, throttles network access and ensures the UI is passively updated
|
||||
* and decoupled from network calls. Examples of other apps using this architecture include
|
||||
* the NBCSportsTalk and Google I/O 2011 apps.
|
||||
* A background-sync intent that, by virtue of extending IntentService, has several notable
|
||||
* features:
|
||||
* * invocations are FIFO and executed serially
|
||||
* * the OS picks an appropriate thread for execution that won't block the UI, but recycles
|
||||
* * supports callbacks where necessary
|
||||
*/
|
||||
public class SyncService extends IntentService {
|
||||
|
||||
public static final String EXTRA_TASK_TYPE = "syncServiceTaskType";
|
||||
public static final String EXTRA_STATUS_RECEIVER = "resultReceiverExtra";
|
||||
public static final String EXTRA_TASK_FEED_ID = "taskFeedId";
|
||||
public static final String EXTRA_TASK_FOLDER_NAME = "taskFoldername";
|
||||
|
@ -44,30 +46,27 @@ public class SyncService extends IntentService {
|
|||
public static final String EXTRA_TASK_READ_FILTER = "read_filter";
|
||||
public static final String EXTRA_TASK_MULTIFEED_IDS = "multi_feedids";
|
||||
|
||||
// TODO: replace these with enums
|
||||
public final static int STATUS_RUNNING = 0x02;
|
||||
public final static int STATUS_FINISHED = 0x03;
|
||||
public final static int STATUS_ERROR = 0x04;
|
||||
public static final int STATUS_NO_MORE_UPDATES = 0x05;
|
||||
public static final int STATUS_FINISHED_CLOSE = 0x06;
|
||||
public static final int NOT_RUNNING = 0x01;
|
||||
public static final int STATUS_PARTIAL_PROGRESS = 0x07;
|
||||
public enum SyncStatus {
|
||||
STATUS_RUNNING,
|
||||
STATUS_FINISHED,
|
||||
STATUS_NO_MORE_UPDATES,
|
||||
STATUS_FINISHED_CLOSE,
|
||||
NOT_RUNNING,
|
||||
STATUS_PARTIAL_PROGRESS,
|
||||
};
|
||||
|
||||
public static final int EXTRA_TASK_FOLDER_UPDATE_TWO_STEP = 30;
|
||||
public static final int EXTRA_TASK_FOLDER_UPDATE_WITH_COUNT = 41;
|
||||
public static final int EXTRA_TASK_FEED_UPDATE = 31;
|
||||
public static final int EXTRA_TASK_SOCIALFEED_UPDATE = 34;
|
||||
public static final int EXTRA_TASK_MARK_SOCIALSTORY_READ = 35;
|
||||
public static final int EXTRA_TASK_MULTIFEED_UPDATE = 36;
|
||||
public static final int EXTRA_TASK_MARK_MULTIPLE_STORIES_READ = 37;
|
||||
public static final int EXTRA_TASK_DELETE_FEED = 39;
|
||||
public static final int EXTRA_TASK_MULTISOCIALFEED_UPDATE = 40;
|
||||
public static final int EXTRA_TASK_STARRED_STORIES_UPDATE = 42;
|
||||
public enum TaskType {
|
||||
FOLDER_UPDATE_TWO_STEP,
|
||||
FOLDER_UPDATE_WITH_COUNT,
|
||||
FEED_UPDATE,
|
||||
SOCIALFEED_UPDATE,
|
||||
MULTIFEED_UPDATE,
|
||||
MULTISOCIALFEED_UPDATE,
|
||||
STARRED_STORIES_UPDATE
|
||||
};
|
||||
|
||||
private APIManager apiManager;
|
||||
private ContentResolver contentResolver;
|
||||
public static final String SYNCSERVICE_TASK = "syncservice_task";
|
||||
|
||||
|
||||
public SyncService() {
|
||||
super(SyncService.class.getName());
|
||||
|
@ -84,131 +83,82 @@ public class SyncService extends IntentService {
|
|||
protected void onHandleIntent(Intent intent) {
|
||||
final ResultReceiver receiver = intent.getParcelableExtra(EXTRA_STATUS_RECEIVER);
|
||||
try {
|
||||
TaskType taskType = (TaskType) intent.getSerializableExtra(EXTRA_TASK_TYPE);
|
||||
Log.d( this.getClass().getName(), "Sync Intent: " + taskType );
|
||||
|
||||
if (receiver != null) {
|
||||
receiver.send(STATUS_RUNNING, Bundle.EMPTY);
|
||||
receiver.send(SyncStatus.STATUS_RUNNING.ordinal(), Bundle.EMPTY);
|
||||
}
|
||||
// TODO: is it ever valid for receiver to be null? if not, we could factor out all
|
||||
// the checks below
|
||||
|
||||
Log.d( this.getClass().getName(), "Sync Intent: " + intent.getIntExtra(SYNCSERVICE_TASK , -1) );
|
||||
// an extra result code to callback before the final STATUS_FINISHED that is always sent
|
||||
SyncStatus resultStatus = null;
|
||||
|
||||
switch (intent.getIntExtra(SYNCSERVICE_TASK , -1)) {
|
||||
switch (taskType) {
|
||||
|
||||
case EXTRA_TASK_FOLDER_UPDATE_TWO_STEP:
|
||||
case FOLDER_UPDATE_TWO_STEP:
|
||||
// do a quick fetch of folders/feeds
|
||||
apiManager.getFolderFeedMapping(false);
|
||||
// notify UI of progress
|
||||
if (receiver != null) {
|
||||
receiver.send(STATUS_PARTIAL_PROGRESS, Bundle.EMPTY);
|
||||
receiver.send(SyncStatus.STATUS_PARTIAL_PROGRESS.ordinal(), Bundle.EMPTY);
|
||||
}
|
||||
// update feed counts
|
||||
apiManager.refreshFeedCounts();
|
||||
// UI will be notified again by default
|
||||
break;
|
||||
|
||||
case EXTRA_TASK_FOLDER_UPDATE_WITH_COUNT:
|
||||
case FOLDER_UPDATE_WITH_COUNT:
|
||||
apiManager.getFolderFeedMapping(true);
|
||||
break;
|
||||
|
||||
case EXTRA_TASK_MARK_MULTIPLE_STORIES_READ:
|
||||
final ValueMultimap stories = (ValueMultimap) intent.getSerializableExtra(EXTRA_TASK_STORIES);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(APIConstants.PARAMETER_FEEDS_STORIES, stories.getJsonString());
|
||||
apiManager.markMultipleStoriesAsRead(values);
|
||||
break;
|
||||
|
||||
case EXTRA_TASK_MARK_SOCIALSTORY_READ:
|
||||
final String markSocialJson = intent.getStringExtra(EXTRA_TASK_MARK_SOCIAL_JSON);
|
||||
if (!TextUtils.isEmpty(markSocialJson)) {
|
||||
apiManager.markSocialStoryAsRead(markSocialJson);
|
||||
} else {
|
||||
Log.e(this.getClass().getName(), "No feed/story to mark as read included in SyncRequest");
|
||||
receiver.send(STATUS_ERROR, Bundle.EMPTY);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXTRA_TASK_FEED_UPDATE:
|
||||
case FEED_UPDATE:
|
||||
if (!TextUtils.isEmpty(intent.getStringExtra(EXTRA_TASK_FEED_ID))) {
|
||||
StoriesResponse storiesForFeed = apiManager.getStoriesForFeed(intent.getStringExtra(EXTRA_TASK_FEED_ID), intent.getStringExtra(EXTRA_TASK_PAGE_NUMBER), (StoryOrder) intent.getSerializableExtra(EXTRA_TASK_ORDER), (ReadFilter) intent.getSerializableExtra(EXTRA_TASK_READ_FILTER));
|
||||
if (storiesForFeed != null && storiesForFeed.stories.length != 0) {
|
||||
receiver.send(STATUS_FINISHED, null);
|
||||
} else {
|
||||
receiver.send(STATUS_NO_MORE_UPDATES, Bundle.EMPTY);
|
||||
if (storiesForFeed == null || storiesForFeed.stories.length == 0) {
|
||||
resultStatus = SyncStatus.STATUS_NO_MORE_UPDATES;
|
||||
}
|
||||
} else {
|
||||
Log.e(this.getClass().getName(), "No feed to refresh included in SyncRequest");
|
||||
receiver.send(STATUS_ERROR, Bundle.EMPTY);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case EXTRA_TASK_MULTIFEED_UPDATE:
|
||||
case MULTIFEED_UPDATE:
|
||||
if (intent.getStringArrayExtra(EXTRA_TASK_MULTIFEED_IDS) != null) {
|
||||
StoriesResponse storiesForFeeds = apiManager.getStoriesForFeeds(intent.getStringArrayExtra(EXTRA_TASK_MULTIFEED_IDS), intent.getStringExtra(EXTRA_TASK_PAGE_NUMBER), (StoryOrder) intent.getSerializableExtra(EXTRA_TASK_ORDER), (ReadFilter) intent.getSerializableExtra(EXTRA_TASK_READ_FILTER));
|
||||
if (storiesForFeeds != null && storiesForFeeds.stories.length != 0) {
|
||||
receiver.send(STATUS_FINISHED, Bundle.EMPTY);
|
||||
} else {
|
||||
receiver.send(STATUS_NO_MORE_UPDATES, Bundle.EMPTY);
|
||||
if (storiesForFeeds == null || storiesForFeeds.stories.length == 0) {
|
||||
resultStatus = SyncStatus.STATUS_NO_MORE_UPDATES;
|
||||
}
|
||||
} else {
|
||||
Log.e(this.getClass().getName(), "No feed ids to refresh included in SyncRequest");
|
||||
receiver.send(STATUS_ERROR, Bundle.EMPTY);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXTRA_TASK_MULTISOCIALFEED_UPDATE:
|
||||
case MULTISOCIALFEED_UPDATE:
|
||||
if (intent.getStringArrayExtra(EXTRA_TASK_MULTIFEED_IDS) != null) {
|
||||
SocialFeedResponse sharedStoriesForFeeds = apiManager.getSharedStoriesForFeeds(intent.getStringArrayExtra(EXTRA_TASK_MULTIFEED_IDS), intent.getStringExtra(EXTRA_TASK_PAGE_NUMBER), (StoryOrder) intent.getSerializableExtra(EXTRA_TASK_ORDER), (ReadFilter) intent.getSerializableExtra(EXTRA_TASK_READ_FILTER));
|
||||
if (sharedStoriesForFeeds != null && sharedStoriesForFeeds.stories.length != 0) {
|
||||
receiver.send(STATUS_FINISHED, null);
|
||||
} else {
|
||||
receiver.send(STATUS_NO_MORE_UPDATES, Bundle.EMPTY);
|
||||
if (sharedStoriesForFeeds == null || sharedStoriesForFeeds.stories.length == 0) {
|
||||
resultStatus = SyncStatus.STATUS_NO_MORE_UPDATES;
|
||||
}
|
||||
} else {
|
||||
Log.e(this.getClass().getName(), "No socialfeed ids to refresh included in SyncRequest");
|
||||
receiver.send(STATUS_ERROR, Bundle.EMPTY);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXTRA_TASK_STARRED_STORIES_UPDATE:
|
||||
case STARRED_STORIES_UPDATE:
|
||||
StoriesResponse starredStories = apiManager.getStarredStories(intent.getStringExtra(EXTRA_TASK_PAGE_NUMBER));
|
||||
if (starredStories != null && starredStories.stories.length != 0) {
|
||||
receiver.send(STATUS_FINISHED, Bundle.EMPTY);
|
||||
} else {
|
||||
receiver.send(STATUS_NO_MORE_UPDATES, Bundle.EMPTY);
|
||||
if (starredStories == null && starredStories.stories.length == 0) {
|
||||
resultStatus = SyncStatus.STATUS_NO_MORE_UPDATES;
|
||||
}
|
||||
break;
|
||||
|
||||
case EXTRA_TASK_DELETE_FEED:
|
||||
if (intent.getLongExtra(EXTRA_TASK_FEED_ID, -1) != -1) {
|
||||
Long feedToBeDeleted = intent.getLongExtra(EXTRA_TASK_FEED_ID, -1);
|
||||
if (apiManager.deleteFeed(feedToBeDeleted, intent.getStringExtra(EXTRA_TASK_FOLDER_NAME))) {
|
||||
Uri feedUri = FeedProvider.FEEDS_URI.buildUpon().appendPath(Long.toString(feedToBeDeleted)).build();
|
||||
contentResolver.delete(feedUri, null, null);
|
||||
receiver.send(STATUS_FINISHED_CLOSE, Bundle.EMPTY);
|
||||
return;
|
||||
} else {
|
||||
Log.e(this.getClass().getName(), "Error deleting feed");
|
||||
Toast.makeText(this, getResources().getString(R.string.error_deleting_feed), Toast.LENGTH_LONG).show();
|
||||
receiver.send(STATUS_ERROR, Bundle.EMPTY);
|
||||
}
|
||||
} else {
|
||||
Log.e(this.getClass().getName(), "No feed id to delete include in SyncRequest");
|
||||
receiver.send(STATUS_ERROR, Bundle.EMPTY);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXTRA_TASK_SOCIALFEED_UPDATE:
|
||||
case SOCIALFEED_UPDATE:
|
||||
if (!TextUtils.isEmpty(intent.getStringExtra(EXTRA_TASK_SOCIALFEED_ID)) && !TextUtils.isEmpty(intent.getStringExtra(EXTRA_TASK_SOCIALFEED_USERNAME))) {
|
||||
SocialFeedResponse storiesForSocialFeed = apiManager.getStoriesForSocialFeed(intent.getStringExtra(EXTRA_TASK_SOCIALFEED_ID), intent.getStringExtra(EXTRA_TASK_SOCIALFEED_USERNAME), intent.getStringExtra(EXTRA_TASK_PAGE_NUMBER), (StoryOrder) intent.getSerializableExtra(EXTRA_TASK_ORDER), (ReadFilter) intent.getSerializableExtra(EXTRA_TASK_READ_FILTER));
|
||||
if (storiesForSocialFeed != null && storiesForSocialFeed.stories.length != 0) {
|
||||
receiver.send(STATUS_FINISHED, null);
|
||||
} else {
|
||||
receiver.send(STATUS_NO_MORE_UPDATES, Bundle.EMPTY);
|
||||
if (storiesForSocialFeed == null || storiesForSocialFeed.stories.length == 0) {
|
||||
resultStatus = SyncStatus.STATUS_NO_MORE_UPDATES;
|
||||
}
|
||||
} else {
|
||||
Log.e(this.getClass().getName(), "Missing parameters for socialfeed SyncRequest");
|
||||
receiver.send(STATUS_ERROR, Bundle.EMPTY);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -217,23 +167,22 @@ public class SyncService extends IntentService {
|
|||
break;
|
||||
}
|
||||
|
||||
// send the first result code if it was set. The STATUS_FINISHED is sent below
|
||||
if ((receiver != null) && (resultStatus != null)) {
|
||||
receiver.send(resultStatus.ordinal(), Bundle.EMPTY);
|
||||
}
|
||||
|
||||
Log.d( this.getClass().getName(), "Sync Intent complete");
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(this.getClass().getName(), "Couldn't synchronise with Newsblur servers: " + e.getMessage(), e.getCause());
|
||||
if (receiver != null) {
|
||||
final Bundle bundle = new Bundle();
|
||||
bundle.putString(Intent.EXTRA_TEXT, e.toString());
|
||||
receiver.send(STATUS_ERROR, bundle);
|
||||
}
|
||||
}
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (receiver != null) {
|
||||
receiver.send(SyncStatus.STATUS_FINISHED.ordinal(), Bundle.EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
if (receiver != null) {
|
||||
receiver.send(STATUS_FINISHED, Bundle.EMPTY);
|
||||
} else {
|
||||
Log.e(this.getClass().getName(), "No receiver attached to Sync?");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,7 +53,29 @@ public class FeedUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static void markStoryUnread( final Story story, final Context context, final APIManager apiManager) {
|
||||
public static void deleteFeed( final long feedId, final String folderName, final Context context, final APIManager apiManager) {
|
||||
|
||||
new AsyncTask<Void, Void, NewsBlurResponse>() {
|
||||
@Override
|
||||
protected NewsBlurResponse doInBackground(Void... arg) {
|
||||
return apiManager.deleteFeed(feedId, folderName);
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(NewsBlurResponse result) {
|
||||
if (!result.isError()) {
|
||||
Toast.makeText(context, R.string.toast_feed_deleted, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(context, result.getErrorMessage(context.getString(R.string.toast_feed_delete_error)), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
|
||||
Uri feedUri = FeedProvider.FEEDS_URI.buildUpon().appendPath(Long.toString(feedId)).build();
|
||||
context.getContentResolver().delete(feedUri, null, null);
|
||||
|
||||
}
|
||||
|
||||
public static void markStoryUnread( final Story story, final Context context, final APIManager apiManager ) {
|
||||
|
||||
new AsyncTask<Void, Void, NewsBlurResponse>() {
|
||||
@Override
|
||||
|
@ -75,33 +97,17 @@ public class FeedUtils {
|
|||
/**
|
||||
* This utility method is a fast-returning way to mark as read a batch of stories in both
|
||||
* the local DB and on the server.
|
||||
*
|
||||
* TODO: the next version of the NB API will let us mark-as-read by a UUID, so we can
|
||||
* hopefully remove the ugly detection of social stories and their whole different
|
||||
* API call.
|
||||
*/
|
||||
public static void markStoriesAsRead( Collection<Story> stories, Context context ) {
|
||||
public static void markStoriesAsRead( Collection<Story> stories, final Context context ) {
|
||||
|
||||
// the map of non-social feedIds->storyIds to mark (auto-serializing)
|
||||
ValueMultimap storiesJson = new ValueMultimap();
|
||||
// the map of social userIds->feedIds->storyIds to mark
|
||||
Map<String, Map<String, Set<String>>> socialStories = new HashMap<String, Map<String, Set<String>>>();
|
||||
// the list of story hashes to mark read
|
||||
final ArrayList<String> storyHashes = new ArrayList<String>();
|
||||
// a list of local DB ops to perform
|
||||
ArrayList<ContentProviderOperation> updateOps = new ArrayList<ContentProviderOperation>();
|
||||
|
||||
for (Story story : stories) {
|
||||
// ops for the local DB
|
||||
appendStoryReadOperations(story, updateOps);
|
||||
// API call to ensure the story is marked read in the context of a feed
|
||||
storiesJson.put(story.feedId, story.storyHash);
|
||||
// API call to ensure the story is marked read in the context of a social share
|
||||
if (story.socialUserId != null) {
|
||||
putMapHeirarchy(socialStories, story.socialUserId, story.feedId, story.storyHash);
|
||||
} else if ((story.friendUserIds != null) && (story.friendUserIds.length > 0) && (story.friendUserIds[0] != null)) {
|
||||
putMapHeirarchy(socialStories, story.friendUserIds[0], story.feedId, story.storyHash);
|
||||
} else if ((story.sharedUserIds != null) && (story.sharedUserIds.length > 0) && (story.sharedUserIds[0] != null)) {
|
||||
putMapHeirarchy(socialStories, story.sharedUserIds[0], story.feedId, story.storyHash);
|
||||
}
|
||||
storyHashes.add(story.storyHash);
|
||||
}
|
||||
|
||||
// first, update unread counts in the local DB
|
||||
|
@ -111,36 +117,23 @@ public class FeedUtils {
|
|||
Log.w(FeedUtils.class.getName(), "Could not update unread counts in local storage.", e);
|
||||
}
|
||||
|
||||
// next, update the server for normal stories
|
||||
if (storiesJson.size() > 0) {
|
||||
Intent intent = new Intent(Intent.ACTION_SYNC, null, context, SyncService.class);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_MARK_MULTIPLE_STORIES_READ);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_STORIES, storiesJson);
|
||||
context.startService(intent);
|
||||
// next, update the server
|
||||
if (storyHashes.size() > 0) {
|
||||
new AsyncTask<Void, Void, NewsBlurResponse>() {
|
||||
@Override
|
||||
protected NewsBlurResponse doInBackground(Void... arg) {
|
||||
APIManager apiManager = new APIManager(context);
|
||||
return apiManager.markStoriesAsRead(storyHashes);
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(NewsBlurResponse result) {
|
||||
if (!result.isError()) {
|
||||
Log.e(FeedUtils.class.getName(), "Could not update unread counts via API: " + result.getErrorMessage());
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
// finally, update the server for social stories
|
||||
if (socialStories.size() > 0) {
|
||||
Intent intent = new Intent(Intent.ACTION_SYNC, null, context, SyncService.class);
|
||||
intent.putExtra(SyncService.SYNCSERVICE_TASK, SyncService.EXTRA_TASK_MARK_SOCIALSTORY_READ);
|
||||
intent.putExtra(SyncService.EXTRA_TASK_MARK_SOCIAL_JSON, gson.toJson(socialStories));
|
||||
context.startService(intent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to help populate the 3-level map structure that the NB API uses in JSON calls.
|
||||
*/
|
||||
private static void putMapHeirarchy(Map<String, Map<String, Set<String>>> map, String s1, String s2, String s3) {
|
||||
if (! map.containsKey(s1)) {
|
||||
map.put(s1, new HashMap<String, Set<String>>());
|
||||
}
|
||||
Map<String, Set<String>> innerMap = map.get(s1);
|
||||
if (! innerMap.containsKey(s2)) {
|
||||
innerMap.put(s2, new HashSet<String>());
|
||||
}
|
||||
innerMap.get(s2).add(s3);
|
||||
}
|
||||
|
||||
private static void appendStoryReadOperations(Story story, List<ContentProviderOperation> operations) {
|
||||
|
|
Loading…
Add table
Reference in a new issue