1.TaskView是什么?
TaskView是谷歌整合安卓多任务多窗口下交互重新重构的独立出来的module,本身继承自ServiceView,TaskView的相关概念性的东西参考TaskView简述 ,安卓原生代码中是没有该控件的,如果需要查看,请看源码,谷歌源码TaskView 源码 ,这里只给出TaskView的代码,相关联的源码,请看源码,如果想要使用TaskView需要自己去编译frameWork的源码,打包一个aar,或者jar出来使用,否则无法直接使用。
2.TaksView如何使用
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.zeekr.avatar.demo1;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
import android.annotation.UiContext;
import android.app.ActivityTaskManager;
import android.app.TaskInfo;
import android.content.Context;
import android.util.Slog;
import android.window.TaskAppearedInfo;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.TaskView;
import com.android.wm.shell.TaskViewFactory;
import com.android.wm.shell.TaskViewFactoryController;
import com.android.wm.shell.common.HandlerExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
import com.android.wm.shell.startingsurface.StartingWindowController;
import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
public final class TaskViewManager {
private static final boolean DBG = true;
private static final String TAG = "TaskViewManager";
private final Context mContext;
private final HandlerExecutor mExecutor;
private final TaskViewFactory mTaskViewFactory;
private final ShellTaskOrganizer mTaskOrganizer;
public TaskViewManager(@UiContext Context context, HandlerExecutor handlerExecutor) {
mContext = context;
mExecutor = handlerExecutor;
mTaskOrganizer = new ShellTaskOrganizer(mExecutor, mContext);
mTaskViewFactory = initWmShell();
if (DBG) Slog.d(TAG, "TaskViewManager.create");
}
private TaskViewFactory initWmShell() {
TransactionPool transactionPool = new TransactionPool();
SyncTransactionQueue syncQueue = new SyncTransactionQueue(transactionPool, mExecutor);
FullscreenTaskListener fullscreenTaskListener = new FullscreenTaskListener(syncQueue,
Optional.empty());
mTaskOrganizer.addListenerForType(fullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
// StartingWindowController startingController =
// new StartingWindowController(mContext, mExecutor,
// new PhoneStartingWindowTypeAlgorithm(), new IconProvider(mContext),
// transactionPool);
// mTaskOrganizer.initStartingWindow(startingController);
List<TaskAppearedInfo> taskAppearedInfos = mTaskOrganizer.registerOrganizer();
// cleanUpExistingTaskViewTasks(taskAppearedInfos);
return new TaskViewFactoryController(mTaskOrganizer, mExecutor, syncQueue)
.asTaskViewFactory();
}
void release() {
if (DBG) Slog.d(TAG, "TaskViewManager.release");
mTaskOrganizer.unregisterOrganizer();
}
void createTaskView(Consumer<TaskView> onCreate) {
mTaskViewFactory.create(mContext, mExecutor, onCreate);
}
private static void cleanUpExistingTaskViewTasks(List<TaskAppearedInfo> taskAppearedInfos) {
ActivityTaskManager atm = ActivityTaskManager.getInstance();
for (TaskAppearedInfo taskAppearedInfo : taskAppearedInfos) {
TaskInfo taskInfo = taskAppearedInfo.getTaskInfo();
// Only TaskView tasks have WINDOWING_MODE_MULTI_WINDOW.
if (taskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) {
if (DBG) Slog.d(TAG, "Found the dangling task, removing: " + taskInfo.taskId);
atm.removeTask(taskInfo.taskId);
}
}
}
}
// Setting as trusted overlay to let touches pass through. getWindow().addPrivateFlags(PRIVATE_FLAG_TRUSTED_OVERLAY); // To pass touches to the underneath task. getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);在activity中需要加上这个flag
注意:xml中无法直接使用taskview作为布局,需要自己自定义封装下,或者代码给个容器动态添加:
使用代码添加TaskView:
mTaskViewManager = new TaskViewManager(this, new HandlerExecutor(new Handler())); mTaskViewManager.createTaskView(taskView -> { //创建的taskview taskView.setListener(getMainExecutor(), mTaskViewListener); left.addView(taskView); mTaskView = taskView; });
//taskview的监听器
private final TaskView.Listener mTaskViewListener = new TaskView.Listener() { @Override public void onInitialized() { Log.d(TAG, "onInitialized()"); mTaskViewReady = true; //初始化后启动别的应用在该容器中展示,下面taskView启动的方式如下 start3DInTaskView(); } @Override public void onReleased() { Log.d(TAG, "onReleased()"); mTaskViewReady = false; } @Override public void onTaskCreated(int taskId, ComponentName name) { Log.d(TAG, "mTaskViewListener onTaskCreated: taskId=" + taskId); mTaskViewTaskId = taskId; if (isResumed()) { maybeBringEmbeddedTaskToForeground(); } } @Override public void onTaskRemovalStarted(int taskId) { Log.d(TAG, "onTaskRemovalStarted: taskId=" + taskId); mTaskViewTaskId = INVALID_TASK_ID; // Don't restart the crashed Maps automatically, because it hinders lots of MultiXXX // CTS tests which cleans up all tasks but Home, then monitor Activity state // changes. If it restarts Maps, which causes unexpected Activity state changes. } };
private void start3DInTaskView() { if (mTaskView == null || !mTaskViewReady) { return; } // If we happen to be be resurfaced into a multi display mode we skip launching content // in the activity view as we will get recreated anyway. if (isInMultiWindowMode() || isInPictureInPictureMode()) { return; } // Don't start Maps when the display is off for ActivityVisibilityTests. if (getDisplay().getState() != Display.STATE_ON) { return; } try { Log.w(TAG, "start3DInTaskView"); ActivityOptions options = ActivityOptions.makeCustomAnimation(this, /* enterResId= */ 0, /* exitResId= */ 0); Intent mapIntent = new Intent(); ComponentName componentName = new ComponentName("com.test.carlauncher3d","com.test.launcher.activity.CarLauncher"); mapIntent.setComponent(componentName); mapIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mTaskView.startActivity( PendingIntent.getActivity(this, /* requestCode= */ 0, mapIntent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT), /* fillInIntent= */ null, options, null /* launchBounds */); } catch (ActivityNotFoundException e) { Log.w(TAG, "Maps activity not found", e); } }
3.TaskView遇到的坑
1.如果分屏的应用如启动两个应用按照权重占比,互相不叠加在一起,点触摸击事件都可响应,例如左边启动QQ了,右边启动的是微信,二者窗口都可操作
2.如果叠加在一起,那就需要设置点击的区域了 使用taskView.setObscuredTouchRect指定区域,动态设置。
3.有出现三个view叠加,出现黑屏白屏的情况,不要同时启动多个应用,坐下延时处理