一、binder服务端及客户端基本架构
1.服务端具体实现
(1)添加一个aidl 来进行和binder交互。
IServices.aidl
// IServices.aidlpackage com.example.service;// Declare any non-default types here with import statementsinterface IServices {int add(int a, int b);}
(2)然后通过服务进行实现,对其中的方法进行重写。
MyService.kt
package com.example.serviceimport android.app.Serviceimport android.content.Intentimport android.os.IBinderimport android.util.Logclass MyService : Service() {private var mBinder: IBinder" />= nulloverride 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
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.service"><applicationandroid: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"><serviceandroid:name=".MyService"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.example.client.MyService" /></intent-filter></service><activityandroid: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.aidlpackage com.example.service;// Declare any non-default types here with import statementsinterface 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.clientimport android.content.ComponentNameimport android.content.Intentimport android.content.ServiceConnectionimport android.os.Bundleimport android.os.IBinderimport android.util.Logimport android.widget.Buttonimport androidx.appcompat.app.AppCompatActivityimport com.example.service.IServicesclass MainActivity : AppCompatActivity(), ServiceConnection {private var mServices: IServices" />= nulloverride 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
来进行
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"><applicationandroid: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"><activityandroid: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>
元素是 AndroidManifest.xml 文件中的一部分,用于指定应用程序可以查询的外部组件和服务。在你的示例中,
元素指定了应用程序可以查询
com.example.client.MyService
这个服务。
具体来说, 元素的作用是允许应用程序查询指定的 intent actions、data、和 categories,以便与其他应用程序的组件进行交互。这在 Android 11(API 级别 30)及更高版本中引入,是为了提高应用程序对其他应用程序组件的访问控制。
在你的示例中,通过指定 元素,你的应用程序声明了对具有 action 为 “com.example.client.MyService” 的 intent 的查询权限。这表示你的应用程序有权向系统查询是否存在具有相应 action 的服务,以便与该服务进行交互。
这样的声明可以在需要与其他应用程序组件(例如服务)交互的场景下使用。在 Android 11 中,如果你的应用程序尝试使用 startService()
、bindService()
等方法与其他应用程序的服务进行通信,而目标服务的包名和 action 没有在 中声明,系统将拒绝这些查询操作,以增强应用程序的隐私和安全性。
请注意,使用 元素时,你需要确保你的应用程序有正当的理由去查询其他应用程序的组件,并且要确保查询的目标是可信任的。