com.code.android.vibevault.FeaturedShowsScreen.java Source code

Java tutorial

Introduction

Here is the source code for com.code.android.vibevault.FeaturedShowsScreen.java

Source

/*
 * FeaturedShowsScreen.java
 * VERSION 3.X
 * 
 * Copyright 2011 Andrew Pearson and Sanders DeNardi.
 * 
 * This file is part of Vibe Vault.
 * 
 * Vibe Vault 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 com.code.android.vibevault;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

import org.apache.http.util.ByteArrayBuffer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.View.OnCreateContextMenuListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;

public class FeaturedShowsScreen extends Activity {

    private static final String LOG_TAG = FeaturedShowsScreen.class.getName();

    protected ListView featuredShowsList;
    protected Button getMoreShowsButton;
    private GetSelectedShowsListTask workerTask;
    private boolean dialogShown;

    @Override
    public void onCreate(Bundle savedInstanceState) {

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

        getMoreShowsButton = new Button(this);
        getMoreShowsButton.setText("More Featured Shows");
        getMoreShowsButton.setTextColor(Color.rgb(18, 125, 212));
        getMoreShowsButton.setTypeface(Typeface.DEFAULT, Typeface.BOLD);
        getMoreShowsButton.setPadding(0, 6, 0, 6);

        getMoreShowsButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (VibeVault.moreFeaturedShows.size() != 0) {
                    fetchSelectedShows(VibeVault.moreFeaturedShows.get(0));
                } else {
                    Toast.makeText(getBaseContext(), "More featured shows weekly...", Toast.LENGTH_SHORT).show();
                }
            }
        });

        this.featuredShowsList = (ListView) this.findViewById(R.id.SelectedShowsListView);
        featuredShowsList.addFooterView(getMoreShowsButton);
        if (VibeVault.featuredShows.size() == 0) {
            getMoreShowsButton.setVisibility(View.GONE);
        } else {
            getMoreShowsButton.setVisibility(View.VISIBLE);
        }
        featuredShowsList.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> a, View v, int position, long id) {
                ArchiveShowObj show = (ArchiveShowObj) featuredShowsList.getItemAtPosition(position);
                Intent i = new Intent(FeaturedShowsScreen.this, ShowDetailsScreen.class);
                i.putExtra("Show", show);
                startActivity(i);
            }
        });
        featuredShowsList.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
            @Override
            public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
                menu.add(Menu.NONE, VibeVault.EMAIL_LINK, Menu.NONE, "Email Link to Show");
                menu.add(Menu.NONE, VibeVault.ADD_TO_FAVORITE_LIST, Menu.NONE, "Bookmark Show");
            }
        });

        Object retained = getLastNonConfigurationInstance();
        if (retained instanceof GetSelectedShowsListTask) {

            workerTask = (GetSelectedShowsListTask) retained;
            workerTask.setActivity(this);
        } else {
            workerTask = new GetSelectedShowsListTask(this);
            if (VibeVault.featuredShows.size() == 0) {
                this.fetchSelectedShows("http://andrewpearson.org/vibevault/shows/vvshows1");
            }
            this.refreshSelectedShowsList();
        }
    }

    public void refreshSelectedShowsList() {
        featuredShowsList.setAdapter(new RatingsAdapter(this, R.layout.search_list_row, VibeVault.featuredShows));
        if (VibeVault.featuredShows.size() == 0) {
            getMoreShowsButton.setVisibility(View.GONE);
        } else {
            getMoreShowsButton.setVisibility(View.VISIBLE);
        }
    }

    /** Dialog preparation method.
    *
    * Includes Thread bookkeeping to prevent not leaking Views on orientation changes.
    */
    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        super.onPrepareDialog(id, dialog);
        if (id == VibeVault.RETRIEVING_DIALOG_ID) {
            dialogShown = true;
        }
    }

    /** Dialog creation method.
    *
    * Includes Thread bookkeeping to prevent not leaking Views on orientation changes.
    */
    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
        case VibeVault.RETRIEVING_DIALOG_ID:

            ProgressDialog dialog = new ProgressDialog(this);
            dialog.setMessage("Retrieving Featured Shows...");
            return dialog;
        default:
            return super.onCreateDialog(id);
        }
    }

    /** Bookkeeping method to deal with dialogs over orientation changes.
    *
    */
    private void onTaskCompleted() {
        this.refreshSelectedShowsList();
        if (dialogShown) {
            try {
                dismissDialog(VibeVault.RETRIEVING_DIALOG_ID);
            } catch (IllegalArgumentException e) {

                e.printStackTrace();
            }
            dialogShown = false;

        }
    }

    /** Persist worker Thread across orientation changes.
    *
    * Includes Thread bookkeeping to prevent not leaking Views on orientation changes.
    */
    @Override
    public Object onRetainNonConfigurationInstance() {
        workerTask.setActivity(null);
        return workerTask;
    }

    /** Handle user's long-click selection.
    *
    */
    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
        if (menuInfo != null) {
            ArchiveShowObj selShow = (ArchiveShowObj) featuredShowsList.getAdapter().getItem(menuInfo.position);
            switch (item.getItemId()) {
            case VibeVault.EMAIL_LINK:
                final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
                emailIntent.setType("plain/text");
                emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
                        "Great show on archive.org: " + selShow.getArtistAndTitle());
                emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,
                        "Hey,\n\nYou should listen to " + selShow.getArtistAndTitle() + ".  You can find it here: "
                                + selShow.getShowURL() + "\n\nSent using VibeVault for Android.");
                startActivity(Intent.createChooser(emailIntent, "Send mail..."));
                return true;
            case (VibeVault.ADD_TO_FAVORITE_LIST):
                VibeVault.db.insertFavoriteShow(selShow);
                return true;
            default:
                break;
            }
            return false;
        }
        return true;
    }

    public void fetchSelectedShows(String show) {
        this.workerTask = new GetSelectedShowsListTask(this);
        workerTask.execute(show);
    }

    // ArrayAdapter for the ListView of shows with ratings.
    private class RatingsAdapter extends ArrayAdapter<ArchiveShowObj> {

        public RatingsAdapter(Context context, int textViewResourceId, List<ArchiveShowObj> objects) {
            super(context, textViewResourceId, objects);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ArchiveShowObj show = (ArchiveShowObj) featuredShowsList.getItemAtPosition(position);

            if (convertView == null) {
                LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                convertView = vi.inflate(R.layout.search_list_row, null);
            }
            TextView artistText = (TextView) convertView.findViewById(R.id.ArtistText);
            TextView showText = (TextView) convertView.findViewById(R.id.ShowText);
            ImageView ratingsIcon = (ImageView) convertView.findViewById(R.id.rating);
            if (show != null) {
                artistText.setText(show.getShowArtist());
                artistText.setSelected(true);
                showText.setText(show.getShowTitle());
                showText.setSelected(true);
                switch ((int) show.getRating()) {
                case 1:
                    ratingsIcon.setImageDrawable(getBaseContext().getResources().getDrawable(R.drawable.star1));
                    break;
                case 2:
                    ratingsIcon.setImageDrawable(getBaseContext().getResources().getDrawable(R.drawable.star2));
                    break;
                case 3:
                    ratingsIcon.setImageDrawable(getBaseContext().getResources().getDrawable(R.drawable.star3));
                    break;
                case 4:
                    ratingsIcon.setImageDrawable(getBaseContext().getResources().getDrawable(R.drawable.star4));
                    break;
                case 5:
                    ratingsIcon.setImageDrawable(getBaseContext().getResources().getDrawable(R.drawable.star5));
                    break;
                default:
                    ratingsIcon.setImageDrawable(getBaseContext().getResources().getDrawable(R.drawable.star0));
                    break;
                }
            }
            return convertView;
        }
    }

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

        private FeaturedShowsScreen parentScreen;
        private boolean completed;

        private GetSelectedShowsListTask(FeaturedShowsScreen activity) {
            this.parentScreen = activity;
        }

        @Override
        protected void onPreExecute() {
            parentScreen.showDialog(VibeVault.RETRIEVING_DIALOG_ID);
        }

        @Override
        protected Void doInBackground(String... listAddress) {

            URL listURL = null;
            String listString = null;

            if (listAddress[0] == null) {
                return null;
            }

            try {
                listURL = new URL(listAddress[0]);
            } catch (MalformedURLException e) {

                return null;
            }
            try {
                URLConnection listConnection;
                listConnection = listURL.openConnection();
                if (listConnection == null) {

                    return null;
                }
                InputStream inStream = listConnection.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(inStream);
                ByteArrayBuffer baf = new ByteArrayBuffer(50);
                int read = 0;
                int bufSize = 512;
                byte[] buffer = new byte[bufSize];
                while (bis.available() == 0) {
                    bis.close();
                    inStream.close();
                    listConnection = listURL.openConnection();
                    inStream = listConnection.getInputStream();
                    bis = new BufferedInputStream(inStream);
                }
                while (true) {
                    read = bis.read(buffer);
                    if (read == -1) {
                        break;
                    }
                    baf.append(buffer, 0, read);
                }
                listString = new String(baf.toByteArray());
                bis.close();
                inStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            if (listString == null) {
                return null;
            }

            JSONObject jObject;
            boolean firstFetch = false;
            try {
                // Root JSON object.
                jObject = new JSONObject(listString);
                jObject = jObject.getJSONObject("response");
                // If there are no featured songs already in the ListView or no featured shows
                // in the Selected Shows list, get the list of other featured shows.
                if (VibeVault.moreFeaturedShows.size() == 0 && VibeVault.featuredShows.size() == 0) {
                    JSONArray showsArray = jObject.getJSONArray("otherLinks");
                    int numShows = showsArray.length();
                    for (int i = 0; i < numShows; i++) {
                        VibeVault.moreFeaturedShows.add((String) showsArray.getString(i));
                    }
                    firstFetch = true;
                }
                // Get the featured shows.
                JSONArray docsArray = jObject.getJSONArray("selectedShows");
                int numItems = docsArray.length();
                for (int i = 0; i < numItems; i++) {
                    JSONObject songObject = docsArray.getJSONObject(i);
                    VibeVault.featuredShows.add(VibeVault.featuredShows.size(),
                            new ArchiveShowObj(songObject.optString("title"), songObject.optString("identifier"),
                                    songObject.optString("date"), songObject.optDouble("avg_rating"),
                                    songObject.optString("format"), songObject.optString("source")));
                }
                // If this isn't the first time you are fetching the information, it is coming from
                // the list of more featured shows, so you need to pop the top show because you just got it.
                if (!firstFetch) {
                    VibeVault.moreFeaturedShows.remove(0);
                }
            } catch (JSONException e) {
                Log.e(LOG_TAG, "JSON error: " + listString);
                Log.e(LOG_TAG, e.toString());
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void v) {
            refreshSelectedShowsList();
            completed = true;
            notifyActivityTaskCompleted();
        }

        // The parent could be null if you changed orientations
        // and this method was called before the new SearchScreen
        // could set itself as this Thread's parent.
        private void notifyActivityTaskCompleted() {
            if (parentScreen != null) {
                parentScreen.onTaskCompleted();
            }
        }

        // When a SearchScreen is reconstructed (like after an orientation change),
        // we call this method on the retained SearchScreen (if one exists) to set
        // its parent Activity as the new SearchScreen because the old one has been destroyed.
        // This prevents leaking any of the data associated with the old SearchScreen.
        private void setActivity(FeaturedShowsScreen activity) {
            this.parentScreen = activity;
            if (completed) {
                notifyActivityTaskCompleted();
            }
        }

    }

}