时间:2020/10/10
之前公司不允许csdn,笔记写在其它地方。最近整理过来
1、图标形状的overlay
frameworks\base\packages\overlays目录
2、某一种形状的源码
默认配置在framework/base/core/res/res
res下面放着图标形状的mask路径,这个值是一个矢量图转换成svg图的path
<string name="config_icon_mask" translatable="false">"M50,0 C10,0 0,10 0,50 0,90 10,100 50,100 90,100 100,90 100,50 100,10 90,0 50,0 Z"</string>
IconShapeCircleOverlay
mk文件定义model名
LOCAL_PACKAGE_NAME := IconShapeCircleOverlay
xml配置特定字串保证自己的overlay能被系统识别
android:isStatic 是否默认启用
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.theme.icon.squircle"
android:versionCode="1"
android:versionName="1.0">
<overlay android:targetPackage="android"
android:category="android.theme.customization.adaptive_icon_shape"
android:isStatic="true"
android:priority="1"/>
<application android:label="@string/icon_shape_squircle_overlay" android:hasCode="false"/>
</manifest>
另外:
要让系统在编译的时候把自己的apk编进去,还需要在frameworks/base/packages/overlays/Android.mk
中加上自己mk里写的modelName。
3、获取系统支持的overlay列表
可以看出主要就是xml里的这两个值
private String mCategory = "android.theme.customization.adaptive_icon_shape";
private static final String OVERLAY_TARGET_PACKAGE = "android";
private List<OverlayInfo> getOverlayInfos() {
final List<OverlayInfo> filteredInfos = new ArrayList<>();
try {
List<OverlayInfo> overlayInfos = mOverlayManager
.getOverlayInfosForTarget(OVERLAY_TARGET_PACKAGE, USER_SYSTEM);
for (OverlayInfo overlayInfo : overlayInfos) {
if (mCategory.equals(overlayInfo.category)) {
filteredInfos.add(overlayInfo);
}
}
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
filteredInfos.sort(OVERLAY_INFO_COMPARATOR);
return filteredInfos;
}
如果有需求,可以做一个选择菜单给用户切换不同的形状。
之前的代码开发者选项里好像是有切换图标形状的菜单,新的版本里找不到了。
//获取mOverlayManager
IOverlayManager mOverlayManager = IOverlayManager.Stub.asInterface(ServiceManager.getService(Context.OVERLAY_SERVICE));
//启用指定包名的overlay
mOverlayManager.setEnabledExclusiveInCategory(packageName,USER_SYSTEM);
4、权限
调用mOverlayManager.setEnabledExclusiveInCategory
方法可能需要以下权限,否则会报错
<uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="android.permission.CHANGE_OVERLAY_PACKAGES"/>
权限检测在
frameworks\base\services\core\java\com\android\server\om\OverlayActorEnforcer.java
void enforceActor(@NonNull OverlayInfo overlayInfo, @NonNull String methodName,
int callingUid, int userId) throws SecurityException {
ActorState actorState = isAllowedActor(methodName, overlayInfo, callingUid, userId);
if (actorState == ActorState.ALLOWED) {
return;
}
String targetOverlayableName = overlayInfo.targetOverlayableName;
throw new SecurityException("UID" + callingUid + " is not allowed to call "
+ methodName + " for "
+ (TextUtils.isEmpty(targetOverlayableName) ? "" : (targetOverlayableName + " in "))
+ overlayInfo.targetPackageName + (DEBUG_REASON ? (" because " + actorState) : "")
);
}
有兴趣的可以看一下isAllowedActor
方法