【问题标题】:Android foreground service which can be bound可绑定的Android前台服务
【发布时间】:2011-03-21 20:34:00
【问题描述】:

我以后可以绑定到前台服务的正确方法是什么? 我已经关注了 Android API 演示,其中包括一个如何创建前台服务的示例。 没有同时绑定启动服务的例子。

我希望看到一个很好的音乐播放器服务示例,其中活动“绑定”到它。

有吗?

我想做这样的事情:

  • 当第一次启动程序时(首先表示服务尚未启动),我想启动前台服务来完成所有工作。用户界面(活动)只是为了控制该工作
  • 如果用户按下主页按钮,服务必须保持正常运行(并且必须存在栏中的通知)
  • 现在,如果用户单击通知栏活动中的通知,则应该启动并绑定到服务(或类似的东西,正确的方式)并且用户可以控制该作业。
  • 如果 Activity 处于活动状态并且用户按下返回按钮,则应销毁 Activity,并且还应销毁服务。

我必须重写哪些方法才能完成此任务?这样做的 Android 方式是什么?

【问题讨论】:

    标签: android service android-activity


    【解决方案1】:

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

    至于绑定 - 您只需在活动 onStart 中以正常方式绑定,您只需调用 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”,是你的手写错误还是我的小知识?
    • oppps 抱歉,它显示为 onCreate - 这是我自己的异常报告包装器。
    • 我发现 API Demos 演示的奇怪行为。如果您转到 API Demos(API 版本 7)并转到应用程序 -> 服务 -> 本地服务控制器,然后点击启动服务。现在通知中的通知。酒吧已启动并正在运行。现在按 HOME 按钮并通知。栏并按下服务通知(本地服务示例)。现在!您必须按三下后退按钮才能真正返回。为什么在世界上?!!?
    • 每次单击通知时都会启动一个新任务,当您回击它时,它会转到上一个任务,因为当前启动的活动已完成。在活动启动意图中使用 FLAG_SINGLE_TASK 停止这个。
    【解决方案2】:

    要完成所要求的任务,我唯一要做的就是将以下属性添加到 AndroidManifest.xml 到我的活动定义中

    android:launchMode="singleTop"
    

    就是这样。

    问候

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多