美文网首页程序员Android开发Android 技术开发
编译调试Android系统原生App - 以Settings为例

编译调试Android系统原生App - 以Settings为例

作者: imyyq_star | 来源:发表于2016-10-28 22:04 被阅读6996次

    0、前言:

    Android原生系统带有许多原生的App,比如浏览器、录音机、计算器、设置等,有些时候,我们需要用到一些系统的功能,或者是对已有的功能做二次开发,比如我上学时给一个公司做过一个Launcher和Wizard,就需要用到系统设置中的某些功能,比如Wifi、声音、显示等功能,于是就需要从Settings源码中提取出需要的功能。

    特别是公司自己定制Android系统,需要在上面做一些系统级的App的时候,原生App已有的功能就可以通过编译其源码的方式直接拿过来改改就能用,而且可用度很高。

    以下内容就以Settings为例,主要介绍如何编译和运行调试Settings源码。
    

    1、源码:

    这里有两种情况,分为原生的和公司定制的系统。无论是原生的还是定制的,类似于Settings这样需要使用到系统级或隐藏API的App,都需要系统签名文件和编译系统源码后得到相应的jar包才可以在IDE中编译,因为标准SDK根本没有那些API可供调用。

    举个栗子:

    • 闹钟、计算器这类的不需要额外的Jar包,得到源码后导入IDE就可以运行的。由于包名冲突,想调试要么删掉系统App,要么修改包名。
    • Settings、Launcher之类的就需要系统级的Jar包,SDK没有提供相应API。这类的想调试就必须删掉同包名的系统App了,修改包名会有意想不到的乱七八糟的问题出现。

    (1)原生App:

    网址:https://android.googlesource.com/
    位置:platform/packages/apps/,可Ctrl+F搜索一下。点击想要编译的App,比如Settings。
    使用Git克隆下来:比如 git clone https://android.googlesource.com/platform/packages/apps/Settings
    

    需要额外的Jar就需要自己编译系统源码啦,这个是比较麻烦的,有兴趣可以试试自己编译定制自己的Android系统。

    (2)定制:

      跟公司的底层工程师要代码。
      首先是“out/target/common/obj/JAVA_LIBRARIES/”文件夹,让底层人员整个文件夹压缩了给到你,虽然比较大(大概1G),但这是必须的,底层人员可能会说:你要什么再跟我说,扯淡,不要听他的,你就要全部。
      再来是要Settings的源码。
    

    ** 注意,既然是定制的,源码、jar、签名文件,还有系统都是一一对应的,你不能拿其他公司的系统签名来给你公司的系统app签名,这样无法运行的。 **

    2、编译:

    有了源码,下一步当然是要跑起来啦。

    建议都使用Eclipse来编译,不要使用AS,因为AS编译大型的原生App能卡到你吐血,而且出错提示也不友好。但是用过AS的人都不想再碰Eclipse了有没有??别急,可以先用Eclipse编译过了,再贴到AS中,这样好很多,也很节省时间。

    步骤:

    初始化:

    • 新建工程,Compile With 选最大,Target和Min都选和你使用的系统一致,包名和原生app的包名一致,比如Settings的是com.android.settings。
    • 新建成功后,添加libs文件夹,删掉AndroidManifest.xml,清空res。使用Git初始化项目,添加ignore文件,提交init,方便出错时回退。

    放入源码:

    • 拷贝Settings源码的AndroidManifest.xml、src、res到工程,选择Project -> Clean清理一下,在Console会得到很多错误。
    • git commit 提交一下,还是那句话,出错方便回退。

    修正res错误:

    • 首先是res下的错误,可能每个语言的strings.xml文件都会报错,建议删掉其他不需要的语言,可以根据Console的报错信息,写个小程序批量删除,留下需要的,并修正错误即可。比如原生的代码可能会有string重复,去掉即可。我只留下了value和value-zh-rCN的strings.xml,因为其他语言的用不到。
    • 若是缺少Drawable文件,比如图片,有以下方式可以找回来:
      * Google搜索文件名,不要使用百度,百度搜不出来。
      * 去SDK文件夹下全局搜索。
    • 不要怕修改,以解决问题为优先。比如我编译后发现缺少了@*android:drawable/XXX文件,在SDK文件夹搜索后找到该文件,放到了res/drawable文件夹后,将其引用修改为@drawable/XXX即可。毕竟只是个资源文件而已。

    • 如果是缺少style,可以把style的名称贴到Google中,一般都能得到正确的结果。

    • 总之就是根据提示一直解决到res没有提示错误为止。解决完毕,git commit。

    修正src错误:

    • 再来是src的错误,首先是必须导入的jar包,解压底层工程师给你的JAVA_LIBRARIES文件夹,里面有很多的子文件夹。
      第一个包:
      文件夹:framework_intermediates
      第二个包:
      文件夹:core_intermediates/core-libart_intermediates(也许是其他的名字)
      第三个包:
      文件夹:android-common_intermediates

            将以上文件夹中的classes.jar,为了好区分重命名为framework-classes.jar、core-classes.jar、common-classes.jar。放到一个方便查找的文件夹中,这三个jar包将作为User Library引用。不能作为常规的jar使用。如何引用请Google。
      
    • 需要注意的是:
      引用后,在Java Build Path/Order and Export中,framework需排在第一、core第二、common第三。

    • 然后再Clean一下,看看src还有什么错误,比方说com.android.setupwizard.Test类没有找到,就去JAVA_LIBRARIES文件夹搜索Test,再定位到其目录下,找到其classes.jar文件,重命名后放入libs中即可。其他的错误也是如此。

    • 有个比较特殊的类EventLogTags,在文件夹中根本没有找到想要的,其使用的都是一些静态变量。于是就直接在网上搜索静态变量的名称,比如EventLogTags.LOCK_SCREEN_TYPE,直接使用其值,虽然对不对,但是没有办法也只能先这样了。

    • 同理,也是一直解决到Clean后src没有错误为止,再git commit。

        建议不勾选:
            Window -> Preference -> Android -> Lint error Checking 的Run full error check ....
        这样有些warning和不影响运行的Lint error就不会提示,反正没事,眼不见心不烦。
      

    3、尝试运行:

    编译通过了,试着直接debug跑一下,在安装进设备的时候,就会有以下错误:
    

    报错:

    • Unable to execute dex: Multiple dex files define Landroid/support/annotation/AnimRes;
      Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Landroid/support/annotation/AnimRes;
      这是因为Annotation曾经是作为一个单独的库存在的,但是由于某些原因,在最新的v4中,已经包含了Annotation了,所以,就不需要Annotation的包了,如果你没有导入Annotation的包,就说明你导入了SDK,通过Java Build Path/Libraries,Remove掉就可以了。比如我使用的是Android N,就Remove掉AndroidN。
      如果发现还有这个问题,那就是v4和v13的包冲突了,v13的包是包含v4的,把v4的包去掉就可以了。

    • Installation error: INSTALL_FAILED_VERSION_DOWNGRADE:
      因为系统中已经存在了Settings了,所以无法安装。可以取得Root权限,删掉/system/app/Settings/Settings.apk文件,删除前记得保存一下,万一出错可以恢复。

      或者,通过右键选择 Android Tools -> Rename Application Package,重命名Package,如果你的项目是GBK编码的,重命名可能会失败,可以通过右键选择Properties -> Resource -> 选择UTF-8即可重命名成功。此方法需慎重使用,不一定全部app都适用,如果没有用到特殊的API就完全没问题。因为像Settings这样的重命名后会有很多奇奇怪怪的问题。
      
      如果要删除Settings.apk,提示:override rw-r--r-- root:root for 'Settings.apk'?,可以使用-rf:
        rm -rf Settings.apk
      
      提示:rm: Settings.apk: Read-only file system的话,可以:
        mount -o rw,remount /system
      
      重新挂载/system目录,然后就可以删除了,这里涉及到的跟Linux的文件权限系统有关,这里不再扩展。
      
      其实有个软件可以操作,如果你的设备已经Root,那么可以下载X-plore这个app,打开设置,选择Root权限访问,选择超级用户+挂载可写,即可轻松删除系统app,不过在删除之前,建议备份。
      
    • Installation error: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED:
      AndroidMenifest.xml错误,据说可能是包名有大写字母,反正我没有。在网上查了一番,有人说是,把Activity之类的注册写上全名即可。但是我也没有这样的情况,后来找到有人说android:taskAffinity的问题,这个是啥自己搜索,我发现有些是"",有些是com.android.settings,我全更改了,可还是有这个错误。搞来搞去,原来是我重命名包名了,才会有这些问题,就把包名改回去了,删掉相应系统App后,这个问题就解决了。

    • 弹出Toast有问题,我在SettingsActivity中使用Toast是有问题的,报xml解析错误。也不知道咋回事,没有深入探索。

    • Installation error: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE:
      原因:apk的AndroidManifest.xml中声明了android:sharedUserId="android.uid.system",但没有相应的系统签名。别急,接下来就说明如何签名的问题。

    4、调试

    使用到系统级API的,或者AndroidManifest.xml文件中声明了

    android:sharedUserId="android.uid.system"
    

    那么没有系统签名,直接debug签名运行是不行的,需要向底层工程师要系统的签名文件,在源码目录
    build\target\product\security
    下的platform.pk8platform.x509.pem,如果你想看此次编译Settings是否已成功了,可以适当的在入口加一下Log,然后导出未签名的apk,使用系统签名进行签名后,放到/system/app/下替换掉Settings.apk,然后重启系统,打开设置,看看Logcat是否输出里加入的Log。

    系统签名转换成debug签名进行调试:

    在不知道系统签名可以转换成debug签名前,老实说我一直都是用Log的方式调试,太特么痛苦了。现在知道后整个人都懵逼了。

    我们都希望可以像调试普通app那样调试系统app,以下是如何通过opensslplatform.pk8platform.x509.pem转换成debug.keystore文件:

    三个命令

    • 得到platform.priv.pem
      openssl pkcs8 -in platform.pk8 -inform DER -outform PEM -out platform.priv.pem -nocrypt

    • 得到platform.pk12
      openssl pkcs12 -export -in platform.x509.pem -inkey platform.priv.pem -out platform.pk12 -name androiddebugkey

      此过程提示输入密码,输入android
      
    • 生成debug.keystore
      keytool -importkeystore -deststorepass android -destkeypass android -destkeystore debug.keystore -srckeystore platform.pk12 -srcstoretype PKCS12 -srcstorepass android -alias androiddebugkey

    此方法来自:http://curlog.com/2016/08/30/android-pk2debug-keystore/

    Mac自带openssl,Linux和Win需要安装。

    然后就可以使用得到的debug签名配置到eclipse后愉快的调试啦,当然,得先把系统中已经存在的app先删除掉。然后重启系统,至于如何配置eclipse的debug签名,请Google。

    5、结语:

    使用过AS后,当然希望在AS中也可以调试系统App,抽空再写篇相关编译和调试的文章。如果这篇文章帮到你了,给个赞呗。

    相关文章

      网友评论

        本文标题:编译调试Android系统原生App - 以Settings为例

        本文链接:https://www.haomeiwen.com/subject/ozmeuttx.html