Shakeitupcodelab

Shake It Up: A Gyroscopic RxJava Boombox. In this android code lab you will build a music player that uses device sensors and RxJava concepts. When you are done, you will have an android app that plays music - but only when you are dancing.
Alternatives To Shakeitupcodelab
Project NameStarsDownloadsRepos Using ThisPackages Using ThisMost Recent CommitTotal ReleasesLatest ReleaseOpen IssuesLicenseLanguage
Listenermusicplayer2,269
6 years ago18Java
A Grace Material Design Music Player
Boring248
6 years ago7Java
Android毕业设计; Android, Music Player, for graduation
Musicplayer Smartisan208
2 months agoJava
锤子音乐播放器,仿照锤子系统音乐播放器写的一个本地播放器,具有常用的基本功能。
Moemusic140
6 years ago2Java
一款基于萌否网站api的音乐管理软件
Dmusic130
a year ago3apache-2.0Java
DMusic Player for Android - An online music player based on Component + MVP Base + MVP Customization + greenDAO + OkHttp3 + Retrofit + RxJava2; supports local and network music playback; can play Baidu music, Netease cloud music; support online music list , radio, MV, music online, download, local and online lyrics; Lyrics, music cache; self-built song list, song management, collection, sorting, sorting, skinning, sleep timing, mode switching, more settings, etc. 基于 Component + MVP Base + MVP Customization + greenDAO + OkHttp3 + Retrofit + RxJava2 的在线音乐播放器; 支持本地及网络音乐播放; 可播放百度音乐,网易云音乐; 支持在线音乐榜单, 电台, MV, 音乐在线播放,下载, 本地及在线歌词; 歌词, 音乐缓存; 自建歌单, 歌曲管理, 收藏, 排序, 分类, 换肤, 睡眠定时, 模式切换, 更多设置等
Neteasemusic57
3 years agon,ullJava
Material Design NetEase Music Player In MVP Pattern Design 网易云音乐
Androidopensourceproject55
4 years agoPython
Android完整的开源项目汇总
Android Music App53
5 years agoapache-2.0Kotlin
Simplified version of Melophile.
Goonj9
3 years agon,ullmitKotlin
A music player library that supports stream playback with download feature, remote playback, and analytics. It is build on Exo-Player and Google Cast framework.
Emilia7
4 years ago1Java
Material Design Music Player (neteasy api)
Alternatives To Shakeitupcodelab
Select To Compare


Alternative Project Comparisons
Readme

ShakeItUp

Overview

RxJava is a Functional Reactive Paradigm. It is essentially the Observer pattern, but taken to the extreme. In the simplest of cases you have standard observables and observers. The real power of Reactive Extensions comes from chaining observables in a functional paradigm. This requires a bit of a mind shift from standard Object oriented programming so do not expect to fully grok it today. The goal of this codelab is to play with RxJava a bit using a fun project. Hopefully by the end you will see a little bit of the power that RxJava provides to Android Development. Some of the things that we will touch on briefly include:

  • How to turn a callback into an observable using a Subject
  • How to take multiple observables and combine the results into a cohesive unit.
  • How to put operations on a background thread and recieve the result on another thread.
  • How to mutate data by chaining Observables in a functional way. (Do not hold state)
  • A grab bag of operators.

The Codelab starts intentionally slow. Everyone leaving should have a finished app that plays music only while the user is dancing within an hour or so. For those more advanced or wanting to explore more there are open ended further steps at the end. Feel free to move ahead at your own pace. If you get stuck don't worry. There is a corresponding branch for each checkpoint in this repo. Feel free to checkout the code and look through the commit history. I tried to keep them super small and targeted.

Checkpoint 0 - Bootstrap an application

  • Open Android Studio and update everything. Either click on Help->Check for updates if a project is open, or Configurations -> Check for updates if a project is not open.
  • Create a new android project. Target api 19+ and choose empty activity.
  • Navigate to AndroidManifest.xml and declare your activity as fixed to portrait orientation (For simplicity sake we will do all our work in this activity and do not wish it to rotate. As an exercise later you can extract logic to a background service that will persist accross configuration change and allow playing music while the app is backgrounded).
        <activity android:name=".MainActivity"
                android:screenOrientation="portrait" >
  • Create a "raw" resources directory by right-clicking src/main/res and selecting new resource directory.
  • Add one or more of you favorite .mp3 files to the raw folder. Ensure the file names are snake cased (b/c that is what we do with resource files)

Checkpoint 1 - Implement a music player that plays and pauses an mp3 on button clicks.

  • Add two buttons to your activities layout with text for play and pause.
  • Implement a MusicPlayer that wraps and android MediaPlayer instance. Give it lifecycle methods for create, destroy, play and pause.
  • Play and Pause functionality of the MusicPlayer should not interact with the MediaPlayer if it is currently playing or paused respectively. (This will be important later)
  • Initialize your MusicPlayer on the activity's onCreate() method and release it onDestroy().
  • Give a View.OnClickListener() to each of the buttons that performs the play and pause functionality on the music player.
  • Test your implementation.

Checkpoint 2 - Add RxJava, RxAndroid, and Retrolambda to your project.

  • Add Retrolambda to your project. Navigate to your app level build.gradle. Apply the following buildscript and apply the retrolambda plugin. This will allow you to use lambdas even though Android is currently limited to java 7. This is not necessary, but cleans up the code and makes it much more readable.
buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath 'me.tatarka:gradle-retrolambda:3.2.4'
        }
}
  • Add the following lines to the compile block of your app level build.gradle to import RxJava and RxAndroid dependencies. The latest versions can be found on the RxAndroid Github ReactiveX/RxAndroid
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.1'
  • In the Android block of your build.gradle add the following compile options.
compileOptions {
    targetCompatibility 1.8
    sourceCompatibility 1.8
}
  • Clean and compile your app. Test it and ensure everything is still working.

Checkpoint 3 - Make observables of the Accelerometers X,Y, and Z values.

In this step we will be taking a callback provided by an external dependency and turn it into a stream of events using a PublishSubject. While not necessary we will be creating an Observable for the emmited x, y , and z values. This will allow us to demonstrate one of the most useful Operators for Android Development.

  • Using the following lines of code register a listener to the accelerometer.
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
final Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(sensorEventListener, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
sensorEventListener = new SensorEventListener() {
    @Override
    public void onSensorChanged(final SensorEvent event) {
    }

   @Override
   public void onAccuracyChanged(final Sensor sensor, final int accuracy) {
   }
};
  • Create three PublishSubject's in your activity using the PublishSubject.create() method.
  • In the onSensorChanged method publish the events to your PublishSubject using the onNext() method with each of your sensor values.
  • In on Start you can now subscribe to one of your PublishSubject's like so
Disposable disposable = xValue.subscribe(new Consumer<Float>() {
               @Override
               public void accept(Float aFloat) throws Exception {
                   Log.i(MainActivity.class.getSimpleName(), "Received xValue " + aFloat);
               }
           });`
  • Make sure you dispose of your disposable in the appropriate lifecycle method to ensure we do not have a memory leak. When using sensors this is important because the service is longer lived than our activity.
  • If Retrolambda is correctly configured you can the reduce this to a lambda using alt+enter
disposable = xValue.subscribe(aFloat -> Log.i(TAG, "Received xValue " + aFloat));
  • At this point you should be observing the xValues emitted by the accelerometer and logging them to the android monitor. Run the app and (carefully) shake your phone to ensure they are correctly being emitted.

Checkpoint 4 - RxJava All the Things!

In this step we will use a functional reactive paradigm to do the following while holding no state in our activity.

  1. Combine the latest emission from our three observables into a single event.
  2. Sample these events every N milliseconds to ensure we can process the output before the next event hits (see Backpressure)
  3. Move to the computation thread because we are going to crunch some numbers
  4. Calculate a moving weighted average with the squared magnitude of the last 10 events
  5. Move onto a new thread strictly dedicated to interacting with the Music Player
  6. If the weighted average is above a reasonable threshold for activity play the music. Otherwise pause it.

So instead of a guided walkthrough let's just look at the code. Take a few minutes and try to grasp what is going on here, and ponder the power of using RxJava over doing the same work in a callback.

//Combine the latest x, y, and z sensor values and emit the combination as a list of Floats.
disposable = Observable.combineLatest(xValue, yValue, zValue, (x, y, z) -> Arrays.asList(x, y, z))
                //Sample the latest event every 20 seconds to limit backpressure
                .sample(20, TimeUnit.MILLISECONDS)
                //From here on go to the computation thread
                .subscribeOn(Schedulers.computation())
                //Turn the list of Floats into a Magnitude
                .map(floats -> {
                    float magnitude = 0;
                    for(Float aFloat : floats){
                        magnitude += aFloat * aFloat;
                    }
                    return magnitude;
                })
                //Accumulate the last 10 magnitude events in an Evicting Queue (you can write one if you are against Guava)
                .scan(EvictingQueue.create(EVENT_COUNT), (BiFunction<EvictingQueue<Float>, Float, EvictingQueue<Float>>) (objects, aFloat) -> {
                    objects.add(aFloat);
                    return objects;
                })
                //Take the last accumulated events and calculate an average
                .map(floats -> {
                    float sum = 0;
                    for(Float foo : floats){
                        sum += foo;
                    }
                    return sum/ EVENT_COUNT;
                })
                //Move onto a new thread to interact with the music player
                .observeOn(Schedulers.newThread())
                .subscribe(weightedMagnitude -> {
                    Log.e("Music", "weighted magnitude was " + weightedMagnitude);
                    if (weightedMagnitude != null && weightedMagnitude > MUSIC_THRESHOLD) {
                        audioPlayer.play();
                    } else {
                        audioPlayer.pause();
                    }
                });

Congrats you made an app. Time to dance and socialize! (or keep hacking and make something even cooler)

Next Steps: A few Ideas

  • Turn you MusicPlayer into an observable that emits progress for the mp3. Show progress on screen as the user plays the file.
  • Adjust the volume of the device track based on the vigor of the shake.
  • Show mp3's in a recycler view. Allow user to select which mp3 they wish to listen to.
  • Move the music player out of the activity and into a background service. Allowing the music to be played while the screen is off.
  • Show a persistent notification when the user has opened the app. Allow them to turn off activity sensing from it.
  • Create a home screen widget that displays if the app is tracking movement. Allow the user to toggle it from there
  • Sense different types of movement and play a different sound file (ex Walking, Cycling, Runnning, Jumping)
  • Make an Android Things music player, using an accelerometer and speaker.

Further reading and resources.

  • Dan Lew made a great series of posts about the basics of RxJava. I visit his posts often as I am working and come accross new questions. Be aware that some of the methods called have changed with the advent of RxJava2, but many of the ideas are still relevant. http://blog.danlew.net/2014/09/15/grokking-rxjava-part-1/
  • Marble diagrams are a great way to visualize how some the Rx operators function on an observable. Many of the most common operators are covered here http://rxmarbles.com/
  • Get info straight from the horses mouth and visit http://reactivex.io/ . This is usually not my first stop, but is definitely the most comprehensive.
  • Rx-Ify your views using Jake Wharton's RxBindings library. This is also great to read to help understand how to turn an external dependency into an observable. JakeWharton/RxBinding
  • Rx-ify your SQLite3 database. square/sqlbrite
  • Rx-ify your networking stack using Retrofit RxAdapters. This is really useful for combining requests, chaining requests, mapping responses, error handling etc. How often do we have to do mashups of several Api's?! https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava
Popular Rxjava Projects
Popular Music Player Projects
Popular Control Flow Categories

Get A Weekly Email With Trending Projects For These Categories
No Spam. Unsubscribe easily at any time.
Java
Play Framework
Rxjava
Observables
Music Player