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.
12 package com.cyngn.eleven.ui.activities;
14 import static com.cyngn.eleven.utils.MusicUtils.mService;
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;
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;
51 import java.lang.ref.WeakReference;
52 import java.util.ArrayList;
55 * A base {@link FragmentActivity} used to update the bottom bar and
56 * bind to Apollo's service.
58 * {@link HomeActivity} extends from this skeleton.
60 * @author Andrew Neal (andrewdneal@gmail.com)
62 public abstract class BaseActivity extends FragmentActivity implements ServiceConnection {
65 * Playstate and meta change listener
67 private final ArrayList<MusicStateListener> mMusicStateListener = Lists.newArrayList();
72 private ServiceToken mToken;
75 * Play pause progress button
77 private PlayPauseProgressButton mPlayPauseProgressButton;
82 private TextView mTrackName;
87 private TextView mArtistName;
92 private ImageView mAlbumArt;
97 private PlaybackStatus mPlaybackStatus;
100 * Keeps track of the back button being used
102 private boolean mIsBackPressed = false;
108 protected void onCreate(final Bundle savedInstanceState) {
109 super.onCreate(savedInstanceState);
112 overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
114 // Control the media volume
115 setVolumeControlStream(AudioManager.STREAM_MUSIC);
117 // Bind Apollo's service
118 mToken = MusicUtils.bindToService(this, this);
120 // Initialize the broadcast receiver
121 mPlaybackStatus = new PlaybackStatus(this);
123 getActionBar().setTitle(getString(R.string.app_name_uppercase));
126 setContentView(setContentView());
128 // set the background on the root view
129 getWindow().getDecorView().getRootView().setBackgroundColor(
130 getResources().getColor(R.color.background_color));
132 // Initialze the bottom action bar
133 initBottomActionBar();
140 public void onServiceConnected(final ComponentName name, final IBinder service) {
141 mService = IElevenService.Stub.asInterface(service);
142 // Set the playback drawables
143 updatePlaybackControls();
152 public void onServiceDisconnected(final ComponentName name) {
160 public boolean onCreateOptionsMenu(final Menu menu) {
162 getMenuInflater().inflate(R.menu.search, menu);
164 getMenuInflater().inflate(R.menu.activity_base, menu);
166 final SearchView searchView = (SearchView)menu.findItem(R.id.menu_search).getActionView();
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() {
175 public boolean onQueryTextSubmit(final String query) {
176 // Open the search activity
177 NavUtils.openSearch(BaseActivity.this, query);
182 public boolean onQueryTextChange(final String newText) {
187 return super.onCreateOptionsMenu(menu);
194 public boolean onOptionsItemSelected(final MenuItem item) {
195 switch (item.getItemId()) {
196 case R.id.menu_settings:
198 NavUtils.openSettings(this);
204 return super.onOptionsItemSelected(item);
211 protected void onResume() {
213 // Set the playback drawables
214 updatePlaybackControls();
223 protected void onStart() {
225 final IntentFilter filter = new IntentFilter();
226 // Play and pause changes
227 filter.addAction(MusicPlaybackService.PLAYSTATE_CHANGED);
229 filter.addAction(MusicPlaybackService.META_CHANGED);
230 // Update a list, probably the playlist fragment's
231 filter.addAction(MusicPlaybackService.REFRESH);
232 registerReceiver(mPlaybackStatus, filter);
234 mPlayPauseProgressButton.resume();
236 MusicUtils.notifyForegroundStateChanged(this, true);
243 protected void onStop() {
246 mPlayPauseProgressButton.pause();
248 MusicUtils.notifyForegroundStateChanged(this, false);
255 protected void onDestroy() {
257 // Unbind from the service
258 if (mToken != null) {
259 MusicUtils.unbindFromService(mToken);
263 // Unregister the receiver
265 unregisterReceiver(mPlaybackStatus);
266 } catch (final Throwable e) {
270 // Remove any music status listeners
271 mMusicStateListener.clear();
278 public void onBackPressed() {
279 super.onBackPressed();
280 mIsBackPressed = true;
284 * Initializes the items in the bottom action bar.
286 private void initBottomActionBar() {
287 // Play and pause button
288 mPlayPauseProgressButton = (PlayPauseProgressButton)findViewById(R.id.playPauseProgressButton);
289 mPlayPauseProgressButton.enableAndShow();
292 mTrackName = (TextView)findViewById(R.id.bottom_action_bar_line_one);
294 mArtistName = (TextView)findViewById(R.id.bottom_action_bar_line_two);
296 mAlbumArt = (ImageView)findViewById(R.id.bottom_action_bar_album_art);
297 // Open to the currently playing album profile
298 mAlbumArt.setOnClickListener(mOpenCurrentAlbumProfile);
300 final LinearLayout bottomActionBar = (LinearLayout)findViewById(R.id.bottom_action_bar);
301 // Display the now playing screen or shuffle if this isn't anything
303 bottomActionBar.setOnClickListener(mOpenNowPlaying);
307 * Sets the track name, album name, and album art. This is protected to enable overriding
309 protected void updateMetaInfo() {
310 updateBottomActionBarInfo();
314 * Sets the track name, album name, and album art.
316 private void updateBottomActionBarInfo() {
317 // Set the track name
318 mTrackName.setText(MusicUtils.getTrackName());
319 // Set the artist name
320 mArtistName.setText(MusicUtils.getArtistName());
322 ApolloUtils.getImageFetcher(this).loadCurrentArtwork(mAlbumArt);
326 * Sets the correct drawable states for the playback controls.
328 private void updatePlaybackControls() {
329 // Set the play and pause image
330 mPlayPauseProgressButton.getPlayPauseButton().updateState();
334 * Opens the album profile of the currently playing album
336 private final View.OnClickListener mOpenCurrentAlbumProfile = new View.OnClickListener() {
342 public void onClick(final View v) {
343 if (MusicUtils.getCurrentAudioId() != -1) {
344 NavUtils.openAlbumProfile(BaseActivity.this, MusicUtils.getAlbumName(),
345 MusicUtils.getArtistName(), MusicUtils.getCurrentAlbumId());
347 MusicUtils.shuffleAll(BaseActivity.this);
349 if (BaseActivity.this instanceof ProfileActivity) {
356 * Opens the now playing screen
358 private final View.OnClickListener mOpenNowPlaying = new View.OnClickListener() {
364 public void onClick(final View v) {
365 if (MusicUtils.getCurrentAudioId() != -1) {
366 NavUtils.openAudioPlayer(BaseActivity.this);
368 MusicUtils.shuffleAll(BaseActivity.this);
374 * Used to monitor the state of playback
376 private final static class PlaybackStatus extends BroadcastReceiver {
378 private final WeakReference<BaseActivity> mReference;
381 * Constructor of <code>PlaybackStatus</code>
383 public PlaybackStatus(final BaseActivity activity) {
384 mReference = new WeakReference<BaseActivity>(activity);
391 public void onReceive(final Context context, final Intent intent) {
392 final String action = intent.getAction();
393 if (action.equals(MusicPlaybackService.META_CHANGED)) {
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();
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();
417 * @param status The {@link MusicStateListener} to use
419 public void setMusicStateListenerListener(final MusicStateListener status) {
420 if (status != null) {
421 mMusicStateListener.add(status);
426 * @return The resource ID to be inflated.
428 public abstract int setContentView();