Showing posts with label step-by-step series. Show all posts
Showing posts with label step-by-step series. Show all posts

Implement Android MP3 Player using MediaPlayer

MediaPlayer class can be used to control playback of audio/video files and streams. It is a example to implement MP3 Player using MediaPlayer. Please note that you have to keep follow the State Diagram, otherwise IllegalStateException will be thrown.


Create a new Android Project in Eclipse, using the auto-generated code extend from ActionBarActivity.

The mp3 file is stored in /res/raw/vespers.mp3. Filename match with the following code in initMediaPlayer().

mediaPlayer = MediaPlayer.create(getActivity(), R.raw.vespers);

MainActivity.java
package com.example.androidmp3player;

import android.support.v7.app.ActionBarActivity;
import android.support.v4.app.Fragment;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {

Button btnStart, btnPause, btnStop, btnSeek;
TextView textState, textDuration, textPosition;

MediaPlayer mediaPlayer;

private int stateMediaPlayer;
private final int STATE_Idle = 0;
private final int STATE_Initialized = 1;
private final int STATE_Preparing = 2;
private final int STATE_Prepared = 3;
private final int STATE_Started = 4;
private final int STATE_Paused = 5;
private final int STATE_Stopped = 6;
private final int STATE_PlaybackCompleted = 7;
private final int STATE_End = 8;
private final int STATE_Error = 9;

public PlaceholderFragment() {
}

@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
initMediaPlayer();
}

@Override
public void onDestroy() {

Toast.makeText(getActivity(),
"release mediaPlayer",
Toast.LENGTH_LONG).show();
mediaPlayer.release();
mediaPlayer = null;
setPlayerState(STATE_End);

super.onDestroy();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
btnStart = (Button) rootView.findViewById(R.id.start);
btnPause = (Button) rootView.findViewById(R.id.pause);
btnStop = (Button) rootView.findViewById(R.id.stop);
btnSeek = (Button) rootView.findViewById(R.id.seekto);

btnStart.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {

if(stateMediaPlayer==STATE_Prepared
|| stateMediaPlayer==STATE_Started
|| stateMediaPlayer==STATE_Paused
|| stateMediaPlayer==STATE_PlaybackCompleted){
mediaPlayer.start();
setPlayerState(STATE_Started);

displayDurationPosition();
}else{
Toast.makeText(getActivity(),
"Play at Invalid state!",
Toast.LENGTH_LONG).show();
}
}
});

btnPause.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {

if(stateMediaPlayer==STATE_Started
|| stateMediaPlayer==STATE_Paused
|| stateMediaPlayer==STATE_PlaybackCompleted){
mediaPlayer.pause();
setPlayerState(STATE_Paused);

displayDurationPosition();
}else{
Toast.makeText(getActivity(),
"Pause at Invalid state!",
Toast.LENGTH_LONG).show();
}
}
});

btnStop.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {

if(stateMediaPlayer==STATE_Prepared
|| stateMediaPlayer==STATE_Started
|| stateMediaPlayer==STATE_Stopped
|| stateMediaPlayer==STATE_Paused
|| stateMediaPlayer==STATE_PlaybackCompleted){

//Stop
mediaPlayer.stop();
setPlayerState(STATE_Stopped);

//then parepare in background thread
mediaPlayer.prepareAsync();
setPlayerState(STATE_Preparing);

displayDurationPosition();
}else{
Toast.makeText(getActivity(),
"Stop at Invalid state!",
Toast.LENGTH_LONG).show();
}

}
});

btnSeek.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
if(stateMediaPlayer==STATE_Prepared
|| stateMediaPlayer==STATE_Started
|| stateMediaPlayer==STATE_Paused
|| stateMediaPlayer==STATE_PlaybackCompleted){
mediaPlayer.seekTo(0);

displayDurationPosition();
}else{
Toast.makeText(getActivity(),
"SeekTo at Invalid state!",
Toast.LENGTH_LONG).show();
}
}});

mediaPlayer.setOnPreparedListener(new OnPreparedListener(){

@Override
public void onPrepared(MediaPlayer mp) {
setPlayerState(STATE_Prepared);
displayDurationPosition();
}});

mediaPlayer.setOnCompletionListener(new OnCompletionListener(){

@Override
public void onCompletion(MediaPlayer mp) {
setPlayerState(STATE_PlaybackCompleted);
displayDurationPosition();
}});

textState = (TextView) rootView.findViewById(R.id.state);
textState.setText(getPlayerState());

textDuration = (TextView) rootView.findViewById(R.id.duration);
textPosition = (TextView) rootView.findViewById(R.id.position);
displayDurationPosition();

textDuration.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
displayDurationPosition();
}});

textPosition.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
displayDurationPosition();
}});

return rootView;
}

private void displayDurationPosition(){
textDuration.setText(
"Duration: " + mediaPlayer.getDuration() + " ms");
textPosition.setText(
"Current Position: " + mediaPlayer.getCurrentPosition() + " ms");
}

private void initMediaPlayer() {
Toast.makeText(getActivity(),
"initMediaPlayer()",
Toast.LENGTH_LONG).show();
mediaPlayer = MediaPlayer.create(getActivity(), R.raw.vespers);
setPlayerState(STATE_Prepared);
}

private void setPlayerState(int st){
stateMediaPlayer = st;

String stringState = getPlayerState();
if(textState!=null){
textState.setText(stringState);
}else{
Toast.makeText(getActivity(),
stringState, Toast.LENGTH_LONG).show();
}

}

private String getPlayerState(){
String strSt;
switch(stateMediaPlayer){
case STATE_Idle:
strSt = "Idle";
break;
case STATE_Initialized:
strSt = "Initialized";
break;
case STATE_Preparing:
strSt = "Preparing";
break;
case STATE_Prepared:
strSt = "Prepared";
break;
case STATE_Started:
strSt = "Started";
break;
case STATE_Paused:
strSt = "Paused";
break;
case STATE_Stopped:
strSt = "Stopped";
break;
case STATE_PlaybackCompleted:
strSt = "PlaybackCompleted";
break;
case STATE_End:
strSt = "End";
break;
case STATE_Error:
strSt = "Error";
break;
default:
strSt = "unknown...";
}
return strSt;
}
}

}

fragment_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.androidmp3player.MainActivity$PlaceholderFragment" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<Button
android:id="@+id/start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start" />
<Button
android:id="@+id/pause"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Pause" />
<Button
android:id="@+id/stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Stop" />
<Button
android:id="@+id/seekto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Seek To Beginning" />
<TextView
android:id="@+id/state"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/duration"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/position"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

</LinearLayout>

Auto generated activity_main.xml.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.androidmp3player.MainActivity"
tools:ignore="MergeRootFrame" />


download filesDownload the files (not include the mp3 file).

Next:
- Implement OnErrorListener.
- Re-set On..Listener after mediaPlayer.release and re-create MediaPlayer
- Implement time bar for MediaPlayer, also introduce bug of MediaPlayer.seekTo()

Runnable in background thread

This exercise show how to run a Runnable in background.
Runnable in background thread
Runnable in background thread

In this exercise, we need to check if the current thread is the main thread, or called UI thread. Using the code:

Looper.getMainLooper().getThread()==Thread.currentThread()

If it's true, means it's in main thread, otherwise it's in background thread.

The example show how to implement a Thread with Runnable object. And call its start() method to starts the new Thread of execution. Also notice that if you call its run() method, it will calls the run() method of the Runnable object directly, in current thread.

package com.example.androidthread;

import android.os.Bundle;
import android.os.Looper;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity {

Button buttonStart, buttonRun;
TextView textInfo;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
buttonStart = (Button)findViewById(R.id.buttonstart);
buttonRun = (Button)findViewById(R.id.buttonrun);
textInfo = (TextView)findViewById(R.id.info);

buttonStart.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
Thread thread = new Thread(new MyRunnable());
thread.start(); //in background thread
}});

buttonRun.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
Thread thread = new Thread(new MyRunnable());
thread.run(); //in current thread
}});
}

private class MyRunnable implements Runnable {

@Override
public void run() {
// check if it's run in main thread, or background thread
if(Looper.getMainLooper().getThread()==Thread.currentThread()){
//in main thread
textInfo.setText("in main thread");
}else{
//in background thread

runOnUiThread(new Runnable(){

@Override
public void run() {
textInfo.setText("in background thread");
}

});
}
}

}

}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />
<Button
android:id="@+id/buttonstart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="start()" />
<Button
android:id="@+id/buttonrun"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="run()" />
<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>


More example about Thread:
- Set name of Thread
- Share object between threads with synchronized methods
- Share object between threads with synchronized Statements
- Synchronized Statements with separate lock object, I
- Synchronized Statements with separate lock object, II
- Example of using Lock/ReentrantLock
- Solve Producer–consumer problem with wait() and notifyAll()

ActionBarCompat

Back to when Android 4.3 and Nexus 7 announced, Google released a new backward-compatible Action Bar implementation called ActionBarCompat that's part of the Support Library r18. The ActionBarCompat APIs let you build the essential Action Bar design pattern into your app, with broad compatibility back to Android 2.1.

The post in Android Developers Blog helps you get started with ActionBarCompat, from setting up the Support Library to adding an Action Bar to your UI.


An introduction to this new support library, which allows you to add a compatible Action Bar to your application, targeting Android v2.1 or newer. This DevByte covers integrating the library, from adding it as a dependency to modifying your resources and code.

For more information you can visit -
http://developer.android.com/guide/topics/ui/actionbar.html




ActionBarCompat Step-by-step:

Example of ViewAnimator

android.widget.ViewAnimator is a subclass of FrameLayout container that will perform animations when switching between its views.



<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://arteluzevida.blogspot.com/"
android:textStyle="bold" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<Button
android:id="@+id/prev"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="previous" />

<Button
android:id="@+id/next"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="next" />
</LinearLayout>

<ViewAnimator
android:id="@+id/viewanimator"
android:layout_width="match_parent"
android:layout_height="wrap_content" >

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView 1" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 2" />

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 3" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center" >

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="- Button 4 -" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LinearLayout 4" />
</LinearLayout>
</ViewAnimator>

</LinearLayout>


package com.example.androidviewanimator;

import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ViewAnimator;

public class MainActivity extends Activity {

Button buttonPrev, buttonNext;
ViewAnimator viewAnimator;

Animation slide_in_left, slide_out_right;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

buttonPrev = (Button)findViewById(R.id.prev);
buttonNext = (Button)findViewById(R.id.next);
viewAnimator = (ViewAnimator)findViewById(R.id.viewanimator);

slide_in_left = AnimationUtils.loadAnimation(this, android.R.anim.slide_in_left);
slide_out_right = AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right);

viewAnimator.setInAnimation(slide_in_left);
viewAnimator.setOutAnimation(slide_out_right);

buttonPrev.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
viewAnimator.showPrevious();
}});

buttonNext.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
viewAnimator.showNext();
}});
}

}





more related example:

Something about processing images in Android

I will do some trial experience about image in Android programming. The list here will be updated once posted.

Related demo video:

The exercises have not take care the bitmap size, and any resizing. So don't test with big picture, otherwise OutOfMemoryError or "Bitmap too large to be uploaded into a texture" will happen.

YouTube Android Player API step-by-step

The YouTube Android Player API enables you to incorporate video playback functionality into your Android applications. The API defines methods for loading and playing YouTube videos (and playlists) and for customizing and controlling the video playback experience.

Using the API, you can load or cue videos into a player view embedded in your application's UI. You can then control playback programmatically. For example, you can play, pause, or seek to a specific point in the currently loaded video.

You can also register event listeners to get callbacks for certain events, such as the player loading a video or the player state changing. Finally, the API has helper functionality to support orientation changes as well as transitions to fullscreen playback.






Develop Android App with YouTube Android Player API step-by-step:

Related: