一、Service 开启和停止

一、Service 开启和停止
二、Service 执行耗时工作
三、IPC常用方式
四、AIDL(一)同一应用中使用AIDL及原理
五、AIDL(二)不同应用中使用、自定义数据类型及定向Tag
六、AIDL(三)实现回调
七、AIDL(四)获取服务及绑定和Binder传递流程


Service 开启和停止

测试代码-BlogsServiceDemo

先定义一个Service类,名为StartStopService,继承自Service,代码如下:

代码1

com/ieening/blogsservicedemo/services/StartStopService.java

public class StartStopService extends Service {
    private final String TAG = StartStopService.class.getName();


    public StartStopService() {
        Log.d(TAG, "executing StartStopService constructor");
    }

    @Override
    public IBinder onBind(Intent intent) {
        // Return the communication channel to the service.
        // 必须重写该方法,该方法为抽象方法。绑定开启 Service 时会调用该方法,在开启和停止调用方式中不会调用该方法
        Log.d(TAG, "executing StartStopService onBind method");
        return null;
    }

    @Override
    public void onCreate() {
        // Service初次创建会调用该方法,我们可以做一些初始化操作,与 onDestroy相对
        Log.d(TAG, "executing StartStopService onCreate method");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 每次显示启动 Service 都会调用该方法
        Log.d(TAG, "executing onStartCommand method");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        // 每次销毁 Service 时都会调用该方法,在该方法内,可以添加释放资源的操作,与 onCreate 相对
        Log.d(TAG, "executing onDestroy method");
        super.onDestroy();
    }
}
  1. 必须重写onBind方法,该方法为抽象方法。绑定开启 Service 时会调用该方法,在开启和停止调用方式中不会调用该方法;
  2. Service初次创建会调用onCreate方法,我们可以做一些初始化操作,与onDestroy相对

1.1 显示开启和关闭

首先构建Intent,然后调用ContextstartServicestopService方法。

代码2

com/ieening/blogsservicedemo/MainActivity.java

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
    private final String TAG = MainActivity.class.getName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        View view = binding.getRoot();
        setContentView(view);

        // ! 绑定 Activity 和 Service
        ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.d(TAG, "executing ServiceConnection onServiceConnected");
                BindUnbindServiceBinder bindUnbindServiceBinder = (BindUnbindServiceBinder) service;
                // 获取 MyService 引用
                BindUnbindService bindUnbindService = (BindUnbindService) bindUnbindServiceBinder.getService();
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.d(TAG, "executing ServiceConnection onServiceDisconnected");
                // Service 被销毁时调用(内存不足等,正常解绑不会走这)
            }
        };

        binding.startServiceButton.setOnClickListener(v -> {
            Log.d(TAG, "click start service button to start service");
            // ! 显示开启 Service
            Intent intent = new Intent(getApplicationContext(), StartStopService.class);
            startService(intent);

            v.setEnabled(false);
            binding.restartServiceButton.setEnabled(true);
            binding.stopServiceButton.setEnabled(true);
        });

        binding.restartServiceButton.setOnClickListener(v -> {
            Log.d(TAG, "click restart service button to restart service");
            // ! 显示重启 Service
            Intent intent = new Intent(getApplicationContext(), StartStopService.class);
            startService(intent);
        });

        binding.stopServiceButton.setOnClickListener(v -> {
            Log.d(TAG, "click stop service button to stop service");
            // ! 显示停止 Service
            Intent stopIntent = new Intent(this, StartStopService.class);
            stopService(stopIntent);

            v.setEnabled(false);
            binding.startServiceButton.setEnabled(true);
            binding.restartServiceButton.setEnabled(false);
        });

        binding.bindServiceButton.setOnClickListener(v -> {
            Log.d(TAG, "click bind service button to bind service");
            Intent bindIntent = new Intent(this, BindUnbindService.class);
            bindService(bindIntent, serviceConnection, BIND_AUTO_CREATE);

            binding.bindServiceButton.setEnabled(false);
            binding.unbindServiceButton.setEnabled(true);
        });

        binding.unbindServiceButton.setOnClickListener(v -> {
            Log.d(TAG, "click unbind service button to unbind service");
            unbindService(serviceConnection);

            binding.bindServiceButton.setEnabled(true);
            binding.unbindServiceButton.setEnabled(false);
        });
    }
}

先点击start service button,再点击restart service button,最后点击stop service button,可以得到下面的日志:

2024-01-01 08:44:29.672 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo         D  click start service button to start service
2024-01-01 08:44:29.675 11694-11694 com.ieenin...topService com.ieening.blogsservicedemo         D  executing StartStopService constructor
2024-01-01 08:44:29.677 11694-11694 com.ieenin...topService com.ieening.blogsservicedemo         D  executing StartStopService onCreate method
2024-01-01 08:44:29.684 11694-11694 com.ieenin...topService com.ieening.blogsservicedemo         D  executing onStartCommand method
2024-01-01 08:44:40.759 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo         D  click restart service button to restart service
2024-01-01 08:44:40.768 11694-11694 com.ieenin...topService com.ieening.blogsservicedemo         D  executing onStartCommand method
2024-01-01 08:44:47.630 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo         D  click stop service button to stop service
2024-01-01 08:44:47.634 11694-11694 com.ieenin...topService com.ieening.blogsservicedemo         D  executing onDestroy method

在这里插入图片描述

1.2 绑定开启

上面显示开启和关闭Service,可以看出,显示开启Service后,调用者就和Service没有关联了。比如调用者是个ActivityService的作用是不断地计数。在显示开启Service的场景下,会存在如下两个问题:

  1. Activity无法直接(间接通过广播等方法)拿到Service计数结果,也就是说没法拿到Service引用。
  2. Activity退出的时候,若不是主动停止Service,那么Service将不会被关闭。不太恰当的比喻是:“管生不管养”。

定义com/ieening/blogsservicedemo/services/BindUnbindServiceBinder.java继承自Binder

代码3

com/ieening/blogsservicedemo/binders/BindUnbindServiceBinder.java

public class BindUnbindServiceBinder extends Binder {
    private final String TAG = BindUnbindServiceBinder.class.getName();
    private final Service service;

    BindUnbindServiceBinder(Service service) { // ! 持有 Service 引用
        Log.d(TAG, "executing BindUnbindServiceBinder constructor");
        this.service = service;
    }

    public Service getService() { // ! 返回 Service 引用
        Log.d(TAG, "executing BindUnbindServiceBinder getService");
        return service;
    }
}

定义BindUnbindService,继承自Service,代码如下:

代码4

com/ieening/blogsservicedemo/services/BindUnbindService.java

public class BindUnbindService extends Service {
    private final String TAG = BindUnbindService.class.getName();

    public BindUnbindService() {
        Log.d(TAG, "executing BindUnbindService constructor");
    }

    @Override
    public void onCreate() {
        // Service初次创建会调用该方法,我们可以做一些初始化操作,与 onDestroy相对
        Log.d(TAG, "executing BindUnbindService onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // 每次显示启动 Service 都会调用该方法
        Log.d(TAG, "executing BindUnbindService onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        // 每次销毁 Service 时都会调用该方法,在该方法内,可以添加释放资源的操作,与 onCreate 相对
        Log.d(TAG, "executing BindUnbindService onDestroy");
        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) { // ! 返回 Binder 对象
        Log.d(TAG, "executing BindUnbindService onBind");
        return new BindUnbindServiceBinder(this);
    }
}

在显示开启Service过程中,我们需要重写public abstract IBinder onBind(Intent intent);,显示场景下该方法并没有调用,而在绑定开启Service时,需要返回IBiner的引用给绑定者使用,重写onBind(Intent intent)方法,如com/ieening/blogsservicedemo/services/BindUnbindService.javaonBind方法。方法返回的是BindUnbindServiceBinder对象的引用,该对象持有了BindUnbindService引用。 那,绑定者在哪里接收IBinder的引用呢? 在Activity里定义ServiceConnection匿名内部类,代码见代码1serviceConnection定义。

有了ServiceConnection引用,接着就需要和Serice建立联系,建立联系的过程即是绑定开启Service的过程。建立联系调用bindService,解除绑定调用unbindService,两个方法都在Context中。

先点击bind service button,再点击unbind service button,得到如下日志:

2024-01-01 08:44:52.982 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo         D  click bind service button to bind service
2024-01-01 08:44:52.990 11694-11694 com.ieenin...indService com.ieening.blogsservicedemo         D  executing BindUnbindService constructor
2024-01-01 08:44:52.990 11694-11694 com.ieenin...indService com.ieening.blogsservicedemo         D  executing BindUnbindService onCreate
2024-01-01 08:44:52.991 11694-11694 com.ieenin...indService com.ieening.blogsservicedemo         D  executing BindUnbindService onBind
2024-01-01 08:44:52.991 11694-11694 com.ieenin...viceBinder com.ieening.blogsservicedemo         D  executing BindUnbindServiceBinder constructor
2024-01-01 08:44:53.000 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo         D  executing ServiceConnection onServiceConnected
2024-01-01 08:44:53.000 11694-11694 com.ieenin...viceBinder com.ieening.blogsservicedemo         D  executing BindUnbindServiceBinder getService
2024-01-01 08:45:21.910 11694-11694 com.ieenin...inActivity com.ieening.blogsservicedemo         D  click unbind service button to unbind service
2024-01-01 08:45:21.912 11694-11694 com.ieenin...indService com.ieening.blogsservicedemo         D  executing BindUnbindService onDestroy

在这里插入图片描述
测试代码-BlogsServiceDemo

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值