Show progressbar while preparing music and increase music volume - android

I'm developing a radio app in which I have written MediaPlayer class inside Service,on button click starting and closing service to start and stop MediaPlayer.But in the project I'm facing two problems
1.I want to show progress while preparing music.although I have written code inside service so not able to show ProgressBar.
2.when we volume up then instead of music volume ringing volume is increasing.
I spent my lot time and didn't get success can any please tell me how to resolve this.Your valuable suggestion would be great appreciated.
PlayerService.java
public class PlayerService extends Service implements OnPreparedListener {
private MediaPlayer mPlayer;
public PlayerService() {
// TODO Auto-generated constructor stub
super();
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
try {
mPlayer = new MediaPlayer();
mPlayer.setDataSource(Live.mUrl);
mPlayer.prepare();
mPlayer.setOnPreparedListener(this);
// mVisualizerView = (VisualizerView)
// findViewById(R.id.visualizerView);
// mVisualizerView.link(mPlayer);
// Start with just line renderer
// addLineRenderer();
} catch (Exception e) {
// TODO: handle exception
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mPlayer.start();
return 0;
}
#Override
public void onDestroy() {
mPlayer.release();
super.onDestroy();
}
#Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
}
}

Check out registerMediaButtonEventReceiver(ComponentName broadcastReceiver);
Define a BroadcastReceiver that handles ACTION_MEDIA_BUTTON. The recieved intent includes a single extra field, EXTRA_KEY_EVENT, containing the key event that caused the broadcast. You can use this key event to get which key was pressed.
This is just a sample code. syntax errors may be there.
// in onCreate of activity
registerMediaButtonEventReceiver(mediaReceiver );
// later somewhere in activity.
MediaButton_Receiver mediaReceiver = new MediaButton_Receiver();
class MediaButton_Receiver implements BroadcastReceiver {
void onReceive(Intent intent) {
KeyEvent ke = (KeyEvent)intent.getExtra(Intent.EXTRA_KEY_EVENT);
if (ke .getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) {
//Decrease your volume
}
// Similarly other key codes .......
}
}
Unregister the receiver in onPause() or onStop()

Related

How to play music in the background through out the App continuously?

I have 4 activities in my android app.When the first activity is created, it starts music in the background. Now when the user goes from 1st activity to the 2nd activity I want the song to continue without any interruption. The song should stop only when the user is out of the app.
Right now the music stops when I am going out of one activity and starts from the beginning in the next activity.
Keep the player in the background as a static reference. Then let it know if you are moving within the app or out of it. Here is how I would do it. I am using a class named DJ for this purpose.
public class DJ {
private static MediaPlayer player;
private static boolean keepMusicOn;
public static void iAmIn(Context context){
if (player == null){
player = MediaPlayer.create(context, R.raw.music1);
player.setLooping(true);
try{
player.prepare();
}
catch (IllegalStateException e){}
catch (IOException e){}
}
if(!player.isPlaying()){
player.start();
}
keepMusicOn= false;
}
public static void keepMusicOn(){
keepMusicOn= true;
}
public static void iAmLeaving(){
if(!keepMusicOn){
player.pause();
}
}
}
Now from your Activity call the DJ like this.(Let him know if you would like to keep the music on)
public void onPause() {
super.onPause();
DJ.iAmLeaving();
}
public void onResume(){
super.onResume();
DJ.iAmIn(this);
}
public void buttonOnClick(View view){
DJ.keepMusicOn();
Intent intent = new Intent(this, TheOtherActivity.class);
startActivity(intent);
}
I did it this way and I'm pleased with the result:
1st create the service:
public class LocalService extends Service
{
// This is the object that receives interactions from clients. See RemoteService for a more complete example.
private final IBinder mBinder = new LocalBinder();
private MediaPlayer player;
/**
* Class for clients to access. Because we know this service always runs in
* the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder
{
LocalService getService()
{
return LocalService.this;
}
}
#Override
public void onCreate()
{
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// We want this service to continue running until it is explicitly stopped, so return sticky.
return START_STICKY;
}
#Override
public void onDestroy()
{
destroy();
}
#Override
public IBinder onBind(Intent intent)
{
return mBinder;
}
public void play(int res)
{
try
{
player = MediaPlayer.create(this, res);
player.setLooping(true);
player.setVolume(0.1f, 0.1f);
player.start();
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void pause()
{
if(null != player && player.isPlaying())
{
player.pause();
player.seekTo(0);
}
}
public void resume()
{
try
{
if(null != player && !player.isPlaying())
{
player.start();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void destroy()
{
if(null != player)
{
if(player.isPlaying())
{
player.stop();
}
player.release();
player = null;
}
}
}
2nd, create a base activity and extend all your activities in witch you wish to play the background music from it:
public class ActivityBase extends Activity
{
private Context context = ActivityBase.this;
private final int [] background_sound = { R.raw.azilum_2, R.raw.bg_sound_5 };
private LocalService mBoundService;
private boolean mIsBound = false;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
doBindService();
}
#Override
protected void onStart()
{
super.onStart();
try
{
if(null != mBoundService)
{
Random rand = new Random();
int what = background_sound[rand.nextInt(background_sound.length)];
mBoundService.play(what);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
#Override
protected void onStop()
{
super.onStop();
basePause();
}
protected void baseResume()
{
try
{
if(null != mBoundService)
{
mBoundService.resume();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
protected void basePause()
{
try
{
if(null != mBoundService)
{
mBoundService.pause();
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
private ServiceConnection mConnection = new ServiceConnection()
{
public void onServiceConnected(ComponentName className, IBinder service)
{
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. Because we have bound to a explicit
// service that we know is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
mBoundService = ((LocalService.LocalBinder) service).getService();
if(null != mBoundService)
{
Random rand = new Random();
int what = background_sound[rand.nextInt(background_sound.length)];
mBoundService.play(what);
}
}
public void onServiceDisconnected(ComponentName className)
{
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
mBoundService = null;
if(null != mBoundService)
{
mBoundService.destroy();
}
}
};
private void doBindService()
{
// Establish a connection with the service. We use an explicit
// class name because we want a specific service implementation that
// we know will be running in our own process (and thus won't be
// supporting component replacement by other applications).
Intent i = new Intent(getApplicationContext(), LocalService.class);
bindService(i, mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
private void doUnbindService()
{
if (mIsBound)
{
// Detach our existing connection.
unbindService(mConnection);
mIsBound = false;
}
}
#Override
protected void onDestroy()
{
super.onDestroy();
doUnbindService();
}
}
And that's it, now you have background sound in all the activities that are extended from ActivityBase.
You can even control the pause / resume functionality by calling basePause() / baseResume().
Don't forget to declare the service in manifest:
<service android:name="com.gga.screaming.speech.LocalService" />
The idea is that you should not play music from the activity itself. On Android, Activities, and other contexts, have life cycles. It means they will live...and die. And when dead, they can't do anything any more.
So you gotta find something with a lifecycle that lasts more than a single activity if you want the music to live longer.
The easiest solution is an Android service. You can find a good thread here : Android background music service

Mediaplayer service not responding

The activity is calling for the service to play but it does not start. It should prompt the user for the time and then play for that amount of time. I dont have any errors in the logcat.
public class Ship extends Activity implements View.OnClickListener {
public static final Integer[] TIME_IN_MINUTES = { 30, 45, 60, 180, 360 };
public MediaPlayer mediaPlayer;
public Handler handler = new Handler();
public Button button2;
public Spinner spinner2;
public PowerManager.WakeLock wl;
// Initialize the activity
#Override
public void onCreate(Bundle savedInstanceState) {
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Howaya");
super.onCreate(savedInstanceState);
wl.acquire();
setContentView(R.layout.ship);
button2 = (Button) findViewById(R.id.btn2);
button2.setOnClickListener(this);
spinner2 = (Spinner) findViewById(R.id.spinner2);
ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(this,
android.R.layout.simple_spinner_item, TIME_IN_MINUTES);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner2.setAdapter(adapter);
}
// Play the sound and start the timer
private void playSound(int resourceId) {
// Cleanup any previous sound files
cleanup();
// Create a new media player instance and start it
// Create the timer to stop the sound after x number of milliseconds
int selectedTime = TIME_IN_MINUTES[spinner2.getSelectedItemPosition()];
handler.postDelayed(runnable, selectedTime * 60 * 1000);
}
// Handle button callback
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn2:
startService(new Intent(this, Shipservice.class));
break;
}
}
protected void onDestroy() {
cleanup();
super.onDestroy();
}
// Stop the sound and cleanup the media player
public void cleanup() {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
// Cancel any previously running tasks
handler.removeCallbacks(runnable);
}
// Runnable task used by the handler to stop the sound
public Runnable runnable = new Runnable() {
public void run() {
cleanup();
}
};
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
wl.release();
}
}
Here is the service class that should be playing.
public class Shipservice extends Service {
static final String TAG=Shipservice.class.getSimpleName();
MediaPlayer player;
#Override
public IBinder onBind(Intent intent) {
return null;
// TODO Auto-generated method stub
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
player = MediaPlayer.create(this, R.raw.ocean_ship);
player.setLooping(false);
Log.d(TAG, "onCreate'd");
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d(TAG, "onDestroy'd");
}
#Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
Log.d(TAG, "onStart'd");
}
class ship extends Thread{
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
}
}
}
You didn't write code for playing media file.
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(//path to file);
mediaPlayer.prepare();
mediaPlayer.start();
write above code in onStartCommand() method in the service class if you want to play media using service. Note - media played by service will continue to play even if your activity is in background until system kills it. See this guide on how to use services. And consider this guide , how to use mediaplayer.

Getting Error in Media Player: SeekTo in wrong state: & start called in state 0

i am facing some issue in media player when i use as service.
1. If i initialize Media Player Object in Activity as static and further use in service class then its show me this error (-38, 0) , Attempt to perform seekTo in wrong state: mPlayer=0x0, mCurrentState=0 , start called in state 0.
2. If i initialize Media Player Object in Service class and user in activity for more
action its show's me Null Pointer.
public static MediaPlayer mPlayer = null;
play Click Event
Audio_Player_Play.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if (mPlayer == null)
{
Intent Play_Intent = new Intent(RDS_Singel_Audio.this,
Audio_Player.class);
startService(Play_Intent);
Audio_Player_Play.setVisibility(View.GONE);
Audio_Player_Pause.setVisibility(View.VISIBLE);
} else
{
// Play_Streaming();
mPlayer.seekTo(mPlayer.getCurrentPosition());
mPlayer.start();
Audio_Player_Play.setVisibility(View.GONE);
Audio_Player_Pause.setVisibility(View.VISIBLE);
}
}
});
Pause Click Event
Audio_Player_Pause.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
// Play_Streaming();
// checking is medai player running
Audio_Player_Play.setVisibility(View.VISIBLE);
Audio_Player_Pause.setVisibility(View.GONE);
// checking is audio playing in background
if (mPlayer != null && mPlayer.isPlaying())
{
mPlayer.pause();
/*
* Intent Pause_Intent = new Intent(RDS_Singel_Audio.this,
* Audio_Player.class); stopService(Pause_Intent);
*/
Audio_Player_Play.setVisibility(View.VISIBLE);
Audio_Player_Pause.setVisibility(View.GONE);
}
}
});
OnResume() - OnPause() -OnDistroy()
#Override
protected void onResume()
{
super.onResume();
}
#Override
protected void onPause()
{
// cleanUp();
if (mPlayer != null && mPlayer.isPlaying())
{
mPlayer.release();
mPlayer = null;
}
super.onPause();
}
#Override
protected void onDestroy()
{
cleanUp();
super.onDestroy();
}
private void cleanUp()
{
if (mPlayer != null)
{
mVisualizerView.release();
mPlayer.release();
mPlayer = null;
}
}
Service.Java
public class Audio_Player extends Service
{
private static final String TAG = "MyService";
// public static MediaPlayer mPlayer;
Function f;
RDS_Singel_Audio sa;
MediaPlayer mPlayer;
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onCreate()
{
try
{
sa = new RDS_Singel_Audio();
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG)
.show();
sa.mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
sa.mPlayer.setDataSource(sa.Audio_URL);
sa.mPlayer.prepare();// might take long! (for buffering, etc)
sa.mVisualizerView.link(sa.mPlayer);
sa.mPlayer.start();
sa.addLineRenderer();
sa.mPlayer.setLooping(false); // Set looping
// sa.mPlayer.start();
} catch (Exception e)
{
// TODO: handle exception
Log.d(TAG, "" + e);
}
}
#Override
public void onDestroy()
{
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
super.onDestroy();
if (sa.mPlayer != null)
{
sa.mPlayer.stop();
sa.mPlayer.release();
}
sa.mPlayer = null;
}
#Override
public void onStart(Intent intent, int startid)
{
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
// mPlayer.setDataSource("http://clients.ncrypted.net/riddimapp/images/audio/4/df9919ccb2880933c795f43d735cf9bc.mp3");
}
}
I found some link about same issue but I don't know how solve it.
Well, I see this part of your code, but it is not clear what you are trying to achieve. You are trying to make the player go to its current position, but it is already at that position? You could remove that part then.
// Play_Streaming();
mPlayer.seekTo(mPlayer.getCurrentPosition());
Also, on your onpause you're releasing the player, but not generating it again on your onresume. You can recreate it there with code from that link you provided:
#Override
protected void onResume()
{
super.onResume();
}
#Override
protected void onPause()
{
// cleanUp();
if (mPlayer != null && mPlayer.isPlaying())
{
mPlayer.release();
mPlayer = null;
}
super.onPause();
}
Also, as you seem to be setting the source of the mediaplayer to be an url, you should change the prepare for a prepareAsync in the following part, so that it buffers:
sa.mPlayer.setDataSource(sa.Audio_URL);
sa.mPlayer.prepare();// might take long! (for buffering, etc)
The link you provided already has a lot of suggestions for overcoming these problems above.
Please try the code on that link, especially the ones that suggest prepareAsync and the onprepared listener. Then you can get back here if it does not work.

How to get seekbar in activity from mediaplayer service?

I'm creating a mediaplayer service to play a media file from internet, like this:
public class MyService extends Service{
private static final String TAG = "MyService";
MediaPlayer mediaPlayer;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
mediaPlayer.stop();
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
String rtsp;
Bundle re= intent.getExtras();
rtsp=re.getString("rtsp");
try {
mediaPlayer.setDataSource(rtsp);
mediaPlayer.prepare();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mediaPlayer.start();
}
}
Now I want to get the seekbar from the activity like this:
SeekBar seekbar= (SeekBar)findviewbyid(R.id.seekbar);
But I can't :( Please help me how to do that!
EDIT
I found another way to solve my problem without using Bind service :)
Here it is:
In your service class, create a static method like this:
public static void setMainActivity(Player_Activity mainActivity)
{
MAIN_ACTIVITY=mainActivity;
}
Ofcourse, you must declare a static varible:
private static Player_Activity MAIN_ACTIVITY;
Next, in your activity, before you call the startService(), you must call this method to set the main activity to your service like this:
MyService.setMainActivity(Player_Activity.this);
Intent myservice= new Intent(this,MyService.class);
startService(myservice);
And finally you can do anything with your activity in your service like this:
final TextView tv_test=(TextView)MAIN_ACTIVITY.findViewById(R.id.textview);
That's all! Hope this help :)
Forgive me if I get some mistake about English ;), my English skill is not good :)
I know that it has been already answered. But I tried the below code which worked for me.May be useful for someone.
public class MediaPlayerService extends Service implements MediaPlayer.OnPreparedListener,MediaPlayer.OnCompletionListener{
String ExactPath;
int total,CurrentPosition;
MediaPlayer mp;
private final IBinder mBinder=new LocalBinder();
public class LocalBinder extends Binder {
MediaPlayerService getService(){
return MediaPlayerService.this;
}
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onCreate() {
mp=new MediaPlayer();
mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp.setOnPreparedListener(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
ExactPath=intent.getStringExtra("pos");
PrepareMediaPlayer();
if(!mp.isPlaying()){
mp.start();
}else{
mp.pause();
}
return START_STICKY;
}
public void PrepareMediaPlayer(){
try {
mp.setDataSource(ExactPath);
mp.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}catch (IllegalStateException e){ }
catch(IllegalFormatException e){ }
}
#Override
public void onPrepared(MediaPlayer mediaPlayer) {
mp.start();
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
stopSelf();
}
public int seekBarGetCurrentPosition(){ //This method is created to get SongCurrentPosition from mediaplayer for seekbar
if(mp!=null&&mp.isPlaying()){
CurrentPosition=mp.getCurrentPosition();
}
return CurrentPosition;
}
#Override
public void onDestroy() {
if(mp.isPlaying()){
mp.stop();
}
mp.release();
}
}
Note:In service class I had issue in getting MediaPlayer duration. I am not getting correct result when my activity requests duration from service. So I have implemented a method which gets the duration right from the activity. Hope you can fix duration in service itself. But this code worked for me.
Then in your Activity, after onCreate() method.
/**The below method songDuration() is created as substitution for getMediaPlayerDuration() method
* if getMediaPlayerDuration() failed to get the duration from mediaPlayer via service this method
* helps to avoid returning zero or null value . Because it has been observed that service takes
* quite a long time to return a value, if it is called frequently with in a span of seconds say, pressing
* Next button continuously.
*/
public int songDuration(){
MediaMetadataRetriever mmr=new MediaMetadataRetriever();
mmr.setDataSource(path);
String Dur=mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
Integer Duration=Integer.parseInt(Dur);
return Duration;
}
#Override
protected void onStart() {
super.onStart();
Intent intent=new Intent(Player.this,MediaPlayerService.class);
bindService(intent,mServiceConnection, Context.BIND_AUTO_CREATE);
getSeekBarStatus();//This method is called onBinding process so that it gets updated with player.
}
#Override
protected void onStop() {
super.onStop();
if(ServiceBinding){
unbindService(mServiceConnection);
ServiceBinding=false;
}
}
//This method gets the MediaPlayer Duration from service.
public int getMediaPlayerDuration(){
if(ServiceBinding){
if(mediaPlayerServiceObject.mp!=null){
Duration=mediaPlayerServiceObject.seekBarDuration();
}
}
return Duration;
}
//This method get MediaPlayerCurrent Position from service
public int getMediaPlayerCurrentPosition(){
if(ServiceBinding){
if(mediaPlayerServiceObject.mp!=null){
currentPosition=mediaPlayerServiceObject.seekBarGetCurrentPosition();
}
}
return currentPosition;
}
//This method is used to update seekBar status by getting Player Current Position from service.
public void getSeekBarStatus(){
new Thread(new Runnable() {
#Override
public void run() {
int total=songDuration();
int CurrentPosition=0;
seekBar.setMax(total);
while(CurrentPosition<total){
try {
Thread.sleep(1000);
CurrentPosition=getMediaPlayerCurrentPosition();
Log.d(TAG,String.valueOf(CurrentPosition));
} catch (InterruptedException e) {
return;
}seekBar.setProgress(CurrentPosition);
}
}
}).start();
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(final SeekBar seekBar, int ProgressValue, boolean fromUser) {
// if(fromUser){
// mp.seekTo(ProgressValue);
//}
final long Minutes=((ProgressValue/1000)/60);
final int Seconds=((ProgressValue/1000)%60);
SongProgress.setText(Minutes+":"+Seconds);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
private ServiceConnection mServiceConnection=new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
MediaPlayerService.LocalBinder binder=(MediaPlayerService.LocalBinder)iBinder;
mediaPlayerServiceObject=binder.getService();
ServiceBinding=true;
getSeekBarStatus();
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
stopService(PlayerServiceIntent);
onStop();
ServiceBinding=false;
}
};
You are playing media in service so to communicate with service you have to bind activity with service.
For more information about Bind see below document
Click here
EDIT
Also see below tutorial
Click Here

The behaviour of bind Service, MP still playing multiple files

I have a service bound to an activity. The activity is a ListView of playable files. The service plays a certain audio file, passed from the Activty. In the previous version I hadn't had the Service bind, so when clicking multiple times on a play element, multiple instances of sounds would occur. I thought I could solve this by binding the service, so I would communicate every time with the same instance, however it still plays multiple files if they are clicked. Maybe i understood the concept of binding wrong, I'm not sure, the android documentation is sometimes a bit vague and misleading. Here is my code, thanks for any input.
Activity:
public class ViewSounds extends ListActivity {
private PlayService myService;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
// Bind Service
Intent intent = new Intent(ViewSounds.this, PlayService.class);
getApplicationContext().bindService(intent, serviceConncetion, BIND_AUTO_CREATE);
// Get list vars
String[] lex_names = getResources().getStringArray(R.array.lex_names);
//final String[] lex_files = getResources().getStringArray(R.array.lex_files);
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_sounds, lex_names));
final ListView lv = getListView();
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//int playFile = getResources().getIdentifier(lex_files[position], "raw", getPackageName());
myService.playAudio();
}
});
}
private ServiceConnection serviceConncetion = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
myService = ((PlayService.MyBinder)service).getService();
}
#Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
myService = null;
}
};
#Override
public void onDestroy(){
super.onDestroy();
unbindService(serviceConncetion);
}
}
Service:
public class PlayService extends Service {
MediaPlayer player;
private final IBinder binder = new MyBinder();
#Override
public IBinder onBind(Intent intent) {
return binder;
}
public class MyBinder extends Binder {
PlayService getService() {
return PlayService.this;
}
}
#Override
public void onCreate() {
super.onCreate();
}
public void playAudio(){
// I hardcoded the file name for this preview
player = MediaPlayer.create(this, R.raw.no_harm);
player.setLooping(false); // Set looping
if (!player.isPlaying()) {
player.start();
}
}
public void onStart(Intent intent, int startId){
super.onStart(intent, startId);
Toast.makeText(this,"Service created ...", Toast.LENGTH_LONG).show();
// Get veriable from Activity
// int extras;
// extras = intent.getExtras().getInt("playFile");
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
You should stop playback of previous file before playing another file. In your code you actually creating new MediaPlayer for each new media file.
Here is how your playAudio should look like:
public void playAudio(){
// I hardcoded the file name for this preview
if(player != null){
player.release();
}
player = MediaPlayer.create(this, R.raw.no_harm);
player.setLooping(false); // Set looping
if (!player.isPlaying()) {
player.start();
}
}
But you should avoid creation of new media players for each new playback. You could do this next way:
public void playAudio(){
// I hardcoded the file name for this preview
if(player == null){
player = new MediaPlayer();
}
if(player.isPlaying()){
player.stop();
}
player.reset();
player.setLooping(false);
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){
#Override
void onPrepared(MediaPlayer mp){
mp.play();
}
});
player.prepareAsync();
}
You should also use onSetErrorListener(...) and onSetComlpletionListener(...) for more control over the player. So that your activity can react on state changes in MediaPlayer.

Categories

Resources