Android14系统go版添加微件功能

2024-04-08 13:04

本文主要是介绍Android14系统go版添加微件功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一般normal版软件自带微件功能,但是go版没有这个功能,但是客户有时会要求也要加上这个微件功能,实现的方法修改如下:

1. frameworks/base

diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 24b3fdf64b0f..d805ff07871a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4191,7 +4191,7 @@<!-- True if the device requires AppWidgetService even if it does not havethe PackageManager.FEATURE_APP_WIDGETS feature -->
-    <bool name="config_enableAppWidgetService">false</bool>
+    <bool name="config_enableAppWidgetService">true</bool><!-- True if the device supports Sustained Performance Mode--><bool name="config_sustainedPerformanceModeSupported">false</bool>

2. frameworks/native

diff --git a/data/etc/go_handheld_core_hardware.xml b/data/etc/go_handheld_core_hardware.xml
index ee829728c8..23077cbc82 100644
--- a/data/etc/go_handheld_core_hardware.xml
+++ b/data/etc/go_handheld_core_hardware.xml
@@ -36,6 +36,7 @@<feature name="android.hardware.security.model.compatible" /><!-- basic system services -->
+    <feature name="android.software.app_widgets" /><feature name="android.software.telecom" /><feature name="android.software.backup" /><feature name="android.software.home_screen" />

3. packages/apps/Launcher3

diff --git a/go/src/com/android/launcher3/model/LauncherBinder.java b/go/src/com/android/launcher3/model/LauncherBinder.java
index 437d8caf94..66d9db0c67 100644
--- a/go/src/com/android/launcher3/model/LauncherBinder.java
+++ b/go/src/com/android/launcher3/model/LauncherBinder.java
@@ -20,6 +20,11 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;import com.android.launcher3.LauncherAppState;import com.android.launcher3.model.BgDataModel.Callbacks;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.widget.model.WidgetsListBaseEntry;
+
+import java.util.HashMap;
+import java.util.List;/*** Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects.
@@ -33,9 +38,17 @@ public class LauncherBinder extends BaseLauncherBinder {@Overridepublic void bindDeepShortcuts() {
+        final HashMap<ComponentKey, Integer> shortcutMapCopy;
+        synchronized (mBgDataModel) {
+            shortcutMapCopy = new HashMap<>(mBgDataModel.deepShortcutMap);
+        }
+        executeCallbacksTask(c -> c.bindDeepShortcutMap(shortcutMapCopy), mUiExecutor);}@Overridepublic void bindWidgets() {
+        final List<WidgetsListBaseEntry> widgets =
+                mBgDataModel.widgetsModel.getWidgetsListForPicker(mApp.getContext());
+        executeCallbacksTask(c -> c.bindAllWidgets(widgets), mUiExecutor);}}
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
index 1aa5d03f6d..75df5e5787 100644
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ b/go/src/com/android/launcher3/model/WidgetsModel.java
@@ -16,23 +16,57 @@package com.android.launcher3.model;+import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_HIDE_FROM_PICKER;
+
+import static com.android.launcher3.pm.ShortcutConfigActivityInfo.queryList;
+import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
+
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.mapping;
+import static java.util.stream.Collectors.toList;
+
+import android.appwidget.AppWidgetProviderInfo;import android.content.ComponentName;import android.content.Context;
+import android.content.pm.PackageManager;import android.os.UserHandle;
+import android.util.Log;
+import android.util.Pair;import androidx.annotation.Nullable;
+import androidx.collection.ArrayMap;+import com.android.launcher3.AppFilter;
+import com.android.launcher3.InvariantDeviceProfile;import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.AlphabeticIndexCompat;
+import com.android.launcher3.config.FeatureFlags;import com.android.launcher3.icons.ComponentWithLabelAndIcon;
+import com.android.launcher3.icons.IconCache;import com.android.launcher3.model.data.PackageItemInfo;
+import com.android.launcher3.pm.ShortcutConfigActivityInfo;
+import com.android.launcher3.util.IntSet;import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.util.Preconditions;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.widget.WidgetManagerHelper;
+import com.android.launcher3.widget.WidgetSections;import com.android.launcher3.widget.model.WidgetsListBaseEntry;
+import com.android.launcher3.widget.model.WidgetsListContentEntry;
+import com.android.launcher3.widget.model.WidgetsListHeaderEntry;import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;import java.util.List;import java.util.Map;
+import java.util.Map.Entry;import java.util.Set;
+import java.util.function.Predicate;/*** Widgets data model that is used by the adapters of the widget views and controllers.
@@ -42,10 +76,14 @@ import java.util.Set;public class WidgetsModel {// True is the widget support is disabled.
-    public static final boolean GO_DISABLE_WIDGETS = true;
-    public static final boolean GO_DISABLE_NOTIFICATION_DOTS = true;
+    public static final boolean GO_DISABLE_WIDGETS = false;
+    public static final boolean GO_DISABLE_NOTIFICATION_DOTS = false;
+
+    private static final String TAG = "WidgetsModel";
+    private static final boolean DEBUG = false;-    private static final ArrayList<WidgetsListBaseEntry> EMPTY_WIDGET_LIST = new ArrayList<>();
+    /* Map of widgets and shortcuts that are tracked per package. */
+    private final Map<PackageItemInfo, List<WidgetItem>> mWidgetsList = new HashMap<>();/*** Returns a list of {@link WidgetsListBaseEntry}. All {@link WidgetItem} in a single row are
@@ -56,36 +94,246 @@ public class WidgetsModel {* @see com.android.launcher3.widget.picker.WidgetsListAdapter#setWidgets(List)*/public synchronized ArrayList<WidgetsListBaseEntry> getWidgetsListForPicker(Context context) {
-        return EMPTY_WIDGET_LIST;
+        ArrayList<WidgetsListBaseEntry> result = new ArrayList<>();
+        AlphabeticIndexCompat indexer = new AlphabeticIndexCompat(context);
+
+        for (Map.Entry<PackageItemInfo, List<WidgetItem>> entry : mWidgetsList.entrySet()) {
+            PackageItemInfo pkgItem = entry.getKey();
+            List<WidgetItem> widgetItems = entry.getValue();
+            String sectionName = (pkgItem.title == null) ? "" :
+                    indexer.computeSectionName(pkgItem.title);
+            result.add(WidgetsListHeaderEntry.create(pkgItem, sectionName, widgetItems));
+            result.add(new WidgetsListContentEntry(pkgItem, sectionName, widgetItems));
+        }
+        return result;}/** Returns a mapping of packages to their widgets without static shortcuts. */public synchronized Map<PackageUserKey, List<WidgetItem>> getAllWidgetsWithoutShortcuts() {
-        return Map.of();
+        Map<PackageUserKey, List<WidgetItem>> packagesToWidgets = new HashMap<>();
+        mWidgetsList.forEach((packageItemInfo, widgetsAndShortcuts) -> {
+            List<WidgetItem> widgets = widgetsAndShortcuts.stream()
+                        .filter(item -> item.widgetInfo != null)
+                        .collect(toList());
+            if (widgets.size() > 0) {
+                packagesToWidgets.put(
+                        new PackageUserKey(packageItemInfo.packageName, packageItemInfo.user),
+                        widgets);
+            }
+        });
+        return packagesToWidgets;}/*** @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise*                    only widgets and shortcuts associated with the package/user are.*/
-    public List<ComponentWithLabelAndIcon> update(LauncherAppState app,
-            @Nullable PackageUserKey packageUser) {
-        return Collections.emptyList();
+    public List<ComponentWithLabelAndIcon> update(
+            LauncherAppState app, @Nullable PackageUserKey packageUser) {
+        Preconditions.assertWorkerThread();
+
+        Context context = app.getContext();
+        final ArrayList<WidgetItem> widgetsAndShortcuts = new ArrayList<>();
+        List<ComponentWithLabelAndIcon> updatedItems = new ArrayList<>();
+        try {
+            InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
+            PackageManager pm = app.getContext().getPackageManager();
+
+            // Widgets
+            WidgetManagerHelper widgetManager = new WidgetManagerHelper(context);
+            for (AppWidgetProviderInfo widgetInfo : widgetManager.getAllProviders(packageUser)) {
+                LauncherAppWidgetProviderInfo launcherWidgetInfo =
+                        LauncherAppWidgetProviderInfo.fromProviderInfo(context, widgetInfo);
+
+                widgetsAndShortcuts.add(new WidgetItem(
+                        launcherWidgetInfo, idp, app.getIconCache(), app.getContext()));
+                updatedItems.add(launcherWidgetInfo);
+            }
+
+            // Shortcuts
+            for (ShortcutConfigActivityInfo info :
+                    queryList(context, packageUser)) {
+                widgetsAndShortcuts.add(new WidgetItem(info, app.getIconCache(), pm));
+                updatedItems.add(info);
+            }
+            setWidgetsAndShortcuts(widgetsAndShortcuts, app, packageUser);
+        } catch (Exception e) {
+            if (!FeatureFlags.IS_STUDIO_BUILD && Utilities.isBinderSizeError(e)) {
+                // the returned value may be incomplete and will not be refreshed until the next
+                // time Launcher starts.
+                // TODO: after figuring out a repro step, introduce a dirty bit to check when
+                // onResume is called to refresh the widget provider list.
+            } else {
+                throw e;
+            }
+        }
+
+        return updatedItems;}+    private synchronized void setWidgetsAndShortcuts(ArrayList<WidgetItem> rawWidgetsShortcuts,
+            LauncherAppState app, @Nullable PackageUserKey packageUser) {
+        if (DEBUG) {
+            Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + rawWidgetsShortcuts.size());
+        }
+
+        // Temporary cache for {@link PackageItemInfos} to avoid having to go through
+        // {@link mPackageItemInfos} to locate the key to be used for {@link #mWidgetsList}
+        PackageItemInfoCache packageItemInfoCache = new PackageItemInfoCache();
+
+        if (packageUser == null) {
+            // Clear the list if this is an update on all widgets and shortcuts.
+            mWidgetsList.clear();
+        } else {
+            // Otherwise, only clear the widgets and shortcuts for the changed package.
+            mWidgetsList.remove(packageItemInfoCache.getOrCreate(packageUser));
+        }
+
+        // add and update.
+        mWidgetsList.putAll(rawWidgetsShortcuts.stream()
+                .filter(new WidgetValidityCheck(app))
+                .flatMap(widgetItem -> getPackageUserKeys(app.getContext(), widgetItem).stream()
+                        .map(key -> new Pair<>(packageItemInfoCache.getOrCreate(key), widgetItem)))
+                .collect(groupingBy(pair -> pair.first, mapping(pair -> pair.second, toList()))));
+
+        // Update each package entry
+        IconCache iconCache = app.getIconCache();
+        for (PackageItemInfo p : packageItemInfoCache.values()) {
+            iconCache.getTitleAndIconForApp(p, true /* userLowResIcon */);
+        }
+    }public void onPackageIconsUpdated(Set<String> packageNames, UserHandle user,LauncherAppState app) {
+        for (Entry<PackageItemInfo, List<WidgetItem>> entry : mWidgetsList.entrySet()) {
+            if (packageNames.contains(entry.getKey().packageName)) {
+                List<WidgetItem> items = entry.getValue();
+                int count = items.size();
+                for (int i = 0; i < count; i++) {
+                    WidgetItem item = items.get(i);
+                    if (item.user.equals(user)) {
+                        if (item.activityInfo != null) {
+                            items.set(i, new WidgetItem(item.activityInfo, app.getIconCache(),
+                                    app.getContext().getPackageManager()));
+                        } else {
+                            items.set(i, new WidgetItem(item.widgetInfo,
+                                    app.getInvariantDeviceProfile(), app.getIconCache(),
+                                    app.getContext()));
+                        }
+                    }
+                }
+            }
+        }}public WidgetItem getWidgetProviderInfoByProviderName(ComponentName providerName, UserHandle user) {
+        List<WidgetItem> widgetsList = mWidgetsList.get(
+                new PackageItemInfo(providerName.getPackageName(), user));
+        if (widgetsList == null) {
+            return null;
+        }
+
+        for (WidgetItem item : widgetsList) {
+            if (item.componentName.equals(providerName)) {
+                return item;
+            }
+        }return null;}/** Returns {@link PackageItemInfo} of a pending widget. */
-    public static PackageItemInfo newPendingItemInfo(
-            Context context, ComponentName provider, UserHandle userHandle) {
-        return new PackageItemInfo(provider.getPackageName(), userHandle);
+    public static PackageItemInfo newPendingItemInfo(Context context, ComponentName provider,
+            UserHandle user) {
+        Map<ComponentName, IntSet> widgetsToCategories =
+                WidgetSections.getWidgetsToCategory(context);
+        if (widgetsToCategories.containsKey(provider)) {
+            Iterator<Integer> categoriesIterator = widgetsToCategories.get(provider).iterator();
+            int firstCategory = NO_CATEGORY;
+            while (categoriesIterator.hasNext() && firstCategory == NO_CATEGORY) {
+                firstCategory = categoriesIterator.next();
+            }
+            return new PackageItemInfo(provider.getPackageName(), firstCategory, user);
+        }
+        return new PackageItemInfo(provider.getPackageName(), user);
+    }
+
+    private List<PackageUserKey> getPackageUserKeys(Context context, WidgetItem item) {
+        Map<ComponentName, IntSet> widgetsToCategories =
+                WidgetSections.getWidgetsToCategory(context);
+        IntSet categories = widgetsToCategories.get(item.componentName);
+        if (categories == null || categories.isEmpty()) {
+            return Arrays.asList(
+                    new PackageUserKey(item.componentName.getPackageName(), item.user));
+        }
+        List<PackageUserKey> packageUserKeys = new ArrayList<>();
+        categories.forEach(category -> {
+            if (category == NO_CATEGORY) {
+                packageUserKeys.add(
+                        new PackageUserKey(item.componentName.getPackageName(),
+                                item.user));
+            } else {
+                packageUserKeys.add(new PackageUserKey(category, item.user));
+            }
+        });
+        return packageUserKeys;
+    }
+
+    private static class WidgetValidityCheck implements Predicate<WidgetItem> {
+
+        private final InvariantDeviceProfile mIdp;
+        private final AppFilter mAppFilter;
+
+        WidgetValidityCheck(LauncherAppState app) {
+            mIdp = app.getInvariantDeviceProfile();
+            mAppFilter = new AppFilter(app.getContext());
+        }
+
+        @Override
+        public boolean test(WidgetItem item) {
+            if (item.widgetInfo != null) {
+                if ((item.widgetInfo.getWidgetFeatures() & WIDGET_FEATURE_HIDE_FROM_PICKER) != 0) {
+                    // Widget is hidden from picker
+                    return false;
+                }
+
+                // Ensure that all widgets we show can be added on a workspace of this size
+                if (!item.widgetInfo.isMinSizeFulfilled()) {
+                    if (DEBUG) {
+                        Log.d(TAG, String.format(
+                                "Widget %s : can't fit on this device with a grid size: %dx%d",
+                                item.componentName, mIdp.numColumns, mIdp.numRows));
+                    }
+                    return false;
+                }
+            }
+            if (!mAppFilter.shouldShowApp(item.componentName)) {
+                if (DEBUG) {
+                    Log.d(TAG, String.format("%s is filtered and not added to the widget tray.",
+                            item.componentName));
+                }
+                return false;
+            }
+
+            return true;
+        }
+    }
+
+    private static final class PackageItemInfoCache {
+        private final Map<PackageUserKey, PackageItemInfo> mMap = new ArrayMap<>();
+
+        PackageItemInfo getOrCreate(PackageUserKey key) {
+            PackageItemInfo pInfo = mMap.get(key);
+            if (pInfo == null) {
+                pInfo = new PackageItemInfo(key.mPackageName, key.mWidgetCategory, key.mUser);
+                pInfo.user = key.mUser;
+                mMap.put(key,  pInfo);
+            }
+            return pInfo;
+        }
+
+        Collection<PackageItemInfo> values() {
+            return mMap.values();
+        }}}
\ No newline at end of file

这篇关于Android14系统go版添加微件功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/885660

相关文章

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

Debian 13升级后网络转发等功能异常怎么办? 并非错误而是管理机制变更

《Debian13升级后网络转发等功能异常怎么办?并非错误而是管理机制变更》很多朋友反馈,更新到Debian13后网络转发等功能异常,这并非BUG而是Debian13Trixie调整... 日前 Debian 13 Trixie 发布后已经有众多网友升级到新版本,只不过升级后发现某些功能存在异常,例如网络转

JWT + 拦截器实现无状态登录系统

《JWT+拦截器实现无状态登录系统》JWT(JSONWebToken)提供了一种无状态的解决方案:用户登录后,服务器返回一个Token,后续请求携带该Token即可完成身份验证,无需服务器存储会话... 目录✅ 引言 一、JWT 是什么? 二、技术选型 三、项目结构 四、核心代码实现4.1 添加依赖(pom

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

基于Python实现自动化邮件发送系统的完整指南

《基于Python实现自动化邮件发送系统的完整指南》在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能,无论是用于发送报告、告警信息还是用户提醒,通过Python实现自动化的邮件发送功能都能... 目录一、前言:二、项目概述三、配置文件 `.env` 解析四、代码结构解析1. 导入模块2. 加载环

linux系统上安装JDK8全过程

《linux系统上安装JDK8全过程》文章介绍安装JDK的必要性及Linux下JDK8的安装步骤,包括卸载旧版本、下载解压、配置环境变量等,强调开发需JDK,运行可选JRE,现JDK已集成JRE... 目录为什么要安装jdk?1.查看linux系统是否有自带的jdk:2.下载jdk压缩包2.解压3.配置环境

Go之errors.New和fmt.Errorf 的区别小结

《Go之errors.New和fmt.Errorf的区别小结》本文主要介绍了Go之errors.New和fmt.Errorf的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考... 目录error的基本用法1. 获取错误信息2. 在条件判断中使用基本区别1.函数签名2.使用场景详细对

基于Java和FFmpeg实现视频压缩和剪辑功能

《基于Java和FFmpeg实现视频压缩和剪辑功能》在视频处理开发中,压缩和剪辑是常见的需求,本文将介绍如何使用Java结合FFmpeg实现视频压缩和剪辑功能,同时去除数据库操作,仅专注于视频处理,需... 目录引言1. 环境准备1.1 项目依赖1.2 安装 FFmpeg2. 视频压缩功能实现2.1 主要功

使用Python实现无损放大图片功能

《使用Python实现无损放大图片功能》本文介绍了如何使用Python的Pillow库进行无损图片放大,区分了JPEG和PNG格式在放大过程中的特点,并给出了示例代码,JPEG格式可能受压缩影响,需先... 目录一、什么是无损放大?二、实现方法步骤1:读取图片步骤2:无损放大图片步骤3:保存图片三、示php