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 + "");
        }
    }
}

 

posted on 2016-07-10 19:18  xiezie  阅读(924)  评论(0编辑  收藏  举报

导航