Android

Android Service两种启动方式

勤劳的小蜜蜂 · 12月30日 · 2018年 ·

Service是Android组件中最基本也是最为常见用的四大组件之一。Android四大组件有ActivityService(服务),Content Provider(内容提供),BroadcastReceiver(广播接收器)。

Service概述

  • 服务是一个在后台运行的程序,它被启动后在后台一直持续运行,直至有人停止了它或它自己停止。
  • 启动方式:调用Context.startService()启动。
  • 停止方式:调用Context.stopService()结束或由自己调用Service.stopSelf() 或 Service.stopSelfResult()来自己停止。
  • 不论调用了多少次startService()方法,只需要调用一次stopService()来停止服务。

Service作用

有时会有一些与用户很少需要产生交互的应用程序,通常是将它们置于后台运行,而且在它们运行期间不影响其它程序的运行。 比如版本升级、播放音乐、 执行文件 I/O 等。

Service两种启动方式

通过startService

这种方式启动的Service是独立于开启它的Activity的。Activity退出后,Service仍然在运行中。

  1. 创建一个类继承android.app.Service类,实现抽象方法onBind(),重写onCreate()、onStartCommand()、onDestry();
  2. 在清单文件中配置Service。
public class MyService extends Service {   
    //创建服务时调用
    @Override  
    public void onCreate() {  
    super.onCreate();  
    Log.d("MyService", "onCreate");  
    }   
    //服务执行的操作
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        Log.d("MyService", "onStartCommand");  
        return super.onStartCommand(intent, flags, startId);  
    }      
    //销毁服务时调用
    @Override  
    public void onDestroy() {  
        super.onDestroy();  
        Log.d("MyService", "onDestroy");  
    }  
    @Override  
    public IBinder onBind(Intent intent) {  
        return null;  
    }  
}

onBind()方法是Service中唯一的一个抽象方法,所以必须要在子类里实现, 即使我们用不到。

第二种启动方式才会用到onBind()方法。此处用第一种方式启动Service,所以暂时忽略onBind()方法。

通过bindService

  1. bindService启动的服务和调用者之间是典型的客户端 – 服务器模式。调用者是客户端,服务则是服务器端。服务只有一个,但绑定到服务上面的客户端可以有一个或很多个。
  2. 客户端可以通过的IBinder接口获取服务实例,从而实现在客户端直接调用服务中的方法以实现灵活交互,这在通过startService方法启动中是无法实现的。
  3. 绑定服务的三种方式:扩展 Binder 类、使用 Messenger、使用 AIDL
  4. 这种方式启动的Service是与开启它的Activity梆定在一起的。Activity退出时,Service会同时退出。

扩展binder类:通过扩展Binder类并重onBind()返回它的一个实例创建接口,客户端收到Binder后可以利用它直接访问Binder实现中的,甚至service中可用的公共方法。

public class LocalService extends Service {
    // 通过binder实现调用者client与Service之间的通信
    private final IBinder mBinder = new LocalBinder();
    // 随机数发生器
    private final Random mGenerator = new Random();
 
    public class LocalBinder extends Binder {
        public LocalService getService() {
            // 返回此LocalService实例,以便客户端可以调用公共方法
            return LocalService.this;
        }
    }
 
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
 
    // getRandomNumber是Service暴露出去供client调用的公共方法
    public int getRandomNumber() {
      return mGenerator.nextInt(100);
    }
}

LocalBinder为客户端提供了getService方法,以检索LocalService的当前实例。这样客户端便可调用服务中的公用方法。如客户端可以调用服务中的getRandomNumber()方法。

public class BindingActivity extends Activity {
    LocalService mService;
    boolean mBound = false;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
 
    @Override
    protected void onStart() {
        super.onStart();
        // 绑定到LocalService
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }
 
    @Override
    protected void onStop() {
        super.onStop();
        // 解绑
        if (mBound) {
            unbindService(mConnection);
            mBound = false;
        }
    }
 
    // 单击按钮时调用(布局文件中的按钮使用android:onclick属性附加到此方法)
    public void onButtonClick(View v) {
        if (mBound) {
            // 从LocalService调用方法
            int num = mService.getRandomNumber();
            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
        }
    }
 
    /** 定义服务绑定的回调, 传给bindService() */
    private ServiceConnection mConnection = new ServiceConnection() {
 
        @Override
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // 已经绑定到localservice,调用ibinder并获取localservice实例
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }
 
        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
}

上例说明客户端如何使用ServiceConnection的实现和onServiceConnected()的回调绑定到服务,点击按键,会调用服务中的公共方法getRandomNumber()。客户端应在适当的时机进行取消绑定,如例子中在onStop()的时候进行取消服务绑定。

不同的启动方式,Service的生命周期有些不同。

AndroidManifest.xml声明服务

<service 
         android:description=“string resource”  //描述service的信息
         // Android7.0新特性,用户解锁设备前是否可以运行
         android:directBootAware=[“true”|“false”]
         // 是否能被系统实例
         android:enabled=[“true”|“false”]
         // 其他应用的组件能否start或者bind该service
         android:exported=[“true”|“false”]
         android:icon=“drawable resource”
         // service将运行在一个单独的进程,进程中只有一个service
         android:isolatedProcess=[“true”|“false”]
         android:label=“string resource”
         // 必须要指定的属性,service的名字
         android:name=“string”
         // 需要的权限,使用该服务的应用需要在manifest中使用<uses-permission>
         android:permission=“string“
         // 所在进程名
         android:process=”string”>
    . . .
</service>

1.与Activity同级

2.一般只需要写name属性即可

0 条回应