Java tutorial
/* * Copyright (C) 2015 Victor Apoyan. * * 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.armtimes.downloaders; import android.app.Service; import android.content.ContentValues; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.IBinder; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import com.armtimes.database.NewsContract; import com.armtimes.database.NewsDatabaseHelper; import com.armtimes.drawer.CommonFragment; import com.armtimes.utils.Logger; import com.armtimes.utils.Utils; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public final class ArticleInfoDownloaderService extends Service implements ArticleInfoDownloader.ArticleInfoDownloaderListener { private final static String TAG = ArticleInfoDownloaderService.class.getSimpleName(); public final static String EXTRA_CATEGORY = "CATEGORY"; private ExecutorService mExecutor = null; private NewsDatabaseHelper mDatabaseHelper = null; private SQLiteDatabase mDatabase = null; @Override public void onCreate() { super.onCreate(); mDatabaseHelper = new NewsDatabaseHelper(getApplicationContext()); // Open database that will be used for reading and writing. mDatabase = mDatabaseHelper.getWritableDatabase(); mExecutor = Executors.newSingleThreadExecutor(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { int result = START_STICKY; // If there are not any pending start commands to be delivered // to the service, it will be called with a null intent object if (intent == null) { // Logger.t(getApplicationContext(), "onStartCommand", "No any pending start commands!", "#8BC34A"); return result; } final String category = intent.getStringExtra(EXTRA_CATEGORY); mExecutor.execute(new QueryDatabaseAsync(category)); return result; } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { // Clean-up ... if (mExecutor != null) mExecutor.shutdown(); if (mDatabase != null && mDatabase.isOpen()) mDatabase.close(); if (mDatabaseHelper != null) mDatabaseHelper.close(); super.onDestroy(); } @Override public void onDownloadCompleted(Set<ArticleInfo> articleInfoSet, String tableName) { if (articleInfoSet != null) { for (ArticleInfo articleInfo : articleInfoSet) { if (articleInfo.processed) { // Update single item info in database. ContentValues cv = new ContentValues(); cv.put(NewsContract.COL_NAME_NEWS_DESC_LONG, articleInfo.description); cv.put(NewsContract.COL_NAME_NEWS_IMAGE_URL, articleInfo.imageLink); cv.put(NewsContract.COL_NAME_NEWS_IMAGE_PATH, articleInfo.thumbnailImagePath); mDatabase.update(tableName.toUpperCase(), cv, String.format("%s=\"%s\"", NewsContract.COL_NAME_NEWS_URL, articleInfo.url), null); } } // Notify that current portion of items were downloaded. Intent intent = new Intent("event-downloaded"); intent.putExtra(CommonFragment.EXTRA_CATEGORY, tableName); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } // Check if all tasks are done close service. if (ArticleInfoDownloader.workDone()) { // Create Intent for broadcast receiver in order to // notify that all data were downloaded. Intent intent = new Intent("event-downloaded"); intent.putExtra(CommonFragment.EXTRA_CATEGORY, "all"); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); stopSelf(); } } /** * */ final class QueryDatabaseAsync implements Runnable { private final static String QUERY_SELECT_ALL_DESC = "SELECT * FROM %s ORDER BY %s DESC"; private final String mCategory; private final Set<ArticleInfo> mArticleInfoSet; private final String mQueryString; private QueryDatabaseAsync(final String category) { mCategory = category; mArticleInfoSet = new HashSet<>(); mQueryString = String.format(QUERY_SELECT_ALL_DESC, mCategory.toUpperCase(), NewsContract.COL_NAME_NEWS_DATE); } @Override public void run() { if (mDatabase == null) { Logger.e(TAG, "Database is null!"); return; } Cursor cursor = mDatabase.rawQuery(mQueryString, null); if (cursor != null && cursor.getCount() > 0) { while (cursor.moveToNext()) { final String url = cursor .getString(cursor.getColumnIndexOrThrow(NewsContract.COL_NAME_NEWS_URL)); final String description = cursor .getString(cursor.getColumnIndexOrThrow(NewsContract.COL_NAME_NEWS_DESC_LONG)); final String imageLink = cursor .getString(cursor.getColumnIndexOrThrow(NewsContract.COL_NAME_NEWS_IMAGE_URL)); ArticleInfo articleInfo = new ArticleInfo(url, description, imageLink); if (!articleInfo.hasAllData() || !Utils.thumbnailImageExistsOnDisk(getApplicationContext(), imageLink)) mArticleInfoSet.add(articleInfo); } cursor.close(); } Logger.d(TAG, String.format( "All information were queried from database for %s. " + "Total items count is: %d", mCategory, mArticleInfoSet.size())); ArticleInfoDownloader.startDownloading(getApplicationContext(), mCategory, ArticleInfoDownloaderService.this, mArticleInfoSet); } } }