我的Android进阶之旅------>Android Service学习之AIDL, Parcelable和远程服务实例
通过上一篇(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" / /LinearLayoutstring.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文件
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(); }
step8:将服务和客户端安装完后,查看运行的效果
Android App开发超实用实例 | Broadcast 介绍Broadcast的静态注册、动态注册及有序广播。 Broadcast(广播)分为发送者和接收者,可实现跨应用的消息传递。重启手机、闹钟、来电、接收短信等都会发出广播,通过BroadcastReceiver就可以接收广播并进行相应处理。
Android 架构MVC MVP MVVM+实例(下) MVC实例 1.在layout创建一个布局文件 2.实体类(User) 3.MVCLoginActivity MVP实例 1.Model层 2.Presenter层 3.View层 MVVM实例 1.Model层 2.ViewModel层 3.View层 实例传送门
Android 架构MVC MVP MVVM+实例(上) MVC是什么? Android中的MVC含义 MVC的缺点 MVP是什么 Android中的MVP含义 MVP的优点 MVP的缺点 MVVM是什么 Android中的MVVM含义 MVVM的优点 MVVM的缺点 MVP和MVC的最大区别 如何选取框架
Android CheckedTextView 使用+实例 CheckedTextView是什么 主要XML属性 在点击事件里判断状态设置状态 第一次点击无效 1.主界面CheckedTextViewActivity.java 2.主布局activity_textview_ctv.xml 3.复选框Adapter 4.复选框adapter对应布局 5.单选框adapter 6.单选框adapter对应布局 7.逻辑处理从adapter放在主界面处
Android ImageView及其子类 介绍+实例(下) ImageButton 什么是ImageButton 通过实例了解ImageButton 1、创建布局文件 运行效果如下: ImageButton灰色边框的产生原因和解决方案 QuickContactBadge 什么是QuickContactBadge QuickContactBadge的调用方法 通过实例了解QuickContactBadge 1、创建布局文件 2、让QuickContactBadge与特定联系人建立联系 3、运行效果
Android ImageView及其子类 介绍+实例(上) ImageView ImageView的继承关系 ImageView支持的常用XML属性 ImageView.ScaleType所支持的常量 ImageView加载图片 实例:用ImageView做一个图片查看器 1、创建布局文件 2、用代码使ImageView显示图片 3、运行效果 ImageView设置图片 设置圆角、圆形 1、通过RoundedBitmapDrawable设置圆角、圆形 2、使用图片加载框架进行设置,以Picasso为例
Android 面试题之 BroadcastReceiver 使用+实例 Broadcast Receiver是什么 Broadcast Receiver使用场景 Broadcast Receiver的种类 按发送顺序 按发送范围 按Broadcast Receiver的实现 Broadcast Receiver的使用 4.1静态注册 4.2动态广播 4.2.1自定义广播接受者, 4.2.2注册广播 4.2.3发送广播 4.2.4注销广播 4.3无序广播 4.4有序广播 Broadcast Receiver实现原理 LocalBroadcastManager特点 Broadcast Receiver注意事项 实例:BroadcastReceiverDemo.zip
Android 面试题之ContentProvider使用+实例 一、什么是ContentProvider 二、什么是Uri 三、什么是ContentResolver 四、创建ContentProvider 五、使用ContentProvider 六、跨应用使用ContentProvider 七、java.lang.SecurityException: Permission Denial: opening provider com.scc.cp.UserProvider from ProcessRecord 源码:ContentProviderDemo.zip
字节卷动 You will never know how excellent you are unless you impel yourself once.
相关文章
- Android SDK platforms build-tools等镜像下载
- 巧用Android图片资源,打造更精致的APP
- Android+struts2+json方式模拟手机登录功能
- androidwebview停用,Android推送技术解析,实战解析
- Android Studio打开出现:Default activity not found
- android 关于appcompat v7出错问题与解决
- [Android+LBS] LBS based on Symfony2 & MongoDB
- android UI设计时须要注意遵循的设计原则
- Android之Android apk动态加载机制的研究
- Android和Flutter混合开发
- android Route模块化路由设计方案
- Android客户端性能优化(魅族资深工程师毫无保留奉献)
- react-native 实现条码扫描(ios&android)
- android4.0 禁止横竖屏切换使用 android:configChanges="orientation|keyboardHidden"无效
- 我的Android进阶之旅------>Android 关于arm64-v8a、armeabi-v7a、armeabi、x86下的so文件兼容问题
- 我的Android进阶之旅------>Android中通过adb shell input来模拟滑动、按键、点击事件
- 我的Android进阶之旅------>Android关于Log的一个简单封装
- 我的Android进阶之旅------>android:drawableLeft的用法
- 我的Android进阶之旅------>Android二级ListView列表的实现
- 我的Android进阶之旅------>Android嵌入图像InsetDrawable的用法
- 我的Android进阶之旅------>如何为ListView组件加上快速滑块以及修改快速滑块图像
- 我的Android进阶之旅------>关于android:layout_weight属性的一个面试题
- 我的Android进阶之旅------>Android中AsyncTask源码分析
- 我的Android进阶之旅------>Android自定义窗口标题实例
- Android系统移植与调试之------->如何修改Android默认字体大小和设置里面字体大小比例
- 我的Android进阶之旅------>如何将Android源码导入Eclipse中来查看(非常实用)
- Android系统移植与调试之------->Amlogic方案编译步骤
- 我的Android进阶之旅------>Android Widget 桌面数字时钟(DigtalClockWidget)实例