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.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.database.Cursor; import android.graphics.Bitmap; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import com.miz.abstractclasses.MovieFileSource; import com.miz.apis.trakt.Trakt; import com.miz.db.DbAdapterSources; import com.miz.filesources.FileMovie; import com.miz.filesources.SmbMovie; import com.miz.filesources.UpnpMovie; import com.miz.functions.FileSource; import com.miz.functions.MizLib; import com.miz.functions.MovieLibraryUpdateCallback; import com.miz.identification.MovieIdentification; import com.miz.identification.MovieStructure; import com.miz.mizuu.BuildConfig; import com.miz.mizuu.CancelLibraryUpdate; import com.miz.mizuu.Main; import com.miz.mizuu.MizuuApplication; import com.miz.mizuu.R; import com.miz.utils.LocalBroadcastUtils; import com.miz.utils.MovieDatabaseUtils; import java.util.ArrayList; import java.util.List; import static com.miz.functions.PreferenceKeys.CLEAR_LIBRARY_MOVIES; import static com.miz.functions.PreferenceKeys.REMOVE_UNAVAILABLE_FILES_MOVIES; import static com.miz.functions.PreferenceKeys.SYNC_WITH_TRAKT; public class MovieLibraryUpdate extends IntentService implements MovieLibraryUpdateCallback { public static final String STOP_MOVIE_LIBRARY_UPDATE = "mizuu-stop-movie-library-update"; private ArrayList<FileSource> mFileSources; private ArrayList<MovieFileSource<?>> mMovieFileSources; private ArrayList<MovieStructure> mMovieQueue = new ArrayList<MovieStructure>(); private boolean mClearLibrary, mClearUnavailable, mSyncLibraries, mStopUpdate; private int mTotalFiles, mCount; private SharedPreferences mSettings; private Editor mEditor; private final int NOTIFICATION_ID = 200, POST_UPDATE_NOTIFICATION = 213; private NotificationManager mNotificationManager; private NotificationCompat.Builder mBuilder; private MovieIdentification mMovieIdentification; public MovieLibraryUpdate() { super("MovieLibraryUpdate"); } public MovieLibraryUpdate(String name) { super(name); } @Override public void onDestroy() { super.onDestroy(); log("onDestroy()"); if (mNotificationManager == null) mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.cancel(NOTIFICATION_ID); reloadLibrary(); showPostUpdateNotification(); LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); MizLib.scheduleMovieUpdate(this); if (Trakt.hasTraktAccount(this) && mSyncLibraries && mCount > 0) { getApplicationContext().startService(new Intent(getApplicationContext(), TraktMoviesSyncService.class)); } } @Override protected void onHandleIntent(Intent intent) { log("clear()"); // Clear and set up all variables clear(); log("setup()"); // Set up Notification, variables, etc. setup(); log("loadFileSources()"); // Load all file sources from the database loadFileSources(); log("setupMovieFileSources()"); // Add the different file sources to the MovieFileSource ArrayList setupMovieFileSources(mClearLibrary); if (mStopUpdate) return; log("removeUnidentifiedFiles()"); // Remove unavailable movies, so we can try to identify them again if (!mClearLibrary) removeUnidentifiedFiles(); if (mStopUpdate) return; // Check if the library should be cleared if (mClearLibrary) { // Reset the preference, so it isn't checked the next // time the user wants to update the library mEditor = mSettings.edit(); mEditor.putBoolean(CLEAR_LIBRARY_MOVIES, false); mEditor.apply(); log("removeMoviesFromDatabase()"); // Remove all entries from the database removeMoviesFromDatabase(); } if (mStopUpdate) return; // Check if we should remove all unavailable files. // Note that this only makes sense if we haven't already cleared the library. if (!mClearLibrary && mClearUnavailable) { log("removeUnavailableFiles()"); // Remove all unavailable files from the database removeUnavailableFiles(); } log("searchFolders()"); if (mStopUpdate) return; reloadLibrary(); // Search all folders searchFolders(); if (mStopUpdate) return; log("mTotalFiles > 0 check"); // Check if we've found any files to identify if (mTotalFiles > 0) { log("updateMovies()"); // Start the actual movie update / identification task updateMovies(); } } private void reloadLibrary() { log("reloadLibrary()"); LocalBroadcastUtils.updateMovieLibrary(getApplicationContext()); } private void loadFileSources() { mFileSources = new ArrayList<FileSource>(); DbAdapterSources dbHelperSources = MizuuApplication.getSourcesAdapter(); Cursor c = dbHelperSources.fetchAllMovieSources(); try { while (c.moveToNext()) { mFileSources.add(new FileSource(c.getLong(c.getColumnIndex(DbAdapterSources.KEY_ROWID)), c.getString(c.getColumnIndex(DbAdapterSources.KEY_FILEPATH)), c.getInt(c.getColumnIndex(DbAdapterSources.KEY_FILESOURCE_TYPE)), c.getString(c.getColumnIndex(DbAdapterSources.KEY_USER)), c.getString(c.getColumnIndex(DbAdapterSources.KEY_PASSWORD)), c.getString(c.getColumnIndex(DbAdapterSources.KEY_DOMAIN)), c.getString(c.getColumnIndex(DbAdapterSources.KEY_TYPE)))); } } catch (Exception e) { } finally { c.close(); } } private void setupMovieFileSources(boolean mClearLibrary) { for (FileSource fileSource : mFileSources) { if (mStopUpdate) return; switch (fileSource.getFileSourceType()) { case FileSource.FILE: mMovieFileSources.add(new FileMovie(getApplicationContext(), fileSource, mClearLibrary)); break; case FileSource.SMB: mMovieFileSources.add(new SmbMovie(getApplicationContext(), fileSource, mClearLibrary)); break; case FileSource.UPNP: mMovieFileSources.add(new UpnpMovie(getApplicationContext(), fileSource, mClearLibrary)); break; } } } private void removeUnidentifiedFiles() { for (MovieFileSource<?> movieFileSource : mMovieFileSources) { movieFileSource.removeUnidentifiedFiles(); } } private void removeMoviesFromDatabase() { MovieDatabaseUtils.deleteAllMovies(this); } private void removeUnavailableFiles() { for (MovieFileSource<?> movieFileSource : mMovieFileSources) { movieFileSource.removeUnavailableFiles(); } } private void searchFolders() { // Temporary collections List<String> tempList = null; for (int j = 0; j < mMovieFileSources.size(); j++) { updateMovieScaningNotification(mMovieFileSources.get(j).toString()); tempList = mMovieFileSources.get(j).searchFolder(); for (int i = 0; i < tempList.size(); i++) { mMovieQueue.add(new MovieStructure(tempList.get(i))); } } // Clean up... if (tempList != null) tempList.clear(); mTotalFiles = mMovieQueue.size(); } private void setup() { LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mMessageReceiver, new IntentFilter(STOP_MOVIE_LIBRARY_UPDATE)); // Set up cancel dialog intent Intent notificationIntent = new Intent(this, CancelLibraryUpdate.class); notificationIntent.putExtra("isMovie", true); notificationIntent.setAction(Intent.ACTION_MAIN); notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER); PendingIntent contentIntent = PendingIntent.getActivity(this, NOTIFICATION_ID, notificationIntent, 0); // Setup up notification mBuilder = new NotificationCompat.Builder(getApplicationContext()); mBuilder.setColor(getResources().getColor(R.color.color_primary)); mBuilder.setPriority(NotificationCompat.PRIORITY_MAX); mBuilder.setSmallIcon(R.drawable.ic_sync_white_24dp); mBuilder.setTicker(getString(R.string.updatingMovies)); mBuilder.setContentTitle(getString(R.string.updatingMovies)); mBuilder.setContentText(getString(R.string.gettingReady)); mBuilder.setContentIntent(contentIntent); mBuilder.setOngoing(true); mBuilder.setOnlyAlertOnce(true); mBuilder.addAction(R.drawable.ic_close_white_24dp, getString(android.R.string.cancel), contentIntent); // 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); mSettings = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); mClearLibrary = mSettings.getBoolean(CLEAR_LIBRARY_MOVIES, false); mClearUnavailable = mSettings.getBoolean(REMOVE_UNAVAILABLE_FILES_MOVIES, false); mSyncLibraries = mSettings.getBoolean(SYNC_WITH_TRAKT, true); } private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { mStopUpdate = true; if (mMovieIdentification != null) mMovieIdentification.cancel(); } }; private void updateMovies() { mMovieIdentification = new MovieIdentification(getApplicationContext(), this, mMovieQueue); mMovieIdentification.start(); } private void clear() { // Lists mFileSources = new ArrayList<FileSource>(); mMovieFileSources = new ArrayList<MovieFileSource<?>>(); mMovieQueue = new ArrayList<MovieStructure>(); // Booleans mClearLibrary = false; mClearUnavailable = false; mSyncLibraries = true; mStopUpdate = false; // Other variables mEditor = null; mSettings = null; mTotalFiles = 0; mNotificationManager = null; mBuilder = null; } private void log(String msg) { if (BuildConfig.DEBUG) Log.d("MovieLibraryUpdate", msg); } @Override public void onMovieAdded(String title, Bitmap cover, Bitmap backdrop, int count) { mCount = count; updateMovieAddedNotification(title, cover, backdrop); } private void updateMovieAddedNotification(String title, Bitmap cover, Bitmap backdrop) { mBuilder.setLargeIcon(cover); mBuilder.setContentTitle(getString(R.string.updatingMovies) + " (" + (int) ((100.0 / (double) mTotalFiles) * (double) mCount) + "%)"); mBuilder.setContentText(getString(R.string.stringJustAdded) + ": " + title); mBuilder.setStyle(new NotificationCompat.BigPictureStyle() .setSummaryText(getString(R.string.stringJustAdded) + ": " + title).bigPicture(backdrop)); // Show the updated notification mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } private void updateMovieScaningNotification(String filesource) { mBuilder.setSmallIcon(R.drawable.ic_sync_white_24dp); mBuilder.setContentTitle(getString(R.string.updatingMovies)); mBuilder.setContentText(getString(R.string.scanning) + ": " + filesource); // Show the updated notification mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } private void showPostUpdateNotification() { // Set up cancel dialog intent Intent notificationIntent = new Intent(this, Main.class); notificationIntent.putExtra("fromUpdate", true); notificationIntent.putExtra("startup", "1"); notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); // Setup up notification mBuilder = new NotificationCompat.Builder(getApplicationContext()); mBuilder.setColor(getResources().getColor(R.color.color_primary)); if (!mStopUpdate) { mBuilder.setSmallIcon(R.drawable.ic_done_white_24dp); mBuilder.setTicker(getString(R.string.finishedMovieLibraryUpdate)); mBuilder.setContentTitle(getString(R.string.finishedMovieLibraryUpdate)); mBuilder.setContentText(getString(R.string.stringJustAdded) + " " + mCount + " " + getResources().getQuantityString(R.plurals.moviesInLibrary, mCount)); } else { mBuilder.setSmallIcon(R.drawable.ic_cancel_white_24dp); mBuilder.setTicker(getString(R.string.stringUpdateCancelled)); mBuilder.setContentTitle(getString(R.string.stringUpdateCancelled)); mBuilder.setContentText(getString(R.string.stringJustAdded) + " " + mCount + " " + getResources().getQuantityString(R.plurals.moviesInLibrary, mCount, mCount)); } mBuilder.setContentIntent(contentIntent); mBuilder.setAutoCancel(true); // Build notification Notification updateNotification = mBuilder.build(); // Show the notification mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if (mCount > 0) mNotificationManager.notify(POST_UPDATE_NOTIFICATION, updateNotification); } }