Set object reference in Service Android - android

I'm creating a music player app in Android and I'm trying to set up the MediaPlayer as a service so that it persists across all Activities/Fragments. The service code:
public class PlayerService extends Service {
MediaPlayer mediaPlayer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
mediaPlayer = new MediaPlayer();
}
public void LoadUrl(String url){
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try {
mediaPlayer.setDataSource(url);
} catch (IOException e) {
e.printStackTrace();
}
try {
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
}
//mediaPlayer.start();
Play(mediaPlayer);
}
public void Play(MediaPlayer player) {
player.start();
}
public void Pause(MediaPlayer player) {
player.pause();
}
}
and the MainActivity:
public class MainActivity extends AppCompatActivity {
PlayerService playerService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState != null){
} else {
playerService = new PlayerService();
Intent startPlayer = new Intent(this, PlayerService.class);
startService(startPlayer);
....
When MainActivity is started, it launches the service, however, when I try to load a Url into the MediaPlayer with:
playerService.LoadUrl(feedItem.getAudioUrl());
I get an exception saying that mediaPlayer in the Service is null. How can I make sure that the mediaPlayer is retained?

You are trying to start the service using startService without onStartCommand in service, without which the sevice won't start. So your media player won't get initialized

Related

Music service is started but song is not playing

I had created music player service which stop automatically on back pressed. I want to set it continuously until songs are available or user manually close from notification window. Any help appreciated.
Here below i put some code which i had created from reference
private MediaPlayer player;
private final IBinder musicBind = new MusicBinder();
public void onCreate(){
super.onCreate();
player = new MediaPlayer();
initMusicPlayer();
}
public void initMusicPlayer(){
//set player properties
player.setWakeMode(getApplicationContext(),
PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
//set listeners
player.setOnPreparedListener(this);
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
}
public class MusicBinder extends Binder {
MusicService getService() {
return MusicService.this;
}
}
//activity will bind to service
#Override
public IBinder onBind(Intent intent) {
return musicBind;
}
//release resources when unbind
#Override
public boolean onUnbind(Intent intent){
//player.stop();
//player.release();
return false;
}
#Override
public void onDestroy() {
//stopForeground(true);
}
this code is used in activity to bind service
bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
startService(playIntent);
From above code my service is started but i'm not able to play song directly i had to click on play button
public void playSong() {
player.reset();
try {
sendName_image();
player.setDataSource(URI object);
player.prepareAsync();
} catch (Exception e) {
}
}
Above method is called on button click
you should call player.start(); to start playing after player prepared

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

Android app crashes when calling MediaController.show() - Unable to add window -- token null is not valid

I'm creating a music streaming app. As per android's MediaPlayer guide, I'm controlling the MediaPlayer from a Service. This all works fine and now I'm trying to add a MediaController to control playback. To do so, I'm having my Service implement MediaController.MediaPlayerControl, and having my Activity bind to my Service, and then instantiating the MediaController from the Activity with the Service context from the ServiceConnection.
Player.java
public class Player extends Activity implements OnClickListener, OnItemClickListener, MediaController.MediaPlayerControl {
private MediaController mediaController;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
showMediaController();
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
startService(
new Intent(this, PlayerService.class)
.setAction("com.limastreamer.action.NEXTSHOW"));
bindService(
new Intent(this, PlayerService.class),
mConnection,
Context.BIND_AUTO_CREATE);
}
public void showMediaController() {
if (mBound) {
mediaController = new MediaController(this);
mediaController.setAnchorView(
findViewById(R.id.player)
);
mediaController.setMediaPlayer(mService);
mediaController.setEnabled(true);
mediaController.show(0);
}
}
}
PlayerService.java
public class PlayerService extends Service implements MediaController.MediaPlayerControl {
private MediaPlayer mMediaPlayer;
public class LocalBinder extends Binder {
PlayerService getService() {
return PlayerService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
String action = intent.getAction();
if (action.equals("com.limastreamer.action.NEXTSHOW")) {
if (mMediaPlayer == null)
{
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setLooping(false);
}
try
{
mMediaPlayer.reset();
mMediaPlayer.setDataSource(url);
mMediaPlayer.prepareAsync(); // prepare async to not block main thread
}
catch (Exception ex)
{
Toast.makeText(getApplicationContext(), "Failed to prepare MediaPlayer", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public boolean canPause() {
return true;
}
#Override
public boolean canSeekBackward() {
return true;
}
#Override
public boolean canSeekForward() {
return true;
}
#Override
public int getBufferPercentage() {
return 0;
}
#Override
public int getCurrentPosition() {
if (mMediaPlayer != null && mMediaPlayer.isPlaying())
return mMediaPlayer.getCurrentPosition();
else
return 0;
}
#Override
public int getDuration() {
if (mMediaPlayer != null && mMediaPlayer.isPlaying())
return mMediaPlayer.getDuration();
else
return 0;
}
#Override
public boolean isPlaying() {
if (mMediaPlayer != null)
return mMediaPlayer.isPlaying();
else
return false;
}
#Override
public void pause() {
if (mMediaPlayer != null)
mMediaPlayer.pause();
}
#Override
public void seekTo(int msec) {
if (mMediaPlayer != null)
mMediaPlayer.seekTo(msec);
}
#Override
public void start() {
if (mMediaPlayer != null)
mMediaPlayer.start();
}
}
R.id.player refers to the root element of my xml layout.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/player"
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"
tools:context=".Player" >
On calling mediaController.show(); the app bombs out with the exception: Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
From looking at other questions on SO (for example), it seems that this is caused by using the wrong context here: mediaController = new MediaController(this);, ie using something other than the Activity context. But as far as I can tell, I am using the Activity context.
I've tried:
Using other views in the layout as the anchor view (even tho the doc says you can use the Activity's main view)
Putting the MediaController in a fragment, and using getActivity() as the context, as shown here
Putting the MediaController in the xml layout instead of instantiating it programatically.
Setting a VideoView as the anchor view (some people say it only works with a VideoView).
Creating a new class that extends VideoView and implements MediaPlayerControl, and instantiating the MediaController in that class, using the saved context that was passed to the class when it was initialized as the context, and this as the anchor view.
Your activity should implement MediaPlayer.OnPreparedListener and set onPreparedListener of mediaPlayer of your service to the player activity.
public class MyMediaPlayer extends Activity implements
MediaController.MediaPlayerControl,MediaPlayer.OnPreparedListener {
...
public void onCreate(Bundle savedInstanceState) {
...
//this mediaPlayer is the reference of your media player inside your service
mediaPlayer.setOnPreparedListener(this);
...
}
...
}
also you have to start your service a little after you created your activity
Intent in=new Intent(MainPlayer.this,MyMediaPlayer.class);
startActivity(in);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//START YOUR SERVICE TO PREPARE YOUR PLAYER
this works for me.

IntentService OnHandleIntent is not being called

I am trying to run a background music using Intent service. The OnhandleIntent does not get called. I tried adding breakpoints and even the code android.os.Debug.waitForDebugger(); but i am unable to step into OnHandleIntent.
I have added the service to the manifest( android:name=".BackgroundMusic"/>) and i am not sure what i am missing here. Any help would be appreciated.
public class BackgroundMusic extends IntentService
{
MediaPlayer mp;
Uri uri;
public BackgroundMusic()
{
super("BackgroundMusic");
setIntentRedelivery(true);
}
#Override
protected void onHandleIntent(Intent intent)
{
try
{
android.os.Debug.waitForDebugger();
int id=intent.getExtras().getInt("musicid");
mp=MediaPlayer.create(this,id);
mp.prepare();
mp.start();
}
catch (Exception e)
{
Log.e("Error",e.getMessage());
}
}
#Override
public void onCreate()
{
super.onCreate();
}
#Override
public void onDestroy()
{
super.onDestroy();
if (mp != null)
mp.release();
mp=null;
}
}
Activity Code
#Override
public void onCreate(Bundle savedInstanceState)
{
try
{
super.onCreate(savedInstanceState);
LMain=new LinearLayout(this);
LMain.setOrientation(LinearLayout.HORIZONTAL);
LayoutParams pFill=new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);
LMain.setLayoutParams(pFill);
imageview=new ImageView(this);
imageview.setLayoutParams(pFill);
setContentView(LMain);
Intent IntImage=getIntent();
int id=IntImage.getExtras().getInt("id");
mresourceid=new ImageAdapter(this).music[id];
imageview.setImageResource(new ImageAdapter(this).images[id]);
Intent IntMusic=new Intent(ImageDetail.this,BackgroundMusic.class);
IntMusic.putExtra("musicid", mresourceid);
startService(IntMusic);
}
catch(Exception e)
{
Log.e("error",e.getMessage());
}
}
It works. I was earlier running the code on device with OS Version 2.3.4 . Intent Services are supported from API level 3.
Wanted to update just in case if anyone is doing the same what i did

Android comprehensive failproof music service across multiple activities

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);

Categories

Resources