本篇文章介绍如何通过App添加一个系统服务,服务端的App通过Android.mk编译进系统,来完成同Client端的跨进程通信。
(1)Server端
在服务端添加如下代码:
(A)服务回调的AIDL
// IDetonatorCallback.aidl
package com.detonator.server;
interface IDetonatorCallback {
void void onServerCallbackMessage(String msg);
}
(B)服务接口的AIDL
// IDetonatorService.aidl
package com.detonator.server;
import com.detonator.server.IDetonatorCallback;
interface IDetonatorService {
void registerCallBack(IDetonatorCallback callback);
void unregisterCallBack(IDetonatorCallback callback);
int getScreenBrightness();
boolean setScreenBrightness(int brightness);
}
(C)服务端Service的实现
package com.detonator.server;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.provider.Settings;
import android.util.Log;
public class DetonatorManagerService extends Service{
private static final String TAG = "DetonatorManagerService";
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mDetonatorStub;
}
/**
* AIDl 服务端声明实现
*/
private final IDetonatorService.Stub mDetonatorStub = new IDetonatorService.Stub() {
@Override
public int getScreenBrightness() throws RemoteException {
int result = -1;
try {
result = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
Log.i(TAG, "getScreenBrightness = " + result);
return result;
}
@Override
public boolean setScreenBrightness(int brightness) throws RemoteException {
Log.i(TAG, "setScreenBrightness_1 = " + brightness);
boolean optResult;
// 自动亮度改为手动亮度
try {
int mode = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE);
if (mode == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC) {
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
}
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
optResult = Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, resultBrightness);
Log.i(TAG, "setScreenBrightness_2 = " + brightness + " , optResult = " + optResult);
return optResult;
}
@Override
public void registerCallBack(IDetonatorCallback callback) throws RemoteException {
Log.i(TAG, "-- registerCallBack --");
CallbackRegisterManager.getInstance().register(callback);
}
@Override
public void unregisterCallBack(IDetonatorCallback callback) throws RemoteException {
Log.i(TAG, "-- unregisterCallBack --");
CallbackRegisterManager.getInstance().unRegister(callback);
}
};
@Override
public void noteClients(String msg) {
RemoteCallbackList<IDetonatorCallback> remoteCallbackList = CallbackRegisterManager.getInstance().getRemoteCallbackList();
int N = remoteCallbackList.beginBroadcast();
for (int i = 0; i < N; i++) {
try {
IDetonatorCallback callback = remoteCallbackList.getBroadcastItem(i);
callback.onMessageReceive(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
remoteCallbackList.finishBroadcast();
}
}
(D)服务端Manager的实现
package com.detonator.server;
import android.os.RemoteCallbackList;
public class CallbackRegisterManager {
private static CallbackRegisterManager instance;
private RemoteCallbackList<IDetonatorCallback> remoteCallbackList = null;
private CallbackRegisterManager() {
remoteCallbackList = new RemoteCallbackList<>();
}
public static CallbackRegisterManager getInstance() {
synchronized (CallbackRegisterManager.class) {
if (instance == null) {
instance = new CallbackRegisterManager();
}
}
return instance;
}
public RemoteCallbackList<IDetonatorCallback> getRemoteCallbackList(){
return remoteCallbackList;
}
public void register(IDetonatorCallback callback){
if(remoteCallbackList != null){
remoteCallbackList.register(callback);
}
}
public void unRegister(IDetonatorCallback callback){
if(remoteCallbackList != null){
remoteCallbackList.unregister(callback);
}
}
}
(E)编译成服务APK
将如上代码编译成服务apk,通过Android.mk文件编译进系统。
<!-- AndroidManifest.xml -->
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.detonator.server"
android:sharedUserId="android.uid.system"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"
tools:ignore="ProtectedPermissions" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
tools:targetApi="31">
<service android:name=".DetonatorManagerService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="action.server.detonator"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
</application>
</manifest>
//Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := DetonatorServer
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := platform
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_SYSTEM_EXT_MODULE := true
LOCAL_PRIVILEGED_MODULE := true
include $(BUILD_PREBUILT)
(2)Client端(应用)
将IDetonatorCallback.aidl和IDetonatorService.aidl拷贝到Client端。
(A)客户端Manager的实现
package com.detonator.server;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class DetonatorManager {
private static final String TAG = "DetonatorManager";
private Context mContext;
private static DetonatorManager mInstance;
private IDetonatorService mService;
private IBinder mBinder;
private boolean mConnected;
private RemoteCallbackImpl mRemoteCallbackImpl;
private IRemoteCallback mRemoteCallback;
public static DetonatorManager getInstance() {
synchronized (DetonatorManager.class) {
if (mInstance == null) {
mInstance = new DetonatorManager();
}
}
return mInstance;
}
public void init(Context context, IRemoteCallback iCallback){
mContext = context.getApplicationContext();
this.mRemoteCallback = iCallback;
}
public void register() {
bindDetonatorManagerService(mConnService);
}
public void unRegister() {
if (mConnected) {
try {
if (mRemoteCallbackImpl != null) {
getService().unregisterCallBack(mRemoteCallbackImpl);
}
} catch (Exception e) {
e.printStackTrace();
}
mContext.unbindService(conn);
}
}
/**
* AIDL 客户端连接器ServiceConnection实现,获取连接后的IBinder对象
*/
private ServiceConnection mConnService = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mBinder = iBinder;
mConnected = true;
// 初始化aidl远程回调
mRemoteCallbackImpl = new RemoteCallbackImpl(mRemoteCallback);
// 注册aidl远程回调
try {
getService().registerCallBack(mRemoteCallbackImpl);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
mConnected = false;
}
};
/**
* 获取连接AIDL服务后的实例
*
* @return
*/
private IDetonatorService getService() {
if (mService != null) {
return mService;
}
mService = IDetonatorService.Stub.asInterface(mBinder);
return mService;
}
private boolean isServiceConnected() {
return mConnected;
}
/* -------------------------------------------- 以下是具体业务操作实现 -------------------------------------------- */
/**
* 获取屏幕亮度
*
* @return 屏幕亮度值,由亮暗到亮[0-255]
*/
public int getScreenBrightness() {
int result = -1;
try {
result = getService().getScreenBrightness();
} catch (RemoteException e) {
e.printStackTrace();
}
return result;
}
/**
* 设置屏幕亮度
*
* @return 屏幕亮度值,由亮暗到亮[0-255]
*/
public boolean setScreenBrightness(int brightness) {
boolean optResult = true;
try {
optResult = getService().setScreenBrightness(brightness);
} catch (RemoteException e) {
optResult = false;
e.printStackTrace();
}
return optResult;
}
}
以上主要使用到如下类和接口。
package com.detonator.server;
public interface IRemoteCallback {
void onReceiveMessage(String msg);
}
package com.detonator.server;
import android.os.RemoteException;
public class RemoteCallbackImpl extends IDetonatorCallback.Stub {
private static final String TAG = "DetonatorCallbackImpl";
private IRemoteCallback mRemoteCallback = null;
public RemoteCallbackImpl(IRemoteCallback iCallback) {
this.mRemoteCallback = iCallback;
}
@Override
public void onServerCallbackMessage(String msg) throws RemoteException {
if (mRemoteCallback != null) {
mRemoteCallback.onReceiveMessage(msg);
}
}
}
上面的Manager是通过SDK的形式发布的,其Module Name是detonatorSDK,其build.gradle如下:
plugins {
id 'com.android.library'
}
android {
namespace 'com.detonator.server'
compileSdk 33
//...
}
}
(B)客户端App调用Manager的实现
package com.detonator.sample;
import com.detonator.server.DetonatorManager;
import com.detonator.server.IRemoteCallback;
public class MainActivity extends AppCompatActivity {
private DetonatorManager mDetonatorManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDetonatorManager = DetonatorManager.getInstance();
mDetonatorManager.init(this, mReceiveMessage);
mDetonatorManager.register();
//通过Manager端调用远程服务的函数
int brightness = mDetonatorManager.getScreenBrightness();
mDetonatorManager.setScreenBrightness(brightness);
}
IRemoteCallback mReceiveMessage = new IRemoteCallback() {
@Override
public void onReceiveMessage(String msg) {
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (mDetonatorManager != null) {
mDetonatorManager.unRegister();
}
}
}
通过aar包或者module引入来调用Manager相关方法。
plugins {
id 'com.android.application'
}
android {
namespace 'com.detonator.sample'
compileSdk 33
//...
}
dependencies {
implementation project(path: ':detonatorSDK')
//implementation(fileTree("libs/DetonatorSDK_v1.0.aar"))
}
至此整个Client端通过AIDL调用远程服务流程全部结束。