[安卓逆向]编写第一个安卓项目(一)

验证图:

一.下载安装开发工具

shell 复制代码
#Android Studio 下载地址
https://developer.android.google.cn/studio?hl=zh-cn
#自行安装该工具

二.编写项目

2.1 创建项目架构

此次开发工具为Android Studio 为2024.3.1版本

创建项目,选择 Empty Views Activity 模板 ,

谷歌已经将Kotlin视为Android开发的首选语言 ,此次演示选择Java 语言

2.2 编写登录界面

打开activity_main.xml

设置登录界面 拖拉了两个Textview,两个Plain Test和一个Button控件

美化后activity_main.xml登录界面(可以不使用):

xml 复制代码
<?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:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F5F7FA"
    tools:context=".MainActivity">

    <!-- 顶部装饰条 -->
    <View
        android:id="@+id/topBar"
        android:layout_width="0dp"
        android:layout_height="120dp"
        android:background="@color/colorPrimary"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="欢迎登录"
        android:textColor="#FFFFFF"
        android:textSize="28sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="@+id/topBar"
        app:layout_constraintEnd_toEndOf="@+id/topBar"
        app:layout_constraintStart_toStartOf="@+id/topBar"
        app:layout_constraintTop_toTopOf="@+id/topBar" />

    <!-- 卡片容器 -->
    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="32dp"
        app:cardCornerRadius="16dp"
        app:cardElevation="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="24dp">

            <!-- 用户名行:固定标签宽度,输入框自适应 -->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:gravity="center_vertical">

                <TextView
                    android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:text="用户名"
                android:textColor="#333333"
                android:textSize="16sp"
                android:textStyle="bold" />

                <EditText
                    android:id="@+id/etUsername"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="@drawable/edittext_bg"
                    android:hint="请输入用户名"
                    android:padding="12dp"
                    android:inputType="text"
                    android:textSize="15sp"
                    android:layout_marginStart="12dp" />
            </LinearLayout>

            <!-- 密码行:同样固定标签宽度,输入框宽度一致 -->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:gravity="center_vertical"
                android:layout_marginTop="20dp">

                <TextView
                    android:layout_width="60dp"
                android:layout_height="wrap_content"
                android:text="密码"
                android:textColor="#333333"
                android:textSize="16sp"
                android:textStyle="bold" />

                <EditText
                    android:id="@+id/etPassword"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:background="@drawable/edittext_bg"
                    android:hint="请输入密码"
                    android:padding="12dp"
                    android:inputType="textPassword"
                    android:textSize="15sp"
                    android:layout_marginStart="12dp" />
            </LinearLayout>

            <!-- 登录按钮 -->
            <Button
                android:id="@+id/btnLogin"
                android:layout_width="match_parent"
                android:layout_height="54dp"
                android:layout_marginTop="32dp"
                android:background="@drawable/button_bg"
                android:text="登 录"
                android:textColor="#FFFFFF"
                android:textSize="18sp"
                android:textStyle="bold" />

        </LinearLayout>

    </androidx.cardview.widget.CardView>

</androidx.constraintlayout.widget.ConstraintLayout>

同时在res/drawable下增加button_bg.xml和edittext_bg.xml ,res/values下修改colors.xml

button_bg.xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#FFFFFF" />
    <corners android:radius="12dp" />
    <stroke android:width="1dp" android:color="#DDDDDD" />
</shape>

edittext_bg.xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape>
            <solid android:color="#0066CC" />
            <corners android:radius="27dp" />
        </shape>
    </item>
    <item>
        <shape>
            <solid android:color="#2196F3" />
            <corners android:radius="27dp" />
        </shape>
    </item>
</selector>

colors.xml

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
    <color name="teal_200">#FF03DAC5</color>
    <color name="teal_700">#FF018786</color>
    <color name="black">#FF000000</color>
    <color name="white">#FFFFFFFF</color>
    <color name="colorPrimary">#2196F3</color>
</resources>

2.3 编写java代码

打开MainActivity.java

编写MainActivity.java代码

java 复制代码
package com.example.myapplication;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
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 {

    private EditText etUsername;
    private EditText etPassword;
    private Button btnLogin;

    @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;
        });

        // 1. 初始化控件(确保 id 与 XML 完全一致)
        try {
            etUsername = findViewById(R.id.etUsername);
            etPassword = findViewById(R.id.etPassword);
            btnLogin = findViewById(R.id.btnLogin);

            // 调试:如果控件为空,会在 Logcat 中打印错误
            if (etUsername == null || etPassword == null || btnLogin == null) {
                Toast.makeText(this, "控件初始化失败,请检查 XML 中的 id", Toast.LENGTH_LONG).show();
                return;
            }
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(this, "初始化出错:" + e.getMessage(), Toast.LENGTH_LONG).show();
            return;
        }

        // 2. 设置登录按钮点击事件
        btnLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 获取输入内容
                String username = etUsername.getText().toString().trim();
                String password = etPassword.getText().toString().trim();

                // 简单的验证逻辑
                if (username.isEmpty()) {
                    Toast.makeText(MainActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show();
                } else if (password.isEmpty()) {
                    Toast.makeText(MainActivity.this, "请输入密码", Toast.LENGTH_SHORT).show();
                } else if (username.equals("admin") && password.equals("123456")) {
                    Toast.makeText(MainActivity.this, "登录成功!", Toast.LENGTH_SHORT).show();
                    // 可以在这里添加跳转逻辑
                } else {
                    // 这里就是你说的"用户名或密码错误"
                    Toast.makeText(MainActivity.this, "用户名或密码错误", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}

三.打包

3.1 调试版APK打包

  1. 点击菜单栏 BuildGenerate App Bundles or APKsGenerate APKs

  2. 等待底部状态栏出现成功提示,并显示 APK 文件路径

    3.点击 locate 直接打开文件夹

3.1 正式签名版APK

如果需要发给别人用,或者要上架应用商店,必须签名。

  1. 点击菜单栏 BuildGenerate Signed App Bundle or APK选择 APK
  2. 点击 Create new 创建签名密钥(只需创建一次)
    • Key store path:点击文件夹图标,选择保存位置(如 D:/mykey.jks
    • Password:输入密码(记住它)
    • Alias:别名(如 mykey
    • 其他随便填,至少填一个 Name
  3. 等待构建完成,点击 locate 打开文件夹

APK 位置
项目根目录/app/release/app-release.apk

3.2 正式版安装

模拟器中安装打包好的签名版APK

总结

此次演示从项目创建到打包以及安装都做了简单描述,有了这些基础逆向时才会如鱼得水。

相关推荐
启雀AI12 小时前
培训平台移动端离线学习方案设计与实现:视频缓存、断点续传与进度同步的工程实践
android·学习·缓存·音视频·企业lms
我命由我1234513 小时前
RxJava - 冷数据流与热数据流
android·java·java-ee·android studio·rxjava·android-studio·android runtime
2601_9665635215 小时前
愤怒的小鸟单机版 去广告 安卓+PC端离线纯净版 益智耐玩小游戏 不需联网 老旧手机都可以玩 怀旧手机小游戏
android·智能手机
hunterandroid15 小时前
[Android 从零到一] Retrofit 请求取消与生命周期绑定:从 Call.cancel 到协程可取消设计
android
爱跑马的程序员16 小时前
安卓专有的通信子系统-Binder IPC
android·binder·ipc·安卓间通信机制
ue星空16 小时前
【安卓逆向】为什么用Frida?
android
小驰行动派17 小时前
Camx架构全景图:从V4L2到Pipeline的完整拆解
android·camera·android camera
hunterandroid17 小时前
[Android 从零到一] Custom View 触摸反馈与手势冲突解决
android
coderSong256818 小时前
Android | 四大组件之 BroadcastReceiver(广播接收器)
android
爱笑鱼21 小时前
Android 系统启动机制(二):init.rc 不是普通脚本,service、action 和 property 怎样驱动启动?
android