精华内容
下载资源
问答
  • Android R新特性:针对Android R 的应用

    万次阅读 2020-03-03 22:03:06
    Android 11平台包括可能会影响你的应用程序的行为更改。以下行为更改适用于在Android 11上运行的所有应用,无论targetSdkVersion如何,你应该测试你的应用程序,然后根据需要对其进行修改以适当地支持它们.

    Android 11平台包括可能会影响你的应用程序的行为更改。以下行为更改适用于在Android 11上运行的所有应用,无论targetSdkVersion如何,你应该测试你的应用程序,然后根据需要对其进行修改以适当地支持它们.

    注意:除了此页面上列出的更改外,Android 11还引入了大量更改和限制以增强用户隐私。后面会陆续更新。

     

    Scoped storage


    为了给开发人员更多的测试时间,面向Android 10(API级别29)或更低版本的应用仍可以请求requestLegacyExternalStorage属性。此标志允许应用程序暂时退出与范围存储相关的更改,例如授予对不同目录和不同类型媒体文件的访问权限。但是,当你将应用更新为Android 11时,将无法使用requestLegacyExternalStorage,并且没有其他可用选项提供退出功能。


    Directory access restrictions


    如果你的应用面向Android 11并使用存储访问框架(SAF),则无法再使用ACTION_OPEN_DOCUMENT和ACTION_OPEN_DOCUMENT_TREE 这些action来访问某些目录。


    Storage permissions


    如果你的应用以Android 11为目标,则与存储权限相关的若干行为更改将生效,后面博客会更新详细信息


    MAC randomization


    在针对Android 10(API级别29)及更低版本的应用上,MAC随机化是按SSID进行的,因为Passpoint可以连接到同一配置文件的不同SSID。在针对Android 11(API级别“ R”)及更高版本的应用中,Passpoint网络的MAC随机化已更改为每个完全合格的域名(FQDN)。


    Netlink MAC restrictions


    在以API等级R或更高级别为目标的应用程序上,非特权应用程序将无法访问设备的MAC地址;只有具有IPv4地址的网络接口才可见。这会影响getifaddrs()和NetworkInterface.getHardwareAddress()方法,以及发送RTM_GETLINK网络链接消息。这是“不适用于MAC地址”中提供的指导的强制实施



         从Android 11 Developer Preview 1开始,尚未完全实现所有这些更改。下表描述了所有非系统应用程序的当前功能,无论目标API级别如何:
        所有网络接口都可以通过NetworkInterface和getifaddrs()获得
        对于具有MAC地址的接口,NetworkInterface.getHardwareAddress()返回02-00-00-00-00-00
        应用程序可以在NETLINK_ROUTE套接字上使用bind()函数
        应用程序开发人员可以调用IP命令以获取有关接口的信息

    上面的列表是对当前行为的描述,但是你不应依赖于它来更新应用程序,因为此部分顶部的描述将与稳定版Android 11一起发布。

    请注意,大多数开发人员应使用ConnectivityManager的较高级别的API,而不是较低级别的NetworkInterface / getifaddrs()API。
     

    展开全文
  • Android R.java类的手动生成

    万次阅读 2016-02-25 16:36:10
    Android中的资源和R.java类 在Android项目中的res目录中包含了项目使用的各种资源,这些资源全部都分布在res目录下的各个子目录中。每个资源都有两个属性,一个是资源的名字,一个是资源的类型。此外,res目录下的...

    Android中的资源和R.java类

    在Android项目中的res目录中包含了项目使用的各种资源,这些资源全部都分布在res目录下的各个子目录中。每个资源都有两个属性,一个是资源的名字,一个是资源的类型。此外,res目录下的资源在编译后都会有一个对应的id。

    R.java类(以下简称R类)是Android中一个非常重要的类,其中定义了res目录中全部资源的id。在代码中通过R类获取到资源的id后,即可调用Android API来获取和使用对应的资源。例如:

    ImageView imageView = (ImageView)findViewById(R.id.imageView);
    TextView textView = (TextView)findViewById(R.id.textView);
    imageView.setImageResource(R.drawable.bg)
    textView.setText(R.string.app_name)

    R类的生成

    R类并不包含在项目代码中,而是由Android SDK在编译阶段通过aapt工具生成的。一般情况下,开发者不需要关注R类的生成,直接在代码中使用即可。然而在某些情况下需要由开发者手动生成R类,并放到项目代码中。

    为什么需要手动生成R.java类

    Android library

    Android 项目根据用途的不同分为app项目和library项目。app项目用来生成可以在Android系统上运行的apk程序,提交到应用市场给用户使用。而library项目并不会生成apk,而是生成一个sdk,提供给其他开发者使用。

    对library项目来说,如果library工程中包含了资源,如layout,drawable,string,dimen等,那么需要将这些资源文件和编译后的代码一起放到sdk中。对Eclipse library工程,是将整个res目录原样放到sdk中。对Android Studio的library工程,会将整个res目录打包到aar文件中。

    Android library工程中的R类

    对包含资源的library工程来说,和app工程一样,需要在代码中通过资源id来获取对应的资源。同样可以在library工程代码中通过library工程包名下的R类来获取对应资源的id。但是library工程中的R类并不会包含在library工程编译后的jar包或arr包中,也就是说,library工程开发完成后,提供给其他开发者的sdk中并没有包含这个R类。这个R类同样是在app工程编译时生成的。那么app工程在编译时是如何知道需要生成library工程包名下的R类呢?

    一个app工程可以包含多个library工程(在Android Studio中称为module)。当一个app工程在编译时,会遍历其所引用的所有library工程,生成各个library工程对应的R.java类。这里会用到每个library sdk中提供的另外一个文件AndroidManifest.xml。在library工程的AndroidManifest.xml文件中包含了各个library工程的包名称,通过这个文件就可以知道各个library工程的包名,从而生成各个library工程包名下的R类。

    例如,一个被引用的library工程中的AndroidManifest.xml文件中配置的package=”com.cclink.mylib”,则app工程在编译时会为该library工程生成一个com.cclink.mylib.R的类。

    最后app工程中全部java代码,app工程的R类,所有library工程的R.java类,都会被编译,并和所有library工程的jar包合并到一起,然后再转换成dex文件。

    Android library sdk的特殊使用方式

    一个library工程开发完成后会以sdk的形式提供给其他开发者来使用。如前所述,其他开发者在开发app时,如果通过引用的方式来使用该library sdk,则app工程编译时会自动为该library sdk下的资源生成一个对应的R类,并打包到apk中。
    然后,app的开发者并不总是希望通过在Android Studio中添加工程引用的方式来使用一个library sdk。他们有时需要将library sdk中的jar和res直接拷贝到app工程来使用,有时需要将所有依赖的sdk中的jar和res拷贝到一起,合并成一个library来使用。
    这样做有时是为了方便,减少工作量,有时则是没有办法通过工程引用方式来使用library。这在游戏开发时非常常见。很多游戏引擎只提供了一个目录,用来放置各类第三方的Android插件,根本就找不到一个Android的主工程,来建立引用关系。APK的编译打包也是在游戏引擎中封装好了,并不需要通过Eclipse或Android Studio来打包。
    例如,Unity3D中通常都是将Android插件(也就是Android library工程对应的sdk)直接拷贝到/Assets/Plugins/Android目录中来使用,虽然Unity3D提供了导出Android工程的功能,但使用起来非常麻烦。开发者很可能不希望这样去做。

    Android library sdk特殊使用方式带来的问题

    如果将sdk中的文件拷贝到app工程中来使用,或者合并所有的sdk到一个library中,由于这时所有library都混合在一起,app在编译时根本就找不到原先各个library中的AndroidManifest.xml文件,也就不会为各个library生成对应的R.java类。当app在运行时,library中代码由于找不到对应的R类,会出现ClassNotFound的异常。Unity虽然支持各个sdk分开存放,不需要将sdk合并到一起,但是Unity编译生成的apk文件中不会包含任何R类,即使是app包名下的R类也不会生成。

    解决没有R类带来的问题

    要解决没有R类的问题,需要从两个角度来考虑。

    从library开发者的角度来看,需要让library工程编译后的sdk在这种没有R类情况下能够正常使用。为了达到此目的,需要将代码中所有通过包名下R类来获取资源id的方式替换为其他的实现方式。Android SDK提供了getResources().getIdentifier()方法来获取资源id,library开发者可以手动将代码中所有需要使用资源id的地方用这种方式来获取。但getResources().getIdentifier()的参数是资源的名字,是一个字符串,这样在获取资源id时,就不能使用IDE的代码提示,自动补全等功能了。

    从app开发者的角度来看,如果需要使用的sdk没有对这种使用方式做兼容,而且不能通过引用方式来使用该sdk时,需要能够让该sdk打包到apk后能够正常运行。为了达到此目录,需要为该sdk生成一个该sdk包名下的R类,然后将该R类编译打包到apk中。这样sdk中的代码在运行就不会找不到对应的R类了。

    AndroidRClassGenerator工具

    AndroidRClassGenerator是一个用来生成R.java类的Python脚本,基于Python2.7版本。它可以以两种方式生成R.java类。工具下载地址附在文章最后。
    对library开发者来说,AndroidRClassGenerator能够生成一个新的R类,新的R类中使用了不同的方式来获取资源id,同时提供了和原先R类一样的资源访问的方式。因此,library开发者可以像开发app一样使用R类来获取资源,只需要将代码中原先的import R类的信息替换替换为新的R类即可访问到对应的资源id。AndroidRClassGenerator可同时生成R类,并完成代码中import信息的替换。
    对app开发者来说,AndroidRClassGenerator可以根据library工程中的res目录,和指定的包名来生成对应的R类。

    参数配置

    在使用前需要先配置config.ini,config.ini中各个参数的含义如下。

    1. ProjectOrResDir:表示library工程的路径(可以是Eclipse的工程,也可以是Android Studio的工程)。也可以直接指定到某个资源目录。
    2. sdkdir:Android SDK的路径
    3. RClassPackage:要生成的目标R类的包名
    4. ReplaceCode:是否替换代码中的import信息,true表示替换,false表示不替换。
      例如library工程的包名为x.y.z,RClassPackage为a.b.c,则当ReplaceCode为true时除了会生成一个a.b.c.R.java类外,还会自动将代码中所有的import x.y.z.R,改为import a.b.c。然代码通过新生成的R类来获取资源id。
      只有ProjectOrResDir配置的library工程的路径时此参数才有效,当ProjectOrResDir配置的是资源目录时,此项配置会被忽略。

    library开发者的使用方法

    对library开发者来说,需要生成一个包含指定包名的R类放到代码中,然后将其他代码中所有用到默认R类(即该library工程包名下R类)的地方都替换为生成的R类。
    具体配置流程如下。

    1. 配置ProjectOrResDir为工程的路径,可以是Eclipse的工程,也可以是Android Studio的工程。
    2. 配置sdkdir为本地的Android SDK的路径
    3. 配置RClassPackage为需要生成的R类的包名,此包名不可和library的包名完全相同。以免在工程编译时出现相同类名的编译错误。
    4. ReplaceCode一般应配置为true。如果已经替换过一次,且没有新的代码需要替换,可以设置为false。
    5. 运行RClassGenerator.py
    6. 在library工程入口代码处(例如初始化,或者第一个界面显示时)调用新生成R类的R.init(context)方法,context是某个Context对象。

    app开发者的使用方法

    对app开发者来说,需要生成一个包含library包名的R类放到app工程的代码中。
    具体配置流程如下。

    1. 如果是Eclipse或完整的Android Studio的library工程,配置ProjectOrResDir为library工程中res目录的路径,如果是单独的aar文件,需要先将res目录从aar文件中解压出来,然后配置ProjectOrResDir为解压后的res目录路径。
    2. 配置sdkdir为本地的Android SDK的路径。
    3. 配置RClassPackage为library的包名,library的包名可以在library工程,或aar压缩包中的AndroidManifest.xml文件中找到。
    4. ReplaceCode参数在ProjectOrResDir配置为资源目录时会被自动忽略。这里不需要配置。
    5. 运行RClassGenerator.py。
    6. 生成的R.java类在res目录的同级目录中,将生成的R类拷贝到app项目中,这可能是一个app工程,也可能是工程中某个可以编辑java代码的目标,有时甚至需要手动将R类编译成class并打包成jar放到app工程中。
    7. 在app工程某个入口处调用新生成R类的R.init(context)方法,context是某个Context对象。这可能是在主Activity的onCreate()中调用,也可能是通过jni方式调用。

    实现原理

    通过用AndroidRClassGenerator生成R类代替了原本应该在app编译时生成的R类,用这种方式来让library中代码能够正确的得到资源id。由于资源id只有在apk编译时才能最终确定,所以AndroidRClassGenerator生成的R类不能用某次编译时的常量来代替。
    有两种方式可以获取到资源id:一种是通过反射app包名下的R类来获取,一种是通过context.getResources().getIdentifier()方法来获取。
    通过反射方式来获取资源id的原理是,虽然app编译时不会为每个library生成单独的R类,但是仍然会生成一个app包名下的R类,这个R类中包含了所有library中的资源id(当然也还包含app自身的全部资源的id),通过反射读取这个R类,可以得到对应的资源id。
    context.getResources().getIdentifier()是android sdk提供的一个api,通过此接口可以获取到指定类型,指定名称的资源id。
    AndroidRClassGenerator生成的R类同时包含了这两种实现方式,它首先会尝试通过反射方式来获取系统资源id,如果反射方式获取失败,再尝试用context.getResources().getIdentifier()方式来获取。
    之所以先用反射方式来获取资源id,是因为反射方式比context.getResources().getIdentifier()方式要快得多。但反射方式的缺点是必须要存在一个app包名下的R类。如果这个类不存在(例如,通过Unity3D直接编译出的apk中就不包含R类),则反射方式失效。
    无论有没有app包名下的R类,context.getResources().getIdentifier()都能够获取到资源id,但context.getResources().getIdentifier()方式比反射方式要慢一些。

    工具路径:http://download.csdn.net/download/ccpat/9443653

    Android Studio的打包问题

    Android Studio从某个版本(具体哪个版本没有去考究)开始,在编译时会自动删除项目中的R.class类,这样在运行时会出现找不到R类的问题。这时只需要在脚本中将R.java类改为一个其他的名字就可以了。也就是将”public final class R”改为”public final class XXXR”,同时将destRClassFile = os.path.join(filePath, ‘R.java’)改为destRClassFile = os.path.join(filePath, ‘XXXR.java’)。

    展开全文
  • Android高版本P/Q/R源码编译指南

    千次阅读 多人点赞 2021-01-04 20:27:17
    文章目录        AndroidP/Q/R编译系统引言一.Android编译整体概述1.1 Kati构建编译系统1.2 Blueprint和Soong构建编译系统1.2.1 Soong简介1.2.2 Blueprint简介1.2.3 Android.bp简介1.2.4 Ninja简介二....

           Android高版本P/Q/R源码编译指南


    Android源码编译系列博客:

    Android.bp你真的了解吗
    Android.bp入门指南之Android.mk转换成Android.bp
    Android.bp入门指南之浅析Android.bp语法
    Android.bp正确姿势添加宏控制编译指南
    Android高版本P/Q/R源码编译指南
    如何在线查看Android源码自带学习文档docs


    本篇博客编写思路总结和关键点说明:
    在这里插入图片描述

    为了更加方便的读者阅读博客,通过导读思维图的形式将本博客的关键点列举出来,从而方便读者取舍和阅读!



    引言

      时代在进步,第三套少儿广播体操!不好意思,搞错频道了,重来!时代在进步,Android的版本也是快速的进行着迭代着,从我们以前最常见的Android 4.4一直发展到了今天的Android 11版本(即Android K到Android R),Android版本的快速迭代对于消费者来说是一件普天同庆的大好事情,但是对于我们开发者来说各种适配各种改造有时候吃翔的心情都有了。而对于Android版本的适配和各种改造的第一步就是从编译Android源码开始,可是不幸的是随着Android版本的迭代连编译Android源码的相关流程都发生了翻天覆地的变化,正所谓工欲利其事必先利器,所以我们今天的这篇博客将带领读者一起来捯饬捯饬Android各个版本的源码编译发展和编译具体操作步骤!

    这里我们需要注意一下Android各个版本的对应关系如下:

    • Android 5.x (Lollipop)简称Android L版本
    • Android 6.0 (MarshMallow) 简称Android M版本
    • Android 7.x (Nougat)简称Android N版本
    • Android 8.x (Oreo)简称Android O版本
    • Android 9.0 (Pie)简称Android P版本
    • Android 10.0 (Q)简称Android Q版本
    • Android 11.0 (R)简称Android R版本

    并且这里还有一点需要特别注意,本文演示的Android R版本是以高通平台为基准进行的。




    一.Android编译环境的构建以及常见命令

      俗话说天时地利人和缺一不可,而这其中的地利翻译过来说的就是环境因素了,人的成长离不开环境因素,而我们的Android编译也离不开编译环境的构建!虽然我们本篇博客的主题是Android源码编译指南,但是我们还是有必要抽出一个章节来简单说明下Android编译环境的构建和初始化过程,以及初始化完毕后常见的命令。


    1.1 Android编译环境的构建

    本章节重点偏向的是Android编译环境的构建,而不是编译环境构建的原理分析(如果是原理分析,那内容就多了,关于Android编译墙裂推荐一篇博客来自IBM社区理解 Android Build 系统,你值得拥有!)。

    虽然Android的版本一直在迭代着,但是Android编译环境的构建步骤还是比较良心的依然没有多大的变化(注意这里的措辞,只是步骤),对于有过Android源码开发经验的读者来说是再为熟悉不过的了,通常是如下二部曲:

    $ source build/envsetup.sh
    $ lunch aosp-eng
    

    虽然各位对上述的命令应该已经烂熟于心了,但是这里我还是简单说明一下:

    • 第一行命令”source build/envsetup.sh”引入了build/envsetup.sh 脚本。该脚本的作用是初始化编译环境,并引入一些辅助的Shell函数,这其中就包括第二步使用 lunch 函数

    • 第二行命令”lunch aosp-eng”是调用 lunch 函数,并指定参数为”aosp-eng”。lunch 函数的参数用来指定此次编译的目标设备以及编译类型。在这里,这两个值分别是”aosp”和”eng”。”aosp”是 Android 源码中已经定义好的一种产品,是为模拟器而设置的。而编译类型会影响最终系统中包含的模块。如果在调用lunch函数的时候没有指定参数,那么该函数将输出列表以供选择,列表内容不同Android版本,不同厂家的基线源码会有所不同,如下:

    在这里插入图片描述


    这里补充一点对Android的源码编译类型简单说明一下,它可以分为如下三种功能,每种类型的特点如下:

    在这里插入图片描述



    1.2 Android编译各种常见命令

    在编译环境初始化完成后,我们就可以使用各种各种编译环境提供的指令和make编译命令族来开启Android的构建之旅了,这里我简单的总结了下,我们在Android编译中可能会用到的编译环境提供的指令和make编译命令族,如下:

    1.2.1 常见的Android命令指令

    指令说明
      croot   切到Android源码树的根目录(当你深入Android源码树的子目录,想回到根目录的时候此命令就非常实用了)
    m相当于在源码树的根目录执行make,并且该命令不一定要在根目录下执行
    mm编译当前目录路径下的所有模块(包括include进来的,但是不包括存在依赖关系模块)
    mma编译当前目录路径下的所有模块(包括include进来的,且包括存在依赖关系模块)
    mmm[module_path]编译指定目录路径下的所有模块(包括include进来的,但是不包括存在存在依赖关系模块)
    mmma[module_path]编译指定目录路径下的所有模块(包括include进来的,包括存在存在依赖关系模块)
    cgrep对C/C++文件执行grep(即grep的时候只搜寻C/C++文件类型,注意这里也包括.h文件类型)
    jgrep对Java文件执行grep(即grep的时候只搜寻Java文件类型)
    resgrep在所有res/.xml文件上执行 grep即grep的时候只搜寻res/.xml文件类型)
    printconfig显示当前Android编译的相关配置信息
    add_lunch_combo在lunch命令的的菜单中添加一个条目

    这里我们对上述表格中的"不包括存在依赖关系的模块"简单解释一下:
    1.依赖关系模块这个要怎么说呢,这里我们举个栗子!譬如模块A的编译需要依赖模块B,此时的B是一个so库。
    2.假如我们通过mm或者mmm编译模块A的时候,此时B模块还没有编译那么此时就会报错
    3.假如我们使用的是mma或者mmma编译模块A,假如依赖的模块B还没有编译,那么会先将模块B编译OK,然后编译模块A(当然这里只是举栗子,可能A还依赖C,D同理也会先编译)

    1.2.2 make编译命令族

    Android的Build编译系统处理常见的make单命令之外,还提供了其它的一系列make命令族,这里我们简单过下:

    指令说明
    make update-api更新API文件,在framework API改动之后,需要首先执行该命令来更新API,公开的API记录在frameworks/base/api目录下
    makeAndroid默认系统编译指令,会编译出整个系统的所有镜像(其实质最终执行的是make droid)
    make droid同上
    make sdk编译出Android的SDK开发套件
    make clean-sdk清理SDK的编译产物
    make dist执行整个编译,并将 MAKECMDGOALS变量定义的输出文件拷贝到 /out/dist目录下,
    这个命令在实际中用的比较少
    make all编译所有内容,不管当前产品的定义中是否会包含,官方解释如下:
    builds everything make droid does,plus everything whose LOCAL_MODULE_TAGS do not include the “droid” tag. The build server runs this to make sure that everything that is in the tree and has an Android.mk builds.
    make help帮助信息命令,显示当前Android版本主要支持的make命令
    make snod从已经编译出的包快速构建系统镜像(譬如你重新单独编译了某个模块,然后想快速进行打包到system.img,可以使用此命令加快速度)
    make clean-$(LOCAL_MODULE)Let you selectively clean one target. For example, you can type make clean-libutils and t will delete libutils.so and all of the intermediate files.
    即清理掉一个指定模块的编译结果和中间产物
    make clean-$(LOCAL_PACKAGE_NAME)Let you selectively clean one target. For example, you can type
    make clean-Home and it will clean just the Home app…
    即清理掉一个指定模块的编译结果和中间产物
    make cleandeletes all of the output and intermediate files for this configuration. This is the same as rm -rf out/<configuration>/
    通常删除的是整个Android源码工程的out/*目录
    make clobberdeletes all of the output and intermediate files for all configurations. This is the same as rm -rf out/.
    这个命令在实际中,应用得比较少
    make datacleandeletes contents of the data directory inside the current combo
    directory. This is especially useful on the simulator and emulator, where the persistent data remains present between builds.
    这个命令在实际中应用得也比价少
    make installclean当我们在执行切换编译目标时可以执行make installclean,用以清除之前编译生成的文件,但是又不会将整个out目录清空,这样可以加快编译目标的构建速度
    make LOCAL_MODULE编译一个指定的模块,LOCAL_MODULE 为模块的名称,这种编译方法通常运用在整个Android工程没有构建,但是想快速编译一个模块时可以使用,可以加快单个模块构建速度
    make targetswill print a list of all of the LOCAL_MODULE names you can make.
    make libandroid_runtime编译所有JNI framework内容。
    make framework编译所有Javaframework内容(做Android framework开发的小伙们对这条命令应该是再熟悉不过的了)。
    make services编译系统服务和相关内容
    make bootimage编译生成boot.img
    make recoveryimage编译生成recovey.img
    make cacheimage编译生成cache.img
    make systemimage编译生成system.img
    make vendorimage编译生成vendor.img
    make superimage编译生成superi.img

    对上述的make命令有几点需要注意:
    1.可能在不同的Android版本有不同表现,且有的可能已经不支持了
    2.读者最好对于每个make编译命令,自行使用一番,然后慢慢品尝




    二.Android编译的发展史简介

      有过一定Android开发经验的读者应该知道Android最初是用Android.mk配置来编译源码的(这里的Android.mk本质上有点类似Makefile文件)。但是随着Android版本的迭代,源码工程文件越来越大,包含的模块越来越多,而以Android.mk组织的项目编译花费的时间越来越多。面对这个严峻的问题,Android的妈咪谷歌终于在在Android7.0开始引入了ninja编译系统。相对于make来说ninja在大的项目管理中速度和并行方面有突出的优势,因此Google采用了ninja来取代之前使用的make。由于Android.mk的数量巨大且复杂,不可能把所有的Android.mk改写成ninja的构建规则,因此Google搞了个kati工具,用于将Androd.mk转换成ninja的构建规则文件build.ninja,再使用ninja来进行构建工作。

      Android编译的发展依然没有停止进化,果不其然Android8.0开始,Google引入了Android.bp文件来替代之前的Android.mk文件,Android.bp只是纯粹的配置文件,不包括分支、循环等流程控制,本质上就是一个json配置文件。同时还引入Soong这个工具,用于将Android.bp转换为ninja的构建规则文件build.ninja,再使用ninja来进行构建工作。但之前的模块全部是用Android.mk来定义的,google不可能一下子把所有模块都修改成Android.bp,只能逐步替换。无论是Android.mk还是Android.bp最后都是转化成ninja的构建规则,再进行编译的。

    如果你对上述的概述,还是觉得太啰嗦了,没有关系。这里我们用更加简单的文字来整体来概括一下Android build系统随着Android版本相应的发展演变过程:

    • Android 7.0引入ninja和kati
    • Android 8.0使用Android.bp来替换Android.mk,引入Soong
    • Android 9.0强制使用Android.bp

    2.1 Soong、Blueprint、Kati、Ninja关系

    通过前面的章节,我们简单介绍了Android编译系统的发展史!读者会发现,其中突然一下子冒出了许多的概念,这里我们先暂且不对其中涉及的概念深入了解,我们先说说上述几个概念Soong、Blueprint、Kati、Ninja之间的关系,它们之间的关系图如下:

    在这里插入图片描述

    上图是一个静态的整体的关系图,但是在Android源码工程构建过程中的它们之间可以使用如下的转换关系图来表示:

    在这里插入图片描述

    关系图已经给各位看官摆出来了,那么它们之间的转换关系是怎么来的呢,这里我们来说说:

    • 首先通过Kati将Android.mk转换成ninja格式的文件
    • 通过androidmk将将Android.mk转换成Android.bp,但是只针对没有分支、循环等流程控制的Android.mk才有效,如果对于有控制流的就必须手动了具体可以想见博客Android.bp正确姿势添加宏控制编译指南
    • 通过Blueprint+ Soong将Android.bp转换成ninja格式的文件

    不容易啊,这里我们对涉及到Ninja, kati, Soong, bp关系搞清楚了(各种三角恋)!那么关于它们的概念,接下来我们也得简单介绍介绍,安排上才行!


    2.2 Kati简介

    Kati是专为Android开发的一个基于Golang和C++的工具,主要功能是把Android中的Android.mk文件转换成 Ninja文件。代码路径是build/kati,编译后的产物是ckati。

    Kati代码是开源的,可以把它clone下来,如果感兴趣可以查看下其实现原理

    这里我们构建一个通过Android.mk配置的LOCAL_MODULE模块,然后通过top命令就可以查看在编译的过程中执行了ckati的命令。
    在这里插入图片描述



    2.3 Ninja简介

    ninja是一个编译框架,会根据相应的ninja格式的配置文件进行编译,但是ninja文件一般不会手动修改,而是通过将Android.bp文件转换成ninja格文件来编译。


    2.4 Android.bp简介

    Android.bp的出现就是为了替换Android.mk文件。而bp跟mk文件不同,它是纯粹的配置,没有分支、循环等流程控制,不能做算数逻辑运算。如果需要控制逻辑,那么只能通过Go语言编写。Android的妈咪谷歌为了让开发者能更加的快速掌握Android.bp特意提供了androidmk命令(关于它的详细介绍可以参见博客Android.bp入门指南之Android.mk转换成Android.bp,这里就不过多的戏说了)用于Android.mk转换成Android.bp使用,如下转换命令:

    $ androidmk Android.mk > Android.bp
    

    2.5 Blueprint和Soong构建编译系统

    2,5.1 Soong简介

    Soong类似于之前的Makefile编译系统的核心,负责提供Android.bp语义解析,并将之转换成Ninja文件。Soong还会编译生成一个androidmk命令,用于将Android.mk文件转换为Android.bp文件,不过这个转换功能仅限于没有分支、循环等流程控制的Android.mk才有效。

    2.5.2 Blueprint简介

    Blueprint是生成、解析Android.bp的工具,是Soong的一部分。Soong负责Android编译而设计的工具,而Blueprint只是解析文件格式,Soong解析内容的具体含义。Blueprint和Soong都是由Golang写的项目,从Android 7.0,prebuilts/go/目录下新增Golang所需的运行环境,在编译时使用。并且因为Soong和Blueprint是Google谷歌为Android.bp特别定制的工具,所以不需要要摘出来单独来操作。




    三.高版本P/Q/R源码编译

      通过前面的章节我们了解了Android编译环境的构建和编译的发展史(前面的章节都是为了后面章节服务做的整体铺垫),那么从本章节开始就要契合本篇博客的主题了将重点分析Android O之后高阶版本的编译的不同之处了。在本篇的博客开始就有说到过是以高通版本的Android R为基线来进行分析的。所以在开始本章节的博客前,有两个知识点需要提前介绍下,一个是Android Q以及之后的动态分区概念,另外一个就是高通Q之后引入的QSSI(或者qssi)的概念!


    3.1 Android动态分区

    动态分区是Android的用户空间分区系统。使用此分区系统,您可以在无线下载(OTA)更新期间创建、销毁分区或者调整分区大小。借助动态分区,供应商无需担心各个分区(例如system、vendor和product)的大小。取而代之的是,设备分配一个super分区,其中的子分区可动态地调整大小。单个分区映像不再需要为将来的OTA预留空间。相反,super中剩余的可用空间还可用于所有动态分区(关于动态分区详见谷歌官方Android实现动态分区)。

    在这里插入图片描述



    3.2 什么是QSSI

    QSSI 是 Qualcomm Single System Image 的缩写,并且高通平台从Android Q开始支持。高通的官方文档对此的解释是引入QSSI的概念是为了解决Android碎片化问题,把system.img和vendor.img进一步拆分。


    在这里插入图片描述


    并且其编译也和Android原生编译有差别,其差别如下:


    在这里插入图片描述



    3.4 高版本Android非QSSI特性的整体编译流程

    高版本Android非QSSI特性的编译流程,依然和以前的版本Android编译变化不大,通常是如下的步骤(这个也是读者最为熟悉的了):

    source build/envsetup.sh 
    lunch xx-userdebug
    make
    

    这里需要注意的的是通用版本的Android还是可以直接通过make相关的分区进行直接编译的,譬如make superimage或者直接执行make编译


    3.4 具有QSSI特性Android高版本整体编译流程

    通过前面看到QSSI特性的固件编译流程也和通用版本的有一定的区别,这里的编译分为两种模式,第一种Android的标准编译模式,另外一种就是高通提供的编译脚本。

    3.4.1 通过Android内置make命令编译

    • 初始化编译环境
    source build/envsetup.sh 
    
    • 编译 system.img
    lunch qssi-userdebug
    make target-files-package
    
    • 编译除system.img外的其他img
    lunch xx-userdebug
    make target-files-package
    

    3.4.2 高通提供的build.sh脚本进行编译

    • 编译所有img,包括system和其它img
    source build/envsetup.sh
    lunch XX-userdebug
    ./build.sh dist -j32
    
    • 编译system.img,产物在qssi目录下
    source build/envsetup.sh
    lunch xx-userdebug
    ./build.sh dist qssi_only -j32
    
    • 编译super.img
    source build/envsetup.sh
    lunch xx-userdebug
    ./build.sh dist merge_only -j32
    
    • 编译其它img,例如vendorimage,如果不指定会编译其它所有img,产物在XX目录下
    source build/envsetup.sh
    lunch xx-userdebug
    ./build.sh vendorimage dist target_only -j32
    
    

    3.5 动态分区刷机的方法

    由于Android Q版本以及以上将system和vendor分区合并为super分区,无法通过adb reboot bootloader模式单独刷动态分区里面的img,例如system,vendor,product,odm等镜像,只能刷super.img和其他的分区,但是super.img分区动辄几个G的大小,每次刷机几乎都要等上个好大几分钟,这个酸爽你懂的。

    这里有一点需要注意并不是说真的在bootloader模式下不能刷入system分区镜像,可以看到下面的截图是可以刷入的,但是只是镜像没有真的烧录生效,所以读者在实际开发中一定不要做无用功,否则一直烧录,会发现咋咋我修改的东西没有生效呢!

    在这里插入图片描述


    那有没有方法单刷呢,当然有了,不然我也不会多提一句不是。我们可以在fastboot模式下可以单独刷动态分区里面的img,其方法如下:

    #推荐进入fastboot模式刷机:
    adb reboot fastboot
    fastboot getvar is-userspace
    is-userspace: yes
    Finished. Total time: 0.002s
    fastboot flash vendor vendor.img
    fastboot flash system system.img
    fastboot flash vbmeta vbmeta.img
    fastboot flash vbmeta_system vbmeta_system.img
    #fastbootd是用户空间的代码,因为动态的逻辑分区只能在应用空间识别
    

    1.如果是在linux下fastboot刷机出现权限问题,需要将fastboot的所有者属性改成root
    sudo chown root:root fastboot
    sudo chmod +s fastboot

    2.如果是在windows环境下使用fastboot,很大概率可能不识别fastboot,此时推荐下载360的手机助手借助它安装对应的驱动,这样就能进行相关的识别了,此处是个人经验

    3.并且我们在实际操作中需要,注意fastboot是否处于锁定模式,否则会报一下错误(我调试的终端,已经强制锁定了,所以那怕我强制执行了解锁也一直报remote: 'Command not available on locked devices’的异常)
    在这里插入图片描述
    4.我们来使用一个可以动态解锁的fastboot,大功告成!
    在这里插入图片描述



    3.6 Framework和services编译

    对于从事Android偏向现Framework开发的读者来说,编译Android的Framework层是再常见不过的操作了,在Android R之上的Framework的编译已经和之前有所不同,具体参见下面解释:

    • Android R之前单独编译framework和service命令为:
    make -j8 framework
    make -j8 services
    
    • Android R之后编译services的命令还有效果,但是对于framework就有点力不从心了(因为编译规则已经改变了),但是没有关系我们可以使用如下的命令进行相关的编译:
    make -j8 framework-minus-apex
    [100% 4845/4845] Copy: out/target/product/bengal_32go/system/framework/arm/boot-framework.art
    
    #### build completed successfully (10:45 (mm:ss)) ####
    
    
    make -j8 services
    [100% 359/359] Copy: out/target/product/bengal_32go/system/framework/oat/arm/services.odex
    
    #### build completed successfully (01:23 (mm:ss)) ####
    
    

    并且关于Android 11®的framework和services的快速开发调试方法,可以详见博客Android 11®快速开发调试framework和services,这里就不再赘述了。





    四.解决Android高版本编译ssd固态硬盘空间不够的问题

      对于Android开发者来说,当然希望自己在服务器上分配到的资源越多越好,特别是固态硬盘的容量,但是公司当开发者过多的时候,公司就会尽量压缩ssd固态硬盘的盘符空间,只给分配了250G的固态硬盘容量,如果是同时开发编译几个Android低版本的源码,那肯定是够了,但是切到Android R之后,250G肯定是远远不够的,这里我们通过du命令查看一下Android R编译出来之后的情况,如下:

    ityuan@pd:~/ssd$ du   -sh    *
    
    260G	qcm2290
    ityuan@pd:~/ssd$ 
    ityuan@pd:~/ssd$ ls
    qcm2290
    ityuan@pd:~/ssd$ cd qcm2290/
    ityuan@pd:~/ssd/qcm2290$ du   -sh    *
    8.0K	about.html
    0	Android.bp
    85M	art
    64M	bionic
    218M	bootable
    0	bootstrap.bash
    24M	build
    0	build.sh
    3.4M	compatibility
    1.7G	cts
    26M	dalvik
    222M	developers
    150M	development
    635M	device
    4.0K	disregard
    7.1G	external
    1.9G	frameworks
    81M	hardware
    1.4G	kernel
    87M	libcore
    420K	libnativehelper
    4.0K	Makefile
    186G	out
    1.1G	packages
    3.4G	xxxdroid
    896K	pdk
    16M	platform_testing
    32G	prebuilts
    12K	product
    4.0K	readme.md
    232K	resources.arsc
    30M	sdk
    444K	shortcut-fe
    8.0K	sync.sh
    704M	system
    408M	test
    16K	TEST_BP
    9.7M	toolchain
    704M	tools
    6.9G	vendor
    
    

    这里可以看到一个Android R的源码工程就将整个的ssd硬盘空间占满了,那么有什么办法精简呢。当然有了,我们可以对Android 的out目录进行软连接,链接到其它的分区之中。说干就干!下面我来记录一下具体的步骤:

    • 建立软链接目录,这里我建立在我的根目录下,如下:
    ityuan@pd:~$ mkdir out
    ityuan@pd:~$ ls out/
    ityuan@pd:~$ 
    
    ityuan@pd:~$ ln -s /home/tangkw/out  /home/tangkw/ssd/qcm2290/out
    ityuan@pd:~$ cd ssd/qcm2290/
    ityuan@pd:~/ssd/qcm2290$ ll out
    lrwxrwxrwx 1 tangkw pd 16 Jan  5 16:54 out -> /home/tangkw/out/
    ityuan@pd:~/ssd/qcm2290$ 
    

    并且在创建软链接中墙裂建议使用绝对路径,否则会提示Too many levels of symbolic links的错误

    • 查看成果,查看我们创建的out软链接目录,是否成功,如下:
    ityuan@pd:~$ cd out/
    ityuan@pd:~/out$ ls -l
    total 12684
    -rw-r--r-- 1 ityuan pd       0 Jan  5 16:56 Android.mk
    -rw-r--r-- 1 ityuan pd     160 Jan  5 16:59 build-bengal-cleanspec.ninja
    -rwxr-xr-x 1 ityuan pd      10 Jan  5 16:56 build_date.txt
    -rw-r--r-- 1 ityuan pd      10 Jan  5 16:56 build.trace.gz
    -rwxr-xr-x 1 ityuan pd       1 Jan  5 16:56 casecheck.txt
    -rwxr-xr-x 1 ityuan pd       1 Jan  5 16:56 CaseCheck.txt
    -rw-r--r-- 1 ityuan pd       0 Jan  5 16:56 CleanSpec.mk
    drwxr-xr-x 2 ityuan pd    4096 Jan  5 16:59 empty
    -rw-r--r-- 1 ityuan pd      39 Jan  5 16:59 env-bengal-cleanspec.sh
    -rw-r--r-- 1 ityuan pd       0 Jan  5 16:56 error.log
    drwxr-xr-x 3 ityuan pd    4096 Jan  5 17:00 host
    -rwxr-xr-x 1 ityuan pd 4309565 Jan  5 16:56 microfactory_Linux
    -rwxr-xr-x 1 ityuan pd     121 Jan  5 16:59 ninja-bengal-cleanspec.sh
    -rw-r--r-- 1 ityuan pd       0 Jan  5 16:56 ninja_build
    drwxr-xr-x 6 ityuan pd    4096 Jan  5 16:59 soong
    -rw-r--r-- 1 ityuan pd   19743 Jan  5 17:00 soong.log
    -rwxr-xr-x 1 ityuan pd 8580360 Jan  5 16:56 soong_ui
    drwxr-xr-x 3 ityuan pd    4096 Jan  5 16:59 target
    -rw-r--r-- 1 ityuan pd   24970 Jan  5 17:00 verbose.log.gz
    ityuan@pd:~/out$ 
    
    • 接着查看下我们ssd目录占用空间大小,如下(可以看到out目录的大小已经为0了):
    ityuan@pd:~/ssd$ du -sh *
    75G	qcm2290
    ityuan@pd:~/ssd$ cd qcm2290/
    ityuan@pd:~/ssd/qcm2290$ 
    ityuan@pd:~/ssd/qcm2290$ 
    ityuan@pd:~/ssd/qcm2290$ du -sh *
    8.0K	about.html
    0	Android.bp
    85M	art
    64M	bionic
    218M	bootable
    0	bootstrap.bash
    24M	build
    0	build.sh
    3.4M	compatibility
    1.7G	cts
    26M	dalvik
    222M	developers
    150M	development
    635M	device
    4.0K	disregard
    7.1G	external
    1.9G	frameworks
    81M	hardware
    1.4G	kernel
    87M	libcore
    420K	libnativehelper
    4.0K	Makefile
    0	out
    1.1G	packages
    3.4G	xxxdroid
    896K	pdk
    16M	platform_testing
    32G	prebuilts
    12K	product
    4.0K	readme.md
    232K	resources.arsc
    30M	sdk
    444K	shortcut-fe
    8.0K	sync.sh
    704M	system
    408M	test
    16K	TEST_BP
    9.7M	toolchain
    704M	tools
    6.9G	vendor
    ityuan@pd:~/ssd/qcm2290$ 
    

    大功告成,当然如果读者是土豪公司,那这个就可以跳过不看了。




    五.Android为啥要引入动态分区

      在前面我们简单说了下动态分区的概念,即在Android Q以及以后得编译包中,我们找不到了对应的system,vendor等img文件,但是多了一个super.img,system,vendor,product,ODM合并为super分区,这个就是动态分区了。简单来说就是为了在ota的时候能够灵活创建分区和修改分区大小,将system,vendor,odm,product合并成super分区,并在super分区上预留出一定量的free space,这样就可以动态调整这些分区的大小,解决了ota的时候分区不足,以及调整分区的风险.。


    在这里插入图片描述


    当OTA升级之后,需要重新调整分区大小:

    在这里插入图片描述




    写在最后

      好了今天的博客Android高版本P/Q/R源码编译指南就到这里了,由于这是一篇实战类型的博客所以也没有多少总结的了,跟着干就行了。总之,青山不改绿水长流先到这里了。如果本博客对你有所帮助,麻烦关注或者点个赞,如果觉得很烂也可以踩一脚!谢谢各位了!!好了,青山不改绿水长流,各位江湖见!当然各位读者的点赞和关注是我写作路上前进的最大动力了,如果有啥不对或者不爽的也可以踩一踩也无妨!

    最后附上参考文档路径Android P/Q/R编译系统,这里我对做了简化,并且加上了自己实际开发中的一些理解,主要是为了方便大家快速入手Android高版本编译。

    展开全文
  • Android系统布局——android.R.layout详解

    万次阅读 2018-09-23 00:31:03
    布局文件,作为android中...系统布局文件:android.R.layout.xxx; 用户自定义布局文件:R.layout.xxx; 那系统布局文件究竟有哪一些,大家在用的时候如果不了解,心里估计有点惴惴。现在下方图中列出所有系统布局,...

    布局文件,作为android中必不可少的一部分,android系统为了方便开发人员,在系统中定义了很多的布局文件。

    系统布局文件和我们自定义的布局在写法用前缀android以示区别:

    系统布局文件:android.R.layout.xxx;

    用户自定义布局文件:R.layout.xxx;

    那系统布局文件究竟有哪一些,大家在用的时候如果不了解,心里估计有点惴惴。现在下方图中列出所有系统布局,我们一一试用:

    下面我们会以代码来解释上面图片中涉及到的布局意义(按顺序描述):

    先插入代码与主布局,如下:

    public class MainActivity extends Activity {
        ListView listView;
        List<String> listStrings;
        ArrayAdapter<String> arrayAdapter;
        SimpleAdapter simpleAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            init();
        }
    
    
        public void init() {
            listView=(ListView)findViewById(R.id.mylistview);
            listStrings=new ArrayList<String>();
            listStrings.add("千山鸟飞绝");
            listStrings.add("万径人踪灭");
            listStrings.add("孤舟蓑笠翁");
            listStrings.add("独钓寒江雪");
    
    
            arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.activity_list_item, android.R.id.text1,listStrings);
            listView.setAdapter(arrayAdapter);
            arrayAdapter.notifyDataSetChanged();
        }
    }
    activity_main布局:
    
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingBottom="@dimen/activity_vertical_margin"
            android:paddingLeft="@dimen/activity_horizontal_margin"
            android:paddingRight="@dimen/activity_horizontal_margin"
            android:paddingTop="@dimen/activity_vertical_margin"
            tools:context=".MainActivity" >
        
            <ListView
                android:id="@+id/mylistview"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                />
        </RelativeLayout>
    

     

    很简单的一段代码,只在主界面显示一个listview,用于后续的测试。

    1、activity_list_item

    在代码中写法如下:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.activity_list_item, android.R.id.text1,listStrings);

    我们关注的是activity_list_item内容是:

     

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="1dip"
        android:paddingBottom="1dip"
        android:paddingStart="8dip"
        android:paddingEnd="8dip">
    
        <ImageView android:id="@+id/icon"
            android:layout_width="24dip"
            android:layout_height="24dip"/>
    
        <TextView android:id="@android:id/text1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:paddingStart="?android:attr/listPreferredItemPaddingStart" />
    </LinearLayout>

     

    可以看出这是一图一文字的一个布局,而我们写的时候并没有将图片加载进去。上面的写法可以达到一个效果,只显示文字。如果需要显示图片,我们还需后续手动编代码加入,所以是不是觉得麻烦。是的,个人不建议使用这个布局在arrayadapter中。这个布局并不比我们自定义的布局方便。

    2、browser_link_context_header

    同样的写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.browser_link_context_header,listStrings);

    我们看看android.R.layout.browser_link_context_header的内容:

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/title"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="@color/white"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLines="2"
        android:paddingStart="10dip"
        android:paddingEnd="10dip"
        />


    只是一个TextView,看布局中规定了字体颜色为白色,无其他效果。在底色为黑色或者暗色的情况下适用。

    3、browser_link_context_header

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/title"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="@color/white"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLines="2"
        android:paddingStart="10dip"
        android:paddingEnd="10dip"
        />

    这个布局与上一个大同小异,不再多做说明。

    4、expandable_list_content

    <ExpandableListView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:drawSelectorOnTop="false" />

     

    这个布局与前几个都不相同,是一个可扩张的listview。但实际使用中没有特别的意义,并不如个人自定义写法方便。弃之。

    如果要使用,可类似:inflate(MainActivity.this,  android.R.layout.expandable_list_content,null);

    5、list_content

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout android:id="@+id/progressContainer"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone"
            android:gravity="center">
            <ProgressBar style="?android:attr/progressBarStyleLarge"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
            <TextView android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceSmall"
                android:text="@string/loading"
                android:paddingTop="4dip"
                android:singleLine="true" />
        </LinearLayout>
    
        <FrameLayout android:id="@+id/listContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <ListView android:id="@android:id/list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:drawSelectorOnTop="false" />
            <TextView android:id="@+android:id/internalEmpty"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:textAppearance="?android:attr/textAppearanceLarge" />
        </FrameLayout>
    </FrameLayout>

    这个布局显的较为复杂,而实用性也很一般。如果需要达到这样的效果,使用这个布局,建议将这个布局拷贝做成自定义布局,方便你取数、赋值。 

    6、preference_category

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        style="?android:attr/listSeparatorTextViewStyle"
        android:id="@+android:id/title"
        />

    这个布局,使用了一个style,写法:

     

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.preference_category,android.R.id.title,listStrings);

    效果如下: 

    分割线加粗、字体变化。在某些列表中可用。

    7、select_dialog_item

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?android:attr/listPreferredItemHeight"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="?android:attr/textColorAlertDialogListItem"
        android:gravity="center_vertical"
        android:paddingStart="14dip"
        android:paddingEnd="15dip"
        android:ellipsize="marquee"
        />

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.select_dialog_item,listStrings);

    也是对字体、宽高等的一些设置,没有特殊变化。 

    8、select_dialog_multichoice

    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?android:attr/listPreferredItemHeight"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="?android:attr/textColorAlertDialogListItem"
        android:gravity="center_vertical"
        android:paddingStart="12dip"
        android:paddingEnd="7dip"
        android:checkMark="?android:attr/listChoiceIndicatorMultiple"
        android:ellipsize="marquee"
        />

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.select_dialog_multichoice,listStrings);

     

    这里出现了一个新的控件,CheckTextView。我们看看这个的效果和样式和以前的TextView是不同的,另外还请注意这个multichoice标识。

    效果如下:


    这是一个可多选的效果。在项目中,这样的样式大家应该不陌生,这个布局对我们来说有一定意义!

    9、select_dialog_singlechoice

    从字面意思可以看到,这个与第8个的区别,在乎单选与多选:

    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?android:attr/listPreferredItemHeight"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="?android:attr/textColorAlertDialogListItem"
        android:gravity="center_vertical"
        android:paddingStart="12dip"
        android:paddingEnd="7dip"
        android:checkMark="?android:attr/listChoiceIndicatorSingle"
        android:ellipsize="marquee"
        />

     写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.select_dialog_singlechoice,listStrings);

     效果:

    10、simple_dropdown_item_1line

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        style="?android:attr/dropDownItemStyle"
        android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
        android:singleLine="true"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/listPreferredItemHeight"
        android:ellipsize="marquee" />

     

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_dropdown_item_1line,listStrings);

    与上方其他的TextView类似,不再说明。 

     

    11、simple_expandable_list_item_1

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/listPreferredItemHeight"
        android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
        android:textAppearance="?android:attr/textAppearanceListItem"
        android:gravity="center_vertical"
        android:textAlignment="viewStart"
        />

     

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_expandable_list_item_1,listStrings);

    不再说明。

    12、simple_gallery_item

    <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="?android:attr/textColorPrimaryDisableOnly"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:maxLines="1" />

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_gallery_item,listStrings);

     

    不再说明。

    13、simple_list_item_1

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
        android:minHeight="?android:attr/listPreferredItemHeightSmall"
        />

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,listStrings);

    这里多说一句,这个应该是我们平常使用最多的一个系统布局文件,习惯成自然。 

    14、simple_list_item_activated_1

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
        android:background="?android:attr/activatedBackgroundIndicator"
        android:minHeight="?android:attr/listPreferredItemHeightSmall"
        />

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_activated_1,listStrings);

    不再说明。

     

    15、simple_list_item_multiple_choice

     

    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/listPreferredItemHeightSmall"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:checkMark="?android:attr/listChoiceIndicatorMultiple"
        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
        />

    这个对我们来说也已经没有新鲜感了,因为在上面,我们有见过类似的了,多选的TextView。
    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_multiple_choice,listStrings);

    16、simple_list_item_single_choice

    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/listPreferredItemHeightSmall"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:checkMark="?android:attr/listChoiceIndicatorSingle"
        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
        />

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_single_choice,listStrings);

    不再说明。

    17、simple_list_item_checked
    看这个带一个checked后缀,有点特殊。先看看xml:

    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/listPreferredItemHeightSmall"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:checkMark="?android:attr/textCheckMark"
        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
        />

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_checked,listStrings);

    效果:

     

    还是有些特殊效果的,选中打钩。这个也可注意使用。

    18、simple_selectable_list_item

    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/listPreferredItemHeight"
        android:textAppearance="?android:attr/textAppearanceListItem"
        android:gravity="center_vertical"
        android:background="?android:attr/listChoiceBackgroundIndicator"
        android:paddingStart="8dip"
        android:paddingEnd="8dip"
        />

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_selectable_list_item,listStrings);

    不再说明。

    19、simple_spinner_dropdown_item

    <CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        style="?android:attr/spinnerDropDownItemStyle"
        android:singleLine="true"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/dropdownListPreferredItemHeight"
        android:ellipsize="marquee"
        android:textAlignment="inherit"/>

     写法:arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_spinner_dropdown_item,listStrings);
    不再说明。

     20、simple_spinner_item

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        style="?android:attr/spinnerItemStyle"
        android:singleLine="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ellipsize="marquee"
        android:textAlignment="inherit"/>

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_spinner_item,listStrings);

     

    不再说明。

    21、test_list_item

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:paddingTop="2dip"
        android:paddingBottom="3dip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />

     

    写法:

    arrayAdapter=new ArrayAdapter<String>(MainActivity.this, android.R.layout.test_list_item,listStrings);

    无特殊,不做说明。

     

    到这里为止,我们单行的显示已经做到头了。。汗。同质的内容太多了。。

    现在来一些不太一样的,被我们略过的几个布局。为了测试这几个布局的不同之处,我们修改下代码如下:

     

     
    public class MainActivity extends Activity {
        ListView listView;
        List<String> listStrings;
        ArrayAdapter<String> arrayAdapter;
        SimpleAdapter simpleAdapter;
       
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            init();
        }
    
    
        public void init() {
            listView=(ListView)findViewById(R.id.mylistview);
            List<Map<String, String>> listmaps=new ArrayList<Map<String,String>>();
            Map<String, String> map=new HashMap<String, String>();
            map.put("first", "第一句");
            map.put("second", "第二句");
            listmaps.add(map);
            simpleAdapter=new SimpleAdapter(MainActivity.this, listmaps, android.R.layout.simple_expandable_list_item_2, new String[]{"first","second"}, new int[]{android.R.id.text1,android.R.id.text2});
            listView.setAdapter(simpleAdapter);
            simpleAdapter.notifyDataSetChanged();
        }
    }
    
    

    代码不一样的地方在于,我们现在不适用ArrayAdapter来测试了,因为现在有两项内容了。ArrayAdapter已经不适合,我们用SimpleAdapter来测试。

    22、simple_expandable_list_item_2

    <TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/listPreferredItemHeight"
        android:paddingTop="2dip"
        android:paddingBottom="2dip"
        android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
        android:mode="twoLine"
        >
    
        <TextView 
            android:id="@android:id/text1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="6dip"
            android:textAppearance="?android:attr/textAppearanceListItem"
            android:textAlignment="viewStart"
            />
    
    
        <TextView 
            android:id="@android:id/text2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@android:id/text1"
            android:layout_alignStart="@android:id/text1"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textAlignment="viewStart"
            />
    </TwoLineListItem>


    这是有两行TextView的一个布局,一上一下,一大一小。

    写法:

    simpleAdapter=new SimpleAdapter(MainActivity.this, listmaps, android.R.layout.simple_expandable_list_item_2, new String[]{"first","second"}, new int[]{android.R.id.text1,android.R.id.text2});

    效果:

    这个布局因为这特殊效果,也是较为实用的。

    23、simple_list_item_2

    <TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minHeight="?android:attr/listPreferredItemHeight"
        android:mode="twoLine"
        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
        >
        
        <TextView android:id="@android:id/text1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dip"
            android:textAppearance="?android:attr/textAppearanceListItem"
            />
        
        <TextView android:id="@android:id/text2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@android:id/text1"
            android:layout_alignStart="@android:id/text1"
            android:textAppearance="?android:attr/textAppearanceSmall"
            />
        
    </TwoLineListItem>
    
    

    写法: 

    simpleAdapter=new SimpleAdapter(MainActivity.this, listmaps, android.R.layout.simple_list_item_2, new String[]{"first","second"}, new int[]{android.R.id.text1,android.R.id.text2});

    效果与上一个类似,不再说明。

     

    24、simple_list_item_activated_2

    <TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
        android:paddingTop="2dip"
        android:paddingBottom="2dip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?android:attr/activatedBackgroundIndicator"
        android:minHeight="?android:attr/listPreferredItemHeight"
        android:mode="twoLine"
        >
    
    
        <TextView android:id="@android:id/text1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
            android:layout_marginTop="6dip"
            android:textAppearance="?android:attr/textAppearanceListItem"
            />
    
    
        <TextView android:id="@android:id/text2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@android:id/text1"
            android:layout_alignStart="@android:id/text1"
            android:textAppearance="?android:attr/textAppearanceSmall"
            />
        
    </TwoLineListItem>

    写法:

    simpleAdapter=new SimpleAdapter(MainActivity.this, listmaps, android.R.layout.simple_list_item_activated_2, new String[]{"first","second"}, new int[]{android.R.id.text1,android.R.id.text2});

    不再说明,效果与上类似。

     

    25、two_line_list_item

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
    
        <TextView android:id="@android:id/text1"
            android:textSize="16sp"
            android:textStyle="bold"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    
        <TextView android:id="@android:id/text2"
            android:textSize="16sp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    
    </LinearLayout>

    布局稍有不同啊,写法:

    simpleAdapter=new SimpleAdapter(MainActivity.this, listmaps, android.R.layout.two_line_list_item, new String[]{"first","second"}, new int[]{android.R.id.text1,android.R.id.text2});

    看一下效果:

    字体大小一致,上下颜色深浅不一。与前三个相比,还是有较大区别的。选用。

    原文地址:https://blog.csdn.net/yangzhaomuma/article/details/49877311​​​​​​​

    展开全文
  • AndroidAndroid 11(R) 新特性解读

    千次阅读 2020-07-01 10:16:38
    Android 10可将requestLegacyExternalStorage设为true以停用分区存储。 2、一次性权限 所有平台,可授予临时访问权限,包括位置、麦克风、摄像头。 3、自动重设权限 Android 11,用户与应用长时间没有互动时,如长...
  • AndroidR文件

    千次阅读 2019-03-31 20:22:42
    Android 应用程序被编译,会自动生成一个 R 类,其中包含了所有 res/ 目录下资源。包括布局文件layout,图片文件drawable等。 具体的内容如下所示: public final class R{ //全是以 publi static final 开头...
  • Android开发中的R文件

    千次阅读 2019-08-07 15:07:01
    Android 应用程序被编译,会自动生成一个 R 类,其中包含了所有 res/ 目录下资源的 ID,如布局文件,资源文件,图片(values下所有文件)的ID等。在写java代码需要用这些资源的时候,你可以使用 R 类,通过子类+...
  • android R.id找不到资源的问题

    千次阅读 2017-09-20 16:39:54
    1.R文件未编译,只需sync project同步编译一下; 2.清理工作空间,build>clean project; 3.没有正确导入资源包,import 修改成自己的包名.R,比如 import com.example.myapplication.R; 4.重命名控件,再同步...
  • Android-SDK_r24.4.1

    2017-01-23 15:25:52
    Android-SDK_r24.4.1
  • 问题是,当你在R.layout.xml文件时,总是找不到您想要的文件,可是它明明就在layout文件下面,而且在R.java中也已经生成了,那么找不到的原因就是你导入了android.R的包,这样你永远找不到你想要是,你应该导入自己...
  • Android_Android R.raw.one的问题

    千次阅读 2012-07-29 14:01:30
    private static int index = 0;//数组元素从0开始  //图片数组  private int[] resIds = new int[] { R.raw.one, R.raw.two, R.raw.three, ... R.raw.four, R.raw.five, R.raw.six, R.raw.seven};   提示R
  • Android系统布局——自带的布局android.R.layout详解

    万次阅读 多人点赞 2015-11-17 00:37:08
    布局文件,作为android中必...系统布局文件:android.R.layout.xxx; 用户自定义布局文件:R.layout.xxx; 那系统布局文件究竟有哪一些,大家在用的时候如果不了解,心里估计有点惴惴。现在下方图中列出所有系统布局,
  • 但在修改layout文件名称时,却不会检查这个要求,若存在大写字母时,程序在编译时,R会全部变红,这时可以查看编译错误提示,可以定位到有问题的layout名称。更改后,如只是这一种原因造成的“R”变红,那么问题就...
  • Android studio中R变成红色

    万次阅读 多人点赞 2016-08-23 23:19:12
    话说从Eclipse换到了Android Studio,撸起代码是爽的不行,但是Android studio出现R的情况却是令人厌烦,以下是我再遇到R变红的解决办法: 1. 选择File-->Project Structure-->在左边选择出错的项目名-->修改 Build...
  • android自带图片资源图标一览,android R drawable
  • android.RR的区别

    千次阅读 2017-02-13 10:21:57
    android.R 系统内部预先定义好的资源 R 工程师自定义的资源
  • Android:解决“无法解析符号R”问题

    千次阅读 2018-11-04 16:48:48
    我打开工程的时候,项目直接报错,出现了以下问题: 如果在确定自己的代码没有问题情况下,可以试一下重新构建项目: 项目正在重构 构建完成,问题解决 ...
  • R.layout.test文件时,总是找不到您想要的文件,可是它明明就在layout文件下面,而且在R.Java中也已经生成了,那么找不到的原因就是你导入了Android.R的包,这样你永远找不到你想要是,你应该导入自己项目的R文件...
  • # 第一,先去import看看有没有 错误导入了import android.R 如果有。删掉。 # 第二,查看xml有没有写错的地方,重要的位置:package <manifest xmlns:android="http://schemas.android.com/apk/res/android" ...
  • 解决办法:菜单栏中的Build菜单项中选择Clean Project,等一会自然好了。
  • 解决Android Studio R突然变红问题

    千次阅读 2018-07-23 12:06:34
    有时候整个工程的R突然变成红色,试了很多方法都不行,直到 点击 file -&gt; Sync with File System就可以了
  • Android Studio中R文件丢失的解决办法

    万次阅读 多人点赞 2016-04-18 22:10:41
    刚才折腾AS制作一个小项目,本来用的好好的突然一下无法运行到模拟器或测试机上了,MainActivity.java文件中R报红,提示"cannot resolve symbol R"。 消息窗口提示了错误信息(起始当时根本没怀疑id会有问题,也是...
  • 如题,一般代码中引入资源文件或者布局文件中的控件时需要用到R.id.xx,这时就需要导入R需要的R.java资源文件(注意导入的是你的包名.R,而不是anroid.R,包名为AndroidManifest.xml中的包名)。 但有时突然项目中...
  • ![图片说明](https://img-ask.csdn.net/upload/201703/27/1490622371_879429.png) 运行时R全红
  • Android Studio 找不到R文件解决方法汇总

    万次阅读 多人点赞 2018-10-28 16:09:28
    一、新建的Activity中R文件找不到,其他文件中的R文件可以正常使用。 解决方法:在该Activity中引入R包即可:import com.example.zcj.password.R; 在子目录下新建Activity文件都会出现这个问题,可以通过设置自动...
  • android版本列表

    千次阅读 2017-08-14 09:37:40
    代号、标记和细分版本 (Build) 号简要来说,Android 的开发是围绕着版本系列进行的,这些版本使用美味的点心名字(按字母顺序)作为代号。平台代号、版本、API 级别和 NDK 版本为方便起见,代号与以下版本号、API ...
  • 一、Android Studio中R文件丢失可能的产生原因: 1.一般出现这种情况很有可能是R文件因为某种原因无法自动生成,多数是res资源文件的错误导致的。 (1)在资源文件res中的资源文件大写例如 bg_editText_focused.xml...
  • android-sdk_r23.0.2-windows.zip

    热门讨论 2014-10-12 17:05:45
    android-sdk_r23.0.2-windows.zip
  • Android Studio R报红的总结

    万次阅读 2018-04-18 18:14:36
    做个笔记,懒得折腾格式 ...4.多次尝试没有效果,可能是控件相关的问题,比如使用某个三方控件(android新新控件)未使用compile添加依赖,或者xml文件写的有问题,资源不存在,或者自定义属性问题。...
  • Android studio 新版本查看R文件内容ID

    千次阅读 2020-03-21 15:53:47
    最近在开发时遇到了“”,仔细检查了都没有文件,但是就是报这个早不到资源文件错误,由于studio新版本的R文件存放位置改变了,害得我一顿好找,再次记录下方便遇到同样错误需要查看R文件来定位错误的位置;sutdio R...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 793,084
精华内容 317,233
关键字:

androidr