Android 四大组件之(2)Service实现原理以及AIDL语言的使用详解
来源:互联网 发布:蓝海软件 编辑:程序博客网 时间:2024/05/18 18:53
1、Service概念介绍以及生命周期解析
Service是Android系统提供的四大组件之一,它的地位与Activity是并列的,只不过没有Activity的使用频率高。顾名思义,Service就是运行在后台的一种服务程序,一般很少与用户交互,因此service没有可视化界面。
定义一个简单的service类比较简单,只需要继承Service类,实现其生命周期几个方法,然后在Manifest文件中添加service标签即可。
Service有自己的生命周期,我们可以使用startService()启动一个service或者使用bindService()来绑定一个存在的service,还可以通过RPC(远程进程调用)机制来实现不同进程中的service的调用。
Service的生命周期介绍 :
使用startService()启动 : onCreate() → onStart() ;
如果对已经启动的service继续调用startService的话,则只进行onStart() ;
使用stopService()关闭 : onDestroy() ;
使用bindService()启动绑定service时,只会调用onCreate() →onBind(),永远不会调用onStart() .
2、本地Service不和Activity进行交互情况
java code :
public class ServiceA extends Service {@Overridepublic void onCreate() {super.onCreate();Log.i("service", "onCreate...");}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);//参数intent可以为activity向service传递相关信息Log.i("service", "onStart..."+intent.getStringExtra("name"));}@Overridepublic void onDestroy() {super.onDestroy();Log.i("service", "onDestroy...");} @Overridepublic IBinder onBind(Intent arg0) {return null;//不需要和Activity进行交互时,可以直接返回null}}
public class MainActivity extends Activity {private Button startBtn , stopBtn;@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.service_demo); startBtn = (Button) findViewById(R.id.startBtn); stopBtn = (Button) findViewById(R.id.stopBtn); startBtn.setOnClickListener(listener); stopBtn.setOnClickListener(listener); }private OnClickListener listener = new OnClickListener() {@Overridepublic void onClick(View view) {Intent service = new Intent();service.setAction("serviceA");//向service传递值service.putExtra("name", "i am service");switch (view.getId()) {case R.id.startBtn:startService(service);break;case R.id.stopBtn:stopService(service);break;default:break;}}};}
manifest:
<service android:name="com.zj.service.ServiceA"><intent-filter><action android:name="serviceA"></action></intent-filter></service>
3、本地Service与Activity进行交互情况
Java Code:
/** (1). 添加了一个public内部类继承Binder,并添加getService方法来返回当前的Service对象;(2). 新建一个IBinder对象——new那个Binder内部类;(3). onBind方法返还那个IBinder对象。 */public class ServiceB extends Service {private final IBinder mBinder = new MyBinder();public class MyBinder extends Binder{public ServiceB getService(){Log.i("service", "ServiceB.this "+ServiceB.this);return ServiceB.this;}}@Overridepublic IBinder onBind(Intent arg0) {Log.i("service", "onBind...");return mBinder;}@Overridepublic void onCreate() {super.onCreate();Log.i("service", "onCreate...");}@Overridepublic void onDestroy() {super.onDestroy();Log.i("service", "onDestroy...");}@Overridepublic void onStart(Intent intent, int startId) {super.onStart(intent, startId);//使用bindService()绑定service时,永远不会调用onStart()方法Log.i("service", "onStart...");} //测试service向activity传递信息 public String getData(){ return "hello android !"; } }
public class MainActivity extends Activity { private Button bindBtn , unbindBtn , dataBtn; private ServiceB mService; private boolean isRegist;//判断service是否已经成功注册 private String name; private ServiceConnection conn = new ServiceConnection() { //断开连接时调用 @Override public void onServiceDisconnected(ComponentName arg0) { Log.i("service", "onServiceDisconnected..."); } //连接时调用 @Override public void onServiceConnected(ComponentName arg0, IBinder binder) { mService = ((MyBinder)binder).getService(); Log.i("service", "onServiceConnected..."+mService); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.service_demo); bindBtn = (Button) findViewById(R.id.bindBtn); unbindBtn = (Button) findViewById(R.id.unbindBtn); dataBtn = (Button)findViewById(R.id.getData); bindBtn.setOnClickListener(listener); unbindBtn.setOnClickListener(listener); dataBtn.setOnClickListener(listener); } private OnClickListener listener = new OnClickListener() { @Override public void onClick(View view) { Intent service = new Intent(); service.setAction("serviceB"); //向service传递值 service.putExtra("name", "i am service"); switch (view.getId()) { case R.id.bindBtn: bindService(service, conn, Service.BIND_AUTO_CREATE); isRegist = true; break; case R.id.unbindBtn: //如果没有先进行bindService就直接unbindService会抛出异常"Service not registered" if(isRegist){ unbindService(conn); isRegist = false; } break; case R.id.getData: //获取Service传递过来的值 Toast.makeText(MainActivity.this, "service传递的值: "+mService.getData(), Toast.LENGTH_LONG).show(); break; default: break; } } }; }Service : onCreate() → onBind() → Activity : onServiceConnected() ; 可见onStart()是不会调用的!
4、远程Service与Activity的交互(AIDL的应用)
首先我们先上一个通俗的情景:在应用1中Activity绑定了一个Service,并且设置了一些值,此时我们想在应用2中调用该service并且想得到该值应该怎么做?我们都知道每个应用程序都运行在各自的进程中,并且android平台是不允许不同进程间进行直接的对象数据等传递的。如果必须进行跨进程之间的数据传递,那么我们就应该使用AIDL(Android Interface Definition Language)。
AIDL只支持方法,不能定义静态成员,并且方法也不能有类似public等的修饰符;AIDL运行方法有任何类型的参数和返回值,在java的类型中,以下的类型使用时不需要导入包(import),基本数据类型、String、Map、List.当然为了避免出错,建议只要使用了,就导入包。
使用AIDL的步骤:
服务端(提供服务):
第1步:定义一个*.aidl文件,该文件里是符合aidl语言规范的接口定义,里面定义了外部应用可以访问的方法。当我们保存该文件的时候,eclipse会自动为我们在gen文件夹下生成一个相应的java接口文件。如:
package com.zj.service;interface IPerson{void setName(String name);String getName();}
第2步:实现AIDL文件生成的JAVA接口Stub
public class PersonImpl extends IPerson.Stub {private String name;@Overridepublic String getName() throws RemoteException {return name;}@Overridepublic void setName(String name) throws RemoteException {this.name = name;}}
第3步:定义一个自己的service, 并将其注册到androidManifest.xml文件中,例如:
public class ServiceC extends Service {private Stub iPerson = new PersonImpl();@Overridepublic IBinder onBind(Intent arg0) {Log.i("service", "onBind...");return iPerson;}}
<service android:name="com.zj.service.ServiceC"><intent-filter><action android:name="forServiceAidl"></action></intent-filter></service>
注意这里一定要提供一个intent-filter,我们的客户端进程就是通过该action访问到服务端进程的哦。
我们都知道,在实现自己的service时,为了其他应用可以通过bindService来和我们的service进行交互,我们都要实现service中的onBind()方法,并且返回一个继承了Binder的内部类;在这里,eclipse自动为我们生成的RemoteServiceInterface.java中有一个实现了Binder的内部类,RemoteServiceInterface.Stub。AIDL要求我们,在这里不能再直接去实现Binder类了,而是去实现,AIDL提供给我们的Stub类。 实现stub类的同时,AIDL还要求我们同时实现我们在接口中定义的各种服务的具体实现。至此为止,我们的服务端已经和我们的aidl文件绑定到一起了哦。
同一个应用中的Activity为该Service中赋值:
public class MainActivity extends Activity {private IPerson iPerson;private Button bindBtn,unbindBtn;private ServiceConnection conn = new ServiceConnection() {//断开连接时调用@Overridepublic void onServiceDisconnected(ComponentName arg0) {}//连接时调用@Overridepublic void onServiceConnected(ComponentName arg0, IBinder binder) {iPerson = IPerson.Stub.asInterface(binder);if(iPerson!=null){try {iPerson.setName("Service AIDL");Toast.makeText(MainActivity.this, "赋值成功!", Toast.LENGTH_LONG).show();} catch (RemoteException e) {e.printStackTrace();Toast.makeText(MainActivity.this, "赋值失败!", Toast.LENGTH_LONG).show();}}}};@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.service_aidl); bindBtn = (Button)findViewById(R.id.bindBtn); unbindBtn = (Button)findViewById(R.id.unbindBtn); bindBtn.setOnClickListener(listener); unbindBtn.setOnClickListener(listener); }private OnClickListener listener = new OnClickListener() {@Overridepublic void onClick(View view) {switch (view.getId()) {case R.id.bindBtn://本应用中需要在manifest中配置RemoteServicebindService(new Intent("forServiceAidl"), conn, Service.BIND_AUTO_CREATE);break;case R.id.unbindBtn:unbindService(conn);break;default:break;}}};}
客户端:
第1步:客户端要想使用该服务,肯定要先知道我们的服务在aidl文件中到底对外提供了什么服务,对吧?所以,第一步,我们要做的就是,将aidl文件拷贝一份到客户端的程序中(这里一定要注意,包路径要和服务端的保持一致哦,例如服务端为cn.com.chenzheng_java.remote.a.aidl,那么在客户端这边也应该是这个路径)。
第2步:我们都知道,想要和service交互,我们要通过bindService方法,该方法中有一个ServiceConnection类型的参数。而我们的主要代码便是在该接口的实现中。
第3步:在ServiceConnection实现类的onServiceConnected(ComponentName name, IBinder service)方法中通过类似remoteServiceInterface = RemoteServiceInterface.Stub.asInterface(service);方式就可以获得远程服务端提供的服务的实例,然后我们就可以通过remoteServiceInterface 对象调用接口中提供的方法进行交互了。(这里的关键是通过*.Stub.asInterface(service);方法获取一个aidl接口的实例哦)
我们前面在服务端中说过了,必须提供一个intent-filter来匹配请求是否合法,所以我们在客户端访问服务的时候,还必须传递包含了匹配action的Intent哦。
客户端中使用服务端中的service范例:
public class MainActivity extends Activity {private IPerson person;private Button btn;private ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName arg0) {}//因为有可能有多个应用同时进行RPC操作,所以同步该方法@Overridepublic synchronized void onServiceConnected(ComponentName arg0, IBinder binder) {//获得IPerson接口person = IPerson.Stub.asInterface(binder);if(person != null){try {//RPC方法调用String name = person.getName();Toast.makeText(MainActivity.this, "远程进程调用成功!值为 : "+name, Toast.LENGTH_LONG).show();} catch (RemoteException e) {e.printStackTrace();Toast.makeText(MainActivity.this, "远程进程调用失败! ", Toast.LENGTH_LONG).show();}}}};@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btn = (Button)findViewById(R.id.btn); btn.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {//该应用中不需要在manifest中配置RemoteServicebindService(new Intent("forServiceAidl"), conn, Service.BIND_AUTO_CREATE);}}); }}
- Android 四大组件之(2)Service实现原理以及AIDL语言的使用详解
- Android 四大组件 Service实现原理以及AIDL语言的使用详解
- Android四大核心组件之Service|AIDL使用详解
- Android应用程序四大组件之使用AIDL如何实现跨进程调用Service
- 关于Android中的四大组件(AIDL Service的使用)
- Android四大组件------Service(远程服务AIDL的使用)
- Android四大组件之Service的使用
- Android 四大组件之特殊Service(IntentService)的使用
- Android四大组件之Service工作原理
- Android四大组件之---Service(服务)详解
- Android 四大组件之Service详解
- Android四大组件之Service详解
- Android中的四大组件之Service详解
- android四大组件之Service详解
- Android四大组件之Service详解
- Android四大组件之Service详解
- Android四大组件之Service详解
- Android -- 四大组件之Service详解
- 两个不错的天气预报代码(带图)
- C#利用ZedDemo组件生成数据报表
- 怎样写linux下的USB设备驱动程序
- android sdk 1.5-2.3 sdk 源码下载地址
- Strust2获得session和request
- Android 四大组件之(2)Service实现原理以及AIDL语言的使用详解
- arm中断控制寄存器
- 分页的 ACTION
- 详介oracle的RBO/CBO优化器
- 自定议字符串hashcode函数
- GPS启动分析
- Java SE 学习笔记 Lesson 4
- poj1141 括号序列 dp
- 使用VC实现可拖动窗口