一个AIDL的例子

昨天学习aidl的时候写了个例子,中间遇到一些问题,比如客户端怎么也绑定不了服务端,后面发现是服务端的服务没有起来。这里分享一下,遇到问题的可以参考一下。
代码下载地址:http://download.csdn.net/detail/crazyman2010/9635323
这个例子有两个应用,一个叫ServiceA作为服务端,一个叫ClientB作为客户端。

服务端

1.设计服务端要提供的接口:

List<Book> getBookList(); //返回当前书藉列表
void addBook(Book book); //增加一本书

2.定义接口需要的参数类型

根据接口,定义可以进行IPC的Book类(需要继承Parcelable接口),注意它需要放到ServiceA的src目录下,不然无法编译,内容如下:

package com.heyy.example.servicea;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by mo on 16-9-19.
 */
public class Book implements Parcelable {
    public int id;
    public String name;

    public Book(int id, String name) {
        this.id = id;
        this.name = name;
    }

    protected Book(Parcel in) {
        id = in.readInt();
        name = in.readString();
    }

    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];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
    }
}

3.定义接口AIDL和参数AIDL文件

建立接口AIDL文件IBookManager.aidl:

package com.heyy.example.servicea;
import com.heyy.example.servicea.Book;
interface IBookManager {
    List<Book> getBookList();
    void addBook(in Book book);
}

为参数Book类建立Book.aidl文件:

package com.heyy.example.servicea;
parcelable Book;

4.导出远程服务接口

编译一下,会生成app/build/generated/source/aidl/debug/com/heyy/example/servicea/IBookManager.java文件,这个文件中有Stub类。
新建一个服务BookManagerService:

package com.heyy.example.servicea;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class BookManagerService extends Service {
    private CopyOnWriteArrayList<Book> mBookList;

    public BookManagerService() {
        mBookList = new CopyOnWriteArrayList<>();
        mBookList.add(new Book(1, "book1"));
        mBookList.add(new Book(2, "book2"));
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("aidl","service a bind!");
        return mBinder;
    }

    private Binder mBinder = new IBookManager.Stub() {

        @Override
        public List<Book> getBookList() throws RemoteException {
            return mBookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            mBookList.add(book);
        }
    };
}

然后在AndroidManifest.xml中添加ACTION过滤器,以供客户端远程绑定到此服务:

<service
    android:name="com.heyy.example.servicea.BookManagerService"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="com.heyy.example.servicea.BookManager" />
    </intent-filter>
</service>

最后,别忘记启动时要启动此服务,因为在客户端是没法启动服务的:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    startService(new Intent(this, BookManagerService.class));
}

服务端目录结构图:
这里写图片描述

客户端

1.复制服务端所有的.aidl文件和参数类到src目录,并保持包名和目录不变。

2.实现ServiceConnection

private ServiceConnection mServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        IBookManager bookManager = IBookManager.Stub.asInterface(service);
        try {
            List<Book> books = bookManager.getBookList();
            Log.i(TAG, "get books:" + books.toString());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
};

3.绑定到远程服务

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Intent intent = new Intent();
    intent.setAction("com.heyy.example.servicea.BookManager");
    Intent explicitIntent = createExplicitFromImplicitIntent(this, intent);
    boolean bindResult = bindService(explicitIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
    Log.i(TAG, "bind result:" + bindResult);
}

public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) {
    // Retrieve all services that can match the given intent
    PackageManager pm = context.getPackageManager();
    List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);

    // Make sure only one match was found
    if (resolveInfo == null || resolveInfo.size() != 1) {
        return null;
    }

    // Get component info and create ComponentName
    ResolveInfo serviceInfo = resolveInfo.get(0);
    String packageName = serviceInfo.serviceInfo.packageName;
    String className = serviceInfo.serviceInfo.name;
    ComponentName component = new ComponentName(packageName, className);

    // Create a new intent. Use the old one for extras and such reuse
    Intent explicitIntent = new Intent(implicitIntent);

    // Set the component to be explicit
    explicitIntent.setComponent(component);

    return explicitIntent;
}

客户端目录结构:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值