Android开发基础——Android简介

本系列文章主要针对Android 10(Q)进行介绍。

Android系统架构

Android大致可以分为4层架构:

  • Linux内核层
  • 系统运行库层
  • 应用框架层
  • 应用层

Linux内核层

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

系统运行库层

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

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

应用框架层

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

应用层

所有安装在手机上的应用程序都是属于这一层的,比如系统自带的联系人,短信等程序,或者是从Google Play上下载的软件,自己开发的程序等。

Android应用开发特色

Android系统为开发优秀的应用程序提供了很多便利的功能。

四大组件

Android系统四大组件分别是Activity,Service,BroadcastReceiver和ContentProvider。

  • Activity是所有应用程序的门面,只要是在应用中能够看到的东西,都是放在Activity中的
  • Service在后台运行,即使用户退出应用,Service仍然是可以继续运行的
  • BroadcastReceiver则允许应用接收来自各处的广播信息,比如电话,信息等,而应用也可以向外发出广播信息
  • ContentProvider则为应用程序之间共享数据提供了可能,比如想要读取系统通讯录中的联系人,就需要通过ContentProvider来实现

系统控件

Android系统为开发者提供了丰富的系统空间,使得用户可以方便地编写漂亮的界面。同时用户还可以定制自己的控件。

扫描二维码关注公众号,回复: 14871304 查看本文章

SQLite数据库

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

强大的多媒体

Android系统还提供了丰富的多媒体服务,如音乐,视频,录音,拍照等,这些功能都可以在程序中使用代码进行控制,从而丰富应用的功能。

搭建开发环境

前期准备

开发Android程序所需要准备的工具主要有以下3个:

JDK:JDK是Java语言的软件开发工具包,它包含了Java的运行环境,工具集合,基础类库等内容

Android SDK:Android SDK是Google提供的Android开发工具包,在开发Android程序时,需要通过引入该工具包来使用Android相关的API

Android Studio:之前Android项目都是使用Eclipse开发的,通过安装ADT插件就可以用来开发Android程序了。而Android Studio则是Google推出的一款官方的IDE工具,使用更为方便

环境搭建

Google将开发环境的搭建进行了集成,下载最新的开发工具就可以完成整个环境的搭建。工具的下载站点是:

Download Android Studio & App Tools - Android Developers

Android Studio 应用社区-安卓应用下载中心:安卓游戏/安卓软件/游戏合集/软件合集/安卓游戏下载/安卓软件下载

HelloWorld

项目创建

在环境搭建完成之后,当然是编写HelloWorld了。

首先创建一个新的项目: 

从上面的项目创建可以看出,能够选择创建手机,平板,可穿戴设备,TV等类型项目,但这里只关注手机和平板。

 项目创建中的各项字段含义为:

  • Name:表示项目名,此处为HelloWorld
  • Package name:表示项目包名,Android系统通过包名来区分不同应用程序,因此包名一定要具有唯一性。Android Studio会根据应用名称自动生成合适的包名,也可以自行修改
  • Save location:项目代码存放位置
  • Lanuage:选择开发语言,可选为Java和Kotlin,这里选择Kotlin(Google推荐)
  • Minimum SDK:设置项目的最低兼容版本

之后,项目创建成功。

 启动模拟器

 Android Studio自动生成了很多东西,此时不需要编写任何代码,该项目即可运行。不过在此之前,还需要有一个运行的载体,可以是一个真正的手机,也可以是Android模拟器。这里先使用模拟器运行程序。

模拟器可以在Android Studio的界面上创建,选择设备,下载对应的镜像,然后启动。之后模拟器就会像一个真正的手机一样,有一个开机过程,启动完成后的模拟器如下:

 运行项目

现在模拟器已经启动了,之后就可以将该项目运行到模拟器上。

 各项图标的含义为:

  • 左侧的锤子:用来编译项目
  • app下拉列表:用来选择运行哪一个项目,通常app就是当前的主项目
  • 设备下拉列表:用来选择运行到哪个设备
  • 右侧的三角:运行项目
  • 右侧的方框:停止项目

项目运行之后,在模拟器上的显示如下:

 之后,在启动器列表中也可以看到多了一个HelloWorld应用:

项目目录

其实整个过程中并没有编写任何代码,但是项目还是可以运行的,这是因为Android Studio已经自动生成的。这里看一下整个项目代码结构:

这里看一下上面显示的内容含义。

 .gradle和.idle

这两个目录下放置的都是Android Studio自动生成的一些文件,无须关心,无须手动编辑。

app

项目中的代码,资源等内容都是放置在这个目录下的。

 build

这个目录主要包含了一些在编译时自动生成的文件,也无须关心。

gradle

这个目录下包含了gradle wrapper的配置文件,使用gradle wrapper的方式不需要提前将gradle下载好,而是会自动根据本地的缓存情况决定是否需要联网下载gradle。Android Studio默认就是启动gradle wrapper方式的,如果需要更改成离线模式,可以在Settings中进行配置更改。

.gitignore

该文件是用来将指定的目录或文件排除在版本控制之外的。

build.gradle

这是项目全局的gradle构建脚本,通常这个文件中的内容是不需要更改的。

gradle.properties

该文件是全局的gradle配置文件,在这里配置的属性将会影响到项目中所有的gradle编译脚本。

gradles和gradlew.bat

这两个文件是用来在命令行界面中执行gradle命令的,其中gradlew是在Linux或Mac系统中使用的,gradlew.bat是在Windows系统中使用的。

local.properties

该文件用于指定本机中的Android SDK路径,通常内容是自动生成的,无需更改。如果本机中的Android SDK位置发生了变化,将该文件中的路径更改为新的位置即可。

settings.gradle

该文件用于指定项目中所有引入的模块。由于HelloWorld项目中只有一个app模块,因此该文件中也就只引入了app这一个模块。通常情况下,模块的引入是自动完成的。

上面提到的文件和目录大部分都是自动生成的,无需更改,而app目录下内容才是项目中的重点,其结构为:

 这里看一下上面显示的内容含义。

 build

该目录和之前的build目录类似,也包含了一些在编译时自动生成的文件,其内容也更加复杂,不过也无须关心。

libs

如果项目中包含了第三方jar包,就需要把这些jar包都放在libs目录下,放在这个目录下的jar包会被自动添加到项目的构建路径中。

androidTest

这里是用来编写Android Test测试用例的,可以对项目进行一些自动化测试。

java

该目录是放置所有Java代码的地方,也包含Kotlin的代码,在该目录下,系统已经主动生成了一个MainActivity文件。

res

该目录下的内容包含项目中使用到的所有图片,布局,字符串等资源。该目录还包含很多子目录,图片放在drawable目录下,布局放在layout目录下,字符串放在values目录下。

AndroidManifest.xml

这是整个项目的配置文件,程序中定义的所有四大组件都需要在该文件中注册,另外还可以在该文件中给应用程序添加权限声明。

test

这里用来编写Unit Test测试用例,是对项目进行自动化测试的另一种形式。

.gitignore

该文件用于将app模块内指定的目录或文件排除在版本控制之外,作用和外层的.gitignore

文件类似。

build.gradle

这里app模块的gradle构建脚本,该文件中指定了很多项目构建相关的配置。

proguard-rules.pro

该文件用于指定项目代码的混淆规则,当代码开发完成后打包成安装包文件,如果不希望代码被别人破解,通常会将代码进行混淆。

项目运行规则

这里看一下HelloWorld项目是如何运行的。首先是AndroidManifest.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.helloworld">

    <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">
        <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>
    </application>

</manifest>

上边的文件中,activity节点中的代码段表示对MainActivity的注册,没有在AndroidManifest.xml文件中注册的Activity是不能够使用的。其中intent-filter中的两行代码比较重要,表示MainActivity是该项目的主Activity,在手机上点击应用图标,首先启动的就是该Activity。

而MainActivity其实就是之前启动项目后出现的界面,其代码为:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

从上面可以看出,MainActivity继承自AppCompatActivity的。AppCompatActivity是AndroidX中提供的一种向下兼容的Activity,可以使Activity在不同系统版本中的功能保持一致性。

而Activity类是Android系统提供的一个基类,项目中所有自定义的Activity都必须继承它或者它的子类才能拥有Activity的特性(AppCompatActivity是Activity的子类)。

同时上面的代码中还有一个onCreate()方法,该方法是一个Activity被创建时必定要执行的方法,其中只有两行代码,并且没有“Hello World!”的字样。那么其显示又是从何而来的?

其实Android程序设计讲究逻辑与视图分离,因此更一般的做法是在布局文件中编写界面,然后在Activity中引入进来。可以看到onCreate()方法的第二行调用了setContentView()方法,就是该方法给当前的Activity引入了一个activity_main布局:

<?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>

之前提到图片,布局,字符串等内容都放置在res目录下,同样上面的文件也位于res/layout目录下,上边的TextView中的内容正是"Hello World!"。

项目中的资源

 既然所有的资源都是在res目录下的,那么看一下其目录结构:

上边显示的内容中:

  • drawable:所有以drawable开头的目录都是用来存放图片的
  • mipmap:所有以mipmap开头的目录都是用来存放应用图标的
  • values:所有以values开头的目录都是用来存放字符串,样式,颜色等配置的
  • layout:所有以layout开头的目录都是用来存放布局文件的

 而之所以有很多mipmap开头的目录,其实是为了使程序能够更好地兼容各种设备,其它目录也有类似的作用,虽然Android Studio没有自动生成,但是用户也可以手动创建drawable-hdpi,drawable-xhdpi,drawable-xxhdpi等目录。在应用开发时,最好能够为同一张图片准备不同分辨率的版本,放置在对应目录下,程序在运行的时候,会自动根据当前运行设备分辨率的高低选择加载哪个目录下的图片。只不过这是最好的情况,更多的时候只会存在一份图片,此时只要将所有图片都放在drawable-xxhdpi目录下就好了,因为这是最主流的设备分辨率目录。

比如res/values/strings.xml文件:

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

上面文件中定义了app_name,这对应应用程序名的字符串,可以通过两种方式进行应用:

  • 在代码中通过R.string.app_name引用该字符串
  • 在XML中通过@string/app_name引用该字符串

上边提到的是基本的语法,其中string部分可以替换为drawable,以引用图片资源,替换为mipmap,以引用应用图标,替换为layout,以引用布局文件。

比如之前提到的AndroidManifest.xml文件中的icon,lable,roundIcon等都是采用了上面的引用形式:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.helloworld">

    <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">
        <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>
    </application>

</manifest>

build.gradle文件

Android Studio是通过Gradle进行项目构建的,该工具基于Groovy的领域特定语言(DSL)来进行项目设置,而不同于基于XML的繁琐配置。

在之前的目录结构中,提到存在两个build.gradle文件,一个在最外层的项目目录下,另一个在app目录下,这两个文件都对项目构建起到了重要的作用。这里看一下这两个文件,首先是最外层的build.gradle文件:

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.0"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"

        // 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()两行配置,分别对应了一个代码仓库,声明了这两行配置后,就可以在项目中使用相关的依赖库了
  • dependencies使用classpath声明了Gradle和Kotlin插件,因为Gradle插件不是专门为创建Android项目而开发的,其它项目如Java/C++也可以使用Gradle来构建,因此需要声明。其声明部分最后表示的是插件的版本号,其一般是和当前Android Studio的版本对应的。而Kotlin插件则表示当前项目是使用Kotlin开发的。

而内层app下的build.gradle文件为:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdk 33

    defaultConfig {
        applicationId "com.example.helloworld"
        minSdk 21
        targetSdk 33
        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
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.3.2'
    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'
}

上面的内容中:

  • plugins:说明了相关的插件
    • com.android.application:表示这是一个应用程序模块(com.android.library表示这是一个库模块,两者区别在于应用程序模块可以直接运行,库模块只能作为代码库依附于别的应用程序模块来运行)
    • kotlin-android:表示应用了该插件
  • android:配置项目构建的各种属性
    • compileSdk:用于指定项目的编译版本
    • defaultConfig:可以配置项目的相关细节
      • applicationId:是每个应用的唯一标识符,默认使用项目创建时指定的包名,如果后期需要更改包名,就是修改这里
      • minSdk:指定项目最低兼容的Android系统版本
      • targetSdk:表示在该目标版本上已经进行了充分测试,系统将会为应用程序启用一些最新的功能和特性
      • versionCode:用于指定项目的版本号
      • versionName:用于指定项目的版本名
      • testInstrumentationRunner:用于在当前项目中启用JUnit测试,可以为当前项目编写测试用例,以保证功能的正确性和稳定性
    • buildTypes:用于指定生成安装文件的相关配置,通常只会有两个子项,release和debug
      • release:用于指定生成正式版安装文件的配置
        • minifyEnabled:用于指定是否对项目的代码进行混淆,true表示混淆,false表示不混淆
        • proguardFiles:用于指定混淆时使用的规则文件,这里指定了两个文件,proguard-android-optimize.txt是在Android SDK/tools/prouard目录下的,该目录包含所有项目通用的混淆规则,proguard-rules.pro是在当前项目的根目录下的,里边可以编写当前项目特有的混淆规则
      • debug:用于指定生成测试版安装文件的配置,可以忽略不写。不过通过Android Studio运行项目生成的都是测试版安装文件
    • compileOptions:指定编译选项配置
      • sourceCompatibility:指定编译编译.java文件的jdk版本

      • targetCompatibility:确保class文件与targetCompatibility指定版本,或者更新的Java虚拟机兼容

    • kotlinOptions:指定Kotlin的相关选项

      • jvmTarget:指定kotlin相关的编译配置

  • dependencies:指定当前项目的所有依赖关系,通常项目中可能存在三种依赖关系:本地依赖,库依赖和远程依赖。本地依赖可以对本地的jar包或目录添加依赖关系,库依赖可以对项目中的库模块添加依赖关系,远程依赖则可以对之前提到的仓库上的开源项目添加依赖关系

    • implementation fileTree():表示本地依赖声明,这里没有用到

    • implementation:表示远程依赖,如 androidx.appcompat:appcompat:1.2.0就是一个标准的远程依赖库格式, androidx.appcompat表示域名部分,用于和其它公司的库做区分,appcompat表示工程名部分,用于和同一个公司中不同的库工程做区分,1.2.0表示版本号,用于和同一个库不同的版本做区分。加上这句声明后,Gradle在项目构建时会首先检查一下本地是否已经有该库的缓存,如果没有的话则会自动联网下载,然后再添加到项目的构建路径中。

    • implementation project():表示库依赖声明,这里没有用到

    • testImplementation:用于声明测试用例库

    • androidTestImplementation:用于声明测试用例库

日志工具

日志工具类

Android中的日志工具类是Log(Android.util.log),该类中提供了5种方法来打印日志:

  • Log.v():对应级别verbose,级别最低,用于打印琐碎的,重要性最小的日志信息
  • Log.d():对应级别debug,级别次低,用于打印一些调试信息,以进行程序调试和分析问题
  • Log.i():对应级别info,级别中等,用于打印一些比较重要的数据,以帮助分析用户行为
  • Log.w():对应级别warn,级别次高,用于打印一些警告信息,以提示用户可能存在潜在的风险
  • Log.e():对应级别error,级别最高,用于打印错误信息,比如catch语句中的内容

为了验证打印内容,可以将之前的MainActivity修改为:

package com.example.helloworld

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d("MainActivity","Hello World")
    }
}

在Log.d()中存在两个参数:

  • tag:一般传入当前类名,主要用于对打印信息进行过滤
  • msg:实际想要打印的内容

之后运行项目,在Logcat中就可以看到打印信息:

2022-09-04 20:05:49.382 11550-11550/com.example.helloworld D/MainActivity: Hello World

打印的内容包含日期,时间,进程号,包名,日志等级,类名,打印信息,可以说是很详细了。

Log和println()

其实从上面的内容看,Log类的作用就是进行信息的打印,其功能和println差不多,这里将上边的代码进行修改,对比一下:

package com.example.helloworld

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d("MainActivity","Hello World")
        println("MainActivity" + " " + "Hello World")
    }
}

其相关打印结果为:

2022-09-04 20:17:06.043 11854-11854/com.example.helloworld D/MainActivity: Hello World
2022-09-04 20:17:06.043 11854-11854/com.example.helloworld I/System.out: MainActivity Hello World

从上面打印结果来看,虽然都能够定位到是MainActivity这个类,但是其形式并没有使用Log类方便。同时使用Log类还有两个好处,一个是可以对打印内容的重要性进行分级,另一个是可以在调试的时候对打印内容进行过滤。

 上图显示的内容为:

  • Show only selected application:表示只显示当前选中程序的日志
  • Firebase:是Google提供的一个开发者工具和基础架构平台,可以忽略
  • No Filters:相当于没有过滤器
  • Edit Filter Configuration:则可以配置过滤器

比如添加如下的过滤器:

 这样就能够在Logcat中过滤tag为MainActivity的所有日志。

而Logcat还可以进行日志级别控制:

上图显示的内容为:

  • Verbose:显示所有等级日志
  • Debug:显示Debug等级及其以上等级的日志
  • Info:显示Info等级及其以上等级的日志
  • Warn:显示Warn等级及其以上等级的日志
  • Error:显示Error等级及其以上等级的日志
  • Assert:和Assert有关

同时Logcat中还支持关键字搜索,其功能类似文本编辑器中的内容搜索,不过Logcat中的关键字搜索支持正则表达式。

猜你喜欢

转载自blog.csdn.net/SAKURASANN/article/details/126685824