Android跨进程通信(二)——应用服务(2)

该文介绍了如何通过AIDL在Android中创建一个系统服务,服务端通过Android.mk编译进系统,实现与Client端的跨进程通信。涉及到的服务包括接口定义、服务实现、回调管理以及客户端的调用和服务连接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章介绍如何通过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调用远程服务流程全部结束。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪舞飞影

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值