Android Service启动方式对比区别(一)

服务简单介绍:

服务是一个应用程序组件,可以在后台执行长时间运行的操作,不提供用户界面。一个应用程序组件可以启动一个服务,它将继续在后台运行,即使用户切换到另一个应用程序。此外,一个组件可以绑定到一个服务与它交互,甚至执行进程间通信(IPC)。例如,一个服务可能处理网络通信、播放音乐、计时操作或与一个内容提供者交互,都在后台执行。

服务的种类

  • 按运行地点分类
类别 区别 优点 缺点 应用
本地服务(Local Service) 该服务依附在主进程上 服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多 主进程被Kill后,服务便会终止。 如:音乐播放器播放等不需要常驻的服务。
远程服务(Remote Service) 该服务是独立的进程 服务为独立的进程,对应进程名格式为所在包名加上你指定android:process字符串。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性 该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点 一些提供系统服务的Service,这种Service是常驻的。
  • 按运行类型分类
类别 区别 应用
前台服务 会在通知栏显示onGoing的 Notification 当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定的通知作用。常见的如音乐播放服务。
后台服务 默认的服务即为后台服务,即不会在通知一栏显示 onGoing的 Notification。 当服务被终止的时候,用户是看不到效果的。某些不需要运行或终止提示的服务,如天气更新,日期同步,邮件同步等。
  • 按使用方式分类
类别 区别
startService启动的服务 主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService。
bindService启动的服务 默认的服务即为后台服务,即不会在通知一栏显示 onGoing的 Notification。
同时使用startService、bindService 启动的服务 停止服务应同时使用stopService与unbindService

服务生命周期

不同启动方式下生命周期对比

通过这个图看到对比,两种启动方式及它们的生命周期,start服务主要是调用onStartCommand()方法处理逻辑。而bind服务主要是调用onBind()方法处理逻辑,还有使用onUnbind()方法进行解绑,service才会被kill掉

我们只要知道不管任何启动服务方式onCreate()生命周期只会被执行一次

  1. startService建立连接后,onBind()生命周期不管怎样始终都不会被调用,当app关闭之后并没有停止服务,它会一直保存在后台,直到调用stopService或Service自身的stopSelf来停止服务。
  2. bindService建立连接后,onStartCommand()生命周期不会被调用,app关闭前执行unBindService()解绑服务后会自动调用 onUnbind()生命周期,它的启动周期依附于启动它的Context,如果没有停止Service,会报异常错误
注意:
  1. 当手机屏幕发生旋转时,如果Activity设置的是自动旋转的话,在旋转的过程中,Activity会被重新创建,如果用bindServie建立连接的话,便会断开服务(之前的Context不存在了),服务会被自动停止
  2. 如果同时使用startService与bindService方法启动Service,需要终止该Service时,要调用stopService和unbindService方法(unbindService依附于启动它的Context,startServicec并不依附于启动它的Context。如果先调用unbindService,这时服务并不会被终止,当调用stopService后,服务才会被终止;如果先调用stopService,服务也不会被终止,当调用unbindService或者之前调用bindService的Context不存在了(如Activity被finish掉了)服务才会自动停止);
  3. 当需要停止服务的时候,最好在Activity的onDestory()来进行停止服务

使用

1.新建一个Serivice后,先要在AndroidManifest.xml中注册Service,在application内添加需要注册的Service信息:

        <service android:name=".TestService" >
            android:exported="true" 
        </service>

2.Service文件里面有 两种启动方式

public class TestService extends Service{

    @Override
    public void onCreate() {
        super.onCreate(); 
    } 

    /** 
    * onBind 是 Service 的虚方法,因此我们不得不实现它。
    * 返回 null,表示客服端不能建立到此服务的连接。
    */ 
    @Override
    public IBinder onBind(Intent intent) { 
        return new MyBinder();
    }

    // 已取代onStart方法--onStart方法是在Android2.0之前的平台使用的.
    // 在2.0及其之后,则需重写onStartCommand方法,同时,旧的onStart方法则不会再被直接调用
    // (外部调用onStartCommand,而onStartCommand里会再调用 onStart。在2.0之后,
    // 推荐覆盖onStartCommand方法,而为了向前兼容,在onStartCommand依然会调用onStart方法。
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(tag, "自启动的flags"+flags+"       启动的strtId"+startId);
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);//休眠三秒===模仿耗时操作
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                String str=intent.getStringExtra("name");
                Log.e(tag, str);
            }
        }).start();
        return START_REDELIVER_INTENT;
    } 

    @Override
    public boolean onUnbind(Intent intent) { 
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy(); 
    } 
    // IBinder是远程对象的基本接口,是为高性能而设计的轻量级远程调用机制的核心部分。但它不仅用于远程
    // 调用,也用于进程内调用。这个接口定义了与远程对象交互的协议。
    // 不要直接实现这个接口,而应该从Binder派生。
    // Binder类已实现了IBinder接口
    class MyBinder extends Binder { 
        /** 
        * 获取Service的方法
        * @return 返回TestService
        */ 
        public  TestService getService(){
            return TestService.this;
        }
    }
}

3.start启动方式

public class TestActivity extends Activity{
  private Intent intent;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    intent = new Intent(this, TestSerice.class);
    intent.putExtra("name", "启动了service");
    startService(intent);// 启动服务
  }
  @Override
  protected void onDestroy() {
    super.onDestroy();
    stopService(intent);// 在退出Activity时停止该服务
  }
}

4.bind启动方式

1).本地绑定

public class TestActivity extends Activity{
   @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Intent intent = new Intent(this, TestService.class);
    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);//绑定目标Service
  }
  @Override
  protected void onDestroy() {
    super.onDestroy();
    unbindService(serviceConnection);// 解除绑定,断开连接
  }
  // 在Activity中,我们通过ServiceConnection接口来取得建立连接与连接意外丢失的回调
  ServiceConnection serviceConnection = new ServiceConnection() {            @Override
    public void onServiceConnected(ComponentName name, IBinder service){
      // 建立连接
      // 获取服务的操作对象
               TestService.MyBinder binder = (TestService.MyBinder)service;
               binder.getService();// 获取到的Service即TestService
    } 
    @Override
    public void onServiceDisconnected(ComponentName name) {
      // 连接断开
    }
  };
}

2).远程绑定

AndroidManifest.xml中Service元素常见属性

  • andorid:name:服务类名。可以是完整的包名+类名。也可使用.代替包名。
  • adroid:exported:其他应用能否访问该服务,如果不能,则只有本应用或有相同用户ID的应用能访问。默认为false。
  • android:enabled:显示给用户的服务名称。如果没有进行服务名称的设置,默认显示服务的类名。
  • android:process : 服务所运行的进程名。默认是在当前进程下运行,与包名一致。如果进行了设置,将会包名后加上设置的集成名。 如果名称设置为冒号 :开头,一个对应用程序私有的新进程会在需要时和运行到这个进程时建立。如果名称为小写字母开头,服务会在一个相同名字的全局进程运行,如果有权限这样的话。这允许不同应用程序的组件可以分享一个进程,减少了资源的使用。
  • android:icon : 服务的图标。
  • android:permission:申请使用该服务的权限,如果没有配置下相关权限,服务将不执行,使用startService()、bindService()方法将都得不到执行。

猜你喜欢

转载自blog.csdn.net/m0_37711172/article/details/80016902