1.å¦ä½è®¾ç½®ç³»ç»å¯ä¸ç launcher
2.HotSpot启动流程
3.Android开发如何获得第三方应用Widget的码l码包名和类名
å¦ä½è®¾ç½®ç³»ç»å¯ä¸ç launcher
ããå®ä¹ä¸ä¸ªç§æçfilteré项ï¼ç¶åç¨è¿ä¸ªé项æ¥è¿æ»¤HOME.
ããä¸è¬æ åµä¸æ们使ç¨Manifestä¸å®ä¹ç<category android:name="android.intent.category.HOME"æ¥è¿æ»¤çï¼
ããæ们ç°å¨å¢å ä¸ä¸ªç§æçHOME_FIRSTè¿æ»¤ã
ããå¨Intent.java(frameworks/base/core/java/android/content/Intent.java)ä¸æ·»å 两è¡ä»£ç
ãã//lixinso:æ·»å CATEGORY_HOME_FIRST
ãã@SdkConstant(SdkConstantType.INTENT_CATEGORY)
ããpublic static final String CATEGORY_HOME_FIRST = "android.intent.category.HOME_FIRST";
ãã3ï¼ä¿®æ¹åCATEGORY_HOMEç¸å ³çææçå°æ¹ï¼é½æ¹æHOME_FIRSTï¼ä¸»è¦æ¯frameworkä¸çè¿å 个å°æ¹ï¼
ããframeworks/base/services/java/com/android/server/am/ActivityManagerService.javaä¸
ãã//intent.addCategory(Intent.CATEGORY_HOME);
ããæ¹æintent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso:
ãã//if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {
ããæ¹æif (r.intent.hasCategory(Intent.CATEGORY_HOME_FIRST)) { //lixinso: Intent.CATEGORY_HOME -> Intent.CATEGORY_HOME_FIRST
ããframeworks/base/services/java/com/android/server/am/HistoryRecorder.javaä¸
ãã// _intent.hasCategory(Intent.CATEGORY_HOME) &&
ããæ¹æ _intent.hasCategory(Intent.CATEGORY_HOME_FIRST) && //lixinso: Intent.CATEGORY_HOME->Intent.CATEGORY_HOME_FIRST
ããframeworks/policies/base/mid/com/android/internal/policy/impl/MidWindowManager.javaä¸
ãã//mHomeIntent.addCategory(Intent.CATEGORY_HOME);
ããæ¹æ mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso
ããframeworks/policies/base/mid/com/android/internal/policy/impl/RecentApplicationsDialog.javaä¸
ãã//new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);
ããæ¹æ new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0); //lixinso
ããframeworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.javaä¸
ãã//mHomeIntent.addCategory(Intent.CATEGORY_HOME);
ããæ¹æ mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso
ããframeworks/policies/base/phone/com/android/internal/policy/impl/RecentApplicationsDialog.javaä¸
ãã//ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);
ããæ¹æ ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0); //lixinso
ãã4) åä¸ä¸ªèªå·±çLauncher.
ããå¯ä»¥åèandroid sampleä¸çLauncherï¼æè androidæºä»£ç ä¸ç /packages/apps/Launcher æ¥åã
ããå¨Launcherä¸æ è®°å ¶æ¯ä¸æ¯Launcherçæå ³é®ç代ç æ¶Manifestä¸çfilter:android:name="android.intent.category.HOME"
ããç°å¨æ们å®ä¹äºèªå·±çfilter,é£ä¹ï¼æ们å¨æ们èªå·±åçLauncherä¸å°Manifestæ¹ä¸ºï¼
ãã<application android:process="android.process.acore3" android:icon="@drawable/icon" android:label="@string/app_name">
ãã<activity android:name=".FirstAppActivity"
ããandroid:label="@string/app_name">
ãã<intent-filter>
ãã<action android:name="android.intent.action.MAIN" />
ãã<category android:name="android.intent.category.HOME_FIRST" />
ãã<category android:name="android.intent.category.DEFAULT" />
ãã<category android:name="android.intent.category.MONKEY" />
ãã</intent-filter>
ãã</activity>
ãã</application>
ããç¶åå°ç¼è¯å¥½çapkæ¾å°/out/target/product/generic/system/appç®å½ä¸ã
ãã5)å°Androidèªå¸¦çLauncherå é¤æï¼å æ¬æºä»£ç (packages/apps/Launcher)åapk(/out/target/product/generic/system/app/Launcher.apk)ã
ãã6)
ããåå®è¿äºå·¥ä½ï¼å°±å¯ä»¥éæ°ç¼è¯Androidäºï¼æ们å¯ä»¥ç¼è¯ä¿®æ¹è¿çå 个ç¸å ³çå ã
ããå¦æä¹åç¼è¯è¿äºAndroidæºç ï¼å¯ä»¥ç¨mmmå½ä»¤æ¥ç¼è¯é¨åçæ¹å¨ã
ããè¿ééè¦è¿æ ·ç¼è¯ï¼
ãã$ . build/envsetup.sh
ãã$ mmm frameworks/base
ãã$ mmm frameworks/base/services/java
ãã$ mmm frameworks/policies/base/mid
ãã$ mmm frameworks/policies/base/phone
ãã7)
ããç¼è¯å®æåéæ°çæimgæ件ã
ãã$ make snod
ãã8) ç°å¨å¯ä»¥å¯å¨Android模æå¨æ¥çææäºã
ããé¦å 设置ç¯å¢åéï¼
ãã$ export ANDROID_PRODUCT_OUT= ./out/target/product/generic
ããç¶ååæ¢å°
ãã$ cd ./out/host/linux-x/bin
ããè¿è¡
ãã$ ./emulator
ããè¿æ ·æ们å¯å¨ç模æå¨éé¢ç¨çimageå°±æ¯æ们åæç¼è¯å¥½çèªå·±å®å¶çä¸è¥¿äºã
ããä»æ¨¡æå¨ä¸å¯ä»¥çå°å¯å¨çLauncheræ¯æ们èªå·±çLauncherï¼ä¸ä¼åºç°é»è®¤çLauncheräºï¼ä¹ä¸ä¼åºç°éæ©çé¢ã
HotSpot启动流程
学习HotSpot启动流程有助于深入理解程序入口和虚拟机运行机制,为后续学习提供整体把握。码l码Launcher作为启动JVM进程的码l码工具,根据类别可划分为正式版启动器,码l码如在Windows下常用的码l码java.exe和javaw.exe,其中前者保留控制台与输出信息,码l码什么是源码系统后者用于GUI程序,码l码不显示输出。码l码使用“java -help”可在控制台查看Launcher的码l码具体使用方法和标准选项配置。
Launcher并非虚拟机核心,码l码而是码l码封装虚拟机执行外壳,负责加载JRE环境与动态链接库。码l码一个JVM进程仅执行指定Java程序,码l码多个Java程序需同时启动多个JVM进程。码l码HotSpot中Launcher由C语言编写,码l码与gamma共享源码,而Java源码位于不同目录。作业批改源码
理解Launcher执行原理对于深入HotSpot意义重大。Launcher调用HotSpot核心代码初始化JVM,维护整个生命周期。通过添加_JAVA_LAUNCHER_DEBUG=1环境变量,JVM输出详细打印,直观了解启动过程。大致步骤包括前期初始化、版本验证、OLAINDEX源码下载创建执行环境、设置虚拟机环境、加载虚拟机、解析参数、虚拟机初始化与线程创建等。
启动入口在main.c/main方法中,调用java.c/JLI_Launch方法,该方法分为几个部分:初始化、文字跳转源码版本验证、创建执行环境、设置虚拟机环境、加载虚拟机、参数解析与虚拟机初始化。新线程执行JavaMain()函数,完成虚拟机创建与Java程序运行。
JavaMain()方法中参数解析、abp vnext 源码虚拟机初始化、打印信息、确定主类、获取main方法并调用、获取执行结果与退出虚拟机的流程清晰。调用的关键函数如初始化虚拟机、确定主类、获取方法ID与执行方法、检查结果与销毁虚拟机,共同完成Java程序的执行。
Android开发如何获得第三方应用Widget的包名和类名
最近在做Android的平板的开发,想在桌面上预置一些第三方应用的Widget,在桌面预置Widget的方法就是要获得应用的包名和类名。
桌面预置widget的方法 在Launcher的配置文件 res/xml/default_workspace.xml中添加如下的代码:<appwidget
launcher:packageName="com.google.android.apps.genie.geniewidget"
//预置应用的包名
launcher:className="com.google.android.apps.genie.geniewidget.miniwidget.MiniWidgetProvider"
//预置应用的Provider的类名,不是Activity的类名
launcher:screen="1"//在第几屏0为第一屏,launcher:x="0"//x坐标launcher:y="0"//y坐标
launcher:spanX="4"//x方向占几个单元格
launcher:spanY="1"///y方向占几个单元格
通过logcat有时可以找到应用的包名和Provider类名,此方法不可取,容易出错。系统的widget可以通过查找相关的源码找到对应的包名和Provider的类名,但是第三方应用看不到源码,但是也可以通过反编译第三方应用,获得相应的Maifest.xml文件,找到对应的包名和Provider类名,但是此方法比较繁琐。
可以通过在Launcher中添加如下代码,可以将系统中所安装的所有 的widget的信息打印出来:
在Launcher.java中的onCreate方法中添加下面的代码:
List<AppWidgetProviderInfoproviders=mAppWidgetManager.getInstalledProviders();finalintproviderCount=providers.size();for(inti=0;i<providerCount;i++){
ComponentNameprovider=providers.get(i).provider;Log.i("xxx",
"packagename:"
+provider.getPackageName()+
"classname:"
+provider.getClassName());}新编译Launcher,把Launcher push进去之后,执行 adb logcat -s xxx,就可以看到打印出来的Log信息,包名和Provider了类名。
桌面预置shortcut的方法:
在Launcher的配置文件 res/xml/default_workspace.xml中添加如下的代码:<favorites