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,停止时则服务端停止渲染。