Android foreground service which can be bound

11,126

Solution 1

To accomplish asked task the only thing I have to do was add following property to AndroidManifest.xml to my activity definition

android:launchMode="singleTop"

That was it.

Regards

Solution 2

before froyo there was setForeground(true) in Service which was easy, but also easy to abuse.

Now there is startForeGround services which requires a notification to be activated (so the user can see there is a foregroundservice running).

i made this class to control it:

public class NotificationUpdater {
    public static void turnOnForeground(Service srv,int notifID,NotificationManager mNotificationManager,Notification notif) {
        try {
            Method m = Service.class.getMethod("startForeground", new Class[] {int.class, Notification.class});
            m.invoke(srv, notifID, notif);
        } catch (Exception e) {
            srv.setForeground(true);
            mNotificationManager.notify(notifID, notif);
        }
    } 

    public static void turnOffForeground(Service srv,int notifID,NotificationManager mNotificationManager) {
        try {
            Method m = Service.class.getMethod("stopForeground", new Class[] {boolean.class});
            m.invoke(srv, true);
        } catch (Exception e) {
            srv.setForeground(false);
            mNotificationManager.cancel(notifID);
        }
    }
}

then for my media player this update the notification - note the foreground service is only required while media is playing and should be left on after it stops, it a bad practice.

private void updateNotification(){
    boolean playing = ((mFGPlayerBean.getState()==MediaPlayerWrapper.STATE_PLAYING) || 
                        (mBGPlayerBean.getState()==MediaPlayerWrapper.STATE_PLAYING));
    if (playing) {
        Notification notification = getNotification();
        NotificationUpdater.turnOnForeground(this,Globals.NOTIFICATION_ID_MP,mNotificationManager,notification);
    } else {
        NotificationUpdater.turnOffForeground(this,Globals.NOTIFICATION_ID_MP,mNotificationManager);
    }
}

as for binding - you just bind in the normal way in your activity onStart you just make a bindService call as you would bind to any service (it doesnt matter weather it foreground or not)

MediaPlayerService mpService=null;
@Override
protected void onEWCreate(Bundle savedInstanceState) {
     Intent intent = new Intent(this, MediaPlayerService.class);
     startService(intent);
}

@Override
protected void onStart() {
    // assume startService has been called already
    if (mpService==null) {
        Intent intentBind = new Intent(this, MediaPlayerService.class);
        bindService(intentBind, mConnection, 0);
    }
}

private ServiceConnection mConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {
        mpService = ((MediaPlayerService.MediaBinder)service).getService();
    }

    public void onServiceDisconnected(ComponentName className) {
        mpService = null;
    }
};
Share:
11,126
zmeda
Author by

zmeda

Wannabe Java developer but actually senior Scala developer

Updated on June 13, 2022

Comments

  • zmeda
    zmeda about 2 years

    What is the right way of doing foreground service which I can later bind to it? I have followed Android API demo which includes an example how to create foreground service. There is no example about start service in bind to it at same time.

    I want to see one good example of music player service with activity "bound" to it.

    Is there any?

    I want to do something like:

    • When a program is first (first means that service isn't started yet) started I want to start foreground service which do all the job. User Interface (activity) is just to control that job
    • If user presses home button service must stay up and running (and notification in bar must be present)
    • Now if user click on notification in notification bar activity should start and bind to service (or something like that, the right way) and user takes control over the job.
    • If activity is active and user presses back button activity should be destroyed and also service should be destroyed.

    What methods do I have to override to accomplish this task? What is the Android way of doing this?

  • pengwang
    pengwang over 13 years
    what is " onEWCreate",is your Handwritten error or my little knowledge?
  • siliconeagle
    siliconeagle over 13 years
    oppps sorry it show be onCreate - thats my own wrapper for exception reporting.
  • zmeda
    zmeda about 13 years
    I have found same odd behaviour of API Demos demo. If you go to API Demos (API Version 7) and go to App -> Service -> Local Service Controller that tap on Start Service. Now the notification in notif. bar is up and running. Now press HOME button and to notif. bar and press on the notification of service (Sample Local Service). Now! You have to press back button three times to actually go back. Why in world?!!?
  • siliconeagle
    siliconeagle about 13 years
    everytime the notif is clicked on it starts a new task, when you hit back it goes to the previous task as the curent one started with the opened activity is finished.using FLAG_SINGLE_TASK in the activity launch intent stops this.