OSDN Git Service

5ed2511303025a4ddcae451c195f869e2ebed0b9
[android-x86/packages-apps-Eleven.git] / src / com / cyngn / eleven / ui / activities / BaseActivity.java
1 /*
2  * Copyright (C) 2012 Andrew Neal Licensed under the Apache License, Version 2.0
3  * (the "License"); you may not use this file except in compliance with the
4  * License. You may obtain a copy of the License at
5  * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
6  * or agreed to in writing, software distributed under the License is
7  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
8  * KIND, either express or implied. See the License for the specific language
9  * governing permissions and limitations under the License.
10  */
11
12 package com.cyngn.eleven.ui.activities;
13
14 import static com.cyngn.eleven.utils.MusicUtils.mService;
15
16 import android.app.SearchManager;
17 import android.app.SearchableInfo;
18 import android.content.BroadcastReceiver;
19 import android.content.ComponentName;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.content.ServiceConnection;
24 import android.media.AudioManager;
25 import android.os.Bundle;
26 import android.os.IBinder;
27 import android.support.v4.app.FragmentActivity;
28 import android.view.Menu;
29 import android.view.MenuItem;
30 import android.view.View;
31 import android.widget.ImageView;
32 import android.widget.LinearLayout;
33 import android.widget.SearchView;
34 import android.widget.SearchView.OnQueryTextListener;
35 import android.widget.TextView;
36
37 import com.cyngn.eleven.IElevenService;
38 import com.cyngn.eleven.MusicPlaybackService;
39 import com.cyngn.eleven.MusicStateListener;
40 import com.cyngn.eleven.R;
41 import com.cyngn.eleven.utils.ApolloUtils;
42 import com.cyngn.eleven.utils.Lists;
43 import com.cyngn.eleven.utils.MusicUtils;
44 import com.cyngn.eleven.utils.MusicUtils.ServiceToken;
45 import com.cyngn.eleven.utils.NavUtils;
46 import com.cyngn.eleven.widgets.PlayPauseButton;
47 import com.cyngn.eleven.widgets.PlayPauseProgressButton;
48 import com.cyngn.eleven.widgets.RepeatButton;
49 import com.cyngn.eleven.widgets.ShuffleButton;
50
51 import java.lang.ref.WeakReference;
52 import java.util.ArrayList;
53
54 /**
55  * A base {@link FragmentActivity} used to update the bottom bar and
56  * bind to Apollo's service.
57  * <p>
58  * {@link HomeActivity} extends from this skeleton.
59  * 
60  * @author Andrew Neal (andrewdneal@gmail.com)
61  */
62 public abstract class BaseActivity extends FragmentActivity implements ServiceConnection {
63
64     /**
65      * Playstate and meta change listener
66      */
67     private final ArrayList<MusicStateListener> mMusicStateListener = Lists.newArrayList();
68
69     /**
70      * The service token
71      */
72     private ServiceToken mToken;
73
74     /**
75      * Play pause progress button
76      */
77     private PlayPauseProgressButton mPlayPauseProgressButton;
78
79     /**
80      * Track name (BAB)
81      */
82     private TextView mTrackName;
83
84     /**
85      * Artist name (BAB)
86      */
87     private TextView mArtistName;
88
89     /**
90      * Album art (BAB)
91      */
92     private ImageView mAlbumArt;
93
94     /**
95      * Broadcast receiver
96      */
97     private PlaybackStatus mPlaybackStatus;
98
99     /**
100      * Keeps track of the back button being used
101      */
102     private boolean mIsBackPressed = false;
103
104     /**
105      * {@inheritDoc}
106      */
107     @Override
108     protected void onCreate(final Bundle savedInstanceState) {
109         super.onCreate(savedInstanceState);
110
111         // Fade it in
112         overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
113
114         // Control the media volume
115         setVolumeControlStream(AudioManager.STREAM_MUSIC);
116
117         // Bind Apollo's service
118         mToken = MusicUtils.bindToService(this, this);
119
120         // Initialize the broadcast receiver
121         mPlaybackStatus = new PlaybackStatus(this);
122
123         getActionBar().setTitle(getString(R.string.app_name_uppercase));
124
125         // Set the layout
126         setContentView(setContentView());
127
128         // set the background on the root view
129         getWindow().getDecorView().getRootView().setBackgroundColor(
130                 getResources().getColor(R.color.background_color));
131
132         // Initialze the bottom action bar
133         initBottomActionBar();
134     }
135
136     /**
137      * {@inheritDoc}
138      */
139     @Override
140     public void onServiceConnected(final ComponentName name, final IBinder service) {
141         mService = IElevenService.Stub.asInterface(service);
142         // Set the playback drawables
143         updatePlaybackControls();
144         // Current info
145         updateMetaInfo();
146     }
147
148     /**
149      * {@inheritDoc}
150      */
151     @Override
152     public void onServiceDisconnected(final ComponentName name) {
153         mService = null;
154     }
155
156     /**
157      * {@inheritDoc}
158      */
159     @Override
160     public boolean onCreateOptionsMenu(final Menu menu) {
161         // Search view
162         getMenuInflater().inflate(R.menu.search, menu);
163         // Settings
164         getMenuInflater().inflate(R.menu.activity_base, menu);
165
166         final SearchView searchView = (SearchView)menu.findItem(R.id.menu_search).getActionView();
167         // Add voice search
168         final SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
169         final SearchableInfo searchableInfo = searchManager.getSearchableInfo(getComponentName());
170         searchView.setSearchableInfo(searchableInfo);
171         // Perform the search
172         searchView.setOnQueryTextListener(new OnQueryTextListener() {
173
174             @Override
175             public boolean onQueryTextSubmit(final String query) {
176                 // Open the search activity
177                 NavUtils.openSearch(BaseActivity.this, query);
178                 return true;
179             }
180
181             @Override
182             public boolean onQueryTextChange(final String newText) {
183                 // Nothing to do
184                 return false;
185             }
186         });
187         return super.onCreateOptionsMenu(menu);
188     }
189
190     /**
191      * {@inheritDoc}
192      */
193     @Override
194     public boolean onOptionsItemSelected(final MenuItem item) {
195         switch (item.getItemId()) {
196             case R.id.menu_settings:
197                 // Settings
198                 NavUtils.openSettings(this);
199                 return true;
200
201             default:
202                 break;
203         }
204         return super.onOptionsItemSelected(item);
205     }
206
207     /**
208      * {@inheritDoc}
209      */
210     @Override
211     protected void onResume() {
212         super.onResume();
213         // Set the playback drawables
214         updatePlaybackControls();
215         // Current info
216         updateMetaInfo();
217     }
218
219     /**
220      * {@inheritDoc}
221      */
222     @Override
223     protected void onStart() {
224         super.onStart();
225         final IntentFilter filter = new IntentFilter();
226         // Play and pause changes
227         filter.addAction(MusicPlaybackService.PLAYSTATE_CHANGED);
228         // Track changes
229         filter.addAction(MusicPlaybackService.META_CHANGED);
230         // Update a list, probably the playlist fragment's
231         filter.addAction(MusicPlaybackService.REFRESH);
232         registerReceiver(mPlaybackStatus, filter);
233
234         mPlayPauseProgressButton.resume();
235
236         MusicUtils.notifyForegroundStateChanged(this, true);
237     }
238
239     /**
240      * {@inheritDoc}
241      */
242     @Override
243     protected void onStop() {
244         super.onStop();
245
246         mPlayPauseProgressButton.pause();
247
248         MusicUtils.notifyForegroundStateChanged(this, false);
249     }
250
251     /**
252      * {@inheritDoc}
253      */
254     @Override
255     protected void onDestroy() {
256         super.onDestroy();
257         // Unbind from the service
258         if (mToken != null) {
259             MusicUtils.unbindFromService(mToken);
260             mToken = null;
261         }
262
263         // Unregister the receiver
264         try {
265             unregisterReceiver(mPlaybackStatus);
266         } catch (final Throwable e) {
267             //$FALL-THROUGH$
268         }
269
270         // Remove any music status listeners
271         mMusicStateListener.clear();
272     }
273
274     /**
275      * {@inheritDoc}
276      */
277     @Override
278     public void onBackPressed() {
279         super.onBackPressed();
280         mIsBackPressed = true;
281     }
282
283     /**
284      * Initializes the items in the bottom action bar.
285      */
286     private void initBottomActionBar() {
287         // Play and pause button
288         mPlayPauseProgressButton = (PlayPauseProgressButton)findViewById(R.id.playPauseProgressButton);
289         mPlayPauseProgressButton.enableAndShow();
290
291         // Track name
292         mTrackName = (TextView)findViewById(R.id.bottom_action_bar_line_one);
293         // Artist name
294         mArtistName = (TextView)findViewById(R.id.bottom_action_bar_line_two);
295         // Album art
296         mAlbumArt = (ImageView)findViewById(R.id.bottom_action_bar_album_art);
297         // Open to the currently playing album profile
298         mAlbumArt.setOnClickListener(mOpenCurrentAlbumProfile);
299         // Bottom action bar
300         final LinearLayout bottomActionBar = (LinearLayout)findViewById(R.id.bottom_action_bar);
301         // Display the now playing screen or shuffle if this isn't anything
302         // playing
303         bottomActionBar.setOnClickListener(mOpenNowPlaying);
304     }
305
306     /**
307      * Sets the track name, album name, and album art.  This is protected to enable overriding
308      */
309     protected void updateMetaInfo() {
310         updateBottomActionBarInfo();
311     }
312
313     /**
314      * Sets the track name, album name, and album art.
315      */
316     private void updateBottomActionBarInfo() {
317         // Set the track name
318         mTrackName.setText(MusicUtils.getTrackName());
319         // Set the artist name
320         mArtistName.setText(MusicUtils.getArtistName());
321         // Set the album art
322         ApolloUtils.getImageFetcher(this).loadCurrentArtwork(mAlbumArt);
323     }
324
325     /**
326      * Sets the correct drawable states for the playback controls.
327      */
328     private void updatePlaybackControls() {
329         // Set the play and pause image
330         mPlayPauseProgressButton.getPlayPauseButton().updateState();
331     }
332
333     /**
334      * Opens the album profile of the currently playing album
335      */
336     private final View.OnClickListener mOpenCurrentAlbumProfile = new View.OnClickListener() {
337
338         /**
339          * {@inheritDoc}
340          */
341         @Override
342         public void onClick(final View v) {
343             if (MusicUtils.getCurrentAudioId() != -1) {
344                 NavUtils.openAlbumProfile(BaseActivity.this, MusicUtils.getAlbumName(),
345                         MusicUtils.getArtistName(), MusicUtils.getCurrentAlbumId());
346             } else {
347                 MusicUtils.shuffleAll(BaseActivity.this);
348             }
349             if (BaseActivity.this instanceof ProfileActivity) {
350                 finish();
351             }
352         }
353     };
354
355     /**
356      * Opens the now playing screen
357      */
358     private final View.OnClickListener mOpenNowPlaying = new View.OnClickListener() {
359
360         /**
361          * {@inheritDoc}
362          */
363         @Override
364         public void onClick(final View v) {
365             if (MusicUtils.getCurrentAudioId() != -1) {
366                 NavUtils.openAudioPlayer(BaseActivity.this);
367             } else {
368                 MusicUtils.shuffleAll(BaseActivity.this);
369             }
370         }
371     };
372
373     /**
374      * Used to monitor the state of playback
375      */
376     private final static class PlaybackStatus extends BroadcastReceiver {
377
378         private final WeakReference<BaseActivity> mReference;
379
380         /**
381          * Constructor of <code>PlaybackStatus</code>
382          */
383         public PlaybackStatus(final BaseActivity activity) {
384             mReference = new WeakReference<BaseActivity>(activity);
385         }
386
387         /**
388          * {@inheritDoc}
389          */
390         @Override
391         public void onReceive(final Context context, final Intent intent) {
392             final String action = intent.getAction();
393             if (action.equals(MusicPlaybackService.META_CHANGED)) {
394                 // Current info
395                 mReference.get().updateMetaInfo();
396                 // Let the listener know to the meta chnaged
397                 for (final MusicStateListener listener : mReference.get().mMusicStateListener) {
398                     if (listener != null) {
399                         listener.onMetaChanged();
400                     }
401                 }
402             } else if (action.equals(MusicPlaybackService.PLAYSTATE_CHANGED)) {
403                 // Set the play and pause image
404                 mReference.get().mPlayPauseProgressButton.getPlayPauseButton().updateState();
405             } else if (action.equals(MusicPlaybackService.REFRESH)) {
406                 // Let the listener know to update a list
407                 for (final MusicStateListener listener : mReference.get().mMusicStateListener) {
408                     if (listener != null) {
409                         listener.restartLoader();
410                     }
411                 }
412             }
413         }
414     }
415
416     /**
417      * @param status The {@link MusicStateListener} to use
418      */
419     public void setMusicStateListenerListener(final MusicStateListener status) {
420         if (status != null) {
421             mMusicStateListener.add(status);
422         }
423     }
424
425     /**
426      * @return The resource ID to be inflated.
427      */
428     public abstract int setContentView();
429 }