Home | History | Annotate | Download | only in browser
      1 /*
      2  * Copyright (C) 2014 Google Inc. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.example.android.musicservicedemo.browser;
     18 
     19 import android.database.MatrixCursor;
     20 import android.media.session.PlaybackState;
     21 import android.net.Uri;
     22 import android.util.Log;
     23 
     24 import com.example.android.musicservicedemo.BrowserService;
     25 
     26 import org.json.JSONArray;
     27 import org.json.JSONException;
     28 import org.json.JSONObject;
     29 
     30 import java.io.BufferedInputStream;
     31 import java.io.BufferedReader;
     32 import java.io.IOException;
     33 import java.io.InputStream;
     34 import java.io.InputStreamReader;
     35 import java.net.URLConnection;
     36 import java.util.ArrayList;
     37 import java.util.List;
     38 
     39 /**
     40  * Utility class to get a list of MusicTrack's based on a server-side JSON
     41  * configuration.
     42  */
     43 public class MusicProvider {
     44 
     45     private static final String TAG = "MusicProvider";
     46 
     47     private static final String MUSIC_URL = "http://storage.googleapis.com/automotive-media/music.json";
     48 
     49     private static String MUSIC = "music";
     50     private static String TITLE = "title";
     51     private static String ALBUM = "album";
     52     private static String ARTIST = "artist";
     53     private static String GENRE = "genre";
     54     private static String SOURCE = "source";
     55     private static String IMAGE = "image";
     56     private static String TRACK_NUMBER = "trackNumber";
     57     private static String TOTAL_TRACK_COUNT = "totalTrackCount";
     58     private static String DURATION = "duration";
     59 
     60     // Cache for music track data
     61     private static List<MusicTrack> mMusicList;
     62 
     63     /**
     64      * Get the cached list of music tracks
     65      *
     66      * @return
     67      * @throws JSONException
     68      */
     69     public List<MusicTrack> getMedia() throws JSONException {
     70         if (null != mMusicList && mMusicList.size() > 0) {
     71             return mMusicList;
     72         }
     73         return null;
     74     }
     75 
     76     /**
     77      * Get the list of music tracks from a server and return the list of
     78      * MusicTrack objects.
     79      *
     80      * @return
     81      * @throws JSONException
     82      */
     83     public List<MusicTrack> retreiveMedia() throws JSONException {
     84         if (null != mMusicList) {
     85             return mMusicList;
     86         }
     87         int slashPos = MUSIC_URL.lastIndexOf('/');
     88         String path = MUSIC_URL.substring(0, slashPos + 1);
     89         JSONObject jsonObj = parseUrl(MUSIC_URL);
     90 
     91         try {
     92             JSONArray videos = jsonObj.getJSONArray(MUSIC);
     93             if (null != videos) {
     94                 mMusicList = new ArrayList<MusicTrack>();
     95                 for (int j = 0; j < videos.length(); j++) {
     96                     JSONObject music = videos.getJSONObject(j);
     97                     String title = music.getString(TITLE);
     98                     String album = music.getString(ALBUM);
     99                     String artist = music.getString(ARTIST);
    100                     String genre = music.getString(GENRE);
    101                     String source = music.getString(SOURCE);
    102                     // Media is stored relative to JSON file
    103                     if (!source.startsWith("http")) {
    104                         source = path + source;
    105                     }
    106                     String image = music.getString(IMAGE);
    107                     if (!image.startsWith("http")) {
    108                         image = path + image;
    109                     }
    110                     int trackNumber = music.getInt(TRACK_NUMBER);
    111                     int totalTrackCount = music.getInt(TOTAL_TRACK_COUNT);
    112                     int duration = music.getInt(DURATION) * 1000; // ms
    113 
    114                     mMusicList.add(new MusicTrack(title, album, artist, genre, source,
    115                             image, trackNumber, totalTrackCount, duration));
    116                 }
    117             }
    118         } catch (NullPointerException e) {
    119             Log.e(TAG, "retreiveMedia", e);
    120         }
    121         return mMusicList;
    122     }
    123 
    124     /**
    125      * Download a JSON file from a server, parse the content and return the JSON
    126      * object.
    127      *
    128      * @param urlString
    129      * @return
    130      */
    131     private JSONObject parseUrl(String urlString) {
    132         InputStream is = null;
    133         try {
    134             java.net.URL url = new java.net.URL(urlString);
    135             URLConnection urlConnection = url.openConnection();
    136             is = new BufferedInputStream(urlConnection.getInputStream());
    137             BufferedReader reader = new BufferedReader(new InputStreamReader(
    138                     urlConnection.getInputStream(), "iso-8859-1"), 8);
    139             StringBuilder sb = new StringBuilder();
    140             String line = null;
    141             while ((line = reader.readLine()) != null) {
    142                 sb.append(line);
    143             }
    144             return new JSONObject(sb.toString());
    145         } catch (Exception e) {
    146             Log.d(TAG, "Failed to parse the json for media list", e);
    147             return null;
    148         } finally {
    149             if (null != is) {
    150                 try {
    151                     is.close();
    152                 } catch (IOException e) {
    153                     // ignore
    154                 }
    155             }
    156         }
    157     }
    158 
    159     public MatrixCursor getRootContainerCurser() {
    160         MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
    161         Uri.Builder pianoBuilder = new Uri.Builder();
    162         pianoBuilder.authority(BrowserService.AUTHORITY);
    163         pianoBuilder.appendPath(BrowserService.PIANO_BASE_PATH);
    164         matrixCursor.addRow(new Object[] {
    165                 pianoBuilder.build(),
    166                 BrowserService.PIANO_BASE_PATH,
    167                 "subtitle",
    168                 null,
    169                 0
    170         });
    171 
    172         Uri.Builder voiceBuilder = new Uri.Builder();
    173         voiceBuilder.authority(BrowserService.AUTHORITY);
    174         voiceBuilder.appendPath(BrowserService.VOICE_BASE_PATH);
    175         matrixCursor.addRow(new Object[] {
    176                 voiceBuilder.build(),
    177                 BrowserService.VOICE_BASE_PATH,
    178                 "subtitle",
    179                 null,
    180                 0
    181         });
    182         return matrixCursor;
    183     }
    184 
    185     public MatrixCursor getRootItemCursor(int type) {
    186         if (type == BrowserService.NOW_PLAYING) {
    187             MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
    188 
    189             try {
    190                 // Just return all of the tracks for now
    191                 List<MusicTrack> musicTracks = retreiveMedia();
    192                 for (MusicTrack musicTrack : musicTracks) {
    193                     Uri.Builder builder = new Uri.Builder();
    194                     builder.authority(BrowserService.AUTHORITY);
    195                     builder.appendPath(BrowserService.NOW_PLAYING_PATH);
    196                     builder.appendPath(musicTrack.getTitle());
    197                     matrixCursor.addRow(new Object[] {
    198                             builder.build(),
    199                             musicTrack.getTitle(),
    200                             musicTrack.getArtist(),
    201                             musicTrack.getImage(),
    202                             PlaybackState.ACTION_PLAY
    203                     });
    204                     Log.d(TAG, "Uri " + builder.build());
    205                 }
    206             } catch (JSONException e) {
    207                 Log.e(TAG, "::getRootItemCursor:", e);
    208             }
    209 
    210             Log.d(TAG, "cursor: " + matrixCursor.getCount());
    211             return matrixCursor;
    212         } else if (type == BrowserService.PIANO) {
    213             MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
    214 
    215             try {
    216                 List<MusicTrack> musicTracks = retreiveMedia();
    217                 for (MusicTrack musicTrack : musicTracks) {
    218                     Uri.Builder builder = new Uri.Builder();
    219                     builder.authority(BrowserService.AUTHORITY);
    220                     builder.appendPath(BrowserService.PIANO_BASE_PATH);
    221                     builder.appendPath(musicTrack.getTitle());
    222                     matrixCursor.addRow(new Object[] {
    223                             builder.build(),
    224                             musicTrack.getTitle(),
    225                             musicTrack.getArtist(),
    226                             musicTrack.getImage(),
    227                             PlaybackState.ACTION_PLAY
    228                     });
    229                     Log.d(TAG, "Uri " + builder.build());
    230                 }
    231             } catch (JSONException e) {
    232                 Log.e(TAG, "::getRootItemCursor:", e);
    233             }
    234 
    235             Log.d(TAG, "cursor: " + matrixCursor.getCount());
    236             return matrixCursor;
    237         } else if (type == BrowserService.VOICE) {
    238             MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
    239 
    240             try {
    241                 List<MusicTrack> musicTracks = retreiveMedia();
    242                 for (MusicTrack musicTrack : musicTracks) {
    243                     Uri.Builder builder = new Uri.Builder();
    244                     builder.authority(BrowserService.AUTHORITY);
    245                     builder.appendPath(BrowserService.VOICE_BASE_PATH);
    246                     builder.appendPath(musicTrack.getTitle());
    247                     matrixCursor.addRow(new Object[] {
    248                             builder.build(),
    249                             musicTrack.getTitle(),
    250                             musicTrack.getArtist(),
    251                             musicTrack.getImage(),
    252                             PlaybackState.ACTION_PLAY
    253                     });
    254                     Log.d(TAG, "Uri " + builder.build());
    255                 }
    256             } catch (JSONException e) {
    257                 Log.e(TAG, "::getRootItemCursor:", e);
    258             }
    259 
    260             Log.d(TAG, "cursor: " + matrixCursor.getCount());
    261             return matrixCursor;
    262 
    263         }
    264         return null;
    265     }
    266 }
    267