hi粉丝朋友们:
大家好!
b站免费视频教程讲解:
https://www.bilibili.com/video/BV1wj411o7A9/
前面的blog都是对于最新的android 13源码进行分析的CarLauncher的实现方案,已经知道CarLauncher使用是TaskView来装载新的地图Task,但是在android 12版本以前其实不是使用的TaskView的方案实现的,而是使用的ActivityView方案。
但是CarLauncher一样实现了CarLauncher的Activity进行内嵌另一个地图Activity,那么下面就有必要来了解一下
创建ActivityView
package/apps/Car/Launcher/src/com/android/car/carlauncher/CarLauncher.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//省略部分
//ActivityView直接在xml中已经定义好了,其实它就是个ViewGroup
mActivityView = findViewById(R.id.maps);
}
ActivityView的相关构造方法:
base/core/java/android/app/ActivityView.java
public ActivityView(
Context context, AttributeSet attrs, int defStyle, boolean singleTaskInstance) {
super(context, attrs, defStyle);
//创建对应的SurfaceView
mSurfaceView = new SurfaceView(context);
//添加到了ActivityView的容器
addView(mSurfaceView);
}
上面可以看出ActivityView就是个ViewGroup,构造方法里面构造了一个SurfaceView
接下来就是SurfaceView的surfaceCreated来触发:
private class SurfaceCallback implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
if (mVirtualDisplay == null) {
//初始化虚拟display
initVirtualDisplay(new SurfaceSession());
if (mVirtualDisplay != null && mActivityViewCallback != null) {
//回调onActivityViewReady,主要是触发startActivity
mActivityViewCallback.onActivityViewReady(ActivityView.this);
}
}
//省略
}
}
下面看看核心方法initVirtualDisplay:
private void initVirtualDisplay(SurfaceSession surfaceSession) {
//创建对应的display
mVirtualDisplay = displayManager.createVirtualDisplay(
DISPLAY_NAME + "@" + System.identityHashCode(this), width, height,
getBaseDisplayDensity(), null,
VIRTUAL_DISPLAY_FLAG_PUBLIC | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
| VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL);
//获取displayId
final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
//给surfaceiew的surfacecontrol多创建一个子surfacecontrol,专门装载新的display
mRootSurfaceControl = new SurfaceControl.Builder(surfaceSession)
.setContainerLayer()
.setParent(mSurfaceView.getSurfaceControl())
.setName(DISPLAY_NAME)
.build();
//把新的displayreparent到前面的mRootSurfaceControl
WindowManagerGlobal.getWindowSession().reparentDisplayContent(
getWindow(), mRootSurfaceControl, displayId);
//省略
mTmpTransaction.show(mRootSurfaceControl).apply();
mTaskStackListener = new TaskStackListenerImpl();
try {
mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
} catch (RemoteException e) {
Log.e(TAG, "Failed to register task stack listener", e);
}
}
上面已经准备好了对应的display了,下面一步就是启动这个display下面的相关Activity
private final ActivityView.StateCallback mActivityViewCallback =
new ActivityView.StateCallback() {
@Override
public void onActivityViewReady(ActivityView view) {
//启动Maps的Activity
startMapsInActivityView();
}
}
private void startMapsInActivityView() {
//实际上只是调用了mActivityView的startActivity
if (mActivityView != null) {
mActivityView.startActivity(getMapsIntent());
}
}
下面看看mActivityView.startActivity
public void startActivity(@NonNull Intent intent) {
//准备好对应的ActivityOption
final ActivityOptions options = prepareActivityOptions();
getContext().startActivity(intent, options.toBundle());
}
private ActivityOptions prepareActivityOptions() {
//这里其实只是获取了新displayId,然后setLaunchDisplayId给ActivityOption
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(mVirtualDisplay.getDisplay().getDisplayId());
return options;
}
上面ActivityOption设置setLaunchDisplayId完成后,那么Activity启动就是在新的display上面