栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android10.0 最近任务

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android10.0 最近任务

最近有个launcher项目,有个修改最近任务的功能。

改成普通安卓手机,按任务栏显示最近打开的任务界面。

 

可以上下滑动层叠卡片式布局,

卡片式布局可以参考我另一篇文章:Android7最近任务栏UI(DeckView)

一.获取最近任务
taskListLoader.loadTaskList(tasks -> {
            try {
                Collections.reverse(tasks);
                for (Task task : tasks) {
                    AppBeanInfo appIconInfo = new AppBeanInfo();
                    task.titleDescription = task.titleDescription;
                    ComponentName component = task.getTopComponent();
                    String pkgName = component.getPackageName();
                    if (pkgName.equals("com.lzui.launcher")) continue;
                    Log.i("RecentsActivity 1", pkgName + "-" + task.getTopComponent());
                    try {
                        ApplicationInfo applicationInfo = pm.getApplicationInfo(pkgName, 0);
                        String applicationName = (String) pm.getApplicationLabel(applicationInfo);
                        Drawable icon = pm.getApplicationIcon(applicationInfo);
                        appIconInfo.setAppName(applicationName);
                        appIconInfo.setDrawable(icon);
                        appIconInfo.setPackageName(pkgName);
                        appIconInfo.setTask(task);
                        appIconInfoList.add(appIconInfo);
                        Log.i("RecentsActivity 1", applicationName);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                mDeckView.notifyDataSetChanged();
                if(appIconInfoList.size() != 0){
                    mDeckView.scrollToChild(appIconInfoList.size() - 2);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
public void loadTaskList(@Nullable Consumer> onLoadedCallback) {
        if (!needsToLoad()) {
            if (onLoadedCallback != null) {
                onLoadedCallback.accept(mTaskList);
            }
            return;
        }
        // TODO: Look into error checking / more robust handling for when things go wrong.
        mTaskListChangeId = mRecentsModel.getTasks(loadedTasks -> {
            ArrayList tasks = new ArrayList<>(loadedTasks);
            // Reverse tasks to put most recent at the bottom of the view
            Collections.reverse(tasks);
            // Load task content
            for (Task task : tasks) {
                int loadedPos = mTaskList.indexOf(task);
                if (loadedPos == -1) {
                    continue;
                }
                Task loadedTask = mTaskList.get(loadedPos);
                task.icon = loadedTask.icon;
                task.titleDescription = loadedTask.titleDescription;
                task.thumbnail = loadedTask.thumbnail;
            }
            mTaskList = tasks;
            onLoadedCallback.accept(tasks);
        });
    }
TaskListLoader在源码

public final class TaskListLoader {

    private final RecentsModel mRecentsModel;

    private ArrayList mTaskList = new ArrayList<>();
    private int mTaskListChangeId;

    public TaskListLoader(Context context) {
        mRecentsModel = RecentsModel.INSTANCE.get(context);
    }

    
    public List getCurrentTaskList() {
        return Collections.unmodifiableList(mTaskList);
    }

    
    public boolean needsToLoad() {
        return !mRecentsModel.isTaskListValid(mTaskListChangeId);
    }

    
    public void loadTaskList(@Nullable Consumer> onLoadedCallback) {
        if (!needsToLoad()) {
            if (onLoadedCallback != null) {
                onLoadedCallback.accept(mTaskList);
            }
            return;
        }
        // TODO: Look into error checking / more robust handling for when things go wrong.
        mTaskListChangeId = mRecentsModel.getTasks(loadedTasks -> {
            ArrayList tasks = new ArrayList<>(loadedTasks);
            // Reverse tasks to put most recent at the bottom of the view
            Collections.reverse(tasks);
            // Load task content
            for (Task task : tasks) {
                int loadedPos = mTaskList.indexOf(task);
                if (loadedPos == -1) {
                    continue;
                }
                Task loadedTask = mTaskList.get(loadedPos);
                task.icon = loadedTask.icon;
                task.titleDescription = loadedTask.titleDescription;
                task.thumbnail = loadedTask.thumbnail;
            }
            mTaskList = tasks;
            onLoadedCallback.accept(tasks);
        });
    }

    
    public void loadTaskIconAndLabel(Task task, @Nullable Runnable onLoadedCallback) {
        mRecentsModel.getIconCache().updateIconInBackground(task,
                loadedTask -> onLoadedCallback.run());
    }

    
    public void loadTaskThumbnail(Task task, @Nullable Runnable onLoadedCallback) {
        mRecentsModel.getThumbnailCache().updateThumbnailInBackground(task,
                thumbnail -> onLoadedCallback.run());
    }

    
    public void removeTask(Task task) {
        mTaskList.remove(task);
    }

    
    public void clearAllTasks() {
        mTaskList.clear();
    }
}
loadTaskList:加载最近任务列表
loadTaskThumbnail:加载最近任务缩略图
removeTask:移除最近任务列表
clearAllTasks:清楚全部最近任务
二、获取最近任务缩略图
private void loadViewDataInternal(final WeakReference weakView, final AppBeanInfo appBeanInfo) {
        if (Build.VERSION.SDK_INT >= 26) {
            taskListLoader.loadTaskThumbnail(appBeanInfo.getTask(), () -> {
                weakView.get().onDataLoaded(appBeanInfo, appBeanInfo.getTask().thumbnail.thumbnail,
                        appBeanInfo.getDrawable(), appBeanInfo.getAppName(), Color.DKGRAY);
            });
        }
    }


    DeckView.Callback deckViewCallback = new DeckView.Callback() {
        @Override
        public ArrayList getData() {
            return appIconInfoList;
        }

        @Override
        public void loadViewData(WeakReference dcv, AppBeanInfo item) {
            llNullContent.setVisibility(View.GONE);
            llCleanAll.setVisibility(View.VISIBLE);
            loadViewDataInternal(dcv, item);
        }

        @Override
        public void unloadViewData(AppBeanInfo item) {

        }

        @Override
        public void onViewDismissed(AppBeanInfo item) {
            ActivityManagerWrapper.getInstance().removeTask(item.getTask().key.id);
            taskListLoader.removeTask(item.getTask());
            appIconInfoList.remove(item);
            mDeckView.notifyDataSetChanged();
        }

        @Override
        public void onItemClick(AppBeanInfo item) {
            // 进入此程序
            try {
                Intent intent = new Intent();
                //通过包名启动
                PackageManager packageManager = getPackageManager();
                intent = packageManager.getLaunchIntentForPackage(item.getPackageName());
                if (null != intent) {
                    startActivity(intent);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onNoViewsToDeck() {
            llNullContent.setVisibility(View.VISIBLE);
            llCleanAll.setVisibility(View.GONE);
        }

        @Override
        public void onFinsh() {
            RecentsActivity.this.finish();
        }
    };
三、清除全部任务
            ActivityManagerWrapper.getInstance().removeAllRecentTasks();
            taskListLoader.clearAllTasks();
            appIconInfoList.clear();
            appIconInfoList = null;
            mDeckView = null;

单个清除

  ActivityManagerWrapper.getInstance().removeTask(item.getTask().key.id);
            taskListLoader.removeTask(item.getTask());
            appIconInfoList.remove(item);
四、拿出10.0的源码修改成launcher用的。

 代码有点多,我整理成资源,供大家下载,又不懂的欢迎留言。

主要代码类:

RecentsModel
public class RecentsModel extends TaskStackChangeListener {

    private static final String TAG = "RecentsModel";

    // We do not need any synchronization for this variable as its only written on UI thread.
    public static final MainThreadInitializedObject INSTANCE =
            new MainThreadInitializedObject<>(c -> new RecentsModel(c));

    private final List mThumbnailChangeListeners = new ArrayList<>();
    private final Context mContext;

    private ISystemUiProxy mSystemUiProxy;

    private final RecentTasksList mTaskList;
    private final TaskIconCache mIconCache;
    private final TaskThumbnailCache mThumbnailCache;

    private RecentsModel(Context context) {
        mContext = context;
        HandlerThread loaderThread = new HandlerThread("TaskThumbnailIconCache",
                Process.THREAD_PRIORITY_BACKGROUND);
        loaderThread.start();
        mTaskList = new RecentTasksList(context);
        mIconCache = new TaskIconCache(context, loaderThread.getLooper());
        mThumbnailCache = new TaskThumbnailCache(context, loaderThread.getLooper());
        ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
    }

    public TaskIconCache getIconCache() {
        return mIconCache;
    }

    public TaskThumbnailCache getThumbnailCache() {
        return mThumbnailCache;
    }

    
    public int getTasks(Consumer> callback) {
        return mTaskList.getTasks(false , callback);
    }

    
    public static int getRunningTaskId() {
        ActivityManager.RunningTaskInfo runningTask =
                ActivityManagerWrapper.getInstance().getRunningTask();
        return runningTask != null ? runningTask.id : -1;
    }

    
    public boolean isTaskListValid(int changeId) {
        return mTaskList.isTaskListValid(changeId);
    }

    
    public void findTaskWithId(int taskId, Consumer callback) {
        mTaskList.getTasks(true , (tasks) -> {
            for (Task task : tasks) {
                if (task.key.id == taskId) {
                    callback.accept(task.key);
                    return;
                }
            }
            callback.accept(null);
        });
    }

    @Override
    public void onTaskStackChangedBackground() {
        if (!mThumbnailCache.isPreloadingEnabled()) {
            // Skip if we aren't preloading
            return;
        }

        int currentUserId = Process.myUserHandle().getIdentifier();
        if (!TaskUtils.checkCurrentOrManagedUserId(currentUserId, mContext)) {
            // Skip if we are not the current user
            return;
        }

        // Keep the cache up to date with the latest thumbnails
        int runningTaskId = RecentsModel.getRunningTaskId();
        mTaskList.getTaskKeys(mThumbnailCache.getCacheSize(), tasks -> {
            for (Task task : tasks) {
                if (task.key.id == runningTaskId) {
                    // Skip the running task, it's not going to have an up-to-date snapshot by the
                    // time the user next enters overview
                    continue;
                }
                mThumbnailCache.updateThumbnailInCache(task);
            }
        });
    }

    @Override
    public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
        mThumbnailCache.updateTaskSnapShot(taskId, snapshot);

        for (int i = mThumbnailChangeListeners.size() - 1; i >= 0; i--) {
            Task task = mThumbnailChangeListeners.get(i).onTaskThumbnailChanged(taskId, snapshot);
            if (task != null) {
                task.thumbnail = snapshot;
            }
        }
    }

    @Override
    public void onTaskRemoved(int taskId) {
        Task.TaskKey dummyKey = new Task.TaskKey(taskId, 0, null, null, 0, 0);
        mThumbnailCache.remove(dummyKey);
    }

    public void setSystemUiProxy(ISystemUiProxy systemUiProxy) {
        mSystemUiProxy = systemUiProxy;
    }

    public ISystemUiProxy getSystemUiProxy() {
        return mSystemUiProxy;
    }

    public void onTrimMemory(int level) {
        if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
            mThumbnailCache.getHighResLoadingState().setVisible(false);
        }
        if (level == ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) {
            // Clear everything once we reach a low-mem situation
            mThumbnailCache.clear();
            mIconCache.clear();
        }
    }

    public void onOverviewShown(boolean fromHome, String tag) {
        if (mSystemUiProxy == null) {
            return;
        }
        try {
            mSystemUiProxy.onOverviewShown(fromHome);
        } catch (RemoteException e) {
            Log.w(tag,
                    "Failed to notify SysUI of overview shown from " + (fromHome ? "home" : "app")
                            + ": ", e);
        }
    }

    public void addThumbnailChangeListener(TaskThumbnailChangeListener listener) {
        mThumbnailChangeListeners.add(listener);
    }

    public void removeThumbnailChangeListener(TaskThumbnailChangeListener listener) {
        mThumbnailChangeListeners.remove(listener);
    }

    public interface TaskThumbnailChangeListener {

        Task onTaskThumbnailChanged(int taskId, ThumbnailData thumbnailData);
    }

    public RecentTasksList getmTaskList() {
        return mTaskList;
    }
}
TaskThumbnailCache
public class TaskThumbnailCache {

    private final Handler mBackgroundHandler;
    private final MainThreadExecutor mMainThreadExecutor;

    private final int mCacheSize;
    private final ThumbnailCache mCache;
    private final HighResLoadingState mHighResLoadingState;

    public static class HighResLoadingState {
        private boolean mIsLowRamDevice;
        private boolean mVisible;
        private boolean mFlingingFast;
        private boolean mHighResLoadingEnabled;
        private ArrayList mCallbacks = new ArrayList<>();

        public interface HighResLoadingStateChangedCallback {
            void onHighResLoadingStateChanged(boolean enabled);
        }

        private HighResLoadingState(Context context) {
            ActivityManager activityManager =
                    (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            mIsLowRamDevice = activityManager.isLowRamDevice();
        }

        public void addCallback(HighResLoadingStateChangedCallback callback) {
            mCallbacks.add(callback);
        }

        public void removeCallback(HighResLoadingStateChangedCallback callback) {
            mCallbacks.remove(callback);
        }

        public void setVisible(boolean visible) {
            mVisible = visible;
            updateState();
        }

        public void setFlingingFast(boolean flingingFast) {
            mFlingingFast = flingingFast;
            updateState();
        }

        public boolean isEnabled() {
            return mHighResLoadingEnabled;
        }

        private void updateState() {
            boolean prevState = mHighResLoadingEnabled;
            mHighResLoadingEnabled = !mIsLowRamDevice && mVisible && !mFlingingFast;
            if (prevState != mHighResLoadingEnabled) {
                for (int i = mCallbacks.size() - 1; i >= 0; i--) {
                    mCallbacks.get(i).onHighResLoadingStateChanged(mHighResLoadingEnabled);
                }
            }
        }
    }

    public TaskThumbnailCache(Context context, Looper backgroundLooper) {
        mBackgroundHandler = new Handler(backgroundLooper);
        mMainThreadExecutor = new MainThreadExecutor();
        mHighResLoadingState = new HighResLoadingState(context);

        Resources res = context.getResources();
        mCacheSize = 3;
        mCache = new ThumbnailCache(mCacheSize);
    }

    
    public void updateThumbnailInCache(Task task) {
        Preconditions.assertUIThread();
        // Fetch the thumbnail for this task and put it in the cache
        if (task.thumbnail == null) {
            updateThumbnailInBackground(task.key, true ,
                    t -> task.thumbnail = t);
        }
    }

    
    public void updateTaskSnapShot(int taskId, ThumbnailData thumbnail) {
        Preconditions.assertUIThread();
        mCache.updateIfAlreadyInCache(taskId, thumbnail);
    }

    

    public ThumbnailLoadRequest updateThumbnailInBackground(
            Task task, Consumer callback) {
        Preconditions.assertUIThread();

        boolean reducedResolution = !mHighResLoadingState.isEnabled();
        if (task.thumbnail != null && (!task.thumbnail.reducedResolution || reducedResolution)) {
            // Nothing to load, the thumbnail is already high-resolution or matches what the
            // request, so just callback
            callback.accept(task.thumbnail);
            return null;
        }


        return updateThumbnailInBackground(task.key, !mHighResLoadingState.isEnabled(), t -> {
            task.thumbnail = t;
            callback.accept(t);
        });
    }

    private ThumbnailLoadRequest updateThumbnailInBackground(TaskKey key, boolean reducedResolution,
            Consumer callback) {
        Preconditions.assertUIThread();

        ThumbnailData cachedThumbnail = mCache.getAndInvalidateIfModified(key);
        if (cachedThumbnail != null && (!cachedThumbnail.reducedResolution || reducedResolution)) {
            // Already cached, lets use that thumbnail
            callback.accept(cachedThumbnail);
            return null;
        }

        ThumbnailLoadRequest request = new ThumbnailLoadRequest(mBackgroundHandler,
                reducedResolution) {
            @Override
            public void run() {
                ThumbnailData thumbnail = ActivityManagerWrapper.getInstance().getTaskThumbnail(
                        key.id, reducedResolution);
                if (isCanceled()) {
                    // We don't call back to the provided callback in this case
                    return;
                }
                mMainThreadExecutor.execute(() -> {
                    mCache.put(key, thumbnail);
                    callback.accept(thumbnail);
                    onEnd();
                });
            }
        };
        Utilities.postAsyncCallback(mBackgroundHandler, request);
        return request;
    }

    
    public void clear() {
        mCache.evictAll();
    }

    
    public void remove(TaskKey key) {
        mCache.remove(key);
    }

    
    public int getCacheSize() {
        return mCacheSize;
    }

    
    public HighResLoadingState getHighResLoadingState() {
        return mHighResLoadingState;
    }

    
    public boolean isPreloadingEnabled() {
        return !mHighResLoadingState.mIsLowRamDevice && mHighResLoadingState.mVisible;
    }

    public static abstract class ThumbnailLoadRequest extends HandlerRunnable {
        public final boolean reducedResolution;

        ThumbnailLoadRequest(Handler handler, boolean reducedResolution) {
            super(handler, null);
            this.reducedResolution = reducedResolution;
        }
    }

    private static class ThumbnailCache extends TaskKeyLruCache {

        public ThumbnailCache(int cacheSize) {
            super(cacheSize);
        }

        
        public void updateIfAlreadyInCache(int taskId, ThumbnailData thumbnailData) {
            ThumbnailData oldData = getCacheEntry(taskId);
            if (oldData != null) {
                putCacheEntry(taskId, thumbnailData);
            }
        }
    }
}

还需要一个10.0的jar包,一起在资源里面了。

SystemUISharedLib.jar

10.0获取最近任务缩略图链接:10.0任务列表获取缩略图-Android文档类资源-CSDN下载

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/930500.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号