先看下面两段非常简单的代码,功能是通过一个Activity启动并绑定一个本地服务,然后马上调用停止服务
MainActivity.java
package com.example.servicetest2; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.support.v7.app.ActionBarActivity; import android.util.Log; public class MainActivity extends ActionBarActivity { private static final String LOG_TAG = "MainActivity"; private ServiceConnection conn = new TestConnection(); private Intent i; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); i = new Intent(this, TestService.class); startService(i);// 新建服务 bindService(i, conn, 0);// 该Activity bind到该服务,0表示不新建服务 } protected void onConnected() { stopService(i);// bind到服务后,马上stop掉 } private class TestConnection implements ServiceConnection { @Override public void onServiceConnected(final ComponentName name, final IBinder service) { Log.d(LOG_TAG, "onServiceConnected"); onConnected(); } @Override public void onServiceDisconnected(final ComponentName name) { Log.d(LOG_TAG, "onServiceDisconnected"); } } }
TestService.java
package com.example.servicetest2; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class TestService extends Service { private static final String LOG_TAG = "TestService"; @Override public void onCreate() { Log.d(LOG_TAG, "onCreate"); } @Override public IBinder onBind(final Intent intent) { Log.d(LOG_TAG, "onBind"); return new TestBinder(); } @Override public boolean onUnbind(final Intent intent) { Log.d(LOG_TAG, "onUnbind"); return false; } @Override public void onDestroy() { Log.d(LOG_TAG, "onDestroy"); } public static class TestBinder extends Binder {} }
按照安卓官方文档(http://developer.android.com/guide/components/services.html,http://developer.android.com/guide/components/bound-services.html)的说法,如果一个服务既被startService启动又被其他组件bind到,那么调用stopService时该服务不会被销毁,直到所有的client都unbind。事实是否如此呢?上述代码执行结果如下:
11-14 22:18:17.527: D/TestService(2481): onBind
11-14 22:18:17.547: D/MainActivity(2481): onServiceConnected
11-14 22:18:17.607: D/MainActivity(2481): onServiceDisconnected
11-14 22:18:17.607: D/TestService(2481): onUnbind
11-14 22:18:17.607: D/TestService(2481): onDestroy
可以看到虽然在代码中并未unbind该服务,但当调用stopService时服务马上就被销毁,而且触发了onServiceDisconnected回调,明显和官方文档以及网上各种说法不一致。为什么会这样呢?去翻关闭服务的源代码:
ActivityManagerService.java
private final void bringDownServiceLocked(final ServiceRecord r, final boolean force) { // Slog.i(TAG, "Bring down service:"); // r.dump(" "); // Does it still need to run? if (!force && r.startRequested) {// 检查stopService或stopSelf是否被调用 return; } if (r.connections.size() > 0) { if (!force) { // XXX should probably keep a count of the number of auto-create // connections directly in the service. final Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator(); while (it.hasNext()) {// 遍历所有绑定到服务的连接记录 final ArrayList<ConnectionRecord> cr = it.next(); for (int i = 0; i < cr.size(); i++) { if ((cr.get(i).flags & Context.BIND_AUTO_CREATE) != 0) {// 检查连接是否设置了BIND_AUTO_CREATE return;// 如果存在设置了BIND_AUTO_CREATE的连接,那么就不销毁服务直接返回 } } } } // Report to all of the connections that the service is no longer // available. final Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator(); while (it.hasNext()) { final ArrayList<ConnectionRecord> c = it.next(); for (int i = 0; i < c.size(); i++) { final ConnectionRecord cr = c.get(i); // There is still a connection to the service that is // being brought down. Mark it as dead. cr.serviceDead = true; try { cr.conn.connected(r.name, null);// 回调ServiceConnection.onServiceDisconnected } catch (final Exception e) { Slog.w(TAG, "Failure disconnecting service " + r.name + " to connection " + c.get(i).conn.asBinder() + " (in " + c.get(i).binding.client.processName + ")", e); } } } } // ... // 销毁服务 }
ActivityManagerService.bringDownServiceLocked方法负责销毁服务,无论stopService或unbindService最终都可能会调用该方法。可以从代码中看到,在真正销毁服务前,会检查和该服务绑定的连接信息(调用该次unbindService的连接在前面已经被过滤掉),如果扔有设置过BIND_AUTO_CREATE的链接存在,就不进行销毁。换句话说,一个BoundService是否被销毁,取决于当前带有BIND_AUTO_CREATE标志的连接数目,不带有BIND_AUTO_CREATE标志的连接会在服务销毁前收到onServiceDisconnected回调。
个人认为,销毁服务的代码实现逻辑和开发设想是有出入的,本应该有特殊的标志位决定是否在有client绑定的情况下销毁服务而不是简单粗暴的“重用”BIND_AUTO_CREATE标志。不过BIND_AUTO_CREATE和startService同时使用并无副作用(同名服务在安卓里头是单例),我们可以根据业务需求灵活设置bindService方法的flags参数。比如一个多client连接的短时间执行的共享服务,当client指定bindService的flags为0时,服务在执行完毕可以及时stopSelf销毁,而不需要等待client unbind,可以有效的节省资源。
相关推荐
Services App : Creating and Managing the lifecycle of android services using Context.BIND_AUTO_CREATE. Sensor App : The purpose of this app is to work with Android Sensors (Timer and Camera). Torch ...
本文实例讲述了Android编程设置TabHost当中字体的方法。分享给大家供大家参考,具体如下: TabWidget tw=this.getTabWidget();//设置TabHost当中的... tv.setGravity(BIND_AUTO_CREATE); tv.setPadding(10, 10, 10
bindService(serviceIntent,mConnection,Context.BIND_AUTO_CREATE); System.out.println("123565"); System.out.println("qwwq"); System.out.println("www"); System.out.println("123ww565"); System...
this.bindService(bindIntent, conn, Context.BIND_AUTO_CREATE); 相同的代码以前使用一直很正常,但最近在项目中使用却一直绑定失败,bindservice返回false。 原因: 使用了TabActivity, TabActivity里的子Activity...
Context.BIND_AUTO_CREATE); } // 初始化控件 private LayoutInflater mInflater; private ListView ble_listview; private List<MTBeacon> scan_devices = new ArrayList(); private List<MTBeacon> ...
auto closeItem = MenuItemImage::create( CloseNormal.png, CloseSelected.png, CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); 2.0内的代码用的不是CC_CALLBACK_1而是menu_selector. CC_CALLBA
14. bindService(new Intent(”com.wissen.testApp.service.MY_SERVICE”), conn, Context.BIND_AUTO_CREATE); 15. … 复制代码 当应用程序绑定一个Service后,该应用程序和Service之间就能进行互相通信,通常,这种...
#hibernate.hbm2ddl.auto create-drop #hibernate.hbm2ddl.auto create #hibernate.hbm2ddl.auto update #hibernate.hbm2ddl.auto validate ## specify a default schema and catalog for unqualified tablenames ...
Ognl support, if test when test ${ bind foreach collection, refactor and inspection and auto completion Jump from refid resultMap to their definition, refactor their name as well Generate page query ...
Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.NORMAL); vTextPaint.setTypeface(font);//字体风格 vTextPaint.setColor(getResources().getColor(R.color.white)); Rect bounds_Number = new...
无限极分类下拉选择插件,经历数个版本,最初使用的jquery bind函数绑定select标签onchange事件。 当前版本使用jquery delegate 方式进行事件处理,代码得到了大大的精简。 理论上支持所有类似 id,name,parendid ...
this.element.bind("remove."+this.widgetName,function(){d.destroy()}),this._create(),this._trigger("create"),this._init()},_getCreateOptions:function(){return a.metadata&&a.metadata.get(this.element[0]...
config port 24 auto off config port 24 duplex full config port 24 speed 100 ! !vlan config config ipaddress 218.3.220.236 255.255.255.0 create vlan manage config vlan manage tag 2007 config vlan ...
auto threadpool = Marvel::mvThreadPool (); // submit function threadpool-> submit (&SomeFunction); // submit function with arguments threadpool-> submit ( std::bind (&SomeVarFunction, arg1, arg2,...
01.CREATE TABLE `test`.`student` ( 02. `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 03. `name` varchar(45) NOT NULL, 04. `psw` varchar(45) NOT NULL, 05. PRIMARY KEY (`id`) 06.) 建好表后...
// create the conversation object self.pcs[message.from] = new Conversation({ id: message.from, parent: self, initiator: false }); self.pcs[message.from].handleMessage(message); } }); ...
这样的程序如果不在IDE 工具中输入,是很难看出这个程序代码会出现问题,可它偏偏就出问题了,这是为什么呢?因为程序里面有个静态方法,如果导入import static java.lang.Integer.parseInt;这样的程序就可以运行了...
Create TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userName` varchar(50) DEFAULT NULL, `userAge` int(11) DEFAULT NULL, `userAddress` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`) ) ...
--bind-address=ADDRESS bind to ADDRESS (hostname or IP) on local host. --limit-rate=RATE limit download rate to RATE. --no-dns-cache disable caching DNS lookups. --restrict-file-names=OS restrict ...
Table of Contents Header Files The #define Guard Header File Dependencies Inline Functions The -inl.h Files Function Parameter Ordering Names and Order of Includes Scoping Namespaces Nested Classes ...