首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Android 4可以用API < 9构建项目吗?

Android 4可以用API < 9构建项目吗?
EN

Stack Overflow用户
提问于 2021-08-20 02:41:34
回答 1查看 64关注 0票数 1

我希望我的应用程序支持任何Android手机api 3和更高版本。

为什么?因为我不喜欢浪费,这些旧手机已经足够完成手头的任务了。

不幸的是,要获得关于基本的预api-9 SDK构建的信息比让NDK工作要困难得多。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-20 02:41:34

我无法找到一种机制来使用developer.android.com提供的任何Android版本来构建applications <9。

但是,可以使用旧的命令行工具来构建它们。(我还没有研究过api <9使用ActivityCompat库或ndk构建来调试JNI应用程序-这些都是留给读者的练习:-)

注意:使用这些技术需要熟悉当前的命令行构建,没有这些构建就没有什么意义了。

这项任务分为四部分:

api <9的Android示例项目

代码语言:javascript
运行
复制
https://android.googlesource.com/platform/development/+refs

从甜甜圈到android 4无所不包。

每个目录都有一个“示例”子目录,这是一个很好的起点。

用于构建api <9个项目的Android工具

代码语言:javascript
运行
复制
https://dl.google.com/android/repository/repository-10.xml

列出所有下载及其摘要/校验和,位于:

代码语言:javascript
运行
复制
https://dl.google.com/android/repository/(repo-filename)

您需要找到、下载和安装:

  • platform sdk 3

  • build-tools 17.0.0 (包含aapt的最新版本)

  • build-tools 24.0.3 (包含apksigner的最古老的)

  • ndk R11C (支持api 3至8 JNI的最新版本)

为api <9构建Android库

请注意,api <4设备似乎更喜欢从设备OS链接共享符号,而不是从JNI库链接,因此避免从库中发布冲突的符号,并静态地链接任何第三方库(许可)。

示例Makefile:

代码语言:javascript
运行
复制
API = 3
NDK = ~/Android/Sdk/ndk/r11c
CC = $(NDK)/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
SR = $(NDK)/platforms/android-$(API)/arch-arm
INC = -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux

objs = obj/thing1.o obj/thing2.o ...

libexample.so : $(objs)
    $(CC) --sysroot=$(SR) -fPIC -Wall -shared -o libexample.so -O $^

obj/%.o : %.c
    $(CC) --sysroot=$(SR) -fPIC -Wall -mthumb -c $< -o $@ $(INC)

如果要构建openssl,则需要额外的配置标志:

代码语言:javascript
运行
复制
--with-rand-seed=devrandom

以及没有线程的非asm。

为api <9构建Android应用程序

遗憾的是,我无法找到一种方法来使用当今的Android来构建这些低api项目,所以下面是一些讨厌的命令行来代替它。

您需要找到、下载和安装:

  • platform sdk 3

  • build-tools 17.0.0 (包含aapt的最新版本)

  • build-tools 24.0.3 (包含apksigner的最古老的)

(关于如何获得这些信息,请参阅上文。)

项目树

代码语言:javascript
运行
复制
project/
    Makefile
    app/
        build/
        src/
            main/
                AndroidManifest.xml
                assets/
                jniLibs/
                    armeabi/
                        libexample.so
                res/
                    layout/
                        activity_main.xml
                java/
                    com/
                        example/
                            project/
                                MainActivity.java

AndroidManifest.xml

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.project">
    <application
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        >
        <uses-sdk android:minSdkVersion="3" />
        <activity android:name="com.example.project.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

activity_main.xml

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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"
    tools:context="com.example.project.MainActivity"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/outer"
    android:orientation="vertical"    
    >
    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="run"
        /><!--note: no onClick-->
    ...

MainActivity.java

代码语言:javascript
运行
复制
package com.example.project;
import android.os.Bundle;
import android.app.Activity;
import android.widget.Button;
public class MainActivity extends Activity {
    @Override protected void onCreate(Bundle bdl) {
        super.onCreate(bdl);
        setContentView(R.layout.activity_main);        
        final Button btn = (Button)findViewById(R.id.btn);
        btn.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                ...
            }
        });
    }
};

Makefile

代码语言:javascript
运行
复制
API = 3
KEY_PATH = ~/jkeystore
DROID_HOME = ~/Android/Sdk
JAVA_HOME = /usr/lib/jvm/java-8-openjdk-amd64
BLD_TOOLS=17.0.0
APK_SIGNR=24.0.3

PKG_PATH = com/example/project
JVA_ROOT = app/src/main/java
RES_ROOT = app/src/main/res
AST_ROOT = app/src/main/assets
AMF_PNAM = app/src/main/AndroidManifest.xml
LIB_REAL = app/src/main/jniLibs

CLS_ROOT = app/build/intermediates/javac/debug/classes
DEX_PATH = app/build/intermediates/dex/debug/mergeDexDebug
APK_PATH = app/build/outputs/apk/debug
APK_NAME = app-debug
LIB_TEMP = lib

JVA_PRJT = $(JVA_ROOT)/$(PKG_PATH)
CLS_PRJT = $(CLS_ROOT)/$(PKG_PATH)
APK_PNAM = $(APK_PATH)/$(APK_NAME)
DRD_JAR =  $(DROID_HOME)/platforms/android-$(API)/android.jar

jopt  = -proc:none -Xlint:all -Xlint:-fallthrough -Werror -Xmaxerrs 5
jopt += -implicit:none -target 1.6 -source 1,6 -bootclasspath ~/jre1.6.0_45/lib/rt.jar

# wildcard matches symlinks awa directories. dir filters, sort dedupes.
JVA_DIRS := $(dir $(wildcard $(JVA_PRJT)/*/) )
JVA_DIRS := $(sort $(JVA_DIRS) )
JVA_DIRS += $(JVA_PRJT)/

# all in java tree except R.java (and thus R.class)
temp_jva := $(foreach pth, $(JVA_DIRS), $(wildcard $(pth)*.java) )
JVA_LIST := $(patsubst $(JVA_PRJT)/R.java, , $(temp_jva))

temp_cls := $(patsubst $(JVA_PRJT)/%.java,$(CLS_PRJT)/%.class, $(JVA_LIST))
CLS_LIST := $(patsubst $(JVA_PRJT)/%,$(CLS_PRJT)/%, $(temp_cls))

LIB_LIST := $(shell find $(LIB_REAL) -type f 2> /dev/null)
LIB_TLST := $(patsubst $(LIB_REAL)/%, $(LIB_TEMP)/%, $(LIB_LIST))

AST_LIST := $(shell find $(AST_ROOT) -type f 2> /dev/null)
ifneq ($(strip $(AST_LIST)),)
    AST_OPTN = -A $(AST_ROOT)
endif

RES_LIST := $(shell find $(RES_ROOT) -type f)

.DELETE_ON_ERROR:

assembleDebug: $(APK_PNAM).apk
    
$(APK_PNAM).apk : $(APK_PNAM).nosig.apk $(AMF_PNAM) $(RES_LIST) $(AST_LIST) $(LIB_LIST)
    #****************************** SIGN **********************************
    $(DROID_HOME)/build-tools/$(APK_SIGNR)/apksigner sign -v --verbose \
        --ks $(KEY_PATH) --ks-pass pass:debug_pw --min-sdk-version $(API) \
        --out $@ $(APK_PNAM).nosig.apk

$(APK_PNAM).nosig.apk : $(DEX_PATH)/classes.dex $(AMF_PNAM) $(RES_LIST) $(AST_LIST) $(LIB_LIST)
    #****************************** PACKAGE *******************************
    @-mkdir -p $(APK_PATH)
    $(DROID_HOME)/build-tools/$(BLD_TOOLS)/aapt package -v -f -M $(AMF_PNAM) \
        -S $(RES_ROOT) $(AST_OPTN) -I $(DRD_JAR) -F $(APK_PNAM).nosig.apk $(DEX_PATH)/
ifneq ($(strip $(LIB_LIST)),)
    #****************************** LIBS **********************************
    cp -r $(LIB_REAL) $(LIB_TEMP)/
    $(DROID_HOME)/build-tools/$(BLD_TOOLS)/aapt add -v $(APK_PNAM).nosig.apk $(LIB_TLST)
    @-rm -r $(LIB_TEMP)
endif

$(DEX_PATH)/classes.dex : $(CLS_LIST) $(CLS_PRJT)/R.class
    #****************************** LINK **********************************
    $(JAVA_HOME)/bin/javac $(jopt) -sourcepath $(JVA_ROOT)/ -cp $(DRD_JAR) \
        -d $(CLS_ROOT)/ $(JVA_PRJT)/$(START).java
    @-mkdir -p $(DEX_PATH)
    $(DROID_HOME)/build-tools/$(BLD_TOOLS)/dx --dex --verbose --output=$@ $(CLS_ROOT)

$(CLS_PRJT)/%.class : $(JVA_PRJT)/%.java $(CLS_PRJT)/R.class
    @-mkdir -p $(CLS_PRJT)
    $(JAVA_HOME)/bin/javac $(jopt) -sourcepath $(JVA_ROOT)/ -cp $(DRD_JAR) -d $(CLS_ROOT)/ $<
    
$(CLS_PRJT)/R.class : $(JVA_PRJT)/R.java
    #****************************** R.CLASS *******************************
    @-mkdir -p $(CLS_PRJT)
    $(JAVA_HOME)/bin/javac $(jopt) -sourcepath $(JVA_ROOT)/ -cp $(DRD_JAR) -d $(CLS_ROOT)/ $<

$(JVA_PRJT)/R.java : $(RES_LIST) $(AMF_PNAM)
    #****************************** R.JAVA ********************************
    $(DROID_HOME)/build-tools/$(BLD_TOOLS)/aapt package -v -f -M $(AMF_PNAM) \
        -S $(RES_ROOT) -m -J $(JVA_ROOT) -I $(DRD_JAR)

您可能需要一个32位的zlib:

代码语言:javascript
运行
复制
sudo apt install zlib1g:i386

...and实际上应该获得java1.6用于引导:

代码语言:javascript
运行
复制
https://www.oracle.com/uk/java/technologies/javase-java-archive-javase6-downloads.html

下载jre-6u45-linux-x64.bin (需要注册)

您还需要为apk签名配置keystore:

代码语言:javascript
运行
复制
/usr/lib/jvm/java-8-openjdk-amd64/bin/keytool \
    -genkeypair -validity 1000 -dname "CN=some company,O=Android,C=JPN" -keystore ~/jkeystore \
    -storepass debug_pw -keypass debug_pw -alias cert -keyalg RSA -v

重要信息:

我要指出的是,api <9设备被认为最容易受到移动数据、wifi、捆绑、亚行、蓝牙、GSM等攻击。

恶搞

对不起,这篇文章太长了,但是当我试着把它放在章节中时,我有版主/复制的问题。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68856399

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档