上一篇学习使用了 基本数据类型的传递,但是在实际开发中肯定是不够用的
这一篇主要学习使用Aidl来实现自定义对象的传递
服务端要简单一些,先写一下服务端(例子是参考的网上的)
需要传递的实体类(不能用Serializable)
package com.chang.test.remote; import android.os.Parcel; import android.os.Parcelable; /** * Created by changquan on 2016/2/26. */ public class StudentBean implements Parcelable{ private String name; private int age; private long number; public StudentBean(String name, int age, long number) { this.name = name; this.age = age; this.number = number; } public StudentBean(Parcel source) { //注意:这里的name age number 的读取顺序和下面writeToParcel()方法里面的顺序要一致,否则出错 this.name = source.readString(); this.age = source.readInt(); this.number = source.readLong(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public long getNumber() { return number; } public void setNumber(int number) { this.number = number; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", number=" + number + '}'; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(age); dest.writeLong(number); } public static final Creator<StudentBean> CREATOR = new Creator<StudentBean>() { @Override public StudentBean createFromParcel(Parcel source) { return new StudentBean(source); } @Override public StudentBean[] newArray(int size) { return new StudentBean[0]; } }; }
然后是两个aidl文件(一个是供使用的接口,一个是为bean指定路径)
StudentBean.aidl(这里去创建aidl文件的时候,因为同名所以可以先创建一个文件,然后改后缀名就好)
package com.chang.test.remote; parcelable StudentBean;
Iserver.aidl
// IServer.aidl package com.chang.test.remote; import com.chang.test.remote.StudentBean; // Declare any non-default types here with import statements interface IServer { // 一般数据类型 void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); String callRemote(); // 复杂数据类型 // 这里的in 是指客户端传值 ,out是服务端返回值,inout是代表双向传值,必须要写一个 List<StudentBean> addStudent(in StudentBean studentBean); }
这里可能会报错,找不到bean,那就是文件放的位置不对,可以通过下面的方法来解决(在该模块的gradle里面添加)
sourceSets { main { Manifest.srcFile 'src/main/AndroidManifest.xml' java.srcDirs = ['src/main/java', 'src/main/aidl'] resources.srcDirs = ['src/main/java', 'src/main/aidl'] aidl.srcDirs = ['src/main/aidl'] res.srcDirs = ['src/main/res'] assets.srcDirs = ['src/main/assets'] } }
也有可能直接编译失败 报如下的错
Error:Execution failed for task ':remote:compileDebugAidl'.
这个可能是aidl文件的包名有误,也有可能是项目的编译版本和编译工具的版本不一致,右键项目 open Moudle Setting -> app -> 修改Compile Sdk Version 和Build Tools Version 版本一致
接下来就是所有接口的实现类
RemoteServerde 实现
package server; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import com.chang.test.remote.IServer; import com.chang.test.remote.StudentBean; import java.util.ArrayList; import java.util.List; /** * Created by changquan on 2017/8/22. */ public class RemoteServer extends Service{ private ArrayList<StudentBean> students; @Override public IBinder onBind(Intent intent) { students = new ArrayList<>(); return mBinder; } private IBinder mBinder = new IServer.Stub() { // 基本类型 @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException { } @Override public String callRemote() throws RemoteException { return "100000"; } // 复杂类型 @Override public List<StudentBean> addStudent(StudentBean student) throws RemoteException { students.add(student); return students; } }; }
// 所有服务端的实现就已经完成了
// 接下来就要实现 客户端了
简单的看一下客户端的目录
aidl文件夹就是拷贝的服务端的
StudentBean 也是拷贝的服务端的,但是要保证包名一致和服务端
MianActivity里面绑定远程服务(具体的实现如下)
package com.chang.test.chang; 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.os.RemoteException; import android.util.Log; import android.view.View; import android.widget.TextView; import android.widget.Toast; import com.chang.test.remote.IServer; import com.chang.test.remote.StudentBean; import java.util.ArrayList; public class MainActivity extends Activity { private TextView bind; private Intent intent; private IServer iServer; private MyConn myConn = new MyConn(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bind = (TextView) findViewById(R.id.bind); bind.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 绑定服务 intent = new Intent(); intent.setAction("android.intent.action.com.chang.test.remoteserver"); intent.setPackage("com.chang.test.remote"); bindService(intent,myConn,BIND_AUTO_CREATE); } }); } class MyConn implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { iServer = IServer.Stub.asInterface(service); try { // 基本数据的类型 String s = iServer.callRemote(); Log.e("hhhhhhhhhh",s); // 复杂类型 ArrayList<StudentBean> students = (ArrayList<StudentBean>) iServer.addStudent(new StudentBean("changchang",20,120)); Log.e("hhhhhhhhhh",students.toString()); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { Toast.makeText(MainActivity.this,"失败!",Toast.LENGTH_SHORT).show(); } } @Override protected void onDestroy() { super.onDestroy(); unbindService(myConn); } }
上面的action在上一遍中有写到,就是远程server的一个事件
这样就完成了整个studio 中aidl的全部实现
效果