changeset 2:3485a304a057 origTutorial tip

adding new branch with the original tutorial code -- later merge to main and mod
author kshalle
date Thu, 23 Apr 2015 10:53:54 -0700
parents bae640f518e4
children
files .gitignore app/src/androidTest/java/com/example/friendstream/friendstream/ApplicationTest.java app/src/androidTest/java/com/example/musicplayer/ApplicationTest.java app/src/main/AndroidManifest.xml app/src/main/java/com/example/friendstream/friendstream/MusicService.java app/src/main/java/com/example/friendstream/friendstream/PickingSongs.java app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHider.java app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHiderBase.java app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHiderHoneycomb.java app/src/main/java/com/example/musicplayer/MainActivity.java app/src/main/java/com/example/musicplayer/util/SystemUiHider.java app/src/main/java/com/example/musicplayer/util/SystemUiHiderBase.java app/src/main/java/com/example/musicplayer/util/SystemUiHiderHoneycomb.java app/src/main/res/layout/activity_main.xml app/src/main/res/layout/activity_picking_songs.xml app/src/main/res/values/strings.xml
diffstat 16 files changed, 592 insertions(+), 810 deletions(-) [+]
line diff
     1.1 --- a/.gitignore	Mon Apr 20 17:11:10 2015 +0300
     1.2 +++ b/.gitignore	Thu Apr 23 10:53:54 2015 -0700
     1.3 @@ -1,6 +1,15 @@
     1.4  .gradle
     1.5 +*.gradle
     1.6 +*.iml
     1.7 +gradle.*
     1.8 +gradle*
     1.9 +/gradle
    1.10 +/.gradle
    1.11  /local.properties
    1.12 +.idea
    1.13 +/.idea
    1.14  /.idea/workspace.xml
    1.15  /.idea/libraries
    1.16  .DS_Store
    1.17  /build
    1.18 +
     2.1 --- a/app/src/androidTest/java/com/example/friendstream/friendstream/ApplicationTest.java	Mon Apr 20 17:11:10 2015 +0300
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,13 +0,0 @@
     2.4 -package com.example.friendstream.friendstream;
     2.5 -
     2.6 -import android.app.Application;
     2.7 -import android.test.ApplicationTestCase;
     2.8 -
     2.9 -/**
    2.10 - * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
    2.11 - */
    2.12 -public class ApplicationTest extends ApplicationTestCase<Application> {
    2.13 -    public ApplicationTest() {
    2.14 -        super(Application.class);
    2.15 -    }
    2.16 -}
    2.17 \ No newline at end of file
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/app/src/androidTest/java/com/example/musicplayer/ApplicationTest.java	Thu Apr 23 10:53:54 2015 -0700
     3.3 @@ -0,0 +1,13 @@
     3.4 +package com.example.musicplayer;
     3.5 +
     3.6 +import android.app.Application;
     3.7 +import android.test.ApplicationTestCase;
     3.8 +
     3.9 +/**
    3.10 + * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
    3.11 + */
    3.12 +public class ApplicationTest extends ApplicationTestCase<Application> {
    3.13 +    public ApplicationTest() {
    3.14 +        super(Application.class);
    3.15 +    }
    3.16 +}
    3.17 \ No newline at end of file
     4.1 --- a/app/src/main/AndroidManifest.xml	Mon Apr 20 17:11:10 2015 +0300
     4.2 +++ b/app/src/main/AndroidManifest.xml	Thu Apr 23 10:53:54 2015 -0700
     4.3 @@ -1,18 +1,14 @@
     4.4  <?xml version="1.0" encoding="utf-8"?>
     4.5  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     4.6 -    package="com.example.friendstream.friendstream" >
     4.7 +    package="com.example.musicplayer" >
     4.8  
     4.9 -    <!--allows music to play in the background, after Activity view switched out -->
    4.10 -    <uses-permission android:name="android.permission.WAKE_LOCK" />
    4.11 -
    4.12 -    <!--Generated by Android Studio -->
    4.13      <application
    4.14          android:allowBackup="true"
    4.15          android:icon="@mipmap/ic_launcher"
    4.16          android:label="@string/app_name"
    4.17          android:theme="@style/AppTheme" >
    4.18          <activity
    4.19 -            android:name=".PickingSongs"
    4.20 +            android:name=".MainActivity"
    4.21              android:configChanges="orientation|keyboardHidden|screenSize"
    4.22              android:label="@string/app_name"
    4.23              android:theme="@style/FullscreenTheme" >
    4.24 @@ -22,12 +18,6 @@
    4.25                  <category android:name="android.intent.category.LAUNCHER" />
    4.26              </intent-filter>
    4.27          </activity>
    4.28 -
    4.29 -        <service
    4.30 -            android:name=".MusicService"
    4.31 -            android:enabled="true"
    4.32 -            android:exported="true" >
    4.33 -        </service>
    4.34      </application>
    4.35  
    4.36  </manifest>
     5.1 --- a/app/src/main/java/com/example/friendstream/friendstream/MusicService.java	Mon Apr 20 17:11:10 2015 +0300
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,132 +0,0 @@
     5.4 -/*
     5.5 -Made from tutorial:
     5.6 -http://code.tutsplus.com/tutorials/create-a-music-player-on-android-song-playback--mobile-22778
     5.7 - */
     5.8 -
     5.9 -
    5.10 -package com.example.friendstream.friendstream;
    5.11 -
    5.12 -import android.app.Service;
    5.13 -import android.content.ContentUris;
    5.14 -import android.content.Intent;
    5.15 -import android.media.MediaPlayer;
    5.16 -import android.net.Uri;
    5.17 -import android.os.IBinder;
    5.18 -import java.util.ArrayList;
    5.19 -
    5.20 -import android.media.AudioManager;
    5.21 -import android.os.Binder;
    5.22 -import android.os.PowerManager;
    5.23 -import android.util.Log;
    5.24 -
    5.25 -/*
    5.26 -Add a Service to the app, which will bind to the song picking activity, and will be what causes
    5.27 - the audio to begin playing
    5.28 -Make sure the class name matches what is listed in the Manifest.
    5.29 - */
    5.30 -public class MusicService extends Service implements
    5.31 -        MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener,
    5.32 -        MediaPlayer.OnCompletionListener {
    5.33 -
    5.34 -    // Activity will pass in a list of songPlayList, and will play each using the MediaPlayer class
    5.35 -    private MediaPlayer mediaPlayerInst;
    5.36 -
    5.37 -    // song list
    5.38 -    private ArrayList<Song> songPlayList;
    5.39 -
    5.40 -    // position within list of song currently playing in the MediaPlayer
    5.41 -    private int songPosnInList;
    5.42 -
    5.43 -    //This is used to connect an instance of this service to Activities that use it
    5.44 -    private final IBinder musicBinderInst = new MusicBinder();
    5.45 -
    5.46 -    public MusicService() {
    5.47 -    }
    5.48 -
    5.49 -//==============  Setup and Connect (bind)  =============
    5.50 -    public void onCreate(){
    5.51 -        //create the service
    5.52 -        super.onCreate();
    5.53 -
    5.54 -        //initialize position
    5.55 -        songPosnInList =0;
    5.56 -
    5.57 -        //create mediaPlayerInst, which is a singleton, that is prepared for each song, then
    5.58 -        // makes the audio for that song happen
    5.59 -        mediaPlayerInst = new MediaPlayer();
    5.60 -        initMusicPlayer();
    5.61 -    }
    5.62 -
    5.63 -    public void initMusicPlayer(){
    5.64 -        //set mediaPlayerInst properties
    5.65 -        mediaPlayerInst.setWakeMode(getApplicationContext(),
    5.66 -                PowerManager.PARTIAL_WAKE_LOCK);
    5.67 -        mediaPlayerInst.setAudioStreamType(AudioManager.STREAM_MUSIC);
    5.68 -        mediaPlayerInst.setOnPreparedListener(this);
    5.69 -        mediaPlayerInst.setOnCompletionListener(this);
    5.70 -        mediaPlayerInst.setOnErrorListener(this);
    5.71 -    }
    5.72 -
    5.73 -    //Inner class, an instance of which is created as part of connecting Activity to this Service
    5.74 -    public class MusicBinder extends Binder {
    5.75 -        MusicService getService() {
    5.76 -            return MusicService.this;
    5.77 -        }
    5.78 -    }
    5.79 -
    5.80 -    @Override
    5.81 -    public IBinder onBind(Intent intent) {
    5.82 -        return musicBinderInst;  //the instance of MusicBinder created as instance var above
    5.83 -    }
    5.84 -    @Override
    5.85 -    public boolean onUnbind(Intent intent){
    5.86 -        mediaPlayerInst.stop();
    5.87 -        mediaPlayerInst.release();
    5.88 -        return false;
    5.89 -    }
    5.90 -
    5.91 -//==========================================
    5.92 -
    5.93 -    public void setList(ArrayList<Song> theSongs){
    5.94 -        songPlayList =theSongs;
    5.95 -    }
    5.96 -
    5.97 -    public void setSong(int songIndex){
    5.98 -        songPosnInList =songIndex;
    5.99 -    }
   5.100 -
   5.101 -    public void playSong(){
   5.102 -        //play a song
   5.103 -        mediaPlayerInst.reset();
   5.104 -
   5.105 -        //get the song from the list, extract the ID for it using its Song object, and cast as a URI
   5.106 -        //get song
   5.107 -        Song playSong = songPlayList.get(songPosnInList);
   5.108 -
   5.109 -        //get id
   5.110 -        long currSong = playSong.getID();
   5.111 -
   5.112 -        //set uri
   5.113 -        Uri trackUri = ContentUris.withAppendedId(
   5.114 -                android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
   5.115 -                currSong);
   5.116 -
   5.117 -        //set this URI as the data source for the MediaPlayer instance,
   5.118 -        try{
   5.119 -            mediaPlayerInst.setDataSource(getApplicationContext(), trackUri);
   5.120 -        }
   5.121 -        catch(Exception e){
   5.122 -            Log.e("MUSIC SERVICE", "Error setting data source", e);
   5.123 -        }
   5.124 -
   5.125 -        //trigger the MediaPlayer to set itself up, open the songfile, and be ready to start playing
   5.126 -        // when done with all that, will call back to this object's "onPrepared"
   5.127 -        mediaPlayerInst.prepareAsync();
   5.128 -    }
   5.129 -
   5.130 -    @Override
   5.131 -    public void onPrepared(MediaPlayer preparedMediaPlayer) {
   5.132 -        //start playback
   5.133 -        preparedMediaPlayer.start();
   5.134 -    }
   5.135 -}
     6.1 --- a/app/src/main/java/com/example/friendstream/friendstream/PickingSongs.java	Mon Apr 20 17:11:10 2015 +0300
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,245 +0,0 @@
     6.4 -/*
     6.5 -Based on these tutorials:
     6.6 -http://code.tutsplus.com/tutorials/create-a-music-player-on-android-project-setup--mobile-22764
     6.7 - */
     6.8 -
     6.9 -package com.example.friendstream.friendstream;
    6.10 -
    6.11 -import com.example.friendstream.friendstream.util.SystemUiHider;
    6.12 -
    6.13 -import android.annotation.TargetApi;
    6.14 -import android.app.Activity;
    6.15 -import android.os.Build;
    6.16 -import android.os.Bundle;
    6.17 -import android.os.Handler;
    6.18 -import android.view.MotionEvent;
    6.19 -import android.view.View;
    6.20 -import android.os.IBinder;
    6.21 -import android.content.ComponentName;
    6.22 -import android.content.Context;
    6.23 -import android.content.Intent;
    6.24 -import android.content.ServiceConnection;
    6.25 -import android.view.MenuItem;
    6.26 -import android.view.View;
    6.27 -import com.example.friendstream.friendstream.MusicService.MusicBinder;
    6.28 -
    6.29 -
    6.30 -/**
    6.31 - * An example full-screen activity that shows and hides the system UI (i.e.
    6.32 - * status bar and navigation/system bar) with user interaction.
    6.33 - *
    6.34 - * @see SystemUiHider
    6.35 - */
    6.36 -public class PickingSongs extends Activity {
    6.37 -    /**
    6.38 -     * Whether or not the system UI should be auto-hidden after
    6.39 -     * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
    6.40 -     */
    6.41 -    private static final boolean AUTO_HIDE = true;
    6.42 -
    6.43 -    /**
    6.44 -     * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
    6.45 -     * user interaction before hiding the system UI.
    6.46 -     */
    6.47 -    private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
    6.48 -
    6.49 -    /**
    6.50 -     * If set, will toggle the system UI visibility upon interaction. Otherwise,
    6.51 -     * will show the system UI visibility upon interaction.
    6.52 -     */
    6.53 -    private static final boolean TOGGLE_ON_CLICK = true;
    6.54 -
    6.55 -    /**
    6.56 -     * The flags to pass to {@link SystemUiHider#getInstance}.
    6.57 -     */
    6.58 -    private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;
    6.59 -
    6.60 -    /**
    6.61 -     * The instance of the {@link SystemUiHider} for this activity.
    6.62 -     */
    6.63 -    private SystemUiHider mSystemUiHider;
    6.64 -
    6.65 -    private MusicService musicSrv;
    6.66 -    private Intent playIntent;
    6.67 -    private boolean musicBound=false;
    6.68 -
    6.69 -
    6.70 -    @Override
    6.71 -    protected void onCreate(Bundle savedInstanceState) {
    6.72 -        super.onCreate(savedInstanceState);
    6.73 -
    6.74 -        setContentView(R.layout.activity_picking_songs);
    6.75 -
    6.76 -        final View controlsView = findViewById(R.id.fullscreen_content_controls);
    6.77 -        final View contentView = findViewById(R.id.fullscreen_content);
    6.78 -
    6.79 -        // Set up an instance of SystemUiHider to control the system UI for
    6.80 -        // this activity.
    6.81 -        mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS);
    6.82 -        mSystemUiHider.setup();
    6.83 -        mSystemUiHider
    6.84 -                .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
    6.85 -                    // Cached values.
    6.86 -                    int mControlsHeight;
    6.87 -                    int mShortAnimTime;
    6.88 -
    6.89 -                    @Override
    6.90 -                    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
    6.91 -                    public void onVisibilityChange(boolean visible) {
    6.92 -                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
    6.93 -                            // If the ViewPropertyAnimator API is available
    6.94 -                            // (Honeycomb MR2 and later), use it to animate the
    6.95 -                            // in-layout UI controls at the bottom of the
    6.96 -                            // screen.
    6.97 -                            if (mControlsHeight == 0) {
    6.98 -                                mControlsHeight = controlsView.getHeight();
    6.99 -                            }
   6.100 -                            if (mShortAnimTime == 0) {
   6.101 -                                mShortAnimTime = getResources().getInteger(
   6.102 -                                        android.R.integer.config_shortAnimTime);
   6.103 -                            }
   6.104 -                            controlsView.animate()
   6.105 -                                    .translationY(visible ? 0 : mControlsHeight)
   6.106 -                                    .setDuration(mShortAnimTime);
   6.107 -                        } else {
   6.108 -                            // If the ViewPropertyAnimator APIs aren't
   6.109 -                            // available, simply show or hide the in-layout UI
   6.110 -                            // controls.
   6.111 -                            controlsView.setVisibility(visible ? View.VISIBLE : View.GONE);
   6.112 -                        }
   6.113 -
   6.114 -                        if (visible && AUTO_HIDE) {
   6.115 -                            // Schedule a hide().
   6.116 -                            delayedHide(AUTO_HIDE_DELAY_MILLIS);
   6.117 -                        }
   6.118 -                    }
   6.119 -                });
   6.120 -
   6.121 -        // Set up the user interaction to manually show or hide the system UI.
   6.122 -        contentView.setOnClickListener(new View.OnClickListener() {
   6.123 -            @Override
   6.124 -            public void onClick(View view) {
   6.125 -                if (TOGGLE_ON_CLICK) {
   6.126 -                    mSystemUiHider.toggle();
   6.127 -                } else {
   6.128 -                    mSystemUiHider.show();
   6.129 -                }
   6.130 -            }
   6.131 -        });
   6.132 -
   6.133 -        // Upon interacting with UI controls, delay any scheduled hide()
   6.134 -        // operations to prevent the jarring behavior of controls going away
   6.135 -        // while interacting with the UI.
   6.136 -        findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener);
   6.137 -    }
   6.138 -
   6.139 -    // This Activity controls the Service that makes the audio of a playlist happen.
   6.140 -    // Bind this Activity to the Service class, using an anonymous Intent class
   6.141 -    // The callback methods essentially inform the Activity instance of when it is connected
   6.142 -    //  to the Service instance. The callback sets a reference to the Service (which it gets via
   6.143 -    //  the MusicBinder instance inside the Service) and a flag.
   6.144 -    // The bind process is what calls the onServiceConnected..  the whole MusicBinder thing looks
   6.145 -    //  pretty messed up..  these guys twist their brains in bizarre ways sometimes..
   6.146 -    private ServiceConnection musicConnection = new ServiceConnection(){
   6.147 -
   6.148 -        @Override
   6.149 -        public void onServiceConnected(ComponentName name, IBinder service) {
   6.150 -            MusicBinder binder = (MusicBinder)service;
   6.151 -            //get service
   6.152 -            musicSrv = binder.getService();
   6.153 -            //pass list
   6.154 -            musicSrv.setList(songList);
   6.155 -            musicBound = true;
   6.156 -        }
   6.157 -
   6.158 -        @Override
   6.159 -        public void onServiceDisconnected(ComponentName name) {
   6.160 -            musicBound = false;
   6.161 -        }
   6.162 -    };
   6.163 -
   6.164 -    // added an onClick attribute to the layout for each item in the song list.. calls this..
   6.165 -    public void songPicked(View view){
   6.166 -        musicSrv.setSong(Integer.parseInt(view.getTag().toString()));
   6.167 -        musicSrv.playSong();
   6.168 -    }
   6.169 -
   6.170 -
   6.171 -    // implement the end button we added to the main menu
   6.172 -    @Override
   6.173 -    public boolean onOptionsItemSelected(MenuItem item) {
   6.174 -        //menu item selected
   6.175 -        switch (item.getItemId()) {
   6.176 -            case R.id.action_shuffle:
   6.177 -                //shuffle
   6.178 -                break;
   6.179 -            case R.id.action_end:
   6.180 -                stopService(playIntent);
   6.181 -                musicSrv=null;
   6.182 -                System.exit(0);
   6.183 -                break;
   6.184 -        }
   6.185 -        return super.onOptionsItemSelected(item);
   6.186 -    }
   6.187 -
   6.188 -    @Override
   6.189 -    protected void onDestroy() {
   6.190 -        stopService(playIntent);
   6.191 -        musicSrv=null;
   6.192 -        super.onDestroy();
   6.193 -    }
   6.194 -
   6.195 -    @Override
   6.196 -    protected void onStart() {
   6.197 -        super.onStart();
   6.198 -        if( playIntent==null ){
   6.199 -            playIntent = new Intent(this, MusicService.class);
   6.200 -            bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
   6.201 -            startService(playIntent);
   6.202 -        }
   6.203 -    }
   6.204 -
   6.205 -
   6.206 -    @Override
   6.207 -    protected void onPostCreate(Bundle savedInstanceState) {
   6.208 -        super.onPostCreate(savedInstanceState);
   6.209 -
   6.210 -        // Trigger the initial hide() shortly after the activity has been
   6.211 -        // created, to briefly hint to the user that UI controls
   6.212 -        // are available.
   6.213 -        delayedHide(100);
   6.214 -    }
   6.215 -
   6.216 -
   6.217 -    /**
   6.218 -     * Touch listener to use for in-layout UI controls to delay hiding the
   6.219 -     * system UI. This is to prevent the jarring behavior of controls going away
   6.220 -     * while interacting with activity UI.
   6.221 -     */
   6.222 -    View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
   6.223 -        @Override
   6.224 -        public boolean onTouch(View view, MotionEvent motionEvent) {
   6.225 -            if (AUTO_HIDE) {
   6.226 -                delayedHide(AUTO_HIDE_DELAY_MILLIS);
   6.227 -            }
   6.228 -            return false;
   6.229 -        }
   6.230 -    };
   6.231 -
   6.232 -    Handler mHideHandler = new Handler();
   6.233 -    Runnable mHideRunnable = new Runnable() {
   6.234 -        @Override
   6.235 -        public void run() {
   6.236 -            mSystemUiHider.hide();
   6.237 -        }
   6.238 -    };
   6.239 -
   6.240 -    /**
   6.241 -     * Schedules a call to hide() in [delay] milliseconds, canceling any
   6.242 -     * previously scheduled calls.
   6.243 -     */
   6.244 -    private void delayedHide(int delayMillis) {
   6.245 -        mHideHandler.removeCallbacks(mHideRunnable);
   6.246 -        mHideHandler.postDelayed(mHideRunnable, delayMillis);
   6.247 -    }
   6.248 -}
     7.1 --- a/app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHider.java	Mon Apr 20 17:11:10 2015 +0300
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,172 +0,0 @@
     7.4 -package com.example.friendstream.friendstream.util;
     7.5 -
     7.6 -import android.app.Activity;
     7.7 -import android.os.Build;
     7.8 -import android.view.View;
     7.9 -
    7.10 -/**
    7.11 - * A utility class that helps with showing and hiding system UI such as the
    7.12 - * status bar and navigation/system bar. This class uses backward-compatibility
    7.13 - * techniques described in <a href=
    7.14 - * "http://developer.android.com/training/backward-compatible-ui/index.html">
    7.15 - * Creating Backward-Compatible UIs</a> to ensure that devices running any
    7.16 - * version of ndroid OS are supported. More specifically, there are separate
    7.17 - * implementations of this abstract class: for newer devices,
    7.18 - * {@link #getInstance} will return a {@link SystemUiHiderHoneycomb} instance,
    7.19 - * while on older devices {@link #getInstance} will return a
    7.20 - * {@link SystemUiHiderBase} instance.
    7.21 - * <p/>
    7.22 - * For more on system bars, see <a href=
    7.23 - * "http://developer.android.com/design/get-started/ui-overview.html#system-bars"
    7.24 - * > System Bars</a>.
    7.25 - *
    7.26 - * @see android.view.View#setSystemUiVisibility(int)
    7.27 - * @see android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
    7.28 - */
    7.29 -public abstract class SystemUiHider {
    7.30 -    /**
    7.31 -     * When this flag is set, the
    7.32 -     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}
    7.33 -     * flag will be set on older devices, making the status bar "float" on top
    7.34 -     * of the activity layout. This is most useful when there are no controls at
    7.35 -     * the top of the activity layout.
    7.36 -     * <p/>
    7.37 -     * This flag isn't used on newer devices because the <a
    7.38 -     * href="http://developer.android.com/design/patterns/actionbar.html">action
    7.39 -     * bar</a>, the most important structural element of an Android app, should
    7.40 -     * be visible and not obscured by the system UI.
    7.41 -     */
    7.42 -    public static final int FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES = 0x1;
    7.43 -
    7.44 -    /**
    7.45 -     * When this flag is set, {@link #show()} and {@link #hide()} will toggle
    7.46 -     * the visibility of the status bar. If there is a navigation bar, show and
    7.47 -     * hide will toggle low profile mode.
    7.48 -     */
    7.49 -    public static final int FLAG_FULLSCREEN = 0x2;
    7.50 -
    7.51 -    /**
    7.52 -     * When this flag is set, {@link #show()} and {@link #hide()} will toggle
    7.53 -     * the visibility of the navigation bar, if it's present on the device and
    7.54 -     * the device allows hiding it. In cases where the navigation bar is present
    7.55 -     * but cannot be hidden, show and hide will toggle low profile mode.
    7.56 -     */
    7.57 -    public static final int FLAG_HIDE_NAVIGATION = FLAG_FULLSCREEN | 0x4;
    7.58 -
    7.59 -    /**
    7.60 -     * The activity associated with this UI hider object.
    7.61 -     */
    7.62 -    protected Activity mActivity;
    7.63 -
    7.64 -    /**
    7.65 -     * The view on which {@link View#setSystemUiVisibility(int)} will be called.
    7.66 -     */
    7.67 -    protected View mAnchorView;
    7.68 -
    7.69 -    /**
    7.70 -     * The current UI hider flags.
    7.71 -     *
    7.72 -     * @see #FLAG_FULLSCREEN
    7.73 -     * @see #FLAG_HIDE_NAVIGATION
    7.74 -     * @see #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES
    7.75 -     */
    7.76 -    protected int mFlags;
    7.77 -
    7.78 -    /**
    7.79 -     * The current visibility callback.
    7.80 -     */
    7.81 -    protected OnVisibilityChangeListener mOnVisibilityChangeListener = sDummyListener;
    7.82 -
    7.83 -    /**
    7.84 -     * Creates and returns an instance of {@link SystemUiHider} that is
    7.85 -     * appropriate for this device. The object will be either a
    7.86 -     * {@link SystemUiHiderBase} or {@link SystemUiHiderHoneycomb} depending on
    7.87 -     * the device.
    7.88 -     *
    7.89 -     * @param activity   The activity whose window's system UI should be
    7.90 -     *                   controlled by this class.
    7.91 -     * @param anchorView The view on which
    7.92 -     *                   {@link View#setSystemUiVisibility(int)} will be called.
    7.93 -     * @param flags      Either 0 or any combination of {@link #FLAG_FULLSCREEN},
    7.94 -     *                   {@link #FLAG_HIDE_NAVIGATION}, and
    7.95 -     *                   {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES}.
    7.96 -     */
    7.97 -    public static SystemUiHider getInstance(Activity activity, View anchorView, int flags) {
    7.98 -        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    7.99 -            return new SystemUiHiderHoneycomb(activity, anchorView, flags);
   7.100 -        } else {
   7.101 -            return new SystemUiHiderBase(activity, anchorView, flags);
   7.102 -        }
   7.103 -    }
   7.104 -
   7.105 -    protected SystemUiHider(Activity activity, View anchorView, int flags) {
   7.106 -        mActivity = activity;
   7.107 -        mAnchorView = anchorView;
   7.108 -        mFlags = flags;
   7.109 -    }
   7.110 -
   7.111 -    /**
   7.112 -     * Sets up the system UI hider. Should be called from
   7.113 -     * {@link Activity#onCreate}.
   7.114 -     */
   7.115 -    public abstract void setup();
   7.116 -
   7.117 -    /**
   7.118 -     * Returns whether or not the system UI is visible.
   7.119 -     */
   7.120 -    public abstract boolean isVisible();
   7.121 -
   7.122 -    /**
   7.123 -     * Hide the system UI.
   7.124 -     */
   7.125 -    public abstract void hide();
   7.126 -
   7.127 -    /**
   7.128 -     * Show the system UI.
   7.129 -     */
   7.130 -    public abstract void show();
   7.131 -
   7.132 -    /**
   7.133 -     * Toggle the visibility of the system UI.
   7.134 -     */
   7.135 -    public void toggle() {
   7.136 -        if (isVisible()) {
   7.137 -            hide();
   7.138 -        } else {
   7.139 -            show();
   7.140 -        }
   7.141 -    }
   7.142 -
   7.143 -    /**
   7.144 -     * Registers a callback, to be triggered when the system UI visibility
   7.145 -     * changes.
   7.146 -     */
   7.147 -    public void setOnVisibilityChangeListener(OnVisibilityChangeListener listener) {
   7.148 -        if (listener == null) {
   7.149 -            listener = sDummyListener;
   7.150 -        }
   7.151 -
   7.152 -        mOnVisibilityChangeListener = listener;
   7.153 -    }
   7.154 -
   7.155 -    /**
   7.156 -     * A dummy no-op callback for use when there is no other listener set.
   7.157 -     */
   7.158 -    private static OnVisibilityChangeListener sDummyListener = new OnVisibilityChangeListener() {
   7.159 -        @Override
   7.160 -        public void onVisibilityChange(boolean visible) {
   7.161 -        }
   7.162 -    };
   7.163 -
   7.164 -    /**
   7.165 -     * A callback interface used to listen for system UI visibility changes.
   7.166 -     */
   7.167 -    public interface OnVisibilityChangeListener {
   7.168 -        /**
   7.169 -         * Called when the system UI visibility has changed.
   7.170 -         *
   7.171 -         * @param visible True if the system UI is visible.
   7.172 -         */
   7.173 -        public void onVisibilityChange(boolean visible);
   7.174 -    }
   7.175 -}
     8.1 --- a/app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHiderBase.java	Mon Apr 20 17:11:10 2015 +0300
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,63 +0,0 @@
     8.4 -package com.example.friendstream.friendstream.util;
     8.5 -
     8.6 -import android.app.Activity;
     8.7 -import android.view.View;
     8.8 -import android.view.WindowManager;
     8.9 -
    8.10 -/**
    8.11 - * A base implementation of {@link SystemUiHider}. Uses APIs available in all
    8.12 - * API levels to show and hide the status bar.
    8.13 - */
    8.14 -public class SystemUiHiderBase extends SystemUiHider {
    8.15 -    /**
    8.16 -     * Whether or not the system UI is currently visible. This is a cached value
    8.17 -     * from calls to {@link #hide()} and {@link #show()}.
    8.18 -     */
    8.19 -    private boolean mVisible = true;
    8.20 -
    8.21 -    /**
    8.22 -     * Constructor not intended to be called by clients. Use
    8.23 -     * {@link SystemUiHider#getInstance} to obtain an instance.
    8.24 -     */
    8.25 -    protected SystemUiHiderBase(Activity activity, View anchorView, int flags) {
    8.26 -        super(activity, anchorView, flags);
    8.27 -    }
    8.28 -
    8.29 -    @Override
    8.30 -    public void setup() {
    8.31 -        if ((mFlags & FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES) == 0) {
    8.32 -            mActivity.getWindow().setFlags(
    8.33 -                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
    8.34 -                            | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
    8.35 -                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
    8.36 -                            | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
    8.37 -        }
    8.38 -    }
    8.39 -
    8.40 -    @Override
    8.41 -    public boolean isVisible() {
    8.42 -        return mVisible;
    8.43 -    }
    8.44 -
    8.45 -    @Override
    8.46 -    public void hide() {
    8.47 -        if ((mFlags & FLAG_FULLSCREEN) != 0) {
    8.48 -            mActivity.getWindow().setFlags(
    8.49 -                    WindowManager.LayoutParams.FLAG_FULLSCREEN,
    8.50 -                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
    8.51 -        }
    8.52 -        mOnVisibilityChangeListener.onVisibilityChange(false);
    8.53 -        mVisible = false;
    8.54 -    }
    8.55 -
    8.56 -    @Override
    8.57 -    public void show() {
    8.58 -        if ((mFlags & FLAG_FULLSCREEN) != 0) {
    8.59 -            mActivity.getWindow().setFlags(
    8.60 -                    0,
    8.61 -                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
    8.62 -        }
    8.63 -        mOnVisibilityChangeListener.onVisibilityChange(true);
    8.64 -        mVisible = true;
    8.65 -    }
    8.66 -}
     9.1 --- a/app/src/main/java/com/example/friendstream/friendstream/util/SystemUiHiderHoneycomb.java	Mon Apr 20 17:11:10 2015 +0300
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,141 +0,0 @@
     9.4 -package com.example.friendstream.friendstream.util;
     9.5 -
     9.6 -import android.annotation.TargetApi;
     9.7 -import android.app.Activity;
     9.8 -import android.os.Build;
     9.9 -import android.view.View;
    9.10 -import android.view.WindowManager;
    9.11 -
    9.12 -/**
    9.13 - * An API 11+ implementation of {@link SystemUiHider}. Uses APIs available in
    9.14 - * Honeycomb and later (specifically {@link View#setSystemUiVisibility(int)}) to
    9.15 - * show and hide the system UI.
    9.16 - */
    9.17 -@TargetApi(Build.VERSION_CODES.HONEYCOMB)
    9.18 -public class SystemUiHiderHoneycomb extends SystemUiHiderBase {
    9.19 -    /**
    9.20 -     * Flags for {@link View#setSystemUiVisibility(int)} to use when showing the
    9.21 -     * system UI.
    9.22 -     */
    9.23 -    private int mShowFlags;
    9.24 -
    9.25 -    /**
    9.26 -     * Flags for {@link View#setSystemUiVisibility(int)} to use when hiding the
    9.27 -     * system UI.
    9.28 -     */
    9.29 -    private int mHideFlags;
    9.30 -
    9.31 -    /**
    9.32 -     * Flags to test against the first parameter in
    9.33 -     * {@link android.view.View.OnSystemUiVisibilityChangeListener#onSystemUiVisibilityChange(int)}
    9.34 -     * to determine the system UI visibility state.
    9.35 -     */
    9.36 -    private int mTestFlags;
    9.37 -
    9.38 -    /**
    9.39 -     * Whether or not the system UI is currently visible. This is cached from
    9.40 -     * {@link android.view.View.OnSystemUiVisibilityChangeListener}.
    9.41 -     */
    9.42 -    private boolean mVisible = true;
    9.43 -
    9.44 -    /**
    9.45 -     * Constructor not intended to be called by clients. Use
    9.46 -     * {@link SystemUiHider#getInstance} to obtain an instance.
    9.47 -     */
    9.48 -    protected SystemUiHiderHoneycomb(Activity activity, View anchorView, int flags) {
    9.49 -        super(activity, anchorView, flags);
    9.50 -
    9.51 -        mShowFlags = View.SYSTEM_UI_FLAG_VISIBLE;
    9.52 -        mHideFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
    9.53 -        mTestFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
    9.54 -
    9.55 -        if ((mFlags & FLAG_FULLSCREEN) != 0) {
    9.56 -            // If the client requested fullscreen, add flags relevant to hiding
    9.57 -            // the status bar. Note that some of these constants are new as of
    9.58 -            // API 16 (Jelly Bean). It is safe to use them, as they are inlined
    9.59 -            // at compile-time and do nothing on pre-Jelly Bean devices.
    9.60 -            mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    9.61 -            mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
    9.62 -                    | View.SYSTEM_UI_FLAG_FULLSCREEN;
    9.63 -        }
    9.64 -
    9.65 -        if ((mFlags & FLAG_HIDE_NAVIGATION) != 0) {
    9.66 -            // If the client requested hiding navigation, add relevant flags.
    9.67 -            mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
    9.68 -            mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
    9.69 -                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
    9.70 -            mTestFlags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
    9.71 -        }
    9.72 -    }
    9.73 -
    9.74 -    /**
    9.75 -     * {@inheritDoc}
    9.76 -     */
    9.77 -    @Override
    9.78 -    public void setup() {
    9.79 -        mAnchorView.setOnSystemUiVisibilityChangeListener(mSystemUiVisibilityChangeListener);
    9.80 -    }
    9.81 -
    9.82 -    /**
    9.83 -     * {@inheritDoc}
    9.84 -     */
    9.85 -    @Override
    9.86 -    public void hide() {
    9.87 -        mAnchorView.setSystemUiVisibility(mHideFlags);
    9.88 -    }
    9.89 -
    9.90 -    /**
    9.91 -     * {@inheritDoc}
    9.92 -     */
    9.93 -    @Override
    9.94 -    public void show() {
    9.95 -        mAnchorView.setSystemUiVisibility(mShowFlags);
    9.96 -    }
    9.97 -
    9.98 -    /**
    9.99 -     * {@inheritDoc}
   9.100 -     */
   9.101 -    @Override
   9.102 -    public boolean isVisible() {
   9.103 -        return mVisible;
   9.104 -    }
   9.105 -
   9.106 -    private View.OnSystemUiVisibilityChangeListener mSystemUiVisibilityChangeListener
   9.107 -            = new View.OnSystemUiVisibilityChangeListener() {
   9.108 -        @Override
   9.109 -        public void onSystemUiVisibilityChange(int vis) {
   9.110 -            // Test against mTestFlags to see if the system UI is visible.
   9.111 -            if ((vis & mTestFlags) != 0) {
   9.112 -                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
   9.113 -                    // Pre-Jelly Bean, we must manually hide the action bar
   9.114 -                    // and use the old window flags API.
   9.115 -                    mActivity.getActionBar().hide();
   9.116 -                    mActivity.getWindow().setFlags(
   9.117 -                            WindowManager.LayoutParams.FLAG_FULLSCREEN,
   9.118 -                            WindowManager.LayoutParams.FLAG_FULLSCREEN);
   9.119 -                }
   9.120 -
   9.121 -                // Trigger the registered listener and cache the visibility
   9.122 -                // state.
   9.123 -                mOnVisibilityChangeListener.onVisibilityChange(false);
   9.124 -                mVisible = false;
   9.125 -
   9.126 -            } else {
   9.127 -                mAnchorView.setSystemUiVisibility(mShowFlags);
   9.128 -                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
   9.129 -                    // Pre-Jelly Bean, we must manually show the action bar
   9.130 -                    // and use the old window flags API.
   9.131 -                    mActivity.getActionBar().show();
   9.132 -                    mActivity.getWindow().setFlags(
   9.133 -                            0,
   9.134 -                            WindowManager.LayoutParams.FLAG_FULLSCREEN);
   9.135 -                }
   9.136 -
   9.137 -                // Trigger the registered listener and cache the visibility
   9.138 -                // state.
   9.139 -                mOnVisibilityChangeListener.onVisibilityChange(true);
   9.140 -                mVisible = true;
   9.141 -            }
   9.142 -        }
   9.143 -    };
   9.144 -}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/app/src/main/java/com/example/musicplayer/MainActivity.java	Thu Apr 23 10:53:54 2015 -0700
    10.3 @@ -0,0 +1,160 @@
    10.4 +package com.example.musicplayer;
    10.5 +
    10.6 +import com.example.musicplayer.util.SystemUiHider;
    10.7 +
    10.8 +import android.annotation.TargetApi;
    10.9 +import android.app.Activity;
   10.10 +import android.os.Build;
   10.11 +import android.os.Bundle;
   10.12 +import android.os.Handler;
   10.13 +import android.view.MotionEvent;
   10.14 +import android.view.View;
   10.15 +
   10.16 +
   10.17 +/**
   10.18 + * An example full-screen activity that shows and hides the system UI (i.e.
   10.19 + * status bar and navigation/system bar) with user interaction.
   10.20 + *
   10.21 + * @see SystemUiHider
   10.22 + */
   10.23 +public class MainActivity extends Activity {
   10.24 +    /**
   10.25 +     * Whether or not the system UI should be auto-hidden after
   10.26 +     * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
   10.27 +     */
   10.28 +    private static final boolean AUTO_HIDE = true;
   10.29 +
   10.30 +    /**
   10.31 +     * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
   10.32 +     * user interaction before hiding the system UI.
   10.33 +     */
   10.34 +    private static final int AUTO_HIDE_DELAY_MILLIS = 3000;
   10.35 +
   10.36 +    /**
   10.37 +     * If set, will toggle the system UI visibility upon interaction. Otherwise,
   10.38 +     * will show the system UI visibility upon interaction.
   10.39 +     */
   10.40 +    private static final boolean TOGGLE_ON_CLICK = true;
   10.41 +
   10.42 +    /**
   10.43 +     * The flags to pass to {@link SystemUiHider#getInstance}.
   10.44 +     */
   10.45 +    private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;
   10.46 +
   10.47 +    /**
   10.48 +     * The instance of the {@link SystemUiHider} for this activity.
   10.49 +     */
   10.50 +    private SystemUiHider mSystemUiHider;
   10.51 +
   10.52 +    @Override
   10.53 +    protected void onCreate(Bundle savedInstanceState) {
   10.54 +        super.onCreate(savedInstanceState);
   10.55 +
   10.56 +        setContentView(R.layout.activity_main);
   10.57 +
   10.58 +        final View controlsView = findViewById(R.id.fullscreen_content_controls);
   10.59 +        final View contentView = findViewById(R.id.fullscreen_content);
   10.60 +
   10.61 +        // Set up an instance of SystemUiHider to control the system UI for
   10.62 +        // this activity.
   10.63 +        mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS);
   10.64 +        mSystemUiHider.setup();
   10.65 +        mSystemUiHider
   10.66 +                .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
   10.67 +                    // Cached values.
   10.68 +                    int mControlsHeight;
   10.69 +                    int mShortAnimTime;
   10.70 +
   10.71 +                    @Override
   10.72 +                    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
   10.73 +                    public void onVisibilityChange(boolean visible) {
   10.74 +                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
   10.75 +                            // If the ViewPropertyAnimator API is available
   10.76 +                            // (Honeycomb MR2 and later), use it to animate the
   10.77 +                            // in-layout UI controls at the bottom of the
   10.78 +                            // screen.
   10.79 +                            if (mControlsHeight == 0) {
   10.80 +                                mControlsHeight = controlsView.getHeight();
   10.81 +                            }
   10.82 +                            if (mShortAnimTime == 0) {
   10.83 +                                mShortAnimTime = getResources().getInteger(
   10.84 +                                        android.R.integer.config_shortAnimTime);
   10.85 +                            }
   10.86 +                            controlsView.animate()
   10.87 +                                    .translationY(visible ? 0 : mControlsHeight)
   10.88 +                                    .setDuration(mShortAnimTime);
   10.89 +                        } else {
   10.90 +                            // If the ViewPropertyAnimator APIs aren't
   10.91 +                            // available, simply show or hide the in-layout UI
   10.92 +                            // controls.
   10.93 +                            controlsView.setVisibility(visible ? View.VISIBLE : View.GONE);
   10.94 +                        }
   10.95 +
   10.96 +                        if (visible && AUTO_HIDE) {
   10.97 +                            // Schedule a hide().
   10.98 +                            delayedHide(AUTO_HIDE_DELAY_MILLIS);
   10.99 +                        }
  10.100 +                    }
  10.101 +                });
  10.102 +
  10.103 +        // Set up the user interaction to manually show or hide the system UI.
  10.104 +        contentView.setOnClickListener(new View.OnClickListener() {
  10.105 +            @Override
  10.106 +            public void onClick(View view) {
  10.107 +                if (TOGGLE_ON_CLICK) {
  10.108 +                    mSystemUiHider.toggle();
  10.109 +                } else {
  10.110 +                    mSystemUiHider.show();
  10.111 +                }
  10.112 +            }
  10.113 +        });
  10.114 +
  10.115 +        // Upon interacting with UI controls, delay any scheduled hide()
  10.116 +        // operations to prevent the jarring behavior of controls going away
  10.117 +        // while interacting with the UI.
  10.118 +        findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener);
  10.119 +    }
  10.120 +
  10.121 +    @Override
  10.122 +    protected void onPostCreate(Bundle savedInstanceState) {
  10.123 +        super.onPostCreate(savedInstanceState);
  10.124 +
  10.125 +        // Trigger the initial hide() shortly after the activity has been
  10.126 +        // created, to briefly hint to the user that UI controls
  10.127 +        // are available.
  10.128 +        delayedHide(100);
  10.129 +    }
  10.130 +
  10.131 +
  10.132 +    /**
  10.133 +     * Touch listener to use for in-layout UI controls to delay hiding the
  10.134 +     * system UI. This is to prevent the jarring behavior of controls going away
  10.135 +     * while interacting with activity UI.
  10.136 +     */
  10.137 +    View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
  10.138 +        @Override
  10.139 +        public boolean onTouch(View view, MotionEvent motionEvent) {
  10.140 +            if (AUTO_HIDE) {
  10.141 +                delayedHide(AUTO_HIDE_DELAY_MILLIS);
  10.142 +            }
  10.143 +            return false;
  10.144 +        }
  10.145 +    };
  10.146 +
  10.147 +    Handler mHideHandler = new Handler();
  10.148 +    Runnable mHideRunnable = new Runnable() {
  10.149 +        @Override
  10.150 +        public void run() {
  10.151 +            mSystemUiHider.hide();
  10.152 +        }
  10.153 +    };
  10.154 +
  10.155 +    /**
  10.156 +     * Schedules a call to hide() in [delay] milliseconds, canceling any
  10.157 +     * previously scheduled calls.
  10.158 +     */
  10.159 +    private void delayedHide(int delayMillis) {
  10.160 +        mHideHandler.removeCallbacks(mHideRunnable);
  10.161 +        mHideHandler.postDelayed(mHideRunnable, delayMillis);
  10.162 +    }
  10.163 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/app/src/main/java/com/example/musicplayer/util/SystemUiHider.java	Thu Apr 23 10:53:54 2015 -0700
    11.3 @@ -0,0 +1,172 @@
    11.4 +package com.example.musicplayer.util;
    11.5 +
    11.6 +import android.app.Activity;
    11.7 +import android.os.Build;
    11.8 +import android.view.View;
    11.9 +
   11.10 +/**
   11.11 + * A utility class that helps with showing and hiding system UI such as the
   11.12 + * status bar and navigation/system bar. This class uses backward-compatibility
   11.13 + * techniques described in <a href=
   11.14 + * "http://developer.android.com/training/backward-compatible-ui/index.html">
   11.15 + * Creating Backward-Compatible UIs</a> to ensure that devices running any
   11.16 + * version of ndroid OS are supported. More specifically, there are separate
   11.17 + * implementations of this abstract class: for newer devices,
   11.18 + * {@link #getInstance} will return a {@link SystemUiHiderHoneycomb} instance,
   11.19 + * while on older devices {@link #getInstance} will return a
   11.20 + * {@link SystemUiHiderBase} instance.
   11.21 + * <p/>
   11.22 + * For more on system bars, see <a href=
   11.23 + * "http://developer.android.com/design/get-started/ui-overview.html#system-bars"
   11.24 + * > System Bars</a>.
   11.25 + *
   11.26 + * @see android.view.View#setSystemUiVisibility(int)
   11.27 + * @see android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
   11.28 + */
   11.29 +public abstract class SystemUiHider {
   11.30 +    /**
   11.31 +     * When this flag is set, the
   11.32 +     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}
   11.33 +     * flag will be set on older devices, making the status bar "float" on top
   11.34 +     * of the activity layout. This is most useful when there are no controls at
   11.35 +     * the top of the activity layout.
   11.36 +     * <p/>
   11.37 +     * This flag isn't used on newer devices because the <a
   11.38 +     * href="http://developer.android.com/design/patterns/actionbar.html">action
   11.39 +     * bar</a>, the most important structural element of an Android app, should
   11.40 +     * be visible and not obscured by the system UI.
   11.41 +     */
   11.42 +    public static final int FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES = 0x1;
   11.43 +
   11.44 +    /**
   11.45 +     * When this flag is set, {@link #show()} and {@link #hide()} will toggle
   11.46 +     * the visibility of the status bar. If there is a navigation bar, show and
   11.47 +     * hide will toggle low profile mode.
   11.48 +     */
   11.49 +    public static final int FLAG_FULLSCREEN = 0x2;
   11.50 +
   11.51 +    /**
   11.52 +     * When this flag is set, {@link #show()} and {@link #hide()} will toggle
   11.53 +     * the visibility of the navigation bar, if it's present on the device and
   11.54 +     * the device allows hiding it. In cases where the navigation bar is present
   11.55 +     * but cannot be hidden, show and hide will toggle low profile mode.
   11.56 +     */
   11.57 +    public static final int FLAG_HIDE_NAVIGATION = FLAG_FULLSCREEN | 0x4;
   11.58 +
   11.59 +    /**
   11.60 +     * The activity associated with this UI hider object.
   11.61 +     */
   11.62 +    protected Activity mActivity;
   11.63 +
   11.64 +    /**
   11.65 +     * The view on which {@link View#setSystemUiVisibility(int)} will be called.
   11.66 +     */
   11.67 +    protected View mAnchorView;
   11.68 +
   11.69 +    /**
   11.70 +     * The current UI hider flags.
   11.71 +     *
   11.72 +     * @see #FLAG_FULLSCREEN
   11.73 +     * @see #FLAG_HIDE_NAVIGATION
   11.74 +     * @see #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES
   11.75 +     */
   11.76 +    protected int mFlags;
   11.77 +
   11.78 +    /**
   11.79 +     * The current visibility callback.
   11.80 +     */
   11.81 +    protected OnVisibilityChangeListener mOnVisibilityChangeListener = sDummyListener;
   11.82 +
   11.83 +    /**
   11.84 +     * Creates and returns an instance of {@link SystemUiHider} that is
   11.85 +     * appropriate for this device. The object will be either a
   11.86 +     * {@link SystemUiHiderBase} or {@link SystemUiHiderHoneycomb} depending on
   11.87 +     * the device.
   11.88 +     *
   11.89 +     * @param activity   The activity whose window's system UI should be
   11.90 +     *                   controlled by this class.
   11.91 +     * @param anchorView The view on which
   11.92 +     *                   {@link View#setSystemUiVisibility(int)} will be called.
   11.93 +     * @param flags      Either 0 or any combination of {@link #FLAG_FULLSCREEN},
   11.94 +     *                   {@link #FLAG_HIDE_NAVIGATION}, and
   11.95 +     *                   {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES}.
   11.96 +     */
   11.97 +    public static SystemUiHider getInstance(Activity activity, View anchorView, int flags) {
   11.98 +        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
   11.99 +            return new SystemUiHiderHoneycomb(activity, anchorView, flags);
  11.100 +        } else {
  11.101 +            return new SystemUiHiderBase(activity, anchorView, flags);
  11.102 +        }
  11.103 +    }
  11.104 +
  11.105 +    protected SystemUiHider(Activity activity, View anchorView, int flags) {
  11.106 +        mActivity = activity;
  11.107 +        mAnchorView = anchorView;
  11.108 +        mFlags = flags;
  11.109 +    }
  11.110 +
  11.111 +    /**
  11.112 +     * Sets up the system UI hider. Should be called from
  11.113 +     * {@link Activity#onCreate}.
  11.114 +     */
  11.115 +    public abstract void setup();
  11.116 +
  11.117 +    /**
  11.118 +     * Returns whether or not the system UI is visible.
  11.119 +     */
  11.120 +    public abstract boolean isVisible();
  11.121 +
  11.122 +    /**
  11.123 +     * Hide the system UI.
  11.124 +     */
  11.125 +    public abstract void hide();
  11.126 +
  11.127 +    /**
  11.128 +     * Show the system UI.
  11.129 +     */
  11.130 +    public abstract void show();
  11.131 +
  11.132 +    /**
  11.133 +     * Toggle the visibility of the system UI.
  11.134 +     */
  11.135 +    public void toggle() {
  11.136 +        if (isVisible()) {
  11.137 +            hide();
  11.138 +        } else {
  11.139 +            show();
  11.140 +        }
  11.141 +    }
  11.142 +
  11.143 +    /**
  11.144 +     * Registers a callback, to be triggered when the system UI visibility
  11.145 +     * changes.
  11.146 +     */
  11.147 +    public void setOnVisibilityChangeListener(OnVisibilityChangeListener listener) {
  11.148 +        if (listener == null) {
  11.149 +            listener = sDummyListener;
  11.150 +        }
  11.151 +
  11.152 +        mOnVisibilityChangeListener = listener;
  11.153 +    }
  11.154 +
  11.155 +    /**
  11.156 +     * A dummy no-op callback for use when there is no other listener set.
  11.157 +     */
  11.158 +    private static OnVisibilityChangeListener sDummyListener = new OnVisibilityChangeListener() {
  11.159 +        @Override
  11.160 +        public void onVisibilityChange(boolean visible) {
  11.161 +        }
  11.162 +    };
  11.163 +
  11.164 +    /**
  11.165 +     * A callback interface used to listen for system UI visibility changes.
  11.166 +     */
  11.167 +    public interface OnVisibilityChangeListener {
  11.168 +        /**
  11.169 +         * Called when the system UI visibility has changed.
  11.170 +         *
  11.171 +         * @param visible True if the system UI is visible.
  11.172 +         */
  11.173 +        public void onVisibilityChange(boolean visible);
  11.174 +    }
  11.175 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/app/src/main/java/com/example/musicplayer/util/SystemUiHiderBase.java	Thu Apr 23 10:53:54 2015 -0700
    12.3 @@ -0,0 +1,63 @@
    12.4 +package com.example.musicplayer.util;
    12.5 +
    12.6 +import android.app.Activity;
    12.7 +import android.view.View;
    12.8 +import android.view.WindowManager;
    12.9 +
   12.10 +/**
   12.11 + * A base implementation of {@link SystemUiHider}. Uses APIs available in all
   12.12 + * API levels to show and hide the status bar.
   12.13 + */
   12.14 +public class SystemUiHiderBase extends SystemUiHider {
   12.15 +    /**
   12.16 +     * Whether or not the system UI is currently visible. This is a cached value
   12.17 +     * from calls to {@link #hide()} and {@link #show()}.
   12.18 +     */
   12.19 +    private boolean mVisible = true;
   12.20 +
   12.21 +    /**
   12.22 +     * Constructor not intended to be called by clients. Use
   12.23 +     * {@link SystemUiHider#getInstance} to obtain an instance.
   12.24 +     */
   12.25 +    protected SystemUiHiderBase(Activity activity, View anchorView, int flags) {
   12.26 +        super(activity, anchorView, flags);
   12.27 +    }
   12.28 +
   12.29 +    @Override
   12.30 +    public void setup() {
   12.31 +        if ((mFlags & FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES) == 0) {
   12.32 +            mActivity.getWindow().setFlags(
   12.33 +                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
   12.34 +                            | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
   12.35 +                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
   12.36 +                            | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
   12.37 +        }
   12.38 +    }
   12.39 +
   12.40 +    @Override
   12.41 +    public boolean isVisible() {
   12.42 +        return mVisible;
   12.43 +    }
   12.44 +
   12.45 +    @Override
   12.46 +    public void hide() {
   12.47 +        if ((mFlags & FLAG_FULLSCREEN) != 0) {
   12.48 +            mActivity.getWindow().setFlags(
   12.49 +                    WindowManager.LayoutParams.FLAG_FULLSCREEN,
   12.50 +                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
   12.51 +        }
   12.52 +        mOnVisibilityChangeListener.onVisibilityChange(false);
   12.53 +        mVisible = false;
   12.54 +    }
   12.55 +
   12.56 +    @Override
   12.57 +    public void show() {
   12.58 +        if ((mFlags & FLAG_FULLSCREEN) != 0) {
   12.59 +            mActivity.getWindow().setFlags(
   12.60 +                    0,
   12.61 +                    WindowManager.LayoutParams.FLAG_FULLSCREEN);
   12.62 +        }
   12.63 +        mOnVisibilityChangeListener.onVisibilityChange(true);
   12.64 +        mVisible = true;
   12.65 +    }
   12.66 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/app/src/main/java/com/example/musicplayer/util/SystemUiHiderHoneycomb.java	Thu Apr 23 10:53:54 2015 -0700
    13.3 @@ -0,0 +1,141 @@
    13.4 +package com.example.musicplayer.util;
    13.5 +
    13.6 +import android.annotation.TargetApi;
    13.7 +import android.app.Activity;
    13.8 +import android.os.Build;
    13.9 +import android.view.View;
   13.10 +import android.view.WindowManager;
   13.11 +
   13.12 +/**
   13.13 + * An API 11+ implementation of {@link SystemUiHider}. Uses APIs available in
   13.14 + * Honeycomb and later (specifically {@link View#setSystemUiVisibility(int)}) to
   13.15 + * show and hide the system UI.
   13.16 + */
   13.17 +@TargetApi(Build.VERSION_CODES.HONEYCOMB)
   13.18 +public class SystemUiHiderHoneycomb extends SystemUiHiderBase {
   13.19 +    /**
   13.20 +     * Flags for {@link View#setSystemUiVisibility(int)} to use when showing the
   13.21 +     * system UI.
   13.22 +     */
   13.23 +    private int mShowFlags;
   13.24 +
   13.25 +    /**
   13.26 +     * Flags for {@link View#setSystemUiVisibility(int)} to use when hiding the
   13.27 +     * system UI.
   13.28 +     */
   13.29 +    private int mHideFlags;
   13.30 +
   13.31 +    /**
   13.32 +     * Flags to test against the first parameter in
   13.33 +     * {@link android.view.View.OnSystemUiVisibilityChangeListener#onSystemUiVisibilityChange(int)}
   13.34 +     * to determine the system UI visibility state.
   13.35 +     */
   13.36 +    private int mTestFlags;
   13.37 +
   13.38 +    /**
   13.39 +     * Whether or not the system UI is currently visible. This is cached from
   13.40 +     * {@link android.view.View.OnSystemUiVisibilityChangeListener}.
   13.41 +     */
   13.42 +    private boolean mVisible = true;
   13.43 +
   13.44 +    /**
   13.45 +     * Constructor not intended to be called by clients. Use
   13.46 +     * {@link SystemUiHider#getInstance} to obtain an instance.
   13.47 +     */
   13.48 +    protected SystemUiHiderHoneycomb(Activity activity, View anchorView, int flags) {
   13.49 +        super(activity, anchorView, flags);
   13.50 +
   13.51 +        mShowFlags = View.SYSTEM_UI_FLAG_VISIBLE;
   13.52 +        mHideFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
   13.53 +        mTestFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
   13.54 +
   13.55 +        if ((mFlags & FLAG_FULLSCREEN) != 0) {
   13.56 +            // If the client requested fullscreen, add flags relevant to hiding
   13.57 +            // the status bar. Note that some of these constants are new as of
   13.58 +            // API 16 (Jelly Bean). It is safe to use them, as they are inlined
   13.59 +            // at compile-time and do nothing on pre-Jelly Bean devices.
   13.60 +            mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
   13.61 +            mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
   13.62 +                    | View.SYSTEM_UI_FLAG_FULLSCREEN;
   13.63 +        }
   13.64 +
   13.65 +        if ((mFlags & FLAG_HIDE_NAVIGATION) != 0) {
   13.66 +            // If the client requested hiding navigation, add relevant flags.
   13.67 +            mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
   13.68 +            mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
   13.69 +                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
   13.70 +            mTestFlags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
   13.71 +        }
   13.72 +    }
   13.73 +
   13.74 +    /**
   13.75 +     * {@inheritDoc}
   13.76 +     */
   13.77 +    @Override
   13.78 +    public void setup() {
   13.79 +        mAnchorView.setOnSystemUiVisibilityChangeListener(mSystemUiVisibilityChangeListener);
   13.80 +    }
   13.81 +
   13.82 +    /**
   13.83 +     * {@inheritDoc}
   13.84 +     */
   13.85 +    @Override
   13.86 +    public void hide() {
   13.87 +        mAnchorView.setSystemUiVisibility(mHideFlags);
   13.88 +    }
   13.89 +
   13.90 +    /**
   13.91 +     * {@inheritDoc}
   13.92 +     */
   13.93 +    @Override
   13.94 +    public void show() {
   13.95 +        mAnchorView.setSystemUiVisibility(mShowFlags);
   13.96 +    }
   13.97 +
   13.98 +    /**
   13.99 +     * {@inheritDoc}
  13.100 +     */
  13.101 +    @Override
  13.102 +    public boolean isVisible() {
  13.103 +        return mVisible;
  13.104 +    }
  13.105 +
  13.106 +    private View.OnSystemUiVisibilityChangeListener mSystemUiVisibilityChangeListener
  13.107 +            = new View.OnSystemUiVisibilityChangeListener() {
  13.108 +        @Override
  13.109 +        public void onSystemUiVisibilityChange(int vis) {
  13.110 +            // Test against mTestFlags to see if the system UI is visible.
  13.111 +            if ((vis & mTestFlags) != 0) {
  13.112 +                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
  13.113 +                    // Pre-Jelly Bean, we must manually hide the action bar
  13.114 +                    // and use the old window flags API.
  13.115 +                    mActivity.getActionBar().hide();
  13.116 +                    mActivity.getWindow().setFlags(
  13.117 +                            WindowManager.LayoutParams.FLAG_FULLSCREEN,
  13.118 +                            WindowManager.LayoutParams.FLAG_FULLSCREEN);
  13.119 +                }
  13.120 +
  13.121 +                // Trigger the registered listener and cache the visibility
  13.122 +                // state.
  13.123 +                mOnVisibilityChangeListener.onVisibilityChange(false);
  13.124 +                mVisible = false;
  13.125 +
  13.126 +            } else {
  13.127 +                mAnchorView.setSystemUiVisibility(mShowFlags);
  13.128 +                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
  13.129 +                    // Pre-Jelly Bean, we must manually show the action bar
  13.130 +                    // and use the old window flags API.
  13.131 +                    mActivity.getActionBar().show();
  13.132 +                    mActivity.getWindow().setFlags(
  13.133 +                            0,
  13.134 +                            WindowManager.LayoutParams.FLAG_FULLSCREEN);
  13.135 +                }
  13.136 +
  13.137 +                // Trigger the registered listener and cache the visibility
  13.138 +                // state.
  13.139 +                mOnVisibilityChangeListener.onVisibilityChange(true);
  13.140 +                mVisible = true;
  13.141 +            }
  13.142 +        }
  13.143 +    };
  13.144 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/app/src/main/res/layout/activity_main.xml	Thu Apr 23 10:53:54 2015 -0700
    14.3 @@ -0,0 +1,31 @@
    14.4 +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    14.5 +    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    14.6 +    android:layout_height="match_parent" android:background="#0099cc" tools:context=".MainActivity">
    14.7 +
    14.8 +    <!-- The primary full-screen view. This can be replaced with whatever view
    14.9 +         is needed to present your content, e.g. VideoView, SurfaceView,
   14.10 +         TextureView, etc. -->
   14.11 +    <TextView android:id="@+id/fullscreen_content" android:layout_width="match_parent"
   14.12 +        android:layout_height="match_parent" android:keepScreenOn="true" android:textColor="#33b5e5"
   14.13 +        android:textStyle="bold" android:textSize="50sp" android:gravity="center"
   14.14 +        android:text="@string/dummy_content" />
   14.15 +
   14.16 +    <!-- This FrameLayout insets its children based on system windows using
   14.17 +         android:fitsSystemWindows. -->
   14.18 +    <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"
   14.19 +        android:fitsSystemWindows="true">
   14.20 +
   14.21 +        <LinearLayout android:id="@+id/fullscreen_content_controls" style="?metaButtonBarStyle"
   14.22 +            android:layout_width="match_parent" android:layout_height="wrap_content"
   14.23 +            android:layout_gravity="bottom|center_horizontal"
   14.24 +            android:background="@color/black_overlay" android:orientation="horizontal"
   14.25 +            tools:ignore="UselessParent">
   14.26 +
   14.27 +            <Button android:id="@+id/dummy_button" style="?metaButtonBarButtonStyle"
   14.28 +                android:layout_width="0dp" android:layout_height="wrap_content"
   14.29 +                android:layout_weight="1" android:text="@string/dummy_button" />
   14.30 +
   14.31 +        </LinearLayout>
   14.32 +    </FrameLayout>
   14.33 +
   14.34 +</FrameLayout>
    15.1 --- a/app/src/main/res/layout/activity_picking_songs.xml	Mon Apr 20 17:11:10 2015 +0300
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,31 +0,0 @@
    15.4 -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    15.5 -    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    15.6 -    android:layout_height="match_parent" android:background="#0099cc" tools:context=".PickingSongs">
    15.7 -
    15.8 -    <!-- The primary full-screen view. This can be replaced with whatever view
    15.9 -         is needed to present your content, e.g. VideoView, SurfaceView,
   15.10 -         TextureView, etc. -->
   15.11 -    <TextView android:id="@+id/fullscreen_content" android:layout_width="match_parent"
   15.12 -        android:layout_height="match_parent" android:keepScreenOn="true" android:textColor="#33b5e5"
   15.13 -        android:textStyle="bold" android:textSize="50sp" android:gravity="center"
   15.14 -        android:text="@string/dummy_content" />
   15.15 -
   15.16 -    <!-- This FrameLayout insets its children based on system windows using
   15.17 -         android:fitsSystemWindows. -->
   15.18 -    <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"
   15.19 -        android:fitsSystemWindows="true">
   15.20 -
   15.21 -        <LinearLayout android:id="@+id/fullscreen_content_controls" style="?metaButtonBarStyle"
   15.22 -            android:layout_width="match_parent" android:layout_height="wrap_content"
   15.23 -            android:layout_gravity="bottom|center_horizontal"
   15.24 -            android:background="@color/black_overlay" android:orientation="horizontal"
   15.25 -            tools:ignore="UselessParent">
   15.26 -
   15.27 -            <Button android:id="@+id/dummy_button" style="?metaButtonBarButtonStyle"
   15.28 -                android:layout_width="0dp" android:layout_height="wrap_content"
   15.29 -                android:layout_weight="1" android:text="@string/dummy_button" />
   15.30 -
   15.31 -        </LinearLayout>
   15.32 -    </FrameLayout>
   15.33 -
   15.34 -</FrameLayout>
    16.1 --- a/app/src/main/res/values/strings.xml	Mon Apr 20 17:11:10 2015 +0300
    16.2 +++ b/app/src/main/res/values/strings.xml	Thu Apr 23 10:53:54 2015 -0700
    16.3 @@ -1,5 +1,5 @@
    16.4  <resources>
    16.5 -    <string name="app_name">FriendStream</string>
    16.6 +    <string name="app_name">MusicPlayer</string>
    16.7  
    16.8      <string name="dummy_button">Dummy Button</string>
    16.9      <string name="dummy_content">DUMMY\nCONTENT</string>