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
Related
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
Hey Thanx for checking my question. im new to android programming. i have created a splash code but its not launching on emulator. it gives Application has stopped unexpectedly. please see to it. im using Android studio.
package com.example.harshit.myapplication;
import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
public class Splash extends Activity {
MediaPlayer sound = MediaPlayer.create(Splash.this, R.raw.us);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
sound.start();
Thread t1 = new Thread() {
public void run() {
try {
sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
Intent Menu = new Intent("com.example.harshit.myapplication.MENU");
startActivity(Menu);}
}
};
t1.start();
}
#Override
protected void onPause() {
super.onPause();
sound.release();
finish();
}
}
MediaPlayer sound = MediaPlayer.create(Splash.this, R.raw.us);
Hey you should place this line inside the oncreate function .You didnt provide logcat so the error will be due to this or you can check your android manifest. Weather you declare your splash class in android manifest or not. You have to declare all the classes in android manifest.
1) Did you include your activity in AndroidManifest.xml
2)
Here the correct code:
public class splash extends Activity {
MediaPlayer ourSound;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
ourSound=MediaPlayer.create(splash.this,R.raw.splashsound);
SharedPreferences getprefs=PreferenceManager.getDefaultSharedPreferences(getBaseContext());
boolean music =getprefs.getBoolean("splashmusic", true);
if(music == true)
ourSound.start();
Thread timer = new Thread()
{
public void run()
{
try
{ sleep(2000);
}catch(InterruptedException e)
{e.printStackTrace();
}
finally
{ Intent openMainActivity=new Intent("your package");
startActivity(openMainActivity);
}
}
};
timer.start();
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
ourSound.release();
finish();
}
}
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
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.
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