summaryrefslogtreecommitdiffstats
path: root/tests/MusicServiceDemo
diff options
context:
space:
mode:
authorYao Chen <yaochen@google.com>2014-07-17 14:39:34 -0700
committerYao Chen <yaochen@google.com>2014-07-21 21:14:43 -0700
commit17d47989ee53c9e54f250d29a343ba949edf0ff9 (patch)
tree666e0297c2c5ec1f740dade8738c7cdeb5ee12fb /tests/MusicServiceDemo
parent66e207ec54e2085c0eb70d5189562effafa2c9c5 (diff)
downloadframeworks_base-17d47989ee53c9e54f250d29a343ba949edf0ff9.zip
frameworks_base-17d47989ee53c9e54f250d29a343ba949edf0ff9.tar.gz
frameworks_base-17d47989ee53c9e54f250d29a343ba949edf0ff9.tar.bz2
Updated media browsing API & tests.
Change-Id: I3a1e3eead99a98b1890e05843dd90203cee517b7
Diffstat (limited to 'tests/MusicServiceDemo')
-rw-r--r--tests/MusicServiceDemo/Android.mk35
-rw-r--r--tests/MusicServiceDemo/AndroidManifest.xml55
-rw-r--r--tests/MusicServiceDemo/proguard-project.txt20
-rw-r--r--tests/MusicServiceDemo/res/drawable-hdpi/ic_launcher.pngbin0 -> 4805 bytes
-rw-r--r--tests/MusicServiceDemo/res/drawable-mdpi/ic_launcher.pngbin0 -> 2592 bytes
-rw-r--r--tests/MusicServiceDemo/res/drawable-xhdpi/ic_launcher.pngbin0 -> 5246 bytes
-rw-r--r--tests/MusicServiceDemo/res/drawable-xxhdpi/ic_launcher.pngbin0 -> 14755 bytes
-rw-r--r--tests/MusicServiceDemo/res/drawable-xxhdpi/thumbsup.pngbin0 -> 1632 bytes
-rw-r--r--tests/MusicServiceDemo/res/layout/activity_main.xml23
-rw-r--r--tests/MusicServiceDemo/res/layout/fragment_main.xml32
-rw-r--r--tests/MusicServiceDemo/res/values/colors.xml22
-rw-r--r--tests/MusicServiceDemo/res/values/dimens.xml23
-rw-r--r--tests/MusicServiceDemo/res/values/strings.xml25
-rw-r--r--tests/MusicServiceDemo/res/values/styles.xml36
-rw-r--r--tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java246
-rw-r--r--tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java101
-rw-r--r--tests/MusicServiceDemo/src/com/example/android/musicservicedemo/Utils.java77
-rw-r--r--tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProvider.java266
-rw-r--r--tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTask.java70
-rw-r--r--tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTaskListener.java24
-rw-r--r--tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicTrack.java138
21 files changed, 1193 insertions, 0 deletions
diff --git a/tests/MusicServiceDemo/Android.mk b/tests/MusicServiceDemo/Android.mk
new file mode 100644
index 0000000..feef67a
--- /dev/null
+++ b/tests/MusicServiceDemo/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := MusicServiceDemo
+#LOCAL_SDK_VERSION := current
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-v4 \
+ android-support-v7-appcompat
+
+LOCAL_RESOURCE_DIR := \
+ $(LOCAL_PATH)/res \
+ frameworks/support/v7/appcompat/res
+LOCAL_PROGUARD_ENABLED := disabled
+#LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+
+LOCAL_AAPT_FLAGS := \
+ --auto-add-overlay \
+ --extra-packages android.support.v7.appcompat
+include $(BUILD_PACKAGE)
diff --git a/tests/MusicServiceDemo/AndroidManifest.xml b/tests/MusicServiceDemo/AndroidManifest.xml
new file mode 100644
index 0000000..4178a80
--- /dev/null
+++ b/tests/MusicServiceDemo/AndroidManifest.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.musicservicedemo"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+
+ <uses-sdk
+ android:minSdkVersion="9"
+ android:targetSdkVersion="19" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme"
+ >
+
+ <activity
+ android:name="com.example.android.automotive.musicplayer.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <service
+ android:name=".BrowserService"
+ android:exported="true"
+ >
+ <intent-filter>
+ <action android:name="android.media.browse.MediaBrowseService" />
+ </intent-filter>
+ </service>
+ </application>
+
+</manifest>
diff --git a/tests/MusicServiceDemo/proguard-project.txt b/tests/MusicServiceDemo/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/tests/MusicServiceDemo/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/tests/MusicServiceDemo/res/drawable-hdpi/ic_launcher.png b/tests/MusicServiceDemo/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..47d6854
--- /dev/null
+++ b/tests/MusicServiceDemo/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicServiceDemo/res/drawable-mdpi/ic_launcher.png b/tests/MusicServiceDemo/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..01b53fd
--- /dev/null
+++ b/tests/MusicServiceDemo/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicServiceDemo/res/drawable-xhdpi/ic_launcher.png b/tests/MusicServiceDemo/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..af762f2
--- /dev/null
+++ b/tests/MusicServiceDemo/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicServiceDemo/res/drawable-xxhdpi/ic_launcher.png b/tests/MusicServiceDemo/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..eef47aa
--- /dev/null
+++ b/tests/MusicServiceDemo/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/tests/MusicServiceDemo/res/drawable-xxhdpi/thumbsup.png b/tests/MusicServiceDemo/res/drawable-xxhdpi/thumbsup.png
new file mode 100644
index 0000000..ea98c95
--- /dev/null
+++ b/tests/MusicServiceDemo/res/drawable-xxhdpi/thumbsup.png
Binary files differ
diff --git a/tests/MusicServiceDemo/res/layout/activity_main.xml b/tests/MusicServiceDemo/res/layout/activity_main.xml
new file mode 100644
index 0000000..71753e3
--- /dev/null
+++ b/tests/MusicServiceDemo/res/layout/activity_main.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="com.example.android.automotive.musicplayer.MainActivity"
+ tools:ignore="MergeRootFrame" />
diff --git a/tests/MusicServiceDemo/res/layout/fragment_main.xml b/tests/MusicServiceDemo/res/layout/fragment_main.xml
new file mode 100644
index 0000000..8796e86
--- /dev/null
+++ b/tests/MusicServiceDemo/res/layout/fragment_main.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="com.example.android.automotive.musicplayer.MainActivity$PlaceholderFragment" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/app_name" />
+
+</RelativeLayout>
diff --git a/tests/MusicServiceDemo/res/values/colors.xml b/tests/MusicServiceDemo/res/values/colors.xml
new file mode 100644
index 0000000..44dd05d
--- /dev/null
+++ b/tests/MusicServiceDemo/res/values/colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <color name="yellow">#ffffff00</color>
+ <color name="green">#ff00ff00</color>
+ <color name="blue">#ff0000ff</color>
+ <color name="red">#ffff0000</color>
+</resources>
diff --git a/tests/MusicServiceDemo/res/values/dimens.xml b/tests/MusicServiceDemo/res/values/dimens.xml
new file mode 100644
index 0000000..9f63ef2
--- /dev/null
+++ b/tests/MusicServiceDemo/res/values/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
diff --git a/tests/MusicServiceDemo/res/values/strings.xml b/tests/MusicServiceDemo/res/values/strings.xml
new file mode 100644
index 0000000..14c0171
--- /dev/null
+++ b/tests/MusicServiceDemo/res/values/strings.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+
+ <string name="app_name">Music Service Demo</string>
+ <string name="action_settings">Settings</string>
+ <string name="thumbs_up">Thumbs Up</string>
+ <string name="music_error">No music found</string>
+ <string name="now_playing">Now Playing</string>
+
+</resources>
diff --git a/tests/MusicServiceDemo/res/values/styles.xml b/tests/MusicServiceDemo/res/values/styles.xml
new file mode 100644
index 0000000..b83662d
--- /dev/null
+++ b/tests/MusicServiceDemo/res/values/styles.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="Theme.AppCompat.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
new file mode 100644
index 0000000..9ca156f
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/BrowserService.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.musicservicedemo;
+
+import android.app.SearchManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.UriMatcher;
+import android.content.res.Resources.NotFoundException;
+import android.database.MatrixCursor;
+import android.graphics.Bitmap;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.MediaPlayer.OnPreparedListener;
+import android.media.browse.MediaBrowserItem;
+import android.media.browse.MediaBrowserService;
+import android.media.session.MediaSession;
+import android.net.Uri;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.WifiLock;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.example.android.musicservicedemo.browser.MusicProvider;
+import com.example.android.musicservicedemo.browser.MusicProviderTask;
+import com.example.android.musicservicedemo.browser.MusicProviderTaskListener;
+import com.example.android.musicservicedemo.browser.MusicTrack;
+
+import org.json.JSONException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Service that implements MediaBrowserService and returns our menu hierarchy.
+ */
+public class BrowserService extends MediaBrowserService {
+ private static final String TAG = "BrowserService";
+
+ // URI paths for browsing music
+ public static final String BROWSE_ROOT_BASE_PATH = "browse";
+ public static final String NOW_PLAYING_PATH = "now_playing";
+ public static final String PIANO_BASE_PATH = "piano";
+ public static final String VOICE_BASE_PATH = "voice";
+
+ // Content URIs
+ public static final String AUTHORITY = "com.example.android.automotive.musicplayer";
+ public static final Uri BASE_URI = Uri.parse("content://" + AUTHORITY);
+ public static final Uri BROWSE_URI = Uri.withAppendedPath(BASE_URI, BROWSE_ROOT_BASE_PATH);
+
+ // URI matcher constants for browsing paths
+ public static final int BROWSE_ROOT = 1;
+ public static final int NOW_PLAYING = 2;
+ public static final int PIANO = 3;
+ public static final int VOICE = 4;
+
+ // Map the the URI paths with the URI matcher constants
+ private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ static {
+ sUriMatcher.addURI(AUTHORITY, BROWSE_ROOT_BASE_PATH, BROWSE_ROOT);
+ sUriMatcher.addURI(AUTHORITY, NOW_PLAYING_PATH, NOW_PLAYING);
+ sUriMatcher.addURI(AUTHORITY, PIANO_BASE_PATH, PIANO);
+ sUriMatcher.addURI(AUTHORITY, VOICE_BASE_PATH, VOICE);
+ }
+
+ // Media metadata that will be provided for a media container
+ public static final String[] MEDIA_CONTAINER_PROJECTION = {
+ "uri",
+ "title",
+ "subtitle",
+ "image_uri",
+ "supported_actions"
+ };
+
+ // MusicProvider will download the music catalog
+ private MusicProvider mMusicProvider;
+
+ private MediaSession mSession;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ mSession = new MediaSession(this, "com.example.android.musicservicedemo.BrowserService");
+ setSessionToken(mSession.getSessionToken());
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+ @Override
+ public Uri onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
+ return BROWSE_URI;
+ }
+
+ @Override
+ public List<MediaBrowserItem> onLoadChildren(Uri parentUri) {
+ final ArrayList<MediaBrowserItem> results = new ArrayList();
+
+ for (int i=0; i<10; i++) {
+ results.add(new MediaBrowserItem.Builder(Uri.withAppendedPath(BASE_URI, Integer.toString(i)),
+ MediaBrowserItem.FLAG_BROWSABLE, "Title " + i).setSummary("Summary " + i).build());
+ }
+
+ return results;
+ }
+
+ @Override
+ public Bitmap onGetThumbnail(Uri uri, int width, int height, int density) {
+ return null;
+ }
+
+ /*
+ @Override
+ public void query(final Query query, final IMetadataResultHandler metadataResultHandler,
+ final IErrorHandler errorHandler)
+ throws RemoteException {
+ Log.d(TAG, "query: " + query);
+ Utils.checkNotNull(query);
+ Utils.checkNotNull(metadataResultHandler);
+ Utils.checkNotNull(errorHandler);
+
+ // Handle async response
+ new Thread(new Runnable() {
+ public void run() {
+ try {
+ // Pre-load the list of music
+ List<MusicTrack> musicTracks = getMusicList();
+ if (musicTracks == null) {
+ notifyListenersOnPlaybackStateUpdate(getCurrentPlaybackState());
+ errorHandler.onError(new Error(Error.UNKNOWN,
+ getString(R.string.music_error)));
+ return;
+ }
+
+ final Uri uri = query.getUri();
+ int match = sUriMatcher.match(uri);
+ Log.d(TAG, "Queried: " + uri + "; match: " + match);
+ switch (match) {
+ case BROWSE_ROOT:
+ {
+ Log.d(TAG, "Browse_root");
+
+ try {
+ MatrixCursor matrixCursor = mMusicProvider
+ .getRootContainerCurser();
+ DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
+ matrixCursor, null);
+
+ Log.d(TAG, "on metadata response called " + holder.getCount());
+ metadataResultHandler.onMetadataResponse(holder);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error delivering metadata in the callback.", e);
+ }
+ break;
+ }
+ case NOW_PLAYING:
+ {
+ try {
+ Log.d(TAG, "query NOW_PLAYING");
+ MatrixCursor matrixCursor = mMusicProvider
+ .getRootItemCursor(
+ PIANO);
+ DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
+ matrixCursor, null);
+ Log.d(TAG, "on metadata response called " + holder.getCount());
+ metadataResultHandler.onMetadataResponse(holder);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error querying NOW_PLAYING");
+ }
+ break;
+ }
+ case PIANO:
+ {
+ try {
+ Log.d(TAG, "query PIANO");
+ MatrixCursor matrixCursor = mMusicProvider
+ .getRootItemCursor(
+ PIANO);
+ DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
+ matrixCursor, null);
+ Log.d(TAG, "on metadata response called " + holder.getCount());
+ metadataResultHandler.onMetadataResponse(holder);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error querying PIANO");
+ }
+ break;
+ }
+ case VOICE:
+ {
+ try {
+ Log.d(TAG, "query VOICE");
+ MatrixCursor matrixCursor = mMusicProvider
+ .getRootItemCursor(
+ VOICE);
+ DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
+ matrixCursor, null);
+ Log.d(TAG, "on metadata response called " + holder.getCount());
+ metadataResultHandler.onMetadataResponse(holder);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error querying VOICE");
+ }
+ break;
+ }
+ default:
+ {
+ Log.w(TAG, "Skipping unmatched URI: " + uri);
+ }
+ }
+ } catch (NotFoundException e) {
+ Log.e(TAG, "::run:", e);
+ } catch (RemoteException e) {
+ Log.e(TAG, "::run:", e);
+ }
+ } // end run
+ }).start();
+ }
+
+ */
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
new file mode 100644
index 0000000..db45b9d
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
@@ -0,0 +1,101 @@
+/* Copyright 2014 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.musicservicedemo;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v7.app.ActionBarActivity;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.example.android.musicservicedemo.R;
+
+// TODO Local UI
+
+/**
+ * Main activity of the app.
+ */
+public class MainActivity extends ActionBarActivity {
+
+ private static final String LOG = "MainActivity";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ if (savedInstanceState == null) {
+ getSupportFragmentManager().beginTransaction()
+ .add(R.id.container, new PlaceholderFragment())
+ .commit();
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+
+ // Inflate the menu; this adds items to the action bar if it is present.
+ //getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ // if (id == R.id.action_settings) {
+ // return true;
+ // }
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * A placeholder fragment containing a simple view.
+ */
+ public static class PlaceholderFragment extends Fragment {
+
+ public PlaceholderFragment() {
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see
+ * android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater
+ * , android.view.ViewGroup, android.os.Bundle)
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_main, container, false);
+ return rootView;
+ }
+ }
+
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/Utils.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/Utils.java
new file mode 100644
index 0000000..3589761
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/Utils.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.musicservicedemo;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+public class Utils {
+
+ private static final String TAG = "Utils";
+
+ /**
+ * Utility method to check that parameters are not null
+ *
+ * @param object
+ */
+ public static final void checkNotNull(Object object) {
+ if (object == null) {
+ throw new NullPointerException();
+ }
+ }
+
+ /**
+ * Utility to download a bitmap
+ *
+ * @param source
+ * @return
+ */
+ public static Bitmap getBitmapFromURL(String source) {
+ try {
+ URL url = new URL(source);
+ HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
+ httpConnection.setDoInput(true);
+ httpConnection.connect();
+ InputStream inputStream = httpConnection.getInputStream();
+ return BitmapFactory.decodeStream(inputStream);
+ } catch (IOException e) {
+ Log.e(TAG, "getBitmapFromUrl: " + source, e);
+ }
+ return null;
+ }
+
+ /**
+ * Utility method to wrap an index
+ *
+ * @param i
+ * @param size
+ * @return
+ */
+ public static int wrapIndex(int i, int size) {
+ int m = i % size;
+ if (m < 0) { // java modulus can be negative
+ m += size;
+ }
+ return m;
+ }
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProvider.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProvider.java
new file mode 100644
index 0000000..15038d7
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProvider.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.musicservicedemo.browser;
+
+import android.database.MatrixCursor;
+import android.media.session.PlaybackState;
+import android.net.Uri;
+import android.util.Log;
+
+import com.example.android.musicservicedemo.BrowserService;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Utility class to get a list of MusicTrack's based on a server-side JSON
+ * configuration.
+ */
+public class MusicProvider {
+
+ private static final String TAG = "MusicProvider";
+
+ private static final String MUSIC_URL = "http://storage.googleapis.com/automotive-media/music.json";
+
+ private static String MUSIC = "music";
+ private static String TITLE = "title";
+ private static String ALBUM = "album";
+ private static String ARTIST = "artist";
+ private static String GENRE = "genre";
+ private static String SOURCE = "source";
+ private static String IMAGE = "image";
+ private static String TRACK_NUMBER = "trackNumber";
+ private static String TOTAL_TRACK_COUNT = "totalTrackCount";
+ private static String DURATION = "duration";
+
+ // Cache for music track data
+ private static List<MusicTrack> mMusicList;
+
+ /**
+ * Get the cached list of music tracks
+ *
+ * @return
+ * @throws JSONException
+ */
+ public List<MusicTrack> getMedia() throws JSONException {
+ if (null != mMusicList && mMusicList.size() > 0) {
+ return mMusicList;
+ }
+ return null;
+ }
+
+ /**
+ * Get the list of music tracks from a server and return the list of
+ * MusicTrack objects.
+ *
+ * @return
+ * @throws JSONException
+ */
+ public List<MusicTrack> retreiveMedia() throws JSONException {
+ if (null != mMusicList) {
+ return mMusicList;
+ }
+ int slashPos = MUSIC_URL.lastIndexOf('/');
+ String path = MUSIC_URL.substring(0, slashPos + 1);
+ JSONObject jsonObj = parseUrl(MUSIC_URL);
+
+ try {
+ JSONArray videos = jsonObj.getJSONArray(MUSIC);
+ if (null != videos) {
+ mMusicList = new ArrayList<MusicTrack>();
+ for (int j = 0; j < videos.length(); j++) {
+ JSONObject music = videos.getJSONObject(j);
+ String title = music.getString(TITLE);
+ String album = music.getString(ALBUM);
+ String artist = music.getString(ARTIST);
+ String genre = music.getString(GENRE);
+ String source = music.getString(SOURCE);
+ // Media is stored relative to JSON file
+ if (!source.startsWith("http")) {
+ source = path + source;
+ }
+ String image = music.getString(IMAGE);
+ if (!image.startsWith("http")) {
+ image = path + image;
+ }
+ int trackNumber = music.getInt(TRACK_NUMBER);
+ int totalTrackCount = music.getInt(TOTAL_TRACK_COUNT);
+ int duration = music.getInt(DURATION) * 1000; // ms
+
+ mMusicList.add(new MusicTrack(title, album, artist, genre, source,
+ image, trackNumber, totalTrackCount, duration));
+ }
+ }
+ } catch (NullPointerException e) {
+ Log.e(TAG, "retreiveMedia", e);
+ }
+ return mMusicList;
+ }
+
+ /**
+ * Download a JSON file from a server, parse the content and return the JSON
+ * object.
+ *
+ * @param urlString
+ * @return
+ */
+ private JSONObject parseUrl(String urlString) {
+ InputStream is = null;
+ try {
+ java.net.URL url = new java.net.URL(urlString);
+ URLConnection urlConnection = url.openConnection();
+ is = new BufferedInputStream(urlConnection.getInputStream());
+ BufferedReader reader = new BufferedReader(new InputStreamReader(
+ urlConnection.getInputStream(), "iso-8859-1"), 8);
+ StringBuilder sb = new StringBuilder();
+ String line = null;
+ while ((line = reader.readLine()) != null) {
+ sb.append(line);
+ }
+ return new JSONObject(sb.toString());
+ } catch (Exception e) {
+ Log.d(TAG, "Failed to parse the json for media list", e);
+ return null;
+ } finally {
+ if (null != is) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ }
+
+ public MatrixCursor getRootContainerCurser() {
+ MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
+ Uri.Builder pianoBuilder = new Uri.Builder();
+ pianoBuilder.authority(BrowserService.AUTHORITY);
+ pianoBuilder.appendPath(BrowserService.PIANO_BASE_PATH);
+ matrixCursor.addRow(new Object[] {
+ pianoBuilder.build(),
+ BrowserService.PIANO_BASE_PATH,
+ "subtitle",
+ null,
+ 0
+ });
+
+ Uri.Builder voiceBuilder = new Uri.Builder();
+ voiceBuilder.authority(BrowserService.AUTHORITY);
+ voiceBuilder.appendPath(BrowserService.VOICE_BASE_PATH);
+ matrixCursor.addRow(new Object[] {
+ voiceBuilder.build(),
+ BrowserService.VOICE_BASE_PATH,
+ "subtitle",
+ null,
+ 0
+ });
+ return matrixCursor;
+ }
+
+ public MatrixCursor getRootItemCursor(int type) {
+ if (type == BrowserService.NOW_PLAYING) {
+ MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
+
+ try {
+ // Just return all of the tracks for now
+ List<MusicTrack> musicTracks = retreiveMedia();
+ for (MusicTrack musicTrack : musicTracks) {
+ Uri.Builder builder = new Uri.Builder();
+ builder.authority(BrowserService.AUTHORITY);
+ builder.appendPath(BrowserService.NOW_PLAYING_PATH);
+ builder.appendPath(musicTrack.getTitle());
+ matrixCursor.addRow(new Object[] {
+ builder.build(),
+ musicTrack.getTitle(),
+ musicTrack.getArtist(),
+ musicTrack.getImage(),
+ PlaybackState.ACTION_PLAY
+ });
+ Log.d(TAG, "Uri " + builder.build());
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "::getRootItemCursor:", e);
+ }
+
+ Log.d(TAG, "cursor: " + matrixCursor.getCount());
+ return matrixCursor;
+ } else if (type == BrowserService.PIANO) {
+ MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
+
+ try {
+ List<MusicTrack> musicTracks = retreiveMedia();
+ for (MusicTrack musicTrack : musicTracks) {
+ Uri.Builder builder = new Uri.Builder();
+ builder.authority(BrowserService.AUTHORITY);
+ builder.appendPath(BrowserService.PIANO_BASE_PATH);
+ builder.appendPath(musicTrack.getTitle());
+ matrixCursor.addRow(new Object[] {
+ builder.build(),
+ musicTrack.getTitle(),
+ musicTrack.getArtist(),
+ musicTrack.getImage(),
+ PlaybackState.ACTION_PLAY
+ });
+ Log.d(TAG, "Uri " + builder.build());
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "::getRootItemCursor:", e);
+ }
+
+ Log.d(TAG, "cursor: " + matrixCursor.getCount());
+ return matrixCursor;
+ } else if (type == BrowserService.VOICE) {
+ MatrixCursor matrixCursor = new MatrixCursor(BrowserService.MEDIA_CONTAINER_PROJECTION);
+
+ try {
+ List<MusicTrack> musicTracks = retreiveMedia();
+ for (MusicTrack musicTrack : musicTracks) {
+ Uri.Builder builder = new Uri.Builder();
+ builder.authority(BrowserService.AUTHORITY);
+ builder.appendPath(BrowserService.VOICE_BASE_PATH);
+ builder.appendPath(musicTrack.getTitle());
+ matrixCursor.addRow(new Object[] {
+ builder.build(),
+ musicTrack.getTitle(),
+ musicTrack.getArtist(),
+ musicTrack.getImage(),
+ PlaybackState.ACTION_PLAY
+ });
+ Log.d(TAG, "Uri " + builder.build());
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "::getRootItemCursor:", e);
+ }
+
+ Log.d(TAG, "cursor: " + matrixCursor.getCount());
+ return matrixCursor;
+
+ }
+ return null;
+ }
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTask.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTask.java
new file mode 100644
index 0000000..ffda110
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTask.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.musicservicedemo.browser;
+
+import android.os.AsyncTask;
+import android.util.Log;
+
+import org.json.JSONException;
+
+/**
+ * Asynchronous task to retrieve the music data using MusicProvider.
+ */
+public class MusicProviderTask extends AsyncTask<Void, Void, Void> {
+
+ private static final String TAG = "MusicProviderTask";
+
+ MusicProvider mMusicProvider;
+ MusicProviderTaskListener mMusicProviderTaskListener;
+
+ /**
+ * Initialize the task with the provider to download the music data and the
+ * listener to be informed when the task is done.
+ *
+ * @param musicProvider
+ * @param listener
+ */
+ public MusicProviderTask(MusicProvider musicProvider,
+ MusicProviderTaskListener listener) {
+ mMusicProvider = musicProvider;
+ mMusicProviderTaskListener = listener;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.os.AsyncTask#doInBackground(java.lang.Object[])
+ */
+ @Override
+ protected Void doInBackground(Void... arg0) {
+ try {
+ mMusicProvider.retreiveMedia();
+ } catch (JSONException e) {
+ Log.e(TAG, "::doInBackground:", e);
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
+ */
+ @Override
+ protected void onPostExecute(Void result) {
+ mMusicProviderTaskListener.onMusicProviderTaskCompleted();
+ }
+
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTaskListener.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTaskListener.java
new file mode 100644
index 0000000..b1d168f
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicProviderTaskListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.musicservicedemo.browser;
+
+/**
+ * Callback listener for completion of MusicProviderTask
+ */
+public interface MusicProviderTaskListener {
+ public void onMusicProviderTaskCompleted();
+}
diff --git a/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicTrack.java b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicTrack.java
new file mode 100644
index 0000000..02ea899
--- /dev/null
+++ b/tests/MusicServiceDemo/src/com/example/android/musicservicedemo/browser/MusicTrack.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2014 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.android.musicservicedemo.browser;
+
+/**
+ * A class to model music track metadata.
+ */
+public class MusicTrack {
+
+ private static final String TAG = "MusicTrack";
+
+ private String mTitle;
+ private String mAlbum;
+ private String mArtist;
+ private String mGenre;
+ private String mSource;
+ private String mImage;
+ private int mTrackNumber;
+ private int mTotalTrackCount;
+ private int mDuration;
+
+ /**
+ * Constructor creating a MusicTrack instance.
+ *
+ * @param title
+ * @param album
+ * @param artist
+ * @param genre
+ * @param source
+ * @param image
+ * @param trackNumber
+ * @param totalTrackCount
+ * @param duration
+ */
+ public MusicTrack(String title, String album, String artist, String genre, String source,
+ String image, int trackNumber, int totalTrackCount, int duration) {
+ this.mTitle = title;
+ this.mAlbum = album;
+ this.mArtist = artist;
+ this.mGenre = genre;
+ this.mSource = source;
+ this.mImage = image;
+ this.mTrackNumber = trackNumber;
+ this.mTotalTrackCount = totalTrackCount;
+ this.mDuration = duration;
+ }
+
+ public String getTitle() {
+ return mTitle;
+ }
+
+ public void setTitle(String mTitle) {
+ this.mTitle = mTitle;
+ }
+
+ public String getAlbum() {
+ return mAlbum;
+ }
+
+ public void setAlbum(String mAlbum) {
+ this.mAlbum = mAlbum;
+ }
+
+ public String getArtist() {
+ return mArtist;
+ }
+
+ public void setArtist(String mArtist) {
+ this.mArtist = mArtist;
+ }
+
+ public String getGenre() {
+ return mGenre;
+ }
+
+ public void setGenre(String mGenre) {
+ this.mGenre = mGenre;
+ }
+
+ public String getSource() {
+ return mSource;
+ }
+
+ public void setSource(String mSource) {
+ this.mSource = mSource;
+ }
+
+ public String getImage() {
+ return mImage;
+ }
+
+ public void setImage(String mImage) {
+ this.mImage = mImage;
+ }
+
+ public int getTrackNumber() {
+ return mTrackNumber;
+ }
+
+ public void setTrackNumber(int mTrackNumber) {
+ this.mTrackNumber = mTrackNumber;
+ }
+
+ public int getTotalTrackCount() {
+ return mTotalTrackCount;
+ }
+
+ public void setTotalTrackCount(int mTotalTrackCount) {
+ this.mTotalTrackCount = mTotalTrackCount;
+ }
+
+ public int getDuration() {
+ return mDuration;
+ }
+
+ public void setDuration(int mDuration) {
+ this.mDuration = mDuration;
+ }
+
+ public String toString() {
+ return mTitle;
+ }
+
+}