Android网络课程笔记-----AIDL

AIDL:Android接口定义语言Android Interface Definition Language (AIDL)
官方文档链接:http://developer.android.com/guide/components/aidl.html

一. 使用AIDL的步骤:
1. 新建一个interface,声明Activity需要调用Service的方法
2. 修改接口文件的扩展名为“.aidl”,点击项目,按F5刷新
3. 拷贝aidl文件到客户端项目中,
    注意:aidl所在报名必须完全一致
4. Service中的Binder继承aidl文件名.Stub
5. 在Activity中的onServiceConnected()方法中,
    mMService = IMyService.Stub.asInterface(service);
实现了Activity所在进程对Service所在进程的方法调用

二. Activity进程调用Service进程,获取任意类型返回值
1. 自定义类型,实现Parcelable接口
    提示:参照Parcelable的doc
2. 创建一个与自定义类型同名的aidl文件,
    内容:parcelable 自定义类型类名

在aidl接口中就可以使用这个类型了
注意:即使在同一个包中,也要导入
         import com.yuchen.aidl.Student;

下面提供一个复合型的AIDL实例

首先考虑Service模块
 
有两个.aidl文件
package com.aidl.service;

    parcelable Person;
package com.aidl.service;

   import com.aidl.service.Person;

   interface IStockQuoteService
   {
        String getQuote(in String ticker, in Person requester);
   }
然后是.aidl文件的实现类
public class Person implements Parcelable {

    private int age;
    private String name;
    
    public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() {
        
        @Override
        public Person[] newArray(int size) {
            // TODO Auto-generated method stub
            return new Person[size];
        }
        
        @Override
        public Person createFromParcel(Parcel source) {
            // TODO Auto-generated method stub
            return new Person(source);
        }
    };
    
    public Person(){
        
    }
    
    public Person(Parcel in){
        readFromParcel(in);
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        // TODO Auto-generated method stub
        out.writeInt(age);
        out.writeString(name);
    }
    
    public void readFromParcel(Parcel in) {
        // TODO Auto-generated method stub
        age = in.readInt();
        name = in.readString();
    }

}
public class StockQuoteService extends Service {

    private NotificationManager notificationManager;
    
    public class StockQuoteServiceImpl extends IStockQuoteService.Stub{

        @Override
        public String getQuote(String ticker, Person requester) throws RemoteException {
            // TODO Auto-generated method stub
            return "Hello" + requester.getName() + "! Quote for " + ticker + "is 20.0";
        }
        
    }

    @Override
    public void onCreate(){
        super.onCreate();
        notificationManager = (NotificationManager)this.getSystemService(NOTIFICATION_SERVICE);
        displayNotificationMessage("onCreate() called in StockQuoteService");
    }
    
    @SuppressWarnings("deprecation")
    private void displayNotificationMessage(String message) {
        // TODO Auto-generated method stub
        Notification notification = new Notification(R.drawable.emo_im_winking,message,System.currentTimeMillis());
        PendingIntent contentIntent = PendingIntent.getActivity(this,0,new Intent(this,MainActivity.class),0);
        notification.setLatestEventInfo(this, "StockQuoteService", message, contentIntent);
        notification.flags = Notification.FLAG_NO_CLEAR;
        notificationManager.notify(R.id.app_notification_id, notification);
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        displayNotificationMessage("onDestroy() called in StockQuoteService");
        notificationManager.cancelAll();
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        displayNotificationMessage("onBind() called in StockQuoteService");
        return new StockQuoteServiceImpl();
    }
}

配置文件

<service android:name="com.aidl.service.StockQuoteService" >
            <intent-filter>
                <action android:name="com.aidl.service.IStockQuoteService" />
            </intent-filter>
  </service>
然后就是Client模块
注意:在Client模块中,必须把在Service模块中的.aidl文件以及JavaBean类连包结构一起移到Client代码中

然后就是视图的实现了

public class MainActivity extends Activity {

    private static final String TAG = "StockQuoteClient";
    private IStockQuoteService stockService = null;
    private ToggleButton bindBtn;
    private Button callBtn;

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

        bindBtn = (ToggleButton) findViewById(R.id.bindBtn);
        bindBtn.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView,
                    boolean isChecked) {
                // TODO Auto-generated method stub
                if (isChecked) {
                    bindService(new Intent(IStockQuoteService.class.getName()),
                            serConn, Context.BIND_AUTO_CREATE);
                } else {
                    unbindService(serConn);
                }
                callBtn.setEnabled(isChecked);
                bindBtn.setChecked(isChecked);
            }

        });
        callBtn = (Button) findViewById(R.id.callBtn);
        callBtn.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                callService();
            }
        });
    }

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

    private void callService() {
            try {
                Person person = new Person();
                person.setAge(22);
                person.setName("VIJAY");
                String response = stockService.getQuote("ANDROID",person);
                Toast.makeText(this, "Value from service is "+response, Toast.LENGTH_SHORT).show();
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }

    private ServiceConnection serConn = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            Log.e(TAG, "onServiceDisconnected() called");
            bindBtn.setChecked(false);
            callBtn.setEnabled(false);
            stockService = null;
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            Log.e(TAG, "onServiceConnected() called");
            stockService = IStockQuoteService.Stub.asInterface(service);
            bindBtn.setChecked(true);
            callBtn.setEnabled(true);
        }
    };

    @Override
    protected void onDestroy() {
        Log.e(TAG, "onDestroy() called");
        if(callBtn.isEnabled())
            unbindService(serConn);
        super.onDestroy();
    }

}

这里介绍一下AIDL对非原句类型的支持

1、AIDL支持String和CharSequence

2、AIDL支持传递其他AIDL接口,但你引用的每个AIDL接口都需要一个Import语句

3、AIDL支持传递实现android.os.Parcelable接口的复杂类型。需要在AIDL文件中包含针对这些类型的import语句

4、AIDL支持java.util.List和java.util.Map,但具有一些限制。集合中的允许数据类型有Java原句、String、CharSequence以及android.os.Parcelable。无需为List或Map提供import语句,但需要为Parcelable提供import语句

5、除字符串外,非原句类型需要一个方向指示符。方向指示符包括in、out和inout

原文地址:https://www.cnblogs.com/vijay/p/3535932.html