分类 android NDK 下的文章

Android中configure: error: C compiler cannot create executables解决方法

软硬件环境

  • android 5.1..1
  • ndk r15c

错误描述

vlc_android_compile_error_01

vlc_android_compile_error_02

解决思路

这个一般是跟ndk相关的错误,某些头文件或者obj文件找不到。可以编写个简单的hello world源文件测试

#include <stdio.h>

int main() {
    printf("Hello world.");
    return 0;
}

使用ndk中的编译器进行编译,如

export $ANDROID_NDK=/home/longjing/tools/Android/android-ndk-r15c
$ANDROID_NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc test.c

编译果然报错,找不到头文件

../test.c:16:19: fatal error: stdio.h: No such file or directory
 #include <stdio.h>
                   ^
compilation terminated.

既然是测试文件,那干脆就去掉include语句,再删除printf语句,重新编译看下结果

//#include <stdio.h>

int main() {
    //printf("Hello world.");
    return 0;
}

这下就告诉你obj文件找不到了

/home/longjing/tools/Android/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtbegin_dynamic.o: No such file or directory
/home/longjing/tools/Android/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtend_android.o: No such file or directory
/home/longjing/tools/Android/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: cannot find -lc
/home/longjing/tools/Android/android-ndk-r15c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld: error: cannot find -ldl
collect2: error: ld returned 1 exit status

使用find命令在ndk目录下搜索下crtend_android.o文件

cd /home/longjing/tools/Android/android-ndk-r15c
find . -iname crtend_android.o

vlc_android_compile_error_03

可以看到,obj文件都是存在的。那么怎么解决呢?既然找不到,那就给你个路径

$ANDROID_NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc test.c --sysroot=$ANDROID_NDK/platforms/android-9/arch-arm

最后重新编译,错误消失了。

vlc_for_android(基于git-3.0.0)快速集成

软硬件环境

  • ubuntu 16.04 64bit
  • Android 5.1.1 TV Box
  • Android studio 2.3.1

前言

最近老有朋友在问vlc for android的移植问题,网络上有一些帖子也有谈到,但是大部分都是基于老版本,况且vlc的更新也很频繁,接口也经常变动,给大家造成了很大的困扰。鉴于此,我专门写一篇博文,将具体的方法及步骤写出来,最后将源码工程上传到了github,方便一些有此需求的朋友,如果感觉对你有所帮助,请去github点个赞,地址是https://github.com/djstava/OTTLivePlayer_vlc,有什么问题也可以在issue里提,谢谢。

vlc-android源码编译

我们的目的是使用最新的vlc-android,而且随着vlc的更新升级,我们的app也需要随时能够得到更新,因此编译源码是少不了的。这个我之前有一篇博文已经写过,请参考http://www.xugaoxiang.com/blog/index.php/archives/57/

vlc-android代码剥离

vlc-android编译完成后 ,目录文件很多。我们需要将动态链接库so文件和java层的相关类库拷出来,它们的路径分别如下图所示

vlc_dir

jniso2

vlc_java

如何创建MediaPlayer

ArrayList<String> options = new ArrayList<>();
options.add("-vvv");
libvlc = new LibVLC(this, options);

mediaPlayer = new MediaPlayer(libvlc);

IVLCVout ivlcVout = mediaPlayer.getVLCVout();
ivlcVout.setVideoView(surfaceView);
ivlcVout.attachViews(this);

Media media = new Media(libvlc, Uri.parse("udp://@225.0.0.1:9000"));
mediaPlayer.setMedia(media);
mediaPlayer.play();

一些坑

Error:(466, 73) 错误: -source 1.6 中不支持 diamond 运算符 (请使用 -source 7 或更高版本以启用 diamond 运算符)

Android studio --> File --> Project structure... --> app --> Source Compatibility

e1

工程截图

s1

s2

s3

s4

s5

参考资料

1 https://github.com/djstava/OTTLivePlayer_vlc

2 http://www.xugaoxiang.com/blog/index.php/archives/57/

3 https://wiki.videolan.org/AndroidCompile

vlc_for_android的编译及使用

软硬件环境

  • ubuntu 16.04 64bit
  • Android 5.1.1 TV Box
  • Android studio 2.1.2

概述

VLC是一款大名鼎鼎的流媒体播放器,对本地和流式媒体都支持良好,跨平台,支持当前市面上绝大多数的封装格式及编码格式,最重要的,它还是开源软件.

Android SDK和NDK环境

之前一直有用Android Studio工具,所以这个环境都已经配置好了,在工程配置文件local.properties中会有描述.

ndk.dir=/home/djstava/Workshop/tool/SDK/ndk-bundle
sdk.dir=/home/djstava/Workshop/tool/SDK

如果之前压根就没有配过,那就从头开始,安装Android Studio,再通过android studio分别去安装SDK和NDK.拿到了这2个路径,设置到环境变量ANDROID_SDK和ANDROID_NDK中去.

export ANDROID_NDK=/home/djstava/Workshop/tool/SDK/ndk-bundle
export ANDROID_SDK=/home/djstava/Workshop/tool/SDK
export PATH=$PATH:$ANDROID_SDK/platform-tools:$ANDROID_SDK/tools

建议将上述配置语句写入~/.bashrc文件中,免得每次编译都要去手动配置.

安装必备的系统工具包

首先安装一些必备的系统工具,如git jdk8 make等

sudo apt-get install automake ant autopoint cmake build-essential libtool patch pkg-config protobuf-compiler ragel subversion unzip git openjdk-8-jdk

编译VLC源码

准备工作就绪,现在开始本文的重头戏.首先还是需要拉下源码

git clone https://code.videolan.org/videolan/vlc-android.git
cd vlc-android
sh compile.sh
compile.sh做了些什么?

查看compile.sh文件,知道脚本会去下载 配置gradle环境(目前的版本是2.14.1),如果执行这个脚本之前跟我一样没有设置ANDROID_ABI环境变量,编译的目标架构就是ARMv7.要修改的话就添加-a参数

sh compile.sh -a <ABI>

其中的可选值有

* armeabi-v7a
* arm64-v8a
* x86
* x86_64
* MIPS
* MIPS64

gradle配置的最后会将ANDROID_SDK和ANDROID_NDK的值写入到vlc-android下的local.properties文件中,将app签名相关的信息写入gradle.properties文件中.

脚本的最后是去下载vlc的源码,然后调用另一个脚本文件compile-libvlc.sh去编译.

compile-libvlc.sh做了些什么?

这是最核心的部分,它负责对vlc进行configure和make,这个过程和在Linux系统下去编译软件是一样的,所不同的是这里用的是android NDK的工具集去生成jni编程中需要用到的动态链接库.做纯app的童鞋,可能之前都没有接触过这块,不过不要紧.也许之前你只是单纯的去调用so,现在这部分我们也做了.脚本执行过程中会去下载需要的工具包,请保持网络畅通.

在播放过程中遇到的很多问题,基本上都是要从这一块来找原因,可想而知这部分的重要性了.

漫长的等待(机器性能差)后,apk终于生成了,位于./vlc-android/build/outputs/apk/VLC-Android-2.1.0-ARMv7.apk

后续的软件升级

前面都是采用git的方式下载源码,因此软件升级就变得非常容易了,git pull再编译就可以了,这里就不多说了.

源码下载

vlc-android

参考文献

  1. https://wiki.videolan.org/AndroidCompile
  2. http://www.androiddevtools.cn

在Android studio中进行NDK开发

软硬件环境

  • ubuntu kylin 14.04
  • 红米note增强版
  • Android studio 0.8.6
  • ndk r10c

前言

本文的目标是在Android studio中进行NDK的开发。示例是在main activity中显示一个字符串,而字符串的内容是来自于一个C函数。归结于一句话:NDK是为了让上层的java应用能够调用底层的c/c++而设计的。马上进入主题。

创建工程

创建一个名为jniDemo的blank activity工程,activity名为MyActivity,在MyActivity类的最后声明一个方法,这个方法会在C函数中去实现,如下图所示,

jni部分

设置ndk路径,打开local.properties,增加

ndk.dir=/home/djstava/Workshop/Android/android-studio/ndk

点击android studio左下角的Terminal

cd src/main
javah -d jni -classpath ~/Workshop/Android/android-studio/sdk/platforms/android-4.4.2/android.jar:../../build/intermediates/classes/debug/ com.example.djstava.jnidemo.MyActivity

参数意义:

-d 输出目录,jni是gradle默认的路径    
-classpath jar的路径,经常碰到的找不到activity的类的错误一般是由这个引起的    
com.example.djstava.jnidemo.MyActivity 包名+activity    

这条命令执行完毕后,会在src/main下生成jni目录,并产生头文件com_example_djstava_jnidemo_MyActivity.h,其内容为

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_djstava_jnidemo_MyActivity */

#ifndef _Included_com_example_djstava_jnidemo_MyActivity
#define _Included_com_example_djstava_jnidemo_MyActivity
#ifdef __cplusplus
extern "C" {
#endif
#undef com_example_djstava_jnidemo_MyActivity_MODE_PRIVATE
#define com_example_djstava_jnidemo_MyActivity_MODE_PRIVATE 0L
#undef com_example_djstava_jnidemo_MyActivity_MODE_WORLD_READABLE
#define com_example_djstava_jnidemo_MyActivity_MODE_WORLD_READABLE 1L
#undef com_example_djstava_jnidemo_MyActivity_MODE_WORLD_WRITEABLE
#define com_example_djstava_jnidemo_MyActivity_MODE_WORLD_WRITEABLE 2L
#undef com_example_djstava_jnidemo_MyActivity_MODE_APPEND
#define com_example_djstava_jnidemo_MyActivity_MODE_APPEND 32768L
#undef com_example_djstava_jnidemo_MyActivity_MODE_MULTI_PROCESS
#define com_example_djstava_jnidemo_MyActivity_MODE_MULTI_PROCESS 4L
#undef com_example_djstava_jnidemo_MyActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING
#define com_example_djstava_jnidemo_MyActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L
#undef com_example_djstava_jnidemo_MyActivity_BIND_AUTO_CREATE
#define com_example_djstava_jnidemo_MyActivity_BIND_AUTO_CREATE 1L
#undef com_example_djstava_jnidemo_MyActivity_BIND_DEBUG_UNBIND
#define com_example_djstava_jnidemo_MyActivity_BIND_DEBUG_UNBIND 2L
#undef com_example_djstava_jnidemo_MyActivity_BIND_NOT_FOREGROUND
#define com_example_djstava_jnidemo_MyActivity_BIND_NOT_FOREGROUND 4L
#undef com_example_djstava_jnidemo_MyActivity_BIND_ABOVE_CLIENT
#define com_example_djstava_jnidemo_MyActivity_BIND_ABOVE_CLIENT 8L
#undef com_example_djstava_jnidemo_MyActivity_BIND_ALLOW_OOM_MANAGEMENT
#define com_example_djstava_jnidemo_MyActivity_BIND_ALLOW_OOM_MANAGEMENT 16L
#undef com_example_djstava_jnidemo_MyActivity_BIND_WAIVE_PRIORITY
#define com_example_djstava_jnidemo_MyActivity_BIND_WAIVE_PRIORITY 32L
#undef com_example_djstava_jnidemo_MyActivity_BIND_IMPORTANT
#define com_example_djstava_jnidemo_MyActivity_BIND_IMPORTANT 64L
#undef com_example_djstava_jnidemo_MyActivity_BIND_ADJUST_WITH_ACTIVITY
#define com_example_djstava_jnidemo_MyActivity_BIND_ADJUST_WITH_ACTIVITY 128L
#undef com_example_djstava_jnidemo_MyActivity_CONTEXT_INCLUDE_CODE
#define com_example_djstava_jnidemo_MyActivity_CONTEXT_INCLUDE_CODE 1L
#undef com_example_djstava_jnidemo_MyActivity_CONTEXT_IGNORE_SECURITY
#define com_example_djstava_jnidemo_MyActivity_CONTEXT_IGNORE_SECURITY 2L
#undef com_example_djstava_jnidemo_MyActivity_CONTEXT_RESTRICTED
#define com_example_djstava_jnidemo_MyActivity_CONTEXT_RESTRICTED 4L
#undef com_example_djstava_jnidemo_MyActivity_RESULT_CANCELED
#define com_example_djstava_jnidemo_MyActivity_RESULT_CANCELED 0L
#undef com_example_djstava_jnidemo_MyActivity_RESULT_OK
#define com_example_djstava_jnidemo_MyActivity_RESULT_OK -1L
#undef com_example_djstava_jnidemo_MyActivity_RESULT_FIRST_USER
#define com_example_djstava_jnidemo_MyActivity_RESULT_FIRST_USER 1L
#undef com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_DISABLE
#define com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_DISABLE 0L
#undef com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_DIALER
#define com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_DIALER 1L
#undef com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SHORTCUT
#define com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SHORTCUT 2L
#undef com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SEARCH_LOCAL
#define com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L
#undef com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SEARCH_GLOBAL
#define com_example_djstava_jnidemo_MyActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L
/*
  • Class: com_example_djstava_jnidemo_MyActivity

    • Method: getStringFromJNI
    • Signature: ()Ljava/lang/String;
      */
      JNIEXPORT jstring JNICALL Java_com_example_djstava_jnidemo_MyActivity_getStringFromJNI
      (JNIEnv *, jobject);

    ifdef __cplusplus

    }

    endif

    endif

根据产生的头文件,在同级目录创建C源文件,内容如下

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_djstava_jnidemo_MyActivity */

/*
  • Class: com_example_djstava_jnidemo_MyActivity
    • Method: getStringFromJNI
    • Signature: ()Ljava/lang/String;
      */
      JNIEXPORT jstring JNICALL Java_com_example_djstava_jnidemo_MyActivity_getStringFromJNI
      (JNIEnv env, jobject obj)
      {
      return (
      env)->NewStringUTF(env,"Hello android from jni!");
      }

gladle配置

打开build.gladle,在defaultConfig设置项内添加

ndk {
    moduleName "jniLib" //这是模块名称,在加载时会被用到
}

在defaultConfig设置项后面添加

flavorGroups "abi"
productFlavors {
    x86 {
        ndk {
            abiFilter "x86"
        }
    }
    arm {
        ndk {
            abiFilter "armeabi-v7a"
        }
    }
    mips {
        ndk {
            abiFilter "mips"
        }
    }
}

在MyActivity中加载jni模块,如下图所示,要去掉前缀lib和后缀.so

修改activity_my.xml

添加textView的id

android:id="@+id/jni_text"

测试

不出意外的话,你的app的textView上会出现"Hello android from jni!"。生成的库位于app/build/intermediates/ndk/arm/debug/lib/armeabi-v7a/libjniLib.so,Makefile文件位于/home/djstava/AndroidstudioProjects/jniDemo/app/build/intermediates/ndk/arm/debug/Android.mk,apk文件位于/home/djstava/AndroidstudioProjects/jniDemo/app/build/outputs/apk,当然这些文件的生成都是在studio里做的,对用户是透明的。

参考文献

1、https://developer.android.com/tools/sdk/ndk/index.html
2、https://www.youtube.com/watch?v=okLKfxfbz40
3、http://www.shaneenishry.com/blog/2014/08/17/ndk-with-android-studio/
4、https://software.intel.com/en-us/videos/using-the-ndk-with-android-studio
5、https://www.youtube.com/watch?v=e54f6dt9OZo&feature=youtube_gdata

Android Studio配置OpenCV开发环境

软硬件环境

  • Macbook Pro MGX 72
  • Android studio 1.0.2
  • OpenCV 2.4.10
  • 红米Note增强版

下载OpenCV

本文中使用的是2.4.10版本,从http://opencv.org/downloads.html下载zip包,解压备用

新建android工程

这个不用说,一步一步跟着向导做就行了,我这里取名HandDetection

导入OpenCV

Android Studio --> File --> Import Module,选择解压后的OpenCV-2.4.10-android-sdk/sdk/java
导入完成以后,会在工程HandDetection根目录下生成目录openCVLibrary2410

修改openCVLibrary2410下的build.gradle

修改compileSdkVersion、buildToolsVersion、minSdkVersion、targetSdkVersion,它们的值与工程下的build.gradle中的相应字段一致,否则系统会报错

增加模块依赖

Android Studio --> File -->Project Structure -->Dependencies

点击下方的 "+" 图标,将openCVLibrary2410勾选

创建jniLibs目录

将解压后的OpenCV-2.4.10-android-sdk/sdk/native/libs目录拷贝到工程下的app/src/main目录下,并重命名为jniLibs

测试

在MainActivity里import个OpenCV包看看是否可以自动导入

参考文献

1 http://opencv.org
2 http://stackoverflow.com/questions/27406303/opencv-in-android-studio