版权声明:本文为【欧阳鹏】原创文章,欢迎转载,转载请注明出处! 【http://blog.csdn.net/ouyang_peng】
通过上一篇(Android Service学习之AIDL, Parcelable和远程服务)的介绍,这一篇写一个小实例来实践一下
step1:建立两个应用,分别为RemoteService和RemoteServiceClient
先编写服务器端的内容
step2:开始编写一个StudentQuery.aidl文件
AIDL(Android Interface Definition Language),用来定义远程接口。AIDL接口定义语言的语法十分简单,这种接口定义语言并不是一种真正的编程语言,它只是定义两个进程之间的通信接口,因此语法非常简单。AIDL的语法与Java接口很相似,但是也存在以下几点差异:
- AIDL定义接口的源代码必须以 .aidl 结尾
- AIDL接口中用到的数据类型,除了基本类型、String、List、Map、CharSequence之外,其他类型全部都需要导入包,即使它们在同一个包中也需要导包。
- package cn.roco.aidl;
- interface StudentQuery {
- String queryStudent(int number);
- }
系统会根据此aidl文件生成一个类StudentQuery.java接口
StudentQuery接口中包含一个Stub内部类,该内部类实现了IBinder和StudentQuery接口,这个Stub类将会作为远程Service的回调类,它实现了IBinder接口,因此可以作为Service的onBind()方法的返回值。
- /*
- * This file is auto-generated. DO NOT MODIFY.
- * Original file: C:\\Documents and Settings\\student\\android\\RemoteService\\src\\cn\\roco\\aidl\\StudentQuery.aidl
- */
- package cn.roco.aidl;
- public interface StudentQuery extends android.os.IInterface
- {
- /** Local-side IPC implementation stub class. */
- public static abstract class Stub extends android.os.Binder implements cn.roco.aidl.StudentQuery
- {
- private static final java.lang.String DESCRIPTOR = "cn.roco.aidl.StudentQuery";
- /** Construct the stub at attach it to the interface. */
- public Stub()
- {
- this.attachInterface(this, DESCRIPTOR);
- }
- /**
- * Cast an IBinder object into an cn.roco.aidl.StudentQuery interface,
- * generating a proxy if needed.
- */
- public static cn.roco.aidl.StudentQuery asInterface(android.os.IBinder obj)
- {
- if ((obj==null)) {
- return null;
- }
- android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
- if (((iin!=null)&&(iin instanceof cn.roco.aidl.StudentQuery))) {
- return ((cn.roco.aidl.StudentQuery)iin);
- }
- return new cn.roco.aidl.StudentQuery.Stub.Proxy(obj);
- }
- public android.os.IBinder asBinder()
- {
- return this;
- }
- @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
- {
- switch (code)
- {
- case INTERFACE_TRANSACTION:
- {
- reply.writeString(DESCRIPTOR);
- return true;
- }
- case TRANSACTION_queryStudent:
- {
- data.enforceInterface(DESCRIPTOR);
- int _arg0;
- _arg0 = data.readInt();
- java.lang.String _result = this.queryStudent(_arg0);
- reply.writeNoException();
- reply.writeString(_result);
- return true;
- }
- }
- return super.onTransact(code, data, reply, flags);
- }
- private static class Proxy implements cn.roco.aidl.StudentQuery
- {
- private android.os.IBinder mRemote;
- Proxy(android.os.IBinder remote)
- {
- mRemote = remote;
- }
- public android.os.IBinder asBinder()
- {
- return mRemote;
- }
- public java.lang.String getInterfaceDescriptor()
- {
- return DESCRIPTOR;
- }
- public java.lang.String queryStudent(int number) throws android.os.RemoteException
- {
- android.os.Parcel _data = android.os.Parcel.obtain();
- android.os.Parcel _reply = android.os.Parcel.obtain();
- java.lang.String _result;
- try {
- _data.writeInterfaceToken(DESCRIPTOR);
- _data.writeInt(number);
- mRemote.transact(Stub.TRANSACTION_queryStudent, _data, _reply, 0);
- _reply.readException();
- _result = _reply.readString();
- }
- finally {
- _reply.recycle();
- _data.recycle();
- }
- return _result;
- }
- }
- static final int TRANSACTION_queryStudent = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
- }
- public java.lang.String queryStudent(int number) throws android.os.RemoteException;
- }
step3:编写服务类StudentQueryService.java
该Service实现类的onBind()方法所返回的IBinder对象应该是的StudentQuert.Stub的子类的实例。
- package cn.roco.remote.service;
- import android.app.Service;
- import android.content.Intent;
- import android.os.IBinder;
- public class StudentQueryService extends Service {
- private String[] names = new String[100];
- private IBinder binder = new StudentQueryBinder();
- @Override
- public IBinder onBind(Intent intent) {
- return binder;
- }
- /**
- * 通过学号查询学生姓名
- *
- * @param no
- * @return
- * @throws Exception
- */
- public String query(int no) {
- if (no > 0 && no < names.length + 1) {
- return names[no - 1];
- } else {
- return null;
- }
- }
- /**
- * 创建服务的时候做初始化操作
- */
- @Override
- public void onCreate() {
- for (int i = 0; i < names.length; i++) {
- names[i] = "RemoteQuery_" + (i + 1);
- }
- super.onCreate();
- }
- /**
- * 关闭服务的时候,释放资源
- */
- @Override
- public void onDestroy() {
- for (int i = 0; i < names.length; i++) {
- names[i] = null;
- }
- }
- /**
- * cn.roco.aidl.StudentQuery.Stub 由系统根据StudentQuery.aidl自动生成
- */
- private final class StudentQueryBinder extends
- cn.roco.aidl.StudentQuery.Stub {
- @Override
- public String queryStudent(int number) {
- return query(number);
- }
- }
- }
step4:在AndroidManifest.xml文件中配置此服务
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="cn.roco.remote.service"
- android:versionCode="1"
- android:versionName="1.0">
- <uses-sdk android:minSdkVersion="8" />
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <service android:name=".StudentQueryService" >
- <intent-filter>
- <action android:name="cn.roco.remote.service.student.query"/>
- </intent-filter>
- </service>
- </application>
- </manifest>
step5:在客户端也要讲StudentQuery.aidl文件导入到客户端中
step6:设计客户端的UI界面,main.xml文件
- <?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/student_no" />
- <EditText android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:id="@+id/student_no" />
- <Button android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:text="@string/button_query"
- android:id="@+id/button_query" />
- <TextView android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:id="@+id/resultView" />
- </LinearLayout>
string.xml文件
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <string name="hello">Hello World, MainActivity!</string>
- <string name="app_name">远程学生查询系统</string>
- <string name="student_no">学号</string>
- <string name="button_query">查询</string>
- </resources>
step7:客户端访问AIDLService
客户端绑定远程Service与绑定本地Service区别不大,同样之需要两步。
- 1.创建ServiceConnection对象。
- 2.以ServiceConnection对象作为参数,调用Context的bindService()方法绑定远程Service即可。
与绑定本地Service不同的是,绑定远程Service的ServiceConnection并不能直接获取Service的onBind()方法所返回的对象,它只能返回onBind()方法所返回的对象的代理因此在ServiceConnection的onServiceConnected方法中需要通过如下代码进行处理:
- // 调用该方法将远程的IBinder转换
- studentQuery = cn.roco.aidl.StudentQuery.Stub.asInterface(service);
MainActivity.java文件
- <span style="font-size:14px;">package cn.roco.remoteservice.client;
- import cn.roco.aidl.StudentQuery;
- 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.Button;
- import android.widget.EditText;
- import android.widget.TextView;
- import android.widget.Toast;
- public class MainActivity extends Activity {
- private EditText student_no;
- private TextView resultView;
- private ServiceConnection conn = new StudentServiceConnection();
- private StudentQuery studentQuery;
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- resultView = (TextView) findViewById(R.id.resultView);
- student_no = (EditText) findViewById(R.id.student_no);
- Button button_query = (Button) findViewById(R.id.button_query);
- button_query.setOnClickListener(new ButtonClickListener());
- /**
- * 该Intent是RemoteService项目中的Service
- * "cn.roco.remote.service.student.query"为
- * <service android:name=".StudentQueryService" >
- <intent-filter>
- <action android:name="cn.roco.remote.service.student.query"/>
- </intent-filter>
- </service>
- */
- Intent service = new Intent("cn.roco.remote.service.student.query");
- // 绑定服务
- bindService(service, conn, BIND_AUTO_CREATE);
- }
- @Override
- protected void onDestroy() {
- unbindService(conn); // 解绑服务
- super.onDestroy();
- }
- /**
- * 该类中的两个方法都是回调函数
- */
- private class StudentServiceConnection implements ServiceConnection {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- // 调用该方法将远程的IBinder转换
- studentQuery = cn.roco.aidl.StudentQuery.Stub.asInterface(service); //重点理解
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- studentQuery=null;
- }
- }
- private final class ButtonClickListener implements View.OnClickListener {
- @Override
- public void onClick(View v) {
- String studentNo = student_no.getText().toString();
- String studentName;
- try {
- studentName = studentQuery.queryStudent(Integer
- .parseInt(studentNo));
- if (studentName!=null) {
- resultView.setText(studentName);
- }else{
- Toast.makeText(getApplicationContext(), "您输入的学号不在规定的学号内,请输入1到100的数字", 1).show();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }</span>
step8:将服务和客户端安装完后,查看运行的效果