我将AndroidAIDL的学习知识总结一下和大家共享
在Android开发中,AIDL主要是用来跨进程访问。
Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信,一般是和Service服务组件一起使用来实现。
1、创建调用AIDL服务
建立AIDL服务的步骤:
第一步:在Eclipse的Android工程的Java源文件目录中建立一个扩展名为aidl的文件,改文件的语法类似于Java代码,但稍有不同。
第二步:如果aidl文件的内容是正确的,ADT会在gen目录下自动生成一个Java接口文件。
第三步:建立一个服务类(Service的子类)。
第四步:实现有aidl文件生成的Java接口。
第五步:在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签中android:name的属性值就是客户端要引用该服务的ID,也就是Intent类构造方法的参数值。
下面实现了一个实例:
IMyService.aidl:(其实和Java类定义接口文件形式上有些类似)
package mobile.android.aidl; interface IMyService { String getValue(); }
实现的MyService.java类:
package mobile.android.aidl; import mobile.android.aidl.IMyService; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; public class MyService extends Service { public class MyServiceImpl extends IMyService.Stub { @Override public String getValue() throws RemoteException { // TODO Auto-generated method stub return "《Android深度探索(卷1):HAL与驱动开发》"; } } @Override public IBinder onBind(Intent intent) { return new MyServiceImpl(); } }
在AndroidManifest.xml的配置:
<service android:name=".MyService" > <span style="white-space:pre"> </span><intent-filter> <action android:name="mobile.android.aidl.IMyService" /> <!--访问的ID--> </intent-filter> </service>
客户端代码:
package mobile.android.aidlclient; import mobile.android.aidl.IMyService; import android.app.Activity; 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.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class Main extends Activity implements OnClickListener { private IMyService myService = null; private Button btnInvokeAIDLService; private Button btnBindAIDLService; private TextView textView; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myService = IMyService.Stub.asInterface(service); //获取服务对象 btnInvokeAIDLService.setEnabled(true); } @Override public void onServiceDisconnected(ComponentName name) { Toast.makeText(Main.this, "无法连接", Toast.LENGTH_SHORT).show(); btnInvokeAIDLService.setEnabled(true); } }; @Override public void onClick(View view) { switch (view.getId()) { case R.id.btnBindAIDLService:
<span style="white-space:pre"> </span>//绑定AIDL服务 if(!bindService(new Intent("mobile.android.aidl.IMyService"), serviceConnection, Context.BIND_AUTO_CREATE)) Toast.makeText(Main.this, "无法连接", Toast.LENGTH_SHORT).show(); break; case R.id.btnInvokeAIDLService: try { textView.setText(myService.getValue()); } catch (Exception e) { textView.setText(e.getMessage()); } break; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnInvokeAIDLService = (Button) findViewById(R.id.btnInvokeAIDLService); btnBindAIDLService = (Button) findViewById(R.id.btnBindAIDLService); btnInvokeAIDLService.setEnabled(false); textView = (TextView) findViewById(R.id.textview); btnInvokeAIDLService.setOnClickListener(this); btnBindAIDLService.setOnClickListener(this); } }
注意几点:
1、使用bindService方法绑定AIDL服务。其中需要使用Intent对象指定AIDL服务的ID,也就是声明服务时<action>标签中android:name的值。
2、在绑定时需要一个ServiceConnection对象。创建ServiceConnection对象的过程中如果绑定成功,系统会调用ServiceConnection.OnServiceConnected方法,
通过该方法的service参数值可获得AIDL服务对象。
2、传递复杂的数据的AIDL服务(自定义类型的数据)
首先,了解一下AIDL服务只支持有限的数据类型,因此,如果用AIDL服务传递一些复杂的数据就需要做更一步处理。
AIDL的支持数据类型如下:
1、Java的简单类型(int 、char、boolean),不需要Import导入。
2、String和CharSequence。不需要Import导入。
3、List和map。但是要注意,List和Map对象元素类型必须是AIDL服务支持的数据类型。不需要Import导入。
4、AIDL自动生成的接口。需要import导入。l
5、实现android.os.Parcelable接口的类。需要import导入。
在传递不需要Import导入的和上面说的一样,传递需要import导入的(实现android.os.Parcelable接口的类)。除了建立一个实现android.os.Parcelable的类
还要为这个类单独建立一个aidl文件,并使用Parcelable关键字进行定义。
看这个实例:
在AndroidManifest.xml的注册配置:
<service android:name=".MyService" > <intent-filter> <action android:name="mobile.android.complex.type.aidl.IMyService" /> </intent-filter> </service>
IMyService.aidl:
package mobile.android.complex.type.aidl; import mobile.android.complex.type.aidl.Product; interface IMyService { Map getMap(in String country, in Product product); Product getProduct(); }
Product.java类:
package mobile.android.complex.type.aidl; import android.os.Parcel; import android.os.Parcelable; public class Product implements Parcelable { private int id; private String name; private float price; public static final Parcelable.Creator<Product> CREATOR = new Parcelable.Creator<Product>() { public Product createFromParcel(Parcel in) { return new Product(in); } public Product[] newArray(int size) { return new Product[size]; } }; public Product() { } private Product(Parcel in) { readFromParcel(in); } @Override public int describeContents() { // TODO Auto-generated method stub return 0; } public void readFromParcel(Parcel in) { id = in.readInt(); name = in.readString(); price = in.readFloat(); } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(id); dest.writeString(name); dest.writeFloat(price); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } }
Product.aidl:(主要是在aidl中声明上面那个自定义的类型,才能在IMyService中使用)
parcelable Product;
MyService.java类:
package mobile.android.complex.type.aidl; import java.util.HashMap; import java.util.Map; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; public class MyService extends Service { public class MyServiceImpl extends IMyService.Stub { @Override public Product getProduct() throws RemoteException { Product product = new Product(); product.setId(1234); product.setName("汽车"); product.setPrice(31000); return product; } @Override public Map getMap(String country, Product product) throws RemoteException { Map map = new HashMap<String, String>(); map.put("country", country); map.put("id", product.getId()); map.put("name", product.getName()); map.put("price", product.getPrice()); map.put("product", product); return map; } } @Override public IBinder onBind(Intent intent) { return new MyServiceImpl(); } }
在客户端实现AIDL服务:
package mobile.android.complex.type.aidlclient; import mobile.android.complex.type.aidl.IMyService; import android.app.Activity; 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.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class Main extends Activity implements OnClickListener { private IMyService myService = null; private Button btnInvokeAIDLService; private Button btnBindAIDLService; private TextView textView; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myService = IMyService.Stub.asInterface(service); btnInvokeAIDLService.setEnabled(true); } @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } }; @Override public void onClick(View view) { switch (view.getId()) { case R.id.btnBindAIDLService: bindService(new Intent("mobile.android.complex.type.aidl.IMyService"), serviceConnection, Context.BIND_AUTO_CREATE); break; case R.id.btnInvokeAIDLService: try { String s = ""; s = "Product.id = " + myService.getProduct().getId() + "\n"; s += "Product.name = " + myService.getProduct().getName() + "\n"; s += "Product.price = " + myService.getProduct().getPrice() + "\n"; s += myService.getMap("China", myService.getProduct()).toString(); textView.setText(s); } catch (Exception e) { } break; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnInvokeAIDLService = (Button) findViewById(R.id.btnInvokeAIDLService); btnBindAIDLService = (Button) findViewById(R.id.btnBindAIDLService); btnInvokeAIDLService.setEnabled(false); textView = (TextView) findViewById(R.id.textview); btnInvokeAIDLService.setOnClickListener(this); btnBindAIDLService.setOnClickListener(this); } }
这边在实现一个扩展的:AIDL与来去电自动挂断
虽然可以同Activity Action来拨打电话,但是使用常规的方法无法挂断电话。不过使用Java反射技术是实现一种通过程序挂断电话的方法。
在Android SDK源生提供了如下接口:
com,android.internal,telephony.ITelephony,外部无法直接访问,这个接口提供了一个ITelephony.endCall的方法:
尽管不能直接访问ITelephony对象。不过在TelephonyManager类提供一个getITelepgony的方法可以返回一个ITelephony的对象。不过这个方法是私有的,但
我们可以通过Java的反射技术来调用该方法。在利用getITelephony获得ITelephony对象之前,先将Android SDK 目录下找到NeighboringCellInfo.aidl和ITelephony.aidl文件
复制到你的工程目录下。
ADT会根据ITelephony.aidl文件自动生成ITelephony.java文件。
下面是一个广播接收来电是先自动挂断指定电话的来电:
package mobile.android.call.aidl; import java.lang.reflect.Method; import com.android.internal.telephony.ITelephony; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.telephony.TelephonyManager; import android.widget.Toast; public class InCallReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { TelephonyManager tm = (TelephonyManager) context .getSystemService(Service.TELEPHONY_SERVICE); switch (tm.getCallState()) { case TelephonyManager.CALL_STATE_RINGING: // 响铃 // 获得来电的电话号 String incomingNumber = intent .getStringExtra("incoming_number"); if ("12345678".equals(incomingNumber)) { try { TelephonyManager telephonyManager = (TelephonyManager) context .getSystemService(Service.TELEPHONY_SERVICE); Class<TelephonyManager> telephonyManagerClass = TelephonyManager.class; Method telephonyMethod = telephonyManagerClass .getDeclaredMethod("getITelephony", (Class[]) null); telephonyMethod.setAccessible(true); ITelephony telephony = (com.android.internal.telephony.ITelephony) telephonyMethod .invoke(telephonyManager, (Object[]) null); telephony.endCall(); } catch (Exception e) { Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show(); } } break; } } }
以上是对AIDL服务的理解总结,希望对大家有用,欢迎共同学习和指导。
版权声明:本文为博主原创文章,未经博主允许不得转载。