可绑定的Android前台服务

9
什么是正确的前台服务实现方式,我以后可以将其绑定到它上面? 我已经按照 Android API 的示例创建了一个前台服务的示例。 但是没有关于同时启动服务和绑定服务的示例。
我想看到一个良好的音乐播放器服务示例,其中活动“bound”到它上面。
有吗?
我想做以下事情:
当程序第一次启动(第一次指服务尚未启动)时,我想启动前台服务来完成所有工作。用户界面(活动)只是为了控制该工作。
如果用户按下主页按钮,则服务必须保持运行状态(并且通知栏中的通知必须存在)。
现在,如果用户单击通知栏中的通知,则应启动活动并将其绑定到服务(或类似的方式),用户接管该工作。
如果活动处于活动状态并且用户按下返回按钮,则应销毁活动并且也应销毁服务。
我必须重写哪些方法才能完成此任务?这是 Android 完成此任务的方式吗?
2个回答

10

在Froyo之前,Service中有一个简单易用但也容易被滥用的setForeground(true)方法。

现在有了startForeGround服务,需要激活通知(以便用户可以看到前台服务正在运行)。

我创建了这个类来控制它:

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

对于我的媒体播放器,这将更新通知 - 请注意,在媒体正在播放时才需要前台服务,并且在停止后应该保持开启。这是一种不好的做法。

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

关于绑定(bind) - 在您的活动(activity) onStart 方法中,您只需像绑定到任何服务(service)一样进行绑定(bindService)调用即可(无论它是否在前台)。

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

"onEWCreate"是什么意思?是你手写错误还是我的知识有限? - pengwang
抱歉,应该是onCreate - 这是我自己用来报告异常的包装器。 - siliconeagle
我发现API Demos演示的同样奇怪的行为。如果您进入API Demos(API版本7),然后进入App-> Service-> Local Service Controller,然后点击Start Service。现在通知栏已经启动了。现在按HOME按钮并转到notif。栏,然后按服务通知(Sample Local Service)上的通知。现在!您必须按三次返回按钮才能实际返回。为什么?!!? - zmeda
每次点击通知时都会启动一个新任务,当您按返回键时,它会返回到上一个任务,因为当前已经打开的活动已经完成。在活动启动意图中使用FLAG_SINGLE_TASK可以阻止这种情况发生。 - siliconeagle

-6
为了完成所要求的任务,我只需要在AndroidManifest.xml中将以下属性添加到我的活动定义中。
android:launchMode="singleTop"

就是这样了。

祝好


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接