当前位置: 代码迷 >> Android >> Android札记三十四.Service综合实例二
  详细解决方案

Android札记三十四.Service综合实例二

热度:83   发布时间:2016-04-28 00:34:23.0
Android笔记三十四.Service综合实例二
综合实例2:客户端访问远程Service服务
实现:通过一个按钮来获取远程Service的状态,并显示在两个文本框中。
思路:假设A应用需要与B应用进行通信,调用B应用中的getName()、getAuthor()方法,B应用以Service方式向A应用提供服务。所以,我们可以将A应用看成是客户端,B应用为服务端,分别命名为AILDClient、AILDServer.
一、服务端应用程序
1.src/com.example.aildserver/song.aidlAILD文件
    当完成aidl文件创建后,选择保存,eclipse会自动在项目的gen目录中同步生成Song.java接口文件。接口文件中生成一个Stub抽象类,里面包括aidl定义的方法,还包括一些其它辅助性的方法,如geName()、getSong()方法,我们可以通过这两个方法实现客户端读写Service服务端数据
  1.     package com.example.aildserver;  
  2.     interface Song  
  3.     {  
  4.          String getName();  
  5.          String getSong();  
  6.     } 
位置如下:

    编写Aidl文件时,需要注意:      
    1.接口名和aidl文件名相同;    
    2.接口和方法前不用加访问权限修饰符public,private等,也不能用final,static;    
    3.Aidl默认支持的类型包话java基本类型(int、long、boolean等)和(String、List、Map、CharSequence),使用这些类型时不需要import声明。对于List和Map中的元素类型必须是Aidl支持的类型。如果使用自定义类型作为参数或返回值,自定义类型必须实现Parcelable接口。    
    4.自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中。            
    5.在aidl文件中所有非Java基本类型参数必须加上in、out、inout标记,以指明参数是输入参数、输出参数还是输入输出参数。   
     6.Java原始类型默认的标记为in,不能为其它标记。 
2.src/com.example.aildserver/MyService.java
功能:Service子类,完成Service服务
开发核心步骤:
    (1)重写Service的onBind()方法(用于返回一个IBinder对象)、onCreate()方法、onDestroy() 方法、onUnbind()方法;
    (2)定义一个Stub的子类,该内部类实现了IBinder、Song两个接口,该子类对象将作为远程Service的onBind()方法返回IBinder对象的代理传给客户端的ServiceConnection的onServiceConnected方法的第二个参数。
  1. package com.example.aildserver;  
  2. import com.example.aildserver.Song.Stub;  
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.Binder;  
  6. import android.os.IBinder;  
  7. import android.os.RemoteException;  
  8. public class MyService extends Service {  
  9.  private String[] names = new String[] {"林俊杰","蔡依林","邓紫棋"};  
  10.  private String[] songs = new String[] {"可惜没如果","第三人称","多远都要在一起"};  
  11.  private String name,song;  
  12.  private int current=1;  //当前位置  
  13.  private MyBinder binder = new MyBinder();  //实例化一个IBinder对象  
  14.  /*0.Stub内部类 
  15.   * 该内部类实现了IBinder、Song两个接口,这个Stub类将会作为远程Service的回调类。*/  
  16.  public class MyBinder extends Stub  
  17.  {  
  18.   //a.客户端回调该方法获取歌手名  
  19.   public String getName() throws RemoteException  
  20.   {  
  21.    return name;  
  22.   }  
  23.   //b.客户端回调该方法获取歌曲  
  24.   public String getSong() throws RemoteException  
  25.   {  
  26.    return song;  
  27.   }  
  28.    
  29.  }  
  30.  /*1.onBind方法 
  31.   * service用于返回一个IBinder对象给客户端方便通信 
  32.  */  
  33.  @Override  
  34.  public IBinder onBind(Intent arg0) {  
  35.   return binder;  
  36.  }  
  37.  /*2.onCreate方法 
  38.   * 当Service启动后,自动调用该方法,用于初始化 
  39.   * */  
  40.  public void onCreate() {  
  41.   name = names[current];     //给name、song赋值  
  42.   song = songs[current];  
  43.   System.out.println("Service print:name="+name+"song="+song);  
  44.   super.onCreate();  
  45.  }  
  46.  /*3.onDestroy方法 
  47.   * 当访问者调用Context.stopService方法后,调用该方法关闭Service服务 
  48.   * */  
  49.  public void onDestroy() {  
  50.   super.onDestroy();  
  51.  }  
  52.  /*4.onUnbind方法 
  53.   * 当访问者调调用Context.unBind()方法后,调用该方法与Service解除绑定*/  
  54.  public boolean onUnbind(Intent intent) {  
  55.   return false;  
  56.  }  
  57.    
  58.  
注意1:客户端访问Service时,Android并不是直接返回Service对象给客户端,Service只是将一个回调对象(IBinder对象)通过onBind()方法回调给客户端。  
注意2:与绑定本地Service不同的是,本地Service的onBind()方法会直接把IBinder对象本身传给客户端的ServiceConnection的onServiceConnected方法的第二个参数。但远程Service的onBind()方法只是将IBinder对象的代理传给客户端的ServiceConnection的onServiceConnected方法的第二个参数。当客户端获取了远程的Service的IBinder对象的代理之后,接下来可通过该IBinder对象去回调远程Service的属性或方法。
3.AndroidManifest.xml
功能:配置Service组件,并指定其action属性(方便其他应用程序启动该Service服务)
  1.     <application  
  2.         ........  
  3.         <!-- 配置service -->  
  4.         <service android:name=".MyService">  
  5.             <intent-filter>  
  6.                     <action android:name="com.jiangdongguo.service"/>  
  7.             </intent-filter>  
  8.         </service>  
  9.     </application> 

二、客户端应用程序
1.拷贝服务端.aidl文件到客户端
    把AIDLService应用中aidl文件所在package连同aidl文件一起拷贝到客户端AIDLClient应用,eclipse会自动在A应用的gen目录中为aidl文件同步生成Song.java接口文件,接下来就可以在AIDLClient应用中实现与AIDLService应用通信。
2.src/com.example.aildclient/MainActivity.java
功能:(1)启动服务端Service服务;(2)获取返回的IBinder代理对象,并完成与服务端程序的通信
  1. package com.example.aildclient;  
  2.   
  3. import com.example.aildserver.Song;  
  4.   
  5. import android.app.Activity;  
  6. import android.app.Service;  
  7. import android.content.ComponentName;  
  8. import android.content.Intent;  
  9. import android.content.ServiceConnection;  
  10. import android.os.Bundle;  
  11. import android.os.IBinder;  
  12. import android.os.RemoteException;  
  13. import android.view.View;  
  14. import android.view.View.OnClickListener;  
  15. import android.widget.Button;  
  16. import android.widget.EditText;  
  17. public class MainActivity extends Activity {  
  18.     private Button getBtn;  
  19.     private EditText song;  
  20.     private EditText name;  
  21.     private Song binder;  
  22.     //1.创建一个ServiceConnection对象  
  23.     private ServiceConnection conn = new  ServiceConnection()  
  24.     {  
  25.   public void onServiceConnected(ComponentName name, IBinder service)  
  26.   {  
  27.    binder = Song.Stub.asInterface(service); //获取Service返回的代理IBinder对象  
  28.      
  29.   }  
  30.   public void onServiceDisconnected(ComponentName name) {  
  31.   }  
  32.     };  
  33.  protected void onCreate(Bundle savedInstanceState) {  
  34.         super.onCreate(savedInstanceState);  
  35.         setContentView(R.layout.main);  
  36.         getBtn=(Button)findViewById(R.id.get);  
  37.         song=(EditText)findViewById(R.id.song);  
  38.         name=(EditText)findViewById(R.id.name);  
  39.     //2.指定要启动的Service  
  40.         Intent intent = new Intent("com.jiangdongguo.service");  
  41.         bindService(intent, conn, Service.BIND_AUTO_CREATE);  
  42.         getBtn.setOnClickListener(new OnClickListener(){  
  43.            
  44.    public void onClick(View arg0)  
  45.    {  
  46.     try {  
  47.      name.setText(binder.getName());  
  48.      song.setText(binder.getSong());  
  49.     } catch (RemoteException e) {  
  50.      e.printStackTrace();  
  51.     }  
  52.    }  
  53.         });  
  54.     }  
  55. }  
    对于远程服务调用,远程服务返回给客户端的对象为代理对象,客户端在onServiceConnected(ComponentName name, IBinder service)方法引用该对象时不能直接强转成接口类型的实例,而应该使用asInterface(IBinder iBinder)进行类型转换。
三、效果演示


  相关解决方案