第2章:编程基础与工具链
2.1 Java编程基础
2.1.1 Java语言特性
Java是安卓应用开发的主要语言,具有以下核心特性:
mindmap
root((Java特性))
面向对象
封装
继承
多态
抽象
平台无关
字节码
JVM
一次编译到处运行
内存管理
自动垃圾回收
堆栈管理
引用类型
安全性
字节码验证
安全管理器
访问控制
示例:Java基础语法
// 类定义和封装
public class Student {
// 私有成员变量(封装)
private String name;
private int age;
private double score;
// 构造方法
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
// 公共方法(接口)
public String getName() {
return name;
}
public void setName(String name) {
if (name != null && !name.trim().isEmpty()) {
this.name = name;
}
}
// 方法重载(多态的一种形式)
public void study() {
System.out.println(name + " is studying");
}
public void study(String subject) {
System.out.println(name + " is studying " + subject);
}
// toString方法重写
@Override
public String toString() {
return String.format("Student{name='%s', age=%d, score=%.2f}",
name, age, score);
}
}
2.1.2 Java内存模型
理解Java内存模型对逆向分析至关重要:
graph TB
subgraph JVM[Java虚拟机内存区域]
subgraph Heap[堆内存]
YoungGen[新生代]
OldGen[老年代]
MetaSpace[元空间]
end
subgraph NonHeap[非堆内存]
PC[程序计数器]
Stack[虚拟机栈]
NativeStack[本地方法栈]
DirectMem[直接内存]
end
end
subgraph GC[垃圾回收器]
MinorGC[Minor GC]
MajorGC[Major GC]
FullGC[Full GC]
end
YoungGen --> MinorGC
OldGen --> MajorGC
Heap --> FullGC
示例:内存分配和垃圾回收
public class MemoryExample {
public static void main(String[] args) {
// 在堆中创建对象
Student student1 = new Student("Alice", 20, 85.5);
Student student2 = new Student("Bob", 21, 92.0);
// 局部变量在栈中
int count = 100;
String message = "Hello World"; // 字符串常量池
// 数组在堆中分配
int[] scores = new int[1000];
// 显式触发垃圾回收(不推荐在生产代码中使用)
System.gc();
// 查看内存使用情况
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
long usedMemory = totalMemory - freeMemory;
System.out.println("Total Memory: " + totalMemory / 1024 / 1024 + " MB");
System.out.println("Used Memory: " + usedMemory / 1024 / 1024 + " MB");
System.out.println("Free Memory: " + freeMemory / 1024 / 1024 + " MB");
}
}
2.1.3 Java反射机制
反射是逆向分析中的重要技术:
import java.lang.reflect.*;
public class ReflectionExample {
public static void main(String[] args) {
try {
// 获取Class对象
Class<?> studentClass = Student.class;
// 或者:Class<?> studentClass = Class.forName("Student");
// 获取类信息
System.out.println("Class Name: " + studentClass.getName());
System.out.println("Simple Name: " + studentClass.getSimpleName());
System.out.println("Package: " + studentClass.getPackage().getName());
// 获取构造方法
Constructor<?>[] constructors = studentClass.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("Constructor: " + constructor);
Parameter[] parameters = constructor.getParameters();
for (Parameter param : parameters) {
System.out.println(" Parameter: " + param.getType() + " " + param.getName());
}
}
// 获取字段
Field[] fields = studentClass.getDeclaredFields();
for (Field field : fields) {
System.out.println("Field: " + field.getName() + " (" + field.getType() + ")");
System.out.println(" Modifiers: " + Modifier.toString(field.getModifiers()));
}
// 获取方法
Method[] methods = studentClass.getDeclaredMethods();
for (Method method : methods) {
System.out.println("Method: " + method.getName());
System.out.println(" Return Type: " + method.getReturnType());
System.out.println(" Parameters: " + Arrays.toString(method.getParameterTypes()));
}
// 创建实例并调用方法
Constructor<?> constructor = studentClass.getConstructor(String.class, int.class, double.class);
Object student = constructor.newInstance("Charlie", 22, 88.5);
// 调用方法
Method studyMethod = studentClass.getMethod("study", String.class);
studyMethod.invoke(student, "Java Programming");
// 访问私有字段
Field nameField = studentClass.getDeclaredField("name");
nameField.setAccessible(true); // 绕过访问控制
String name = (String) nameField.get(student);
System.out.println("Private field value: " + name);
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出示例:
Class Name: Student
Simple Name: Student
Package: com.example
Constructor: public Student(java.lang.String,int,double)
Parameter: class java.lang.String name
Parameter: int age
Parameter: double score
Field: name (class java.lang.String)
Modifiers: private
Field: age (int)
Modifiers: private
Method: getName
Return Type: class java.lang.String
Parameters: []
Charlie is studying Java Programming
Private field value: Charlie
2.2 Kotlin编程基础
2.2.1 Kotlin语言特性
Kotlin是Google推荐的安卓开发语言,具有现代化特性:
// 数据类(自动生成equals、hashCode、toString等方法)
data class User(
val id: Long,
val name: String,
val email: String?, // 可空类型
val age: Int = 0 // 默认参数
)
// 扩展函数
fun String.isValidEmail(): Boolean {
return this.contains("@") && this.contains(".")
}
// 高阶函数和Lambda表达式
fun processUsers(users: List<User>, processor: (User) -> Unit) {
users.forEach { user ->
processor(user)
}
}
// 密封类(类似于枚举但更强大)
sealed class Result<out T> {
data class Success<T>(val data: T) : Result<T>()
data class Error(val exception: Throwable) : Result<Nothing>()
object Loading : Result<Nothing>()
}
// 协程支持
suspend fun fetchUserData(userId: Long): Result<User> {
return try {
// 模拟网络请求
delay(1000)
val user = User(userId, "John Doe", "john@example.com", 25)
Result.Success(user)
} catch (e: Exception) {
Result.Error(e)
}
}
// 使用示例
fun main() {
val users = listOf(
User(1, "Alice", "alice@example.com", 25),
User(2, "Bob", null, 30),
User(3, "Charlie", "charlie@invalid", 22)
)
// 使用扩展函数
users.forEach { user ->
val emailStatus = user.email?.let { email ->
if (email.isValidEmail()) "Valid" else "Invalid"
} ?: "No email"
println("${user.name}: $emailStatus")
}
// 函数式编程风格
val validUsers = users.filter { it.email?.isValidEmail() == true }
val userNames = users.map { it.name }
val averageAge = users.map { it.age }.average()
println("Valid users: ${validUsers.size}")
println("User names: $userNames")
println("Average age: $averageAge")
}
2.2.2 Kotlin与Java互操作
Kotlin与Java完全互操作,这在逆向分析中很重要:
// Kotlin调用Java代码
import java.util.ArrayList
import java.util.Collections
class KotlinJavaInterop {
fun useJavaCollections() {
// 使用Java集合
val javaList = ArrayList<String>()
javaList.add("Kotlin")
javaList.add("Java")
// 调用Java静态方法
Collections.sort(javaList)
// 使用Java的System类
System.out.println("Current time: ${System.currentTimeMillis()}")
}
// 生成Java风格的getter/setter
@JvmField
var publicField: String = "accessible from Java"
// 静态方法(供Java调用)
companion object {
@JvmStatic
fun staticMethod(param: String): String {
return "Processed: $param"
}
}
}
对应的Java调用:
public class JavaKotlinInterop {
public static void main(String[] args) {
// 创建Kotlin对象
KotlinJavaInterop kotlinObj = new KotlinJavaInterop();
// 访问Kotlin字段
kotlinObj.publicField = "Modified from Java";
System.out.println(kotlinObj.publicField);
// 调用Kotlin静态方法
String result = KotlinJavaInterop.staticMethod("Hello from Java");
System.out.println(result);
// 调用Kotlin方法
kotlinObj.useJavaCollections();
}
}
2.3 安卓开发环境
2.3.1 Android Studio配置
Android Studio是官方的安卓开发IDE:
# 1. 下载Android Studio
# 访问 https://developer.android.com/studio
# 2. 配置SDK路径
export ANDROID_HOME=/Users/username/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/platform-tools
export PATH=$PATH:$ANDROID_HOME/build-tools/30.0.3
# 3. 验证安装
android --version
adb version
项目结构分析:
MyAndroidApp/
├── app/ # 应用模块
│ ├── build.gradle # 模块构建脚本
│ ├── proguard-rules.pro # 代码混淆规则
│ └── src/
│ ├── main/
│ │ ├── java/ # Java/Kotlin源码
│ │ ├── res/ # 资源文件
│ │ │ ├── layout/ # 布局文件
│ │ │ ├── values/ # 值资源
│ │ │ └── drawable/ # 图片资源
│ │ └── AndroidManifest.xml # 应用清单
│ ├── test/ # 单元测试
│ └── androidTest/ # 集成测试
├── build.gradle # 项目构建脚本
├── gradle.properties # Gradle配置
├── settings.gradle # 项目设置
└── local.properties # 本地配置
2.3.2 Gradle构建系统
Gradle是安卓项目的构建系统:
// app/build.gradle
android {
compileSdkVersion 31
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.myapp"
minSdkVersion 21
targetSdkVersion 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {
debuggable true
minifyEnabled false
applicationIdSuffix ".debug"
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
构建过程分析:
2.3.3 ADB工具详解
Android Debug Bridge是安卓开发和逆向的重要工具:
# 设备管理
adb devices # 列出连接的设备
adb connect 192.168.1.100:5555 # 通过网络连接设备
adb disconnect # 断开连接
# 应用管理
adb install app.apk # 安装应用
adb install -r app.apk # 覆盖安装
adb uninstall com.example.app # 卸载应用
# 文件操作
adb push local.txt /sdcard/ # 推送文件到设备
adb pull /sdcard/remote.txt . # 从设备拉取文件
# Shell命令
adb shell # 进入设备Shell
adb shell ls /data/data/ # 执行Shell命令
adb shell pm list packages # 列出安装的包
# 日志查看
adb logcat # 查看系统日志
adb logcat -s TAG # 过滤特定标签
adb logcat | grep "MyApp" # 过滤应用日志
# 端口转发
adb forward tcp:8080 tcp:8080 # 端口转发
# 屏幕截图和录制
adb shell screencap /sdcard/screen.png # 截图
adb shell screenrecord /sdcard/demo.mp4 # 录屏
实践示例:应用调试
# 1. 启动应用并查看进程
adb shell am start -n com.example.myapp/.MainActivity
adb shell ps | grep myapp
# 2. 查看应用日志
adb logcat -s "MyApp"
# 3. 查看应用数据目录
adb shell ls -la /data/data/com.example.myapp/
# 4. 导出应用数据库
adb shell cp /data/data/com.example.myapp/databases/app.db /sdcard/
adb pull /sdcard/app.db ./
# 5. 查看应用内存使用
adb shell dumpsys meminfo com.example.myapp
2.4 开发工具链
2.4.1 SDK工具集
Android SDK提供了丰富的开发和分析工具:
# SDK Manager - 管理SDK组件
sdkmanager --list # 列出可用组件
sdkmanager "platforms;android-31" # 安装特定平台
sdkmanager --update # 更新所有组件
# AVD Manager - 管理虚拟设备
avdmanager create avd -n "Pixel_API_31" -k "system-images;android-31;google_apis;x86_64"
avdmanager list avd # 列出虚拟设备
emulator -avd Pixel_API_31 # 启动虚拟设备
# AAPT - Android Asset Packaging Tool
aapt dump badging app.apk # 分析APK信息
aapt dump xmltree app.apk AndroidManifest.xml # 查看清单文件
aapt list app.apk # 列出APK内容
# DX/D8 - DEX编译器
dx --dex --output=classes.dex *.class # 编译为DEX
d8 --output . *.class # 使用D8编译器
2.4.2 构建工具
# Gradle Wrapper
./gradlew build # 构建项目
./gradlew assembleDebug # 构建Debug版本
./gradlew assembleRelease # 构建Release版本
./gradlew clean # 清理项目
# 查看构建信息
./gradlew tasks # 列出所有任务
./gradlew dependencies # 查看依赖关系
./gradlew properties # 查看项目属性
# ProGuard/R8 - 代码优化和混淆
# 在build.gradle中配置
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
}
ProGuard规则示例:
# proguard-rules.pro
# 保持Activity类不被混淆
-keep public class * extends android.app.Activity
# 保持自定义View
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
}
# 保持Parcelable实现
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
# 保持枚举
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# 保持注解
-keepattributes *Annotation*
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
2.4.3 调试工具
# JDWP - Java Debug Wire Protocol
adb forward tcp:8700 jdwp:1234 # 转发调试端口
jdb -attach localhost:8700 # 连接调试器
# GDB - GNU Debugger (用于Native代码)
adb push gdbserver /data/local/tmp/
adb shell chmod 755 /data/local/tmp/gdbserver
adb forward tcp:1234 tcp:1234
adb shell /data/local/tmp/gdbserver :1234 --attach 1234
# 在主机上连接
arm-linux-androideabi-gdb
(gdb) target remote :1234
(gdb) continue
2.5 版本控制与项目管理
2.5.1 Git版本控制
# 初始化Git仓库
git init
git remote add origin https://github.com/username/android-project.git
# 常用Git操作
git add . # 添加所有文件
git commit -m "Initial commit" # 提交更改
git push origin main # 推送到远程仓库
# 分支管理
git checkout -b feature/new-feature # 创建并切换分支
git merge feature/new-feature # 合并分支
git branch -d feature/new-feature # 删除分支
# 查看历史
git log --oneline # 简洁日志
git diff HEAD~1 # 查看差异
Android项目.gitignore示例:
# Built application files
*.apk
*.ap_
*.aab
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
build/
# Gradle files
.gradle/
gradle-app.setting
!gradle-wrapper.jar
!gradle-wrapper.properties
# Local configuration file
local.properties
# Android Studio
.idea/
*.iml
*.ipr
*.iws
.DS_Store
# External native build
.externalNativeBuild
.cxx/
# Version control
.svn/
# Keystore files
*.jks
*.keystore
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
2.5.2 持续集成
使用GitHub Actions进行自动化构建:
# .github/workflows/android.yml
name: Android CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'adopt'
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- name: Run tests
run: ./gradlew test
- name: Generate APK
run: ./gradlew assembleDebug
- name: Upload APK
uses: actions/upload-artifact@v2
with:
name: app-debug
path: app/build/outputs/apk/debug/app-debug.apk
2.6 实践项目:简单安卓应用
2.6.1 项目需求
创建一个简单的学生管理应用,包含以下功能:
- 学生信息录入
- 学生列表显示
- 数据持久化存储
- 基本的增删改查操作
2.6.2 项目实现
1. 数据模型
// Student.kt
data class Student(
val id: Long = 0,
val name: String,
val age: Int,
val major: String,
val gpa: Double
) {
fun isValidGpa(): Boolean = gpa in 0.0..4.0
fun getGradeLevel(): String = when {
gpa >= 3.5 -> "优秀"
gpa >= 3.0 -> "良好"
gpa >= 2.5 -> "中等"
gpa >= 2.0 -> "及格"
else -> "不及格"
}
}
2. 数据库设计
// StudentDatabase.kt
import androidx.room.*
@Entity(tableName = "students")
data class StudentEntity(
@PrimaryKey(autoGenerate = true)
val id: Long = 0,
@ColumnInfo(name = "name")
val name: String,
@ColumnInfo(name = "age")
val age: Int,
@ColumnInfo(name = "major")
val major: String,
@ColumnInfo(name = "gpa")
val gpa: Double
)
@Dao
interface StudentDao {
@Query("SELECT * FROM students ORDER BY name ASC")
suspend fun getAllStudents(): List<StudentEntity>
@Query("SELECT * FROM students WHERE id = :id")
suspend fun getStudentById(id: Long): StudentEntity?
@Insert
suspend fun insertStudent(student: StudentEntity): Long
@Update
suspend fun updateStudent(student: StudentEntity)
@Delete
suspend fun deleteStudent(student: StudentEntity)
@Query("DELETE FROM students WHERE id = :id")
suspend fun deleteStudentById(id: Long)
}
@Database(
entities = [StudentEntity::class],
version = 1,
exportSchema = false
)
@TypeConverters(Converters::class)
abstract class StudentDatabase : RoomDatabase() {
abstract fun studentDao(): StudentDao
companion object {
@Volatile
private var INSTANCE: StudentDatabase? = null
fun getDatabase(context: Context): StudentDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
StudentDatabase::class.java,
"student_database"
).build()
INSTANCE = instance
instance
}
}
}
}
3. Repository模式
// StudentRepository.kt
class StudentRepository(private val studentDao: StudentDao) {
suspend fun getAllStudents(): List<Student> {
return studentDao.getAllStudents().map { it.toStudent() }
}
suspend fun getStudentById(id: Long): Student? {
return studentDao.getStudentById(id)?.toStudent()
}
suspend fun insertStudent(student: Student): Long {
return studentDao.insertStudent(student.toEntity())
}
suspend fun updateStudent(student: Student) {
studentDao.updateStudent(student.toEntity())
}
suspend fun deleteStudent(student: Student) {
studentDao.deleteStudent(student.toEntity())
}
}
// 扩展函数用于转换
fun StudentEntity.toStudent(): Student {
return Student(id, name, age, major, gpa)
}
fun Student.toEntity(): StudentEntity {
return StudentEntity(id, name, age, major, gpa)
}
4. ViewModel实现
// StudentViewModel.kt
import androidx.lifecycle.*
import kotlinx.coroutines.launch
class StudentViewModel(private val repository: StudentRepository) : ViewModel() {
private val _students = MutableLiveData<List<Student>>()
val students: LiveData<List<Student>> = _students
private val _loading = MutableLiveData<Boolean>()
val loading: LiveData<Boolean> = _loading
private val _error = MutableLiveData<String?>()
val error: LiveData<String?> = _error
init {
loadStudents()
}
fun loadStudents() {
viewModelScope.launch {
try {
_loading.value = true
_error.value = null
val studentList = repository.getAllStudents()
_students.value = studentList
} catch (e: Exception) {
_error.value = "加载学生数据失败: ${e.message}"
} finally {
_loading.value = false
}
}
}
fun addStudent(student: Student) {
viewModelScope.launch {
try {
repository.insertStudent(student)
loadStudents() // 重新加载数据
} catch (e: Exception) {
_error.value = "添加学生失败: ${e.message}"
}
}
}
fun updateStudent(student: Student) {
viewModelScope.launch {
try {
repository.updateStudent(student)
loadStudents()
} catch (e: Exception) {
_error.value = "更新学生信息失败: ${e.message}"
}
}
}
fun deleteStudent(student: Student) {
viewModelScope.launch {
try {
repository.deleteStudent(student)
loadStudents()
} catch (e: Exception) {
_error.value = "删除学生失败: ${e.message}"
}
}
}
fun clearError() {
_error.value = null
}
}
// ViewModel Factory
class StudentViewModelFactory(private val repository: StudentRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(StudentViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return StudentViewModel(repository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
5. UI实现
// MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: StudentViewModel
private lateinit var adapter: StudentAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setupDatabase()
setupRecyclerView()
setupObservers()
setupClickListeners()
}
private fun setupDatabase() {
val database = StudentDatabase.getDatabase(this)
val repository = StudentRepository(database.studentDao())
val factory = StudentViewModelFactory(repository)
viewModel = ViewModelProvider(this, factory)[StudentViewModel::class.java]
}
private fun setupRecyclerView() {
adapter = StudentAdapter { student ->
// 点击学生项的处理
showStudentDetails(student)
}
binding.recyclerViewStudents.apply {
layoutManager = LinearLayoutManager(this@MainActivity)
adapter = this@MainActivity.adapter
// 添加分隔线
addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL))
}
}
private fun setupObservers() {
viewModel.students.observe(this) { students ->
adapter.submitList(students)
binding.textViewEmpty.isVisible = students.isEmpty()
}
viewModel.loading.observe(this) { isLoading ->
binding.progressBar.isVisible = isLoading
}
viewModel.error.observe(this) { errorMessage ->
errorMessage?.let {
Snackbar.make(binding.root, it, Snackbar.LENGTH_LONG).show()
viewModel.clearError()
}
}
}
private fun setupClickListeners() {
binding.fabAddStudent.setOnClickListener {
showAddStudentDialog()
}
}
private fun showAddStudentDialog() {
val dialogBinding = DialogAddStudentBinding.inflate(layoutInflater)
AlertDialog.Builder(this)
.setTitle("添加学生")
.setView(dialogBinding.root)
.setPositiveButton("添加") { _, _ ->
val name = dialogBinding.editTextName.text.toString().trim()
val ageStr = dialogBinding.editTextAge.text.toString().trim()
val major = dialogBinding.editTextMajor.text.toString().trim()
val gpaStr = dialogBinding.editTextGpa.text.toString().trim()
if (validateInput(name, ageStr, major, gpaStr)) {
val student = Student(
name = name,
age = ageStr.toInt(),
major = major,
gpa = gpaStr.toDouble()
)
viewModel.addStudent(student)
}
}
.setNegativeButton("取消", null)
.show()
}
private fun validateInput(name: String, age: String, major: String, gpa: String): Boolean {
return when {
name.isEmpty() -> {
showError("请输入姓名")
false
}
age.isEmpty() || age.toIntOrNull() == null || age.toInt() < 0 -> {
showError("请输入有效年龄")
false
}
major.isEmpty() -> {
showError("请输入专业")
false
}
gpa.isEmpty() || gpa.toDoubleOrNull() == null || gpa.toDouble() !in 0.0..4.0 -> {
showError("请输入有效GPA (0.0-4.0)")
false
}
else -> true
}
}
private fun showError(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
private fun showStudentDetails(student: Student) {
val details = """
姓名: ${student.name}
年龄: ${student.age}
专业: ${student.major}
GPA: ${student.gpa}
等级: ${student.getGradeLevel()}
""".trimIndent()
AlertDialog.Builder(this)
.setTitle("学生详情")
.setMessage(details)
.setPositiveButton("编辑") { _, _ ->
showEditStudentDialog(student)
}
.setNegativeButton("删除") { _, _ ->
showDeleteConfirmation(student)
}
.setNeutralButton("关闭", null)
.show()
}
private fun showEditStudentDialog(student: Student) {
// 实现编辑对话框
// 类似于添加对话框,但预填充现有数据
}
private fun showDeleteConfirmation(student: Student) {
AlertDialog.Builder(this)
.setTitle("确认删除")
.setMessage("确定要删除学生 ${student.name} 吗?")
.setPositiveButton("删除") { _, _ ->
viewModel.deleteStudent(student)
}
.setNegativeButton("取消", null)
.show()
}
}
6. RecyclerView适配器
// StudentAdapter.kt
class StudentAdapter(
private val onItemClick: (Student) -> Unit
) : ListAdapter<Student, StudentAdapter.StudentViewHolder>(StudentDiffCallback()) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): StudentViewHolder {
val binding = ItemStudentBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
return StudentViewHolder(binding)
}
override fun onBindViewHolder(holder: StudentViewHolder, position: Int) {
holder.bind(getItem(position))
}
inner class StudentViewHolder(
private val binding: ItemStudentBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind(student: Student) {
binding.apply {
textViewName.text = student.name
textViewAge.text = "年龄: ${student.age}"
textViewMajor.text = "专业: ${student.major}"
textViewGpa.text = "GPA: ${String.format("%.2f", student.gpa)}"
textViewGrade.text = student.getGradeLevel()
// 根据成绩等级设置颜色
val gradeColor = when (student.getGradeLevel()) {
"优秀" -> ContextCompat.getColor(root.context, R.color.grade_excellent)
"良好" -> ContextCompat.getColor(root.context, R.color.grade_good)
"中等" -> ContextCompat.getColor(root.context, R.color.grade_average)
"及格" -> ContextCompat.getColor(root.context, R.color.grade_pass)
else -> ContextCompat.getColor(root.context, R.color.grade_fail)
}
textViewGrade.setTextColor(gradeColor)
root.setOnClickListener {
onItemClick(student)
}
}
}
}
}
class StudentDiffCallback : DiffUtil.ItemCallback<Student>() {
override fun areItemsTheSame(oldItem: Student, newItem: Student): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: Student, newItem: Student): Boolean {
return oldItem == newItem
}
}
2.6.3 测试实现
// StudentViewModelTest.kt
@RunWith(MockitoJUnitRunner::class)
class StudentViewModelTest {
@Mock
private lateinit var repository: StudentRepository
private lateinit var viewModel: StudentViewModel
@Before
fun setup() {
viewModel = StudentViewModel(repository)
}
@Test
fun `loadStudents should update students LiveData`() = runTest {
// Given
val expectedStudents = listOf(
Student(1, "Alice", 20, "Computer Science", 3.8),
Student(2, "Bob", 21, "Mathematics", 3.5)
)
`when`(repository.getAllStudents()).thenReturn(expectedStudents)
// When
viewModel.loadStudents()
// Then
verify(repository).getAllStudents()
assertEquals(expectedStudents, viewModel.students.value)
}
@Test
fun `addStudent should call repository and reload students`() = runTest {
// Given
val newStudent = Student(0, "Charlie", 22, "Physics", 3.2)
`when`(repository.insertStudent(newStudent)).thenReturn(3L)
`when`(repository.getAllStudents()).thenReturn(emptyList())
// When
viewModel.addStudent(newStudent)
// Then
verify(repository).insertStudent(newStudent)
verify(repository, times(2)).getAllStudents() // 初始化时一次,添加后一次
}
}
2.7 常见问题与解答
Q1:Java和Kotlin在安卓开发中各有什么优势?
A1:
Java优势:
- 成熟稳定,生态系统完善
- 学习资源丰富,社区支持强大
- 与现有Java代码库兼容性好
- 企业级应用经验丰富
Kotlin优势:
- 语法简洁,减少样板代码
- 空安全,减少NullPointerException
- 协程支持,简化异步编程
- 与Java 100%互操作
- Google官方推荐
**建议:**新项目优先选择Kotlin,现有Java项目可以逐步迁移。
Q2:如何选择合适的架构模式?
A2:常见架构模式对比:
| 架构模式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| MVC | 简单应用 | 简单易懂 | 耦合度高 |
| MVP | 中等复杂度 | 解耦View和Model | Presenter容易臃肿 |
| MVVM | 复杂应用 | 数据绑定,测试友好 | 学习成本高 |
| Clean Architecture | 大型项目 | 高度解耦,可测试 | 复杂度高 |
选择建议:
- 小型项目:MVVM + Repository
- 中型项目:MVVM + Repository + UseCase
- 大型项目:Clean Architecture
Q3:如何优化应用性能?
A3:性能优化策略:
内存优化:
// 使用对象池避免频繁创建对象
class ObjectPool<T>(private val factory: () -> T) {
private val pool = mutableListOf<T>()
fun acquire(): T {
return if (pool.isNotEmpty()) {
pool.removeAt(pool.size - 1)
} else {
factory()
}
}
fun release(obj: T) {
pool.add(obj)
}
}
// 使用WeakReference避免内存泄漏
class ImageCache {
private val cache = mutableMapOf<String, WeakReference<Bitmap>>()
fun get(key: String): Bitmap? {
return cache[key]?.get()
}
fun put(key: String, bitmap: Bitmap) {
cache[key] = WeakReference(bitmap)
}
}
UI优化:
// 使用ViewBinding减少findViewById调用
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
}
// RecyclerView优化
class OptimizedAdapter : RecyclerView.Adapter<OptimizedAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
// 复用ViewHolder
return ViewHolder(ItemBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// 避免在bind中进行复杂计算
holder.bind(getItem(position))
}
// 实现getItemViewType支持多种布局
override fun getItemViewType(position: Int): Int {
return when (getItem(position).type) {
ItemType.HEADER -> VIEW_TYPE_HEADER
ItemType.CONTENT -> VIEW_TYPE_CONTENT
else -> VIEW_TYPE_FOOTER
}
}
}
2.8 本章小结
本章详细介绍了安卓逆向工程所需的编程基础和工具链知识:
- Java编程基础:面向对象特性、内存模型、反射机制
- Kotlin编程:现代化语言特性、与Java互操作
- 安卓开发环境:Android Studio、Gradle构建系统、ADB工具
- 开发工具链:SDK工具集、构建工具、调试工具
- 项目管理:版本控制、持续集成
- 实践项目:完整的学生管理应用实现
这些知识为后续的逆向分析工作提供了必要的技术基础。掌握了开发技能,才能更好地理解应用的内部结构和运行机制。
学习检查清单:
- 掌握Java面向对象编程概念
- 理解Java内存模型和垃圾回收
- 熟悉Java反射机制的使用
- 了解Kotlin语言特性和优势
- 能够配置Android Studio开发环境
- 熟练使用ADB进行设备调试
- 理解Gradle构建系统
- 掌握Git版本控制基础
- 能够独立完成简单的安卓应用开发
下一章预告:
在下一章中,我们将学习逆向工程的理论基础,包括逆向工程方法论、汇编语言基础、程序分析理论等核心概念,为实际的逆向分析工作做好理论准备。
2806

被折叠的 条评论
为什么被折叠?



