Android AIDL <1>

本篇文章主要是讲述aidl接口被其他APP使用的情况,当然顺便也给出了所在aidl的APP的使用.

开发AIDL步骤:

<1> : 首先AIDL接口里面的方法是在Android 组件Service中实现的,首先新建Android工程,让后新建一个包,用于放AIDL的文件,

在这个包下面,新建一个aidl的文件"aidluse.aidl",不要忘记扩展名,文件名将会是AIDL接口的接口名称,具体内容如下:

package service;
interface aidluse{
void show(String s);
String getInfor();
}

文件的写法与java接口写法差不多,但是不能够有public之类的关键词,一般的数据类型如int,String,long不需要引入对应的java包,但是如果要使用parcel对象,就需要引入它对应的包,基本接口可以大致这么做:

package aidl文件所在的包名(全路径包名);

import java.io.InputStream;(加入说下面要用到InputStream,那么导入对应的java包)

interface aidl文件的文件名{

/*接口里面的方法,只要不加public/private/protected基本上不会有什么问题*/

/*下面可以给出一个事例写法*/

int getId();

}

AIDL文件如果没有错误,那么eclipse将会在gen下自动产生一个aidluse.java的文件.
<2> : AIDL接口一般在android组件Service中实现其具体方法,由于其本身对应实例aidl.stud是一个IBinder对象,那么在使用时通过链接时获得这个IBinder对象就可以调用aidl的方法了.

可以这样来搞,首先新建一个继承Service的类,然后在这个类中实现aidl接口中的方法:

// remote binder
    //AIDL接口中的具体方法实现
    public final aidluse.Stub mRemoteBinder = new aidluse.Stub() {

        @Override
        public void show(String s) throws RemoteException {
            // TODO Auto-generated method stub
            Log.i(TAG, "you have already call aidl show function !");

        }

        @Override
        public String getInfor() throws RemoteException {
            // TODO Auto-generated method stub
            return "get information successfully !".toString();
        }
    };

实现了这个AIDL接口,那么就需要返回这个aidluse.Stud对象,要返回这个对象,是通过Service类重载下来的这个方法实现的,当Service一旦被绑定时,这个立刻将会返回这个IBinder,即将调用下面的方法:

public IBinder onBind(Intent arg0){

return yourbinderobject;

}

具体应用中是这么写的:

@Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        String aidlname = arg0.getAction();
        Log.i(TAG, "name : " + aidlname);
        Toast.makeText(aidlService.this, "name : "+aidlname, Toast.LENGTH_SHORT).show();
        // if (aidlname.toString().equalsIgnoreCase("")) {
        return mRemoteBinder;
        // } else if (aidlname.toString().equalsIgnoreCase("")) {
        // return mLocalBinder;
        // }

    }

其中里面的if被注释掉了,如果不被注释掉的话,它就相当于过滤或者选择调用返回IBinder对象了,但是要注意这个aidlname,这个对象是否有值,实际上要看BindService(...)中第一个参数new Intent(...)参数的写法,比如说,如果是如下写法:

new Intent(context,aidlService.class)

如果是上面的作为参数传递给BindService方法,那么aidlname=null;那就Service中的if语句就区分不出来了,那么要怎么写呢?可以这样:

new Intent("service.aidlService");

这样的写的话,aidlname="service.aidlService",但是这两种写法实际上发挥的作用可能存在差异.

具有筛选功能,即意味着可以在一个Service实现多个aidl的接口.
OK,下面给出整个aidlService类的source code:

package service;

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 android.widget.Toast;

public class aidlService extends Service {

    private static final String TAG = "aidlService";

    private IBinder mLocalBinder = new LocalBinder();

    //放回绑定了AIDL的IBinder对象
    //应用中获得这个绑定了实现AIDL接口类的IBinder对象
    //就可以调用AIDL里面的方法了
    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        String aidlname = arg0.getAction();
        Log.i(TAG, "name : " + aidlname);
        Toast.makeText(aidlService.this, "name : "+aidlname, Toast.LENGTH_SHORT).show();
        // if (aidlname.toString().equalsIgnoreCase("")) {
        return mRemoteBinder;
        // } else if (aidlname.toString().equalsIgnoreCase("")) {
        // return mLocalBinder;
        // }

    }

    // local binder
    //这里可返回本地service里面的方法
    //被其他方法调用时
    class LocalBinder extends Binder {
        aidlService localService() {
            return aidlService.this;
        }
    }

    // remote binder
    //AIDL接口中的具体方法实现
    public final aidluse.Stub mRemoteBinder = new aidluse.Stub() {

        @Override
        public void show(String s) throws RemoteException {
            // TODO Auto-generated method stub
            Log.i(TAG, "you have already call aidl show function !");

        }

        @Override
        public String getInfor() throws RemoteException {
            // TODO Auto-generated method stub
            return "get information successfully !".toString();
        }
    };

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
    }

    @Override
    public void onStart(Intent intent, int startId) {
        // TODO Auto-generated method stub
        super.onStart(intent, startId);
    }

}
View Code

<3>  如何被调用,首先要声明一个aidluse接口的对象:

private aidluse mService;

<4> 然后连接实现aidl的Service上面:

private ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName arg0, IBinder arg1) {
            // TODO Auto-generated method stub
            mService = aidluse.Stub.asInterface(arg1);

        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            // TODO Auto-generated method stub
            if(mService!=null){
                mService=null;
            }
        }

    };

<5> 要想在Activity中使用,还需要绑定这个连接(可以在onCreate(),onResume()中进行),如果Activity结束),也要接解绑定这个连接(可以在finish(),destroy(),也可以stop()中),具体绑定和解绑如下:

this.bindService(new Intent(this, aidlService.class), connection,
                Context.BIND_AUTO_CREATE);

这样的写法,aidlname=null,所以去掉了if筛选功能.
解绑如下:

this.unbindService(connection);

整个代码如下:

package com.example.androidaidlsdemo;

import service.aidlService;
import service.aidluse;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

    private aidluse mService;
    
    private Button mShowBtn;

    private ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName arg0, IBinder arg1) {
            // TODO Auto-generated method stub
            mService = aidluse.Stub.asInterface(arg1);

        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            // TODO Auto-generated method stub
            if(mService!=null){
                mService=null;
            }
        }

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        this.bindService(new Intent(this, aidlService.class), connection,
                Context.BIND_AUTO_CREATE);
        
        mShowBtn=(Button)findViewById(R.id.show);
        mShowBtn.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                try {
                    mService.show("you are right !");
                    Toast.makeText(MainActivity.this, mService.getInfor(), Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            
        });

    }

    @Override
    public void finish() {
        // TODO Auto-generated method stub
        super.finish();

        this.unbindService(connection);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}
View Code

 

<6> 运行之前,由于Service也是Android的四大组件之一,所以需要在AndroidManifest.xml进行配置:

<service
            android:name="service.aidlService"
            android:exported="true" >
            <intent-filter>
                <action android:name="service.aidlService" >
                </action>
            </intent-filter>
        </service>

如果没有特别的要求,就相当于写Activity的是一样的.


<7> 上面瞎扯了那么多,都不是这篇文章的重点,重点是如何让其他APP调用这个AIDL接口.上面全部是铺垫.

要想调用,那么新建一个android工程后,第一件事就是讲前面那个APP的service包和包下的文件拷贝放到新建工程中,由于上面的那个

service包包含了aidl文件盒继承Service的类文件,那么拷贝以后,那个继承Service的java文件不是我们需要的,就要删掉,删掉以后,刷新工程,

如果不出意外,工程下的gen目录下会自动产生aidluse.java的文件.

<8> 进行完上面一个步骤,即可以直接使用了,当然在运行之前,需要先运行前面个APP,让其将service服务启动起来.

具体操作和前面APP差不多:

package com.example.androidaidldemo;

import service.aidluse;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity {

    
    private aidluse mService;
    
    private Button mButton;
    
    private ServiceConnection connection=new ServiceConnection(){

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            mService=aidluse.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            if(mService!=null){
                mService=null;
            }
        }
        
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        this.bindService(new Intent("service.aidlService"), connection, Context.BIND_AUTO_CREATE);
        
        mButton=(Button)findViewById(R.id.button1);
        mButton.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                try {
                    Toast.makeText(MainActivity.this, mService.getInfor(), Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            
        });
        
    }

    
    
    @Override
    public void finish() {
        // TODO Auto-generated method stub
        super.finish();
        
        this.unbindService(connection);
    }



    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}
View Code

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2014-03-27 19:38  MMLoveMeMM  阅读(303)  评论(0)    收藏  举报