利用binder的简单跨进程通讯架构

一、binder服务端及客户端基本架构

在这里插入图片描述

1.服务端具体实现

在这里插入图片描述

(1)添加一个aidl 来进行和binder交互。

IServices.aidl

// IServices.aidl
package com.example.service;

// Declare any non-default types here with import statements

interface IServices {
        int add(int a, int b);
}

(2)然后通过服务进行实现,对其中的方法进行重写。

在这里插入图片描述

MyService.kt

package com.example.service

import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.util.Log

class MyService : Service() {

    private var mBinder: IBinder? = null

    override fun onBind(intent: Intent): IBinder {
        mBinder = MyBinder()
        return mBinder!!
    }

    inner class MyBinder : IServices.Stub() {
        override fun add(a: Int, b: Int): Int {
            return a + b
        }
    }
}

(3)针对客户端的绑定,服务端进行意图定义

AndroidManifest.xml

<action android:name="com.example.client.MyService" />

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.service"
    >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Client">
        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true">
            
            <intent-filter>
                <action android:name="com.example.client.MyService" />
            </intent-filter>
            
        </service>

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
2.客户端具体实现

(1)添加aidl,来进行客户端的调用定义

在这里插入图片描述

IServices.aidl

// IServices.aidl
package com.example.service;

// Declare any non-default types here with import statements

interface IServices {
        int add(int a, int b);
}

tips:这里需要相同的package com.example.service;和服务端,否则调用 Binder invocation to an incorrect interface 报错。

(2)通过Activity来进行绑定服务

在这里插入图片描述

MainActivity.kt

package com.example.client

import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.example.service.IServices

class MainActivity : AppCompatActivity(), ServiceConnection {

    private var mServices: IServices? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<Button>(R.id.btn_1).setOnClickListener {
            val intent: Intent =
                Intent("com.example.client.MyService").setPackage("com.example.service")
            bindService(intent, this, BIND_AUTO_CREATE)
        }
        findViewById<Button>(R.id.btn_2).setOnClickListener {
            val result = mServices!!.add(1, 6)
            Log.d(TAG, "reseult=$result")
        }
    }

    override fun onServiceConnected(name: ComponentName?, service: IBinder?) {

        mServices = IServices.Stub.asInterface(service)
        Log.d(TAG, "onServiceConnected$mServices")
    }

    override fun onServiceDisconnected(name: ComponentName?) {
        mServices = null
    }

}

tips:这里有可能出现绑定不上的情况,一般是权限不足,这里可以通过改变服务端的apk类型为系统apk来进行清单文件的注册,完成客户端能够进行调用,或者通过 queries 来进行

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Client"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <queries>
        <intent>
            <action android:name="com.example.client.MyService" />
        </intent>
    </queries>
</manifest>

<queries> 元素是 AndroidManifest.xml 文件中的一部分,用于指定应用程序可以查询的外部组件和服务。在你的示例中,<queries> 元素指定了应用程序可以查询 com.example.client.MyService 这个服务。

具体来说,<queries> 元素的作用是允许应用程序查询指定的 intent actions、data、和 categories,以便与其他应用程序的组件进行交互。这在 Android 11(API 级别 30)及更高版本中引入,是为了提高应用程序对其他应用程序组件的访问控制。

在你的示例中,通过指定 <queries> 元素,你的应用程序声明了对具有 action 为 “com.example.client.MyService” 的 intent 的查询权限。这表示你的应用程序有权向系统查询是否存在具有相应 action 的服务,以便与该服务进行交互。

这样的声明可以在需要与其他应用程序组件(例如服务)交互的场景下使用。在 Android 11 中,如果你的应用程序尝试使用 startService()bindService() 等方法与其他应用程序的服务进行通信,而目标服务的包名和 action 没有在 <queries> 中声明,系统将拒绝这些查询操作,以增强应用程序的隐私和安全性。

请注意,使用 <queries> 元素时,你需要确保你的应用程序有正当的理由去查询其他应用程序的组件,并且要确保查询的目标是可信任的。

  • 40
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值