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
17package com.example.android.musicservicedemo;
18
19import android.app.SearchManager;
20import android.app.Service;
21import android.content.Context;
22import android.content.Intent;
23import android.content.UriMatcher;
24import android.content.res.Resources.NotFoundException;
25import android.database.MatrixCursor;
26import android.graphics.Bitmap;
27import android.media.AudioManager;
28import android.media.MediaDescription;
29import android.media.MediaPlayer;
30import android.media.MediaPlayer.OnCompletionListener;
31import android.media.MediaPlayer.OnErrorListener;
32import android.media.MediaPlayer.OnPreparedListener;
33import android.media.browse.MediaBrowser;
34import android.service.media.MediaBrowserService;
35import android.service.media.MediaBrowserService.BrowserRoot;
36import android.media.session.MediaSession;
37import android.net.Uri;
38import android.net.wifi.WifiManager;
39import android.net.wifi.WifiManager.WifiLock;
40import android.os.Bundle;
41import android.os.Handler;
42import android.os.IBinder;
43import android.os.Message;
44import android.os.PowerManager;
45import android.os.RemoteException;
46import android.os.SystemClock;
47import android.util.Log;
48
49import com.example.android.musicservicedemo.browser.MusicProvider;
50import com.example.android.musicservicedemo.browser.MusicProviderTask;
51import com.example.android.musicservicedemo.browser.MusicProviderTaskListener;
52import com.example.android.musicservicedemo.browser.MusicTrack;
53
54import org.json.JSONException;
55
56import java.io.IOException;
57import java.util.ArrayList;
58import java.util.List;
59
60/**
61 * Service that implements MediaBrowserService and returns our menu hierarchy.
62 */
63public class BrowserService extends MediaBrowserService {
64    private static final String TAG = "BrowserService";
65
66    // URI paths for browsing music
67    public static final String BROWSE_ROOT_BASE_PATH = "browse";
68    public static final String NOW_PLAYING_PATH = "now_playing";
69    public static final String PIANO_BASE_PATH = "piano";
70    public static final String VOICE_BASE_PATH = "voice";
71
72    // Content URIs
73    public static final String AUTHORITY = "com.example.android.automotive.musicplayer";
74    public static final Uri BASE_URI = Uri.parse("content://" + AUTHORITY);
75    public static final Uri BROWSE_URI = Uri.withAppendedPath(BASE_URI, BROWSE_ROOT_BASE_PATH);
76
77    // URI matcher constants for browsing paths
78    public static final int BROWSE_ROOT = 1;
79    public static final int NOW_PLAYING = 2;
80    public static final int PIANO = 3;
81    public static final int VOICE = 4;
82
83    // Map the the URI paths with the URI matcher constants
84    private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
85    static {
86        sUriMatcher.addURI(AUTHORITY, BROWSE_ROOT_BASE_PATH, BROWSE_ROOT);
87        sUriMatcher.addURI(AUTHORITY, NOW_PLAYING_PATH, NOW_PLAYING);
88        sUriMatcher.addURI(AUTHORITY, PIANO_BASE_PATH, PIANO);
89        sUriMatcher.addURI(AUTHORITY, VOICE_BASE_PATH, VOICE);
90    }
91
92    // Media metadata that will be provided for a media container
93    public static final String[] MEDIA_CONTAINER_PROJECTION = {
94            "uri",
95            "title",
96            "subtitle",
97            "image_uri",
98            "supported_actions"
99    };
100
101    // MusicProvider will download the music catalog
102    private MusicProvider mMusicProvider;
103
104    private MediaSession mSession;
105
106    @Override
107    public void onCreate() {
108        super.onCreate();
109
110        mSession = new MediaSession(this, "com.example.android.musicservicedemo.BrowserService");
111        setSessionToken(mSession.getSessionToken());
112    }
113
114    @Override
115    public void onDestroy() {
116        super.onDestroy();
117    }
118
119    @Override
120    public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) {
121        return new BrowserRoot(BROWSE_URI.toString(), null);
122    }
123
124    @Override
125    public void onLoadChildren(final String parentId,
126            final Result<List<MediaBrowser.MediaItem>> result) {
127        new Handler().postDelayed(new Runnable() {
128                public void run() {
129                    final ArrayList<MediaBrowser.MediaItem> list = new ArrayList();
130
131                    for (int i=0; i<10; i++) {
132                        MediaDescription.Builder bob = new MediaDescription.Builder();
133                        bob.setTitle("Title " + i);
134                        bob.setSubtitle("Summary " + i);
135                        bob.setMediaId(Uri.withAppendedPath(BASE_URI,
136                                Integer.toString(i)).toString());
137                        list.add(new MediaBrowser.MediaItem(bob.build(),
138                                MediaBrowser.MediaItem.FLAG_BROWSABLE));
139                    }
140
141                    result.sendResult(list);
142                }
143            }, 2000);
144        result.detach();
145    }
146
147    /*
148    @Override
149    public void query(final Query query, final IMetadataResultHandler metadataResultHandler,
150            final IErrorHandler errorHandler)
151            throws RemoteException {
152        Log.d(TAG, "query: " + query);
153        Utils.checkNotNull(query);
154        Utils.checkNotNull(metadataResultHandler);
155        Utils.checkNotNull(errorHandler);
156
157        // Handle async response
158        new Thread(new Runnable() {
159            public void run() {
160                try {
161                    // Pre-load the list of music
162                    List<MusicTrack> musicTracks = getMusicList();
163                    if (musicTracks == null) {
164                        notifyListenersOnPlaybackStateUpdate(getCurrentPlaybackState());
165                        errorHandler.onError(new Error(Error.UNKNOWN,
166                                getString(R.string.music_error)));
167                        return;
168                    }
169
170                    final Uri uri = query.getUri();
171                    int match = sUriMatcher.match(uri);
172                    Log.d(TAG, "Queried: " + uri + "; match: " + match);
173                    switch (match) {
174                        case BROWSE_ROOT:
175                        {
176                            Log.d(TAG, "Browse_root");
177
178                            try {
179                                MatrixCursor matrixCursor = mMusicProvider
180                                        .getRootContainerCurser();
181                                DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
182                                        matrixCursor, null);
183
184                                Log.d(TAG, "on metadata response called " + holder.getCount());
185                                metadataResultHandler.onMetadataResponse(holder);
186                            } catch (RemoteException e) {
187                                Log.w(TAG, "Error delivering metadata in the callback.", e);
188                            }
189                            break;
190                        }
191                        case NOW_PLAYING:
192                        {
193                            try {
194                                Log.d(TAG, "query NOW_PLAYING");
195                                MatrixCursor matrixCursor = mMusicProvider
196                                        .getRootItemCursor(
197                                        PIANO);
198                                DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
199                                        matrixCursor, null);
200                                Log.d(TAG, "on metadata response called " + holder.getCount());
201                                metadataResultHandler.onMetadataResponse(holder);
202                            } catch (RemoteException e) {
203                                Log.w(TAG, "Error querying NOW_PLAYING");
204                            }
205                            break;
206                        }
207                        case PIANO:
208                        {
209                            try {
210                                Log.d(TAG, "query PIANO");
211                                MatrixCursor matrixCursor = mMusicProvider
212                                        .getRootItemCursor(
213                                        PIANO);
214                                DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
215                                        matrixCursor, null);
216                                Log.d(TAG, "on metadata response called " + holder.getCount());
217                                metadataResultHandler.onMetadataResponse(holder);
218                            } catch (RemoteException e) {
219                                Log.w(TAG, "Error querying PIANO");
220                            }
221                            break;
222                        }
223                        case VOICE:
224                        {
225                            try {
226                                Log.d(TAG, "query VOICE");
227                                MatrixCursor matrixCursor = mMusicProvider
228                                        .getRootItemCursor(
229                                        VOICE);
230                                DataHolder holder = new DataHolder(MEDIA_CONTAINER_PROJECTION,
231                                        matrixCursor, null);
232                                Log.d(TAG, "on metadata response called " + holder.getCount());
233                                metadataResultHandler.onMetadataResponse(holder);
234                            } catch (RemoteException e) {
235                                Log.w(TAG, "Error querying VOICE");
236                            }
237                            break;
238                        }
239                        default:
240                        {
241                            Log.w(TAG, "Skipping unmatched URI: " + uri);
242                        }
243                    }
244                } catch (NotFoundException e) {
245                    Log.e(TAG, "::run:", e);
246                } catch (RemoteException e) {
247                    Log.e(TAG, "::run:", e);
248                }
249            } // end run
250        }).start();
251    }
252
253    */
254}
255