com.adam.aslfms.service.Scrobbler.java Source code

Java tutorial

Introduction

Here is the source code for com.adam.aslfms.service.Scrobbler.java

Source

/**
 *  This file is part of Simple Last.fm Scrobbler.
 *
 *  Simple Last.fm Scrobbler 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.
 *
 *  Simple Last.fm Scrobbler 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 Simple Last.fm Scrobbler.  If not, see <http://www.gnu.org/licenses/>.
 *  
 *  See http://code.google.com/p/a-simple-lastfm-scrobbler/ for the latest version.
 */

package com.adam.aslfms.service;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.content.Context;
import android.util.Log;

import com.adam.aslfms.R;
import com.adam.aslfms.service.Handshaker.HandshakeResult;
import com.adam.aslfms.util.ScrobblesDatabase;
import com.adam.aslfms.util.Track;
import com.adam.aslfms.util.AuthStatus.BadSessionException;
import com.adam.aslfms.util.AuthStatus.TemporaryFailureException;
import com.adam.aslfms.util.enums.SubmissionType;

/**
 * 
 * @author tgwizard
 * 
 */
public class Scrobbler extends AbstractSubmitter {

    private static final String TAG = "Scrobbler";

    // private final Context mCtx;
    private final ScrobblesDatabase mDb;

    public static final int MAX_SCROBBLE_LIMIT = 50;

    public Scrobbler(NetApp napp, Context ctx, Networker net, ScrobblesDatabase db) {
        super(napp, ctx, net);
        this.mDb = db;
    }

    @Override
    public boolean doRun(HandshakeResult hInfo) {
        boolean ret;
        try {
            Log.d(TAG, "Scrobbling: " + getNetApp().getName());
            Track[] tracks = mDb.fetchTracksArray(getNetApp(), MAX_SCROBBLE_LIMIT);

            if (tracks.length == 0) {
                Log.d(TAG, "Retrieved 0 tracks from db, no scrobbling: " + getNetApp().getName());
                return true;
            }
            Log.d(TAG, "Retrieved " + tracks.length + " tracks from db: " + getNetApp().getName());

            for (int i = 0; i < tracks.length; i++) {
                Log.d(TAG, getNetApp().getName() + ": " + tracks[i].toString());
            }

            scrobbleCommit(hInfo, tracks); // throws if unsuccessful

            // delete scrobbles (not tracks) from db (not array)
            for (int i = 0; i < tracks.length; i++) {
                mDb.deleteScrobble(getNetApp(), tracks[i].getRowId());
            }

            // clean up tracks if no one else wants to scrobble them
            mDb.cleanUpTracks();

            // there might be more tracks in the db
            if (tracks.length == MAX_SCROBBLE_LIMIT) {
                Log.d(TAG, "Relaunching scrobbler, might be more tracks in db");
                relaunchThis();
            }

            // status stuff
            notifySubmissionStatusSuccessful(tracks[tracks.length - 1], tracks.length);

            ret = true;
        } catch (BadSessionException e) {
            Log.i(TAG, "BadSession: " + e.getMessage() + ": " + getNetApp().getName());
            getNetworker().launchHandshaker();
            relaunchThis();
            notifySubmissionStatusFailure(getContext().getString(R.string.auth_just_error));
            ret = true;
        } catch (TemporaryFailureException e) {
            Log.i(TAG, "Tempfail: " + e.getMessage() + ": " + getNetApp().getName());
            notifySubmissionStatusFailure(getContext().getString(R.string.auth_network_error_retrying));
            ret = false;
        }
        return ret;
    }

    @Override
    protected void relaunchThis() {
        getNetworker().launchScrobbler();
    }

    private void notifySubmissionStatusFailure(String reason) {
        super.notifySubmissionStatusFailure(SubmissionType.SCROBBLE, reason);
    }

    private void notifySubmissionStatusSuccessful(Track track, int statsInc) {
        super.notifySubmissionStatusSuccessful(SubmissionType.SCROBBLE, track, statsInc);
    }

    /**
     * 
     * @return a {@link ScrobbleResult} struct with some info
     * @throws BadSessionException
     * @throws TemporaryFailureException
     */
    public void scrobbleCommit(HandshakeResult hInfo, Track[] tracks)
            throws BadSessionException, TemporaryFailureException {

        DefaultHttpClient http = new DefaultHttpClient();
        HttpPost request = new HttpPost(hInfo.scrobbleUri);

        List<BasicNameValuePair> data = new LinkedList<BasicNameValuePair>();
        data.add(new BasicNameValuePair("s", hInfo.sessionId));

        for (int i = 0; i < tracks.length; i++) {
            Track track = tracks[i];
            String is = "[" + i + "]";
            data.add(new BasicNameValuePair("a" + is, track.getArtist()));
            data.add(new BasicNameValuePair("b" + is, track.getAlbum()));
            data.add(new BasicNameValuePair("t" + is, track.getTrack()));
            data.add(new BasicNameValuePair("i" + is, Long.toString(track.getWhen())));
            data.add(new BasicNameValuePair("o" + is, track.getSource()));
            data.add(new BasicNameValuePair("l" + is, Integer.toString(track.getDuration())));
            data.add(new BasicNameValuePair("n" + is, track.getTrackNr()));
            data.add(new BasicNameValuePair("m" + is, track.getMbid()));
            data.add(new BasicNameValuePair("r" + is, track.getRating()));
        }

        try {
            request.setEntity(new UrlEncodedFormEntity(data, "UTF-8"));
            ResponseHandler<String> handler = new BasicResponseHandler();
            String response = http.execute(request, handler);
            String[] lines = response.split("\n");
            if (response.startsWith("OK")) {
                Log.i(TAG, "Scrobble success: " + getNetApp().getName());
            } else if (response.startsWith("BADSESSION")) {
                throw new BadSessionException("Scrobble failed because of badsession");
            } else if (response.startsWith("FAILED")) {
                String reason = lines[0].substring(7);
                throw new TemporaryFailureException("Scrobble failed: " + reason);
            } else {
                throw new TemporaryFailureException("Scrobble failed weirdly: " + response);
            }

        } catch (ClientProtocolException e) {
            throw new TemporaryFailureException(TAG + ": " + e.getMessage());
        } catch (IOException e) {
            throw new TemporaryFailureException(TAG + ": " + e.getMessage());
        } finally {
            http.getConnectionManager().shutdown();
        }
    }
}