插件的编写
参照ExamplePlugin,需要系统签名。
需要先编译以下模块得到jar,引用在项目中。
m SystemUIPluginLib
com.android.systemui.permission.PLUGIN
PluginManager.addPluginListener
SystemUI 是如何发现 clock plugin 的?
SystemUI发现插件的处理流程:
apk安装的广播处理中调用handleQueryPlugins,如果发现有插件,
则handleQueryPlugins调用的PluginInstanceManager的handleLoadPlugin 发送 PLUGIN_CONNECTED 信息 给 listener 比如 ClockManager,ClockManager 通过addOnClockChangedListener发送给KeyguardClockSwitch。
何时会加载插件?
用户解锁的时候
PluginManager.addPluginListener的时候
PluginManager 的功能
开始监听:
private void startListening() {if (mListening) return;mListening = true;IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);filter.addAction(Intent.ACTION_PACKAGE_CHANGED);filter.addAction(Intent.ACTION_PACKAGE_REPLACED);filter.addAction(Intent.ACTION_PACKAGE_REMOVED);filter.addAction(PLUGIN_CHANGED);filter.addAction(DISABLE_PLUGIN);filter.addDataScheme("package");mContext.registerReceiver(this, filter);filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);mContext.registerReceiver(this, filter);}
PluginInstanceManager 就是一个具体的插件的管理类,比如Clock,或者Left button。
如何创建一个PluginInstanceManager
加载plugin的关键代码:
PluginManagerImpl:
/** Returns class loader specific for the given plugin. */public ClassLoader getClassLoader(ApplicationInfo appInfo) {if (!isDebuggable && !isPluginPackageWhitelisted(appInfo.packageName)) {Log.w(TAG, "Cannot get class loader for non-whitelisted plugin. Src:"+ appInfo.sourceDir + ", pkg: " + appInfo.packageName);return null;}if (mClassLoaders.containsKey(appInfo.packageName)) {return mClassLoaders.get(appInfo.packageName);}List<String> zipPaths = new ArrayList<>();List<String> libPaths = new ArrayList<>();LoadedApk.makePaths(null, true, appInfo, zipPaths, libPaths);ClassLoader classLoader = new PathClassLoader(TextUtils.join(File.pathSeparator, zipPaths),TextUtils.join(File.pathSeparator, libPaths),getParentClassLoader());mClassLoaders.put(appInfo.packageName, classLoader);return classLoader;}
有哪些插件?
开机时的QUERY_ALL是怎么发送的?
取决于具体的PluginInstanceManager实例
com.android.systemui.action.PLUGIN_LOCKSCREEN_LEFT_BUTTON
KeyguardAffordanceView ,左边是Phone,右边是Camera.
拖到的圆形动画的实现:
控制是否显示:
<!-- Show mic or phone affordance on Keyguard --><bool name="config_keyguardShowLeftAffordance">false</bool><!-- Show camera affordance on Keyguard --><bool name="config_keyguardShowCameraAffordance">false</bool>
LeftButton 的实现效果
为什么显示的是白色?原因如下:
val loading = this.resources.getDrawable(R.drawable.loading_quan,this.theme)loading.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);binding.imageView.setImageDrawable(loading)
插件apk需要push到system/app下
scp andy@192.168.16.128:android11/out/target/product/Tinker_Board_2/system/app/Left/Left.apk .
adb root
adb remount
adb shell rm -r /system/app/Left/
adb shell mkdir /system/app/Left
adb push Left.apk /system/app/Left/
adb reboot
pause