第一行代码Android--------阅读笔记

第1章        第一行Android代码

1.1 Android 简介

1.1.1 Android系统架构:Linux内核层、系统运行库层、应用框架层和应用层

  • Linux内核层

        Android系统是基于Linux内核的,这一层为Android设备的各种硬件提供了底层的驱动,如显示驱动、音频驱动、照相机驱动、蓝牙驱动、Wifi驱动、电源管理等。

  • 系统运行库层

        这一层通过一些C/C++库来为Android系统提供主要的特性支持。如SQLite库提供了数据库的支持,OpenGL|ES库提供了3D绘图的支持,Webkit库提供了浏览器内核的支持等。

        同样在这一层还有Android运行时库,它主要提供一些核心库,能够允许开发者使用Java语言来编写Android应用。另外,Android运行时库还包含了Dalvik虚拟机(5.0系统之后改为ART运行环境),它使得每一个Android应用都能运行在独立的进程当中,并且拥有一个自己的Davilk虚拟机实例。相较于Java虚拟机,Dalvik是专门为移动设备定制的,它针对手机内存、CPU性能有限等情况做了优化处理。

  • 应用框架层

        这一层主要提供构建应用程序时可能用到的各种API,Android自带的一些核心应用就是使用这些API完成的,开发者也可以通过使用这些API来构建自己的应用程序。

  • 应用层

         所有安装在手机上的应用程序都是属于这一层的,比如系统自带的联系人、短信等程序,或者是你从Google Play上下载的小游戏,当然还包括自己开发的程序。

1.1.3 Android应用开发特色

  • 四大组件

        Android系统四大组件分别是活动(Activity)服务(Service)广播接收器(Broadcast Receiver)内容提供器(Content Provider)

        其中活动是所有Android应用程序的门面,凡是在应用中看得到的东西,都是放在活动中的。而服务,你无法看到它,但它会一直在后台默默地运行,即使用户退出了应用,服务仍然是可以继续运行的。广播接收器允许你的应用接收来自各处的广播消息,比如电话、短信等,当然你的应用同样也可以向外发送广播消息。内容提供器则为应用程序之间共享数据提供了可能,比如你想要读取系统电话簿中的联系人,就需要通过内容提供器来实现。

  • 丰富的系统控件

        Android系统为开发者提供了丰富的系统控件,若不满足系统自带的控件效果,也可以定制属于自己的控件。

  • SOLite数据库

        Android系统还自带了这种轻量级、运算速度极快的嵌入式关系型数据库。它不仅支持标准的SQL语法,还可以通过Android封装好的API进行操作,让存储和读取数据变得非常方便。

  • 强大的多媒体

        Android系统还提供了丰富的多媒体服务,如音乐、视频、录音、拍照、闹铃等等,这一切你都可以在程序中通过代码进行控制,让你的应用变得更加丰富多彩。

  • 地理位置定位

        移动设备和PC相比起来,地理位置定位功能应该可以算是很大的一个亮点。现在的Android手机都内置有GPS,走到哪都可以定位到自己的位置,发挥想象可以做出创意十足的应用,如果再结合强大的地图功能,LBS这一领域潜力无限。

1.2 搭建开发环境

        设备均已安装相应软件,暂略环境搭建过程。

1.3 创建第一个Android项目

1.3.4 分析第一个Android程序

        默认Android模式的项目结构如下图:

        将项目结构模式切换成Project,此时是项目真实的目录结构,如下图:

  • .gradle和.idea ------ 这两个目录下放置的都是Android Studio 自动生成的一些文件。
  • app -------------------- 项目中的代码、资源等内容都是放置在这个目录下,后面单独讲解。
  • build ------------------- 这个目录主要包含一些编译时自动生成的文件(上图没有,原因待定)
  • gradle ----------------- 这个目录下包含了gradle wrapper的配置文件,使用gradle wrapper的方式不需要提前将gradle下载好,而是会自动根据本地的缓存情况决定是否需要联网下载gradle 。Android Studio默认就是启用gradle wrapper方式的,如果需更改成离线模式,可以点击Android Studio 导航栏---> File--->Setting--->Build, Execution, Deployment---->gradle,进行配置更改。
  • .gitignore ------------- 这个文件是将指定的目录或文件排除在版本控制之外的,版本控制见后续
  • build.gradle ---------- 这是项目全局的gradle构建脚本,通常该文件内容不需修改。
  • gradle.properties --- 这个文件是全局的gradle配置文件,在这里配置的属性将会影响到项目中所有的gradle编译脚本。
  • gradlew和gradlew.bat                                                                                                                  这两个文件是用来在命令行界面中执行gradle命令的,其中gradlew是在Linux或Mac系统中使用的,gradlew.bat 是在Windows系统中使用的。
  • HelloWorld.iml ------ 自动生成,用于标识这是一个IntelliJ IDEA项目,不需修改(上图未显示,原因未知)
  • local.properties ----- 用于指定本机中的Android SDK 路径,通常自动生成。
  • settings.gradle ------ 这个文件用于指定项目中所有引入的模块。由于Hello World项目中只有一个app模块,因此该文件中也就只引入了app这一个模块。通常情况下,模块的引入是自动完成的。

        除app目录之外,大多数的文件和目录是自动生成的,app目录下的才是重点,展开如图:

  • build ------ 和外层的build目录类似,包含一些在编译时自动生成的文件
  • libs -------- 如果项目中使用到了第三方jar包,需要把这些jar包都放在libs目录下,放在这个目录下的jar包都会被自动添加到构建路径里去。
  • androidTest ---- 此处是用来编写Android Test 测试用例的,可以对项目进行一些自动化测试
  • java ------- java目录是放置所有java代码的地方。
  • res -------- 在项目中使用到的所有图片、布局、字符串等资源都要存放在这个目录下。
  • AndroidManifest.xml --------- 这是整个项目的配置文件,在程序中定义的所有四大组件都需要在这个文件里注册,另外还可以在这个文件中给应用程序添加权限声明。
  • test -------- 此处是用来比编写Unit Test测试用例的,是对项目进行自动化测试的另一种方式。
  • .gitignore ----- 这个文件用于将app模块内指定的目录或文件排除在版本控制之外,作用和外层的.gitignore文件类似。
  • app.iml -------- IntelliJ IDEA项目自动生成的文件,不需修改。
  • build.gradle ---- 这是app模块的gradle构建脚本,这个文件中会指定很多项目构建相关的配置
  • proguard-rules.pro ----- 这个文件用于指定项目代码的混淆规则,当代码开发完成后打包成安装包文件,如果不希望代码被别人破解,通常会将代码进行混淆,从而让破解者难以阅读。

        打开AndroidManifest.xml文件,里面含有如下代码:


        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
  

          这段代码表示对MainActivity进行注册,没有在AndroidManifest.xml里注册的Activity是不能使用的。<action android:name="android.intent.action.MAIN" /><category android:name ="android.intent.category.LAUNCHER" />表示MainActivity是这个项目的主Activity,在手机上点击图标,首先启动的就是这个Activtity。

        打开MainActivity,代码如下:

package com.example.helloworld;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

          MainActivity是继承自AppCompatActivity的。AppCompatActivity是AndroidX中提供的一种向下兼容是我Activity,可以使Activity在不同系统版本中的功能保持一致性,而Activity类是Android系统提供的一个基类,项目中所有定义的Activity都必须继承它或者它的子类才能拥有Activity的特性(AppCompatActivity是Activity的子类)。

        MainActivity中有一个onCreate()方法,这个方法是一个Activity被创建时必定要执行的方法。

        Android程序的设计讲究逻辑和视图分离,因此通常在布局文件中编写界面,然后在Activity中引入进来。在onCreate()方法的第二行调用了setContentView()方法,这个方法给当前的Activity引入了一个activity_main布局。

        布局文件都是定义在res/layout目录下的,展开layout目录,打开activity_main.xml文件,切换到Text视图,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

        其中,TextView是Android提供的一个控件,用于在布局中显示文字。

1.3.5 详解项目中的资源

        res目录如下图:

        其中,所有以drawable开头的文件夹都是用来放图片的;所有以mipmap开头的文件夹都是用来放应用图标的;所有以values开头的文件夹都是用来放字符串、样式、颜色等配置;layout文件夹用来放布局文件的。

        这么多mipmap开头的文件夹,是为了让程序能够更好地兼容各种设备。应自行创建drawable-hdpi、drawable-xhdpi、drawable-xxhdpi等目录。在制作程序时,能够给同一张图片提供几个不同分辨率的版本,分别放在这些目录下,程序运行的时候,会自动根据当前运行设备分辨率的高低选择加载哪个目录下的图片。如果只有一份图片,把所有图片放在drawable-xxhdpi目录下,这是最主流的设备分辨率目录。

        打开res/values/strings.xml文件,内容如下:

<resources>
    <string name="app_name">HelloWorld</string>
</resources>

        这里定义了一个应用程序名的字符串,有以下两种方式引用它。

  • 在代码中通过R.string.hello_world可以获得该字符串的引用。 R.string.app_name
  • 在XML中通过@string/hello_world可以获得该字符串的引用。 @string/app_name

        其中,string部分可以替换,如果引用图片资源替换为drawable,引用应用图标替换成mipmap,引用布局文件替换成layout,以此类推。

        例如,打开AndroidManifest.xml文件,找到如下代码:

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.HelloWorld">
        ...
    </application>

        其中,HelloWorld项目的应用图标是通过android:icon属性指定的;应用的名称是通过android:lable指定的。这里对资源的引用方式正是在XML中引用资源的语法。

1.3.6 详解build.gradle文件

        Android Studio是采用Gradle来构建项目的。Gradle是一个非常先进的项目构建工具,它使用了一种基于Groovy的领域特定语言(DSL)来声明项目设置,摒弃了传统基于XML的各种繁琐配置。

        HelloWorld项目中有两个build.gradle文件,一个在最外层目录下,一个在app目录下。这两个文件对构建Android Studio项目都起到了至关重要的作用。

  • 最外层目录下的build.gradle文件,代码如下:
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.4"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

        其中,repositories的闭包中声明了google()和mavenCentral()这两行配置,它们分别对应了一个代码仓库,google仓库中包含的主要是Google自家的扩展依赖库,而mavenCentral仓库中包含的大多是一些第三方的开源库,声明这两行配置后,可以在项目中轻松引用任何google和mavenCentral仓库中的依赖库。

        dependencies闭包中使用classpath声明了一个Gradle插件。插件版本号通常和当前Android Studio的版本是对应的。

        通常情况下,并不需要修改这个文件中的内容,除非想添加一些全局的项目构建配置。

  • app目录下的build.gradle文件,代码如下:
plugins {
    id 'com.android.application'
}

android {
    compileSdk 32

    defaultConfig {
        applicationId "com.example.helloworld"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

        第一行应用了一个插件,一般有两种值可选:com.android.application表示这是一个应用程序模块,com.android.library表示这是一个库模块。两者区别是,应用程序模块可以直接运行,库模块只能作为代码库依附于别的应用程序模块来运行。

        在android闭包中可以配置项目构建的各种属性。其中,compileSdk用于指定项目的编译版本。android闭包中嵌套了一个defaultConfig闭包,defaultConfig闭包中可以对项目的更多细节进行配置。其中,application用于指定项目的包名,这里可以对包名进行修改。minSdk用于指定项目最低兼容的Android系统版本。targetSdk指定的值表示在该目标版本上已经做过充分的测试,系统将会为你的应用程序启动一些最新的功能和特性。versionCode用于指定项目版本号,versionName  用于指定项目版本名,这两个属性在生成安装文件时非常重要。最后,testInstrumentationRunner用于在当前项目中启用JUnit测试,可以为当前项目编写测试用例,以保证功能的正确性和稳定性

        buildTypes闭包中用于指定生成安装文件的相关配置,通常只会有两个子闭包:一个是debug ,一个是release。debug闭包用于指定生成测试版安装文件的配置,release闭包用于指定生成正式版安装文件的配置。另外,debug闭包是可以忽略不写的。release闭包中,minifyEnabled用于指定是否对代码进行混淆,true表示混淆,false表示不混淆。proguardFiles用于指定混淆时使用的规则文件,这里指定了两个文件:第一个proguard-android-optimize.txt是在<Android SDK>/tools/ proguard目录下的,里面是所有项目通用的混淆规则;第二个proguard-rules.pro是在当前项目的根目录下的,里面可以编写当前项目特有的混淆规则。需要注意的是,通过Android Studio直接运行项目生成的都是测试版安装文件,关于如何生成正式版安装文件,会在后续章节学习。

        dependencies闭包的功能非常强大,它可以指定当前项目所有的依赖关系。通常Android Studio项目一共有3种依赖方式:本地依赖、库依赖和远程依赖。本地依赖可以对本地的jar包或目录添加依赖关系,库依赖可以对项目中的库模块添加依赖关系,远程依赖可以对仓库上开源项目添加依赖关系。

        在dependencies闭包的配置中,implementation是远程依赖声明,androidx.appcompat: appcompat:1.2.0就是一个标准的远程依赖库格式,其中androidx.appcompat是域名部分,用于和其他公司的库做区分;appcompat是工程名部分,用于和同一个公司中不同的库工程做区分;1.2.0是版本号,用于和同一个库不同的版本做区分。加上这句声明后,Gradle在构建项目时会首先检查下本地是否已经有这个库的缓存,如果没有的话则会自动联网下载,然后再添加到项目的构建路径中。至于库依赖声明,这里没有用到,它的基本格式是implementation project后面加上要依赖的库的名称,比如implementation project(':helper')这句声明,helper为一个库模块的名字。剩下的testImplementation和androidTestImplementation都是用于声明测试用例库的,暂时用不到,先忽略。

1.4 掌握日志工具的使用

1.4.1 使用Android的日志工具Log

        Android中的日志工具类是Log(android.util.Log),这个类中提供了如下5个方法来供打印日志。

  • Log.v() ---- 用于打印最为琐碎的、意义最小的日志信息。对应级别verbose,是Android日志里级别最低的一种。
  • Log.d() ---- 用于打印一些调试信息,这些信息对调试程序和分析问题有帮助。对应级别debug,比verbose高一级。
  • Log.i() ------ 用于打印一些比较重要的数据,可以帮助分析用户行为的数据。对应级别info,比debug高一级。
  • Log.w() ----- 用于打印警告信息,提示程序在这个地方可能会有潜在的风险,最好修复一下。对应级别warn,比info高一级。
  • Log.e() ------ 用于打印程序中的错误信息,必须尽快修复。对应级别error,比warn高一级。

        打开MainActivity,在onCreate()方法中添加一行打印日志的语句,如下所示:

package com.example.helloworld;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("MainActivity", "onCreate execute");
    }
}

        Log.d()方法中传入了两个参数:第一个参数是tag,一般传入当前的类名就好,主要用于对打印信息进行过滤;第二个参数是msg,即想要打印的具体内容。

1.4.2 为什么使用Log而不使用System.out

        System.out.println()方法的缺点太多,比如日志打印不可控制、打印时间无法确定、不能添加过滤器、日志没有级别区分等。

        Log和logcat配合的强大之处。首先,Logcat可以轻松添加过滤器,下图可以看到目前所有的过滤器:

        目前只有3个过滤器,Show only selected application表示只显示当前选中程序的日志,Firebase 是谷歌提供的一个分析工具,可以不用管它,No Filters相当于没有过滤器,会把所有的日志都显示出来。除此之外,可以自定义过滤器,添加过滤器流程如下:

        点击上图中的“Edit Filter Configuration”,会弹出一个过滤器配置界面,给过滤器取名叫data,并且让它对名为data的tag进行过滤,如下图:

         点击OK,会发现已经多了一个data过滤器。当点击这个过滤器的时候,会发现刚才在onCreate()方法里打印的日志没了,这是因为data过滤器只会显示tag名为data的日志。在onCreate()方法中把打印语句改成Log.d("data", "onCreate execute"),然后再次运行程序,就会在data过滤器下看到这行日志了。

        logcat中主要有5个日志级别控制,分别对应上面介绍的5个方法,如下图:

        当前选中的级别是Verbose,也就是最低等级。这意味着不管使用哪一个方法打印日志,这条日志都一定会显示出来。如果奖级别选中为debug,这是只有使用debug及以上级别方法打印的日志才会显示出来,以此类推。

        关键字过滤。如果使用过滤器加日志级别控制还是不能锁定想查看的日志内容,那么可以通过关键字进行进一步的过滤。如图:

        可以在输入框中输入关键字的内容,这样只有符合关键字条件的日志才会显示出来,从而能够快速定位到任何想查看的日志。另外,关键字过滤是支持正则表达式的。

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值