diff --git a/chapter-04/README.md b/chapter-04/README.md index 8c0b8c9..f5dd34f 100644 --- a/chapter-04/README.md +++ b/chapter-04/README.md @@ -64,9 +64,9 @@ ​ 最后就是从原理层面了解资源所在位置,如何修改Android源码替换资源。实现对系统UI的定制化,从根本上解决美化系统的问题,编译出来的镜像直接刷机后就能获得美化后的界面。这种定制方式的难度最高,同时也是最根源的办法。当我们掌握原理后,那么以上两种方式是如何做到美化的同样也会了如指掌。接下来,我们将先对原理性的知识进行了解。 -## 4.3 UI界面资源 +## 4.3 主题修改 -​ 我们可以直接通过修改Android源码中对资源的配置,达到修改系统UI的目的,大多数的系统UI相关的资源和配置都存放在目录`frameworks/base/core/res/res/`。我们可以找到与主题相关的资源文件,通过修改这些资源文件中的属性来实现改变 整个系统UI的外观样式,而图标相关的素材一般在这个目录下的`drrawable-*`的子目录中。我们可以直接替换图标素材来实现修改图标。 +​ 有多种方式可以修改主题,例如通过修改Android源码中对资源的配置,达到修改系统UI的目的,大多数的系统UI相关的资源和配置都存放在目录`frameworks/base/core/res/res/`。找到与主题相关的资源文件,通过修改这些资源文件中的属性来实现改变 整个系统UI的外观样式,而图标相关的素材一般在这个目录下的`drawable-*`的子目录中。可以直接替换图标素材来实现修改图标,或者是直接替换主题apk同样可以实现切换主题。 ​ 在源码编译刷入手机后,在手机中会有默认自带文件`./system/framework/framework-res.apk`,这是存放Android系统UI界面的资源文件,图片、布局、颜色、字符串等。它包含了 Android Framework 中的所有公共资源。当Android应用程序需要使用系统级的UI资源时,就可以访问并使用这些资源。 @@ -164,3 +164,18 @@ public class WallpaperManager { ​ 从源码中看到可以从三个地方获取默认壁纸,同样想要修改也能从这三个方式着手,比如添加一个属性设置默认壁纸路径,或者修改cmfpath的路径设置默认壁纸,最后就是修改资源文件名来设置默认壁纸。这里我们采用的是最后一种。 +## 4.5 修改图标 + +​ 在AOSP源码中,系统图标资源的目录位置取决于特定的应用、部件或系统服务。以下是AOSP源码中一些常见的系统图标资源目录及其位置: + +​ 1、Android 框架(AOSP 源码树下的 frameworks/base/core/res/):这些图标资源包括桌面、通知栏、设置等应用程序的图标。 + +​ 2、系统UI(AOSP 源码树下的 frameworks/base/packages/SystemUI/res/):这些图标资源包括状态栏、快捷设置面板、锁定屏幕、任务管理器等。 + +​ 3、电话(AOSP 源码树下的 packages/apps/PhoneCommon/res/drawable/):这些图标资源包括来电、拨号、通话记录等电话应用图标。 + +​ 4、联系人(AOSP 源码树下的 packages/apps/Contacts/res/drawable/):这些图标资源包括联系人、群组、通讯录等联系人应用图标。 + +​ + +TODO 第四章要花时间测试的,先跳过。 diff --git a/chapter-05/README.md b/chapter-05/README.md new file mode 100644 index 0000000..72b9815 --- /dev/null +++ b/chapter-05/README.md @@ -0,0 +1,165 @@ +# 第五章 系统内置功能 # + +## 5.1 什么是系统内置 + +​ 系统内置简单的说就是将镜像刷入手机后默认就在手机中能够使用的功能,例如Android内置的Launcher、Phone、Email、Setting等系统App都是属于内置的。同样开发者也可以制作一个App将其内置在系统中并且作为系统应用,又或者在工作中,每次手机刷机后需要安装的一些环境,也可以内置在系统中,这样每次刷机后都不必重新配置环境。 + +​ 在前几章的学习中,介绍了Android是如何实现启动系统以及打开应用程序的执行流程,并且小牛试刀修改替换了系统的资源文件。将AOSP看做是一个大型的项目,本章需要学习的是如何对这个项目二次开发,在它的基础上扩展一些让我们使用起来更加便利的功能内置在系统中,由于Android系统非常庞大,每次修改后都需要进行编译再刷入手机。而这些功能的业务相关的代码尽量不要直接写在AOSP源码中,避免浪费大量的时间在等待中。 + +## 5.2 系统内置App + +​ 首先找到Android系统自身内置app的所在目录`packages/apps`,在系统中内置的大多数App源码都是在这里,打开任意一个系统内App的目录进去后,能看到这里的结构和我们正常开发的Android App没有什么区别。需要内置的App代码并不是一定要放在这个目录下,可以选择将编译后的apk内置进去,这样就能使用Android Studio单独开发这个App。 + +``` +cd ./packages/apps +ls + +BasicSmsReceiver DevCamera ManagedProvisioning QuickSearchBox Test +Bluetooth Dialer Messaging RemoteProvisioner ThemePicker +Browser2 DocumentsUI Music SafetyRegulatoryInfo TimeZoneData +Calendar EmergencyInfo MusicFX SampleLocationAttribution TimeZoneUpdater +Camera2 Gallery Nfc SecureElement Traceur +Car Gallery2 OnDeviceAppPrediction Settings TV +CarrierConfig HTMLViewer OneTimeInitializer SettingsIntelligence TvSettings +CellBroadcastReceiver ImsServiceEntitlement PhoneCommon SpareParts UniversalMediaPlayer +CertInstaller KeyChain Protips Stk WallpaperPicker +Contacts Launcher3 Provision StorageManager WallpaperPicker2 +DeskClock LegacyCamera QuickAccessWallet Tag + +cd WallpaperPicker +ls + +Android.bp AndroidManifest.xml build.gradle CleanSpec.mk LibraryManifest.xml OWNERS res src +``` + +​ 接下来开发一个简单的案例,功能是在`/data/system`目录中创建一个文件并且写入内容。这个目录是只有system身份权限的进程才能访问。最后将这个App应用内置到系统中,编译后刷入手机,验证是否成功写入数据。以下是案例的实现代码。 + +```java + +public class MainActivity extends AppCompatActivity { + + public String writeTxtToFile(String strContent, String filePath, String fileName) { + String strFilePath = filePath+fileName; + try { + File file = new File(strFilePath); + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + RandomAccessFile raf = new RandomAccessFile(file, "rwd"); + raf.setLength(0); + long writePosition = raf.getFilePointer(); + raf.seek(writePosition); + raf.write(strContent.getBytes()); + raf.close(); + // + } catch (Exception e) { + Log.e("MainActivity", "Error on write File:" + e); + return e.getMessage(); + } + return ""; + } + TextView txtContext; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + txtContext=findViewById(R.id.txtContext); + String errMsg= writeTxtToFile("测试内置系统App","/data/system/","demo.txt"); + if(errMsg.isEmpty()){ + txtContext.setText("写入成功"); + }else{ + txtContext.setText("写入失败,"+errMsg); + } + } +} +``` + +​ 内置到手机前,先直接将app安装测试,写入文件时提示错误`Error on write File:java.io.IOException: Permission denied`。 + +​ `android:shareUserId` 是 AndroidManifest.xml 文件中的一个属性,用于应用程序之间的共享用户 ID。共用用户 ID 可以让应用程序之间更好的进行相互访问和操作。当一个应用程序定义了`android:shareUserId`属性时,另一个相互信任的应用程序可以设置相同的 `android:shareUserId` 属性,从而实现应用程序的数据共享和交互。 + +​ 在安装和运行应用程序之前,设备会将具有相同共享用户 ID 的应用程序视为同一用户,因此可以访问对方的数据,比如 SharedPreferences 和文件等。如果应用程序没有设置 `android:shareUserId` 属性,则其默认值是该应用程序的包名。以下是AndroidManifest.xml中的配置。 + +``` + + + ... + +``` + +​ 需要注意的是,如果两个应用程序带有相同的 `android:shareUserId` 属性,则它们必须由同一个签名密钥签名,这是为了保证安全性。如果你直接设置了这个属性后,再使用常规的方式安装就提示下面的错误 + +``` +Installation did not succeed. +The application could not be installed: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE + +List of apks: +[0] 'C:\Users\king\AndroidStudioProjects\SystemAppDemo\app\build\intermediates\apk\debug\app-debug.apk' +Installation failed due to: 'INSTALL_FAILED_SHARED_USER_INCOMPATIBLE: Package cn.mik.systemappdemo tried to change user null' +``` + +​ 测试用例准备就绪后就可以来到源码的目录`packages/apps`,创建一个新的目录`SystemAppDemo`,将刚刚编译的样例App也改名为SystemAppDemo放入这个目录,在这个新目录中添加一个编译的配置文件Android.mk。 + +~~~ +cd ./packages/apps/ +mkdir SystemAppDemo && cd SystemAppDemo +touch Android.mk +gedit Android.mk + +//添加下面的内容 +#当前路径 +LOCAL_PATH := $(call my-dir) +#清除环境变量 +include $(CLEAR_VARS) + +#模块名称 +LOCAL_MODULE := SystemAppDemo +#编译的模块文件 +LOCAL_SRC_FILES := $(LOCAL_MODULE).apk +#定义编译完成之后的类型 +LOCAL_MODULE_CLASS := APPS +#定义编译完成之后模块的后缀 +LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) +#哪个版本进行编译,optional表示全版本编译。可选字段: user 、 eng 、 tests +LOCAL_MODULE_TAGS := optional +#不进行odex优化 +LOCAL_DEX_PREOPT := false +#签名,platform表示系统签名,PRESIGNED表示保持原签名 +LOCAL_CERTIFICATE := platform +include $(BUILD_PREBUILT) +~~~ + +​ 在 Android 系统编译过程中,`PRODUCT_PACKAGES` 是一个重要的变量,它定义了系统所需构建的软件包列表。`PRODUCT_PACKAGES` 变量定义的是本次构建需要编译打包的软件包,包括一些基础系统组件和应用程序模块,例如音频服务模块、媒体播放库、输入法、设置应用程序等。 + +​ 在构建规则文件`./build/make/target/product/handheld_system.mk`的末尾添加配置。 + +~~~ +PRODUCT_PACKAGES += SystemAppDemo \ +~~~ + +​ 到这里就修改完毕了,最后重新编译系统,将其刷入手机中。 + +``` +source ./build/envsetup.sh + +lunch aosp_blueline-userdebug + +make -j$(nproc --all) + +adb reboot bootloader + +flashflash all -w + +``` + +​ 刷机完成后,在桌面就能看到刚刚内置的App了,这时再打开App时。不会提示没有权限了。来到`/data/system`目录验证创建的这个文件已经存在并且写入内容。 + + + +​ + +​ diff --git a/目录.md b/目录.md index 65b3bd4..19edc6c 100644 --- a/目录.md +++ b/目录.md @@ -51,7 +51,7 @@ ### 4.1 系统美化简介 ### 4.2 常见的系统美化方式 -### 4.3 UI界面资源 +### 4.3 主题修改 ### 4.3.1 认识framework-res ### 4.3.2 编译framework-res ### 4.4 修改开机画面 @@ -60,13 +60,10 @@ ### 4.7 修改图标 ### 4.8 美化包使用 -## 第5章 系统功能增强 -### 5.1 内置谷歌套件 -### 5.1.1 gapps是什么 -### 5.1.2 系统如何内置 -### 5.1.3 测试效果 -### 5.2 为系统预置app -### 5.3 为系统预置jar库 +## 第5章 系统内置功能 +### 5.1 什么是系统内置 +### 5.2 系统内置app +### 5.3 系统内置jar库 ### 5.3.1 jar的编译与生成 ### 5.3.2 内置jar ### 5.3.3 测试效果