【讨论】通过bindService启动的service,在unbindService后service也结束了

ameyume
博客专家认证
2011-03-26 09:42:04
这个问题以前讨论过,各个文档blog上也是这么写的,但有人还是说即使unbindService了,service还是会继续运行。
但刚才验证,unbindService后,执行了service的onDestroy方法,service也停止了。
下面是一个通过servcie来实现计数的功能,并且在activity中显示出此计数
1.接口ICountService.java,只有一个返回计数值的函数声明
package com.min.localservicedemo;

public interface ICountService {
public abstract int getCount();
}

2.服务类CountService.java,用于实现计数功能,在一个新线程中执行,并更新view显示当前计数值
package com.min.localservicedemo;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class CountService extends Service implements ICountService {
private static final String TAG = "CountService";
private boolean threadDisable;
private int count;
private ServiceBinder serviceBinder = new ServiceBinder();

public class ServiceBinder extends Binder implements ICountService {

public int getCount() {
// TODO Auto-generated method stub
return count;
}

}

public int getCount() {
// TODO Auto-generated method stub
return count;
}

@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return serviceBinder;
}

@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();

new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
while(!threadDisable) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
Log.d(TAG, "count is " + count);

updateCount();
}
}
}
).start();
}

@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
super.onStart(intent, startId);
}

@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return super.onUnbind(intent);
}

@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
threadDisable = true;
Log.d(TAG, "onDestroy");
}

/**
* Update view
*/
public void updateCount() {
LocalServiceDemo.getMyHandler().sendEmptyMessage(1);
}
}

3.Activity类LocalServiceDemo.java,显示当前的计数值
package com.min.localservicedemo;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

public class LocalServiceDemo extends Activity {
private static final String TAG = "LocalServiceDemo";

private static TextView tvCount;
private static ICountService countService;

private static MyHandler myHandler = MyHandler.getInstance();

private ServiceConnection serviceConnection = new ServiceConnection() {

public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
countService = (ICountService)service;
Log.d(TAG, "onServiceConnected count is " + countService.getCount());
tvCount.setText("Count:" + countService.getCount());
}

public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
countService = null;
}

};

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

tvCount = (TextView)findViewById(R.id.tvCount);
this.bindService(new Intent("com.min.localservicedemo.CountService"),
serviceConnection, BIND_AUTO_CREATE);
}

@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
this.unbindService(serviceConnection);
Log.d(TAG, "onDestroy unbindService");
}

public static class MyHandler extends Handler {
private static MyHandler myHandler = null;

private MyHandler() {
}

/**
* Single Instance
* @return
*/
public static MyHandler getInstance() {
if (myHandler == null) {
myHandler = new MyHandler();
}
return myHandler;
}

@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
if(msg.what == 1) {
tvCount.setText("Count:" + countService.getCount());
}

super.handleMessage(msg);
}

}

public static MyHandler getMyHandler() {
return myHandler;
}
}


4.log输出
03-26 01:33:16.710: INFO/ActivityManager(59): Starting activity: Intent {

act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000

cmp=com.min.localservicedemo/.LocalServiceDemo }
03-26 01:33:17.480:

DEBUG/LocalServiceDemo(349): onServiceConnected count is 0
03-26 01:33:17.580:

INFO/ActivityManager(59): Displayed activity com.min.localservicedemo/.LocalServiceDemo:

666 ms (total 666 ms)
03-26 01:33:18.329: DEBUG/CountService(349): count is 1
03-26

01:33:19.388: DEBUG/CountService(349): count is 2
03-26 01:33:20.453: DEBUG/CountService

(349): count is 3
03-26 01:33:21.506: DEBUG/CountService(349): count is 4
03-26

01:33:22.573: DEBUG/CountService(349): count is 5
03-26 01:33:22.850: DEBUG/dalvikvm(127):

GC_EXPLICIT freed 227 objects / 11056 bytes in 168ms
03-26 01:33:23.612:

DEBUG/CountService(349): count is 6
03-26 01:33:24.671: DEBUG/CountService(349): count is

7
03-26 01:33:25.738: DEBUG/CountService(349): count is 8
03-26 01:33:26.804:

DEBUG/CountService(349): count is 9
03-26 01:33:27.871: DEBUG/CountService(349): count is

10
03-26 01:33:28.531: WARN/KeyCharacterMap(349): No keyboard for id 0
03-26 01:33:28.531:

WARN/KeyCharacterMap(349): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
03-26

01:33:28.871: DEBUG/CountService(349): count is 11
03-26 01:33:29.231:

DEBUG/LocalServiceDemo(349): onDestroy unbindService
03-26 01:33:29.340:

DEBUG/CountService(349): onDestroy
03-26 01:33:29.941: DEBUG/CountService(349): count is

12
03-26 01:34:54.540: DEBUG/SntpClient(59): request time failed: java.net.SocketException:

Address family not supported by protocol

Log截图

可以在log中看到,当退出activity时,执行了onDestroy函数的unbindService
然后又执行了CountService类的onDestroy,这时候service就结束了。

我是这么理解的,如果在unbindService后,service还能继续存在,那么就是我理解的有偏差。
欢迎各抒己见。
...全文
11659 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
lxyoo111 2013-12-09
  • 打赏
  • 举报
回复
unbind之后虽然不会停止服务,但是会把service重新create,这个要怎么解决啊
「已注销」 2012-10-26
  • 打赏
  • 举报
回复
非常感谢
W710327M 2012-08-16
  • 打赏
  • 举报
回复
大牛们太吊了。值得学习。。
ColaCoding 2012-06-24
  • 打赏
  • 举报
回复
好帖,关注一下.
izard999 2012-01-31
  • 打赏
  • 举报
回复
非常感谢, 正在为bindService发愁呢。
xiao3ge 2011-09-20
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 oyzz1988 的回复:]

有三种情况:如果直接使用服务,则没有必要进行绑定,但是如果要使用服务里面的方法,则要进行绑定。具体的启动情况有下:

1.当启动时,单独调用bindService方法,在unbindService后,会执行service的onUnbind,在执行onDestroy方法。
2.当启动时,先调用startService,在调用bindService方法后,在unbindService后,会……
[/Quote]

我也是这么理解的
biosxjj 2011-08-31
  • 打赏
  • 举报
回复
unbindservice 只会执行一次 。。很奇怪。。。
oyzz1988 2011-07-21
  • 打赏
  • 举报
回复
有三种情况:如果直接使用服务,则没有必要进行绑定,但是如果要使用服务里面的方法,则要进行绑定。具体的启动情况有下:

1.当启动时,单独调用bindService方法,在unbindService后,会执行service的onUnbind,在执行onDestroy方法。
2.当启动时,先调用startService,在调用bindService方法后,在unbindService后,会执行service的onUnbind,不会执行onDestroy方法。除非你在执行stopService.
3. 先调用startService,在调用stopService,会执行service的onDestroy方法。
  • 打赏
  • 举报
回复
<uses-permission android:name=”android.permission.INTERNET” />
缺少这个
ameyume 2011-03-29
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 yang79tao 的回复:]
这个对我来说很难,还没有想到什么办法。因为这是android系统决定要结束服务的,在所有连接都解绑之后。
[/Quote]
谢谢。
android自带music源码中也是先startService,然后执行bindService的
这是MusicUtils.java中定义的绑定函数bindToService,先startService,再bindService。
    public static ServiceToken bindToService(Activity context, ServiceConnection callback) {
Activity realActivity = context.getParent();
if (realActivity == null) {
realActivity = context;
}
ContextWrapper cw = new ContextWrapper(realActivity);
cw.startService(new Intent(cw, MediaPlaybackService.class));
ServiceBinder sb = new ServiceBinder(callback);
if (cw.bindService((new Intent()).setClass(cw, MediaPlaybackService.class), sb, 0)) {
sConnectionMap.put(cw, sb);
return new ServiceToken(cw);
}
Log.e("Music", "Failed to bind to service");
return null;
}
ameyume 2011-03-29
  • 打赏
  • 举报
回复
的确是在bindService之前先startService,当activity结束时,unbindService后service还是可以继续运行。
本例只需要增加一个startService就可以了
tvCount = (TextView)findViewById(R.id.tvCount);
startService(new Intent("com.min.localservicedemo.CountService"));
this.bindService(new Intent("com.min.localservicedemo.CountService"),
serviceConnection, BIND_AUTO_CREATE);
ameyume 2011-03-28
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 drsmart 的回复:]
呵呵,建议你到google面试,百度那些人技术不行啊
[/Quote]
目前还是好好的做两年android,提高水平,而不是像现在只懂皮毛。
那样再进入一流公司就容易了,现在大部分机会都是浪费掉了。

回到主题,通过aidl启动的远程服务是可以在unbindService之后还可以继续运行service的吧
service和activity属于不同的进程里吧?
是service属于server程序,activity属于client端?
看了一些aidl的例子,还没有彻底弄明白。
DrSmart 2011-03-28
  • 打赏
  • 举报
回复
呵呵,建议你到google面试,百度那些人技术不行啊
ameyume 2011-03-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 peijiangping1989 的回复:]
楼主是BJ的么,祝你找个好工作。。对于面试考这些个理解性问题我很蛋疼。。。
[/Quote]
是啊,谢谢。周六去百度面试,过了笔试,笔试完等了一下午到六点多才轮到面试,结果不到10分钟就死在了面试上,我做的音乐播放器的确是问题太多了。
youngwolf 2011-03-28
  • 打赏
  • 举报
回复
这个对我来说很难,还没有想到什么办法。因为这是android系统决定要结束服务的,在所有连接都解绑之后。
小裴同学 2011-03-28
  • 打赏
  • 举报
回复
楼主是BJ的么,祝你找个好工作。。对于面试考这些个理解性问题我很蛋疼。。。
ameyume 2011-03-28
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 ameyume 的回复:]
引用 3 楼 yang79tao 的回复:
如果不是通过bindService创建的服务(但仍然通过bindService得到了服务对象),就可能unbindService后还在运行,否则应该是结束掉了。

嗯。
通过bindService启动的服务,在unbindService后应该是可以继续运行service,今天去面试在这个问题上又被鄙视了。
在android播放器源码里好像有这个……
[/Quote]
android自带的music源码
http://android.git.kernel.org/?p=platform/packages/apps/Music.git;a=tree
看了下是用AIDL远程服务的方式启动的SERVICE类MediaPlaybackService.java
http://android.git.kernel.org/?p=platform/packages/apps/Music.git;a=blob;f=src/com/android/music/MediaPlaybackService.java;h=7c0bbedbedef49bf4c38ef97fdcd0f1017bf5d35;hb=HEAD

还没来得及仔细看,是不是通过在activity中获取到远程service后,bindService,这样即使unbindService后,还是可以继续运行service播放音乐?
ameyume 2011-03-28
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 yang79tao 的回复:]
aidl只是一个stub,相当于代理,与服务没有关系。不会影响服务的生命周期。
service可以和activity在同一进程,也可以不在。这要看AndroidManifest.xml里面的定义。
service与server好像没有什么关系吧?前者是系统的概念,后者大多指c/s这种结构。
[/Quote]
多谢,那该如何控制通过bindService启动的服务,在unbindService后不结束service,让service继续运行呢?
youngwolf 2011-03-28
  • 打赏
  • 举报
回复
aidl只是一个stub,相当于代理,与服务没有关系。不会影响服务的生命周期。
service可以和activity在同一进程,也可以不在。这要看AndroidManifest.xml里面的定义。
service与server好像没有什么关系吧?前者是系统的概念,后者大多指c/s这种结构。
ameyume 2011-03-28
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 nevsaynev666 的回复:]
通过bindService启动的service有一个bound计数,当计数为0时,service就destroy了。
同一个app中的service和activity属于同一个进程,也是同一个线程,但是可以通过设置属性改变。

你看看下docs/guide/topics/fundamentals/services.html这个描述吧。我也只是把这个看完了,没在app中使用,刚刚入手andro……
[/Quote]
谢谢,以前看到过bindService有个计数来判断是否还有没有调用者,但没有具体用过,还是记忆不深刻啊。
加载更多回复(5)

80,350

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧