Android服务之AIDL
在android开发过程中,为了让其他的应用程序,也可以访问本应用程序的服务,android系统采用远程过程调用来实现。android通过接口来公开定义的服务。我们将能够夸进程访问的服务成为AIDL服务(Android Interface Definition Language)。本节主要讲述通过aidl服务来传递数据。aidl支持的数据类型“简单数据类型、String和char、List和Map、aidl自动生成的接口、实现android.Parcelable的类。
1.建立aidl服务
在Eclipse中建立android_adil应用程序,在java的包目录中建立一个IMyService.aidl文件.
1 package com.example.android_demo_aidl; 2 import com.example.android_demo_aidl.Person; 3 interface IMyService 4 { 5 Map getMap(in String key,in Person person); 6 Person getPerson(); 7 }
Person是实现了parcelable接口的类,需要使用import导入。in表示该值可以在客户端设置,out表示该值可以在服务端设置,inout表示该值既可以在客户端设置,也可以再服务端设置。如果aidl正确,会自动生成IMyService.java文件。
在包中建立Person类。
1 package com.example.android_demo_aidl; 2 3 import android.os.Parcel; 4 import android.os.Parcelable; 5 6 public class Person implements Parcelable { 7 8 private int id; 9 private String name; 10 private int age; 11 public static final Parcelable.Creator<Person> CREATOR= new Parcelable.Creator<Person>() { 12 13 @Override 14 public Person[] newArray(int size) { 15 // TODO Auto-generated method stub 16 return new Person[size]; 17 } 18 19 @Override 20 public Person createFromParcel(Parcel source) { 21 // TODO Auto-generated method stub 22 return new Person(source); 23 } 24 }; 25 public Person() 26 { 27 } 28 private Person(Parcel in) 29 { 30 readFormParce(in); 31 } 32 private void readFormParce(Parcel in) { 33 // TODO Auto-generated method stub 34 id=in.readInt(); 35 name=in.readString(); 36 age=in.readInt(); 37 38 } 39 public int describeContents() 40 { 41 return 0; 42 } 43 public void writeToParcel(Parcel dest,int flags) 44 { 45 dest.writeInt(id); 46 dest.writeString(name); 47 dest.writeInt(age); 48 } 49 public int getId() 50 { 51 return id; 52 } 53 public void setId(int id) 54 { 55 this.id=id; 56 } 57 public String getName() 58 { 59 return name; 60 } 61 public void setName(String name) 62 { 63 this.name=name; 64 } 65 public int getAge() 66 { 67 return age; 68 } 69 public void setAge(int age) 70 { 71 this.age=age; 72 } 73 }
Person类定义name,age等成员变量,实现了接口parcelable。同时必须定义CREATOR的常量,类型为Parcelable.Creator。在writeToParcel中将序列化的值传入Parcel。
建立Person.aidl
parcelable Person;
编写MyService类
1 package com.example.android_demo_aidl; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import android.app.Service; 7 import android.content.Intent; 8 import android.os.IBinder; 9 import android.os.RemoteException; 10 import android.util.Log; 11 12 public class MyService extends Service { 13 14 public class MyServiceImpl extends IMyService.Stub 15 { 16 17 @Override 18 public Map getMap(String key, Person person) throws RemoteException { 19 // TODO Auto-generated method stub 20 Map map = new HashMap<String,String>(); 21 map.put("id", person.getId()); 22 map.put("age", person.getAge()); 23 map.put("name", person.getName()); 24 map.put("person", person); 25 return map; 26 } 27 28 @Override 29 public Person getPerson() throws RemoteException { 30 // TODO Auto-generated method stub 31 Person person = new Person(); 32 person.setAge(18); 33 person.setId(1); 34 person.setName("Tom"); 35 return person; 36 } 37 38 39 40 } 41 @Override 42 public IBinder onBind(Intent intent) { 43 // TODO Auto-generated method stub 44 return new MyServiceImpl(); 45 } 46 @Override 47 public void onCreate() { 48 // TODO Auto-generated method stub 49 super.onCreate(); 50 Log.d("test", "oncreate"); 51 } 52 }
在MyService类中定义一个新类MyServiceIm继承于IMyService.Stub.需要实现在接口中定义的方法。MyService类继承android.Service,在绑定方法中,返回一个实例。
最后,在AndroidManifest.xml中配置该服务。
1 <service android:name=".MyService"> 2 <intent-filter > 3 <action android:name="com.example.android_demo_aidl.IMyService"/> 4 </intent-filter> 5 </service>
android:name,在客户端通过该id调用服务。
2.调用服务
在Eclipse中建立新的android应用程序,android_ail_client。在调用服务之前,需要绑定服务,通过bindService进行服务的绑定。将服务端自动生成的IMyservice.java连同包一起复制到新的应用程序用。程序结构如下图
1 package com.example.android_demo_aidl_client; 2 3 import com.example.android_demo_aidl.IMyService; 4 5 import android.support.v7.app.ActionBarActivity; 6 import android.content.ComponentName; 7 import android.content.Context; 8 import android.content.Intent; 9 import android.content.ServiceConnection; 10 import android.os.Bundle; 11 import android.os.IBinder; 12 import android.util.Log; 13 import android.view.Menu; 14 import android.view.MenuItem; 15 import android.view.View; 16 import android.view.View.OnClickListener; 17 import android.widget.Button; 18 import android.widget.TextView; 19 20 public class MainActivity extends ActionBarActivity implements OnClickListener { 21 22 private Button btnstart; 23 private Button btninvoke; 24 private IMyService myService=null; 25 private TextView textView; 26 private ServiceConnection conn=new ServiceConnection() { 27 28 @Override 29 public void onServiceDisconnected(ComponentName name) { 30 // TODO Auto-generated method stub 31 Log.d("test", "绑定错误"); 32 } 33 34 @Override 35 public void onServiceConnected(ComponentName name, IBinder service) { 36 // TODO Auto-generated method stub 37 myService=IMyService.Stub.asInterface(service); 38 btninvoke.setEnabled(true); 39 } 40 }; 41 @Override 42 protected void onCreate(Bundle savedInstanceState) { 43 super.onCreate(savedInstanceState); 44 setContentView(R.layout.activity_main); 45 btnstart=(Button)findViewById(R.id.button1); 46 btninvoke=(Button)findViewById(R.id.button2); 47 textView=(TextView)findViewById(R.id.textView1); 48 49 btninvoke.setOnClickListener(this); 50 btnstart.setOnClickListener(this); 51 } 52 53 @Override 54 public boolean onCreateOptionsMenu(Menu menu) { 55 // Inflate the menu; this adds items to the action bar if it is present. 56 getMenuInflater().inflate(R.menu.main, menu); 57 return true; 58 } 59 60 @Override 61 public boolean onOptionsItemSelected(MenuItem item) { 62 // Handle action bar item clicks here. The action bar will 63 // automatically handle clicks on the Home/Up button, so long 64 // as you specify a parent activity in AndroidManifest.xml. 65 int id = item.getItemId(); 66 if (id == R.id.action_settings) { 67 return true; 68 } 69 return super.onOptionsItemSelected(item); 70 } 71 72 @Override 73 public void onClick(View v) { 74 // TODO Auto-generated method stub 75 switch(v.getId()) 76 { 77 case R.id.button1: 78 bindService(new Intent("com.example.android_demo_aidl.IMyService"), conn, Context.BIND_AUTO_CREATE); 79 break; 80 case R.id.button2: 81 try 82 { 83 String s=""; 84 s="person.id="+myService.getPerson().getId()+"\n"; 85 s+="person.name="+myService.getPerson().getName()+"\n"; 86 s+="person.age="+myService.getPerson().getAge(); 87 textView.setText(s); 88 } 89 catch(Exception e) 90 { 91 Log.d("test",e.getMessage()); 92 } 93 break; 94 } 95 } 96 @Override 97 protected void onDestroy() { 98 // TODO Auto-generated method stub 99 super.onDestroy(); 100 unbindService(conn); 101 } 102 }
在该段代码中,通过ServiceConnection获取Aidl服务的对象实例。在调用服务之前需先绑定服务。
3.程序运行截图
运行的时候,需要先运行服务端程序,再运行客户端程序。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。