SurfaceControlViewHost 实现跨进程UI渲染

背景

在学习photo picker文档时,看到了这样一个描述;可以通过一种方法,将另一个进程的复杂页面渲染到当前页面中,并支持做复杂交互,且具备一定的安全性和隐私性保护。结合之前项目上的一个诉求(给第三方业务暴露登陆按钮,但不想让业务方得知实现细节,避免业务方后台调用该按钮后台偷偷登陆)感觉可以用这种方式去实现,因此去了解下细节

实现效果

实现方式:

1、使用SurfaceControlViewHost + SurfaceView 实现

SurfaceView原理: 核心是把主进程的surface传递给单独的渲染进程,从而实现跨进程渲染的效果

SurfaceControlViewHost: 并提供将渲染进程的view嵌入到主进程中

使用步骤

客户端(主进程):

--创建用于展示内容的,surfaceView,提供host token确定是具体哪个surface View,提供display ID,用于渲染的一些基础依赖(字体大小等)

--获取服务端返回的SurfacePackage,与surfaceView绑定

--事件通知,所有input事件,通知服务器

服务端(渲染进程):

--使用客户端提供的display ID、hostToken 创建SurfaceControlViewHost,创建自定义view,返回SurfacePackage给客户端

--接收input事件,传递给自定义view

java 复制代码
//aidl
interface IRemoteRender {
    //客户端提供surface、大小、display 从服务端获取 surfacePackage
    SurfacePackage getSurfacePackage(int displayId, IBinder hostToken, int width, int height);
    //客户端向服务端传递 事件
    boolean onTouch(in MotionEvent motionEvent);
}
 
//服务端
    private final IRemoteRender.Stub mBinder = new IRemoteRender.Stub() {
 
        @Override
        public SurfaceControlViewHost.SurfacePackage getSurfacePackage(int displayId, IBinder hostToken, int width, int height) {
            Log.i(TAG, "getSurfacePackage, displayId=" + displayId + ", hostToken=" + hostToken + ", width=" + width + ", height=" + height);
            final SurfaceControlViewHost.SurfacePackage[] result = new SurfaceControlViewHost.SurfacePackage[1];
            final CountDownLatch latch = new CountDownLatch(1);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    // 创建SurfaceControlViewHost
                    Context context = getBaseContext();
                    Display display = context.getSystemService(DisplayManager.class).getDisplay(displayId);
                    mSurfaceControlViewHost = new SurfaceControlViewHost(context, display, hostToken);
                    createRootView(width,height);
                    // 将视图附加到SurfaceControlViewHost
                    mSurfaceControlViewHost.setView(mRootView, width, height);
                    result[0] = mSurfaceControlViewHost.getSurfacePackage();
                    latch.countDown();
                }
            });
 
            try {
                latch.await(); // 等待主线程完成操作
                return result[0];
            } catch (InterruptedException e) {
                Log.i(TAG, "getSurfacePackage, e=" + e.getMessage());
            }
            return null;
        }
 
        @Override
        public boolean onTouch(MotionEvent event) throws RemoteException {
            final CountDownLatch latch = new CountDownLatch(1);
            final boolean[] result = {true};
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    mRootView.dispatchTouchEvent(event);
                    latch.countDown();
                }
            });
            try {
                latch.await(); // 等待主线程完成操作
                return result[0];
            } catch (InterruptedException e) {
                Log.i(TAG, "getSurfacePackage, e=" + e.getMessage());
            }
            return true;
        }
    };
 
 
//客户端
      try {
            IBinder hostToken = mSurfaceView.getHostToken();
            SurfaceControlViewHost.SurfacePackage surfacePackage = mRemoteRender.getSurfacePackage(0, hostToken, 1000, 2000);
            mSurfaceView.setChildSurfacePackage(surfacePackage);
            mSurfaceView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
 
                    try {
                        return mRemoteRender.onTouch(motionEvent);
                    } catch (RemoteException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        } catch (RemoteException e) {
            e.printStackTrace();
        }
相关推荐
Libraeking9 小时前
破壁行动:在旧项目中丝滑嵌入 Compose(混合开发实战)
android·经验分享·android jetpack
市场部需要一个软件开发岗位10 小时前
JAVA开发常见安全问题:Cookie 中明文存储用户名、密码
android·java·安全
JMchen12312 小时前
Android后台服务与网络保活:WorkManager的实战应用
android·java·网络·kotlin·php·android-studio
crmscs12 小时前
剪映永久解锁版/电脑版永久会员VIP/安卓SVIP手机永久版下载
android·智能手机·电脑
localbob12 小时前
杀戮尖塔 v6 MOD整合版(Slay the Spire)安卓+PC端免安装中文版分享 卡牌肉鸽神作!杀戮尖塔中文版,电脑和手机都能玩!杀戮尖塔.exe 杀戮尖塔.apk
android·杀戮尖塔apk·杀戮尖塔exe·游戏分享
机建狂魔12 小时前
手机秒变电影机:Blackmagic Camera + LUT滤镜包的专业级视频解决方案
android·拍照·摄影·lut滤镜·拍摄·摄像·录像
hudawei99612 小时前
flutter和Android动画的对比
android·flutter·动画
lxysbly14 小时前
md模拟器安卓版带金手指2026
android
儿歌八万首15 小时前
硬核春节:用 Compose 打造“赛博鞭炮”
android·kotlin·compose·春节
消失的旧时光-194318 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed