com.squeezecontrol.download.MusicDownloadService.java Source code

Java tutorial

Introduction

Here is the source code for com.squeezecontrol.download.MusicDownloadService.java

Source

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 */

package com.squeezecontrol.download;

import android.os.Environment;
import android.util.Log;
import com.squeezecontrol.BrowseLoadResult;
import com.squeezecontrol.io.MusicBrowser;
import com.squeezecontrol.model.Album;
import com.squeezecontrol.model.Song;
import com.squeezecontrol.util.PathUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHttpResponse;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.LinkedBlockingQueue;

public class MusicDownloadService {

    private static final int BUFFER_SIZE = 8096 * 4;
    private static final int PROGRESS_THRESHOLD = 1000 * 200;

    private static final String TAG = "SongDownloadService";

    private SongDownloadThread mDownloadThread;
    private AlbumDownloadThread mAlbumDownloadThread;

    private LinkedBlockingQueue<Song> mSongQueue = new LinkedBlockingQueue<Song>();
    private LinkedBlockingQueue<Album> mAlbumQueue = new LinkedBlockingQueue<Album>();

    private DefaultHttpClient mClient;
    private String mBaseUrl;
    private String mSongFolder;

    private MusicBrowser mMusicBrowser;

    public MusicDownloadService(MusicBrowser musicBrowser, String baseUrl, String username, String password) {
        this.mMusicBrowser = musicBrowser;
        this.mBaseUrl = baseUrl;
        this.mSongFolder = Environment.getExternalStorageDirectory() + "/Music/";

        mClient = new DefaultHttpClient();
        if (username != null && !"".equals(username)) {
            Credentials defaultcreds = new UsernamePasswordCredentials("dag", "test");
            mClient.getCredentialsProvider().setCredentials(AuthScope.ANY, defaultcreds);
        }
    }

    public void queueSongForDownload(Song song) {
        mSongQueue.add(song);
    }

    public synchronized void start() {
        mDownloadThread = new SongDownloadThread();
        mDownloadThread.start();
        mAlbumDownloadThread = new AlbumDownloadThread();
        mAlbumDownloadThread.start();
    }

    public synchronized void stop() {
        if (mDownloadThread != null) {
            mDownloadThread.mStopped = true;
            mDownloadThread.interrupt();
        }
        if (mAlbumDownloadThread != null) {
            mAlbumDownloadThread.mStopped = true;
            mAlbumDownloadThread.interrupt();
        }
    }

    protected void onDownloadStarted(Song song, int songsInQueue) {

    }

    protected void onDownloadProgress(Song song, int songsInQueue, long bytesTransferred, long totalBytes) {

    }

    protected void onDownloadCompleted(Song song, int songsInQuee) {

    }

    protected void onDownloadError(Song song, String errorMessage) {

    }

    public void queueAlbumForDownload(Album album) {
        mAlbumQueue.add(album);
    }

    private void downloadSong(Song song) {
        HttpEntity entity = null;
        InputStream in = null;
        try {
            onDownloadStarted(song, mSongQueue.size());
            String fileName = createFilenamePath(song);
            HttpGet get = new HttpGet(mBaseUrl + song.id + "/download");
            HttpResponse response = (BasicHttpResponse) mClient.execute(get);
            entity = response.getEntity();
            long length = response.getEntity().getContentLength();
            in = response.getEntity().getContent();
            FileOutputStream out = new FileOutputStream(fileName);

            byte[] buf = new byte[BUFFER_SIZE];
            long bytesTransferred = 0;
            long bytesTransferredSinceThreshold = 0;
            int read = 0;
            while ((read = in.read(buf, 0, BUFFER_SIZE)) != -1) {
                out.write(buf, 0, read);
                bytesTransferred += read;
                bytesTransferredSinceThreshold += read;
                if (bytesTransferredSinceThreshold > PROGRESS_THRESHOLD) {
                    onDownloadProgress(song, mSongQueue.size(), bytesTransferred, length);
                    bytesTransferredSinceThreshold = 0;
                }
            }
            out.close();
            in.close();
            response.getEntity().consumeContent();
            onDownloadCompleted(song, mSongQueue.size());
        } catch (IOException e) {
            Log.e(TAG, "Error downloading song: " + e.getMessage());
            onDownloadError(song, e.getMessage());
        } finally {
            if (entity != null) {
                try {
                    entity.consumeContent();
                } catch (IOException e) {
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ioe) {
                }
            }
        }
    }

    private String createFilenamePath(Song song) throws IOException {
        File songFolder = new File(mSongFolder + "/" + PathUtils.escapeInvalidPathCharacters(song.artist) + "/"
                + PathUtils.escapeInvalidPathCharacters(song.album));
        if (!songFolder.exists()) {
            if (!songFolder.mkdirs()) {
                throw new IOException("Error creading album folder. Is the SD card mounted?");
            }
        }
        return songFolder.getAbsolutePath() + "/" + PathUtils.escapeInvalidPathCharacters(song.title) + "."
                + song.type;
    }

    /**
     * Looks up song information for an album and queues the songs individually.
     *
     * @author daggerrz
     */
    class AlbumDownloadThread extends Thread {
        private boolean mStopped = false;

        public AlbumDownloadThread() {
            setName("Album download thread");
        }

        @Override
        public void run() {
            while (!mStopped) {
                Album a;
                try {
                    a = mAlbumQueue.take();
                    int songCount = mMusicBrowser.getSongCount(null, a.id);
                    BrowseLoadResult<Song> songs = mMusicBrowser.getSongs(null, a.id, null, 0, songCount);
                    for (Song song : songs.getResults())
                        mSongQueue.add(song);
                } catch (InterruptedException e) {
                }
            }
        }
    }

    class SongDownloadThread extends Thread {

        private boolean mStopped = false;

        public SongDownloadThread() {
            setName("Song download thread");
        }

        @Override
        public void run() {
            while (!mStopped) {
                Song song;
                try {
                    song = mSongQueue.take();
                    downloadSong(song);
                } catch (InterruptedException e) {
                }
            }
        }
    }

}