android studio使用Aidl跨进程调用服务

以前就知道其大概代码流程,但是一直没有敲代码去实现,今天将其实现了,android studio下编写也遇到了一些小细节的问题,特此记录一下。
既然是模拟Aidl通讯,那么当然要编写两个应用了,一个提供服务给另一个应用调用,那么开始吧。
一、服务提供方应用编写
①.为了更全面一些,我编写了一个自定义类Book在Aidl之中传递,不同进程间传递自定义对象必须实现Parcelable接口,Serializable是不行的哦。Book类如下:

package com.lbb.aidltest.bean;
import android.os.Parcel;
import android.os.Parcelable;
/**
 * 作者:李少波
 * 邮箱:lishaobo@seengene.com
 * 日期:16/10/20
 */
public class Book implements Parcelable{
    private String name;
    private int id;
    public Book(String name, int id) {
        this.name = name;
        this.id = id;
    }
    protected Book(Parcel in) {
        name = in.readString();
        id = in.readInt();
    }
    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];
        }
    };
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Override
    public int describeContents() {
        return 0;
    }
    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(name);
        parcel.writeInt(id);
    }
}

②.编写.Aidl文件,因为此处用到了自定义类的对象的传递,所以需要编写两类aidl文件,分别是定义服务接口的和定义自定义类的aidl文件。
a.定义服务接口。右键-new-aidl-aidl file,文件名随便定义,可以是服务的类名前边加I。就像一个接口文件一样声明对外开放的方法即可,此处需要注意的是:如果用到了自定义类,则需要显示的import进来,此处需要显示import com.lbb.aidltest.bean.Book,否则会”Execution failed for task :app:compileDebugAidl”。我的接口定义文件如下:

// IAidlInterface.aidl
package com.lbb.aidltest;
import com.lbb.aidltest.bean.Book;
interface IAidlInterface {
 Book getBookByIndex(int index);
}

b.定义需要在进程间传递的自定义类同名的.aidl文件,此处是Book.aidl。这一步不能右键创建aidl file了,因为输入Book会提示”Interface Name must be unique”,导致无法下一步。所以只能在aidl文件夹下创建和Book一样的包路径,并在路径下new-file,填入Book.aidl,手动输入文件内容如下(全程系统无任何提示输入。。汗):

package com.lbb.aidltest.bean;
parcelable Book;

③.万事俱备,创建自己的AidlService继承自Service,在onBind中返回一个.Stub自类的对象供其它app中使用,我的服务代码如下:

package com.lbb.aidltest;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import com.lbb.aidltest.bean.Book;
/**
 * 作者:李少波
 * 邮箱:lishaobo@seengene.com
 * 日期:16/10/20
 */
public class AidlService extends Service {
    IAidlInterface.Stub mStub = new IAidlInterface.Stub() {
        @Override
        public Book getBookByIndex(int index) throws RemoteException {
            Book book = null;
            if(index ==0){
                book = new Book("第一本书",0);
            }
            return book;
        }
    };
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mStub;
    }
}

至此服务供应方代码编写完毕,对了,还有一点很重要,记得在mainfest中声明服务的隐式intent-filter,因为其它app都是用隐式方式调用这个服务的:

 <service android:name=".AidlService">
<intent-filter><action android:name="com.lbb.aidltest.AidlService"></action></intent-filter>
 </service>

二、调用其它app中可以被调用的服务。此处我调用我上一个app中的服务,前提是安装了上一个app哦。。使用过程分两步:
①.带上包名拷贝上一个app中的bean和aidl文件(包括自定义类以及接口的都要),也就是使用端要和提供端的bean的包路径以及aidl的包路径是一样的,没有路径创造路径也要保证一样。
②.在Activity中愉快的引用其他app服务吧,这里是隐式调用的,如果直接隐式调用在android 5.0之后的环境下会报”只能显式启动Service”的错误,此处用了一个网上荡的方法,可以用隐式打开服务了,我是这样使用的:

public class MainActivity extends Activity {
    private IAidlInterface aidlService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final Intent intent = new Intent();
        intent.setAction("com.lbb.aidltest.AidlService");
        final Intent eintent = new Intent(createExplicitFromImplicitIntent(this,intent));
        bindService(eintent,serviceConnection, Service.BIND_AUTO_CREATE);
    }

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            aidlService = IAidlInterface.Stub.asInterface(iBinder);
            try {
                Book book = aidlService.getBookByIndex(0);
                Log.d(MainActivity.class.getSimpleName(),"book名字: "+book.getName());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(serviceConnection);
    }


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

三、小结
1.提供端接口aidl文件创建需要手动import 自定义类,自定义类的aidl需要全手工填写包名并parcelable Book;
2.使用端要拷贝提供端的bean和aidl文件,并且在android 5.0以上系统需要用以上的方式来使得隐式bindService变为显式bind。
3.aidl调用第一个应用服务,不需要启动第一个应用哦

demo下载链接:
http://download.csdn.net/detail/lishaobo211985/9659733

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值