Android开发学习笔记(1)——初识安卓

第一章——初识安卓

1、了解全貌

1.1、Android系统架构

Android大致可以分为四层架构:Linux内核层、系统运行库层、应用框架层和应用层。

a、Linux内核层

Android系统是基于Linux内核开发的,这层为Android设备的各种硬件提供了底层的驱动,如显示驱动、音频驱动、照相机驱动、蓝牙驱动、WIFI驱动、电源驱动等。也就是通过底层代码去调用硬件设备。

b、系统运行库层

这一层主要是C/C++实现,为安卓系统提供一些特性支持。比如SQLite库提供了对数据库的支持,OpenGl|ES库提供了对3D绘图的支持等。另外这一层还有一个安卓运行时库,是对上层Java的支持,上层Java最终会调用到该层的C/C++实现函数,其实也就是同一个功能函数的更底层版本。

c、应用框架层

提供一些开发时会用到的Java封装的Api

d、应用层

我们安装的软件、手机自带的软件等都在这一层上。

下面是一张结构图,便于我们对安卓系统架构更加了解

1.2、Android已经发布的版本

Android1.0:2008年9月

Android2.1、2.2、2.3:占据大量市场

Android3:市场份额少,有点失败

Android4:可以在平板和手机上使用

Android5:使用ART运行环境代替了Dalvik虚拟机,优化应用运行速度

Android6:加入运行时权限功能

Android7:加入多窗口模式功能

目前已经到Android14了

1.3、Android应用开发特色

我们看看Android系统给我们提供了哪些东西可供我们开发出优秀的应用程序。

a、四大组件

Android系统的四大组件分别是:

活动(Activity):在应用中能看到的东西都是放在活动中。

服务(Service):无法看到,它会一直在后台运行,即使用户退出了应用,服务可以继续运行。

广播接收器(Broadcast Receiver):允许应用接受来自各处的广播信息,比如电话、短信等。

内容提供器(Content Provider):为应用程序之间共享数据提供了可能,比如读取系统电话簿中的联系人。

b、系统控件

Android系统为开发者提供了丰富的系统控件,有助于我们编写出漂亮的界面,控件也可以自己定制

c、SQLite数据库

Android系统自带轻量级、运算速度快的嵌入式关系型数据库,支持标准的SQL语法,还可以通过封装好的API进行操作

d、多媒体

Android系统提供了丰富的多媒体服务,比如音乐、视频、录像、拍照、闹铃等。

e、地理位置定位

现在的Android都内置GPS,可以定位自己的位置。

2、Android Studio的安装

这个网上很多,随便找个教程跟着装就行了。

3、创建第一个Android项目

一些配置可以看图

项目的模版可以选择empty activity

可以配置一下模拟器环境,用于测试我们写好的App,后期也可以选择用真机测试,我就直接用真机了

由于我们选的empty activity模版帮我们已经生成好了hello world,所以就不用我们自己敲了

4、分析第一个Android程序

Project目录分析

这个是默认的Android项目结构,但是并不是真正的目录结构,而是被Android Studio转换过的,这种项目简洁明了,有助于开发

真正的项目目录结构,通过点击左上角的Android图标进行切换,现在我们逐一讲解每个目录:

1、.gradle和.idea:这两个目录下放置的都是Android Studio自动生成的一些文件,我们无须关心,也不要去手动编辑。

2、app:项目中的代码、资源等内容几乎都是放置在这个目录下的,开发工作也基本都是在这个目录下进行的

3、build:这个目录你也不需要过多关心,它主要包含了一些在编译时自动生成的文件。

4、gradle:这个目录下包含了gradle wrapper的配置文件,使用gradle wrapper的方式不需要提前将gradle下载好,而是会自动根据本地的缓存情况决定是否需要联网下载gradle。Android Studio默认没有启用gradlewrapper的方式,如果需要打开,可以点击Android Studio导航栏→File→Settings→Build, Execution,Deployment→Gradle,进行配置更改。
5、.gitignore这个文件是用来将指定的目录或文件排除在版本控制之外的

6、build.gradle:这是项目全局的gradle构建脚本,通常这个文件中的内容是不需要修改的

7、gradle.properties:这个文件是全局的gradle配置文件,在这里配置的属性将会影响到项目中所有的gradle编译脚本

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

9、HelloWorld.iml:iml文件是所有IntelliJ IDEA项目都会自动生成的一个文件(Android Studio是基于IntelliJ IDEA开发的),用于标识这是一个IntelliJ IDEA项目,我们不需要修改这个文件中的任何内容

10、local.properties:这个文件用于指定本机中的Android SDK路径,通常内容都是自动生成的,我们并不需要修改。除非你本机中的Android SDK位置发生了变化,那么就将这个文件中的路径改成新的位置即可

11、settings.gradle:这个文件用于指定项目中所有引入的模块。由于HelloWorld项目中就只有一个app模块,因此该文件中也就只引入了app这一个模块。通常情况下模块的引入都是自动完成的,需要我们手动去修改这个文件的场景可能比较少

app目录分析

1、build:这个目录和外层的build目录类似,主要也是包含了一些在编译时自动生成的文件,不过它里面的内容会更多更杂,我们不需要过多关心

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

3、androidTest:此处是用来编写Android Test测试用例的,可以对项目进行一些自动化测试

4、毫无疑问,java目录是放置我们所有Java代码的地方,展开该目录,你将看到我们刚才创建的the_first_demo文件就在里面

5、res:这个目录下的内容就有点多了。简单点说,就是你在项目中使用到的所有图片、布局、字符串等资源都要存放在这个目录下。当然这个目录下还有很多子目录,图片放在drawable目录下,布局放在layout目录下,字符串放在values目录下,所以你不用担心会把整个res目录弄得乱糟糟的

6、AndroidManifest.xml:这是你整个Android项目的配置文件,你在程序中定义的所有四大组件都需要在这个文件里注册,另外还可以在这个文件中给应用程序添加权限声明

7、test:此处是用来编写Unit Test测试用例的,是对项目进行自动化测试的另一种方式

8、gitignore:这个文件用于将app模块内的指定的目录或文件排除在版本控制之外,作用和外层的.gitignore文件类似

9、build.gradle:这是app模块的gradle构建脚本,这个文件中会指定很多项目构建相关的配置

10、proguard-rules.pro:这个文件用于指定项目代码的混淆规则,当代码开发完成后打成安装包文件,如果不希望代码被别人破解,通常会将代码进行混淆,从而让破解者难以阅读

分析helloword程序的运行流程

首先打开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注册的活动是不能使用的。

<action android:name="android.intent.action.MAIN" />
 <category android:name="android.intent.category.LAUNCHER" />

表示MainActivity是这个项目的主活动,在手机上点击图标启动,首先启动的就是这个活动。

那么MainActivity具体又有什么用呢?之前说过活动是可以看见的,我们测试时的那张图就是MainActivity的效果,现在一起看一下MainActivity的代码

package com.example.the_first_demo;
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,这是一种向下兼容的Activity,可以将Activity在各个系统版本中增加的特性和功能最低兼容到Android2.1系统。Activity是Android系统提供的一个活动基类,我们项目中所有的活动都必须继承它或者它的子类才能拥有活动的特性(AppCompatActivity是Activity的子类),onCreate是一个活动被创建时必定要执行的方法。或许现在有个疑问,为什么没有helloword字符串的打印,我们的界面上就有了helloword,这是因为安卓讲究的逻辑和视图分离,所以基本上不在Activity中编写界面的,更常见的做法是在布局文件中编写界面,然后在Activity中引入。我们注意到第二行有个setContentView,这就是引入布局R.layout.activity_main,那么helloword大概率就是在这个布局文件中。

布局文件

布局文件一般存放在res/layout中

<?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_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

TextView是一个Android系统提供的控件,用于在布局中显示文字,android:text=”Hello World!”实现了在app中显示helloword

项目中包含的资源

drawable开头的文件夹都是用来放图片的

mimmap开头的文件夹都是用来放应用图标的

values开头的文件夹都是用来放字符串、样式、颜色等

layout文件夹用来放布局文件的

可能有人会困惑一个App一般只有一个图标,为什么会有这么多个文件夹?因为这是为了让程序能够更好地兼容各种设备。

现在来看一下res/values/strings.xml

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

可以看到,这里定义了一个应用程序名的字符串,可以通过以下两种方式进行引用。

1、在代码中通过R.string.app_name
2、在xml中通过@string/app_name

其中的string也可以换成图片资源drawable、应用图标mipmap、布局文件layout等

举例

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

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/Theme.The_first_demo"
        tools:targetApi="31">
        <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>

可以看到应用程序的图标是通过android:icon设置,应用的名称是根据android:label指定,而他们使用的语法就是我们上面所说的第二种,现在如果想要实现修改App名称或者图标就可以通过修改 AndroidManifest.xml的相关属性。

详解build.gradle文件

Gradle是一个非常先进的项目构建工具,Android Studio是采用Gradle来构建项目的。在我们的测试项目中有两个build.gradle,一个是在最外层目录下,一个是在app目录下。

最外层目录下的build.gradle
    // Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
    id 'com.android.application' version '7.4.2' apply false
    id 'com.android.library' version '7.4.2' apply false
}

plugins代码块用于声明并配置要应用的Gradle插件。在这个例子中,它声明了两个插件:com.android.application和com.android.library,它们的版本号都是7.4.2,并且apply false是指这些插件不会自动应用到项目中。如果需要使用这些插件,可以在项目的其他构建脚本中显式地应用它们。通常情况下我们是不用修改这个文件的

app目录下的build.gradle
plugins {
    id 'com.android.application'//声明了使用的Gradle插件	
}
//一般有两种值可选:com.android.application表示这是一个应用程序模块,com.android.library 表示这是一个库模块。应用程序模块和库模块的最大区别在于,一个是可以直接运行的,一个只能作为代码库依附于别的应用程序模块来运行


android {
    namespace 'com.example.the_first_demo'//指定应用程序的命名空间,也就是应用程序的包名
    compileSdk 33//指定编译使用的API级别,sdk版本

    defaultConfig {
        applicationId "com.example.the_first_demo" //应用程序ID
        minSdk 16 //最低支持的Android版本
        targetSdk 33//指定的值表示你在该目标版本上已经做过了充分的测试,会启用该版本的新特性(目标版本)
        versionCode 1 //版本代码
        versionName "1.0"//版本名称

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false //指定是否对项目的代码进行混淆,true 表示混淆,false 表示不混淆
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            // proguardFiles 用于指定混淆时使用的规则文件,这里指定了两个文件
            // 第一个proguard-android-optimize.txt 是在Android SDK目录下的,里面是所有项目通用的混淆规则;
            // 第二个proguard-rules.pro 是在当前项目的根目录下的,里面可以编写当前项目特有的混淆规则

        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8 //指定编译使用的Java版本
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
	//声明了应用所依赖的库
	//指定应用程序运行时需要的库
    implementation 'androidx.appcompat:appcompat:1.4.1'//是支持应用程序兼容旧版本Android的库
    implementation 'com.google.android.material:material:1.5.0'//是Material Design组件库
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'//是一个用于布局的库
    //指定单元测试时需要的库
    testImplementation 'junit:junit:4.13.2'//JUnit单元测试库
    //指定Android测试时需要的库
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'//JUnit扩展库
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'//Android UI测试的Espresso库
}

5、日志工具的使用

Android中的日志工具类是Log(android.util.Log),可以方便我们打印一些信息进行调试。这个类一共提供了5个方法供我们打印日志:

a、Log.v()

用于打印那些最为琐碎的、意义最小的日志信息。对应级别verbose,是Android日志里面级别最低的一种

b、Log.d()

用于打印一些调试信息,这些信息对你调试程序和分析问题应该是有帮助的。对应级别debug,比verbose高一级

c、Log.i()

用于打印一些比较重要的数据,这些数据应该是你非常想看到的、可以帮你分析用户行为数据。对应级别info,比debug高一级

d、Log.w()

用于打印一些警告信息,提示程序在这个地方可能会有潜在的风险,最好去修复一下这些出现警告的地方。对应级别warn,比info高一级

e、Log.e()

用于打印程序中的错误信息,比如程序进入到了catch语句当中。当有错误信息打印出来的时候,一般都代表你的程序出现严重问题了,必须尽快修复。对应级别error,比warn高一级

测试

package com.example.the_first_demo;

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("HelloWordActivity","onCreate execute");

    }
}

Log.d有两个参数,第一个参数是tag,可以对打印的信息进行过滤,第二个参数是msg,是我们想要打印的值

打印的内容包含时间、应用程序的进程号、tag、包名、打印的信息。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 767778848@qq.com