android代码_android代码混淆 - CSDN
  • Android开发精典案例60个【源码】

    千次下载 热门讨论 2020-07-28 23:32:54
    60个Android开发精典案例,好东西 - 给大家分享60个Android开发的精典案例,包含任务监听、设备适配,游戏框架搭建,特效实现,多点触控,网络协议,游戏关卡设置等内容。特别是做游戏开发的朋友值得研究。喜欢就拿...
  • 50个经典安卓项目源码 50个经典安卓项目源码 50个经典安卓项目源码
  • Android代码生成器

    2020-07-28 23:33:05
    基于安卓Android代码生成器是一款生成安卓手机程序的代码生成器 基于分层模式设计思想,生成的代码直接导入Eclipse软件就可以用的! 真正面向对象设计:系统的整体设计,提供通过使用面向对象的方法,设计所需系统...
  • 其实我当初决定开始写博客的想法挺简单的,觉得自己搞技术这么多年...更令我没想到的事,在我开始写博客不久之后,人民邮电出版社图灵公司的副总编辑陈冰老师就联系上了我,希望我可以写一本关于Android开发技术的书籍

    书中源码下载地址:http://download.csdn.net/detail/sinyu890807/7747691


    前言


    其实我当初决定开始写博客的想法挺简单的,觉得自己搞技术这么多年了,总应该要留下点什么。既然没能写出什么出色的应用,那至少也要留下点文字分享给大家,以指引在我后面的开发者们,毕竟我也从前辈们的博客那里受惠了很多。


    受邀


    下定决心之后我就开始了我的博客之旅,令我没想到的是,我写的文章竟然非常受大家的欢迎,短时间内就聚集了大量的人气。更令我没想到的事,在我开始写博客不久之后,人民邮电出版社图灵公司的副总编辑陈冰老师就联系上了我,希望我可以写一本关于Android开发技术的书籍!


    陈冰,第一次听到这个名字的时候相信大家和我一样都不会感到熟悉,但是当他告诉我,他之前一手策划过《大话设计模式》这本书时,我立刻冲向了我的书柜并找到它,翻开扉页后赫然就在责任编辑那一栏看到了陈冰的名字,往后翻还可以看到他为《大话设计模式》写的序。这时我的心里只有一个念头,他邀请我写的这本书我是无论如何都拒绝不了了!


    创作


    接下来我就开始构思如何去完成这本书了。创作的过程注定是艰辛的,虽然我已经有了一些写博客的经验,但写书着实还是头一回,而写书又和写博客有着很大的差距。博客的内容可以比较散乱,想到哪里写到哪里,但书的内容一定要系统化,讲究循序渐进,基本上在写第1章的时候就应该把全书的内容都确定下来了。


    正所谓万事开头难,因此我首先是花了大约两个星期的时间制定了这本书的目录,这也就成为了我后面的写作大纲。陈冰告诉我,如果可以把目录制定出来,那么基本上就已经完成80%的工作了,然而事实证明,即使制定出了目录,事情也远远没有想象中的那么简单。我毕竟无法全身心地投入到写书当中,因为每天还要上班工作,有时还要加班,我只能在下班了之后再开始整理自己的思绪,然后动笔。另外,我之前对写书这件事算是严格保密的,并没有在博客上进行过任何透漏,因此我无法因为这个原因而停止更新博客,仍然坚持着每周或两周一篇的节奏。


    就这样在工作、博客和写书之间制衡着,虽然很辛苦,但我并没有落下任何一项。工作依旧相当出色,博客的质量大家有目共睹,而书怎么样大家拿到手之后就知道了。我创作的那段时间大概是保持着每月两章的进度,包括春节假期的那段时间也写个不停,最终在今年的3月份完全终稿,刚好赶上了截稿日期。到这里我的工作就已经基本完成了,后面的任务开始由出版社接手,他们审核、校对、排版、设计封面、印刷,终于在7月份的下旬开始预售了,一年的辛苦即将可以看到成果,我也表示非常期待。


    比较


    叙述完了创作的过程,接下来我们还是看一看这本书吧。这本书叫作《第一行代码——Android》,从名字上就可以看出来,这是一本非常适合初学者的书籍,我特别想写这样的一本书,因为它可以和我的博客相辅相成。由于我写博客的时间比较晚,13年才开始写的,当时很多Android技术相关的内容都已经被人写过了,重复再写一遍别人写过的东西显然太没创意,因此我给自己的博客定了一个主题,那就是只写比较高级的应用技术。可是博客的主题虽然非常鲜明,却明显不太适合初学者的朋友们阅读,从众多的评论当中我也能看出,有不少朋友的基本功还是不够扎实的,如果能结合一本介绍基础的书来巩固基本功,那你就真的变得无懈可击了,因此《第一行代码——Android》应运而生。


    下面我来对博客和书中的内容做个简要的对比吧,让大家心里有个数。

    • 博客更加倾向于介绍Android高级技巧,而书中则是基础、进阶、实用技巧都有。
    • 阅读博客时你需要有相当不错的Android基础,而阅读书时你不需要有任何的Android基础。
    • 博客中的内容相对比较散乱,而书中的内容更加系统化、科学化(这个是必然现象,一个是想到哪儿写到哪儿,一个是精心策划出来的)。
    • 出于对读者的尊重,我不会简单地将博客里的内容复制到书里,而出于对版权的保护,我也不会把书里的内容在博客上发表。因此,书和博客的内容基本不会有交集,这样买书的朋友们不会有种买了本纸质版博客的感觉。


    特色


    当然了,这本书还是有很多独有特色的,不然的话就和市场上的其它书没什么区别了。你不需要有任何Android基础就可以阅读它,但它会带领你一步步深入了解Android的各项功能。其中有不少章节我认为是非常出彩的,比如说第二章对Activity启动模式的讲解非常细致,市场上多数同类书中都没有这部分内容的,第七章对ContentProvider的讲解也相当到位,相信可以满足不少朋友的求知欲望。再比如说大部分章节的最后都会附有一个最佳实践部分,其中很多的技巧都是我日常工作中总结出来的,对你来说一定也很适用。再比如说,书中会对Git的用法进行穿插讲解,并教你如何将代码托管到GitHub,如何将软件上架到Google Play,如何在软件中嵌入广告盈利等等等等,我就不一一举出了,等待你自己去发现。


    另外,为了让这本书读起来不会枯燥,我努力让自己的语言变得幽默,可毕竟在这方面不怎么擅长,做得不够好。但本书中引入的经验值、升级、宝物系统则很好地弥补了这一点,通过不断地阅读,你将会获得经验值、升级,并赢得匪夷所思的宝物,让你在阅读过程体会到更多的乐趣。这个系统是由陈冰写的,如果大家阅读之后对这个系统有什么反馈或建议,可以发送邮件给他(neosaga@126.com)。


    很多朋友私下里有问过我,应该怎样去学习Android才能有所提高,那么今天我可以给出答案了。书和博客结合在一起学习,建议先看书打牢基础,然后再看博客进行进阶,当你把书和博客中的内容都吃透了的时候,那么我会的东西你也就都会了。


    封面


    看到了这里,相信有些朋友已经迫不及待想要购买一本了吧?别着急,我们再来看一下这本书的封面。封面的设计不是由我负责的,但诞生的过程也算是经历了各种曲折。陈冰对封面的要求非常苛刻,既要有深度有含义,又要能吸引眼球,还要给人一种想要翻开的冲动。经过了两个月左右的设计,所谓的“本年度最佳封面终于出炉了”,我们来欣赏一下:




    红色作为亮色系的代表色,使得它可以在众多图书当中脱颖而出,让人一眼就能看见它。


    再来看一下宣传海报的样子:




    怎么样,有没有一种视觉震撼的感觉?!虽然最终的封面夺人眼球,但任何东西都不会是凭空出现的,创作的过程必然有它的艰辛和曲折,《第一行代码——Android》封面诞生记这篇文章中专门讲述了本书封面的诞生过程,感兴趣的朋友可以像看故事一样去了解了解。


    定价


    79元,看到这个价格时我相信很多朋友觉得并不便宜,但实际上这已经是我尽最大可能争取到的价格了。由于书的价格是由出版社根据页数来制定的,我并不能做过多干预。通常情况下五百多页的书都可以定价到八十几、九十几元,最低也不能低于79元,于是我果断申请了最低的价格。


    其实换一种思路来想,79元也不算贵,因为这只是书的原售价,而我们在网上买书的话通常都会打折,基本上也就只需要五十多块钱就可以买到了。另外我觉得买书不用太在意价格,而是应该更在意里面的内容,书的内容只要能够真正给你带来帮助,那么它的价值就是远远大于这几十块钱的(就我自己而言,我大学期间总共大概花了两千多块的生活费用于买书,这些书一直都珍藏在我的书架上,是我永久的财富)。


    购买


    了解了这么多,不知道你有没有下定决心要买一本呢?目前《第一行代码——Android》这本书已经在当当、京东、亚马逊、互动这几个网上书店上架了,有需要的小伙伴们请猛戳下面的地址:


    当当网购买地址

    京东购买地址

    亚马逊购买地址

    互动出版购买地址

    天猫购买地址


    然后


    书的出版算是我的程序之路上一个新的里程碑吧,然而人生的路还很长,未来仍然需要努力向前。因此,我后面还是会一如既往地坚持更新博客,自我提升的同时也分享给大家。因为博客的原因,我结识了很多天南海北的新朋友,感谢众多朋友以及亲人的一路陪伴,愿未来大家都能天天向上。


    书中源码下载地址:http://download.csdn.net/detail/sinyu890807/7747691


    关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

    微信扫一扫下方二维码即可关注:

            

    展开全文
  • Android 系统源码——下载到编译

    万次阅读 2020-07-07 10:50:05
    一直想下载、编译、调试一下Android源码 ,加强对一些framework的理解,搞了好多次,终于可以正常调试了。这里进行一些总结和分享。 Android源码到模拟器运行,主要有的四个步骤: 下载源码 搭建编译环境 准备...

    一直想下载、编译、调试一下Android源码 ,加强对一些framework的理解,搞了好多次,终于可以正常调试了。这里进行一些总结和分享。

    Android源码到模拟器运行,主要有的四个步骤:

    1. 下载源码
    2. 搭建编译环境
    3. 准备编译

    我使用的环境是Ubuntu16.04 、openJDK8、Android 8.0.0

    硬件软件要求

    官方文档:要求

    硬件要求:

    • 如果是 Android 2.3.x (Gingerbread) 及更高版本(包括 master 分支),需要使用 64 位环境。如果是较低的版本,则可以在 32 位系统中进行编译。
    • 如果要检出代码,至少需要 250GB 可用磁盘空间;如果要进行编译,则还需要 150GB。如果要进行多次编译,则需要更多空间。
    • 如果在虚拟机中运行 Linux,则至少需要 16GB 的 RAM/交换空间。

    我的电脑是双系统,ubuntu 空间划分不集中,分区空间不够,导致编译失败。我在实践过程中,发现不需要官方声明的那么多空间,下载初始化包.repo 40G左右,检出代码(Android 8.0.0),又占用了40G左右,编译用了60G左右。总共算下来160G的分区空间应该是够用了。

    一、 下载源码

    Android 源码是非常庞大的,而且每个模块都是用git来进行管理 ,整个Android源码是由很多个git项目构成,Google对Android代码的更新也是更新到相应模块的git项目上。

    那对于需要编译Android的开发者来说,要分别clone 每个git项目而且还要放到固定的位置确实是件惨绝人寰的事,所以Google就开发了一个基于Python编写的帮助开发者管理多个项目的工具,这个工具就叫repo,repo就是封装了git命令的python脚本。

    由于国内网络的原因,我们使用国内的清华源下载源码和repo工具

    1.1、下载repo

    下面的命令,是从清华源下载repo工具,这样脚本中的路径就是指向清华源的aosp

    mkdir ~/bin   # 在home下创建bin文件夹
    PATH=~/bin:$PATH   # 把bin文件夹加入环境变量的
    curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo  > ~/bin/repo #下载repo脚本
    chmod a+x ~/bin/repo #添加权限
    

    repo 工具讲解

    我们有个非常庞大的项目Pre,该项目由很多个子项目R1,R2,…Rn等组成,为了方便管理和协同开发,我们为每个子项目创立自己的仓库,整个项目的结构如下:

    在这里插入图片描述

    项目Pre进行分库的好处就是,只需要创建需要开发的模块分支,代码量减少了很多。检出的时候也可以只检出某一模块的代码。

    会遇到这么一个问题:如果我们想要创建Pre分支来做feature开发,这就意味着,我们需要到每个子项目中分别创建对应的分支,这个过程如果纯粹靠手工做,那简直是个灾难,于是会写个自动化处理程序(我们假设这个工具叫做RepoUtil)来帮助我们解决这个问题。这个RepoUtil也会有版本管理之类的需求,因此我们也用Git对其管理,并为其创建对应的仓库。此时整个项目的结构如下:

    在这里插入图片描述

    这里RepoUtil知道整个项目Pre下的每个子项目(即维护子项目的列表),同时提供对这些子项目的管理功能,比如统一创建分支等。但是从"单一职责"角度来看,RepoUitl这个工具的功能过于复杂,我们完全可以将维护子项目列表这个功能抽取出来作为一个新项目sub_projects,因为子项目也会变化。因此,为其创建对应的仓库,并用Git管理,RepoUtil只需要通过简单的对ub_projects进行依赖即可,此时整个项目的结构如下:
    在这里插入图片描述

    AOSP项目结构

    • .repo工具对应RepoUtil
    • mainfest对应sub_projects

    在mainfest文件夹中,执行git branch -a 就可以看到所有的分支

    1.2、下载源码

    下载源码有两种方法:

    1)Android 官方下载源代码

    官方文档:下载源代码

    2)使用初始化包(建议)

    初始化包每月都会进行更新,由于首次同步需要下载约 30GB 数据,如果上面的方法,过程中任何网络故障都可能造成同步失败,我第一次是使用官方的方法,失败过一次。后来都是用这个方法。

    下载 https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar,下载完成后记得根据 checksum.txt 的内容校验一下。

    由于所有代码都是从隐藏的 .repo 目录中 checkout 出来的,所以我们只保留了 .repo 目录,下载后解压 再 repo sync 一遍即可得到完整的目录。

    使用方法如下:

    wget -c https://mirrors.tuna.tsinghua.edu.cn/aosp-monthly/aosp-latest.tar # 下载初始化包
    tar xf aosp-latest.tar
    cd AOSP   # 解压得到的 AOSP 工程目录
    # 这时 ls 的话什么也看不到,因为只有一个隐藏的 .repo 目录
    repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-8.0.1_r1 # 可选命令,指定版本,如果未指定,则使用最新的版本
    repo sync # 正常同步一遍即可得到完整目录
    # 或 repo sync -l 仅checkout代码
    

    Android各版本列表:https://source.android.google.cn/setup/start/build-numbers.html#source-code-tags-and-builds

    二、搭建编译环境

    官方文档:搭建编译环境

    安装openJDK8

    sudo apt-get update
    sudo apt-get install openjdk-8-jdk
    

    安装软件包

    官方文档没有介绍Ubuntu 16.04所需的软件包。使用Ubuntu 16.04的小伙伴,需要安装下面的软件

    sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib 
    sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386 
    sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386 
    sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev
    sudo apt-get install git-core gnupg flex bison gperf build-essential  
    sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib 
    sudo apt-get install libc6-dev-i386 
    sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev 
    sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
    sudo apt-get install lib32z-dev ccache
    
    

    三、准备编译

    设置环境

    使用 envsetup.sh 脚本初始化环境。请注意,将 source 替换成 .(一个点)可以省去一些字符,这种简写形式在文档中更为常用。

    source build/envsetup.sh
    

    或者

    . build/envsetup.sh
    

    选择目标

    使用 lunch 选择要编译的目标。确切的配置可作为参数进行传递。例如,以下命令表示针对模拟器进行完整编译,并且所有调试功能均处于启用状态。

    lunch aosp_arm-eng
    

    直接运行 lunch (没有参数),会列出所有支持的类型,输入对应的序号来进行选择。
    在这里插入图片描述

    所有编译目标都采用 BUILD-BUILDTYPE 形式,其中 BUILD 是表示特定功能组合的代号。BUILDTYPE 是以下类型之一:

    编译类型 使用情况
    user 权限受限;适用于生产环境
    userdebug 与“user”类似,但具有 root 权限和可调试性;是进行调试时的首选编译类型
    eng 具有额外调试工具的开发配置

    源码编译

    您可以使用 make 编译任何代码。GNU make 可以借助 -jN 参数处理并行任务,通常使用的任务数 N 介于编译时所用计算机上硬件线程数的 1-2 倍之间。例如,在一台双核 E5520 计算机(2 个 CPU,每个 CPU 4 个内核,每个内核 2 个线程)上,要实现最快的编译速度,可以使用介于 make -j16 到 make -j32 之间的命令。

    make -j4
    

    如果编译完一个版本后想重新编译一个,可以使用 make clobber清除之前编译生成的文件。我们编译产生的文件都在 out文件夹下。

    四、如何查看源码的版本

    1、 从代码中查看当前版本,找到如下文件

    build\make\core\version_defaults.mk
    

    搜索关键字 PLATFORM_VERSION

    # This is the canonical definition of the platform version,
    # which is the version that we reveal to the end user.
    # Update this value when the platform version changes (rather
    # than overriding it somewhere else).  Can be an arbitrary string.
    
    # When you add a new PLATFORM_VERSION which will result in a new
    # PLATFORM_SDK_VERSION please ensure you add a corresponding isAtLeast*
    # method in the following java file:
    # frameworks/support/compat/gingerbread/android/support/v4/os/BuildCompat.java
    
    # When you change PLATFORM_VERSION for a given PLATFORM_SDK_VERSION
    # please add that PLATFORM_VERSION to the following text file:
    # cts/tests/tests/os/assets/platform_versions.txt
    PLATFORM_VERSION.OPR1 := 8.0.0
    

    五、错误及解决方法

    由于在Ubuntu上开发,很多常用软件都没有,所以后来又在mac上编译源码,遇到不少问题,下面来分享一下

    错误 1、Could not find a supported mac sdk: [“10.10” “10.11” “10.12” “10.13” “10.14”]

    两种解决方法:

    1. 把当前系统有的sdk 版本,加入到这个列表中
    2. 下载列表中的sdk

    具体操作,下载地址,可以参考这里

    错误 2、在mac 10.15.4 上编译Android 8.0.0_r1 ,出现bad cpu type in executable

    这篇文章 也遇到这个错误,但是报错细节、Android版本号 和我的不一样,所以我暂时没有去尝试

    在苹果官网看到 关于bad cpu type in executable 回复 的,

    想了一下,既然Mac 10.15 支持64位,不支持32位,那就用新版Android吧,免得Android 8.0.0_r1 上越改问题越多

    错误3、在mac 10.15.4上编译Android10.0.0_r1,

    Android10.0.0_r1 是支持64位的,但是在编译过程中一定会遇到这个错误

    FAILED: build out/target/product/generic_x86_64/obj/ETC/sepolicy_tests_intermediates/sepolicy_tests
    Outputs: out/target/product/generic_x86_64/obj/ETC/sepolicy_tests_intermediates/sepolicy_tests
    Error: exited with code: 1
    Command: /bin/bash -c "(out/host/darwin-x86/bin/sepolicy_tests -l out/host/darwin-x86/lib64/libsepolwrap.dylib       -f out/target/product/generic_x86_64/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts  -f out/target/product/generic_x86_64/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts  -p out/target/product/generic_x86_64/obj/ETC/sepolicy_intermediates/sepolicy ) && (touch out/target/product/generic_x86_64/obj/ETC/sepolicy_tests_intermediates/sepolicy_tests )"
    Output:
    /bin/bash: line 1: 28159 Segmentation fault: 11  ( out/host/darwin-x86/bin/sepolicy_tests -l out/host/darwin-x86/lib64/libsepolwrap.dylib -f out/target/product/generic_x86_64/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts -f out/target/product/generic_x86_64/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts -p out/target/product/generic_x86_64/obj/ETC/sepolicy_intermediates/sepolicy )
    

    这个错误是与mac 10.15 兼容问题,可通过这个临时解决

    make SELINUX_IGNORE_NEVERALLOWS=true
    

    还有个官方方案,打上下面的patch:(我是使用这个方法解决的)
    1f944107a3341ab593c93bbdf09e22436cc0e3d3

    官方就是修改 system/sepolicy/tests/Android.bp 去掉stl: “libc++_static”,

    下面这个是Catalina MacOS SDK 10.15的patch:
    89dad60ed5ec30b0f732b612d454151abdb4e449

    出自这篇文章:AOSP SELinux error

    错误4、Mac 下编译 关于 文件格式

    注意在mac 上编译,磁盘格式最好使用 Mac OS扩展(区分大小写,日志式),我在APFS 上解压aosp-laster.rar、同步代码、编译,完整操作了两次都不行。遇到同样的错误,也没再网上找到答案。也有可能是其它原因,按照官方的最好

    六、使用Android studio 查看源码

    Android Studio 导入 Android 源码

    IntelliJ IDEA导入Android源码

    注意:执行命令的时候,需要在bash 环境下,不能再zsh 环境下

    参考:
    官方文档:准备编译
    自己动手编译Android源码(超详细)
    Android 源码下载 到 编译全过程
    从源码中查看当前android版本

    展开全文
  • android通过代码动态添加和删除控件

    万次阅读 多人点赞 2018-05-13 20:08:50
    1.概述android开发当中有可能会碰到以下这种情况,某个页面,内容不确定,根据用户需求增加或减少相应控件数。这种情况一般发生在编辑类页面当中,比如你的应用包含用户发帖功能,其内容组织结构和多少是可变的。...

    1.概述

    android开发当中有可能会碰到以下这种情况,某个页面,内容不确定,根据用户需求增加或减少相应控件数。这种情况一般发生在编辑类页面当中,比如你的应用包含用户发帖功能,其内容组织结构和多少是可变的。

    本文实现了一个动态添加和删除控件的简单例子!先上截图:

    截图1






    2.代码实现

    (1)布局文件activity_main.xml

    [html] view plain copy
    1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    2.     xmlns:tools="http://schemas.android.com/tools"  
    3.     android:layout_width="match_parent"  
    4.     android:layout_height="match_parent"  
    5.     android:background="@android:color/darker_gray"  
    6.     tools:context=".MainActivity" >  
    7.   
    8.     <ScrollView  
    9.         android:layout_width="match_parent"  
    10.         android:layout_height="match_parent"  
    11.         android:scrollbars="none" >  
    12.   
    13.         <LinearLayout  
    14.             android:id="@+id/content_view"  
    15.             android:layout_width="match_parent"  
    16.             android:layout_height="wrap_content"  
    17.             android:isScrollContainer="true"  
    18.             android:orientation="vertical"  
    19.             android:padding="10.0dip" >  
    20.   
    21.             <LinearLayout  
    22.                 android:id="@+id/ll_one"  
    23.                 android:layout_width="match_parent"  
    24.                 android:layout_height="wrap_content"  
    25.                 android:layout_marginTop="5dip"  
    26.                 android:background="#FFA2CD5A"  
    27.                 android:orientation="vertical"  
    28.                 android:padding="5dip" >  
    29.   
    30.                 <EditText  
    31.                     android:id="@+id/et_content1"  
    32.                     android:layout_width="match_parent"  
    33.                     android:layout_height="80dip"  
    34.                     android:background="#FFFFFFFF"  
    35.                     android:gravity="left"  
    36.                     android:inputType="textMultiLine"  
    37.                     android:paddingLeft="5dip"  
    38.                     android:textSize="16sp" />  
    39.   
    40.                 <RelativeLayout  
    41.                     android:layout_width="match_parent"  
    42.                     android:layout_height="wrap_content"  
    43.                     android:layout_marginTop="5dip" >  
    44.   
    45.                     <ImageButton  
    46.                         android:id="@+id/ibn_add1"  
    47.                         android:layout_width="wrap_content"  
    48.                         android:layout_height="wrap_content"  
    49.                         android:layout_alignParentRight="true"  
    50.                         android:background="@drawable/ic_add" />  
    51. <!--   
    52.                     <ImageButton  
    53.                         android:id="@+id/ibn_del1"  
    54.                         android:layout_width="wrap_content"  
    55.                         android:layout_height="wrap_content"  
    56.                         android:layout_marginRight="10dip"  
    57.                         android:layout_toLeftOf="@id/ibn_add1"  
    58.                         android:background="@drawable/ic_delete" />  
    59.  -->  
    60.                 </RelativeLayout>  
    61.             </LinearLayout>  
    62.         </LinearLayout>  
    63.     </ScrollView>  
    64.   
    65. </RelativeLayout>  

    简单来讲,一个ScrollView和内嵌的LinearLayout的组合实现了本例。LinearLayout内部控件可增可减,因为其包含在ScrollView里,所以内容超出页面显示范围时可以滚动。
    该布局文件显示效果如上面第一个截图所示,包含一个编辑框(EditText)和“添加”按钮。

    (2)MainActivity文件

    [java] view plain copy
    1. package com.example.androiddynamiclayout;  
    2.   
    3. import java.util.LinkedList;  
    4.   
    5. import android.os.Bundle;  
    6. import android.app.Activity;  
    7. import android.graphics.Color;  
    8. import android.text.InputType;  
    9. import android.view.Gravity;  
    10. import android.view.Menu;  
    11. import android.view.View;  
    12. import android.view.ViewGroup;  
    13. import android.widget.EditText;  
    14. import android.widget.ImageButton;  
    15. import android.widget.LinearLayout;  
    16. import android.widget.RelativeLayout;  
    17.   
    18. public class MainActivity extends Activity {  
    19.   
    20.     // 外围的LinearLayout容器  
    21.     private LinearLayout llContentView;  
    22.       
    23.     private EditText etContent1;  
    24.       
    25.     // “+”按钮控件List  
    26.     private LinkedList<ImageButton> listIBTNAdd;  
    27.     // “+”按钮ID索引  
    28.     private int btnIDIndex = 1000;  
    29.     // “-”按钮控件List  
    30.     private LinkedList<ImageButton> listIBTNDel;  
    31.       
    32.     private int iETContentHeight = 0;   // EditText控件高度  
    33.     private float fDimRatio = 1.0f; // 尺寸比例(实际尺寸/xml文件里尺寸)  
    34.       
    35.     @Override  
    36.     protected void onCreate(Bundle savedInstanceState) {  
    37.         super.onCreate(savedInstanceState);  
    38.         setContentView(R.layout.activity_main);  
    39.           
    40.         initCtrl();  
    41.     }  
    42.       
    43.     /** 
    44.      * 初始化控件 
    45.      */  
    46.     private void initCtrl()  
    47.     {  
    48.         llContentView = (LinearLayout) this.findViewById(R.id.content_view);  
    49.         etContent1 = (EditText) this.findViewById(R.id.et_content1);  
    50.         listIBTNAdd = new LinkedList<ImageButton>();  
    51.         listIBTNDel = new LinkedList<ImageButton>();  
    52.           
    53.         // “+”按钮(第一个)  
    54.         ImageButton ibtnAdd1 = (ImageButton) this.findViewById(R.id.ibn_add1);  
    55.         ibtnAdd1.setOnClickListener(new View.OnClickListener() {  
    56.   
    57.             @Override  
    58.             public void onClick(View v) {  
    59.                 // 获取尺寸变化比例  
    60.                 iETContentHeight = etContent1.getHeight();  
    61.                 fDimRatio = iETContentHeight / 80;  
    62.   
    63.                 addContent(v);  
    64.             }  
    65.         });  
    66.   
    67.         listIBTNAdd.add(ibtnAdd1);  
    68.         listIBTNDel.add(null);  // 第一组隐藏了“-”按钮,所以为null  
    69.     }  
    70.       
    71.     /** 
    72.      * 添加一组新控件 
    73.      * @param v 事件触发控件,其实就是触发添加事件对应的“+”按钮 
    74.      */  
    75.     private void addContent(View v) {  
    76.         if (v == null) {  
    77.             return;  
    78.         }  
    79.           
    80.         // 判断第几个“+”按钮触发了事件  
    81.         int iIndex = -1;  
    82.         for (int i = 0; i < listIBTNAdd.size(); i++) {  
    83.             if (listIBTNAdd.get(i) == v) {  
    84.                 iIndex = i;  
    85.                 break;  
    86.             }  
    87.         }  
    88.           
    89.         if (iIndex >= 0) {  
    90.             // 控件实际添加位置为当前触发位置点下一位  
    91.             iIndex += 1;  
    92.               
    93.             // 开始添加控件  
    94.               
    95.             // 1.创建外围LinearLayout控件  
    96.             LinearLayout layout = new LinearLayout(MainActivity.this);  
    97.             LinearLayout.LayoutParams lLayoutlayoutParams = new LinearLayout.LayoutParams(  
    98.                     ViewGroup.LayoutParams.MATCH_PARENT,  
    99.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
    100.             // 设置margin  
    101.             lLayoutlayoutParams.setMargins(0, (int) (fDimRatio * 5), 00);  
    102.             layout.setLayoutParams(lLayoutlayoutParams);  
    103.             // 设置属性  
    104.             layout.setBackgroundColor(Color.argb(25516220590));   // #FFA2CD5A  
    105.             layout.setPadding((int) (fDimRatio * 5), (int) (fDimRatio * 5),  
    106.                     (int) (fDimRatio * 5), (int) (fDimRatio * 5));  
    107.             layout.setOrientation(LinearLayout.VERTICAL);  
    108.               
    109.             // 2.创建内部EditText控件  
    110.             EditText etContent = new EditText(MainActivity.this);  
    111.             LinearLayout.LayoutParams etParam = new LinearLayout.LayoutParams(  
    112.                     ViewGroup.LayoutParams.MATCH_PARENT, iETContentHeight);  
    113.             etContent.setLayoutParams(etParam);  
    114.             // 设置属性  
    115.             etContent.setBackgroundColor(Color.argb(255255255255));   // #FFFFFFFF  
    116.             etContent.setGravity(Gravity.LEFT);  
    117.             etContent.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);  
    118.             etContent.setPadding((int) (fDimRatio * 5), 000);  
    119.             etContent.setTextSize(16);  
    120.             // 将EditText放到LinearLayout里  
    121.             layout.addView(etContent);  
    122.               
    123.             // 3.创建“+”和“-”按钮外围控件RelativeLayout  
    124.             RelativeLayout rlBtn = new RelativeLayout(MainActivity.this);  
    125.             RelativeLayout.LayoutParams rlParam = new RelativeLayout.LayoutParams(  
    126.                     ViewGroup.LayoutParams.MATCH_PARENT,  
    127.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
    128. //          rlParam.setMargins(0, (int) (fDimRatio * 5), 0, 0);  
    129.             rlBtn.setPadding(0, (int) (fDimRatio * 5), 00);  
    130.             rlBtn.setLayoutParams(rlParam);  
    131.               
    132.             // 4.创建“+”按钮  
    133.             ImageButton btnAdd = new ImageButton(MainActivity.this);  
    134.             RelativeLayout.LayoutParams btnAddParam = new RelativeLayout.LayoutParams(  
    135.                     ViewGroup.LayoutParams.WRAP_CONTENT,  
    136.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
    137.             // 靠右放置  
    138.             btnAddParam.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);  
    139.             btnAdd.setLayoutParams(btnAddParam);  
    140.             // 设置属性  
    141.             btnAdd.setBackgroundResource(R.drawable.ic_add);  
    142.             btnAdd.setId(btnIDIndex);  
    143.             // 设置点击操作  
    144.             btnAdd.setOnClickListener(new View.OnClickListener() {  
    145.   
    146.                 @Override  
    147.                 public void onClick(View v) {  
    148.                     addContent(v);  
    149.                 }  
    150.             });  
    151.             // 将“+”按钮放到RelativeLayout里  
    152.             rlBtn.addView(btnAdd);  
    153.             listIBTNAdd.add(iIndex, btnAdd);  
    154.               
    155.             // 5.创建“-”按钮  
    156.             ImageButton btnDelete = new ImageButton(MainActivity.this);  
    157.             btnDelete.setBackgroundResource(R.drawable.ic_delete);  
    158.             RelativeLayout.LayoutParams btnDeleteAddParam = new RelativeLayout.LayoutParams(  
    159.                     ViewGroup.LayoutParams.WRAP_CONTENT,  
    160.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
    161.             btnDeleteAddParam.setMargins(00, (int) (fDimRatio * 5), 0);  
    162.             // “-”按钮放在“+”按钮左侧  
    163.             btnDeleteAddParam.addRule(RelativeLayout.LEFT_OF, btnIDIndex);  
    164.             btnDelete.setOnClickListener(new View.OnClickListener() {  
    165.   
    166.                 @Override  
    167.                 public void onClick(View v) {  
    168.                     deleteContent(v);  
    169.                 }  
    170.             });  
    171.             // 将“-”按钮放到RelativeLayout里  
    172.             rlBtn.addView(btnDelete, btnDeleteAddParam);  
    173.             listIBTNDel.add(iIndex, btnDelete);  
    174.               
    175.             // 6.将RelativeLayout放到LinearLayout里  
    176.             layout.addView(rlBtn);  
    177.               
    178.             // 7.将layout同它内部的所有控件加到最外围的llContentView容器里  
    179.             llContentView.addView(layout, iIndex);  
    180.               
    181.             btnIDIndex++;  
    182.         }  
    183.     }  
    184.       
    185.     /** 
    186.      * 删除一组控件 
    187.      * @param v 事件触发控件,其实就是触发删除事件对应的“-”按钮 
    188.      */  
    189.     private void deleteContent(View v) {  
    190.         if (v == null) {  
    191.             return;  
    192.         }  
    193.   
    194.         // 判断第几个“-”按钮触发了事件  
    195.         int iIndex = -1;  
    196.         for (int i = 0; i < listIBTNDel.size(); i++) {  
    197.             if (listIBTNDel.get(i) == v) {  
    198.                 iIndex = i;  
    199.                 break;  
    200.             }  
    201.         }  
    202.         if (iIndex >= 0) {  
    203.             listIBTNAdd.remove(iIndex);  
    204.             listIBTNDel.remove(iIndex);  
    205.               
    206.             // 从外围llContentView容器里删除第iIndex控件  
    207.             llContentView.removeViewAt(iIndex);  
    208.         }  
    209.     }  
    210.   
    211.     /*@Override  
    212.     public boolean onCreateOptionsMenu(Menu menu) {  
    213.         // Inflate the menu; this adds items to the action bar if it is present.  
    214.         getMenuInflater().inflate(R.menu.activity_main, menu);  
    215.         return true;  
    216.     }  */
    217.   
    218. }  

    浏览这段代码需要注意以下几两点:
    1.llContentView:这个变量对应的是上面布局文件提到的那个LinearLayout,通过llContentView.addView(layout, iIndex)往某一位置添加子控件,通过llContentView.removeViewAt(iIndex)删除某一位置上的子控件。
    2.List对象listIBTNAdd和listIBTNDel:存储了当前所包含的所有“添加”和“删除”按钮对象,在发生添加或删除事件时,用于定位触发事件位
    置。

    原文地址:https://blog.csdn.net/chadeltu/article/details/42390047

    展开全文
  • 自己动手编译Android源码(超详细) 涅槃1992 2016.06.20 02:12* 字数 43...

    自己动手编译Android源码(超详细)

    2016.06.20 02:12* 字数 4330 阅读 86819评论 89赞赏 7

    Android Studio代码调试一文中,简单的介绍了代码调试的一些技巧.现在我们来谈谈android源码编译的一些事.(俺认为,作为android developer人人都应该有一份自己Android源码,这样我们就可以随时对自己有疑惑的地方通过亲手调试来加强理解).

    本文使用最新的Ubuntu 16.04,请首先确保自己已经安装了Git.没安装的同学可以通过以下命令进行安装:

    sudo apt-get install git 
    git configglobal user.emailtest@test.com” 
    git config –global user.name “test”
    

    其中test@test.com为你自己的邮箱.

    简要说明

    android源码编译的四个流程:1.源码下载;2.构建编译环境;3.编译源码;4运行.下文也将按照该流程讲述.


    源码下载

    由于某墙的原因,这里我们采用国内的镜像源进行下载.
    目前,可用的镜像源一般是科大和清华的,具体使用差不多,这里我选择清华大学镜像进行说明.(参考:科大源,清华源)

    repo工具下载及安装

    通过执行以下命令实现repo工具的下载和安装

    mkdir ~/bin
    PATH=~/bin:$PATH
    curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
    chmod a+x ~/bin/repo
    

    补充说明
    这里,我来简单的介绍下repo工具,我们知道AOSP项目由不同的子项目组成,为了方便进行管理,Google采用Git对AOSP项目进行多仓库管理.在聊repo工具之前,我先带你来聊聊多仓库项目:

    我们有个非常庞大的项目Pre,该项目由很多个子项目R1,R2,...Rn等组成,为了方便管理和协同开发,我们为每个子项目创立自己的仓库,整个项目的结构如下:


    这里写图片描述

    将一个项目Pre进行分库后会遇到这么一个问题:如果我们想要创建Pre分支来做feature开发,这就意味着,我们需要到每个子项目中分别创建对应的分支,这个过程如果纯粹靠手工做,那简直是个灾难,利索当然我们会想写个自动化处理程序(我们假设这个工具叫做RepoUtil)来帮助我们解决这个问题.这个RepoUtil也会有版本管理之类的需求,因此我们也用Git对其管理,并为其创建对应的仓库.此时整个项目的结构如下:


    这里写图片描述

    这里RepoUtil知道整个项目Pre下的每个子项目(即维护子项目的列表),同时需要提供对这些子项目的管理功能,比如统一创建分支等.但是从"单一职责"角度来看,RepoUitl这个工具的功能过于复杂,我们完全可以将维护子项目列表这个功能抽取出来作为一个新项目sub_projects,因为子项目也会变化,因此,为其创建对应的仓库,并用Git管理,这样的化,RepoUtil只需要通过简单的对ub_projects进行依赖即可,此时整个项目的结构如下:


    这里写图片描述

    AOSP项目结构和我上文的描述非常类似.repo工具对应RepoUtil,mainfest对应sub_projects.
    总结一下:repo就是这么一种工具,由一系列python脚本组成,通过调用Git命令实现对AOSP项目的管理.

    建立源码文件夹

    熟悉Git的同学都应该知道,我们需要为项目在本地创建对应的仓库.同样,这里为了方便对代码进行管理,我们为其创建一个文件夹.这里我在当前用户目录下创建了source文件夹,后面所有的下载的源码和编译出的产物也都放在这里,命令如下:

    mkdir source
    cd source
    

    初始化仓库

    我们将上面的source文件夹作为仓库,现在需要来初始化这个仓库了.通过执行初始化仓库命令可以获取AOSP项目master上最新的代码并初始化该仓库,命令如下:

    repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest
    
    

    或者使用:

    repo init -u git://aosp.tuna.tsinghua.edu.cn/aosp/platform/manifest
    

    两者实现的效果一致,仅仅只是协议不同.
    如果执行该命令的过程中,如果提示无法连接到 gerrit.googlesource.com,那么我们只需要编辑 ~/bin/repo文件,找到REPO_URL这一行,然后将其内容修改为:

    REPO_URL = 'https://gerrit-google.tuna.tsinghua.edu.cn/git-repo'
    

    然后重新执行上述命令即可.

    补充说明
    不带参数的manifest命令用于获取master上最新的代码,但是可以通过-b参数指定获取某个特定的android版本,比如我们想要获取android-4.0.1_r1分支,那么命令如下:

    repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-4.0.1_r1
    

    (AOSP项目当前所有的分支列表参看:分支列表)

    同步源码到本地

    初始化仓库之后,就可以开始正式同步代码到本地了,命令如下:

    repo sync
    

    以后如果需要同步最新的远程代码到本地,也只需要执行该命令即可.在同步过程中,如果因为网络原因中断,使用该命令继续同步即可.不出意外,5个小时便可以将全部源码同步到本地.所以呢,这个过程可以放在晚上睡觉期间完成.

    (提示:一定要确定代码完全同步了,不然在下面编译过程出现的错误会让你痛不欲生,不确定的童鞋可以多用repo sync同步几次)


    构建编译环境

    源码下载完成后,就可以构建编译环境了.在开始之前,我们先来看看一些编译要求:

    1. 硬件要求:
    64位的操作系统只能编译2.3.x以上的版本,如果你想要编译2.3.x以下的,那么需要32位的操作系统.
    磁盘空间越多越好,至少在100GB以上.意思就是,你可以去买个大点的硬盘了啊
    如果你想要在是在虚拟机运行linux,那么至少需要16GB的RAM/swap.
    (实际上,我非常不推荐在虚拟机中编译2.3.x以上的代码.)

    2. 软件要求:
    1. 操作系统要求
    AOSP开源中,主分支使用Ubuntu长期版本开发和测试的,因此也建议你使用Ubuntu进行编译,下面我们列出不同版本的的Ubuntu能够编译那些android版本:

    Android版本编译要求的Ubuntu最低版本
    Android 6.0至AOSP masterUbuntu 14.04
    Android 2.3.x至Android 5.xUbuntu 12.04
    Android 1.5至Android 2.2.xUbuntu 10.04

    2. JDK版本要求
    除了操作系统版本这个问题外,我们还需要关注JDK版本问题,为了方便,同样我们也列出的不同Android版本的源码需要用到的JDK版本:

    Android版本编译要求的JDK版本
    AOSP的Android主线OpenJDK 8
    Android 5.x至android 6.0OpenJDK 7
    Android 2.3.x至Android 4.4.xOracle JDK 6
    Android 1.5至Android 2.2.xOracle JDK 5

    更具体的可以参看:Google源码编译要求

    我现在在Ubuntu 16.04下编译AOSP主线代码,因此需要安装OpenJDK 8,执行命令如下:
    sudo apt-get install openjdk-8-jdk
    如果你需要在Ubuntu 14.04下编译AOSP主线代码,同样需要安装OpenJDK 8,此时需要执行如下命令:

    sudo apt-get update
    sudo apt-get install openjdk-8-jdk
    

    如果你要编译的是Android 5.x到android 6.0之间的系统版本,需要采用openjdk7.但是在Ubuntu 15.04及之后的版本的在线安装库中只支持openjdk8和openjdk9的安装.因此,如果你想要安装openjdk 7需要首先设置ppa:

    sudo add-apt-repository ppa:openjdk-r/ppa 
    sudo apt-get update
    

    然后再执行安装命令:

    sudo apt-get install openjdk-7-jdk 
    

    有时候,我们需要编译不同版本的android系统,就可能使用不同的jdk版本.关于jdk版本切换,可以使用如下命令:

    sudo update-alternative --config java
    sudo update-alternative --config javac
    

    3. 其他要求

    Google官方构建编译环境指南中已经说明了Ubuntu14.04,Ubuntu 12.04,Ubuntu 10.04需要添加的依赖,这里我们就不做介绍了.我原先以为,Ubuntu16.04的设置和Ubuntu14.04的依赖设置应该差不多,但是只能说too young too simple.
    下面是Ubuntu16.04中的依赖设置:

    sudo apt-get install libx11-dev:i386 libreadline6-dev:i386 libgl1-mesa-dev g++-multilib 
    sudo apt-get install -y git flex bison gperf build-essential libncurses5-dev:i386 
    sudo apt-get install tofrodos python-markdown libxml2-utils xsltproc zlib1g-dev:i386 
    sudo apt-get install dpkg-dev libsdl1.2-dev libesd0-dev
    sudo apt-get install git-core gnupg flex bison gperf build-essential  
    sudo apt-get install zip curl zlib1g-dev gcc-multilib g++-multilib 
    sudo apt-get install libc6-dev-i386 
    sudo apt-get install lib32ncurses5-dev x11proto-core-dev libx11-dev 
    sudo apt-get install libgl1-mesa-dev libxml2-utils xsltproc unzip m4
    sudo apt-get install lib32z-dev ccache
    

    (其中几个命令中参数是重复的,但不妨碍我们)

    初始化编译环境

    确保上述过程完成后,接下来我们需要初始化编译环境,命令如下:

    source build/envsetup.sh
    

    执行该命令结果如下:


    这里写图片描述

    不难发现该命令只是引入了其他执行脚本,至于这些脚本做什么,目前不在本文中细说.
    该命令执行成功后,我们会得到了一些有用的命令,比如最下面要用到的lunch命令.


    编译源码

    初始化编译环境之后,就进入源码编译阶段.这个阶段又包括两个阶段:选择编译目标和执行编译.

    选择编译目标

    通过lunch指令设置编译目标,所谓的编译目标就是生成的镜像要运行在什么样的设备上.这里我们设置的编译目标是aosp_arm64-eng,因此执行指令:

    lunch aosp_arm64-eng
    

    编译目标格式说明
    编译目标的格式:BUILD-BUILDTYPE,比如上面的aosp_arm-eng的BUILD是aosp_arm,BUILDTYPE是eng.

    什么是BUILD

    BUILD指的是特定功能的组合的特定名称,即表示编译出的镜像可以运行在什么环境.其中,aosp(Android Open Source Project)代表Android开源项目;arm表示系统是运行在arm架构的处理器上,arm64则是指64位arm架构;处理器,x86则表示x86架构的处理器;此外,还有一些单词代表了特定的Nexus设备,下面是常用的设备代码和编译目标,更多参考官方文档
    |受型号|设备代码|编译目标|
    |---|----|---|
    |Nexus 6P|angler|aosp_angler-userdebug|
    |Nexus 5X|bullhead|aosp_bullhead-userdebug|
    |Nexus 6|shamu|aosp_shamu-userdebug|
    |Nexus 5|hammerhead|aosp_hammerhead-userdebug|

    提示:如果你没有Nexus设备,那么通常选择arm或者x86即可

    什么是BUILDTYPE

    BUILD TYPE则指的是编译类型,通常有三种:
    -user:代表这是编译出的系统镜像是可以用来正式发布到市场的版本,其权限是被限制的(如,没有root权限,不鞥年dedug等)
    -userdebug:在user版本的基础上开放了root权限和debug权限.
    -eng:代表engineer,也就是所谓的开发工程师的版本,拥有最大的权限(root等),此外还附带了许多debug工具

    了解编译目标的组成之后,我们就可以根据自己目前的情况选择了.那不知道编译目标怎么办?
    我们只需要执行不带参数的lunch指令,稍后,控制台会列出所有的编译目标,如下:


    这里写图片描述

    接着我们只需要输入相应的数字即可.

    来举个例子:你没有Nexus设备,只想编译完后运行看看,那么就可以选择aosp_arm-eng.
    (我在ubuntu 16.04(64位)中编译完成后启动虚拟机时,卡在黑屏,尝试编译aosp_arm64-eng解决.因此,这里我使用了aosp_arm64-eng)

    开始编译

    通过make指令进行代码编译,该指令通过-j参数来设置参与编译的线程数量,以提高编译速度.比如这里我们设置8个线程同时编译:

    make -j8
    

    需要注意的是,参与编译的线程并不是越多越好,通常是根据你机器cup的核心来确定:core*2,即当前cpu的核心的2倍.比如,我现在的笔记本是双核四线程的,因此根据公式,最快速的编译可以make -j8.
    (通过cat /proc/cpuinfo查看相关cpu信息)

    如果一切顺利的化,在几个小时之后,便可以编译完成.看到### make completed successfully (01:18:45(hh:mm:ss)) ###表示你编译成功了.


    运行模拟器

    在编译完成之后,就可以通过以下命令运行Android虚拟机了,命令如下:

    source build/envsetup.sh
    lunch(选择刚才你设置的目标版本,比如这里了我选择的是2)
    emulator
    

    如果你是在编译完后立刻运行虚拟机,由于我们之前已经执行过source及lunch命令了,因此现在你只需要执行命令就可以运行虚拟机:

    emulator
    

    不出意外,在等待一会之后,你会看到运行界面:


    这里写图片描述

    补充
    既然谈到了模拟器运行,这里我们顺便介绍模拟器运行所需要四个文件:

    1. Linux Kernel
    1. system.img
    2. userdate.img
    3. ramdisk.img

    如果你在使用lunch命令时选择的是aosp_arm-eng,那么在执行不带参数的emualtor命令时,Linux Kernel默认使用的是/source/prebuilds/qemu-kernel/arm/kernel-qemu目录下的kernel-qemu文件;而android镜像文件则是默认使用source/out/target/product/generic目录下的system.img,userdata.img和ramdisk.img,也就是我们刚刚编译出来的镜像文件.

    上面我在使用lunch命令时选择的是aosp_arm64-eng,因此linux默认使用的/source/prebuilds/qemu-kernel/arm64/kernel-qemu下的kernel-qemu,而其他文件则是使用的source/out/target/product/generic64目录下的system.img,userdata.img和ramdisk.img.
    当然,emulator指令允许你通过参数制定使用不同的文件,具体用法可以通过emulator --help查看


    模块编译

    除了通过make命令编译可以整个android源码外,Google也为我们提供了相应的命令来支持单独模块的编译.

    编译环境初始化(即执行source build/envsetup.sh)之后,我们可以得到一些有用的指令,除了上边用到的lunch,还有以下:

      - croot: Changes directory to the top of the tree.
      - m: Makes from the top of the tree.
      - mm: Builds all of the modules in the current directory.
      - mmm: Builds all of the modules in the supplied directories.
      - cgrep: Greps on all local C/C++ files.
      - jgrep: Greps on all local Java files.
      - resgrep: Greps on all local res/*.xml files.
      - godir: Go to the directory containing a file.
    

    其中mmm指令就是用来编译指定目录.通常来说,每个目录只包含一个模块.比如这里我们要编译Launcher2模块,执行指令:

    mmm packages/apps/Launcher2/
    

    稍等一会之后,如果提示:
    ### make completed success fully ###
    即表示编译完成,此时在out/target/product/gereric/system/app就可以看到编译的Launcher2.apk文件了.

    重新打包系统镜像
    编译好指定模块后,如果我们想要将该模块对应的apk集成到系统镜像中,需要借助make snod指令重新打包系统镜像,这样我们新生成的system.img中就包含了刚才编译的Launcher2模块了.重启模拟器之后生效.

    单独安装模块
    我们在不断的修改某些模块,总不能每次编译完成后都要重新打包system.img,然后重启手机吧?有没有什么简单的方法呢?
    在编译完后,借助adb install命令直接将生成的apk文件安装到设备上即可,相比使用make snod,会节省很多事件.

    补充
    我们简单的来介绍out/target/product/generic/system目录下的常用目录:
    Android系统自带的apk文件都在out/target/product/generic/system/apk目录下;
    一些可执行文件(比如C编译的执行),放在out/target/product/generic/system/bin目录下;
    动态链接库放在out/target/product/generic/system/lib目录下;
    硬件抽象层文件都放在out/targer/product/generic/system/lib/hw目录下.


    SDK编译

    如果你需要自己编译SDK使用,很简单,只需要执行命令make sdk即可.


    错误集合

    在编译过程中,遇到的大部分错误都可以在google搜到解决方案.这里只列举几个常见的错误:
    错误一: You are attemping to build with the incorrect version.具体错误如下:

    这里写图片描述

    如果你认真看了构建环境的的要求,那么这个错误是可以避免的.当然,这个问题也很容易解决:安装openjdk 8,别忘了使用sudo update-alternative命令切换jdk版本.

    错误二: Out of memory error.具体错误如下:

    这里写图片描述

    这个错误比较常见,尤其是在编译AOSP主线代码时,常常会因为JVM heap size太小而导致该错误.
    此时有两种解决方法:
    方法一:
    在编译命令之前,修改prebuilts/sdk/tools/jack-admin文件,找到文件中的这一行:
    JACK_SERVER_COMMAND="java -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -cp $LAUNCHER_JAR $LAUNCHER_NAME"
    然后在该行添加-Xmx4096m,如:
    JACK_SERVER_COMMAND="java -Djava.io.tmpdir=$TMPDIR $JACK_SERVER_VM_ARGUMENTS -Xmx4096m -cp $LAUNCHER_JAR $LAUNCHER_NAME"
    然后再执行time make -8j

    方法二:
    在控制台执行以下命令:

    export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4096m"
    out/host/linux-x86/bin/jack-admin kill-server
    out/host/linux-x86/bin/jack-admin start-server
    

    如图:


    这里写图片描述

    执行完该命令后,再使用make命令继续编译.某些情况下,当你执行jack-admin kill-server时可能提示你命令不存在,此时去你去out/host/linux-x86/bin/目录下会发现不存在jack-admin文件.如果我是你,我就会重新repo sync下,然后从头来过.

    错误三:使用emulator时,虚拟机停在黑屏界面,点击无任何响应.此时,可能是kerner内核问题,解决方法如下:
    执行如下命令:

    ./out/host/linux-x86/bin/emulator -partition-size 1024 -kernel ./prebuilts/qemu-kernel/arm/kernel-qemu-armv7 
    
    

    通过使用kernel-qemu-armv7内核 解决模拟器等待黑屏问题.而-partition-size 1024 则是解决警告: system partion siez adjusted to match image file (163 MB >66 MB)

    如果你一开始编译的版本是aosp_arm-eng,使用上述命令仍然不能解决等待黑屏问题时,不妨编译aosp_arm64-eng试试.


    结束吧

    到现在为止,你已经了解了整个android编译的流程.除此之外,我也简单的说明android源码的多仓库管理机制.下面,不妨自己动手尝试一下.

    展开全文
  • 160多个android开源代码汇总

    千次阅读 2018-10-02 18:42:38
    第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView、ActionBar、Menu、ViewPager、Gallery、GridView、ImageView、ProgressBar、TextView、ScrollView、TimeView、TipView、FlipView、...
  • android代码在线查看

    千次阅读 2018-11-21 11:15:22
    android代码在线查看 android代码各个版本在线查看网址 android报bug路径: android上code reiview路径: android代码在线查看 android代码各个版本在线查看网址 http://androidxre...
  • Android代码优化

    2019-03-15 10:58:08
    为性能设计: 1)避免创建对象 对象的创建从来不是免费的。虽然GC使得内存申请代价不再高昂,但是申请总是比不申请来得昂贵。如果你在一个用户接口循环中申请对象,你将会强行执行周期性的GC,在用户体验上...
  • Android代码中设置控件属性

    千次阅读 2017-07-10 14:48:38
    Android代码中设置控件属性在项目的开发过程中时常会需要在java代码中设置控件的宽高,位置,显示与隐藏等属性。我们可以理解为在布局文件中可以设置的属性,都可以在java代码中来完成,甚至我们可以不需要布局文件...
  • android 代码重启app

    千次阅读 2019-06-21 08:58:41
    android 代码重启app方法完事 方法 /** * 重启app * @param context */ public static void restartApp(Context context) { PackageManager packageManager = context.getPackageManager(); ...
  • 移动开发者最爱的9个优秀Android代码编辑器 在网络信息高速发展的今天,移动设备的方便快捷已经深入人心,越来越多的开发人员会选择在移动设备上查看或编辑源代码。于是,Android平台上大量基于代码编程的应用...
  • Android代码混淆之混淆规则

    万次阅读 热门讨论 2015-04-17 10:44:07
    因为Android是使用Java开发的,所以开发者可以使用ProGuard对代码进行混淆。SDK已经集成了ProGuard工具,开发者可以从SDK目录下的\tools\proguard目录中进行查看。  ProGuard是一个免费的Java类文件收缩,优化,...
  • Android代码生成器使用说明

    千次阅读 2017-01-11 15:44:50
    Android代码生成器使用说明
  • Android 代码混淆及第三方jar包不被混淆 为了保护代码被反编译,android引入了混淆代码的概念。 1.设置混淆 在工程下找到project.properties文件 在文件中加入proguard.config=${sdk.dir}/tools/proguard/proguard-...
  • android代码运行cmd命令截屏

    万次阅读 2014-09-23 10:56:21
    android代码中使用adb命令来截屏 直接在PC上cmd下可调用adb shell screencap -p /sdcard/screenshot.png来截屏,截取到的内容将包括在线视频等原本需要单独处理的内容。 使用过在ondraw()里面获取cache或者view...
  • Android代码中设置字体大小,字体颜色,显示两种颜色 在xml文件中字体大小用的像素 &lt;TextView android:id="@+id/uppaid_time" android:layout_width="wrap_content" android:...
  • Android代码命名规范

    千次阅读 2019-08-23 16:49:38
    1、为什么 规范 Android 代码命名? 增强代码的可读性 增强代码的可维护性 正由于上述两个作用,从而使得 开发效率 & 维护效率 得到大幅度的提高。 2、Android需要命名的代码(对象)有哪些? 3、具体命名...
  • Android 代码设置 控件背景颜色

    千次阅读 2015-12-09 15:48:39
    Android 代码设置 控件背景颜色
1 2 3 4 5 ... 20
收藏数 1,144,594
精华内容 457,837
关键字:

android代码