com.twitterdev.rdio.app.RdioApp.java Source code

Java tutorial

Introduction

Here is the source code for com.twitterdev.rdio.app.RdioApp.java

Source

package com.twitterdev.rdio.app;

/*
 Copyright (c) 2011 Rdio Inc
    
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
    
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
    
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.rdio.android.api.Rdio;
import com.rdio.android.api.RdioApiCallback;
import com.rdio.android.api.RdioListener;
import com.rdio.android.api.services.RdioAuthorisationException;
import com.rdio.android.api.OAuth1WebViewActivity;

import android.app.Activity;
import android.app.DialogFragment;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import twitter4j.Query;
import twitter4j.QueryResult;
import twitter4j.Status;
import twitter4j.Trend;
import twitter4j.Trends;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.ConfigurationBuilder;

/**
 * Really basic test app for the Rdio playback API.
 */
public class RdioApp extends Activity implements RdioListener {

    private static SharedPreferences mSharedPreferences;
    private static Twitter twitter;
    private static RequestToken requestToken;
    private AccessToken twitterAccessToken;

    private static final String TAG = "RdioAPIExample";

    private MediaPlayer player;

    private Queue<Track> trackQueue;

    private static Rdio rdio;

    // TODO CHANGE THIS TO YOUR APPLICATION KEY AND SECRET

    private static final List<String> where = new ArrayList<String>();

    private static String accessToken = null;
    private static String accessTokenSecret = null;
    protected ImageLoader imageLoader;

    private static final String PREF_ACCESSTOKEN = "prefs.accesstoken";
    private static final String PREF_ACCESSTOKENSECRET = "prefs.accesstokensecret";

    private static String collectionKey = null;

    private ImageView albumArt;
    private ImageView playPause;

    private DialogFragment getUserDialog;
    private DialogFragment getCollectionDialog;
    private DialogFragment getHeavyRotationDialog;
    private ArrayAdapter<String> stringTweetAdapter;
    private List<twitter4j.Status> statuses;
    private List<String> stringStatuses = new ArrayList<String>();
    private Activity ac;

    // Our model for the metadata for a track that we care about
    private class Track {
        public String key;
        public String trackName;
        public String artistName;
        public String albumName;
        public String albumArt;

        public Track(String k, String name, String artist, String album, String uri) {
            key = k;
            trackName = name;
            artistName = artist;
            albumName = album;
            albumArt = uri;
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        //
        imageLoader = ImageLoader.getInstance();
        imageLoader.init(ImageLoaderConfiguration.createDefault(this));
        // set full screen
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        final Activity ac = this;
        setContentView(R.layout.activity_main);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        List<String> where = new ArrayList<String>();

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        trackQueue = new LinkedList<Track>();

        // Initialize our Rdio object.  If we have cached access credentials, then use them - otherwise
        // Initialize w/ null values and the user will be prompted (if the Rdio app is installed), or
        // we'll fallback to 30s samples.
        if (rdio == null) {
            SharedPreferences settings = getPreferences(MODE_PRIVATE);
            accessToken = settings.getString(PREF_ACCESSTOKEN, null);
            accessTokenSecret = settings.getString(PREF_ACCESSTOKENSECRET, null);

            rdio = new Rdio(Constants.appKey, Constants.appSecret, accessToken, accessTokenSecret, this, this);

            if (accessToken == null || accessTokenSecret == null) {
                // If either one is null, reset both of them
                accessToken = accessTokenSecret = null;
                Intent myIntent = new Intent(RdioApp.this, OAuth1WebViewActivity.class);
                myIntent.putExtra(OAuth1WebViewActivity.EXTRA_CONSUMER_KEY, Constants.appKey);
                myIntent.putExtra(OAuth1WebViewActivity.EXTRA_CONSUMER_SECRET, Constants.appSecret);
                RdioApp.this.startActivityForResult(myIntent, 1);

            } else {
                Log.d(TAG, "Found cached credentials:");
                Log.d(TAG, "Access token: " + accessToken);
                Log.d(TAG, "Access token secret: " + accessTokenSecret);
                rdio.prepareForPlayback();
            }

        }

        ImageView i = (ImageView) findViewById(R.id.next);
        i.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                next(true);
            }
        });

        playPause = (ImageView) findViewById(R.id.playPause);
        playPause.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                playPause();
            }
        });

        albumArt = (ImageView) findViewById(R.id.albumArt);
        playPause();
    }

    @Override
    public void onDestroy() {
        Log.i(TAG, "Cleaning up..");

        // Make sure to call the cleanup method on the API object
        rdio.cleanup();

        // If we allocated a player, then cleanup after it
        if (player != null) {
            player.reset();
            player.release();
            player = null;
        }

        super.onDestroy();
    }

    /**
     * Get the current user, and load their collection to start playback with.
     * Requires authorization and the Rdio app to be installed.
     */

    private void LoadMoreTracks() {
        if (accessToken == null || accessTokenSecret == null) {
            Log.i(TAG, "Anonymous user! No more tracks to play.");

            // Notify the user we're out of tracks
            //Toast.makeText(this, getString(R.string.no_more_tracks), Toast.LENGTH_LONG).show();

            // Then helpfully point them to the market to go install Rdio ;)
            accessToken = accessTokenSecret = null;
            Intent myIntent = new Intent(RdioApp.this, OAuth1WebViewActivity.class);
            myIntent.putExtra(OAuth1WebViewActivity.EXTRA_CONSUMER_KEY, Constants.appKey);
            myIntent.putExtra(OAuth1WebViewActivity.EXTRA_CONSUMER_SECRET, Constants.appSecret);
            RdioApp.this.startActivityForResult(myIntent, 1);

            //finish();
            return;
        }

        showGetCollectionDialog();
        List<NameValuePair> args = new LinkedList<NameValuePair>();

        //

        //args.add(new BasicNameValuePair("query", where.get(1)));
        args.add(new BasicNameValuePair("type", "Track"));
        //Log.v("args", args.toString());
        rdio.apiCall("getTopCharts", args, new RdioApiCallback() {
            @Override
            public void onApiFailure(String methodName, Exception e) {
                dismissGetCollectionDialog();
                Log.e(TAG, methodName + " failed: ", e);
            }

            @Override
            public void onApiSuccess(JSONObject result) {
                try {
                    Log.v("result", result.toString());
                    //result = result.getJSONObject("result");

                    //                    result = result.getJSONObject(collectionKey);
                    List<Track> trackKeys = new LinkedList<Track>();
                    JSONArray tracks = result.getJSONArray("result");
                    Log.v("results", tracks.toString());
                    for (int i = 0; i < tracks.length(); i++) {
                        JSONObject trackObject = tracks.getJSONObject(i);
                        String key = trackObject.getString("key");
                        final String name = trackObject.getString("name");
                        final String artist = trackObject.getString("artist");
                        String album = trackObject.getString("album");
                        String albumArt = trackObject.getString("icon");
                        Log.d(TAG, "Found track: " + key + " => " + trackObject.getString("name"));

                        trackKeys.add(new Track(key, artist, album, name, albumArt));
                    }
                    if (trackKeys.size() > 1)
                        trackQueue.addAll(trackKeys);
                    dismissGetCollectionDialog();

                    next(true);

                } catch (Exception e) {
                    dismissGetCollectionDialog();
                    Log.e(TAG, "Failed to handle JSONObject: ");
                }
            }
        });
    }

    private void next(final boolean manualPlay) {
        if (player != null) {
            player.stop();
            player.release();
            player = null;
        }

        final Track track = trackQueue.poll();
        if (trackQueue.size() < 3) {
            Log.i(TAG, "Track queue depleted, loading more tracks");
            LoadMoreTracks();
        }

        if (track == null) {
            Log.e(TAG, "Track is null!  Size of queue: " + trackQueue.size());
            return;
        }

        // Load the next track in the background and prep the player (to start buffering)
        // Do this in a bkg thread so it doesn't block the main thread in .prepare()
        AsyncTask<Track, Void, Track> task = new AsyncTask<Track, Void, Track>() {
            @Override
            protected Track doInBackground(Track... params) {
                Track track = params[0];
                final String trackName = track.artistName;
                final String artist = track.trackName;
                try {
                    player = rdio.getPlayerForTrack(track.key, null, manualPlay);
                    player.prepare();
                    player.setOnCompletionListener(new OnCompletionListener() {
                        @Override
                        public void onCompletion(MediaPlayer mp) {
                            next(false);
                        }
                    });
                    player.start();
                    new getSearch().execute(track.trackName);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            TextView a = (TextView) findViewById(R.id.artist);
                            //a.setText(artist);
                            TextView t = (TextView) findViewById(R.id.track);
                            //t.setText(trackName);
                        }
                    });

                } catch (Exception e) {
                    Log.e("Test", "Exception " + e);
                }
                return track;
            }

            @Override
            protected void onPostExecute(Track track) {
                updatePlayPause(true);
            }
        };
        task.execute(track);

        // Fetch album art in the background and then update the UI on the main thread
        AsyncTask<Track, Void, Bitmap> artworkTask = new AsyncTask<Track, Void, Bitmap>() {
            @Override
            protected Bitmap doInBackground(Track... params) {
                Track track = params[0];
                try {
                    String artworkUrl = track.albumArt.replace("square-200", "square-600");
                    Log.i(TAG, "Downloading album art: " + artworkUrl);
                    Bitmap bm = null;
                    try {
                        URL aURL = new URL(artworkUrl);
                        URLConnection conn = aURL.openConnection();
                        conn.connect();
                        InputStream is = conn.getInputStream();
                        BufferedInputStream bis = new BufferedInputStream(is);
                        bm = BitmapFactory.decodeStream(bis);
                        bis.close();
                        is.close();
                    } catch (IOException e) {
                        Log.e(TAG, "Error getting bitmap", e);
                    }
                    return bm;
                } catch (Exception e) {
                    Log.e(TAG, "Error downloading artwork", e);
                    return null;
                }
            }

            @Override
            protected void onPostExecute(Bitmap artwork) {
                if (artwork != null) {
                    int imageWidth = artwork.getWidth();
                    int imageHeight = artwork.getHeight();
                    DisplayMetrics dimension = new DisplayMetrics();
                    getWindowManager().getDefaultDisplay().getMetrics(dimension);
                    int newWidth = dimension.widthPixels;

                    float scaleFactor = (float) newWidth / (float) imageWidth;
                    int newHeight = (int) (imageHeight * scaleFactor);

                    artwork = Bitmap.createScaledBitmap(artwork, newWidth, newHeight, true);
                    //albumArt.setImageBitmap(bitmap);

                    albumArt.setAdjustViewBounds(true);
                    albumArt.setImageBitmap(artwork);

                } else
                    albumArt.setImageResource(R.drawable.blank_album_art);
            }
        };
        artworkTask.execute(track);

        //Toast.makeText(this, String.format(getResources().getString(R.string.now_playing), track.trackName, track.albumName, track.artistName), Toast.LENGTH_LONG).show();
    }

    private void playPause() {
        if (player != null) {
            if (player.isPlaying()) {
                player.pause();
                updatePlayPause(false);
            } else {
                player.start();
                updatePlayPause(true);
            }
        } else {
            next(true);
        }
    }

    private void updatePlayPause(boolean playing) {
        if (playing) {
            playPause.setImageResource(R.drawable.pause);
        } else {
            playPause.setImageResource(R.drawable.play);
        }
    }

    /*************************
     * RdioListener Interface
     *************************/

    /*
     * Dispatched by the Rdio object when the Rdio object is done initializing, and a connection
     * to the Rdio app service has been established.  If authorized is true, then we reused our
     * existing OAuth credentials, and the API is ready for use.
     * @see com.rdio.android.api.RdioListener#onRdioReady()
     */
    @Override
    public void onRdioReadyForPlayback() {
        Log.i(TAG, "Rdio SDK is ready for playback");
    }

    @Override
    public void onRdioUserPlayingElsewhere() {
        Log.w(TAG, "Tell the user that playback is stopping.");
    }

    /*
     * Dispatched by the Rdio object once the setTokenAndSecret call has finished, and the credentials are
     * ready to be used to make API calls.  The token & token secret are passed in so that you can
     * save/cache them for future re-use.
     * @see com.rdio.android.api.RdioListener#onRdioAuthorised(java.lang.String, java.lang.String)
     */
    @Override
    public void onRdioAuthorised(String accessToken, String accessTokenSecret) {
        Log.i(TAG, "Application authorised, saving access token & secret.");
        Log.d(TAG, "Access token: " + accessToken);
        Log.d(TAG, "Access token secret: " + accessTokenSecret);

        SharedPreferences settings = getPreferences(MODE_PRIVATE);
        Editor editor = settings.edit();
        editor.putString(PREF_ACCESSTOKEN, accessToken);
        editor.putString(PREF_ACCESSTOKENSECRET, accessTokenSecret);
        editor.commit();
    }

    /*************************
     * Activity overrides
     *************************/
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == 1) {
            if (resultCode == RESULT_OK) {
                Log.v(TAG, "Login success");
                if (data != null) {
                    accessToken = data.getStringExtra("token");
                    accessTokenSecret = data.getStringExtra("tokenSecret");
                    onRdioAuthorised(accessToken, accessTokenSecret);
                    rdio.setTokenAndSecret(accessToken, accessTokenSecret);
                }
            } else if (resultCode == RESULT_CANCELED) {
                if (data != null) {
                    String errorCode = data.getStringExtra(OAuth1WebViewActivity.EXTRA_ERROR_CODE);
                    String errorDescription = data.getStringExtra(OAuth1WebViewActivity.EXTRA_ERROR_DESCRIPTION);
                    Log.v(TAG, "ERROR: " + errorCode + " - " + errorDescription);
                }
                accessToken = null;
                accessTokenSecret = null;
            }
            rdio.prepareForPlayback();
        }
    }

    /*************************
     * Dialog helpers
     *************************/
    private void showGetUserDialog() {
        if (getUserDialog == null) {
            getUserDialog = new RdioProgress();
        }

        if (getUserDialog.isAdded()) {
            return;
        }

        Bundle args = new Bundle();
        args.putString("message", getResources().getString(R.string.getting_user));

        getUserDialog.setArguments(args);
        getUserDialog.show(getFragmentManager(), "getUserDialog");
    }

    private void dismissGetUserDialog() {
        if (getUserDialog != null) {
            getUserDialog.dismiss();
        }
    }

    private void showGetCollectionDialog() {
        if (getCollectionDialog == null) {
            getCollectionDialog = new RdioProgress();
        }

        if (getCollectionDialog.isAdded()) {
            return;
        }

        Bundle args = new Bundle();
        args.putString("message", getResources().getString(R.string.getting_collection));

        getCollectionDialog.setArguments(args);
        getCollectionDialog.show(getFragmentManager(), "getCollectionDialog");
    }

    private void dismissGetCollectionDialog() {
        if (getCollectionDialog != null) {
            getCollectionDialog.dismiss();
        }
    }

    private void showGetHeavyRotationDialog() {
        if (getHeavyRotationDialog == null) {
            getHeavyRotationDialog = new RdioProgress();
        }

        if (getHeavyRotationDialog.isAdded()) {
            return;
        }

        Bundle args = new Bundle();
        args.putString("message", getResources().getString(R.string.getting_heavy_rotation));

        getHeavyRotationDialog.setArguments(args);
        getHeavyRotationDialog.show(getFragmentManager(), "getHeavyRotationDialog");
    }

    private void dismissGetHeavyRotationDialog() {
        if (getHeavyRotationDialog != null) {
            getHeavyRotationDialog.dismiss();
        }
    }

    // Twitter info

    private class getSearch extends AsyncTask<String, Void, String> {

        // set the last_tweet this is displayed on the device in a TextView

        @Override
        protected String doInBackground(String... params) {

            Log.v("LoggedIn", "getUser..doInBackground");
            Log.v("Search for ", params[0]);
            ConfigurationBuilder builder = new ConfigurationBuilder();
            builder.setOAuthConsumerKey(Constants.API_KEY);
            builder.setOAuthConsumerSecret(Constants.API_SECRET);

            //
            final Activity ac = RdioApp.this;

            // // Setup preferences
            mSharedPreferences = getApplicationContext().getSharedPreferences("twitter4j-sample", 0);

            // Access Token
            String twitter_access_token = mSharedPreferences.getString(Constants.PREF_KEY_OAUTH_TOKEN, "");
            // Access Token Secret
            String twitter_access_token_secret = mSharedPreferences.getString(Constants.PREF_KEY_OAUTH_SECRET, "");
            // Setup Access Token
            AccessToken accessToken = new AccessToken(twitter_access_token, twitter_access_token_secret);
            // Setup instance of twitter to perform requests e.g. twitter.showUser(<:handle>);
            Twitter twitter = new TwitterFactory(builder.build()).getInstance(accessToken);
            // Define the twitter_handle
            Query query = new Query(params[0]);
            QueryResult result = null;
            try {
                result = twitter.search(query);
            } catch (TwitterException e) {
                e.printStackTrace();
            }

            final ArrayList<String> items = new ArrayList<String>();
            final JSONArray tweets = new JSONArray();
            for (twitter4j.Status status : result.getTweets()) {
                final twitter4j.Status s = status;
                JSONObject t = new JSONObject();
                try {
                    t.put("tweet", s.getText());
                    t.put("src", s.getUser().getBiggerProfileImageURL());
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                tweets.put(t);
                items.add(s.getText());

            }

            final ListView listView = (ListView) findViewById(R.id.list);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    String[] array = items.toArray(new String[items.size()]);
                    //r

                    //TweetAdapter a = new TweetAdapter(ac,tweets);
                    TweetAdapter a = new TweetAdapter(ac, R.layout.list_v, tweets);
                    listView.setAdapter(a);

                }

            });

            // Try and make magic

            return null;
        }
    }

}