# HG changeset patch # User kshalle # Date 1429811634 25200 # Node ID 3485a304a057cdd642362a6f0803235678cb0e08 # Parent bae640f518e491fa09913b6059bf58dbf44e1efd adding new branch with the original tutorial code -- later merge to main and mod diff -r bae640f518e4 -r 3485a304a057 .gitignore --- a/.gitignore Mon Apr 20 17:11:10 2015 +0300 +++ b/.gitignore Thu Apr 23 10:53:54 2015 -0700 @@ -1,6 +1,15 @@ .gradle +*.gradle +*.iml +gradle.* +gradle* +/gradle +/.gradle /local.properties +.idea +/.idea /.idea/workspace.xml /.idea/libraries .DS_Store /build + diff -r bae640f518e4 -r 3485a304a057 app/src/androidTest/java/com/example/friendstream/friendstream/ApplicationTest.java --- a/app/src/androidTest/java/com/example/friendstream/friendstream/ApplicationTest.java Mon Apr 20 17:11:10 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -package com.example.friendstream.friendstream; - -import android.app.Application; -import android.test.ApplicationTestCase; - -/** - * Testing Fundamentals - */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); - } -} \ No newline at end of file diff -r bae640f518e4 -r 3485a304a057 app/src/androidTest/java/com/example/musicplayer/ApplicationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/androidTest/java/com/example/musicplayer/ApplicationTest.java Thu Apr 23 10:53:54 2015 -0700 @@ -0,0 +1,13 @@ +package com.example.musicplayer; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff -r bae640f518e4 -r 3485a304a057 app/src/main/AndroidManifest.xml --- a/app/src/main/AndroidManifest.xml Mon Apr 20 17:11:10 2015 +0300 +++ b/app/src/main/AndroidManifest.xml Thu Apr 23 10:53:54 2015 -0700 @@ -1,18 +1,14 @@ + package="com.example.musicplayer" > - - - - @@ -22,12 +18,6 @@ - - - diff -r bae640f518e4 -r 3485a304a057 app/src/main/java/com/example/friendstream/friendstream/MusicService.java --- a/app/src/main/java/com/example/friendstream/friendstream/MusicService.java Mon Apr 20 17:11:10 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/* -Made from tutorial: -http://code.tutsplus.com/tutorials/create-a-music-player-on-android-song-playback--mobile-22778 - */ - - -package com.example.friendstream.friendstream; - -import android.app.Service; -import android.content.ContentUris; -import android.content.Intent; -import android.media.MediaPlayer; -import android.net.Uri; -import android.os.IBinder; -import java.util.ArrayList; - -import android.media.AudioManager; -import android.os.Binder; -import android.os.PowerManager; -import android.util.Log; - -/* -Add a Service to the app, which will bind to the song picking activity, and will be what causes - the audio to begin playing -Make sure the class name matches what is listed in the Manifest. - */ -public class MusicService extends Service implements - MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, - MediaPlayer.OnCompletionListener { - - // Activity will pass in a list of songPlayList, and will play each using the MediaPlayer class - private MediaPlayer mediaPlayerInst; - - // song list - private ArrayList songPlayList; - - // position within list of song currently playing in the MediaPlayer - private int songPosnInList; - - //This is used to connect an instance of this service to Activities that use it - private final IBinder musicBinderInst = new MusicBinder(); - - public MusicService() { - } - -//============== Setup and Connect (bind) ============= - public void onCreate(){ - //create the service - super.onCreate(); - - //initialize position - songPosnInList =0; - - //create mediaPlayerInst, which is a singleton, that is prepared for each song, then - // makes the audio for that song happen - mediaPlayerInst = new MediaPlayer(); - initMusicPlayer(); - } - - public void initMusicPlayer(){ - //set mediaPlayerInst properties - mediaPlayerInst.setWakeMode(getApplicationContext(), - PowerManager.PARTIAL_WAKE_LOCK); - mediaPlayerInst.setAudioStreamType(AudioManager.STREAM_MUSIC); - mediaPlayerInst.setOnPreparedListener(this); - mediaPlayerInst.setOnCompletionListener(this); - mediaPlayerInst.setOnErrorListener(this); - } - - //Inner class, an instance of which is created as part of connecting Activity to this Service - public class MusicBinder extends Binder { - MusicService getService() { - return MusicService.this; - } - } - - @Override - public IBinder onBind(Intent intent) { - return musicBinderInst; //the instance of MusicBinder created as instance var above - } - @Override - public boolean onUnbind(Intent intent){ - mediaPlayerInst.stop(); - mediaPlayerInst.release(); - return false; - } - -//========================================== - - public void setList(ArrayList theSongs){ - songPlayList =theSongs; - } - - public void setSong(int songIndex){ - songPosnInList =songIndex; - } - - public void playSong(){ - //play a song - mediaPlayerInst.reset(); - - //get the song from the list, extract the ID for it using its Song object, and cast as a URI - //get song - Song playSong = songPlayList.get(songPosnInList); - - //get id - long currSong = playSong.getID(); - - //set uri - Uri trackUri = ContentUris.withAppendedId( - android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, - currSong); - - //set this URI as the data source for the MediaPlayer instance, - try{ - mediaPlayerInst.setDataSource(getApplicationContext(), trackUri); - } - catch(Exception e){ - Log.e("MUSIC SERVICE", "Error setting data source", e); - } - - //trigger the MediaPlayer to set itself up, open the songfile, and be ready to start playing - // when done with all that, will call back to this object's "onPrepared" - mediaPlayerInst.prepareAsync(); - } - - @Override - public void onPrepared(MediaPlayer preparedMediaPlayer) { - //start playback - preparedMediaPlayer.start(); - } -} diff -r bae640f518e4 -r 3485a304a057 app/src/main/java/com/example/friendstream/friendstream/PickingSongs.java --- a/app/src/main/java/com/example/friendstream/friendstream/PickingSongs.java Mon Apr 20 17:11:10 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,245 +0,0 @@ -/* -Based on these tutorials: -http://code.tutsplus.com/tutorials/create-a-music-player-on-android-project-setup--mobile-22764 - */ - -package com.example.friendstream.friendstream; - -import com.example.friendstream.friendstream.util.SystemUiHider; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.view.MotionEvent; -import android.view.View; -import android.os.IBinder; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.view.MenuItem; -import android.view.View; -import com.example.friendstream.friendstream.MusicService.MusicBinder; - - -/** - * An example full-screen activity that shows and hides the system UI (i.e. - * status bar and navigation/system bar) with user interaction. - * - * @see SystemUiHider - */ -public class PickingSongs extends Activity { - /** - * Whether or not the system UI should be auto-hidden after - * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds. - */ - private static final boolean AUTO_HIDE = true; - - /** - * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after - * user interaction before hiding the system UI. - */ - private static final int AUTO_HIDE_DELAY_MILLIS = 3000; - - /** - * If set, will toggle the system UI visibility upon interaction. Otherwise, - * will show the system UI visibility upon interaction. - */ - private static final boolean TOGGLE_ON_CLICK = true; - - /** - * The flags to pass to {@link SystemUiHider#getInstance}. - */ - private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION; - - /** - * The instance of the {@link SystemUiHider} for this activity. - */ - private SystemUiHider mSystemUiHider; - - private MusicService musicSrv; - private Intent playIntent; - private boolean musicBound=false; - - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.activity_picking_songs); - - final View controlsView = findViewById(R.id.fullscreen_content_controls); - final View contentView = findViewById(R.id.fullscreen_content); - - // Set up an instance of SystemUiHider to control the system UI for - // this activity. - mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS); - mSystemUiHider.setup(); - mSystemUiHider - .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() { - // Cached values. - int mControlsHeight; - int mShortAnimTime; - - @Override - @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) - public void onVisibilityChange(boolean visible) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { - // If the ViewPropertyAnimator API is available - // (Honeycomb MR2 and later), use it to animate the - // in-layout UI controls at the bottom of the - // screen. - if (mControlsHeight == 0) { - mControlsHeight = controlsView.getHeight(); - } - if (mShortAnimTime == 0) { - mShortAnimTime = getResources().getInteger( - android.R.integer.config_shortAnimTime); - } - controlsView.animate() - .translationY(visible ? 0 : mControlsHeight) - .setDuration(mShortAnimTime); - } else { - // If the ViewPropertyAnimator APIs aren't - // available, simply show or hide the in-layout UI - // controls. - controlsView.setVisibility(visible ? View.VISIBLE : View.GONE); - } - - if (visible && AUTO_HIDE) { - // Schedule a hide(). - delayedHide(AUTO_HIDE_DELAY_MILLIS); - } - } - }); - - // Set up the user interaction to manually show or hide the system UI. - contentView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (TOGGLE_ON_CLICK) { - mSystemUiHider.toggle(); - } else { - mSystemUiHider.show(); - } - } - }); - - // Upon interacting with UI controls, delay any scheduled hide() - // operations to prevent the jarring behavior of controls going away - // while interacting with the UI. - findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener); - } - - // This Activity controls the Service that makes the audio of a playlist happen. - // Bind this Activity to the Service class, using an anonymous Intent class - // The callback methods essentially inform the Activity instance of when it is connected - // to the Service instance. The callback sets a reference to the Service (which it gets via - // the MusicBinder instance inside the Service) and a flag. - // The bind process is what calls the onServiceConnected.. the whole MusicBinder thing looks - // pretty messed up.. these guys twist their brains in bizarre ways sometimes.. - private ServiceConnection musicConnection = new ServiceConnection(){ - - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - MusicBinder binder = (MusicBinder)service; - //get service - musicSrv = binder.getService(); - //pass list - musicSrv.setList(songList); - musicBound = true; - } - - @Override - public void onServiceDisconnected(ComponentName name) { - musicBound = false; - } - }; - - // added an onClick attribute to the layout for each item in the song list.. calls this.. - public void songPicked(View view){ - musicSrv.setSong(Integer.parseInt(view.getTag().toString())); - musicSrv.playSong(); - } - - - // implement the end button we added to the main menu - @Override - public boolean onOptionsItemSelected(MenuItem item) { - //menu item selected - switch (item.getItemId()) { - case R.id.action_shuffle: - //shuffle - break; - case R.id.action_end: - stopService(playIntent); - musicSrv=null; - System.exit(0); - break; - } - return super.onOptionsItemSelected(item); - } - - @Override - protected void onDestroy() { - stopService(playIntent); - musicSrv=null; - super.onDestroy(); - } - - @Override - protected void onStart() { - super.onStart(); - if( playIntent==null ){ - playIntent = new Intent(this, MusicService.class); - bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE); - startService(playIntent); - } - } - - - @Override - protected void onPostCreate(Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - - // Trigger the initial hide() shortly after the activity has been - // created, to briefly hint to the user that UI controls - // are available. - delayedHide(100); - } - - - /** - * Touch listener to use for in-layout UI controls to delay hiding the - * system UI. This is to prevent the jarring behavior of controls going away - * while interacting with activity UI. - */ - View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() { - @Override - public boolean onTouch(View view, MotionEvent motionEvent) { - if (AUTO_HIDE) { - delayedHide(AUTO_HIDE_DELAY_MILLIS); - } - return false; - } - }; - - Handler mHideHandler = new Handler(); - Runnable mHideRunnable = new Runnable() { - @Override - public void run() { - mSystemUiHider.hide(); - } - }; - - /** - * Schedules a call to hide() in [delay] milliseconds, canceling any - * previously scheduled calls. - */ - private void delayedHide(int delayMillis) { - mHideHandler.removeCallbacks(mHideRunnable); - mHideHandler.postDelayed(mHideRunnable, delayMillis); - } -} diff -r bae640f518e4 -r 3485a304a057 app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHider.java --- a/app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHider.java Mon Apr 20 17:11:10 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,172 +0,0 @@ -package com.example.friendstream.friendstream.util; - -import android.app.Activity; -import android.os.Build; -import android.view.View; - -/** - * A utility class that helps with showing and hiding system UI such as the - * status bar and navigation/system bar. This class uses backward-compatibility - * techniques described in - * Creating Backward-Compatible UIs to ensure that devices running any - * version of ndroid OS are supported. More specifically, there are separate - * implementations of this abstract class: for newer devices, - * {@link #getInstance} will return a {@link SystemUiHiderHoneycomb} instance, - * while on older devices {@link #getInstance} will return a - * {@link SystemUiHiderBase} instance. - *

- * For more on system bars, see System Bars. - * - * @see android.view.View#setSystemUiVisibility(int) - * @see android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN - */ -public abstract class SystemUiHider { - /** - * When this flag is set, the - * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN} - * flag will be set on older devices, making the status bar "float" on top - * of the activity layout. This is most useful when there are no controls at - * the top of the activity layout. - *

- * This flag isn't used on newer devices because the action - * bar, the most important structural element of an Android app, should - * be visible and not obscured by the system UI. - */ - public static final int FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES = 0x1; - - /** - * When this flag is set, {@link #show()} and {@link #hide()} will toggle - * the visibility of the status bar. If there is a navigation bar, show and - * hide will toggle low profile mode. - */ - public static final int FLAG_FULLSCREEN = 0x2; - - /** - * When this flag is set, {@link #show()} and {@link #hide()} will toggle - * the visibility of the navigation bar, if it's present on the device and - * the device allows hiding it. In cases where the navigation bar is present - * but cannot be hidden, show and hide will toggle low profile mode. - */ - public static final int FLAG_HIDE_NAVIGATION = FLAG_FULLSCREEN | 0x4; - - /** - * The activity associated with this UI hider object. - */ - protected Activity mActivity; - - /** - * The view on which {@link View#setSystemUiVisibility(int)} will be called. - */ - protected View mAnchorView; - - /** - * The current UI hider flags. - * - * @see #FLAG_FULLSCREEN - * @see #FLAG_HIDE_NAVIGATION - * @see #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES - */ - protected int mFlags; - - /** - * The current visibility callback. - */ - protected OnVisibilityChangeListener mOnVisibilityChangeListener = sDummyListener; - - /** - * Creates and returns an instance of {@link SystemUiHider} that is - * appropriate for this device. The object will be either a - * {@link SystemUiHiderBase} or {@link SystemUiHiderHoneycomb} depending on - * the device. - * - * @param activity The activity whose window's system UI should be - * controlled by this class. - * @param anchorView The view on which - * {@link View#setSystemUiVisibility(int)} will be called. - * @param flags Either 0 or any combination of {@link #FLAG_FULLSCREEN}, - * {@link #FLAG_HIDE_NAVIGATION}, and - * {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES}. - */ - public static SystemUiHider getInstance(Activity activity, View anchorView, int flags) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - return new SystemUiHiderHoneycomb(activity, anchorView, flags); - } else { - return new SystemUiHiderBase(activity, anchorView, flags); - } - } - - protected SystemUiHider(Activity activity, View anchorView, int flags) { - mActivity = activity; - mAnchorView = anchorView; - mFlags = flags; - } - - /** - * Sets up the system UI hider. Should be called from - * {@link Activity#onCreate}. - */ - public abstract void setup(); - - /** - * Returns whether or not the system UI is visible. - */ - public abstract boolean isVisible(); - - /** - * Hide the system UI. - */ - public abstract void hide(); - - /** - * Show the system UI. - */ - public abstract void show(); - - /** - * Toggle the visibility of the system UI. - */ - public void toggle() { - if (isVisible()) { - hide(); - } else { - show(); - } - } - - /** - * Registers a callback, to be triggered when the system UI visibility - * changes. - */ - public void setOnVisibilityChangeListener(OnVisibilityChangeListener listener) { - if (listener == null) { - listener = sDummyListener; - } - - mOnVisibilityChangeListener = listener; - } - - /** - * A dummy no-op callback for use when there is no other listener set. - */ - private static OnVisibilityChangeListener sDummyListener = new OnVisibilityChangeListener() { - @Override - public void onVisibilityChange(boolean visible) { - } - }; - - /** - * A callback interface used to listen for system UI visibility changes. - */ - public interface OnVisibilityChangeListener { - /** - * Called when the system UI visibility has changed. - * - * @param visible True if the system UI is visible. - */ - public void onVisibilityChange(boolean visible); - } -} diff -r bae640f518e4 -r 3485a304a057 app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHiderBase.java --- a/app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHiderBase.java Mon Apr 20 17:11:10 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -package com.example.friendstream.friendstream.util; - -import android.app.Activity; -import android.view.View; -import android.view.WindowManager; - -/** - * A base implementation of {@link SystemUiHider}. Uses APIs available in all - * API levels to show and hide the status bar. - */ -public class SystemUiHiderBase extends SystemUiHider { - /** - * Whether or not the system UI is currently visible. This is a cached value - * from calls to {@link #hide()} and {@link #show()}. - */ - private boolean mVisible = true; - - /** - * Constructor not intended to be called by clients. Use - * {@link SystemUiHider#getInstance} to obtain an instance. - */ - protected SystemUiHiderBase(Activity activity, View anchorView, int flags) { - super(activity, anchorView, flags); - } - - @Override - public void setup() { - if ((mFlags & FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES) == 0) { - mActivity.getWindow().setFlags( - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, - WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); - } - } - - @Override - public boolean isVisible() { - return mVisible; - } - - @Override - public void hide() { - if ((mFlags & FLAG_FULLSCREEN) != 0) { - mActivity.getWindow().setFlags( - WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - mOnVisibilityChangeListener.onVisibilityChange(false); - mVisible = false; - } - - @Override - public void show() { - if ((mFlags & FLAG_FULLSCREEN) != 0) { - mActivity.getWindow().setFlags( - 0, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - mOnVisibilityChangeListener.onVisibilityChange(true); - mVisible = true; - } -} diff -r bae640f518e4 -r 3485a304a057 app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHiderHoneycomb.java --- a/app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHiderHoneycomb.java Mon Apr 20 17:11:10 2015 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -package com.example.friendstream.friendstream.util; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.os.Build; -import android.view.View; -import android.view.WindowManager; - -/** - * An API 11+ implementation of {@link SystemUiHider}. Uses APIs available in - * Honeycomb and later (specifically {@link View#setSystemUiVisibility(int)}) to - * show and hide the system UI. - */ -@TargetApi(Build.VERSION_CODES.HONEYCOMB) -public class SystemUiHiderHoneycomb extends SystemUiHiderBase { - /** - * Flags for {@link View#setSystemUiVisibility(int)} to use when showing the - * system UI. - */ - private int mShowFlags; - - /** - * Flags for {@link View#setSystemUiVisibility(int)} to use when hiding the - * system UI. - */ - private int mHideFlags; - - /** - * Flags to test against the first parameter in - * {@link android.view.View.OnSystemUiVisibilityChangeListener#onSystemUiVisibilityChange(int)} - * to determine the system UI visibility state. - */ - private int mTestFlags; - - /** - * Whether or not the system UI is currently visible. This is cached from - * {@link android.view.View.OnSystemUiVisibilityChangeListener}. - */ - private boolean mVisible = true; - - /** - * Constructor not intended to be called by clients. Use - * {@link SystemUiHider#getInstance} to obtain an instance. - */ - protected SystemUiHiderHoneycomb(Activity activity, View anchorView, int flags) { - super(activity, anchorView, flags); - - mShowFlags = View.SYSTEM_UI_FLAG_VISIBLE; - mHideFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE; - mTestFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE; - - if ((mFlags & FLAG_FULLSCREEN) != 0) { - // If the client requested fullscreen, add flags relevant to hiding - // the status bar. Note that some of these constants are new as of - // API 16 (Jelly Bean). It is safe to use them, as they are inlined - // at compile-time and do nothing on pre-Jelly Bean devices. - mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_FULLSCREEN; - } - - if ((mFlags & FLAG_HIDE_NAVIGATION) != 0) { - // If the client requested hiding navigation, add relevant flags. - mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; - mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - mTestFlags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - } - } - - /** - * {@inheritDoc} - */ - @Override - public void setup() { - mAnchorView.setOnSystemUiVisibilityChangeListener(mSystemUiVisibilityChangeListener); - } - - /** - * {@inheritDoc} - */ - @Override - public void hide() { - mAnchorView.setSystemUiVisibility(mHideFlags); - } - - /** - * {@inheritDoc} - */ - @Override - public void show() { - mAnchorView.setSystemUiVisibility(mShowFlags); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isVisible() { - return mVisible; - } - - private View.OnSystemUiVisibilityChangeListener mSystemUiVisibilityChangeListener - = new View.OnSystemUiVisibilityChangeListener() { - @Override - public void onSystemUiVisibilityChange(int vis) { - // Test against mTestFlags to see if the system UI is visible. - if ((vis & mTestFlags) != 0) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - // Pre-Jelly Bean, we must manually hide the action bar - // and use the old window flags API. - mActivity.getActionBar().hide(); - mActivity.getWindow().setFlags( - WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - - // Trigger the registered listener and cache the visibility - // state. - mOnVisibilityChangeListener.onVisibilityChange(false); - mVisible = false; - - } else { - mAnchorView.setSystemUiVisibility(mShowFlags); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - // Pre-Jelly Bean, we must manually show the action bar - // and use the old window flags API. - mActivity.getActionBar().show(); - mActivity.getWindow().setFlags( - 0, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - - // Trigger the registered listener and cache the visibility - // state. - mOnVisibilityChangeListener.onVisibilityChange(true); - mVisible = true; - } - } - }; -} diff -r bae640f518e4 -r 3485a304a057 app/src/main/java/com/example/musicplayer/MainActivity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/example/musicplayer/MainActivity.java Thu Apr 23 10:53:54 2015 -0700 @@ -0,0 +1,160 @@ +package com.example.musicplayer; + +import com.example.musicplayer.util.SystemUiHider; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.view.MotionEvent; +import android.view.View; + + +/** + * An example full-screen activity that shows and hides the system UI (i.e. + * status bar and navigation/system bar) with user interaction. + * + * @see SystemUiHider + */ +public class MainActivity extends Activity { + /** + * Whether or not the system UI should be auto-hidden after + * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds. + */ + private static final boolean AUTO_HIDE = true; + + /** + * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after + * user interaction before hiding the system UI. + */ + private static final int AUTO_HIDE_DELAY_MILLIS = 3000; + + /** + * If set, will toggle the system UI visibility upon interaction. Otherwise, + * will show the system UI visibility upon interaction. + */ + private static final boolean TOGGLE_ON_CLICK = true; + + /** + * The flags to pass to {@link SystemUiHider#getInstance}. + */ + private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION; + + /** + * The instance of the {@link SystemUiHider} for this activity. + */ + private SystemUiHider mSystemUiHider; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_main); + + final View controlsView = findViewById(R.id.fullscreen_content_controls); + final View contentView = findViewById(R.id.fullscreen_content); + + // Set up an instance of SystemUiHider to control the system UI for + // this activity. + mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS); + mSystemUiHider.setup(); + mSystemUiHider + .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() { + // Cached values. + int mControlsHeight; + int mShortAnimTime; + + @Override + @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) + public void onVisibilityChange(boolean visible) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { + // If the ViewPropertyAnimator API is available + // (Honeycomb MR2 and later), use it to animate the + // in-layout UI controls at the bottom of the + // screen. + if (mControlsHeight == 0) { + mControlsHeight = controlsView.getHeight(); + } + if (mShortAnimTime == 0) { + mShortAnimTime = getResources().getInteger( + android.R.integer.config_shortAnimTime); + } + controlsView.animate() + .translationY(visible ? 0 : mControlsHeight) + .setDuration(mShortAnimTime); + } else { + // If the ViewPropertyAnimator APIs aren't + // available, simply show or hide the in-layout UI + // controls. + controlsView.setVisibility(visible ? View.VISIBLE : View.GONE); + } + + if (visible && AUTO_HIDE) { + // Schedule a hide(). + delayedHide(AUTO_HIDE_DELAY_MILLIS); + } + } + }); + + // Set up the user interaction to manually show or hide the system UI. + contentView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (TOGGLE_ON_CLICK) { + mSystemUiHider.toggle(); + } else { + mSystemUiHider.show(); + } + } + }); + + // Upon interacting with UI controls, delay any scheduled hide() + // operations to prevent the jarring behavior of controls going away + // while interacting with the UI. + findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + + // Trigger the initial hide() shortly after the activity has been + // created, to briefly hint to the user that UI controls + // are available. + delayedHide(100); + } + + + /** + * Touch listener to use for in-layout UI controls to delay hiding the + * system UI. This is to prevent the jarring behavior of controls going away + * while interacting with activity UI. + */ + View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + if (AUTO_HIDE) { + delayedHide(AUTO_HIDE_DELAY_MILLIS); + } + return false; + } + }; + + Handler mHideHandler = new Handler(); + Runnable mHideRunnable = new Runnable() { + @Override + public void run() { + mSystemUiHider.hide(); + } + }; + + /** + * Schedules a call to hide() in [delay] milliseconds, canceling any + * previously scheduled calls. + */ + private void delayedHide(int delayMillis) { + mHideHandler.removeCallbacks(mHideRunnable); + mHideHandler.postDelayed(mHideRunnable, delayMillis); + } +} diff -r bae640f518e4 -r 3485a304a057 app/src/main/java/com/example/musicplayer/util/SystemUiHider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/example/musicplayer/util/SystemUiHider.java Thu Apr 23 10:53:54 2015 -0700 @@ -0,0 +1,172 @@ +package com.example.musicplayer.util; + +import android.app.Activity; +import android.os.Build; +import android.view.View; + +/** + * A utility class that helps with showing and hiding system UI such as the + * status bar and navigation/system bar. This class uses backward-compatibility + * techniques described in + * Creating Backward-Compatible UIs to ensure that devices running any + * version of ndroid OS are supported. More specifically, there are separate + * implementations of this abstract class: for newer devices, + * {@link #getInstance} will return a {@link SystemUiHiderHoneycomb} instance, + * while on older devices {@link #getInstance} will return a + * {@link SystemUiHiderBase} instance. + *

+ * For more on system bars, see System Bars. + * + * @see android.view.View#setSystemUiVisibility(int) + * @see android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN + */ +public abstract class SystemUiHider { + /** + * When this flag is set, the + * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN} + * flag will be set on older devices, making the status bar "float" on top + * of the activity layout. This is most useful when there are no controls at + * the top of the activity layout. + *

+ * This flag isn't used on newer devices because the action + * bar, the most important structural element of an Android app, should + * be visible and not obscured by the system UI. + */ + public static final int FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES = 0x1; + + /** + * When this flag is set, {@link #show()} and {@link #hide()} will toggle + * the visibility of the status bar. If there is a navigation bar, show and + * hide will toggle low profile mode. + */ + public static final int FLAG_FULLSCREEN = 0x2; + + /** + * When this flag is set, {@link #show()} and {@link #hide()} will toggle + * the visibility of the navigation bar, if it's present on the device and + * the device allows hiding it. In cases where the navigation bar is present + * but cannot be hidden, show and hide will toggle low profile mode. + */ + public static final int FLAG_HIDE_NAVIGATION = FLAG_FULLSCREEN | 0x4; + + /** + * The activity associated with this UI hider object. + */ + protected Activity mActivity; + + /** + * The view on which {@link View#setSystemUiVisibility(int)} will be called. + */ + protected View mAnchorView; + + /** + * The current UI hider flags. + * + * @see #FLAG_FULLSCREEN + * @see #FLAG_HIDE_NAVIGATION + * @see #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES + */ + protected int mFlags; + + /** + * The current visibility callback. + */ + protected OnVisibilityChangeListener mOnVisibilityChangeListener = sDummyListener; + + /** + * Creates and returns an instance of {@link SystemUiHider} that is + * appropriate for this device. The object will be either a + * {@link SystemUiHiderBase} or {@link SystemUiHiderHoneycomb} depending on + * the device. + * + * @param activity The activity whose window's system UI should be + * controlled by this class. + * @param anchorView The view on which + * {@link View#setSystemUiVisibility(int)} will be called. + * @param flags Either 0 or any combination of {@link #FLAG_FULLSCREEN}, + * {@link #FLAG_HIDE_NAVIGATION}, and + * {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES}. + */ + public static SystemUiHider getInstance(Activity activity, View anchorView, int flags) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + return new SystemUiHiderHoneycomb(activity, anchorView, flags); + } else { + return new SystemUiHiderBase(activity, anchorView, flags); + } + } + + protected SystemUiHider(Activity activity, View anchorView, int flags) { + mActivity = activity; + mAnchorView = anchorView; + mFlags = flags; + } + + /** + * Sets up the system UI hider. Should be called from + * {@link Activity#onCreate}. + */ + public abstract void setup(); + + /** + * Returns whether or not the system UI is visible. + */ + public abstract boolean isVisible(); + + /** + * Hide the system UI. + */ + public abstract void hide(); + + /** + * Show the system UI. + */ + public abstract void show(); + + /** + * Toggle the visibility of the system UI. + */ + public void toggle() { + if (isVisible()) { + hide(); + } else { + show(); + } + } + + /** + * Registers a callback, to be triggered when the system UI visibility + * changes. + */ + public void setOnVisibilityChangeListener(OnVisibilityChangeListener listener) { + if (listener == null) { + listener = sDummyListener; + } + + mOnVisibilityChangeListener = listener; + } + + /** + * A dummy no-op callback for use when there is no other listener set. + */ + private static OnVisibilityChangeListener sDummyListener = new OnVisibilityChangeListener() { + @Override + public void onVisibilityChange(boolean visible) { + } + }; + + /** + * A callback interface used to listen for system UI visibility changes. + */ + public interface OnVisibilityChangeListener { + /** + * Called when the system UI visibility has changed. + * + * @param visible True if the system UI is visible. + */ + public void onVisibilityChange(boolean visible); + } +} diff -r bae640f518e4 -r 3485a304a057 app/src/main/java/com/example/musicplayer/util/SystemUiHiderBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/example/musicplayer/util/SystemUiHiderBase.java Thu Apr 23 10:53:54 2015 -0700 @@ -0,0 +1,63 @@ +package com.example.musicplayer.util; + +import android.app.Activity; +import android.view.View; +import android.view.WindowManager; + +/** + * A base implementation of {@link SystemUiHider}. Uses APIs available in all + * API levels to show and hide the status bar. + */ +public class SystemUiHiderBase extends SystemUiHider { + /** + * Whether or not the system UI is currently visible. This is a cached value + * from calls to {@link #hide()} and {@link #show()}. + */ + private boolean mVisible = true; + + /** + * Constructor not intended to be called by clients. Use + * {@link SystemUiHider#getInstance} to obtain an instance. + */ + protected SystemUiHiderBase(Activity activity, View anchorView, int flags) { + super(activity, anchorView, flags); + } + + @Override + public void setup() { + if ((mFlags & FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES) == 0) { + mActivity.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, + WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); + } + } + + @Override + public boolean isVisible() { + return mVisible; + } + + @Override + public void hide() { + if ((mFlags & FLAG_FULLSCREEN) != 0) { + mActivity.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + mOnVisibilityChangeListener.onVisibilityChange(false); + mVisible = false; + } + + @Override + public void show() { + if ((mFlags & FLAG_FULLSCREEN) != 0) { + mActivity.getWindow().setFlags( + 0, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + mOnVisibilityChangeListener.onVisibilityChange(true); + mVisible = true; + } +} diff -r bae640f518e4 -r 3485a304a057 app/src/main/java/com/example/musicplayer/util/SystemUiHiderHoneycomb.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/com/example/musicplayer/util/SystemUiHiderHoneycomb.java Thu Apr 23 10:53:54 2015 -0700 @@ -0,0 +1,141 @@ +package com.example.musicplayer.util; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.os.Build; +import android.view.View; +import android.view.WindowManager; + +/** + * An API 11+ implementation of {@link SystemUiHider}. Uses APIs available in + * Honeycomb and later (specifically {@link View#setSystemUiVisibility(int)}) to + * show and hide the system UI. + */ +@TargetApi(Build.VERSION_CODES.HONEYCOMB) +public class SystemUiHiderHoneycomb extends SystemUiHiderBase { + /** + * Flags for {@link View#setSystemUiVisibility(int)} to use when showing the + * system UI. + */ + private int mShowFlags; + + /** + * Flags for {@link View#setSystemUiVisibility(int)} to use when hiding the + * system UI. + */ + private int mHideFlags; + + /** + * Flags to test against the first parameter in + * {@link android.view.View.OnSystemUiVisibilityChangeListener#onSystemUiVisibilityChange(int)} + * to determine the system UI visibility state. + */ + private int mTestFlags; + + /** + * Whether or not the system UI is currently visible. This is cached from + * {@link android.view.View.OnSystemUiVisibilityChangeListener}. + */ + private boolean mVisible = true; + + /** + * Constructor not intended to be called by clients. Use + * {@link SystemUiHider#getInstance} to obtain an instance. + */ + protected SystemUiHiderHoneycomb(Activity activity, View anchorView, int flags) { + super(activity, anchorView, flags); + + mShowFlags = View.SYSTEM_UI_FLAG_VISIBLE; + mHideFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE; + mTestFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE; + + if ((mFlags & FLAG_FULLSCREEN) != 0) { + // If the client requested fullscreen, add flags relevant to hiding + // the status bar. Note that some of these constants are new as of + // API 16 (Jelly Bean). It is safe to use them, as they are inlined + // at compile-time and do nothing on pre-Jelly Bean devices. + mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_FULLSCREEN; + } + + if ((mFlags & FLAG_HIDE_NAVIGATION) != 0) { + // If the client requested hiding navigation, add relevant flags. + mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + mTestFlags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void setup() { + mAnchorView.setOnSystemUiVisibilityChangeListener(mSystemUiVisibilityChangeListener); + } + + /** + * {@inheritDoc} + */ + @Override + public void hide() { + mAnchorView.setSystemUiVisibility(mHideFlags); + } + + /** + * {@inheritDoc} + */ + @Override + public void show() { + mAnchorView.setSystemUiVisibility(mShowFlags); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isVisible() { + return mVisible; + } + + private View.OnSystemUiVisibilityChangeListener mSystemUiVisibilityChangeListener + = new View.OnSystemUiVisibilityChangeListener() { + @Override + public void onSystemUiVisibilityChange(int vis) { + // Test against mTestFlags to see if the system UI is visible. + if ((vis & mTestFlags) != 0) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { + // Pre-Jelly Bean, we must manually hide the action bar + // and use the old window flags API. + mActivity.getActionBar().hide(); + mActivity.getWindow().setFlags( + WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + // Trigger the registered listener and cache the visibility + // state. + mOnVisibilityChangeListener.onVisibilityChange(false); + mVisible = false; + + } else { + mAnchorView.setSystemUiVisibility(mShowFlags); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { + // Pre-Jelly Bean, we must manually show the action bar + // and use the old window flags API. + mActivity.getActionBar().show(); + mActivity.getWindow().setFlags( + 0, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + } + + // Trigger the registered listener and cache the visibility + // state. + mOnVisibilityChangeListener.onVisibilityChange(true); + mVisible = true; + } + } + }; +} diff -r bae640f518e4 -r 3485a304a057 app/src/main/res/layout/activity_main.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/res/layout/activity_main.xml Thu Apr 23 10:53:54 2015 -0700 @@ -0,0 +1,31 @@ + + + + + + + + + + +