Android四大组件之Service(笔记)续
2014-02-18 10:29
549 查看
在Android中,每个应用程序都有自己的进程,当需要在不同的进程之间进行通信,该如何来实现呢?进程间的通信即IPC通信,这个是android最核心的内容,熟悉了ipc通信android就熟悉了一大半。
在java中是不支持跨进程的内存共享,因此要传递对象就必须把对象解析成系统能够理解的数据编码,以便达到跨进程通信的目的。
在这里就采用AIDL(Android Interface Definition Language 接口定义语言 )方式来实现
AIDL是一种接口定义语言,用于约束两个进程通讯规则,提供给编译器生成代码,实现android设备上两个进程间IPC的通信,AIDL的进程之间的通讯信息首先被转换成AIDL协议信息,然后发送给对方,对方接收到AIDL协议信息后又转换成相应的对象。由于进程间通信信息需要双向转换,所以android采用代理类的形式在背后执行双向转换,代理类由android编译器生成,对开发人员来说是透明的,不需要知道如何实现。
实现跨进程通信一般需要四个步骤:
假如A应用需要跨进程调用B应用的一个方法,B应用以service的方式为A应用提供服务
1.在B应用中编写.aidl文件
package com.android.aidl;
interface QueryService {
String queryStudent(int no);
}
当.aidl文件创建完成之后,刷新eclipse会自动在gen目录下生成QueryService.java接口文件
类里面包括aidl定义的方法,还包括一些其它辅助方法。值得关注的是接口文件中生成一个Stub的抽象asInterface(IBinderiBinder),它返回接口类型的实例,对于远程服务调用,远程服务返回给客户端的对象为代理对象,客户端在onServiceConnected(ComponentName
name, IBinder service)方法引用该对象时不能直接强转成接口类型的实例,而应该使用asInterface(IBinderiBinder)进行类型转换。
编写aidl文件时应该注意:
1.接口名和aidl文件名必须相同。
2.接口和方法前不用加访问权限修饰符public,private,protected等,也不能用final,static。
3.Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),使用这些类型时不需要import声明。对于List和Map中的元素类型必须是Aidl支持的类型。如果使用自定义类型作为参数或返回值,自定义类型必须实现Parcelable接口。
4.自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中。
5.在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数。
6.Java原始类型默认的标记为in,不能为其它标记。
2.在B应用中实现aidl生成的接口,并非直接实现接口,而且通过继承Stub来实现(Stub实现了aidl的接口)
代码如下:
private final class StudentBinder extends QueryService.Stub{
public String queryStudent(int no) throws RemoteException {
Log.i("StudentService", no+"");
return query(no);
}
}
3.在B应用中创建一个Service,在服务的onBind(Intent intent) 方法中返回实现了aidl接口的对象,在这里是StudentBinder对象
代码如下:
package com.android.remoteservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.android.aidl.QueryService;
public class StudentService extends Service {
private String[] names = {"成龙", "李连杰", "洪金宝"};
private IBinder binder = new StudentBinder();
private String query(int no){
if(no > 0 && no <4){
return names[no - 1];
}
return null;
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
private final class StudentBinder extends QueryService.Stub{
public String queryStudent(int no) throws RemoteException {
Log.i("StudentService", no+"");
return query(no);
}
}
}
在其他其他应用可以通过隐式意图访问服务,意图的动作可以自定义,AndroidManifest.xml配置代码如下:
<serviceandroid:name=".QueryService" >
<intent-filter>
<action
android:name=“com.android.process.aidl.QueryService" />
</intent-filter>
</service>
4.把B应用中aidl文件所在package连同aidl文件一起拷贝到客户端A应用,eclipse会自动在A应用的gen目录中为aidl文件同步生成QueryService.java接口文件,接下来就可以在A应用中实现与B应用通信
A应用布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/number"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/number"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button"
android:onClick="query"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/resultView"
/>
</LinearLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, MainActivity!</string>
<string name="app_name">访问远程服务</string>
<string name="number">学号</string>
<string name="button">查询</string>
</resources>
MainActivity.java
package com.android.service.client;
import com.android.aidl.QueryService;
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.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private EditText numberText;
private TextView resultView;
private StudentConnection conn = new StudentConnection();
private QueryService queryService;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
numberText = (EditText) this.findViewById(R.id.number);
resultView = (TextView) this.findViewById(R.id.resultView);
Intent service = new Intent("com.android.process.aidl.QueryService");
bindService(service, conn, BIND_AUTO_CREATE);
}
private final class StudentConnection implements ServiceConnection{
public void onServiceConnected(ComponentName name, IBinder service) {
queryService = QueryService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName name) {
queryService = null;
}
}
public void query(View v){
String number = numberText.getText().toString();
try {
String name = queryService.queryStudent(Integer.valueOf(number));
resultView.setText(name);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在java中是不支持跨进程的内存共享,因此要传递对象就必须把对象解析成系统能够理解的数据编码,以便达到跨进程通信的目的。
在这里就采用AIDL(Android Interface Definition Language 接口定义语言 )方式来实现
AIDL是一种接口定义语言,用于约束两个进程通讯规则,提供给编译器生成代码,实现android设备上两个进程间IPC的通信,AIDL的进程之间的通讯信息首先被转换成AIDL协议信息,然后发送给对方,对方接收到AIDL协议信息后又转换成相应的对象。由于进程间通信信息需要双向转换,所以android采用代理类的形式在背后执行双向转换,代理类由android编译器生成,对开发人员来说是透明的,不需要知道如何实现。
实现跨进程通信一般需要四个步骤:
假如A应用需要跨进程调用B应用的一个方法,B应用以service的方式为A应用提供服务
1.在B应用中编写.aidl文件
package com.android.aidl;
interface QueryService {
String queryStudent(int no);
}
当.aidl文件创建完成之后,刷新eclipse会自动在gen目录下生成QueryService.java接口文件
类里面包括aidl定义的方法,还包括一些其它辅助方法。值得关注的是接口文件中生成一个Stub的抽象asInterface(IBinderiBinder),它返回接口类型的实例,对于远程服务调用,远程服务返回给客户端的对象为代理对象,客户端在onServiceConnected(ComponentName
name, IBinder service)方法引用该对象时不能直接强转成接口类型的实例,而应该使用asInterface(IBinderiBinder)进行类型转换。
编写aidl文件时应该注意:
1.接口名和aidl文件名必须相同。
2.接口和方法前不用加访问权限修饰符public,private,protected等,也不能用final,static。
3.Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),使用这些类型时不需要import声明。对于List和Map中的元素类型必须是Aidl支持的类型。如果使用自定义类型作为参数或返回值,自定义类型必须实现Parcelable接口。
4.自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中。
5.在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数。
6.Java原始类型默认的标记为in,不能为其它标记。
2.在B应用中实现aidl生成的接口,并非直接实现接口,而且通过继承Stub来实现(Stub实现了aidl的接口)
代码如下:
private final class StudentBinder extends QueryService.Stub{
public String queryStudent(int no) throws RemoteException {
Log.i("StudentService", no+"");
return query(no);
}
}
3.在B应用中创建一个Service,在服务的onBind(Intent intent) 方法中返回实现了aidl接口的对象,在这里是StudentBinder对象
代码如下:
package com.android.remoteservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.android.aidl.QueryService;
public class StudentService extends Service {
private String[] names = {"成龙", "李连杰", "洪金宝"};
private IBinder binder = new StudentBinder();
private String query(int no){
if(no > 0 && no <4){
return names[no - 1];
}
return null;
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
private final class StudentBinder extends QueryService.Stub{
public String queryStudent(int no) throws RemoteException {
Log.i("StudentService", no+"");
return query(no);
}
}
}
在其他其他应用可以通过隐式意图访问服务,意图的动作可以自定义,AndroidManifest.xml配置代码如下:
<serviceandroid:name=".QueryService" >
<intent-filter>
<action
android:name=“com.android.process.aidl.QueryService" />
</intent-filter>
</service>
4.把B应用中aidl文件所在package连同aidl文件一起拷贝到客户端A应用,eclipse会自动在A应用的gen目录中为aidl文件同步生成QueryService.java接口文件,接下来就可以在A应用中实现与B应用通信
A应用布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/number"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/number"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button"
android:onClick="query"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/resultView"
/>
</LinearLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, MainActivity!</string>
<string name="app_name">访问远程服务</string>
<string name="number">学号</string>
<string name="button">查询</string>
</resources>
MainActivity.java
package com.android.service.client;
import com.android.aidl.QueryService;
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.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private EditText numberText;
private TextView resultView;
private StudentConnection conn = new StudentConnection();
private QueryService queryService;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
numberText = (EditText) this.findViewById(R.id.number);
resultView = (TextView) this.findViewById(R.id.resultView);
Intent service = new Intent("com.android.process.aidl.QueryService");
bindService(service, conn, BIND_AUTO_CREATE);
}
private final class StudentConnection implements ServiceConnection{
public void onServiceConnected(ComponentName name, IBinder service) {
queryService = QueryService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName name) {
queryService = null;
}
}
public void query(View v){
String number = numberText.getText().toString();
try {
String name = queryService.queryStudent(Integer.valueOf(number));
resultView.setText(name);
} catch (Exception e) {
e.printStackTrace();
}
}
}
相关文章推荐
- Android开发总结笔记 四大组件之Service(中) 1-2-5
- Android开发总结笔记 四大组件之Service(下) 1-2-6
- android四大组件笔记之Service(二)
- Android四大组件之Service(笔记)
- Android开发总结笔记 四大组件之Service(上) 1-2-4
- android四大组件之-Service笔记
- Android四大组件之Service复习笔记
- Android笔记---四大组件之Service服务详解
- #Android笔记#四大组件之Service
- Android四大组件之Service服务学习笔记(一)
- android四大组件之service
- Android源码解析四大组件系列(一)---Service的启动过程分析
- android 四大组件之Service(10) AIDL android interface definition language
- Android四大组件之Service
- Android四大组件之一Service介绍-android学习之旅(十二)
- Android四大组件之Service
- Android 四大组件生命周期:Service
- Android四大组件应用系列5——使用AIDL实现跨进程调用Service
- Android四大组件之Service(一)本地服务
- 01 Android应用的构成 四大组件 Activity, Intent Receiver , Service , Content Provider