google原生动态图标方案

近期由于moto的项目需要适配,根据原生机制实现日历的动态图标,所以研究了一下:

packages/apps/Launcher3/src/com/android/launcher3/DynamicIconProvider.java

Launcher的DaynamicIconProvider.java文件夹中有相关的代码,我们来看,google是如何实现日历动态图标的。

在构造函数中注册了和Date变化相关的监听器

 /**
61       * invoked by IconProvider#loadByName
62       * @param context context
63       */
64      public DynamicIconProvider(Context context) {
65          IntentFilter filter = new IntentFilter(Intent.ACTION_TIME_CHANGED);
66          filter.addAction("android.intent.action.TIME_SET");
67          filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
68  
69          context.registerReceiver(new DateTimeChangedReceiver(), filter);
70          mPackageManager = context.getPackageManager();
71      }

当日期或者timezone产生变化后,回调getIcon方法

90      @Override
91      public Drawable getIcon(LauncherActivityInfo info, int iconDpi, boolean flattenDrawable) {
92          String packageName = info.getApplicationInfo().packageName;
93          Drawable icon = null;
94          if (isCalendarSupportedDynamicIcon(packageName)) {//判断是否支持
95              try {
96                  Bundle bundle = mPackageManager.getActivityInfo(info.getComponentName(),
97                          PackageManager.GET_META_DATA).metaData;获取calendar AndroidManifest中metadata 标签相关的信息                //获取日历apk resources
98                  Resources resources = mPackageManager.getResourcesForApplication(packageName);
                                    //这个方法应该是关键
99                  int iconResId = getCalendarIconResource(bundle, resources);
100                  if (iconResId != 0) {
101                      icon = resources.getDrawableForDensity(iconResId, iconDpi, null);
102                  }
103              } catch (PackageManager.NameNotFoundException e) {
105              }
106          }
114          return icon;
115      }
116  

接下来来看我们猜测的关键方法 getCalendarIconResource(bundle,resources)这个方法

    private int getCalendarIconResource(Bundle bundle, Resources resources) {
171  
172          boolean useRoundIcon = getIsSystemUseRoundIcon();
             //提供了2套资源,一个是圆形的一个非圆形的,根据这个条件取不同的资源
173          int iconArrayResId = bundle.getInt(useRoundIcon ?
174                  GMS_CALENDAR_RES_ARRAY_ROUND : GMS_CALENDAR_RES_ARRAY_REGULAR, 0);
175          if (iconArrayResId == 0) {
176              return 0;
177          }
178  
179          try{
                 //先是获取Array,之后根据日历的日期获取对应的资源
180              return resources.obtainTypedArray(iconArrayResId).getResourceId(
181                      generateResourceIndexWithCalendarDate(), 0);
182          } catch (Resources.NotFoundException e) {
183              if (DBG) loge("getCalendarIconResource -> Resources.NotFoundException", e);
184          }
185          return 0;
186      }

至此我们大概明白了,google实现动态图标的原理,主要是跨包获取日历的资源,这个资源可能定义在manifest中的Metadata,然后根据日期获取对应的图片资源。

我们反编译GMS 的日历,找一下



这两个key的名字和Launcher中定义的DynamicIconProvider.java 两个key可以对应起来,看来就是两个array就是日历提供的动态图标了。



    
        @drawable/logo_calendar_01_adaptive
        @drawable/logo_calendar_02_adaptive
        @drawable/logo_calendar_03_adaptive
        @drawable/logo_calendar_04_adaptive
        @drawable/logo_calendar_05_adaptive
        @drawable/logo_calendar_06_adaptive
        @drawable/logo_calendar_07_adaptive
        @drawable/logo_calendar_08_adaptive
        @drawable/logo_calendar_09_adaptive
        @drawable/logo_calendar_10_adaptive
        @drawable/logo_calendar_11_adaptive
        @drawable/logo_calendar_12_adaptive
        @drawable/logo_calendar_13_adaptive
        @drawable/logo_calendar_14_adaptive
        @drawable/logo_calendar_15_adaptive
        @drawable/logo_calendar_16_adaptive
        @drawable/logo_calendar_17_adaptive
        @drawable/logo_calendar_18_adaptive
        @drawable/logo_calendar_19_adaptive
        @drawable/logo_calendar_20_adaptive
        @drawable/logo_calendar_21_adaptive
        @drawable/logo_calendar_22_adaptive
        @drawable/logo_calendar_23_adaptive
        @drawable/logo_calendar_24_adaptive
        @drawable/logo_calendar_25_adaptive
        @drawable/logo_calendar_26_adaptive
        @drawable/logo_calendar_27_adaptive
        @drawable/logo_calendar_28_adaptive
        @drawable/logo_calendar_29_adaptive
        @drawable/logo_calendar_30_adaptive
        @drawable/logo_calendar_31_adaptive
    

找到后是01-31的drawbale资源,每一个drawable都是按照google新的静态图标的规范提供的,有背景和前景两个layer



    
    
        
            
            
        
    

至此就清楚了,只要请GUI 按照google提供的背景,以及1-31的资源图就可以了。:)

 

你可能感兴趣的:(andorid)