1 /* 2 * Copyright (C) 2014 The Android Open Source Project 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 package com.example.android.mediabrowserservice; 17 18 import android.app.Fragment; 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.media.browse.MediaBrowser; 22 import android.media.session.MediaController; 23 import android.os.Bundle; 24 import android.util.Log; 25 import android.view.LayoutInflater; 26 import android.view.View; 27 import android.view.ViewGroup; 28 import android.widget.AdapterView; 29 import android.widget.ArrayAdapter; 30 import android.widget.ImageView; 31 import android.widget.ListView; 32 import android.widget.TextView; 33 import android.widget.Toast; 34 35 import com.example.android.mediabrowserservice.utils.LogHelper; 36 37 import java.util.ArrayList; 38 import java.util.List; 39 40 /** 41 * A Fragment that lists all the various browsable queues available 42 * from a {@link android.service.media.MediaBrowserService}. 43 * <p/> 44 * It uses a {@link MediaBrowser} to connect to the {@link MusicService}. Once connected, 45 * the fragment subscribes to get all the children. All {@link MediaBrowser.MediaItem}'s 46 * that can be browsed are shown in a ListView. 47 */ 48 public class BrowseFragment extends Fragment { 49 50 private static final String TAG = LogHelper.makeLogTag(BrowseFragment.class.getSimpleName()); 51 52 public static final String ARG_MEDIA_ID = "media_id"; 53 54 public static interface FragmentDataHelper { onMediaItemSelected(MediaBrowser.MediaItem item)55 void onMediaItemSelected(MediaBrowser.MediaItem item); 56 } 57 58 // The mediaId to be used for subscribing for children using the MediaBrowser. 59 private String mMediaId; 60 61 private MediaBrowser mMediaBrowser; 62 private BrowseAdapter mBrowserAdapter; 63 64 private MediaBrowser.SubscriptionCallback mSubscriptionCallback = new MediaBrowser.SubscriptionCallback() { 65 66 @Override 67 public void onChildrenLoaded(String parentId, List<MediaBrowser.MediaItem> children) { 68 mBrowserAdapter.clear(); 69 mBrowserAdapter.notifyDataSetInvalidated(); 70 for (MediaBrowser.MediaItem item : children) { 71 mBrowserAdapter.add(item); 72 } 73 mBrowserAdapter.notifyDataSetChanged(); 74 } 75 76 @Override 77 public void onError(String id) { 78 Toast.makeText(getActivity(), R.string.error_loading_media, 79 Toast.LENGTH_LONG).show(); 80 } 81 }; 82 83 private MediaBrowser.ConnectionCallback mConnectionCallback = 84 new MediaBrowser.ConnectionCallback() { 85 @Override 86 public void onConnected() { 87 LogHelper.d(TAG, "onConnected: session token " + mMediaBrowser.getSessionToken()); 88 89 if (mMediaId == null) { 90 mMediaId = mMediaBrowser.getRoot(); 91 } 92 mMediaBrowser.subscribe(mMediaId, mSubscriptionCallback); 93 if (mMediaBrowser.getSessionToken() == null) { 94 throw new IllegalArgumentException("No Session token"); 95 } 96 MediaController mediaController = new MediaController(getActivity(), 97 mMediaBrowser.getSessionToken()); 98 getActivity().setMediaController(mediaController); 99 } 100 101 @Override 102 public void onConnectionFailed() { 103 LogHelper.d(TAG, "onConnectionFailed"); 104 } 105 106 @Override 107 public void onConnectionSuspended() { 108 LogHelper.d(TAG, "onConnectionSuspended"); 109 getActivity().setMediaController(null); 110 } 111 }; 112 newInstance(String mediaId)113 public static BrowseFragment newInstance(String mediaId) { 114 Bundle args = new Bundle(); 115 args.putString(ARG_MEDIA_ID, mediaId); 116 BrowseFragment fragment = new BrowseFragment(); 117 fragment.setArguments(args); 118 return fragment; 119 } 120 121 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)122 public View onCreateView(LayoutInflater inflater, ViewGroup container, 123 Bundle savedInstanceState) { 124 View rootView = inflater.inflate(R.layout.fragment_list, container, false); 125 126 mBrowserAdapter = new BrowseAdapter(getActivity()); 127 128 View controls = rootView.findViewById(R.id.controls); 129 controls.setVisibility(View.GONE); 130 131 ListView listView = (ListView) rootView.findViewById(R.id.list_view); 132 listView.setAdapter(mBrowserAdapter); 133 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 134 @Override 135 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 136 MediaBrowser.MediaItem item = mBrowserAdapter.getItem(position); 137 try { 138 FragmentDataHelper listener = (FragmentDataHelper) getActivity(); 139 listener.onMediaItemSelected(item); 140 } catch (ClassCastException ex) { 141 Log.e(TAG, "Exception trying to cast to FragmentDataHelper", ex); 142 } 143 } 144 }); 145 146 Bundle args = getArguments(); 147 mMediaId = args.getString(ARG_MEDIA_ID, null); 148 149 mMediaBrowser = new MediaBrowser(getActivity(), 150 new ComponentName(getActivity(), MusicService.class), 151 mConnectionCallback, null); 152 153 return rootView; 154 } 155 156 @Override onStart()157 public void onStart() { 158 super.onStart(); 159 mMediaBrowser.connect(); 160 } 161 162 @Override onStop()163 public void onStop() { 164 super.onStop(); 165 mMediaBrowser.disconnect(); 166 } 167 168 // An adapter for showing the list of browsed MediaItem's 169 private static class BrowseAdapter extends ArrayAdapter<MediaBrowser.MediaItem> { 170 BrowseAdapter(Context context)171 public BrowseAdapter(Context context) { 172 super(context, R.layout.media_list_item, new ArrayList<MediaBrowser.MediaItem>()); 173 } 174 175 static class ViewHolder { 176 ImageView mImageView; 177 TextView mTitleView; 178 TextView mDescriptionView; 179 } 180 181 @Override getView(int position, View convertView, ViewGroup parent)182 public View getView(int position, View convertView, ViewGroup parent) { 183 184 ViewHolder holder; 185 186 if (convertView == null) { 187 convertView = LayoutInflater.from(getContext()) 188 .inflate(R.layout.media_list_item, parent, false); 189 holder = new ViewHolder(); 190 holder.mImageView = (ImageView) convertView.findViewById(R.id.play_eq); 191 holder.mImageView.setVisibility(View.GONE); 192 holder.mTitleView = (TextView) convertView.findViewById(R.id.title); 193 holder.mDescriptionView = (TextView) convertView.findViewById(R.id.description); 194 convertView.setTag(holder); 195 } else { 196 holder = (ViewHolder) convertView.getTag(); 197 } 198 199 MediaBrowser.MediaItem item = getItem(position); 200 holder.mTitleView.setText(item.getDescription().getTitle()); 201 holder.mDescriptionView.setText(item.getDescription().getDescription()); 202 if (item.isPlayable()) { 203 holder.mImageView.setImageDrawable( 204 getContext().getDrawable(R.drawable.ic_play_arrow_white_24dp)); 205 holder.mImageView.setVisibility(View.VISIBLE); 206 } 207 return convertView; 208 } 209 } 210 } 211