当前位置:   article > 正文

构建 Aria2 (Android share library)_aria2 安卓编译

aria2 安卓编译

搭建工具环境

安装系统工具

sudo apt-get install autoconf ???point docbook2x tofrodos

下载NDK,android-ndk-r14b-linux-x86_64.zip,解压后,在NDK目录执行:

  1. mkdir -p /mnt/work/toolchain/android-standalone-r14b
  2. export ANDROID_HOME=/mnt/work/toolchain/android-standalone-r14b
  3. build/tools/make_standalone_toolchain.py \
  4. --arch arm --api 16 --stl=gnustl \
  5. --install-dir $ANDROID_HOME/toolchain
  6. export ANDROID_NDK_ROOT=/mnt/work/toolchain/ndk/android-ndk-r14b
  7. export ANDROID_NDK_HOME=/mnt/work/toolchain/ndk/android-ndk-r14b

构建依赖库

c-ares

  1. git clone https://github.com/c-ares/c-ares.git
  2. cd c-ares
  3. git br 1.15.0 e982924acee7f7313b4baa4ee5ec000c5e373c30
  4. git co 1.15.0
  5. ./buildconf
  6. ./configure \
  7. --prefix=${ANDROID_HOME}/usr/local \
  8. --host=arm-linux-androideabi \
  9. CC=arm-linux-androideabi-gcc \
  10. --enable-shared=no \
  11. --enable-static=yes
  12. make install
  13. cd ..

libexpat

  1. git clone https://github.com/libexpat/libexpat.git
  2. cd libexpat
  3. git br 2.2.6 39e487da353b20bb3a724311d179ba0fddffc65b
  4. git co 2.2.6
  5. ./buildconf
  6. ./configure \
  7. --prefix=${ANDROID_HOME}/usr/local \
  8. --host=arm-linux-androideabi \
  9. CC=arm-linux-androideabi-gcc \
  10. --enable-shared=no \
  11. --enable-static=yes \
  12. --with-docbook
  13. make install
  14. cd ..

openssl

  1. git clone https://github.com/openssl/openssl.git
  2. cd openssl
  3. git br 1.1.1b 50eaac9f3337667259de725451f201e784599687
  4. git co 1.1.1b
  5. wget https://wiki.openssl.org/images/7/70/Setenv-android.sh
  6. fromdos Setenv-android.sh
  7. chmod u+x Setenv-android.sh
  8. . Setenv-android.sh
  9. ./config shared no-ssl2 no-ssl3 no-comp no-hw no-engine \
  10. --openssldir=${ANDROID_HOME}/usr/local \
  11. --prefix=${ANDROID_HOME}/usr/local
  12. make depend
  13. make all
  14. make install \
  15. CC=$ANDROID_TOOLCHAIN/arm-linux-androideabi-gcc \
  16. RANLIB=$ANDROID_TOOLCHAIN/arm-linux-androideabi-ranlib
  17. export PATH=${PATH#*:}
  18. cd ..

zlib

(tar.gz包手动下载)

  1. tar -xzvf zlib-1.2.11.tar.gz
  2. cd zlib-1.2.11
  3. export CC=arm-linux-androideabi-gcc
  4. ./configure \
  5. --prefix=${ANDROID_HOME}/usr/local \
  6. -static
  7. make install

libssh2

  1. git clone https://github.com/libssh2/libssh2.git
  2. cd libssh2
  3. # 1.8.2 failed need patch d071e0e07b2, use master
  4. # git br 1.8.2 02ecf17a6d5f9837699e8fb3aad0c804caa67eeb
  5. # git co 1.8.2
  6. ./configure \
  7. --prefix=${ANDROID_HOME}/usr/local \
  8. --host=arm-linux-androideabi \
  9. CC=arm-linux-androideabi-gcc \
  10. --enable-shared=no \
  11. --enable-static=yes
  12. make install

构建aria2

  1. git clone https://github.com/aria2/aria2.git
  2. cd aria2
  3. autoreconf -i
  4. ./android-config
  5. ./android-make
  6. ./android-release
  7. ln -s src/.libs/libaria2.a
  8. cd ..

如果要生成动态链接库

  1. /bin/bash ../libtool --silent --tag=CXX --mode=link \
  2. /home/cmguo/work/toolchain/android-standalone-r14b/toolchain/bin/arm-linux-androideabi-clang++ \
  3. -export-dynamic -std=c++11 -pipe -Os -g -fPIE -pie -shared -o libaria2.so main.o libaria2.la \
  4. /home/cmguo/work/toolchain/android-standalone-r14b/usr/local/lib/libz.a \
  5. /home/cmguo/work/toolchain/android-standalone-r14b/usr/local/lib/libexpat.a \
  6. /home/cmguo/work/toolchain/android-standalone-r14b/usr/local/lib/libssl.a \
  7. /home/cmguo/work/toolchain/android-standalone-r14b/usr/local/lib/libcrypto.a \
  8. /home/cmguo/work/toolchain/android-standalone-r14b/usr/local/lib/libssh2.a \
  9. /home/cmguo/work/toolchain/android-standalone-r14b/usr/local/lib/libcares.a \
  10. -llog ../deps/wslay/lib/libwslay.la
  11. arm-linux-androideabi-strip -s libaria2.so -o ../libaria2.so

 二次开发

动态库生成后,我们就可以在APP里面加载aria2库了。

JNI对接

我们只使用rpc(即http)接口操作aria2,所以只要完成启动其main入口就行了。为此,我们将main方法通过JNI形式提供给java层调用。

  1. extern "C" JNIEXPORT jint JNICALL Java_com_xxx_aria2_Aria2_main(JNIEnv *env, jclass clazz, jobjectArray jargv)
  2. { //jargv is a Java array of Java strings
  3. int argc = env->GetArrayLength(jargv);
  4. typedef char *pchar;
  5. pchar *argv = new pchar[argc];
  6. int i;
  7. for(i = 0; i < argc; i++)
  8. {
  9. jstring js = (jstring) env->GetObjectArrayElement(jargv, i); //A Java string
  10. jboolean isCopy;
  11. const char *pjc = env->GetStringUTFChars(js, &isCopy); //A pointer to a Java-managed char buffer
  12. size_t jslen = strlen(pjc);
  13. argv[i] = new char[jslen+1]; //Extra char for the terminating null
  14. strcpy(argv[i], pjc); //Copy to *our* buffer. We could omit that, but IMHO this is cleaner. Also, const correctness.
  15. env->ReleaseStringUTFChars(js, pjc);
  16. }
  17. //Call main
  18. chdir(argv[0]);
  19. int ret = main2(argc, argv);
  20. //Now free the array
  21. for(i=0;i<argc;i++)
  22. delete [] argv[i];
  23. delete [] argv;
  24. return ret;
  25. }

Log对接

但启动出现问题时,通过aria2自己的输出日志排查问题是很必要的。Aria2通过OutputFile基类输出日志,因此我们可以很方便的扩展一个使用Android Log的OutputFile——LogcatFile。

  1. // LogcatFile.h
  2. #include "OutputFile.h"
  3. #include <android/log.h>
  4. #include <stdarg.h>
  5. namespace aria2 {
  6. class LogcatFile : public OutputFile {
  7. public:
  8. LogcatFile(int l)
  9. {
  10. level_ = l;
  11. }
  12. virtual ~LogcatFile() = default;
  13. virtual size_t write(const char* str)
  14. {
  15. __android_log_print(level_, "Aria2", "%s", str);
  16. return 0;
  17. }
  18. virtual int flush() { return 0; }
  19. virtual int vprintf(const char* format, va_list va)
  20. {
  21. __android_log_vprint(level_, "Aria2", format, va);
  22. return 0;
  23. }
  24. inline int printf(const char* format, ...)
  25. {
  26. va_list va;
  27. va_start(va, format);
  28. int rv = vprintf(format, va);
  29. va_end(va);
  30. return rv;
  31. }
  32. virtual bool supportsColor() { return true; }
  33. private:
  34. int level_;
  35. };
  36. }

在Console初始化中,增加Android情况下的选择策略,使用LogcatFile。

  1. #include "NullOutputFile.h"
  2. #ifdef __MINGW32__
  3. # include "WinConsoleFile.h"
  4. #elif __ANDROID__
  5. # include "LogcatFile.h"
  6. #else // !__MINGW32__
  7. # include "BufferedFile.h"
  8. #endif // !__MINGW32__
  9. void initConsole(bool suppress)
  10. {
  11. if (suppress) {
  12. consoleCout = consoleCerr = std::make_shared<NullOutputFile>();
  13. }
  14. else {
  15. #ifdef __MINGW32__
  16. consoleCout = std::make_shared<WinConsoleFile>(STD_OUTPUT_HANDLE);
  17. consoleCerr = std::make_shared<WinConsoleFile>(STD_ERROR_HANDLE);
  18. #elif __ANDROID__
  19. consoleCout = std::make_shared<LogcatFile>(3);
  20. consoleCerr = std::make_shared<LogcatFile>(5);
  21. #else // !__MINGW32__
  22. consoleCout = std::make_shared<BufferedFile>(stdout);
  23. consoleCerr = std::make_shared<BufferedFile>(stderr);
  24. #endif // !__MINGW32__
  25. }
  26. }

Java封装

接下来,我们就可以在APP使用aria2了。

  1. public class Aria2
  2. {
  3. protected static final String TAG = "Aria2";
  4. static {
  5. System.loadLibrary("aria2");
  6. }
  7. private static Thread sThread;
  8. public static void start(Context context) {
  9. File extDir = context.getExternalCacheDir();
  10. File storageDir = new File(extDir, "aria2");
  11. File sessionFile = new File(extDir, "aria2.session");
  12. File cacheDir = context.getCacheDir();
  13. File confFile = new File(cacheDir, "aria2.conf");
  14. File logFile = new File(cacheDir, "aria2.log");
  15. storageDir.mkdirs();
  16. Assets.extract(context, "aria2.conf", confFile);
  17. try {
  18. new FileOutputStream(sessionFile).close();
  19. } catch (Exception e) {
  20. }
  21. final List<String> argv = new ArrayList<String>();
  22. argv.add(cacheDir.getAbsolutePath());
  23. argv.add("--conf-path=" + confFile.getAbsolutePath());
  24. argv.add("--log=" + logFile.getAbsolutePath());
  25. argv.add("--input-file=" + sessionFile.getAbsolutePath());
  26. argv.add("--save-session=" + sessionFile.getAbsolutePath());
  27. argv.add("--dir=" + storageDir.getAbsolutePath());
  28. sThread = new Thread(new Runnable() {
  29. @Override
  30. public void run() {
  31. main(argv.toArray(new String[argv.size()]));
  32. }
  33. });
  34. sThread.start();
  35. }
  36. }

这里我们做了下面几件事:

  1. 在assets里面集成了配置文件 aria2.conf,一开始将其解压出来
  2. 通过命令行参数传递一些与文件路径有关的传输,比如conf-path、log、dir等,有些目录和文件要提前准备好
  3. 配置文件 aria2.conf的deamon改成false,要不然aria2会fork一个新进程,其实是fork了一个应用进程,这会导致一些不可预见的问题。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/576904
推荐阅读
相关标签
  

闽ICP备14008679号