前两天一个朋友问我:我完全没写过代码,能直接做手机App吗?我反问他:你是想先搞清楚那些抽象术语,还是想亲手做一个能装进手机里跑起来的东西?他说想要后者。那答案就很直接了——打开 Android Studio,跟着下面的步骤走一遍,你就能得到第一个真正属于你的手机端 App。这篇文章不会跟你讲编译原理,也不会逼你背两个月的 Java 教材,而是从零开始,带你装好工具、创建工程、写一个能点击计数的界面,跑上模拟器,最后打包成 APK 塞进手机。全程用零基础视角来,每个操作我都会解释“为什么这么做”,你只要照着做就能跟上。
1. 动手前,先把这三件事想明白,后面能省一半时间
1.1 选 Kotlin 还是 Java,别再纠结了
很多零基础同学第一关就卡在语言选择上,因为网上说法太多:有人说 Java 稳,有人说 Kotlin 是未来。我的建议非常直接:新项目用 Kotlin,不要犹豫。
理由很简单,现在的 Android Studio 默认新建项目就是 Kotlin,官方模板、官方文档、社区新教程,几乎全部默认 Kotlin。你跟着官方生态走,遇到报错时搜到的答案是绝大多数匹配的,学习阻力最小。这就好比你去一个新城市,先学大家日常都说普通话,而不是先研究冷门方言,等方言学会了地方可能已经混熟了。
Kotlin 还有个好处是它能直接调用所有 Java 库,所以不用担心以后接触老项目或者别人写的 Java 代码看不懂。入门阶段,选跟工具走得最近的那条路,永远是最优策略。
1.2 Android Studio 到底是什么,为什么非它不可
你可以把 Android Studio 理解成 Android 官方提供的一台“造车车间”。它不是一个单纯的文本编辑器,而是一个把画界面、写代码、预览效果、连接手机、打包安装全都整合在一起的开发工具,也就是所谓的 IDE。
有些人会说:我不装 Android Studio,用命令行加 Gradle 也能写 App,何必多装一个占内存的软件?这话理论上没错,但对新手来说,官方工具已经把所有复杂流程都拧成了“点按钮操作”。你点一下运行,它帮你构建、安装、启动;你拖一个按钮,它自动同步 XML。省下来的时间不是一点点。
更重要的是,大量新手报错其实是环境不一致造成的,Android Studio 帮你把常用的构建环境统一了,至少能挡掉一半“为什么我这里运行不了”的奇怪问题。
1.3 电脑配置要什么级别,才不会被劝退
先给结论:内存 8GB 能跑,16GB 更稳,固态硬盘必须有。
Android Studio 本身加上 Gradle 构建、模拟器运行,都属于吃内存大户。我以前用一台 4GB 内存的老笔记本,第一次构建等了二十分钟,屏幕一直转圈,差点就卸载了。后来换了 16GB 内存的机器,同一个工程一分钟内完成构建,体验完全两回事。
CPU 方面,主流的 i5/R5 以上都够用,CPU 只决定你等待时间长短,不决定你能不能学。硬盘一定要用 SSD,机械硬盘在构建时会有大量小文件读写,速度差距非常明显。如果你电脑里之前装过别的 Java 环境,安装 Android Studio 的时候也要注意版本冲突的问题,这一点马上就会讲到。
2. 环境搭建:装好 Android Studio,先别急着写代码,卡住 90% 新手的是这一步
2.1 别再手动装 JDK 了
以前学 Android 需要先去官网下载 JDK,再配置 JAVA_HOME 环境变量,这套步骤在现在的新版本里已经过时了。
现在 Android Studio 自身内置了 JBR(JetBrains Runtime,本质上是完整 JDK),你直接安装 Android Studio,它就会用内置版本完成编译,不需要额外配置任何环境变量。
不过有一种特殊情况要提醒你:你自己以前装过 JDK,而且设置过 JAVA_HOME,Android Studio 可能会检测到系统环境变量,导致启动或者构建时版本对不上。我的建议是保持 Android Studio 默认,不要自己去动环境变量;如果确实发现构建报 JVM 相关的错,再回头检查你系统里是不是装了版本冲突的 JDK,而不是一上来就去折腾配置。
2.2 安装的两大细节:路径和组件
下载安装包时根据你的操作系统选,Windows 就下载 exe,macOS 就下载 dmg。安装过程中大部分步骤一路 Next 就行,但有两个细节我每次都要强调。
第一,安装路径要放到纯英文目录下,比如D:\AndroidStudio。不要放在用户目录里面带着中文的名字里。你可能觉得中文路径无所谓的,但 Gradle 脚本和 SDK 组件对路径非常敏感,各种找不到目录、路径解析失败都会随之而来,我见得太多了。
第二,安装过程中会有勾选项,Android SDK、Android Virtual Device 这些组件一定要保持选中,它们是后面跑模拟器和编译 App 的必需品。第一次安装完成后,Android Studio 会自动下载 SDK 组件,这个过程的耗时取决于网络环境,耐心等待即可;如果中间下载失败,重启 Studio 再试一次通常能续上。
2.3 创建模拟器:给自己配一台“手机”
打开 Android Studio 后,先去 Device Manager(设备管理器),点加号创建虚拟设备。机型随便选一台 Pixel 系列就行,重点在 System Image 这一步。
新手很容易在这里犯迷糊,看到一堆 API 版本不知道选什么。直接选稳定版本就好,比如 API 34,对应 Android 14。镜像架构一定要选 x86_64 的,在 Windows 上速度和兼容性都远好于 ARM 镜像。如果你选错了架构,模拟器启动会特别慢,甚至直接黑屏。
创建时给模拟器分配的内存不要低于 2GB,我一般会调到 3GB。内存太低的模拟器虽然也能启动,但运行起来卡到怀疑人生,体验很差。模拟器启动后就像一台缩小版手机,你可以用鼠标点击、滚动,虽然手感比真机差一点,但日常调试界面和交互完全够用。
2.4 第一次构建前,先给 Gradle 换个“源”
这是新手最容易长时间卡住的环节,我当年在这里干等过一个下午。
Android 构建时依赖包默认从google()和mavenCentral()仓库下载,当网络到这个仓库不够通畅时,Gradle 就会一直转圈,甚至报Could not resolve。与其干等,不如在项目创建后直接把国内镜像仓库加到settings.gradle.kts里。
pluginManagement { repositories { maven("https://maven.aliyun.com/repository/google") maven("https://maven.aliyun.com/repository/public") maven("https://maven.aliyun.com/repository/gradle-plugin") google() mavenCentral() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven("https://maven.aliyun.com/repository/google") maven("https://maven.aliyun.com/repository/public") google() mavenCentral() } }如果你项目里生成的脚本还是build.gradle(Groovy 写法),那只需要把maven("...")换成maven { url = uri("...") }这种格式就行。改完点右上角的 Sync Now,正常情况依赖会很快下载完成。我建议每一个新项目都先做这一步,别等卡半天才想起来。镜像地址以实际可用为准,如果某个地址失效,换成其他公开镜像即可。
注意:不要擅自把镜像仓库插在原来仓库列表的中间,然后又把括号改乱了。保持结构顺序,只加仓库地址,不要动其他配置。
3. 创建项目之后先别急着写,认路的功夫能让你后面三天不晕
3.1 新建项目的模板到底选哪个
打开 Android Studio 的欢迎界面,点 New Project,会看到一排模板。新手最容易看到什么选什么,但第一次学的话,我强烈建议选 Empty Views Activity,而不是最新的 Empty Compose Activity。
区别在于:Empty Views Activity 用的是传统 XML 加 Activity 的方式,界面写在一个 XML 文件里,逻辑写在 Kotlin 类里,概念非常直观。而 Compose 是声明式 UI,所有界面都写在 Kotlin 代码里,表面上看起来很简洁,但对初学者来说,少了一层“界面文件”和“逻辑文件”的对应关系,反而容易糊涂。
我的看法是,第一次接触 Android,先看明白 XML 布局和 Activity 之间的关系,之后再学 Compose 会容易得多。否则你一上来直接看到一堆Modifier、setContent,很容易觉得“这都啥跟啥”,然后放弃。
3.2 目录结构:官方到底帮你生成了什么
项目创建后,左上角是 Project 视图。你主要关心四块内容:
manifests:存放全局配置文件,核心是 AndroidManifest.xml。java(或kotlin):存放所有 Kotlin/Java 源码。res:存放界面布局、图片、字符串等资源。Gradle Scripts:存放构建脚本和 Gradle 配置。
我用一个生活化的比方来帮你记:AndroidManifest.xml是 App 的户口本,系统安装 App 时首先看它,你的应用叫什么、有哪几个页面、需要哪些权限,它都要交代清楚;res是素材库,所有图标、布局、文字、颜色都分门别类放好;Gradle Scripts是后厨的菜谱,告诉系统怎么把一堆代码和资源做成一个 APK。
如果你想改某个页面的界面排版,去res/layout找 XML;想找某个页面的逻辑,去java目录找对应的类;工程跑不起来,先看 Gradle 控制台输出。
3.3 核心三件套:AndroidManifest、MainActivity、activity_main
有三个文件是你会频繁打交道的,必须认识。
第一个是AndroidManifest.xml。你每创建一个 Activity,通常需要在<application>标签里用<activity>登记,否则运行时一打开那个页面就崩,并提示ActivityNotFoundException。后面讲页面跳转时会细说。
第二个是MainActivity.kt,这是 App 的入口页面。系统启动应用时会调用它的onCreate方法,你所有的启动逻辑基本都在那里写。比如设置要显示哪个界面,绑定哪些按钮事件。
第三个是activity_main.xml,它负责管理页面上的文字、按钮、输入框的位置。MainActivity会通过setContentView(R.layout.activity_main)把布局文件“贴”到这个页面。
这三者的关系,我一般给学员说:manifest 是门牌号,MainActivity 是客厅,XML 是沙盘。沙盘上的家具要拿到代码里操作,就必须给它们起 ID,然后用findViewById找到。
3.4 build.gradle 里的版本号,看到别慌
工程里通常有两个 build.gradle 文件,一个是项目级,一个是app模块级。项目级文件里主要是一些公共仓库和插件配置,大多数情况下你不需要改它;而app模块级里会看到compileSdk、minSdk、targetSdk这些概念。
compileSdk表示编译时用的 API 等级,翻译成大白话就是“我告诉编译器,最新代码里用到的这些新接口,它得能识别”;minSdk则是你允许运行这个 App 的最低 Android 版本,如果调太高,老手机就装不上。
新项目默认一般会给你一个比较合理的组合,比如 compileSdk 35、minSdk 24,这个阶段你不用去动它。版本最忌讳自己乱升级,因为 AGP 版本要和 Gradle 版本匹配,入门阶段跟着模板走,稳是第一位。看到版本号不用慌,它们不是让你背的。
4. 写第一个能交互的“计数器”:布局、控件和 Kotlin 逻辑
4.1 先把界面折腾出来:XML 里放一个 TextView 和一个 Button
我们现在做一个最简单的功能:屏幕中间一个数字,下方一个按钮,每点一次按钮数字加一。
打开activity_main.xml,默认的根布局可能是 ConstraintLayout,但新手建议先换成 LinearLayout。原因是 LinearLayout 的方向、排列规则特别好猜,页面从上到下依次排下去;而 ConstraintLayout 的拖拽约束虽然强大,但新手很容易被“为什么我拖过去的控件一运行就跑了”给搞蒙。
把布局文件改成下面这样:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <TextView android:id="@+id/tvCount" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0" android:textSize="42sp" /> <Button android:id="@+id/btnAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="加一" /> </LinearLayout>这里你只需要记住三组概念:wrap_content表示“包住内容多大就多大”;match_parent表示“填满父容器”;@+id/tvCount是给控件起一个 ID,之后在代码里可以用R.id.tvCount找到它。
TextView是显示文字的控件,Button是按钮。sp和dp都是尺寸单位,文字大小用sp,控件大小和间距用dp。你不用刻意背,用几次自然就分清了。
4.2 让按钮有反应:MainActivity 里的 Kotlin 代码
打开MainActivity.kt,把模板里的内容替换成下面这段。我会逐行解释。
package com.example.myfirstapp import android.os.Bundle import android.widget.Button import android.widget.TextView import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { private var count = 0 private lateinit var tvCount: TextView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) tvCount = findViewById(R.id.tvCount) val btnAdd = findViewById<Button>(R.id.btnAdd) btnAdd.setOnClickListener { count++ tvCount.text = count.toString() } } }onCreate是这个页面被创建时第一个执行的方法,你可以理解为 App 打开页面后的“起跑线”。setContentView把之前写的 XML 布局挂上来,这样屏幕上才会出现你画好的按钮和数字。
findViewById的作用是从布局里找到那个控件。注意R.id.tvCount必须和 XML 里的@+id/tvCount完全一致,多一个字母或者改大小写都会编译失败。这是新手最容易犯的笔误。
lateinit var tvCount表示这个变量先声明再赋值,这是 Kotlin 为了避免空指针问题,在一些“声明和初始化分离”的场景下的写法。按钮的点击事件通过setOnClickListener设置,花括号里面的代码就是每次点击时要做的事。count++让数字加一,再通过tvCount.text把新数字写回到界面上。
如果你以前接触过 Java,不必担心,这里的思路完全一样,只是 Kotlin 的写法更简洁。
4.3 第一次点击运行:等待 Gradle 构建也是学习的一部分
点击左上角的绿色三角形按钮,Android Studio 会先弹出设备选择窗口,选中你刚创建的模拟器,然后开始 Gradle 构建。
第一次构建通常最慢,因为它要下载依赖、建立索引,三到五分钟都是正常情况。我第一次在咖啡厅等首次构建,咖啡凉了模拟器才亮起来。所谓“卡住了”,其实很多时候不是死循环,而是构建确实在进行。
你仔细观察底部 Gradle 窗口,如果任务一直在推进,就说明它在干活;等构建完成,模拟器里会弹出你的 App。用鼠标点几下“加一”,数字开始变化,恭喜,你的第一个 Android App 已经能跑了。
5. 页面跳转与数据传递:Intent 是基础中的基础
5.1 为什么每个页面都要在 Manifest 里“报到”
一个 App 很少只有一个页面,页面之间的跳转是你写任何实际项目都要用到的高频操作。
Android 里的页面通常对应一个Activity。从当前页面跳到另一个页面,标准工具是Intent,但在跳转之前,必须先把目标页面登记到AndroidManifest.xml。
你先创建一个新的 Kotlin 类,名字叫SecondActivity,继承AppCompatActivity。然后打开 manifest,在<application>标签内部新增一行:
<activity android:name=".SecondActivity" />这里的.SecondActivity是相对于包名的路径,等价于com.example.myfirstapp.SecondActivity。如果你不写这一行,运行点击跳转时一定会崩溃,提示ActivityNotFoundException。很多新手第一次遇到闪退都不知道去哪查,其实就是漏了登记。
5.2 Intent 的定位作用:把“地址”和“包裹”一起交给系统
跳转的代码非常简单。比如我们想在计数器页面放一个按钮,点击后跳到SecondActivity,同时把当前的count数字带过去:
val intent = Intent(this, SecondActivity::class.java) intent.putExtra("count", count) startActivity(intent)Intent这个词可以理解成“意图”,它描述了你想要启动哪个页面,以及要带过去的包裹数据。putExtra("count", count)是把count的值放入包裹,Key 是"count"。
在SecondActivity的onCreate里接收数据,写法是:
val receivedCount = intent.getIntExtra("count", 0)这里的0是默认值,意思是如果"count"这个 Key 不存在,至少返回 0,不会让程序崩溃。putExtra和getIntExtra使用的 Key 必须完全一致,哪怕大小写不同都会取不到值。我见过有人左边写"count",右边写"Count",排查了一下午。
5.3 从新页面返回和回传数据,现在都推荐 Activity Result API
系统返回键可以直接把当前页面结束掉并回到上一页,这个不用写逻辑。
但如果你需要第二页填一个结果,点按钮返回并把结果带回第一页,那就要用setResult加上启动方注册回调。旧教程里会教你用startActivityForResult,但这个方法已经被标记为废弃,新项目不要学。
现在更通用的做法是 Activity Result API,大概流程是在接收方先声明一个 launcher,再通过 Intent 跳转,第二页返回时设置结果。初学阶段你不需要把整个 API 背下来,但要养成一个习惯:看到“已废弃”的 API,别照抄老教程,去搜最新写法。这个习惯能让你少踩很多老坑。
6. 换成真机调试:USB 调试、驱动和 Logcat 日志
6.1 为什么我建议你的第二个 App 就开始用真机
模拟器跑 UI 很方便,但它替代不了真机。
相机、震动、蓝牙、传感器、定位、不同屏幕尺寸,以及一些第三方的登录支付 SDK,都需要在真机上验证。更重要的是,不少国产手机系统在后台管理、权限弹窗上有自己的逻辑,很多你觉得没问题的功能,装到真机上就是莫名其妙闪退。所以学会真机调试,是从“能写”到“能调”的关键一步。
6.2 一步步打开开发者选项和 USB 调试
手机的第一步:打开“设置”,找到“关于手机”,找到“版本号”,连续点击七次,系统会提示“你已进入开发者模式”。不同品牌的入口略有差异,有的在“我的设备”里,有的需要先点“全部参数”,但核心都是找到版本号之后狂点。
第二步:进入“开发者选项”,打开“USB 调试”。戴着壳或者用扩展坞的同学注意,最好也把“仅充电模式下允许 ADB 调试”打开,否则手机连接电脑后系统可能忽略调试指令。
第三步:用数据线连接电脑,手机屏幕会弹出是否允许调试的窗口,勾选“始终允许”,点允许。
这里有一个特别容易踩的坑:数据线要能传数据,而不能是只能充电的线。很多“只能充电”的数据线会让电脑一直无法识别设备,我遇到不下三次。
6.3 连接不上,从这几个方向排查
设备列表里一直看不到手机,先别急着怀疑电脑,按顺序排查:
- 在 Windows 的设备管理器里看有没有带黄色感叹号的 Android 设备,有的话去手机厂商官网下载对应 USB 驱动安装,装完重启。
- 下拉手机状态栏,把 USB 模式从“仅充电”切换到“文件传输”。
- 在 Android Studio 里拔插一次数据线,手机上重新点一次允许调试授权。
这三步能解决绝大部分连接问题。真机比模拟器更贴近真实用户,值得你花二十分钟把它调通。
6.4 Logcat 崩溃日志:红色的字不是吓唬人
Android Studio 底部有一个 Logcat 窗口,App 运行时打印的日志都会出现在这里。
调试时最实用的动作,是在关键代码处加一行日志:
Log.d("MainActivity", "按钮被点击了")然后你就可以在 Logcat 里过滤MainActivity这个 Tag,看到日志有没有执行到那一行。
如果 App 崩溃,Logcat 里会刷出一堆红色栈信息。里面最经典的一行是Caused by:,它通常是崩溃根源。比如你调用了没有在 manifest 注册的 Activity,堆栈里会出现ActivityNotFoundException,定位到具体类名后,你就能回头检查注册。学会看这一行,能省掉你 90% 的崩溃排查时间。
7. 制作可安装的 APK:签名、打包和安装的坑
7.1 调试 APK 和正式 APK 的差别
直接点运行安装到手机上的是 debug 包,它默认用的是调试签名,只能用来自己测试。
如果你要把 App 发给朋友安装,或者要上架应用商店,必须生成 release 正式包。这里的“签名”指的是数字签名,相当于 App 的防伪标记,系统靠它判断这个安装包的来源和身份。
旧项目更新升级时必须使用同一个签名的证书,否则系统会拒绝覆盖安装,提示“原签名不一致”。这就是为什么密钥库文件一定要当宝贝一样保存好。
7.2 一步步创建密钥并生成签名 APK
菜单栏选 Build —— Generate Signed Bundle / APK。
这个弹窗会问你是输出 AAB 还是 APK:如果只是想拿到一个 apk 文件直接发给别人安装,选 APK。点 Next 之后选择 Create new keystore,接着填一堆密码、别名和个人信息。
这一步的关键是:密钥库文件保存好,密码和别名也一定要记录。我之前遇到过客户自己忘了密钥库密码,结果应用只能用新签名重新上架,老用户全部无法覆盖安装,非常狼狈。证书就是 App 身份证,丢了就得“重新做人”。
创建完成后,勾选 release,点击 Finish。几分钟后,工程目录下的app/release里会出现app-release.apk,这就是可以传播安装的正式包。
7.3 把 APK 装到手机上,常见的三种问题
拿着 APK 传到手机后用文件管理器安装,容易遇到下面这些情况:
| 现象 | 常见原因 | 处理办法 |
|---|---|---|
| 显示“解析包错误” | 文件下载不完整,或手机系统版本低于 minSdk | 重新下载完整 APK,检查系统版本 |
| 显示“应用未安装” | 手机已有同应用但签名不同 | 先卸载旧版本再安装,或统一签名 |
| 文件打不开 | 聊天工具传输时把 APK 后缀改了 | 重命名回 .apk,或换安装包链接 |
另外提醒一下,应用市场的目标版本要求会随行业规范调整,新上架应用尽量按官方最新要求设置targetSdk,不是越高就越好,也不是低了就可以永久不用改。这一块以当前官方和市场的实际要求为准。
最后说一句我自己的体会:第一次跑通 App 时,很多人都会觉得神奇,然后马上想加各种炫酷功能,结果越改越乱。我建议你把教程里的例子亲手重做一遍,比如给计数器再加一个清零按钮,不要只靠重启来归零。这个过程只要自己完整走一遍,那些知识点就会从“看过”变成“会写”。之后再去碰列表、网络请求、数据库,会顺很多。先祝你的第一个 App 跑起来顺利。