android跨进程如何渲染Surface

Surface实现了Parcelable序列化,代表可以跨进程传递Surface对象。因此可以通过跨进程渲染Surface,实现如主界面地图加载、主界面应用卡片加载。下面介绍下客户端和服务端进行AIDL通信渲染Surface流程。
首先在服务端新建AIDL文件ISurfaceInterface.aidl。

// ISurfaceInterface.aidl
package com.example.surfaceviewtest;

import android.view.Surface;
// Declare any non-default types here with import statements

interface ISurfaceInterface {

    void addSurface(in Surface surface);

    void addSurfaceWithSize(in Surface surface, int width, int height);

    void removeSurface(in Surface surface);

    void start();

    void stop();
}

接着服务端新建MyService的服务,负责绘制Surface。

package com.example.surfaceviewtest;

import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.Surface;

import androidx.annotation.DrawableRes;

public class MyService extends Service {

    private Canvas mCanvas;
    private Surface mSurface;
    private Rect mRect;
    private Paint mPaint;
    private int mWidth;
    private int mHeight;
    private int mShowTime;
    private Handler mHandler = new Handler();
    private Runnable mRun = new Runnable() {
        @Override
        public void run() {
            mShowTime++;
            drawSomething(mShowTime % 2 == 0 ? R.mipmap.pic_zjm1 : R.mipmap.pic_zjm2);
            mHandler.postDelayed(mRun, 1000);
        }
    };

    private ISurfaceInterface mBinder = new ISurfaceInterface.Stub() {
        @Override
        public void addSurface(Surface surface) throws RemoteException {
            mSurface = surface;
        }

        @Override
        public void addSurfaceWithSize(Surface surface, int width, int height) throws RemoteException {
            mSurface = surface;
            mRect = new Rect(0, 0, width, height);
            mWidth = width;
            mHeight = height;
        }

        @Override
        public void removeSurface(Surface surface) throws RemoteException {
            mSurface = null;
            mCanvas = null;
        }

        @Override
        public void start() throws RemoteException {
            drawSomething(R.mipmap.pic_zjm1);
            mHandler.postDelayed(mRun, 1000);
        }

        @Override
        public void stop() throws RemoteException {
            mHandler.removeCallbacks(mRun);
            clearSurface();
        }
    };

    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mRect = new Rect(0, 0, 300, 300);
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(5);
        mPaint.setAntiAlias(true);
    }

    private void drawSomething(@DrawableRes int id) {
        if (mSurface != null) {
            mCanvas = mSurface.lockCanvas(mRect);
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), id);
            Matrix matrix = new Matrix();
            int bWidth = bitmap.getWidth();
            int bHeight = bitmap.getHeight();
            matrix.postScale(mWidth * 1.0f / bHeight, mHeight * 1.0f / bHeight);
            Bitmap bitmap1 = Bitmap.createBitmap(bitmap, 0, 0, bWidth, bHeight, matrix, false);
            mCanvas.drawBitmap(bitmap1, 0, 0, mPaint);
            mSurface.unlockCanvasAndPost(mCanvas);
        }
    }

    private void clearSurface() {
        if (mSurface != null) {
            mCanvas = mSurface.lockCanvas(mRect);
            mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            mSurface.unlockCanvasAndPost(mCanvas);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder.asBinder();
    }

    @Override
    public void onDestroy() {
        mHandler.removeCallbacksAndMessages(null);
        super.onDestroy();
    }
}

最后客户端定义需要被绘制的SurfaceView,再引用服务端的AIDL文件,通过AIDL绑定服务端的MyService,绑定成功后即可传入Surface给服务端,需要注意只有再Surface创建成功才可传给服务端。客户端代码如下:

    private SurfaceView mSurfaceView;
    private boolean mIsSurfaceCreated;
    private boolean mSurfaceAdd;
    private ISurfaceInterface mSurfaceInterface;
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mSurfaceInterface = ISurfaceInterface.Stub.asInterface(service);
            if (mSurfaceInterface != null && mIsSurfaceCreated && !mSurfaceAdd) {
                try {
                    mSurfaceInterface.addSurfaceWithSize(mSurfaceView.getHolder().getSurface(), 300, 300);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mSurfaceAdd = false;
            if (mSurfaceInterface != null) {
                try {
                    mSurfaceInterface.removeSurface(mSurfaceView.getHolder().getSurface());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
                mSurfaceInterface = null;
            }

        }
    };
    
    private void init() {
        mSurfaceView = findViewById(R.id.surface_view);
        mSurfaceView.getHolder().addCallback(this);
        Button btn1 = findViewById(R.id.btn_test1);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mSurfaceInterface != null) {
                    try {
                        mSurfaceInterface.start();
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        Button btn2 = findViewById(R.id.btn_test2);
        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mSurfaceInterface != null) {
                    try {
                        mSurfaceInterface.stop();
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        //绑定服务端的MyService服务
        Intent intent = new Intent("com.example.surfaceviewtest.action");
        intent.setPackage("com.example.surfaceviewtest");
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mIsSurfaceCreated = true;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.d(TAG, "surfaceChanged:" + width);
        if (mSurfaceInterface != null && !mSurfaceAdd) {
            try {
                mSurfaceInterface.addSurfaceWithSize(mSurfaceView.getHolder().getSurface(), width, height);
                mSurfaceAdd = true;
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsSurfaceCreated = false;
    }

客户端展示效果如下,点击开始时开始则服务端渲染Surface,停止时则服务端停止渲染。
在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

言并肃

感谢大哥支持!您的鼓励是我动力

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

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

打赏作者

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

抵扣说明:

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

余额充值