【Android 界面效果34】Android里Service的bindService()和startService()混合使用深入分析
.先讲讲怎么使用bindService()绑定服务
应用组件(客户端)可以调用bindService()绑定到一个service.Android系统之后调用service的onBind()方法,它返回一个用来与service交互的IBinder
绑定是异步的.bindService()会立即返回,它不会返回IBinder给客户端.要接收IBinder,客户端必须创建一个ServiceConnection的实例并传
给bindService().ServiceConnection包含一个回调方法,系统调用这个方法来传递要返回的IBinder.
注:只有activities,services,和contentproviders可以绑定到一个service—你不能从一个broadcastreceiver绑定到service.
所以,从你的客户端绑定到一个service,你必须:
1实现ServiceConnection.
你的实现必须重写两个回调方法:
onServiceConnected()
系统调用这个来传送在service的onBind()中返回的IBinder.
OnServiceDisconnected()
Android系统在同service的连接意外丢失时调用这个.比如当service崩溃了或被强杀了.当客户端解除绑定时,这个方法不会被调用.
2调用bindService(),传给它ServiceConnection的实现.
3当系统调用你的onServiceConnected()方法时,你就可以使用接口定义的方法们开始调用service了.
4要与service断开连接,调用unbindService().
当你的客户端被销毁,它将从service解除绑定,但是你必须总是在你完成与service的交互时或当你的activity暂停于是service在不被使用时可以关闭此两种情况下解
除绑定.(下面会讨论更多在适当的时候绑定和解除绑定的问题.
使用这个ServiceConnection,客户端可以绑定到一个service,通过把它传给bindService().例如:
Intentintent = new Intent(this, LocalService.class);
bindService(intent,mConnection, Context.BIND_AUTO_CREATE);
第一个bindService()的参数是一个明确指定了要绑定的service的Intent.
第二个参数是ServiceConnection对象.
第三个参数是一个标志,它表明绑定中的操作.它一般应是BIND_AUTO_CREATE,这样就会在service不存在时创建一个.其它可选的值是BIND_DEBUG_UNBIND和BIND_NOT_FOREGROUND,不想指定时设为0即可.。
补充事项
下面是一些关于绑定到service的重要事项:
你总是需要捕获DeadObjectException异常.它会在连接被打断时抛出.这是被远程方法抛出的唯一异常.
对象引用计数是跨进程的作用的.
你应该在客户端的生命期内使绑定和解除绑定配对进行,例如:
如果你需要在你的activity可见时与service交互,你应该在onStart()绑定并在onStop()中解除绑定.
如果你想让你的activity即使在它停止时也能接收回应,那么你可以在onCreate()中绑定并在onDestroy()中解除绑定.注意这意味着你的activity需要使用在自己整
个运行期间使用service(即使位于后台),所以如果service在另一个进程中,那么你增加了这个进程的负担而使它变得更容易被系统杀掉.
注:你一般不应该在你的activity的onResume()和onPause()中绑定和解除绑定到service,因为这些回调方法,出现在每个生命期变化中,并且你需要使发生在这
些变化中的处理最小化.还有,如果你应用中的多个activity绑定到同一个service,并且有一个变化发生在其中两个activity之间,service可能在当前activity解除绑
定(pause中)和下一个绑定前(rusume中)被销毁又重建.
2.管理(多个客户端)BoundService的生命期
当一个service的所有客户端都解除绑定,Android系统就销毁它(除非它是从onStartCommand()启动).如果你的service是一个纯boundservice,你不需管理它的生命
期—Android系统会为你管理它.。
然而,如果你选择了实现onStartCommand()回调方法,那么你必须明确地停止service,因为service现在被认为是"开始的".在此情况下,service会一直运行,直
到service使用stopSelf()停止它自己或另外的组件调用了stopService()停止了它,不管是否有客户端绑定了它.
另外,如果你的service已经启动并且接受绑定,那么当系统调用你的onUnbind()方法,你可以选择返回true表示你想在客户端下一次绑定到service时接受一个
对onRebind()的调用(而不是一个对onBind()的调用).onRebind()返回void,但是客户端依然会在它的onServiceConnected()回调中接收到IBinder.下图演示了这种生命其的
逻辑:
3。bindService和startService混合使用时
1.如果先bindService,再startService:
在bind的Activity退出的时候,Service会执行unBind方法而不执行onDestory方法,因为有startService方法调用过,所以Activity与Service解除绑定后会有一个与调用者没有关连的Service存在
2.如果先bindService,再startService,再调用Context.stopService
Service的onDestory方法不会立刻执行,因为有一个与Service绑定的Activity,但是在Activity退出的时候,会执行onDestory,如果要立刻执行stopService,就得先解除绑定
---------------------------
把上面的"如果先bindService,再startService"换成"如果先startService,再bindService",结果是一样的
问题:
如果在一个Activity的onCreate方法中,
先
bindService(serviceIntent, conn, Context.BIND_AUTO_CREATE);
再startService(serviceIntent);
退出这个Activity时,会执行onUnBind
但是再次进入这个Activity的时候,为什么不执行onBind方法了?只有在这个Service销毁后(执行onDestory),再进这个Activity才会执行onBind,还有就是当有两个客户端时,在第一个客户端startServie启动服务再bindService绑定服务,这时跳到第二个客户端里(启动时会调用onBind()),再客户端startServie启动服务再bindService绑定服务,启动时不会调用用onBind()了(因为之前客户端已经启动后没有onDestory()销毁Service,所以再客户端第二次绑定服务时,只会返回IBinder对象给onServiceConnected()),而且要注意的是当,当第一个服务启动并绑定一个服务时,再跳去第二个服务端启动并绑定这个服务时,第二个服务端再解绑时,不会调用onUnbind(),只有回到第一个客户端时,解绑这是才会调用onUnbind(),顺序反过来结果是一样的。得出一个结论是:当一个服务没被onDestory()销毁之前,只有第一个启动它的客户端能调用它的onBind()和onUnbind()。
package yy.android.service;
import org.apache.http.conn.ClientConnectionManager;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences.Editor;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class ServiceActivity extends Activity {
// private final String TAG = "ServiceActivity";
private Button unbind;
public static IService iService=null;
private Button mSkiptoClient;
private Button mStart;
public static EditText medit;
private Button mBind;
private Button mStop;
public static ServiceConnection connection=new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
Log.d("LOG","Activity ->Disconnected the LocalService");
}
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
//获取连接的服务对象
//System.out.println("Connection!!!");
iService=(IService)service;
medit.setText(iService.getName());
Log.d("LOG","Activity ->Connected the Service");
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.d("LOG","Activity ->OnCreate");
unbind = (Button)findViewById(R.id.unbind);
mSkiptoClient = (Button)findViewById(R.id.skip);
mStart = (Button)findViewById(R.id.start);
mStop = (Button )findViewById(R.id.stop);
medit = (EditText)findViewById(R.id.edit);
mBind = (Button)findViewById(R.id.connection);
mBind.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent(ServiceActivity.this,LocalService.class);
bindService(intent,connection, BIND_AUTO_CREATE);
}
});
mStart.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent(ServiceActivity.this,LocalService.class);
startService(intent);
}
});
mStop.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent(ServiceActivity.this,LocalService.class);
stopService(intent);
}
});
mSkiptoClient.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent("android.intent.action.YClient");
startActivity(intent);
}
});
unbind.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
unbindService(connection);
}
});
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d("LOG","Activity ->OnDestory");
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
// unbindService(connection);
Log.d("LOG","Activity ->OnPause");
super.onPause();
}
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Log.d("LOG","Activity ->OnRestart");
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
Log.d("LOG","Activity ->OnResume");
// Intent intent=new Intent(ServiceActivity.this,LocalService.class);
// bindService(intent,connection, BIND_AUTO_CREATE);
super.onResume();
}
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Log.d("LOG","Activity ->OnSatrt");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.d("LOG","Activity ->OnStop");
}
}
////////////////////////////////////////////////////////////////////////////
package yy.android.service;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class CLient extends Activity{
private IService iService2=null;
private Button unbind2;
private Button mStart2;
private EditText medit2;
private Button mBind2;
private Button mStop2;
ServiceConnection connection2=new ServiceConnection() {
public void onServiceDisconnected(ComponentName name) {
Log.d("LOG","Client ->Disconnected the LocalService");
}
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
//获取连接的服务对象
//System.out.println("Connection!!!");
iService2=(IService)service;
medit2.setText(iService2.getName());
Log.d("LOG","Client ->Connected the Service");
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.client);
Log.d("LOG","Client ->OnCreate");
unbind2 = (Button)findViewById(R.id.unbind2);
mStart2 = (Button)findViewById(R.id.start2);
mStop2 = (Button )findViewById(R.id.stop2);
medit2 = (EditText)findViewById(R.id.edit2);
mBind2 = (Button)findViewById(R.id.connection2);
mBind2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent(CLient.this,LocalService.class);
bindService(intent,connection2, BIND_AUTO_CREATE);
}
});
mStart2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent(CLient.this,LocalService.class);
startService(intent);
}
});
mStop2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent(CLient.this,LocalService.class);
stopService(intent);
}
});
unbind2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Log.e("LOG", "Unbind");
unbindService(connection2);
Log.e("LOG", "Unbind");
}
});
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
//unbindService(connection2);
Log.d("LOG","Client ->OnDestory");
super.onDestroy();
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Log.d("LOG","Client ->OnPause");
}
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Log.d("LOG","Client ->OnRestart");
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Log.d("LOG","Client ->OnResume");
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Log.d("LOG","Client ->OnSatrt");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.d("LOG","Client ->OnStop");
}
}
///////////////////////////////////////////////////////////////////
package yy.android.service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class LocalService extends Service{
private MyBind myBind=new MyBind();
public IBinder onBind(Intent intent) {
//System.out.println("Service onBind!!!");
Log.d("LOG","LocalService ->onBind");
return myBind;
}
@Override
public void onCreate() {
// TODO Auto-generated method stub
Log.d("LOG","LocalService ->onCreate");
super.onCreate();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d("LOG","LocalService ->onDestory");
super.onDestroy();
}
@Override
public void onStart(Intent intent, int startId) {
// TODO Auto-generated method stub
Log.d("LOG","LocalService ->onSatrt");
super.onStart(intent, startId);
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
Log.d("LOG","LocalService ->onUnbind");
return super.onUnbind(intent);
//return true;
}
@Override
public void onRebind(Intent intent) {
// TODO Auto-generated method stub
Log.d("LOG","LocalService ->onRebind");
super.onRebind(intent);
}
public class MyBind extends Binder implements IService{
public String getName() {
// TODO Auto-generated method stub
return "YUZHIBOYI";
}
}
}
/////////////////////////////////////////////////////////////////////////
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="yy.android.service"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".ServiceActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".CLient"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.YClient" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service android:name=".LocalService">
<intent-filter>
<action android:name="com.yy.yy"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
</application>
</manifest>
/////////////////////////////////////////////////////////
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/edit2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
></EditText>
<Button
android:id = "@+id/connection2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/Bind"
/>
<Button
android:id = "@+id/start2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/Start"
/>
<Button
android:id = "@+id/stop2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/StopService"
/>
<Button
android:id = "@+id/unbind2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/UnbindService"
/>
</LinearLayout>
//////////////////////////////////////////////////////
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/edit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
></EditText>
<Button
android:id = "@+id/connection"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/Bind"
/>
<Button
android:id = "@+id/start"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/Start"
/>
<Button
android:id = "@+id/stop"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/StopService"
/>
<Button
android:id = "@+id/skip"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/Skip"
/>
<Button
android:id = "@+id/unbind"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "@string/UnbindService"
/>
</LinearLayout>
////////////////////////////////////////////////////
混合使用的时候总结的,欢迎大家来一起讨论!
【Android 界面效果34】Android里Service的bindService()和startService()混合使用深入分析的更多相关文章
- 【Android 界面效果25】android中include标签的使用
在一个项目中我们可能会需要用到相同的布局设计,如果都写在一个xml文件中,代码显得很冗余,并且可读性也很差,所以我们可以把相同布局的代码单独写成一个模块,然后用到的时候可以通过<include ...
- 【Android 界面效果21】Android ViewPager使用详解
这是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api.而viewpager就是其中之一利用它,我们可以做很多事情,从最简单的导航,到页面菜单等等.那如 ...
- 【Android 界面效果17】Android手机平板两不误,使用Fragment实现兼容手机和平板的程序
记得我之前参与开发过一个华为的项目,要求程序可以支持好几种终端设备,其中就包括Android手机和Android Pad.然后为了节省人力,公司无节操地让Android手机和Android Pad都由 ...
- 【Android 界面效果31】Android--侧滑菜单应用的实现
侧滑菜单应用现在非常多,而且实现方式也多种多样.通过在网上的多方查找,我找到郭霖少侠的这篇文章:http://blog.csdn.net/guolin_blog/article/details/874 ...
- 【Android 界面效果23】LayoutInflater作用及使用
作用: 1.对于一个没有被载入或者想要动态载入的界面, 都需要使用inflate来载入. 2.对于一个已经载入的Activity, 就可以使用实现了这个Activiyt的的findViewById方 ...
- 【Android 界面效果22】Android的Tab与TabHost
Tab与TabHost 这就是Tab,而盛放Tab的容器就是TabHost 如何实现?? 每一个Tab还对应了一个布局,这个就有点好玩了.一个Activity,对应了多个功能布局. ①新建一个Tab项 ...
- 【Android 界面效果18】Android软件开发之常用系统控件界面整理
[java] view plaincopyprint? <span style="font-size:18px">1.文本框TextView TextView的作用 ...
- 【Android 界面效果16】关于android四大组件的总结
Android四大组件:Activity.Service.Broadcast receiver.Content provider 在Android中,一个应用程序可以使用其它应用程序的组件,这是And ...
- 【Android 界面效果13】关于全屏和取消标题栏
------- 源自梦想.永远是你IT事业的好友.只是勇敢地说出我学到! ---------- 去掉标题栏: 第一种:也一般入门的时候经常使用的一种方法 requestWindowFeature(Wi ...
随机推荐
- POJ2299Ultra-QuickSort (线段树和归并排序的解法)
题目大意就是说帮你给一些(n个)乱序的数,让你求冒泡排序需要交换数的次数(n<=500000) 此题最初真不会做,我也只是在听了章爷的讲解后才慢慢明白过来的 首先介绍线段树的解法: 我们先将原数 ...
- kindeditor html代码过滤不能保存
这是因为编辑器默认开启了过滤模式(filterMode:true).当filterMode为true时,编辑器会根据htmlTags设定自动过滤HTML代码,主要是为了生成干净的代码.如果想保留所有H ...
- Joel Spolsky对计算机学生的七大建议
/*先来介绍下作者:Joel Spolsky,世界最具影响的程序员网志Joel on Software的主人,软件业一位旗帜鲜明的思想者,一位传统软件管理理念的挑战者.他创办的这个网站被程序员誉为“反 ...
- python安装(windows)
1.python安装(windows) 1.1 下载安装包 https://www.python.org/downloads/ 1.2 安装 python2.7默认安装路径:C:\python27 注 ...
- android 解释dp,px,pt,sp单位
1.dp(dip):不同设备有不同的显示效果,这个和设备硬件有关系,一般我们为了支持WVGA,HVGA和QVGA对剑使用这个,它是不依赖像素的 2.px:pixels(像素),不同设备显示效果相同,一 ...
- document.getElementById和document.querySelector的区别
zepto中的$(".111")出错,jQuery中$(".111")不出错的原因: zepto用document.querySelector实现,jQuery ...
- (剑指Offer)面试题16:反转链表
题目: 定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点. 链表的定义如下: struct ListNode{ int val; ListNode* next; }; 思路: 反 ...
- WSO2 Stratos手册
WSO2 Stratos是最完整的企业级cloud solution,提供了一个开放的PaaS平台,相比于其他的PaaS平台来说,Stratos支持更多核心的服务.Stratos2.0对那些想从异构环 ...
- 网络虚拟化技术 TUN/TAP MACVLAN MACVTAP
TUN 设备 TUN 设备是一种虚拟网络设备,通过此设备,程序可以方便得模拟网络行为.先来看看物理设备是如何工作的:
- Using Eclipse With CloudStack
As part of switching to Apache Maven for building CloudStack, the .classpath and .project files used ...