无痛的使用BindService,将本地服务改成远程服务

1 题目要求

创建一个服务 QueryWeekdayService,该服务提供一个公共方法 QueryWeekday,输入参数日期(年、月、日),返回该日期是星期几。要求本应用程序和其它应用程序都能够绑定到该服务,并调用公共方法。

原创作品,转载请声明

2 实现思路

笔者上课的教材上面明确标注BindService只能进行进程内绑定,因此让笔者在实现题目需要的时候费了很多精力(辣鸡书,不看也罢 √)

回归正题,分析题目可知,需要通过服务去获取输入日期是星期几,所以一个简单的直觉就是使用BindService来进行通信,然而题目要求其他应用程序也要能使用该服务,所以这里引入一个新东西(反正书上没写)AIDL接口。

3 AIDL 接口

AIDL是Android Interface Definition Language的缩写,即Android接口定义语言。它是Android的进程间通信比较常用的一种方式。

通过使用AIDL接口可以轻松实现跨进程通信(IPC - Inter Process Communication),也就是说可以用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。

4 如何使用

4.1 新建AIDL文件
  1. 在包中,new—>AIDL—>AIDL file。

在这里插入图片描述

  1. 声明想要远程调用的接口

在这里插入图片描述

3. 下一步是关键,点击 Build–>Rebuild Project,从而将接口文件自动生成为java文件

在这里插入图片描述

4.2 写Service文件(这一步与本地Service有点不同)
  1. 声明并实现一个IBinder对象(这里与一般的bindService不同),这里就是实例化你刚刚定义的接口

    private final IBinder mBinder = new IMyAidlInterface.Stub(){
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
        }
        @Override
        public String remoteGetWeekday(String date) throws RemoteException {
            return getWeekday(date); //调用具体的业务
        }
    };
    
  2. 绑定你的接口

        @Override
        public IBinder onBind(Intent intent) {
    //        return new MyBinder();
            return mBinder;
        }
    
  3. 写具体的业务

    public String getWeekday(String date){
        String[] dates = date.split("-");
        String[] weekdays = {"星期日","星期一","星期二","星期三","星期四","星期五","星期六",};
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR,Integer.parseInt(dates[0]));
        cal.set(Calendar.MONTH,Integer.parseInt(dates[1])-1);
        cal.set(Calendar.DATE,Integer.parseInt(dates[2]));
        int weekday = cal.get(Calendar.DAY_OF_WEEK)-1;
        return date+"的那天是"+weekdays[weekday];
    }
    
4.3 在Manifests中声明你的服务
<service
    android:name=".service.QueryWeekday"
    android:process=":remote"
    android:exported="true"
    android:enabled="true">
</service>

4.4 新建一个App,用于验证

  1. 将AIDL接口文件放在新的App中,注意要先创建一个与原来AIDL接口所在的接口一样包名的包。

在这里插入图片描述

  1. 然后build—>rebuild project,生成对应的java文件

  2. 在Acitivity中调用服务,即new一个ServiceConnection对象(这里是new的是接口对象),然后在onStart中调用服务,注意这里需要setComponent,具体看代码和注释

    private final ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            queryWeekday = IMyAidlInterface.Stub.asInterface(service);
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
    
        }
    };
    
    @Override
    protected void onStart() {
        super.onStart();
        Intent serviceIntent = new Intent();
        //这里的包名是原来服务所在的包的包名,cls是你在manifests文件中定义的服务的name
        serviceIntent.setComponent(new ComponentName("com.young.project02","com.young.project02.service.QueryWeekday"));
        bindService(serviceIntent,conn, BIND_AUTO_CREATE);
        boolean result = bindService(serviceIntent,conn, Context.BIND_AUTO_CREATE);
        Log.i("result",result+"" );
    }
    

    然后就是你的业务逻辑了,这里因人而异了

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button queryBtn = (Button)findViewById(R.id.queryBtn);
        EditText dateText = (EditText)findViewById(R.id.dateEditView);
        queryBtn.setOnClickListener(v -> {
            String date = dateText.getText().toString();
            String weekday = null;
            try {
                weekday = queryWeekday.remoteGetWeekday(date);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            Toast.makeText(this,weekday,Toast.LENGTH_LONG).show();
        });
    }
    

5 效果

从结果可以看到跨APP可以调用服务

在这里插入图片描述

6 源代码

https://github.com/GoatYoung/issue10A 给颗小星星⭐可否? 嘿嘿

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值