该篇用于记录学习安卓逆向基础知识,估计很杂很杂,也不会记录配置环境,中途不是很典型的错误调试过程也不会展示,更像是自己的学习笔记,不适合大家看。

第一个安卓项目

环境:

  • Android Studio 2024.2
  • Java 21.0.5
  • SDK:API 24
  • 虚拟机:Pixel 9 Pro API 27 / Android 8.1

项目目录

新建项目,可得到目录内容:

app
├── manifests
│ └── AndroidManifest.xml
├── java
│ ├── com.dta.first
│ │ └── MainActivity.java
│ ├── com.dta.first (androidTest)
│ ├── com.dta.first (test)
│ └── java (generated)
├── res
│ ├── drawable
│ ├── layout
│ ├── mipmap
│ ├── values
│ └── xml
└── res (generated)
Gradle Scripts

manifests目录

其中manifest文件用来存放一些安卓应用程序的配置文件,通常每个安卓应用都包含AndroidManifest.xml,是一个全局配置文件,会在内部定义一些组件、权限、图标等配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?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:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.FirstApplication"
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>

其中application节点包含了应用项目中application组建中的根结点

配置 含义
android:allowBackup=”true” 允许备份,默认为true
android:icon=”@mipmap/ic_launcher” 应用程序图标
android:label=”@string/app_name” 应用程序的名字
android:roundIcon=”@mipmap/ic_launcher_round” 圆形图标
android:theme=”@style/Theme.FirstApplication” 应用主题

activity节点(安卓里重要的组成部分),默认界面

1
2
3
4
# 主界面
<action android:name="android.intent.action.MAIN" />
# 启动界面
<category android:name="android.intent.category.LAUNCHER" />

java目录

然后还有java目录,其下存放的就是我们的代码,创建时我选择了一个默认界面,因此运行后可以得到:

image-20241226222544240

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.dta.first;

import android.os.Bundle;

import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
}
}

可以看到默认的代码,其中继承了一个AppCompatActivity类,重写了一个onCreate方法,onCreate就是应用程序启动后打开第一个界面时会回调该方法。

res目录

drawable:存放应用所需的图片资源(如 PNG、JPG 等)。

layout:存放 XML 格式的布局文件,定义了应用的 UI 结构。

mipmap:存放应用图标(通常是不同分辨率的图标文件)。

values:存放资源值文件(如 strings.xml、colors.xml 等),用于定义字符串、颜色、样式等资源。

xml:存放自定义的 XML 配置文件(如导航、网络安全配置等)。

**res (generated)**:这是由工具生成的资源文件夹,内容通常是编译时生成的。

Gradle Scripts目录

其下可以配置一些需要打包或者要引入一些外部的类库,或指定gradle版本等。包含项目的构建脚本,主要用于定义依赖关系、构建配置和任务。

编写应用程序

布局

先看看默认的布局:

image-20241226224213093

此时,我希望这个App最上方,显示出来我的项目名称,和他的logo,就可以通过调整themes下的style中继承的类即可修改:

image-20241226224558780

image-20241226224606262

在layout中可以修改页面的样式,TextView中就是页面中间默认的那个存放了Hello World的文本框,我们也可以在其中加一些内容:

1
2
3
4
5
6
<Button
android:id="@+id/btn_change"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="change"
tools:ignore=",MissingConstraints" />

可以看到,我加了一个按钮组件,id为btn_change,其中的text设置为change:

image-20241226225745822

java代码

默认代码中存在以下:

1
setContentView(R.layout.activity_main);

这个就是显示系统默认的布局文件,也就是默认关联到layout下的activity_main。此处也可以在onCreate下通过关联id操作组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MainActivity extends AppCompatActivity {
private Button btn_change;
private TextView tv_helloworld;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_change = findViewById(R.id.btn_change);
tv_helloworld = findViewById(R.id.tv_helloworld);
btn_change.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv_helloworld.setText("我被点击了~");
}
});
}
}

功能简述:点击btn后,textview中内容变成我被点击了~:

image-20241226230903567

常见组件

四大组件

  • Activity****(活动)

    Activity是Android应用的核心组件之一,负责管理用户界面和用户交互。每个Activity代表一个屏幕或界面。

    主要功能:管理UI,处理用户输入,控制界面跳转和生命周期。

    生命周期:包括onCreate、onStart、onResume等方法,用于管理从创建到销毁的整个过程。

    关键点

    1. 每个Activity都有一个Intent,用于启动自身或其他Activity。

    2. startActivityForResult可以在不同Activity之间返回数据。

  • BroadCastReceiver(广播接收器)

    BroadCastReceiver用于接收系统或应用发出的广播事件,并根据事件触发相应逻辑。

    主要功能:监听系统或自定义事件,例如电量变化、网络状态、电话呼入等。

    注册方式

    1. 静态注册:在AndroidManifest.xml中声明。应用即使未运行,系统广播依然能触发。

    2. 动态注册:在代码中使用registerReceiver()注册,随应用运行和销毁。

    典型广播

    1. 系统广播:android.intent.action.BOOT_COMPLETED(设备启动完成)

    2. 自定义广播:应用内部自定义事件广播。

  • Service(服务)

    Service用于在后台执行长时间运行的任务,无需与用户直接交互。

    主要功能:进行耗时操作(如下载、播放音乐)或持续性任务(如后台同步)。

    类型

    前台服务:用户可感知,带有通知栏提示。

    后台服务:用户不可感知,在后台运行。

    生命周期

    1. onStartCommand:启动服务的方法,常用于执行任务。

    2. onBind:绑定服务,提供与其他组件的通信接口。

    3. onDestroy:销毁服务,释放资源。

    关键点:Android 8.0(API 26)后,限制后台服务,需要使用前台服务或JobScheduler。

  • ContentProvider(内容提供者)

    ContentProvider用于在不同应用间安全地共享数据。

    主要功能:提供统一的接口,允许其他应用访问或修改数据。

    访问方式:通过URI访问,支持CRUD(增删改查)操作。

    典型应用:访问联系人数据、共享媒体文件或应用数据库。

    核心方法

    1. query:查询数据。
    2. insert:插入数据。
    3. update:更新数据。
    4. delete:删除数据。

    权限控制:通过标签限制外部访问,防止数据泄露。