In our app we have a MusicService. Currently, it works perfectly fine in terms of playing music and stopping it, but that is from starting and stopping the service. We are calling it in other methods, but mp.pause() is crashing unless it is surrounded by a null checker. But when it checks for nulls it doesn't work at all. We had all this working earlier, but we started reformatting the way were doing it, because on Android 4.0 (ICS) the Music kept playing randomly even when we stopped it, but thats not the point anyway.
public class MusicService extends Service {
public static MediaPlayer mp;
#Override
public IBinder onBind(final Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mp = MediaPlayer.create(this, R.raw.title_music);
mp.setLooping(true);
mp.setVolume(200, 200);
}
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
mp.start();
return 1;
}
#Override
public void onStart(final Intent intent, final int startId) {
}
public IBinder onUnBind(final Intent arg0) {
return null;
}
public static void onStop() {
mp.stop();
mp.release();
}
public static void onPause() {
if (mp!=null) {
mp.pause();
}
}
public static void onResume() {
if (mp!=null) {
mp.start();
}
}
#Override
public void onDestroy() {
mp.stop();
mp.release();
super.onDestroy();
}
#Override
public void onLowMemory() {
mp.stop();
mp.release();
}
}
We are using this to start the service in another activity:
intent = new Intent(this, MusicService.class);
startService(intent);
Without a log I can't really say with 100% certainty this is the issue, but it would appear that the pause method is being called while mp is in an invalid state. I suggest you change your onPause method so that it reads like so.
public static void onPause() {
if (mp!=null) {
if (mp.isPlaying())
mp.pause();
}
}
This will check to see if it is actually playing and will work for any state it is in, except an error state. At least according to the documentation.
Related
I am trying to write a small android app for my son. The idea is to make ringtone start to play on button click and it should be stoped by clicking on the other button. Something like you click a button to start a calling and another button to answer to it.
What I manage to do is to make the first button to ring to work by the following code:
CallLukas.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
MediaPlayer mp = MediaPlayer.create(getApplicationContext(), notification);
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
}
});
However, the second button to stop the ringtone does not work as it suppose to. I use the following code:
Incoming.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mp.isPlaying()) {
mp.stop();
mp.release();
}
}
});
It stops the ringtone but in the same time makes the app to crash.
What would be the right way to stop the previously activated ringtone?
Thnak you...
This answer should help you.
I believe the problem is you're creating multiple MediaPlayer objects. Also try to use .reset() instead of .stop().
The solution for my issue was making the MediaPlayer as a service.
I have created a new Java class to extend the service class. Here is the code for it:
public class RingtoneService extends Service {
private MediaPlayer mp;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mp = MediaPlayer.create(this, Settings.System.DEFAULT_RINGTONE_URI);
mp.setLooping(true);
mp.start();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mp.stop();
}
}
Then I have updated my MainActivity class with the fallowing code:
CallLukas.setOnClickListener(this);
Incoming.setOnClickListener(this);
#Override
public void onClick(View v) {
if (v == CallLukas){
startService(new Intent(this, RingtoneService.class));
}else if (v == Incoming) {
stopService(new Intent(this, RingtoneService.class));
}
}
The code basically sets the OnClickListener on my buttons and starts the service if one is clicked and stops the service if the other is clicked.
The final steps are to add the newly created service to the AndroidManifest file. It needs to be added inside the <application> tag.
<application
<service android:name=".RingtoneService"></service>
</application>
The completed instruction on how to implement this can be found here:
https://www.youtube.com/watch?v=p2ffzsCqrs8&t=315s
How to make service (background music) to turn off when I close the app or turn off the screen, but not when I switch to another activity?
Currently Music plays fine, I lasts until the screen turn off or I close the app, but also close when I switch to another activity. It is probably caused by onStop and onPause assigned to every activity. Please help me solve this issue
My service:
public class MyService extends Service {
private final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.music;
player.setLooping(true); // Set looping
player.setVolume(100, 100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
public void onStart(Intent intent, int startId) {
// TO DO
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
protected void onStop() {
player.pause();
}
public void onPause() {
player.pause();
}
#Override
public void onDestroy() {
player.stop();
player.release();
}
#Override
public void onLowMemory() {
}
}
My example activity has this:
public void onPause() {
super.onPause();
stopService(new Intent(a.this, MyService.class));
}
public void onStop() {
super.onStop();
stopService(new Intent(a.this, MyService.class));
}
public void onResume() {
super.onResume();
startService(new Intent(a.this, MyService.class));
}
public void onRestart() {
super.onRestart();
startService(new Intent(a.this, MyService.class));
}
There are two ways i can suggest
1) let it be in onPause(), create a flag/boolean that will set to false by default and will be true in every-case such as new activity startup, on back press etc. so if onPause is called and flag is false you can stop the music.
2) you have background service already, you can keep checking which activity is in foreground, if is homeScreen you can stop the music.
Edit :- to know if your app is not in the foreground
check this link
this is good example
Use this code.
Remove this line:
player.pause();
public class MyService extends Service {
private final String TAG = null;
MediaPlayer player;
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
player = MediaPlayer.create(this, R.raw.music;
player.setLooping(true); // Set looping
player.setVolume(100, 100);
}
public int onStartCommand(Intent intent, int flags, int startId) {
player.start();
return 1;
}
public void onStart(Intent intent, int startId) {
// TO DO
}
public IBinder onUnBind(Intent arg0) {
// TO DO Auto-generated method
return null;
}
protected void onStop() {
//player.pause();
}
public void onPause() {
//player.pause();
}
#Override
public void onDestroy() {
//player.stop();
player.release();
}
#Override
public void onLowMemory() {
}
}
I know this question has been asked many times before and might seem to be a conglomeration of several questions, but I feel that it is relevant and important to many developers; I need to create a background music Service that can run across multiple activities for my Android game that ends when the application is terminated and pauses in all of the following circumstances:
A certain Activity that has its own music is started. (Resume when this Activity finishes. This happens to be an AndEngine activity.)
The home screen is pressed and the app is backgrounded, or the application is terminated. Resumes when the app returns to the foreground. Requires use of onUserLeaveHint(). Another helpful link.
The phone receives a call and interrupts the app. Resumes when the call has been dealt with. Requires use of TelephonyManager similar to this.
The screen is locked. (Resumes after screen has been unlocked.) Requires use of ACTION_USER_PRESENT, which seems to be very problematic.
Basically the music pauses whenever the app is not being shown or when the special activity from #1 is being shown to the user.
Above is all of what I need and the information I have pieced together. My current code basically resembles this.
I find it curious that AndEngine manages to have none of these issues with their music, so maybe looking in the source code would help someone looking for an answer. I'm using the last functional GLES1 version from Google Code.
I have taken a look at the following links as well on creating a good music Service:
Stopping Background Service Music
http://www.codeproject.com/Articles/258176/Adding-Background-Music-to-Android-App
Android background music service
Playing BG Music Across Activities in Android
http://www.rbgrn.net/content/307-light-racer-20-days-61-64-completion
I would like the solution Service to:
Minimize the use of BroadcastReceivers and Android Manifest additions/permissions if possible
Self contained and error checking
Other Notes
Currently all the activities that require the background music all extend a common special class.
The music needs to loop but only runs a single track.
Thanks to everyone ahead of time! Best of luck!
Edit - Here are code snippets, feel free to improve or ignore:
Media Player Wrapper
import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.preference.PreferenceManager;
import android.util.Log;
public class CarefulMediaPlayer {
final SharedPreferences sp;
final MediaPlayer mp;
private boolean isPlaying = false;
public CarefulMediaPlayer(final MediaPlayer mp, final MusicService ms) {
sp = PreferenceManager.getDefaultSharedPreferences(ms.getApplicationContext());
this.mp = mp;
}
public void start() {
if (sp.getBoolean("com.embed.candy.music", true) && !isPlaying) {
mp.start();
isPlaying = true;
}
}
public void pause() {
if (isPlaying) {
mp.pause();
isPlaying = false;
}
}
public void stop() {
isPlaying = false;
try {
mp.stop();
mp.release();
} catch (final Exception e) {}
}
}
Music Service
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
public class MusicService extends Service {
static CarefulMediaPlayer mPlayer = null;
#Override
public IBinder onBind(final Intent arg0) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
final MediaPlayer mp = MediaPlayer.create(this, R.raw.title_music);
mp.setLooping(true);
mPlayer = new CarefulMediaPlayer(mp,this);
}
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
mPlayer.start();
return 1;
}
#Override
public void onStart(final Intent intent, final int startId) {
}
public IBinder onUnBind(final Intent arg0) {
return null;
}
public static void onStop() {
mPlayer.stop();
}
public static void onPause() {
if (mPlayer!=null) {
mPlayer.pause();
}
}
public static void onResume() {
if (mPlayer!=null) {
mPlayer.start();
}
}
#Override
public void onDestroy() {
mPlayer.stop();
mPlayer = null;
}
#Override
public void onLowMemory() {
}
}
Improved Base Activity Class
import android.app.Activity;
import android.content.Intent;
import android.os.PowerManager;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
public abstract class BetterActivity extends Activity {
private boolean isHome = true;
#Override
protected void onResume() {
System.gc();
super.onResume();
MusicService.onResume();
isHome = true;
}
#Override
protected void onPause() {
if (((TelephonyManager)getSystemService(TELEPHONY_SERVICE)).getCallState()==TelephonyManager.CALL_STATE_RINGING
|| !((PowerManager)getSystemService(POWER_SERVICE)).isScreenOn()) {
MusicService.onPause();
}
super.onPause();
System.gc();
}
#Override
public boolean onKeyDown (final int keyCode, final KeyEvent ke) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
isHome = false;
default:
return super.onKeyDown(keyCode, ke);
}
}
#Override
public void startActivity(final Intent i) {
isHome = false;
super.startActivity(i);
}
#Override
protected void onUserLeaveHint() {
if (isHome) {
MusicService.onPause();
}
super.onUserLeaveHint();
}
}
First here is some code. Below I'll give you an explanation.
public class MusicService extends Service {
// service binder
private final IBinder mBinder = new LocalBinder();
// music player controling game music
private static CarefulMediaPlayer mPlayer = null;
#Override
public void onCreate() {
// load music file and create player
MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.title_music);
mediaPlayer.setLooping(true);
mPlayer = new CarefulMediaPlayer(mediaPlayer, this);
}
#Override
public void onDestroy() {
super.onDestroy();
}
// =========================
// Player methods
// =========================
public void musicStart() {
mPlayer.start();
}
public void musicStop() {
mPlayer.stop();
}
public void musicPause() {
mPlayer.pause();
}
/**
* 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 {
MusicService getService() {
return MusicService.this;
}
}
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
}
Activity:
public class StartupActivity extends Activity {
// bounded service
private static MusicService mBoundService;
// whetere service is bounded or not
private boolean mIsBound;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_startup);
doBindService();
// HOW TO WORK WITH THE SERVICE:
// call the following methods whenever
// you want to interact with you
// music player
// ===================================
// call this e.g. in onPause() of your Activities
StartupActivity.getService().musicPause();
// call this e.g. in onStop() of your Activities
StartupActivity.getService().musicStop();
// call this e.g. in onResume() of your Activities
StartupActivity.getService().musicStart();
}
#Override
public void onDestroy() {
super.onDestroy();
doUnbindService();
}
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
setService(((MusicService.LocalBinder) service).getService());
}
#Override
public void onServiceDisconnected(ComponentName className) {
setService(null);
}
};
private void doBindService() {
Intent service = new Intent(getBaseContext(), MusicService.class);
// start service and bound it
startService(service);
bindService(new Intent(this, MusicService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
private void doUnbindService() {
if (mIsBound) {
// Detach existing connection.
unbindService(mServiceConnection);
mIsBound = false;
}
}
public static MusicService getService() {
return mBoundService;
}
private static void setService(MusicService mBoundService) {
StartupActivity.mBoundService = mBoundService;
}
}
First of all you got a Service which runs in background. This service creates the mediaPlayer object as you did. With the localBinder you can bind the Service in your Activity(ies) and access it like a normal Java-Object.
The Activity I've posted bindes the Service. In it's onCreate() method you can find a way how to interact with your mediaPlayer.
You can bind any Activity to your Service.
Another Solution:
public class CarefulMediaPlayer {
final SharedPreferences sp;
final MediaPlayer mp;
private boolean isPlaying = false;
private static CarefulMediaPlayer instance;
public CarefulMediaPlayer(final MediaPlayer mp, final MusicService ms) {
sp = PreferenceManager.getDefaultSharedPreferences(ms.getApplicationContext());
this.mp = mp;
instance = this;
}
public static CarefulMediaPlayer getInstance() {
return instance;
}
public void start() {
if (sp.getBoolean("com.embed.candy.music", true) && !isPlaying) {
mp.start();
isPlaying = true;
}
}
public void pause() {
if (isPlaying) {
mp.pause();
isPlaying = false;
}
}
public void stop() {
isPlaying = false;
try {
mp.stop();
mp.release();
} catch (final Exception e) {}
}
}
Then you can pause, play and stop the music by calling CarefulMediaPlayer.getInstance().play();
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" />
In the startup activity we are binding and Starting Service seperately. This is wrong since service will keep running after activity exits as we haven't called stopService() anywhere. So The part ' startService(service) ' should be removed as bind service is already "Auto-Creating" the service too.
Please correct me if anyone got opposite results
startService(service);// remove this part
bindService(new Intent(this, MusicService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
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
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.