1 2 /* 3 * Copyright (C) 2014 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package com.android.onemedia; 18 19 import android.media.MediaMetadata; 20 import android.media.session.MediaController; 21 import android.media.session.MediaSession; 22 import android.media.session.MediaSessionManager; 23 import android.media.session.PlaybackState; 24 import android.os.Bundle; 25 import android.os.Handler; 26 import android.os.IBinder; 27 import android.os.RemoteException; 28 import android.app.Activity; 29 import android.content.ComponentName; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.ServiceConnection; 33 import android.graphics.Bitmap; 34 import android.util.Log; 35 36 import com.android.onemedia.playback.RequestUtils; 37 38 public class PlayerController { 39 private static final String TAG = "PlayerController"; 40 41 public static final int STATE_DISCONNECTED = 0; 42 public static final int STATE_CONNECTED = 1; 43 44 protected MediaController mController; 45 protected IPlayerService mBinder; 46 protected MediaController.TransportControls mTransportControls; 47 48 private final Intent mServiceIntent; 49 private Activity mContext; 50 private Listener mListener; 51 private SessionCallback mControllerCb; 52 private MediaSessionManager mManager; 53 private Handler mHandler = new Handler(); 54 55 private boolean mResumed; 56 private Bitmap mArt; 57 PlayerController(Activity context, Intent serviceIntent)58 public PlayerController(Activity context, Intent serviceIntent) { 59 mContext = context; 60 if (serviceIntent == null) { 61 mServiceIntent = new Intent(mContext, PlayerService.class); 62 } else { 63 mServiceIntent = serviceIntent; 64 } 65 mControllerCb = new SessionCallback(); 66 mManager = (MediaSessionManager) context 67 .getSystemService(Context.MEDIA_SESSION_SERVICE); 68 69 mResumed = false; 70 } 71 setListener(Listener listener)72 public void setListener(Listener listener) { 73 mListener = listener; 74 Log.d(TAG, "Listener set to " + listener + " session is " + mController); 75 if (mListener != null) { 76 mHandler = new Handler(); 77 mListener.onConnectionStateChange( 78 mController == null ? STATE_DISCONNECTED : STATE_CONNECTED); 79 } 80 } 81 onResume()82 public void onResume() { 83 mResumed = true; 84 Log.d(TAG, "onResume. Binding to service with intent " + mServiceIntent.toString()); 85 bindToService(); 86 } 87 onPause()88 public void onPause() { 89 mResumed = false; 90 Log.d(TAG, "onPause, unbinding from service"); 91 unbindFromService(); 92 } 93 setArt(Bitmap art)94 public void setArt(Bitmap art) { 95 mArt = art; 96 if (mBinder != null) { 97 try { 98 mBinder.setIcon(art); 99 } catch (RemoteException e) { 100 } 101 } 102 } 103 play()104 public void play() { 105 if (mTransportControls != null) { 106 mTransportControls.play(); 107 } 108 } 109 pause()110 public void pause() { 111 if (mTransportControls != null) { 112 mTransportControls.pause(); 113 } 114 } 115 setContent(String source)116 public void setContent(String source) { 117 RequestUtils.ContentBuilder bob = new RequestUtils.ContentBuilder(); 118 bob.setSource(source); 119 try { 120 mBinder.sendRequest(RequestUtils.ACTION_SET_CONTENT, bob.build(), null); 121 } catch (RemoteException e) { 122 Log.d(TAG, "setContent failed, service may have died.", e); 123 } 124 } 125 setNextContent(String source)126 public void setNextContent(String source) { 127 RequestUtils.ContentBuilder bob = new RequestUtils.ContentBuilder(); 128 bob.setSource(source); 129 try { 130 mBinder.sendRequest(RequestUtils.ACTION_SET_NEXT_CONTENT, bob.build(), null); 131 } catch (RemoteException e) { 132 Log.d(TAG, "setNexctContent failed, service may have died.", e); 133 } 134 } 135 showRoutePicker()136 public void showRoutePicker() { 137 // TODO 138 } 139 getSessionToken()140 public MediaSession.Token getSessionToken() { 141 if (mBinder != null) { 142 try { 143 return mBinder.getSessionToken(); 144 } catch (RemoteException e) { 145 } 146 } 147 return null; 148 } 149 unbindFromService()150 private void unbindFromService() { 151 mContext.unbindService(mServiceConnection); 152 } 153 bindToService()154 private void bindToService() { 155 mContext.bindService(mServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE); 156 } 157 158 private ServiceConnection mServiceConnection = new ServiceConnection() { 159 @Override 160 public void onServiceDisconnected(ComponentName name) { 161 if (mController != null) { 162 mController.unregisterCallback(mControllerCb); 163 } 164 mBinder = null; 165 mController = null; 166 mTransportControls = null; 167 mContext.setMediaController(null); 168 Log.d(TAG, "Disconnected from PlayerService"); 169 170 if (mListener != null) { 171 mListener.onConnectionStateChange(STATE_DISCONNECTED); 172 } 173 } 174 175 @Override 176 public void onServiceConnected(ComponentName name, IBinder service) { 177 mBinder = IPlayerService.Stub.asInterface(service); 178 Log.d(TAG, "service is " + service + " binder is " + mBinder); 179 MediaSession.Token token; 180 try { 181 token = mBinder.getSessionToken(); 182 } catch (RemoteException e) { 183 Log.e(TAG, "Error getting session", e); 184 return; 185 } 186 mController = new MediaController(mContext, token); 187 mContext.setMediaController(mController); 188 mController.registerCallback(mControllerCb, mHandler); 189 mTransportControls = mController.getTransportControls(); 190 if (mArt != null) { 191 setArt(mArt); 192 } 193 Log.d(TAG, "Ready to use PlayerService"); 194 195 if (mListener != null) { 196 mListener.onConnectionStateChange(STATE_CONNECTED); 197 if (mTransportControls != null) { 198 mListener.onPlaybackStateChange(mController.getPlaybackState()); 199 } 200 } 201 } 202 }; 203 204 private class SessionCallback extends MediaController.Callback { 205 @Override onPlaybackStateChanged(PlaybackState state)206 public void onPlaybackStateChanged(PlaybackState state) { 207 if (state == null) { 208 return; 209 } 210 Log.d(TAG, "Received playback state change to state " + state.getState()); 211 if (mListener != null) { 212 mListener.onPlaybackStateChange(state); 213 } 214 } 215 216 @Override onMetadataChanged(MediaMetadata metadata)217 public void onMetadataChanged(MediaMetadata metadata) { 218 if (metadata == null) { 219 return; 220 } 221 Log.d(TAG, "Received metadata change, " + metadata.getDescription()); 222 if (mListener != null) { 223 mListener.onMetadataChange(metadata); 224 } 225 } 226 } 227 228 public interface Listener { onPlaybackStateChange(PlaybackState state)229 public void onPlaybackStateChange(PlaybackState state); onMetadataChange(MediaMetadata metadata)230 public void onMetadataChange(MediaMetadata metadata); onConnectionStateChange(int state)231 public void onConnectionStateChange(int state); 232 } 233 234 } 235