AIDL实例
转载声明:原文转自:http://www.cnblogs.com/xiezie/p/5658372.html
什么是AIDL
Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。
为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。
建立AIDL服务的步骤
建立AIDL服务要比建立普通的服务复杂一些,具体步骤如下:
(1)在Eclipse Android工程的Java包目录中建立一个扩展名为aidl的文件。该文件的语法类似于Java代码,但会稍有不同。
(2)如果aidl文件的内容是正确的,ADT会自动生成一个Java接口文件(*.java)。
(3)建立一个服务类(Service的子类)。
(4)实现由aidl文件生成的Java接口。
(5)在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。
另外,要设置service的process属性为":remote"
实现AIDL接口的说明:
(1)AIDL接口只支持方法,不能声明静态成员;
(2)不会有返回给调用方的异常。
AIDL实例
服务器端
1.建立JavaBean--Model book.java 继承 Parceable 实现序列化。
package testaidl.x.com.testaidl.aidl; import android.os.Parcel; import android.os.Parcelable; /** * Created by Administrator on 2016/7/10. */ public class Book implements Parcelable { public int id; public String name; public Book(int id, String name) { this.id = id; this.name = name; } private Book(Parcel in) { id = in.readInt(); name = in.readString(); } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(id); out.writeString(name); } public static final Creator<Book> CREATOR = new Creator<Book>() { @Override public Book createFromParcel(Parcel in) { return new Book(in); } @Override public Book[] newArray(int size) { return new Book[size]; } }; }
2.(Android Studio) 在src/main/下 建立 aidl 包(与java同级),在aidl下建立JavaBean相同目录的包
建立JavaBean相同名称的.aidl文件 --> Book.aidl
建立服务接口的.aidl文件 --> IBookManager.aidl (必须 import testaidl.x.com.testaidl.aidl.Book;)
// IBook.aidl package testaidl.x.com.testaidl.aidl; parcelable Book;
// IBookManager.aidl package testaidl.x.com.testaidl.aidl; import testaidl.x.com.testaidl.aidl.Book; interface IBookManager { List<Book> getAllBook(); void addBook(in Book book); }
目录:
3.此时,进行编译 如果aidl文件的内容是正确的,IDE会自动生成在根目录下一个Java接口文件(*.java)。-->IBookManager.java
4.建立一个服务类(Service的子类)。-->RemoteService.java
package testaidl.x.com.testaidl.aidl; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import java.util.LinkedList; import java.util.List; /** * Created by Administrator on 2016/7/10. */ public class RemoteService extends Service { private List<Book> mBooks = new LinkedList<>(); @Override public IBinder onBind(Intent intent) { return mBinder; } private final IBookManager.Stub mBinder = new IBookManager.Stub() { @Override public List<Book> getAllBook() throws RemoteException { return mBooks; } @Override public void addBook(Book book) throws RemoteException { if(book!=null){ mBooks.add(book); } } }; }
5.在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类的参数值。
另外,要设置service的process属性为":remote"
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="testaidl.x.com.testaidl" > <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > <!--<activity android:name=".MainActivity" >--> <!--<intent-filter>--> <!--<action android:name="android.intent.action.MAIN" />--> <!--<category android:name="android.intent.category.LAUNCHER" />--> <!--</intent-filter>--> <!--</activity>--> <service android:name=".aidl.RemoteService" android:process=":remote"> <intent-filter> <action android:name="testaidl.x.com.testaidl.aidl.RemoteService"/> </intent-filter> </service> </application> </manifest>
客户端
1.(Android Studio) 在src/main/下 建立 aidl 包和(与服务端包名一致)JavaBean相同目录的包,并将JavaBean和 JavaBean、服务的AIDL文件全部复制(与服务端包名一致)
2.建立Activity界面-->MainActivity.java
package testaidl.x.com.testaidl.aidl; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import testaidl.x.com.testaidl.R; public class MainActivity extends AppCompatActivity { private ListView mListView; private EditText mEditText; private List<Book> mBooks = new ArrayList<>(); private IBookManager mService; private static boolean mIsRemoteBound = false; private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = IBookManager.Stub.asInterface(service); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) findViewById(R.id.list); mEditText = (EditText) findViewById(R.id.input_name); if(mIsRemoteBound){ unbindService(conn); }else{ Intent intent=new Intent("testaidl.x.com.testaidl.aidl.RemoteService");//这里的action应与服务端的Service的<action>名称相同 bindService(intent, conn, BIND_AUTO_CREATE); } mIsRemoteBound = !mIsRemoteBound; } static int id = 0; public void addBook(View v) { String name = mEditText.getText().toString(); if(name.equals("")){ Toast.makeText(getApplicationContext(),"名字不能为空",Toast.LENGTH_SHORT).show(); }else{ Book book = new Book(id++,name); try { mService.addBook(book); Toast.makeText(getApplicationContext(),"添加书籍成功",Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); Toast.makeText(getApplicationContext(),"添加书籍失败:" + e.toString(),Toast.LENGTH_SHORT).show(); } } } public void getBooks(View v){ try { mBooks = mService.getAllBook(); } catch (RemoteException e) { e.printStackTrace(); } mListView.setAdapter(new MBookAdapter(getApplicationContext(),mBooks,R.layout.item_book)); } class MBookAdapter extends CommonAdapter<Book> { public MBookAdapter(Context context, List<Book> mDatas, int itemLayoutId) { super(context, mDatas, itemLayoutId); } @Override public void convert(ViewHolder helper, Book item, int position) { helper.setText(R.id.book_id,item.id + ""); helper.setText(R.id.book_name,item.name + ""); } } }
让蔷薇开出一种结果~