org.gateshipone.malp.application.artworkdatabase.BulkDownloadService.java Source code

Java tutorial

Introduction

Here is the source code for org.gateshipone.malp.application.artworkdatabase.BulkDownloadService.java

Source

/*
 *  Copyright (C) 2017 Team Gateship-One
 *  (Hendrik Borghorst & Frederik Luetkes)
 *
 *  The AUTHORS.md file contains a detailed contributors list:
 *  <https://github.com/gateship-one/malp/blob/master/AUTHORS.md>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package org.gateshipone.malp.application.artworkdatabase;

import android.app.Notification;
import android.app.NotificationManager;

import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.Log;

import com.android.volley.Request;
import com.android.volley.RequestQueue;

import org.gateshipone.malp.R;
import org.gateshipone.malp.application.artworkdatabase.network.MALPRequestQueue;
import org.gateshipone.malp.mpdservice.ConnectionManager;
import org.gateshipone.malp.mpdservice.handlers.MPDConnectionStateChangeHandler;
import org.gateshipone.malp.mpdservice.handlers.serverhandler.MPDQueryHandler;
import org.gateshipone.malp.mpdservice.profilemanagement.MPDProfileManager;

public class BulkDownloadService extends Service implements ArtworkManager.BulkLoadingProgressCallback {
    private static final String TAG = BulkDownloadService.class.getSimpleName();

    private static final int NOTIFICATION_ID = 42;

    public static final String ACTION_CANCEL = "org.gateshipone.malp.cancel_download";
    public static final String ACTION_START_BULKDOWNLOAD = "org.gateshipone.malp.start_download";

    public static final String BUNDLE_KEY_ARTIST_PROVIDER = "org.gateshipone.malp.artist_provider";
    public static final String BUNDLE_KEY_ALBUM_PROVIDER = "org.gateshipone.malp.album_provider";
    public static final String BUNDLE_KEY_WIFI_ONLY = "org.gateshipone.malp.wifi_only";

    private MPDProfileManager mProfileManager;

    private NotificationManager mNotificationManager;
    private NotificationCompat.Builder mBuilder;

    private ConnectionStateHandler mConnectionHandler;

    private int mRemainingArtists;
    private int mRemainingAlbums;

    private int mSumImageDownloads;

    private ActionReceiver mBroadcastReceiver;

    private PowerManager.WakeLock mWakelock;

    private ConnectionStateReceiver mConnectionStateChangeReceiver;

    private boolean mWifiOnly;

    /**
     * Called when the service is created because it is requested by an activity
     */
    @Override
    public void onCreate() {
        super.onCreate();
        mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
        if (null == mConnectionHandler) {
            mConnectionHandler = new ConnectionStateHandler(this);
            Log.v(TAG, "Registering connection state listener");
            MPDQueryHandler.registerConnectionStateListener(mConnectionHandler);
        }
        if (null == mProfileManager) {
            mProfileManager = new MPDProfileManager(getApplicationContext());
        }

        mSumImageDownloads = 0;

        mConnectionStateChangeReceiver = new ConnectionStateReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(mConnectionStateChangeReceiver, filter);
    }

    @Override
    public void onDestroy() {
        unregisterReceiver(mBroadcastReceiver);
        unregisterReceiver(mConnectionStateChangeReceiver);
        Log.v(TAG, "Calling super.onDestroy()");
        super.onDestroy();
        Log.v(TAG, "Called super.onDestroy()");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        if (intent != null && intent.getAction() != null && intent.getAction().equals(ACTION_START_BULKDOWNLOAD)) {
            Log.v(TAG, "Starting bulk download in service with thread id: " + Thread.currentThread().getId());

            // reset counter
            mRemainingArtists = 0;
            mRemainingAlbums = 0;
            mSumImageDownloads = 0;

            String artistProvider = getString(R.string.pref_artwork_provider_artist_default);
            String albumProvider = getString(R.string.pref_artwork_provider_album_default);
            mWifiOnly = true;

            // read setting from extras
            Bundle extras = intent.getExtras();
            if (extras != null) {
                artistProvider = extras.getString(BUNDLE_KEY_ARTIST_PROVIDER,
                        getString(R.string.pref_artwork_provider_artist_default));
                albumProvider = extras.getString(BUNDLE_KEY_ALBUM_PROVIDER,
                        getString(R.string.pref_artwork_provider_album_default));
                mWifiOnly = intent.getBooleanExtra(BUNDLE_KEY_WIFI_ONLY, true);
            }

            ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkInfo netInfo = cm.getActiveNetworkInfo();
            if (null == netInfo) {
                return START_NOT_STICKY;
            }
            boolean isWifi = netInfo.getType() == ConnectivityManager.TYPE_WIFI
                    || netInfo.getType() == ConnectivityManager.TYPE_ETHERNET;

            if (mWifiOnly && !isWifi) {
                return START_NOT_STICKY;
            }

            PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
            mWakelock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MALP_BulkDownloader");

            ArtworkManager artworkManager = ArtworkManager.getInstance(getApplicationContext());
            artworkManager.initialize(artistProvider, albumProvider, mWifiOnly);

            // FIXME do some timeout checking. e.g. 5 minutes no new image then cancel the process
            mWakelock.acquire();
            ConnectionManager.reconnectLastServer(this);
        }
        return START_NOT_STICKY;

    }

    private void runAsForeground() {
        if (mBroadcastReceiver == null) {
            mBroadcastReceiver = new ActionReceiver();

            // Create a filter to only handle certain actions
            IntentFilter intentFilter = new IntentFilter();

            intentFilter.addAction(ACTION_CANCEL);

            registerReceiver(mBroadcastReceiver, intentFilter);
        }

        mBuilder = new NotificationCompat.Builder(this)
                .setContentTitle(getResources().getString(R.string.downloader_notification_title))
                .setStyle(new NotificationCompat.BigTextStyle()
                        .bigText(getResources().getString(R.string.downloader_notification_remaining_images) + ' '
                                + String.valueOf(mSumImageDownloads - (mRemainingArtists + mRemainingAlbums)) + '/'
                                + String.valueOf(mSumImageDownloads)))
                .setProgress(mSumImageDownloads, mSumImageDownloads - (mRemainingArtists + mRemainingAlbums), false)
                .setSmallIcon(R.drawable.ic_notification_24dp);

        mBuilder.setOngoing(true);

        // Cancel action
        Intent nextIntent = new Intent(BulkDownloadService.ACTION_CANCEL);
        PendingIntent nextPendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 1, nextIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
        android.support.v7.app.NotificationCompat.Action cancelAction = new android.support.v7.app.NotificationCompat.Action.Builder(
                R.drawable.ic_cancel_24dp, getResources().getString(R.string.dialog_action_cancel),
                nextPendingIntent).build();

        mBuilder.addAction(cancelAction);

        Notification notification = mBuilder.build();
        startForeground(NOTIFICATION_ID, notification);
        mNotificationManager.notify(NOTIFICATION_ID, notification);

    }

    @Override
    public void startAlbumLoading(int albumCount) {
        Log.v(TAG, "Albumloading started with: " + albumCount + " albums");
        mSumImageDownloads += albumCount;
        mRemainingAlbums = albumCount;
        runAsForeground();
    }

    @Override
    public void startArtistLoading(int artistCount) {
        Log.v(TAG, "Artistloading started with: " + artistCount + " artists");
        mSumImageDownloads += artistCount;
        mRemainingArtists = artistCount;
        runAsForeground();
    }

    @Override
    public void albumsRemaining(int remainingAlbums) {
        mRemainingAlbums = remainingAlbums;
        updateNotification();
    }

    @Override
    public void artistsRemaining(int remainingArtists) {
        mRemainingArtists = remainingArtists;
        updateNotification();
    }

    @Override
    public void finishedLoading() {
        mNotificationManager.cancel(NOTIFICATION_ID);
        stopForeground(true);
        MPDQueryHandler.unregisterConnectionStateListener(mConnectionHandler);
        stopSelf();
        if (mWakelock.isHeld()) {
            mWakelock.release();
        }
    }

    private void updateNotification() {
        if ((mSumImageDownloads - (mRemainingArtists + mRemainingAlbums)) % 10 == 0) {
            mBuilder.setProgress(mSumImageDownloads, mSumImageDownloads - (mRemainingArtists + mRemainingAlbums),
                    false);
            mBuilder.setStyle(new NotificationCompat.BigTextStyle()
                    .bigText(getResources().getString(R.string.downloader_notification_remaining_images) + ' '
                            + String.valueOf(mSumImageDownloads - (mRemainingArtists + mRemainingAlbums)) + '/'
                            + String.valueOf(mSumImageDownloads)));
            mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
        }
    }

    private class ConnectionStateHandler extends MPDConnectionStateChangeHandler {

        BulkDownloadService mService;

        public ConnectionStateHandler(BulkDownloadService service) {
            mService = service;
        }

        @Override
        public void onConnected() {
            Log.v(TAG, "Connected to mpd host");
            mSumImageDownloads = 0;
            mRemainingArtists = 0;
            mRemainingAlbums = 0;
            ArtworkManager.getInstance(getApplicationContext()).bulkLoadImages(mService);
        }

        @Override
        public void onDisconnected() {

        }
    }

    private class ActionReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.e(TAG, "Broadcast requested");
            if (intent.getAction().equals(ACTION_CANCEL)) {
                Log.e(TAG, "Cancel requested");
                ArtworkManager.getInstance(getApplicationContext()).cancelAllRequests();
                mNotificationManager.cancel(NOTIFICATION_ID);
                stopForeground(true);
                MPDQueryHandler.unregisterConnectionStateListener(mConnectionHandler);
                stopSelf();
            }
        }
    }

    private class ConnectionStateReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(BulkDownloadService.this);

            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkInfo netInfo = cm.getActiveNetworkInfo();
            if (null == netInfo) {
                return;
            }
            boolean wifiOnly = sharedPref.getBoolean(getString(R.string.pref_download_wifi_only_key),
                    getResources().getBoolean(R.bool.pref_download_wifi_default));
            boolean isWifi = netInfo.getType() == ConnectivityManager.TYPE_WIFI
                    || netInfo.getType() == ConnectivityManager.TYPE_ETHERNET;

            if (wifiOnly && !isWifi) {
                // Cancel all downloads
                Log.v(TAG, "Cancel all downloads because of connection change");
                MALPRequestQueue.getInstance(BulkDownloadService.this).cancelAll(new RequestQueue.RequestFilter() {
                    @Override
                    public boolean apply(Request<?> request) {
                        return true;
                    }
                });
            }

        }
    }
}