Android12 车载开发TaskView实现分屏

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叠加,出现黑屏白屏的情况,不要同时启动多个应用,坐下延时处理

                

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值