[android]第一行android代码

Android 系统架构

安卓操作系统的体系结构可以分为四个主要层级:
1.Linux内核层:Android基于Linux内核构建,它提供了底层的硬件抽象层(Hardware Abstraction Layer,HAL),用于管理设备驱动程序、内存管理、进程管理、安全性等底层功能。
2.系统库和运行时环境层:这一层包括了Android Runtime(ART)和核心的Java类库。ART是一个虚拟机,用于执行应用程序的字节码。Android平台使用的是基于Java的编程语言,应用程序通常以Dalvik Executable(DEX)格式运行在ART上。此外,Android还提供了一系列的系统库,用于实现常见的功能,例如图形渲染、数据库访问、网络通信等。
3.应用框架层:这一层提供了开发Android应用程序所需的各种服务和API。开发人员可以利用这些API来构建应用程序,包括用户界面(UI)组件、通知系统、数据存储、多媒体支持、位置服务等。Android应用程序通过调用应用框架中的API来与底层系统进行交互。
4.应用层:最顶层是应用层,包括了用户直接与之交互的应用程序,例如浏览器、短信应用、社交媒体应用等。这些应用程序是构建在Android应用框架之上的,它们通过调用框架提供的服务来实现各种功能。

四大组件

分别是Activity、Service、BroadcastReceive和ContentProvider。
Activity是所有Android应用程序的门面,凡是在应用中看得到的东西,都是放在Activity中的。
Service比较低调,无法看到它,但它会在后台默默地运行,即使用户瑞出了应用,Service仍然是可以继续运行的。
BroadcastReceive允许应用接收来自各处的广播消息,也可以向外发出广播消息。
ContentProvider为应用程序之间共享数据提供了可能。

开发环境

要准备的工具:
JDK
Android SDK
Android Studio

创建第一个项目 HelloWorld

创建过程略

这就创建成功了
运行程序即可把app推送到手机上并运行。

分析app程序

将项目结构模式切换为Project,就能看到真是目录结构了。

Project目录结构分析

1.gradle和.idea
这两个目录下放置的都是Android Studio 自动生成的一些文件,我们无需关心和编辑。
2.app
项目中的代码、资源等内容几乎都是放置在这个目录下的,我们后面的开发工作也都是在这个目录下进行的。
3.build
这个目录也无需关心,它主要包含了一些在编译时自动生成的文件。
4.gradle
这个目录包含了gradle wrapper的配置文件,使用gradle wrapper的方式不需要提前将gradle下载好,而是会自动根据本地的缓存情况决定是否需要联网下载gradle。
Android Studio默认没有启用gradle wrapper的方式,如果需要打开,可以点击Android Studio导航栏->File->Settings->Buile,Execution,Deployment->Buile Tools->Gradle,进行配置更改。

app目录内容分析

1.build
包含编译时自动生成的文件
2.libs
如果项目中使用到了第三方jar包,就需要把这些jar包都放在libs目录下,该目录下的jar包都会被自动添加到构建路径里去。
3.androidTest
这里编写Android Test测试用例的,可以对项目进行一些自动化调试
4.java
java目录是放置我们所有java代码的地方,展开该目录,将看到刚才创建的HelloWorld文件。
5.res
这个目录下内容很多,项目中使用到的所有的图片、布局、字符串等资源都要放在这个目录下。
这个目录下还有很多子目录,图片放在drawable目录下,布局放在layout目录下,字符串放在values目录下等。
6.AndroidManifest.xml
这是整个Android项目的配置文件,在程序中定义的所有四大组件都需要在这个文件里注册,还可以在这个文件中。
7.test
用来编写UnitTest测试用例的,是对项目及逆行自动化测试的另一种方式。
8. .gitignore
这个文件用于将app模块内的指定的目录或文件排除在版本控制之外,作用和外层的.gitignore文件类似。
9.build。gradle
这是app模块的gradle构建脚本,这个文件会指定很多项目构建相关的配置。
10.proguard-rules.pro
这个文件用于指定项目代码的混淆规则,当代码开发完成后打成安装包文件,如果不希望别人破解,通常会将代码进行混淆,从而让破解者难以阅读。

分析HelloWorld 项目

首先打开AndroidManifest.xml文件,找到

1
2
3
4
5
6
7
8
9
<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里注册的活动是不能使用的。
其中intent-filer里的两行代码非常重要是这个项目的主活动,在手机上点击应用图标,首先启动的就是这个活动。
打开MainActivity,代码如下

1
2
3
4
5
6
7
8
public class MainActivity extends AppCompatActivity {

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

从代码中可以看出MainActivity是继承自AppCompatActivity的,这是一种向下兼容的Activity,可以将Activity在各个系统版本中增加的特性和功能最低兼容到Android 2.1系统。
Actiity是Android系统提供的一个活动基类,我们项目中所有的活动都必须继承它或者它的子类才能拥有活动的特性(AppCompatActivity 是 Activity 的子类)。
在MainActivity里有一个onCreat()方法,这个方法是一个活动被创建时必定要执行的方法,其中有两行代码,但并没有”HelloWorld”字样。
Android程序的设计讲究逻辑和视图分离,通用做法就是在布局文件里编写界面,然后在活动中引入进来。
在onCreat()方法的第二行调用了 setContentView()方法,这个方法给当前活动引入了activity_main布局,HelloWorld就在那个文件里定义。
打开布局文件,布局文件都定义在res/layout目录下,展开layout目录会看到activity_main.xml文件。打开文件切换到Text视图,有如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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!",在这里定义的。

详解项目中的资源

展开res目录,里面有很多文件夹。

所有以drawable开头的文件夹都是用来放图片的,所有以mipmap开头的文件夹都是用来放应用图标的,所有以values开头的文件夹都是用来放字符串、样式、颜色等配置的,layout文件夹时用来放布局文件的。
之所以有这么多mipmap开头的文件夹,主要是为了让程序更好地兼容各种设备。
drawable文件夹也是这样,我们应该自己创建以drawable开头的文件夹。
打开 res/values/strings.xml文件,有以下内容:

1
2
3
<resources>
<string name="app_name">HelloWorld</string>
</resources>

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

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

其中string部分是可以替换的,如果引用的图片资源就可以替换成drawable,如果是引用的图片资源就可以替换成drawable,如果引用的是应用图标就可以替换成mipmap,如果引用的是布局文件就可以替换成layout。
举个栗子,打开AndroidManifest.xml文件,找到如下代码:

1
2
3
4
5
6
7
8
9
10
11
<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:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.HelloWorld"
...
</application>

其中,HelloWorld项目的应用图标就是通过android:icon属性来指定的,应用名称则是通过android:label属性来指定的。这里对资源的引用方式就是刚刚的XML中引用资源的语法。

详解build.gradle文件

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

掌握日志工具的使用

使用Android的日志工具Log

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

  • Log.v()。用于打印那些最为繁琐、意义最小的日志信息。对应级别verbose。
  • Log.d()。用于打印一些调试信息,这些信息对调试程序和分析问题应该是有帮助的。对应级别是debug。
  • Log.i()。用于打印一些比较重要的数据,这些数据应该是可以帮助分析用户行为的数据。对应级别info。
  • Log.w()。用于打印一些警告信息,提示程序在这个地方可能会有潜在风险,最好去修复一下出现警告的地方。对应级别warn。
  • Log.e()。用于打印程序中的错误信息当有错误信息打印出来的时候,一般都代表程序出现问题了,要尽快修复。对用级别error。
    一共有5个方法,每个方法还会有不同的重载。
    我们在HelloWorld项目中试试日志工具好不好用吧。
    打开MainActivity文件,在onCreat方法中添加一行打印日志的语句
    1
    2
    3
    4
    5
    6
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.d("MainActivity","onCreat execute");
    }
    Log.d()方法里传入了两个参数:第一个参数是tag,一般传入当前的类名就好,主要用于对打印信息进行过滤;第二个参数是msg,即想要打印的具体的内容。
    重新运行HelloWorld项目,点击顶部工具栏运行按钮,或者快捷键Shift+F10,等程序运行完毕,在logcat中就可以看到打印信息了。

    其中,可以看到打印日志的内容和tag名,还有包名、打印时间以及应用程序的进程号都可以看到

为什么用Log而不用System.out

在Java中经常使用System.out.println()方法来打印日志,但在项目开发中,极度不建议使用System.out.println()。
System.out除了使用方便之外一无是处。
快捷输入,在Android Studio中,想打印一条debug级别的日志,只需输入logd,回车,即可自动代码补全。