[编译] 5、在Linux下搭建安卓APP的开发烧写环境(makefile版)—— 在Linux上用命令行+VIM开发安卓APP
星期三, 19. 九月 2018 02:19上午 - BEAUTIFULZZZZ

0)前言
本文不讨论用IDE和文本编辑器开发的优劣,是基于以下两点考虑去尝试用命令行编译安卓APP的:
- 了解安卓APP的编译过程,了解IDE干了什么事;
- 放在打包服务器上需要自动化生成APP的脚本;
1)安装配置环境
安装java
sudo apt-get install openjdk-8-jdk-headless
**note: **安装之前先要卸载之前版本的java,否则会报错!!! [error-1].
安装SDK tools
wget https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
建议将其解压到
/opt目录下:mkdir -p /opt/android-sdk
unzip sdk-tools-linux-3859397.zip -d /opt/android-sdk
用sdkmanager安装SDK(#1)
sdkmanager是用来查看、安装、更新、卸载Android SDK的命令行工具,官方说明如下:
The sdkmanager is a command line tool that allows you to view, install, update, and uninstall packages for the Android SDK.
The sdkmanager tool is provided in the Android SDK Tools package (25.2.3 and higher) and is located in android_sdk/tools/bin/.列出Installed packages和Available Packages,查看包安装情况:
cd /opt/android-sdk/tools/bin
./sdkmanager --list
安装platform tools 19(写文章时最新的是26),该工具包含adb和fastboot,该工具对应的API级别也是19:
./sdkmanager "platform-tools" "platforms;android-19"
安装build tools 26.0.1(最新的),该工具包含aapt、apksigner、zipalign等编译、认证、打包工具:
./sdkmanager "platform-tools" "build-tools;26.0.1"
最后你会在/opt/android-sdk/中看到build-tools、paltforms、tools三个文件夹~
2)编写简单Hello World程序
创建工程文件夹
cd ~/Downloads/
mkdir HelloAndroid
cd HelloAndroid
创建工程文件tree
mkdir -p src/com/example/helloandroid
mkdir obj
mkdir bin
mkdir -p res/layout
mkdir res/values
mkdir res/drawable
Make the file src/com/example/helloandroid/MainActivity.java and put that inside:
package com.example.helloandroid;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Make the strings.xml file in the res/values folder. It contains all the text that your application uses:
<resources>
<string name="app_name">A Hello Android</string>
<string name="hello_msg">Hello Android!</string>
<string name="menu_settings">Settings</string>
<string name="title_activity_main">MainActivity</string>
</resources>
The activity_main.xml is a layout file which have to be in res/layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/hello_msg"
tools:context=".MainActivity" />
</RelativeLayout>
You also have to add the file AndroidManifest.xml at the root:
<?xml version='1.0'?>
<manifest xmlns:a='http://schemas.android.com/apk/res/android' package='com.example.helloandroid' a:versionCode='0' a:versionName='0'>
<application a:label='A Hello Android'>
<activity a:name='com.example.helloandroid.MainActivity'>
<intent-filter>
<category a:name='android.intent.category.LAUNCHER'/>
<action a:name='android.intent.action.MAIN'/>
</intent-filter>
</activity>
</application>
</manifest>
最终文件构成为:
➜ HelloAndroid tree
.
├── AndroidManifest.xml
├── bin
├── libs
├── obj
├── res
│ ├── drawable
│ ├── layout
│ │ └── activity_main.xml
│ └── values
│ └── strings.xml
└── src
└── com
└── example
└── helloandroid
└── MainActivity.java
3)编译工程
将工程路径设置为变量(方便一会使用):
export PROJ=~/Downloads/HelloAndroid
First, we need generate the R.java file which is necessary for our code:
cd /opt/android-sdk/build-tools/26.0.1/
./aapt package -f -m -J $PROJ/src -M $PROJ/AndroidManifest.xml -S $PROJ/res -I /opt/android-sdk/platforms/android-19/android.jar
compile the .java files:
cd ~/Downloads/HelloAndroid
javac -d obj -classpath src -bootclasspath /opt/android-sdk/platforms/android-19/android.jar src/com/example/helloandroid/*.java
The compiled .class files are in obj folder, but Android can’t read them. We have to translate them in a file called “classes.dex” which will be read by the dalvik Android runtime:
cd /opt/android-sdk/build-tools/26.0.1/
./dx --dex --output=$PROJ/bin/classes.dex $PROJ/obj
We can now put everything in an APK:
./aapt package -f -m -F $PROJ/bin/hello.unaligned.apk -M $PROJ/AndroidManifest.xml -S $PROJ/res -I /opt/android-sdk/platforms/android-19/android.jar
cp $PROJ/bin/classes.dex .
./aapt add $PROJ/bin/hello.unaligned.apk classes.dex
If you want, you can check the content of the package like this:
./aapt list $PROJ/bin/hello.unaligned.apk
至此,我们生成了一个hello.unaligned.apk文件,但是,它是不能安装到安卓手机里面的!因为它unaligned && unsigned。
4)Align and Sign the package
keytool -genkeypair -validity 365 -keystore mykey.keystore -keyalg RSA -keysize 2048
cd /opt/android-sdk/build-tools/26.0.1/
./zipalign -f 4 $PROJ/bin/hello.unaligned.apk $PROJ/bin/hello.apk
./apksigner sign --ks mykey.keystore $PROJ/bin/hello.apk
使用keytool创建一个keystore,只要依次回答其问题即可,输入密码自己别忘了,今后会用到!运行成功之后会生成一个mykey.keystore文件,用于今后给apk签名。
note: 记住务必要先Align,然后再Sign,否则会出错 [error-2].
5)真机安装测试
安装并运行比较简单:
adb install $PROJ/bin/hello.apk
adb shell am start -n com.example.helloandroid/.MainActivity
note: 一般运行安装前,建议先运行adb logcat看看安卓有没有连接并开启开发者模式
6)自动化脚本
为了不用每次都要手输上面的每一步,我们将上面的操作整理成一个脚本run.sh:
➜ HelloAndroid cat run.sh
#!/bin/bash
set -e
AAPT="/opt/android-sdk/build-tools/26.0.1/aapt"
DX="/opt/android-sdk/build-tools/26.0.1/dx"
ZIPALIGN="/opt/android-sdk/build-tools/26.0.1/zipalign"
APKSIGNER="/opt/android-sdk/build-tools/26.0.1/apksigner" # /!\ version 26
PLATFORM="/opt/android-sdk/platforms/android-19/android.jar"
function build(){
echo "Generating R.java file..."
$AAPT package -f -m -J src -M AndroidManifest.xml -S res -I $PLATFORM
echo "Compiling..."
javac -d obj -classpath src -bootclasspath $PLATFORM src/com/example/helloandroid/*.java
echo "Translating in Dalvik bytecode..."
$DX --dex --output=classes.dex obj
echo "Making APK..."
$AAPT package -f -m -F bin/hello.unaligned.apk -M AndroidManifest.xml -S res -I $PLATFORM
$AAPT add bin/hello.unaligned.apk classes.dex
echo "Aligning and signing APK..."
$ZIPALIGN -f 4 bin/hello.unaligned.apk bin/hello.apk
$APKSIGNER sign --ks mykey.keystore bin/hello.apk
}
function clean(){
echo "Cleaning..."
rm -rf classes.dex
rm -rf bin/*
rm -rf obj/*
rm -rf src/com/example/helloandroid/R.java
}
function program(){
echo "Launching..."
adb install -r bin/hello.apk
adb shell am start -n com.example.helloandroid/.MainActivity
}
if [ "$1" == "all" ]; then
clean
build
program
elif [ "$1" == "clean" ]; then
clean
elif [ "$1" == "build" ]; then
build
elif [ "$1" == "program" ]; then
program
else
echo "error"
fi
并编写一个makefile脚本,通过调用run.sh实现编译、清除、安装各种操作:
➜ HelloAndroid cat makefile
clean:
./run.sh clean
build:
./run.sh build
program:
./run.sh program
all:
./run.sh all
至此,我们完成了一个简单的命令行版的Hello World工程!当然,大多数非常复杂的安卓工程需要用IDE去开发,或者开发用IDE打包用命令 ~ 下次我会把一个稍微复杂点的蓝牙安卓工程改造成命令行版。

常见错误
error-1:
➜ HelloAndroid javac -d obj -classpath src -bootclasspath /opt/android-sdk/platforms/android-19/android.jar src/com/example/helloandroid/*.java
javac: option --boot-class-path not allowed with target 1.10
error-2:
➜ HelloAndroid ./build.sh test
Cleaning...
Generating R.java file...
Compiling...
Translating in Dalvik bytecode...
Making APK...
'classes.dex'...
Aligning and signing APK...
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by com.android.apksigner.PasswordRetriever (file:/opt/android-sdk/build-tools/26.0.1/lib/apksigner.jar) to method java.io.Console.encoding()
WARNING: Please consider reporting this to the maintainers of com.android.apksigner.PasswordRetriever
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Keystore password for signer #1:
Launching...
Failed to install bin/hello.apk: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from /data/app/vmdl1775334521.tmp/base.apk: META-INF/MYKEY.SF indicates /data/app/vmdl1775334521.tmp/base.apk is signed using APK Signature Scheme v2, but no such signature was found. Signature stripped?]
需要If you need to run zipalign, do it before the APK is signed,因此将APKSIGNER放在ZIPALIG之后(#4)。
error-3:
$ avdmanager
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
at com.android.repository.api.SchemaModule$SchemaModuleVersion.<init>(SchemaModule.java:156)
at com.android.repository.api.SchemaModule.<init>(SchemaModule.java:75)
at com.android.sdklib.repository.AndroidSdkHandler.<clinit>(AndroidSdkHandler.java:81)
at com.android.sdklib.tool.AvdManagerCli.run(AvdManagerCli.java:213)
at com.android.sdklib.tool.AvdManagerCli.main(AvdManagerCli.java:200)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:496)
... 5 more
需要加:export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee'

LINKS
[1].sdkmanager 用法
[2].Build your app from the command line
[3].How to make Android apps without IDE from command line
[4].Android signing apk signature V2
[5].What are the Android SDK build-tools, platform-tools and tools? And which version should be used?
[6].Not able to build code after installing latest java version 1.9
[7].Android SDK is not installed or is not configured properly, environment looks ok
[8].Command line tools only Download
[9].GITHUB this project

@beautifulzzzz
智能硬件、物联网,热爱技术,关注产品
博客:http://blog.beautifulzzzz.com
园友交流群:414948975
[编译] 5、在Linux下搭建安卓APP的开发烧写环境(makefile版)—— 在Linux上用命令行+VIM开发安卓APP的更多相关文章
- [编译] 8、在Linux下搭建 stm8 单片机的开发烧写环境(makefile版)
目录 一.SDCC(Small Device C Compiler)编译环境搭建 1.1.下载 1.2.编译 1.3.测试 二.Hex2Bin+命令行烧写工具配置使用 2.1.下载工具安装配置 2.2 ...
- [编译] 3、在Linux下搭建51单片机的开发烧写环境(makefile版)
星期二, 10. 七月 2018 01:01上午 - beautifulzzzz 一.SDCC(Small Device C Compiler)编译环境搭建 SDCC是一个小型设备的C语言编译器,该编 ...
- 单片机成长之路(51基础篇) - 006 在Linux下搭建51单片机的开发烧写环境
在Linux下没有像keli那样好用的IDE来开发51单片机,开发环境只能自己搭建了. 第一步:安装交叉编译工具 a) 安装SDCC sudo apt-get install sdcc b)测试SDC ...
- [编译] 7、在Linux下搭建安卓APP的开发烧写环境(makefile版-gradle版)—— 在Linux上用命令行+VIM开发安卓APP
April 18, 2020 6:54 AM - BEAUTIFULZZZZ 目录 0 前言 1 gradle 安装配置 1.1 卸载系统默认装的gradle 1.2 下载对应版本的二进制文件 1.3 ...
- [编译] 9、在Linux下搭建 nordic 最新基于 zephyr 的开发烧写环境
目录 前言 1.概述 2.安装工具 3.获取 nRF Connect SDK 源码 4.安装 Python modules 5.安装 toolchain 6.下载 nRF Command Line T ...
- [编译] 4、在Linux下搭建nRF51822的开发烧写环境(makefile版)
星期日, 09. 九月 2018 07:51下午 - beautifulzzzz 1.安装步骤 1) 从GNU Arm Embedded Toolchain官网下载最新的gcc-arm工具链,写文章时 ...
- 在Linux下搭建nRF51822的开发烧写环境(makefile版)
http://www.qingpingshan.com/m/view.php?aid=394836
- Linux下搭建 Cocos2d-x-2.1.4 编译环境
[tonyfield 2013.09.04 ] 参考 Linux下搭建 Cocos2d-x-2.1.4 编译环境 导入 HelloCpp 例程 1. Java 入口 HelloCpp.java Hel ...
- Linux学习心得之 Linux下命令行Android开发环境的搭建
作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Linux学习心得之 Linux下命令行Android开发环境的搭建 1. 前言2. Jav ...
随机推荐
- java基础知识三 流
Java 流(Stream).文件(File)和IOJava.io 包几乎包含了所有操作输入.输出需要的类.所有这些流类代表了输入源和输出目标. Java.io 包中的流支持很多种格式,比如:基本类型 ...
- STM32F0使用LL库实现PWM输出
在本次项目中,限于空间要求我们选用了STM32F030F4作为控制芯片.这款MCU不但封装紧凑,而且自带的Flash空间也非常有限,所以我们选择了LL库实现.本文我们将说明如何通过LL库实现PWM信号 ...
- Day04.a(对象类型的转换,多态)
对象类型的转换 Dog dog = new Dog(); 通常情况下,对象(new Dog())类型和引用(dog)类型是相同的,当引用类型和对象类型不一致时,就需要类型转换. 向上转型:将较具体的类 ...
- 一个Tomcat下部署两个,甚至多个项目
是的這是我粘過來的 Tomcat目录下的结构如图: 第一步:Tomcat默认空间webapps,中已经存在一个项目了,此时要增加一个项目运行可以将原本webapps目录copa一份, 改名为webap ...
- angular6、7 兼容ie9、10、11
1. 找到 polyfill.ts 并打开注释 /** * This file includes polyfills needed by Angular and is loaded before th ...
- Java 后台POST模拟文件上传
概述 废话不多说,直接撸代码 代码 1.引入Maven包 <dependency> <groupId>org.apache.httpcomponents</groupId ...
- log4j警告:WARN Please initialize the log4j system properly 的解决方法
出现这个问题的原因则是因为没有为log4j建立配置文件导致的.所以解决问题的方法很简单,只要在 src文件目录下建立配置文件即可: 右键点击src -> New -> File 文件 ...
- 关于Selenium3+python3.6自动化测试中iframe切换
本篇内容主要表述以下几个问题: 1.iframe 这个是什么? 2.定位iframe 标签时遇到的几个报错总结. 3.显示等待与隐示等待的原理与优缺点. 4.无name,ID可变情况下的处理方式 5. ...
- 音频相关基本概念,音频处理及编解码基本框架和原理以及音、重采样、3A等音频处理(了解概念为主)
视频笔记:音频专业级分析软件(Cooledit) 音质定义以语音带宽来区分,采样率越高,带宽越大,则保真度越高,音质越好.窄带(8khz采样),宽带(16khz采样),CD音质(44.1khz采样) ...
- Ubuntu zsh shell 一站式解决方案
#!/bin/bash sudo apt-get install zsh python -y sudo apt-get install python-pip -y sh -c "$(curl ...