Java tutorial
/* * Copyright (C) 2014 Michell Bak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.miz.service; import android.app.IntentService; import android.app.Notification; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.support.v4.app.NotificationCompat; import com.google.common.collect.Multimap; import com.miz.apis.trakt.Trakt; import com.miz.apis.trakt.TraktTvShow; import com.miz.db.DbAdapterTvShowEpisodes; import com.miz.db.DbAdapterTvShows; import com.miz.functions.ColumnIndexCache; import com.miz.functions.MizLib; import com.miz.mizuu.MizuuApplication; import com.miz.mizuu.R; import com.miz.mizuu.TvShow; import com.miz.utils.LocalBroadcastUtils; import org.json.JSONArray; import org.json.JSONObject; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Set; public class TraktTvShowsSyncService extends IntentService { private NotificationCompat.Builder mBuilder; private NotificationManager mNotificationManager; private ArrayList<TvShow> mShows; private ArrayList<TraktTvShow> mLocalCollection, mLocalWatched; private LinkedHashMap<String, TraktTvShow> mTraktCollection, mTraktWatched; private HashSet<String> mShowIds, mTraktFavorites, mLocalFavorites; private DbAdapterTvShows mShowDatabase; private DbAdapterTvShowEpisodes mEpisodeDatabase; private final int NOTIFICATION_ID = 8; public TraktTvShowsSyncService() { super("TraktTvShowsSyncService"); } @Override protected void onHandleIntent(Intent intent) { // Variables and collections setup(); // Notification setupNotification(); // Internet check if (!MizLib.isOnline(this)) { showNoInternetNotification(); return; } // Load all local TV shows into an ArrayList and a map of TVDB ID and // corresponding row ID loadTvShowLibrary(); updateNotification(getString(R.string.downloadingTvShowCollection)); // Download Trakt TV show collection downloadTvShowCollection(); updateNotification(getString(R.string.updatingTvShowCollection)); // Compare the local TV show collection with the one from Trakt and update // the Trakt collection if new items are found updateTvShowCollection(); updateNotification(getString(R.string.downloadingWatchedTvShows)); // Download watched TV shows from Trakt downloadWatchedTvShows(); updateNotification(getString(R.string.updatingWatchedTvShows)); // Sync locally watched TV shows with Trakt updateWatchedTvShows(); updateNotification(getString(R.string.downloadingTvShowFavorites)); // Download TV show favorites from Trakt downloadTvShowFavorites(); updateNotification(getString(R.string.updatingTvShowFavorites)); // Sync local favorites with Trakt updateTvShowFavorites(); // Clean up mShows.clear(); mShows = null; // Let the application know that the sync is finished broadcastLibraryUpdate(); // Let the user know that the sync is finished showPostUpdateNotification(); } private void setup() { mShows = new ArrayList<TvShow>(); mLocalCollection = new ArrayList<TraktTvShow>(); mLocalWatched = new ArrayList<TraktTvShow>(); mTraktCollection = new LinkedHashMap<String, TraktTvShow>(); mTraktWatched = new LinkedHashMap<String, TraktTvShow>(); mShowIds = new HashSet<String>(); mTraktFavorites = new HashSet<String>(); mLocalFavorites = new HashSet<String>(); } private void setupNotification() { // Setup up notification mBuilder = new NotificationCompat.Builder(getApplicationContext()); mBuilder.setColor(getResources().getColor(R.color.color_primary)); mBuilder.setSmallIcon(R.drawable.ic_tv_white_24dp); mBuilder.setTicker(getString(R.string.syncTvShows)); mBuilder.setContentTitle(getString(R.string.syncTvShows)); mBuilder.setContentText(getString(R.string.updatingShowInfo)); mBuilder.setOngoing(true); mBuilder.setOnlyAlertOnce(true); // Build notification Notification updateNotification = mBuilder.build(); // Show the notification mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(NOTIFICATION_ID, updateNotification); // Tell the system that this is an ongoing notification, so it shouldn't be killed startForeground(NOTIFICATION_ID, updateNotification); } private void loadTvShowLibrary() { // Get shows mShowDatabase = MizuuApplication.getTvDbAdapter(); Cursor cursor = mShowDatabase.getAllShows(); ColumnIndexCache cache = new ColumnIndexCache(); try { while (cursor.moveToNext()) { mShowIds.add(cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_ID))); // Full TV shows mShows.add(new TvShow(this, cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_ID)), cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_TITLE)), cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_PLOT)), cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_RATING)), cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_GENRES)), cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_ACTORS)), cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_CERTIFICATION)), cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_FIRST_AIRDATE)), cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_RUNTIME)), false, cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_FAVOURITE)), MizuuApplication.getTvEpisodeDbAdapter().getLatestEpisodeAirdate( cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_ID))))); if (cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_FAVOURITE)).equals("1")) mLocalFavorites .add(cursor.getString(cache.getColumnIndex(cursor, DbAdapterTvShows.KEY_SHOW_ID))); } } catch (Exception e) { } finally { cursor.close(); cache.clear(); } mEpisodeDatabase = MizuuApplication.getTvEpisodeDbAdapter(); int count = mShows.size(); for (int i = 0; i < count; i++) { TraktTvShow collectionShow = new TraktTvShow(mShows.get(i).getId(), mShows.get(i).getTitle()); TraktTvShow watchedShow = new TraktTvShow(mShows.get(i).getId(), mShows.get(i).getTitle()); Cursor c = mEpisodeDatabase.getEpisodes(mShows.get(i).getId()); try { while (c.moveToNext()) { collectionShow.addEpisode( c.getString(cache.getColumnIndex(c, DbAdapterTvShowEpisodes.KEY_SEASON)), c.getString(cache.getColumnIndex(c, DbAdapterTvShowEpisodes.KEY_EPISODE))); if (c.getString(cache.getColumnIndex(c, DbAdapterTvShowEpisodes.KEY_HAS_WATCHED)).equals("1")) { watchedShow.addEpisode( c.getString(cache.getColumnIndex(c, DbAdapterTvShowEpisodes.KEY_SEASON)), c.getString(cache.getColumnIndex(c, DbAdapterTvShowEpisodes.KEY_EPISODE))); } } } catch (Exception ignored) { } finally { c.close(); } if (collectionShow.getSeasons().size() > 0) mLocalCollection.add(collectionShow); if (watchedShow.getSeasons().size() > 0) mLocalWatched.add(watchedShow); } } private void downloadTvShowCollection() { JSONArray jsonArray = Trakt.getTvShowLibrary(this, Trakt.COLLECTION); if (jsonArray.length() > 0) { for (int i = 0; i < jsonArray.length(); i++) { try { String id = String.valueOf(jsonArray.getJSONObject(i).getString("tvdb_id")); TraktTvShow show = new TraktTvShow(id, jsonArray.getJSONObject(i).getString("title")); JSONArray seasons = jsonArray.getJSONObject(i).getJSONArray("seasons"); for (int j = 0; j < seasons.length(); j++) { String season = seasons.getJSONObject(j).getString("season"); JSONArray episodes = seasons.getJSONObject(j).getJSONArray("episodes"); for (int k = 0; k < episodes.length(); k++) { show.addEpisode(season, episodes.getString(k)); } } mTraktCollection.put(id, show); } catch (Exception e) { } } } } private void updateTvShowCollection() { int count = mLocalCollection.size(); if (count > 0) { ArrayList<TraktTvShow> collection = new ArrayList<TraktTvShow>(); for (int i = 0; i < count; i++) { if (!mTraktCollection.containsKey(mLocalCollection.get(i).getId())) { // This show isn't in the Trakt library, so we'll add everything collection.add(mLocalCollection.get(i)); } else { TraktTvShow traktTemp = mTraktCollection.get(mLocalCollection.get(i).getId()); TraktTvShow temp = new TraktTvShow(mLocalCollection.get(i).getId(), mLocalCollection.get(i).getTitle()); // This show is in the Trakt library, so we'll have to check each episode in each season Multimap<String, String> seasonsMap = mLocalCollection.get(i).getSeasons(); Set<String> seasons = seasonsMap.keySet(); for (String season : seasons) { Collection<String> episodes = seasonsMap.get(season); for (String episode : episodes) { if (!traktTemp.contains(MizLib.removeIndexZero(season), MizLib.removeIndexZero(episode))) { temp.addEpisode(season, episode); } } } if (temp.getSeasons().size() > 0) collection.add(temp); } } count = collection.size(); for (int i = 0; i < count; i++) { Trakt.addTvShowToLibrary(collection.get(i), getApplicationContext()); } // Clean up collection.clear(); collection = null; mTraktCollection.clear(); mTraktCollection = null; } } private void downloadWatchedTvShows() { JSONArray jsonArray = Trakt.getTvShowLibrary(this, Trakt.WATCHED); if (jsonArray.length() > 0) { for (int i = 0; i < jsonArray.length(); i++) { try { String showId = String.valueOf(jsonArray.getJSONObject(i).getString("tvdb_id")); TraktTvShow show = new TraktTvShow(showId, jsonArray.getJSONObject(i).getString("title")); JSONArray seasons = jsonArray.getJSONObject(i).getJSONArray("seasons"); for (int j = 0; j < seasons.length(); j++) { String season = seasons.getJSONObject(j).getString("season"); JSONArray episodes = seasons.getJSONObject(j).getJSONArray("episodes"); for (int k = 0; k < episodes.length(); k++) { show.addEpisode(season, episodes.getString(k)); } } mTraktWatched.put(showId, show); if (mShowIds.contains(String.valueOf(jsonArray.getJSONObject(i).get("tvdb_id")))) { for (int j = 0; j < seasons.length(); j++) { JSONObject season = seasons.getJSONObject(j); String seasonNumber = MizLib.addIndexZero(String.valueOf(season.get("season"))); JSONArray seasonEpisodes = season.getJSONArray("episodes"); for (int k = 0; k < seasonEpisodes.length(); k++) { mEpisodeDatabase.updateEpisode(showId, seasonNumber, MizLib.addIndexZero(String.valueOf(seasonEpisodes.get(k))), DbAdapterTvShowEpisodes.KEY_HAS_WATCHED, "1"); } } } } catch (Exception e) { } } } } private void updateWatchedTvShows() { int count = mLocalWatched.size(); if (count > 0) { ArrayList<TraktTvShow> watched = new ArrayList<TraktTvShow>(); for (int i = 0; i < count; i++) { if (!mTraktWatched.containsKey(mLocalWatched.get(i).getId())) { // This show isn't in the Trakt library, so we'll add everything watched.add(mLocalWatched.get(i)); } else { TraktTvShow traktTemp = mTraktWatched.get(mLocalWatched.get(i).getId()); TraktTvShow temp = new TraktTvShow(mLocalWatched.get(i).getId(), mLocalWatched.get(i).getTitle()); // This show is in the Trakt library, so we'll have to check each episode in each season Multimap<String, String> seasonsMap = mLocalWatched.get(i).getSeasons(); Set<String> seasons = seasonsMap.keySet(); for (String season : seasons) { Collection<String> episodes = seasonsMap.get(season); for (String episode : episodes) { if (!traktTemp.contains(MizLib.removeIndexZero(season), MizLib.removeIndexZero(episode))) { temp.addEpisode(MizLib.removeIndexZero(season), MizLib.removeIndexZero(episode)); } } } if (temp.getSeasons().size() > 0) watched.add(temp); } } count = watched.size(); for (int i = 0; i < count; i++) { Trakt.markTvShowAsWatched(watched.get(i), getApplicationContext()); } // Clean up watched.clear(); watched = null; mTraktWatched.clear(); mTraktWatched = null; } } private void downloadTvShowFavorites() { JSONArray jsonArray = Trakt.getTvShowLibrary(this, Trakt.RATINGS); if (jsonArray.length() > 0) { for (int i = 0; i < jsonArray.length(); i++) { try { String showId = String.valueOf(jsonArray.getJSONObject(i).getString("tvdb_id")); mTraktFavorites.add(showId); if (!mLocalFavorites.contains(showId)) mShowDatabase.updateShowSingleItem(showId, DbAdapterTvShows.KEY_SHOW_FAVOURITE, "1"); } catch (Exception e) { } } } } private void updateTvShowFavorites() { ArrayList<TvShow> favs = new ArrayList<TvShow>(); int count = mShows.size(); for (int i = 0; i < count; i++) if (mShows.get(i).isFavorite() && !mTraktFavorites.contains(mShows.get(i).getId())) favs.add(mShows.get(i)); Trakt.tvShowFavorite(favs, this); favs.clear(); favs = null; } private void broadcastLibraryUpdate() { LocalBroadcastUtils.updateTvShowLibrary(this); } private void showPostUpdateNotification() { // Remove the old one mNotificationManager.cancel(NOTIFICATION_ID); mBuilder = new NotificationCompat.Builder(getApplicationContext()); mBuilder.setColor(getResources().getColor(R.color.color_primary)); mBuilder.setTicker(getString(R.string.finishedTraktTvShowSync)); mBuilder.setContentTitle(getString(R.string.finishedTraktTvShowSync)); mBuilder.setSmallIcon(R.drawable.ic_done_white_24dp); mBuilder.setOngoing(false); mBuilder.setAutoCancel(true); mBuilder.setOnlyAlertOnce(true); // Build notification Notification updateNotification = mBuilder.build(); // Show the notification mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(NOTIFICATION_ID + 1000, updateNotification); } private void showNoInternetNotification() { // Remove the old one mNotificationManager.cancel(NOTIFICATION_ID); mBuilder = new NotificationCompat.Builder(getApplicationContext()); mBuilder.setColor(getResources().getColor(R.color.color_primary)); mBuilder.setTicker(getString(R.string.traktSyncFailed)); mBuilder.setContentTitle(getString(R.string.traktSyncFailed)); mBuilder.setContentText(getString(R.string.noInternet)); mBuilder.setSmallIcon(R.drawable.ic_signal_wifi_statusbar_connected_no_internet_2_white_24dp); mBuilder.setOngoing(false); mBuilder.setAutoCancel(true); mBuilder.setOnlyAlertOnce(true); // Build notification Notification updateNotification = mBuilder.build(); // Show the notification mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(NOTIFICATION_ID + 1000, updateNotification); } private void updateNotification(String text) { // Setup up notification mBuilder.setContentText(text); // Build notification Notification updateNotification = mBuilder.build(); // Show the notification mNotificationManager.notify(NOTIFICATION_ID, updateNotification); } }