android编写Service入门

android SDK提供了Service,用于类似*nix守护进程或者windows的服务。

Service有两种类型:

  1. 本地服务(Local Service):用于应用程序内部
  2. 远程服务(Remote Sercie):用于android系统内部的应用程序之间

      前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。

后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。

编写不需和Activity交互的本地服务示例

      本地服务编写比较简单。首先,要创建一个Service类,该类继承android的Service类。这里写了一个计数服务的类,每秒钟为计数器加一。在服务类的内部,还创建了一个线程,用于实现后台执行上述业务逻辑。

Service类:

[java] view plaincopy
  1. package com.test;  
  2.   
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.IBinder;  
  6. import android.util.Log;  
  7.   
  8. public class CountService extends Service {  
  9.     public static final String TAG = "CountService";  
  10.     private boolean threadDisable;  
  11.     private int count ;  
  12.       
  13.     @Override  
  14.     public IBinder onBind(Intent intent) {  
  15.         // TODO Auto-generated method stub  
  16.         return null;  
  17.     }  
  18.   
  19.     @Override  
  20.     public void onCreate() {  
  21.         // TODO Auto-generated method stub  
  22.         super.onCreate();  
  23.         new Thread(new Runnable(){  
  24.             @Override  
  25.             public void run() {  
  26.                 // TODO Auto-generated method stub  
  27.                 while(!threadDisable){  
  28.                     try {  
  29.                         Thread.sleep(1000);  
  30.                     } catch (InterruptedException e) {  
  31.                         // TODO Auto-generated catch block  
  32.                         e.printStackTrace();  
  33.                     }  
  34.                     count++;  
  35.                     Log.v(TAG , "Count="+count);  
  36.                 }  
  37.             }  
  38.         }).start();  
  39.     }  
  40.   
  41.     @Override  
  42.     public void onDestroy() {  
  43.         // TODO Auto-generated method stub  
  44.         super.onDestroy();  
  45.         threadDisable = true;  
  46.         Log.v(TAG , "onDestroy");  
  47.     }  
  48.       
  49.     public int getCount(){  
  50.         return count;  
  51.     }  
  52.       
  53. }  
需要将该服务注册到配置文件AndroidManifest.xml中,否则无法找到:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.test"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk android:minSdkVersion="15" />  
  8.   
  9.     <application  
  10.         android:icon="@drawable/ic_launcher"  
  11.         android:label="@string/app_name" >  
  12.         <activity  
  13.             android:name=".LocalServiceDemoActivity"  
  14.             android:label="@string/app_name" >  
  15.             <intent-filter>  
  16.                 <action android:name="android.intent.action.MAIN" />  
  17.   
  18.                 <category android:name="android.intent.category.LAUNCHER" />  
  19.             </intent-filter>  
  20.         </activity>  
  21.         <span style="color:#000000;"><service android:name="CountService"/></span>  
  22.     </application>  
  23. </manifest>  
在Activity中启动和关闭本地服务:

[java] view plaincopy
  1. package com.test;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.os.Bundle;  
  6.   
  7. public class LocalServiceDemoActivity extends Activity {  
  8.     /** Called when the activity is first created. */  
  9.     @Override  
  10.     public void onCreate(Bundle savedInstanceState) {  
  11.         super.onCreate(savedInstanceState);  
  12.         setContentView(R.layout.main);  
  13.           
  14.         startService(new Intent(this , CountService.class));  
  15.     }  
  16.   
  17.     @Override  
  18.     protected void onDestroy() {  
  19.         // TODO Auto-generated method stub  
  20.         super.onDestroy();  
  21.         stopService(new Intent(this , CountService.class));  
  22.     }  
  23.       
  24. }  
可通过日志查看到后台线程打印的计数内容。

==================================================

编写本地服务和Activity交互的示例

      上面的示例是通过startService和stopService启动关闭服务的。适用于服务和activity之间没有交互调用的情况。如果之间需要传递参数或者方法调用。需要使用bind和unbind方法。

      具体做法是,服务类需要增加接口,比如ICountService,另外,服务类需要有一个内部类,这样可以方便访问外部类的封装数据,这个内部类需要继承Binder类并实现ICountService接口。还有,就是要实现Service的onBind方法,不能只传回一个null了。

这是新建立的接口代码:

[java] view plaincopy
  1. package com.test;  
  2.   
  3. public interface ICountService {  
  4.     public abstract int getCount();  
  5. }  

修改后的CountService代码:
[java] view plaincopy
  1. package com.test;  
  2.   
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.Binder;  
  6. import android.os.IBinder;  
  7. import android.util.Log;  
  8.   
  9. public class CountService extends Service {  
  10.     public static final String TAG = "CountService";  
  11.     private boolean threadDisable;  
  12.     private int count ;  
  13.       
  14.     private ServiceBinder serviceBinder = new ServiceBinder();  
  15.       
  16.     public class ServiceBinder extends Binder implements ICountService{  
  17.         @Override  
  18.         public int getCount() {  
  19.             // TODO Auto-generated method stub  
  20.             return count;  
  21.         }  
  22.     }  
  23.       
  24.     @Override  
  25.     public IBinder onBind(Intent intent) {  
  26.         // TODO Auto-generated method stub  
  27.         return serviceBinder;  
  28.     }  
  29.   
  30.     @Override  
  31.     public void onCreate() {  
  32.         // TODO Auto-generated method stub  
  33.         super.onCreate();  
  34.         new Thread(new Runnable(){  
  35.             @Override  
  36.             public void run() {  
  37.                 // TODO Auto-generated method stub  
  38.                 while(!threadDisable){  
  39.                     try {  
  40.                         Thread.sleep(1000);  
  41.                     } catch (InterruptedException e) {  
  42.                         // TODO Auto-generated catch block  
  43.                         e.printStackTrace();  
  44.                     }  
  45.                     count++;  
  46.                     Log.v(TAG , "Count="+count);  
  47.                 }  
  48.             }  
  49.         }).start();  
  50.     }  
  51.   
  52.     @Override  
  53.     public void onDestroy() {  
  54.         // TODO Auto-generated method stub  
  55.         super.onDestroy();  
  56.         threadDisable = true;  
  57.         Log.v(TAG , "onDestroy");  
  58.     }  
  59.       
  60.     public int getCount(){  
  61.         return count;  
  62.     }  
  63.       
  64. }  
服务的注册也要做改动,AndroidManifest.xml文件:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.test"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk android:minSdkVersion="15" />  
  8.   
  9.     <application  
  10.         android:icon="@drawable/ic_launcher"  
  11.         android:label="@string/app_name" >  
  12.         <activity  
  13.             android:name=".LocalServiceDemoActivity"  
  14.             android:label="@string/app_name" >  
  15.             <intent-filter>  
  16.                 <action android:name="android.intent.action.MAIN" />  
  17.                 <category android:name="android.intent.category.LAUNCHER" />  
  18.             </intent-filter>  
  19.         </activity>  
  20.         <!-- <service android:name="CountService"/> -->    
  21.         <span style="color:#000000;"><service android:name="CountService">  
  22.             <intent-filter>  
  23.                 <action android:name="com.test.CountService"  />  
  24.             </intent-filter>  
  25.         </service></span>  
  26.     </application>  
  27. </manifest>  
Acitity代码不再通过startSerivce和stopService启动关闭服务,另外,需要通过ServiceConnection的内部类实现来连接Service和Activity。

[java] view plaincopy
  1. package com.test;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.ComponentName;  
  5. import android.content.Intent;  
  6. import android.content.ServiceConnection;  
  7. import android.os.Bundle;  
  8. import android.os.IBinder;  
  9. import android.util.Log;  
  10.   
  11. public class LocalServiceDemoActivity extends Activity {  
  12.     private ICountService countService;  
  13.       
  14.     private ServiceConnection serviceConnection = new ServiceConnection(){  
  15.         @Override  
  16.         public void onServiceConnected(ComponentName name, IBinder service) {  
  17.             // TODO Auto-generated method stub  
  18.             countService = (ICountService)service;  
  19.             Log.v(CountService.TAG , "on service connected,count is:"+  
  20.             countService.getCount());  
  21.         }  
  22.         @Override  
  23.         public void onServiceDisconnected(ComponentName name) {  
  24.             // TODO Auto-generated method stub  
  25.             countService = null ;  
  26.         }  
  27.     };  
  28.       
  29.     /** Called when the activity is first created. */  
  30.     @Override  
  31.     public void onCreate(Bundle savedInstanceState) {  
  32.         super.onCreate(savedInstanceState);  
  33.         setContentView(R.layout.main);  
  34.           
  35.         //startService(new Intent(this , CountService.class));  
  36.         this.bindService(new Intent("com.test.CountService"),   
  37.                 this.serviceConnection, BIND_AUTO_CREATE);  
  38.     }  
  39.   
  40.     @Override  
  41.     protected void onDestroy() {  
  42.         // TODO Auto-generated method stub  
  43.         super.onDestroy();  
  44.         Log.v(CountService.TAG , "last onDestroy,count is:"+  
  45.                 countService.getCount());  
  46.         //stopService(new Intent(this , CountService.class));  
  47.         this.unbindService(serviceConnection);  
  48.     }  
  49.       
  50. }  

编写传递基本型数据的远程服务

上面的示例,可以扩展为,让其他应用程序复用该服务。这样的服务叫远程(remote)服务,实际上是进程间通信(RPC)。

这时需要使用android接口描述语言(AIDL)来定义远程服务的接口,而不是上述那样简单的java接口。扩展名为aidl而不是java。可用上面的ICountService改动而成ICountSerivde.aidl,eclipse会自动生成相关的java文件。

[java] view plaincopy
  1. package com.test;  
  2.   
  3. interface ICountService {  
  4.     int getCount();  
  5. }  

编写服务(Service)类,稍有差别,主要在binder是通过远程获得的,需要通过桩(Stub)来获取。桩对象是远程对象的本地代理

[java] view plaincopy
  1. package com.test;  
  2.   
  3. import android.app.Service;  
  4. import android.content.Intent;  
  5. import android.os.IBinder;  
  6. import android.os.RemoteException;  
  7. import android.util.Log;  
  8.   
  9. public class CountService extends Service {  
  10.     public static final String TAG = "CountService";  
  11.     private boolean threadDisable;  
  12.     private int count ;  
  13.       
  14.     private ICountService.Stub serviceBinder = new ICountService.Stub(){  
  15.         @Override  
  16.         public int getCount() throws RemoteException {  
  17.             // TODO Auto-generated method stub  
  18.             return count;  
  19.         }  
  20.           
  21.     };  
  22.       
  23.     @Override  
  24.     public IBinder onBind(Intent intent) {  
  25.         // TODO Auto-generated method stub  
  26.         return serviceBinder;  
  27.     }  
  28.   
  29.     @Override  
  30.     public void onCreate() {  
  31.         // TODO Auto-generated method stub  
  32.         super.onCreate();  
  33.         new Thread(new Runnable(){  
  34.             @Override  
  35.             public void run() {  
  36.                 // TODO Auto-generated method stub  
  37.                 while(!threadDisable){  
  38.                     try {  
  39.                         Thread.sleep(1000);  
  40.                     } catch (InterruptedException e) {  
  41.                         // TODO Auto-generated catch block  
  42.                         e.printStackTrace();  
  43.                     }  
  44.                     count++;  
  45.                     Log.v(TAG , "Count="+count);  
  46.                 }  
  47.             }  
  48.         }).start();  
  49.     }  
  50.   
  51.     @Override  
  52.     public void onDestroy() {  
  53.         // TODO Auto-generated method stub  
  54.         super.onDestroy();  
  55.         threadDisable = true;  
  56.         Log.v(TAG , "onDestroy");  
  57.     }  
  58.       
  59. }  

配置文件AndroidManifest.xml和上面的类似,没有区别。

在Activity中使用服务的差别不大,只需要对ServiceConnection中的调用远程服务的方法时,要捕获异常。

[java] view plaincopy
  1. package com.test;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.ComponentName;  
  5. import android.content.Intent;  
  6. import android.content.ServiceConnection;  
  7. import android.os.Bundle;  
  8. import android.os.IBinder;  
  9. import android.os.RemoteException;  
  10. import android.util.Log;  
  11.   
  12. public class LocalServiceDemoActivity extends Activity {  
  13.     private ICountService countService;  
  14.       
  15.     private ServiceConnection serviceConnection = new ServiceConnection(){  
  16.         @Override  
  17.         public void onServiceConnected(ComponentName name, IBinder service) {  
  18.             // TODO Auto-generated method stub  
  19.             countService = (ICountService)service;  
  20.             try {  
  21.                 Log.v(CountService.TAG , "on service connected,count is:"+  
  22.                 countService.getCount());  
  23.             } catch (RemoteException e) {  
  24.                 // TODO Auto-generated catch block  
  25.                 throw new RuntimeException(e);  
  26.             }  
  27.         }  
  28.         @Override  
  29.         public void onServiceDisconnected(ComponentName name) {  
  30.             // TODO Auto-generated method stub  
  31.             countService = null ;  
  32.         }  
  33.     };  
  34.       
  35.     /** Called when the activity is first created. */  
  36.     @Override  
  37.     public void onCreate(Bundle savedInstanceState) {  
  38.         super.onCreate(savedInstanceState);  
  39.         setContentView(R.layout.main);  
  40.           
  41.         //startService(new Intent(this , CountService.class));  
  42.         this.bindService(new Intent("com.test.CountService"),   
  43.                 this.serviceConnection, BIND_AUTO_CREATE);  
  44.     }  
  45.   
  46.     @Override  
  47.     protected void onDestroy() {  
  48.         // TODO Auto-generated method stub  
  49.         super.onDestroy();  
  50.         try {  
  51.             Log.v(CountService.TAG , "last onDestroy,count is:"+  
  52.                     countService.getCount());  
  53.         } catch (RemoteException e) {  
  54.             // TODO Auto-generated catch block  
  55.             e.printStackTrace();  
  56.         }  
  57.         //stopService(new Intent(this , CountService.class));  
  58.         this.unbindService(serviceConnection);  
  59.     }  
  60.       
  61. }  

这样就可以在同一个应用程序中使用远程服务的方式和自己定义的服务交互了。

如果是另外的应用程序使用远程服务,需要做的是复制上面的aidl文件和相应的包构到应用程序中,其他调用等都一样。

编写传递复杂数据类型的远程服务

服务的生命周期

原文地址:https://www.cnblogs.com/walccott/p/4957020.html