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