Android 笔记:AndroidTrain , Lint , build.gradle , 第三方库

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014136472/article/details/50241805

重读官方Train的部分笔记

注意: 目前,所有应用都可以读取外部存储,而无需特别的权限。 但这在将来版本中会进行更改。如果您的应用需要读取外部存储(但不向其写入信息),那么您将需要声明 READ_EXTERNAL_STORAGE 权限。 要确保您的应用继续正常工作,您应在更改生效前声明此权限。

<manifest ...>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    ...
</manifest>

但是,如果您的应用使用 WRITE_EXTERNAL_STORAGE 权限,那么它也隐含读取外部存储的权限。
您无需任何权限,即可在内部存储中保存文件。 您的应用始终具有在其内部存储目录中进行读写的权限。


注意:保存您的文件之前,您无需检查可用空间量。 您可以尝试立刻写入文件,然后在 IOException 出现时将其捕获。 如果您不知道所需的确切空间量,您可能需要这样做。
例如,如果在保存文件之前通过将 PNG 图像转换成JPEG 更改了文件的编码,您事先将不知道文件的大小。


注意:当用户卸载您的应用时,Android 系统会删除以下各项:

  • 您保存在内部存储中的所有文件
  • 您使用 getExternalFilesDir() 保存在外部存储中的所有文件。

但是,您应手动删除使用 getCacheDir() 定期创建的所有缓存文件并且定期删除不再需要的其他文件。

ID

任何视图对象都可能具有关联的整型 ID,此 ID 用于在结构树中对 View 对象进行唯一标识。编译应用后,此 ID 将作为整型数引用,但在布局 XML 文件中,通常会在 id 属性中为该 ID 赋予字符串值。这是所有 View 对象共用的 XML 属性(由 View 类定义),您会经常用到它。XML 标记内部的 ID 语法是:

android:id="@+id/my_button"

字符串开头处的 @ 符号指示 XML 解析程序应该解析并展开 ID 字符串的其余部分,并将其标识为 ID 资源。
加号 (+) 表示这是一个新的资源名称,必须创建该名称并将其添加到我们的资源(在 R.java 文件中)内。Android 框架还提供了许多其他 ID 资源。引用 Android 资源 ID 时,不需要加号,但必须添加 android 软件包命名空间,如下所示:

android:id="@android:id/empty"

添加 android 软件包命名空间之后,现在,我们将从 android.R 资源类而非本地资源类引用 ID。

ID 不需要在整个结构树中具有唯一性,但在您要搜索的结构树部分应具有唯一性(要搜索的部分往往是整个结构树,因此最好尽可能具有全局唯一性)。

布局位置

位置和尺寸的单位是 像素
getLeft() getTop()
前者会返回表示视图的矩形的水平向左(或称 X 轴) 坐标。

这些方法都会返回视图相对于其父项的位置。
例如,如果 getLeft() 返回 20,则意味着视图位于其直接父项左边缘向右 20 个像素处。

系统还提供了几种便捷方法来避免不必要的计算:
getRight() getBottom()
这些方法会返回表示视图的矩形的右边缘和下边缘的坐标。 例如,调用 getRight() 类似于进行以下计算:getLeft() + getWidth()。

尺寸、内边距和外边距

视图实际上具有两对宽度和高度值。

  • getMeasuredWidth() : 测量宽度
    getMeasuredHeight() : 测量高度
    这些尺寸定义视图想要在其父项内具有的大小。

  • getWidth() : 绘制宽度
    getHeight() : 绘制高度
    些尺寸定义视图在绘制时和布局后在屏幕上的实际尺寸。
    这些值可以(但不必)与测量宽度和测量高度不同。

要想测量其尺寸,视图需要将其内边距考虑在内。
内边距以视图左侧、顶部、右侧和底部各部分的 像素 数表示。
尽管视图可以定义内边距,但它并不支持外边距。
不过,视图组可以提供此类支持。


SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to)
  • This constructor was deprecated in API level 11. This option is discouraged, as it results in Cursor queries being performed on the application’s UI thread and thus can cause poor responsiveness or even Application Not Responding errors. As an alternative, use LoaderManager with a CursorLoader.
SimpleCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags)
  • Standard constructor.

项目 res/ 目录内支持的资源目录:

目录 资源类型
animator/ 用于定义属性动画的 XML 文件。
anim/ 定义渐变动画的 XML 文件。(属性动画也可以保存在此目录中,但是为了区分这两种类型,属性动画首选 animator/ 目录。)
mipmap/ 适用于不同启动器图标密度的 Drawable 文件
raw/ 要以原始形式保存的任意文件。要使用原始 InputStream 打开这些资源,请使用资源 ID(即 R.raw.filename)调用 Resources.openRawResource()。但是,如需访问原始文件名和文件层次结构,则可以考虑将某些资源保存在 assets/ 目录下(而不是 res/raw/)。assets/ 中的文件没有资源 ID,只能使用 AssetManager 读取这些文件D
color/ 用于定义 颜色状态列表XML文件
xml/ 可以在运行时通过调用 Resources.getXML() 读取的任意 XML 文件。各种 XML 配置文件(如可搜索配置)都必须保存在此处。

注意:切勿将资源文件直接保存在 res/ 目录内,这会导致出现编译错误。

创建别名资源

如果您想将某一资源用于多种设备配置(但是不想作为默认资源提供),则无需将同一资源放入多个备用资源目录中。 相反,您可以(在某些情况下)创建备用资源,充当保存在默认资源目录下的资源的别名。

注:并非所有资源都会提供相应机制让您创建指向其他资源的别名。 特别是,xml/ 目录中的动画资源、菜单资源、原始资源以及其他未指定资源均 不提供 此功能。

例如,假设您有一个应用图标 icon.png,并且需要不同区域设置的独特版本。 但是,加拿大英语和加拿大法语这两种区域设置需要使用同一版本。 您可能会认为需要将相同的图像复制到加拿大英语和加拿大法语对应的资源目录中,但事实并非如此。 相反,您可以将用于二者的图像另存为 icon_ca.png(除 icon.png 以外的任何名称),并将其放入默认 res/drawable/ 目录中。然后,在 res/drawable-en-rCA/res/drawable-fr-rCA/ 中创建 icon.xml 文件,使用 <bitmap> 元素引用 icon_ca.png资源。这样,您只需存储 PNG 文件的一个版本和两个指向该版本的小型 XML 文件。(XML 文件示例如下:)

1. Drawable
要创建指向现有 Drawable 的别名,请使用 元素。例如:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/icon_ca" />

如果将此文件另存为 icon.xml(例如,在备用资源目录中,另存为 res/drawable-en-rCA/),则会编译到可作为 R.drawable.icon 引用的资源中,但实际上它是 R.drawable.icon_ca 资源(保存在 res/drawable/ 中)的别名。

2. 布局
要创建指向现有 布局的别名,请使用包装在 <merge> 中的 <include>元素。例如:

<?xml version="1.0" encoding="utf-8"?>
<merge>
    <include layout="@layout/main_ltr"/>
</merge>

如果将此文件另存为 main.xml,则会编译到可作为 R.layout.main 引用的资源中,但实际上它是 R.layout.main_ltr 资源的别名。

3. 字符串和其他简单值
要创建指向现有字符串的别名,只需将所需字符串的资源 ID 用作新字符串的值即可。例如:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello</string>
    <string name="hi">@string/hello</string>
</resources>

R.string.hi 资源现在是 R.string.hello 的别名。
其他简单值的原理相同。 例如,颜色:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="yellow">#f00</color>
    <color name="highlight">@color/red</color>
</resources>

访问资源

编译应用时,aapt 会生成 R 类,其中包含您的 res/ 目录中所有资源的资源 ID。 每个资源类型都有对应的 R 子类(例如,R.drawable 对应于所有 Drawable 资源),而该类型的每个资源都有对应的静态整型数(例如,R.drawable.icon)。这个整型数就是可用来检索资源的资源 ID。
注意:res/ 读取资源的唯一方法是使用资源 ID

// Set the Activity title by getting a string from the Resources object, because
//  this method requires a CharSequence rather than a resource ID
getWindow().setTitle(getResources().getText(R.string.main_title));

// Set a slide in animation by getting an Animation from the Resources object
mFlipper.setInAnimation(AnimationUtils.loadAnimation(this,
        R.anim.hyperspace_in));

引用样式属性
您可以通过样式属性资源在当前应用的风格主题中引用某个属性的值。 通过引用样式属性,您可以不采用为 UI 元素提供硬编码值这种方式,而是通过为 UI 元素设置样式,使其匹配当前风格主题提供的标准变型来定制这些元素的外观。引用样式属性的实质作用是,“在当前风格主题中使用此属性定义的样式”。

要引用样式属性,名称语法几乎与普通资源格式完全相同,只不过将 at 符号 (@) 改为问号 (?),资源类型部分为可选项。 例如:

?[<package_name>:][<resource_type>/]<resource_name>

例如,您可以通过以下代码引用一个属性,将文本颜色设置为与系统风格主题的“主要”文本颜色匹配:

<EditText id="text"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="?android:textColorSecondary"
    android:text="@string/hello_world" />

在以上代码中,android:textColor 属性表示当前风格主题中某个样式属性的名称。Android 现在会使用应用于 android:textColorSecondary 样式属性的值作为 android:textColor 在这个小工具中的值。由于系统资源工具知道此环境中肯定存在某个属性资源,因此您无需显式声明类型(类型应为 ?android:attr/textColorSecondary)— 您可以将 attr 类型排除在外。

使用Lint排除潜在的问题

Lint是Google专门为Android推出的代码检查工具,可以在编译期发现APP中潜在的问题。
菜单栏中Analyze -> Inspect Code 开始检查代码,项目越大耗时越长。
检查完成会自动打开Inspection窗口并显示结果,如下图所示:
这里写图片描述

我们重点来看一下Android Lint:
这里写图片描述

build.gradle文件

build.gradle文件结构

AS中APP所有的配置尽在一个build.gradle文件中,打包的时候也是解析build.gralde文件来打包的。结构如下所示:
这里写图片描述

1) apply plugin 用来指定用的是哪个插件

  • com.android.application:Android APP插件(打包得到的是.apk文件)
  • com.android.library:Android库插件(打包得到的是.aar文件)

2) android 用来指定Android打包插件的相关属性

  • compileSdkVersion(apiLevel):设置编译时用的Android版本
  • buildToolsVersion(buildToolsVersionName):设置编译时使用的构建工具的版本
  • defaultConfig:设置一些默认属性,其可用属性是 buildTypesProductFlavors 之和
  • sourceSets:配置相关源文件的位置,当你的项目的目录结构跟默认的有区别但又不想改的时候sourceSets就派上用场了
    • aidl 设置aidi的目录
    • assets 设置assets资源目录
    • compileConfigurationName The name of the compile configuration for this source set.
    • java Java 源代码目录
    • jni JNI代码目录
    • jniLibs 已编译好的JNI库目录
    • manifest 指定清单文件
    • name The name of this source set.
    • packageConfigurationName The name of the runtime configuration for this source set.
    • providedConfigurationName The name of the compiled-only configuration for this source set.
    • renderscript Renderscript源代码目录
    • res 资源目录
    • setRoot(path) 根目录
  • signingConfigs:配置签名信息
    • keyAlias 签名的别名
    • keyPassword 密码
    • storeFile 签名文件的路径
    • storePassword 签名密码
    • storeType 类型
  • buildTypes:配置构建类型,可打出不同类型的包。默认有 debugrelease 两种,你还可以在增加N种。
    • applicationIdSuffix 用于修改 applicationId,在默认 applicationId 的基础上加后缀。在 buildType 中修改 applicationId 时只能加后缀,不能完全修改。
    • debuggable 设置是否生成debug版的APK
    • jniDebuggable 设置生成的APK是否支持调试本地代码
    • minifyEnabled 设置是否执行混淆
    • multiDexEnabled Whether Multi-Dex is enabled for this variant.
    • renderscriptDebuggable 设置生成的APK是否支持调试RenderScript代码
    • renderscriptOptimLevel 设置RenderScript优化级别
    • signingConfig 设置签名信息
    • versionNameSuffix 修改版本名称,在默认版本名称的基础上加后缀。在buildType中修改版本名称时只能加后缀,不能完全修改
    • zipAlignEnabled 设置是否对APK包执行ZIP对齐优化
    • proguardFile(proguardFile) 添加一个混淆文件
    • proguardFiles(proguardFileArray) 添加多个混淆文件
    • setProguardFiles(proguardFileIterable) 设置多个混淆文件
  • productFlavors:配置不同风格的APP,在buildTypes的基础上还可以让每一个类型的APP拥有不同的风格,所以最终打出的APK的数量就是buildTypes乘以productFlavors
    • applicationId 设置应用ID
    • multiDexEnabled Whether Multi-Dex is enabled for this variant.signingConfig Signing config used by this product flavor.
    • testApplicationId 设置测试时的应用ID
    • testFunctionalTest See instrumentation.
    • testHandleProfiling See instrumentation.
    • testInstrumentationRunner Test instrumentation runner class name.
    • versionCode 设置版本号
    • versionName 设置版本名称
    • minSdkVersion(int minSdkVersion) 设置兼容的最小SDK版本
    • minSdkVersion(String minSdkVersion) 设置兼容的最小版本
    • proguardFile(proguardFile) 添加一个混淆文件
    • proguardFiles(proguardFileArray) 添加多个混淆文件
    • setProguardFiles(proguardFileIterable) 设置多个混淆文件
    • targetSdkVersion(int targetSdkVersion) 设置目标SDK版本
    • targetSdkVersion(String targetSdkVersion) 设置目标SDK版本
  • testOptions:设置测试相关属性
    • reportDir 设置测试报告的目录
    • resultsDir 设置测试结果的目录
    • aaptOptions:设置AAPT的属性
    • failOnMissingConfigEntry Forces aapt to return an error if it fails to find an entry for a configuration.
    • ignoreAssets Pattern describing assets to be ignore.
    • noCompress Extensions of files that will not be stored compressed in the APK.
    • useNewCruncher Whether to use the new cruncher.
  • lintOptions:设置Lint的属性
  • dexOptions
  • compileOptions:设置编译的相关属性
  • packagingOptions:设置APK包的相关属性
  • splits:设置如何拆分APK(比如你想拆分成arm版和x86版)

3) dependencies:配置依赖

新特性:

Google在用Gradle最为Android打包工具的时候引入了 applicationId 的概念,这是为了 打多个不同ID的APK包 准备的。

applicationId 可以和清单文件中的 packageName 不一样,我们在代码中通过 getPackageName() 方法拿到的是 applicationId ,而清单文件中配置的packageName则仅作为 R.javaBuildConfig.java 的存放目录。
这样一来通过 Class.forName(getPackageName()+”.R”) 来获取 R 类的方式就行不通了,一定要注意。

打包

build.gradle 文件配置完成后,打开终端,进入项目目录下,执行 gradle build 即可打包,打包结束后在相应module的 build/outputs/apk/ 目录下可以看到 .apk 文件。

如果你是在项目目录下执行的打包命令,那么会对项目中所有的 module 都打包,进入某个module目录下执行打包命令就只对当前module打包,每个module打包生成的APK或AAR都才存放在mudule的 build/outputs 目录下。

使用第三方库

1) 指定libs目录为jar库

目录的配置就是在build.gradle文件中,如下图所示:
这里写图片描述

2) Module之间的依赖

现在假如项目中有两个Module,一个 library 一个 sample ,现在sample要依赖library:
这里写图片描述

只需在 samplebuild.gradle 文件中添加 compile project(':library’) 即可,如下图所示:
这里写图片描述

这里有个限制就是library必须library module,那么如何决定一个Module是不是library module呢,区别就在于build.gradle文件的apply plugin参数,例如:

sample的apply plugin参数的值是 com.android.application ,就说明这是个app
这里写图片描述

library的apply plugin参数的值是 com.android.library,就说明这是个library
这里写图片描述

需要注意的是从1.0开始library module的build.gradle不再需要 applicationId 参数,如果有的请删除

3) 使用AAR

第三方的库无外乎两种情况:

  • 一些基础功能库,例如图片加载、网络请求等,这些库只有一个jar文件
    使用的时候就很方便了直接放到libs目录下就可以了。
  • 一些UI组件库,既包含有Java文件又有资源文件 eclipse里我们要么把第三方库弄成一个library项目(在studio中就是把第三方库弄成一个library Module)然后引用,要么就把第三方库里的所有文件融合到我们的项目中。这样很不方便,也很难维护。

Android官方在开发Android Studio的时候就发布了一种独有的格式AAR,专门用于打包UI组件库。与jar相比其多了一些UI组件用到的属性、图片等一系列文件,它的好处在于你不需要再多创建一个Library Module,只需引用这个AAR文件即可,Android Sudio会自动把AAR包里的文件跟你的项目融合。

1)) AAR包的内部文件结构

/AndroidManifest.xml (mandatory)
/classes.jar (mandatory)
/res/ (mandatory)
/R.txt (mandatory)
/assets/ (optional)
/libs/*.jar (optional)
/jni/<abi>/*.so (optional)
/proguard.txt (optional)
/lint.jar (optional)

2)) 优缺点

优点:使用方便,提升编译速度
缺点:不能方便的对AAR进行修改,Eclipse不支持AAR

  • 因为AAR是Google在开发Android Studio的时候推出的,并且Google正在抛弃Eclipse转向Android Studio .

3)) 生成AAR包

在你的项目中创建一个library Module然后在终端中执行 grade build,然后到 build/outputs/aar 目录下就能看到你的AAR文件。

4)) 使用本地AAR

recyclerview-v7-21.0.0.aar 为例,首先将AAR包放到libs文件夹下:
这里写图片描述

然后在 build.gradle 中添加如下代码将 libs 文件夹作为一个仓库:
这里写图片描述

然后依赖中配置即可
这里写图片描述

5)) 使用Maven仓库中的库

Gradle还支持直接使用Maven中的项目,使用方式也是很简单,只需在依赖配置中通过 compile参数 配置即可,jaraar 都支持。例如:
这里写图片描述

优点:

  • 使用方便,只需一行代码
  • 自动下载源码并关联
  • 自动发现新版本并提醒升级

缺点:受网络限制

6)) 使用私有Maven仓库

在项目的build.gradle文件的repositories节点中配置本地Maven仓库地址,,如下:
这里写图片描述

7)) 使用第三方库中的so文件

一些第三方的库出于提高性能或保护代码的目的,会将核心代码用C、C++来实现,并提供编译好的 so文件jar 给你用,例如国内的一些提供消息推送的sdk就是这么搞的。

在Eclipse中我们直接将so文件放到 libs 目录下即可使用。那么在AS中使用so文件同样简单,我们直接在main目录下创建 jniLibs 目录,并将so文件放到目录下即可,如下图所示:
这里写图片描述

参考文章:Android Studio大课堂 - 4.3.Coding - 使用第三方库

阅读更多
换一批

没有更多推荐了,返回首页