创建不带gradle、ant或cmake的仅JNI/NDK apk命令行

本教程将介绍创建不带gradle、ant或cmake的仅JNI/NDK apk命令行的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。

问题描述

我为Android创建了一个只使用JNI和NDK的应用程序,除了连接我的代码与JNI所需之外,没有使用Java代码,因为这是一个使用OpenGL ES的应用程序,它将使用一个用于Linux和Android的代码。但是我不明白怎么创建一个APK文件,而没有我现在不想要的许多东西。所以,我试着创建一个没有Gradle,Ant,Android-studio的应用程序…也只能使用命令行。

我现在还有什么?

我可以使用NDK-Build成功构建我的项目,它创建了一个包含.o文件的”obj/”目录,但是现在呢?

怎么走?

使用AAPT和之后的zipign?

目标文件是否都是我使用AAPT所需的AAPT?

推荐答案

我甚至给了Gradle一个机会,但我不知道他在做什么,我很不安,于是决定把他放在一边,自己动手学习,就是这样。

教程内部版本java和JNI/NDK APK

1.安装JDK8和Android SDK,带NDK、Build-Tools、
平台-工具和Android平台23.

2.设置环境变量。

$ export SDK="${HOME}/Programs/Android" 
  export BUILD_TOOLS="${SDK}/build-tools/29.0.2" 
  export PLATFORM="${SDK}/platforms/android-23" 
  export ANDROID_API=23 
  export APK_NAME="APKName" 
  export PACKAGE_NAME="some.some.some" 
  export ORG_DIRS="${PACKAGE_NAME//.//}" 
  export NDK="${SDK}/ndk-bundle"
  export ANDROID_TOOLCHAIN="${NDK}/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi23-clang"

3.创建项目目录和文件。

创建目录树:

$ mkdir -p  src/"${ORG_DIRS}" res/layout build/gen build/obj build/apk jni

创建./AndroidManifest.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="some.some.some"
 versionCode="1"
 versionName="0.1">
 <uses-sdk android:minSdkVersion="23"/>
 <application android:label="Hello">
  <activity android:name=".MainActivity">
<intent-filter>
 <action android:name="android.intent.action.MAIN"/>
 <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
  </activity>
 </application>
</manifest>

创建./res/layout/main.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:gravity="center"
 android:orientation="vertical">

 <TextView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:id="@+id/my_text"/>
</LinearLayout>

创建src/ome/MainActivity.java文件:

package some.some.some;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  TextView text = (TextView)findViewById(R.id.my_text);
  text.setText("Hello, world!");
 }
}

4.使用Android资产打包工具(AAPT)生成R.java文件

$ "${BUILD_TOOLS}/aapt" package -f -m -J build/gen/ -S res 
 -M AndroidManifest.xml -I "${PLATFORM}/android.jar"

-f标志用于AAPT覆盖任何现有输出文件。

-m使其在输出目录下创建包目录。

使-J生成R.java文件并设置输出目录。

-S指出资源目录。-M指定清单。

-I将平台.jar添加为”包含文件”。

全部创建:build/gen/”${ORG_DIRS}”/R.java。

5.用javac编译java文件

$ javac -bootclasspath "${JAVA_HOME}/jre/lib/rt.jar" 
-classpath "${PLATFORM}/android.jar" -d build/obj 
build/gen/"${ORG_DIRS}"/R.java src/"${ORG_DIRS}"/MainActivity.java

如果您看到有关JDK版本的编译错误,请尝试使用
-source 1.7 -target 1.7命令中的-source 1.7 -target 1.7标记。

6.使用DX工具将build/obj/中的.class文件转换为Dalvik字节码。

$ "${BUILD_TOOLS}/dx" --dex --output=build/apk/classes.dex build/obj/

7.使用AAPT工具重新打包以创建APK。

$ "${BUILD_TOOLS}/aapt" package -f -M AndroidManifest.xml -S res/ 
-I "${PLATFORM}/android.jar" 
-F build/"${APK_NAME}".unsigned.apk build/apk/

8.在APK中使用zipign工具

它用于在4字节边界上对齐APK中的未压缩文件
以便更轻松地进行内存映射。

$ "${BUILD_TOOLS}/zipalign" -f -p 4 
build/"${APK_NAME}".unsigned.apk build/"${APK_NAME}".aligned.apk

9.创建用于使用Java密钥工具签名的密钥存储区和密钥。

$ keytool -genkeypair -keystore keystore.jks -alias androidkey 
-validity 10000 -keyalg RSA -keysize 2048

10.使用apksigner工具签署APK。

$ "${BUILD_TOOLS}/apksigner" sign --ks keystore.jks 
--ks-key-alias androidkey --out build/"${APK_NAME}".apk 
build/"${APK_NAME}".aligned.apk

11.使用ADB工具测试您的应用。

$ "${SDK}/platform-tools/adb" install -r build/"${APK_NAME}".apk
$ "${SDK}/platform-tools/adb" shell am start -n "${PACKAGE_NAME}"/.MainActivity

您可以在adb shell...之前使用adb logcat进行调试。

在步骤11之前,您是从Java代码构建APK的。现在让我们看看
怎么制作JNI/NDK代码的APK。

12.更改MainActivity.java文件,然后重新编译并翻译。

更改src/ome/MainActivity.java文件:

package some.some.some;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {
 static {
  System.loadLibrary("hello");
 }

 public native String getMessage();

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  TextView text = (TextView)findViewById(R.id.my_text);
  text.setText(getMessage());
 }
}

重新编译:

$ javac -bootclasspath "${JAVA_HOME}/jre/lib/rt.jar" 
-classpath "${PLATFORM}/android.jar" -d build/obj 
build/gen/"${ORG_DIRS}"/R.java src/"${ORG_DIRS}"/MainActivity.java

并再次转换为Dalvik字节码:

$ "${BUILD_TOOLS}/dx" --dex --output=build/apk/classes.dex build/obj/

13.使用javah工具查找Java方法对应的C函数签名

$ javah -classpath "${PLATFORM}/android.jar:build/obj" 
-o /tmp/jni.h "${PACKAGE_NAME}".MainActivity
$ grep -A1 _getMessage /tmp/jni.h
JNIEXPORT jstring JNICALL Java_some_some_some_MainActivity_getMessage
  (JNIEnv *, jobject);

14.创建hello.c文件。

#include <stdlib.h>
#include <jni.h>
#include <time.h>

static const char *const messages[] = {
  "Hello, world!",
  "Hej världen!",
  "Bonjour, monde!",
  "Hallo Welt!"
};

JNIEXPORT jstring JNICALL
Java_net_hanshq_hello_MainActivity_getMessage(JNIEnv *env, jobject obj) {
  int i;
  srand(time(NULL));
  i = rand() % (sizeof(messages) / sizeof(messages[0]));
  return (*env)->NewStringUTF(env, messages[i]);
}

15.使用ARM工具链创建libhello.so

首先,创建build/apk/lib/armeabi-v7a目录:

$ mkdir -p build/apk/lib/armeabi-v7a

构建libhello.so:

$ ${ANDROID_TOOLCHAIN} -shared -o build/apk/lib/armeabi-v7a/libhello.so jni/hello.c

16.重新打包APK。

$ "${BUILD_TOOLS}/aapt" package -f -M AndroidManifest.xml -S res/ 
-I "${PLATFORM}/android.jar" 
-F build/"${APK_NAME}".unsigned.apk build/apk/

17.重新对齐APK。

$ "${BUILD_TOOLS}/zipalign" -f -p 4 
build/"${APK_NAME}".unsigned.apk build/"${APK_NAME}".aligned.apk

18.重新签署APK。

$ "${BUILD_TOOLS}/apksigner" sign --ks keystore.jks 
--ks-key-alias androidkey --out build/"${APK_NAME}".apk 
build/"${APK_NAME}".aligned.apk

19.使用AAPT工具或JAR工具检查APK内容。

使用AAPT:

$ "${BUILD_TOOLS}/aapt" list build/"${APK_NAME}".apk

或AAPT提供更多详细信息:

$ "${BUILD_TOOLS}/aapt" list -v build/"${APK_NAME}".apk

或使用JAR:

$ jar tf build/"${APK_NAME}"

20.使用ADB工具再次测试您的应用。

$ "${SDK}/platform-tools/adb" install -r build/"${APK_NAME}".apk
$ "${SDK}/platform-tools/adb" shell am start --activity-clear-top -n "${PACKAGE_NAME}"/.MainActivity

--activity-clear-top用于清除任务,避免出现警告
“警告:活动未启动,其当前任务已进入
前面”。

本教程基于以下内容:
https://www.hanshq.net/command-line-android.html

好了关于创建不带gradle、ant或cmake的仅JNI/NDK apk命令行的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。

0
没有账号?注册  忘记密码?