/* * This source is part of the * _____ ___ ____ * __ / / _ \/ _ | / __/___ _______ _ * / // / , _/ __ |/ _/_/ _ \/ __/ _ `/ * \___/_/|_/_/ |_/_/ (_)___/_/ \_, / * /___/ * repository. * * Copyright (C) 2015 Carmen Alvarez (c@rmen.ca) * * 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 ca.rmen.android.networkmonitor.app.dbops.backend; import android.app.IntentService; 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.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.annotation.DrawableRes; import android.support.v4.app.ActivityCompat; import android.support.v4.app.NotificationCompat; import android.widget.Toast; import java.io.File; import ca.rmen.android.networkmonitor.Constants; import ca.rmen.android.networkmonitor.R; import ca.rmen.android.networkmonitor.app.bus.NetMonBus; import ca.rmen.android.networkmonitor.app.dbops.backend.clean.DBCompress; import ca.rmen.android.networkmonitor.app.dbops.backend.clean.DBPurge; import ca.rmen.android.networkmonitor.app.dbops.backend.export.CSVExport; import ca.rmen.android.networkmonitor.app.dbops.backend.export.DBExport; import ca.rmen.android.networkmonitor.app.dbops.backend.export.ExcelExport; import ca.rmen.android.networkmonitor.app.dbops.backend.export.FileExport; import ca.rmen.android.networkmonitor.app.dbops.backend.export.GnuplotExport; import ca.rmen.android.networkmonitor.app.dbops.backend.export.HTMLExport; import ca.rmen.android.networkmonitor.app.dbops.backend.export.kml.KMLExport; import ca.rmen.android.networkmonitor.app.dbops.backend.imp0rt.DBImport; import ca.rmen.android.networkmonitor.util.Log; /** */ public class DBOpIntentService extends IntentService { private static final String TAG = Constants.TAG + DBOpIntentService.class.getSimpleName(); private NotificationProgressListener mCompressProgressListener; private NotificationProgressListener mPurgeProgressListener; private NotificationProgressListener mExportProgressListener; private NotificationProgressListener mImportProgressListener; private final static Object lock = new Object(); public enum ExportFormat { CSV, DB, EXCEL, HTML, KML, GNUPLOT, SUMMARY } public static final String ACTION_STOP_DB_OP = "ca.rmen.android.networkmonitor.app.dbops.backend.action.STOP_DB_OP"; private static final String ACTION_COMPRESS = "ca.rmen.android.networkmonitor.app.dbops.backend.action.COMPRESS"; private static final String ACTION_PURGE = "ca.rmen.android.networkmonitor.app.dbops.backend.action.PURGE"; private static final String ACTION_EXPORT = "ca.rmen.android.networkmonitor.app.dbops.backend.action.EXPORT"; private static final String ACTION_IMPORT = "ca.rmen.android.networkmonitor.app.dbops.backend.action.IMPORT"; private static final String EXTRA_PURGE_NUM_ROWS_TO_KEEP = "ca.rmen.android.networkmonitor.app.dbops.backend.extra.PURGE_NUM_ROWS_TO_KEEP"; private static final String EXTRA_EXPORT_FORMAT = "ca.rmen.android.networkmonitor.app.dbops.backend.extra.EXPORT_FILE_FORMAT"; private static final String EXTRA_EXPORT_KML_PLACEMARK_COLUMN_NAME = "ca.rmen.android.networkmonitor.app.dbops.backend.extra.EXPORT_KML_PLACEMARK_COLUMN_NAME"; private static final String EXTRA_DB_OP_TOAST = "ca.rmen.android.networkmonitor.app.dbops.backend.extra.DP_OP_TOAST"; private static final String EXTRA_DB_OP_NAME = "ca.rmen.android.networkmonitor.app.dbops.backend.extra.DP_OP_NAME"; private DBOperation mDBOperation = null; private NetMonBus.DBOperationStarted mDBOperationStarted; private Handler mHandler; public static void startActionCompress(Context context) { Intent intent = new Intent(context, DBOpIntentService.class); intent.setAction(ACTION_COMPRESS); intent.putExtra(EXTRA_DB_OP_TOAST, context.getString(R.string.compress_toast_start)); intent.putExtra(EXTRA_DB_OP_NAME, context.getString(R.string.compress_feature_name)); context.startService(intent); } public static void startActionPurge(Context context, int numRowsToKeep) { Intent intent = new Intent(context, DBOpIntentService.class); intent.setAction(ACTION_PURGE); intent.putExtra(EXTRA_PURGE_NUM_ROWS_TO_KEEP, numRowsToKeep); intent.putExtra(EXTRA_DB_OP_TOAST, context.getString(R.string.purge_toast_start)); intent.putExtra(EXTRA_DB_OP_NAME, context.getString(R.string.purge_feature_name)); context.startService(intent); } public static void startActionExport(Context context, ExportFormat exportFormat) { Intent intent = new Intent(context, DBOpIntentService.class); intent.setAction(ACTION_EXPORT); intent.putExtra(EXTRA_EXPORT_FORMAT, exportFormat); intent.putExtra(EXTRA_DB_OP_TOAST, context.getString(R.string.export_progress_preparing_export)); intent.putExtra(EXTRA_DB_OP_NAME, context.getString(R.string.export_feature_name)); context.startService(intent); } public static void startActionKMLExport(Context context, String placemarkNameColumn) { Intent intent = new Intent(context, DBOpIntentService.class); intent.setAction(ACTION_EXPORT); intent.putExtra(EXTRA_EXPORT_FORMAT, ExportFormat.KML); intent.putExtra(EXTRA_EXPORT_KML_PLACEMARK_COLUMN_NAME, placemarkNameColumn); intent.putExtra(EXTRA_DB_OP_TOAST, context.getString(R.string.export_progress_preparing_export)); intent.putExtra(EXTRA_DB_OP_NAME, context.getString(R.string.export_feature_name)); context.startService(intent); } public static void startActionImport(Context context, Uri uri) { Intent intent = new Intent(context, DBOpIntentService.class); intent.setAction(ACTION_IMPORT); intent.setData(uri); intent.putExtra(EXTRA_DB_OP_TOAST, context.getString(R.string.import_toast_start)); intent.putExtra(EXTRA_DB_OP_NAME, context.getString(R.string.import_feature_name)); context.startService(intent); } @SuppressWarnings("WeakerAccess") public DBOpIntentService() { super("DBOpIntentService"); } @Override public void onCreate() { super.onCreate(); mHandler = new Handler(); mCompressProgressListener = new NotificationProgressListener(this, DBCompress.class.hashCode(), R.drawable.ic_stat_db_op_compress, R.string.compress_notif_progress_title, R.string.compress_notif_progress_content, R.string.compress_notif_complete_title); mPurgeProgressListener = new NotificationProgressListener(this, DBPurge.class.hashCode(), R.drawable.ic_stat_db_op_delete, R.string.purge_notif_progress_title, R.string.purge_notif_progress_content, R.string.purge_notif_complete_title); mExportProgressListener = new NotificationProgressListener(this, FileExport.class.hashCode(), R.drawable.ic_stat_db_op_export, R.string.export_notif_progress_title, R.string.export_notif_progress_content, R.string.export_notif_complete_title); mImportProgressListener = new NotificationProgressListener(this, DBImport.class.hashCode(), R.drawable.ic_stat_db_op_import, R.string.import_notif_progress_title, R.string.import_notif_progress_content, R.string.import_notif_complete_title); registerReceiver(mStopSelfReceiver, new IntentFilter(ACTION_STOP_DB_OP)); } @Override protected void onHandleIntent(final Intent intent) { if (intent != null) { final String action = intent.getAction(); String dbOp = intent.getStringExtra(EXTRA_DB_OP_NAME); synchronized (lock) { mDBOperationStarted = new NetMonBus.DBOperationStarted(getString(R.string.db_op_in_progress, dbOp)); } // Show a toast mHandler.post(() -> { String toast = intent.getStringExtra(EXTRA_DB_OP_TOAST); Toast.makeText(DBOpIntentService.this, toast, Toast.LENGTH_LONG).show(); synchronized (lock) { if (mDBOperationStarted != null) { NetMonBus.getBus().postSticky(mDBOperationStarted); } } }); // Do the db operation if (ACTION_COMPRESS.equals(action)) { handleActionCompress(); NetMonBus.post(new NetMonBus.DBOperationEnded(true)); } else if (ACTION_PURGE.equals(action)) { final int numRowsToKeep = intent.getIntExtra(EXTRA_PURGE_NUM_ROWS_TO_KEEP, 0); handleActionPurge(numRowsToKeep); NetMonBus.post(new NetMonBus.DBOperationEnded(true)); } else if (ACTION_EXPORT.equals(action)) { final ExportFormat exportFileFormat = (ExportFormat) intent.getSerializableExtra(EXTRA_EXPORT_FORMAT); handleActionExport(exportFileFormat, intent.getExtras()); NetMonBus.post(new NetMonBus.DBOperationEnded(false)); } else if (ACTION_IMPORT.equals(action)) { final Uri uri = intent.getData(); handleActionImport(uri); NetMonBus.post(new NetMonBus.DBOperationEnded(true)); } mDBOperation = null; synchronized (lock) { mDBOperationStarted = null; NetMonBus.DBOperationStarted stickyEvent = NetMonBus.getBus().getStickyEvent(NetMonBus.DBOperationStarted.class); if (stickyEvent != null) NetMonBus.getBus().removeStickyEvent(stickyEvent); } } } @Override public void onDestroy() { unregisterReceiver(mStopSelfReceiver); super.onDestroy(); } private void handleActionCompress() { Log.d(TAG, "handleActionCompress()"); mDBOperation = new DBCompress(this); mDBOperation.execute(mCompressProgressListener); } private void handleActionPurge(int numRowsToKeep) { Log.d(TAG, "handleActionPurge() called with " + "numRowsToKeep = [" + numRowsToKeep + "]"); mDBOperation = new DBPurge(this, numRowsToKeep); mDBOperation.execute(mPurgeProgressListener); } private void handleActionExport(ExportFormat exportFileFormat, Bundle extras) { Log.d(TAG, "handleActionExport() called with exportFileFormat = [" + exportFileFormat + "]"); FileExport fileExport; switch (exportFileFormat) { case CSV: fileExport = new CSVExport(this); break; case DB: fileExport = new DBExport(this); break; case EXCEL: fileExport = new ExcelExport(this); break; case HTML: fileExport = new HTMLExport(this, true); break; case KML: String placemarkColumnName = extras.getString(EXTRA_EXPORT_KML_PLACEMARK_COLUMN_NAME); fileExport = new KMLExport(this, placemarkColumnName); break; case GNUPLOT: fileExport = new GnuplotExport(this); break; case SUMMARY: default: fileExport = null; } mDBOperation = fileExport; File file = null; if (fileExport != null) { fileExport.execute(mExportProgressListener); file = fileExport.getFile(); } NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // Start the summary report Intent shareIntent = FileExport.getShareIntent(this, file); // All done PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, shareIntent, PendingIntent.FLAG_UPDATE_CURRENT); final NotificationCompat.Builder notificationBuilder; if (fileExport != null && fileExport.isCanceled()) { notificationBuilder = prepareFileExportNotification(R.drawable.ic_stat_action_done, getString(R.string.export_notif_canceled_title), getString(R.string.export_notif_canceled_content), pendingIntent, true); } else { notificationBuilder = prepareFileExportNotification(R.drawable.ic_stat_action_done, getString(R.string.export_notif_complete_title), getString(R.string.export_notif_complete_content), pendingIntent, true); } notificationBuilder.addAction(R.drawable.ic_pref_share, getString(R.string.action_share), pendingIntent); notificationManager.notify(FileExport.class.hashCode(), notificationBuilder.build()); } private NotificationCompat.Builder prepareFileExportNotification(@DrawableRes int iconId, String titleText, String contentText, PendingIntent pendingIntent, boolean autoCancel) { return new NotificationCompat.Builder(this) .setSmallIcon(iconId) .setTicker(titleText) .setContentTitle(titleText) .setContentText(contentText) .setStyle(new NotificationCompat.BigTextStyle().bigText(contentText)) .setAutoCancel(autoCancel) .setOngoing(!autoCancel) .setContentIntent(pendingIntent) .setColor(ActivityCompat.getColor(this, R.color.netmon_color)); } private void handleActionImport(Uri uri) { Log.d(TAG, "handleActionImport() called with " + "uri = [" + uri + "]"); mDBOperation = new DBImport(this, uri); mDBOperation.execute(mImportProgressListener); } private final BroadcastReceiver mStopSelfReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.d(TAG, "onReceive() called with " + "context = [" + context + "], intent = [" + intent + "]"); if (ACTION_STOP_DB_OP.equals(intent.getAction())) { if (mDBOperation != null) mDBOperation.cancel(); } } }; }