如何在Java Android Studio项目中使用.so共享库

7
我已经在过去的几天里一直在解决这个问题。我正在尝试将C/C++流媒体服务器live555 (http://www.live555.com/) 作为Java Android Studio项目中的库来使用。我已经能够使用ndk-build创建一组.so文件,但我找不到任何文档来说明如何在我的Java应用程序中使用该库。以下是我的设置:
  • Windows 8.1 64位
  • Oracle JDK 1.8
  • Android Studio 1.5.1
  • Gradle 1.5.0
  • Build Tools 23.0.2
迄今为止所采取的步骤:
  1. Create a standard Android application using Android Studio.
  2. Right click on the app module in the Project explorer and choose New | Folder | JNI Folder from the context menu.
  3. Download the live555 sources from http://www.live555.com/liveMedia/public/ selecting the live555-latest.tar.gz file.
  4. Extract the sources to the JNI folder, such that you now have a folder structure like:
    $PROJECT_DIR
    |--app
    |--|--src
    |--|--|--main
    |--|--|--|--jni
    |--|--|--|--|--live
    where the live folder contains the live555 sources.
  5. Inside the jni folder above, create the Android.mk and Application.mk files. The Application.mk file contains:

    APP_OPTM := release
    APP_ABI := armeabi armeabi-v7a
    APP_PLATFORM := android-21
    APP_STL := stlport_shared
    

    The Android.mk file contains:

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := live555
    
    LOCAL_SRC_FILES := \
    live\BasicUsageEnvironment\BasicHashTable.cpp                \
    live\BasicUsageEnvironment\BasicTaskScheduler0.cpp           \
    ...All of the rest of the .c and .cpp files
    
    LOCAL_C_INCLUDES := \
        $(LOCAL_PATH)\live \
        $(LOCAL_PATH)\live\BasicUsageEnvironment\include \
        $(LOCAL_PATH)\live\BasicUsageEnvironment \
        $(LOCAL_PATH)\live\UsageEnvironment\include \
        $(LOCAL_PATH)\live\UsageEnvironment \
        $(LOCAL_PATH)\live\groupsock\include \
        $(LOCAL_PATH)\live\groupsock \
        $(LOCAL_PATH)\live\liveMedia\include \
        $(LOCAL_PATH)\live\liveMedia \
    
    LOCAL_CPPFLAGS += -fPIC -fexceptions -DXLOCALE_NOT_USED=1 -DNULL=0 -DNO_SSTREAM=1 -UIP_ADD_SOURCE_MEMBERSHIP
    
    include $(BUILD_SHARED_LIBRARY)
    
  6. In my $PROJECT_DIR\gradle.properties file, I've included the line android.useDeprecatedNdk=true

  7. In $PROJECT_DIR\local.properties, I have:

    ndk.dir=C\:\\Users\\user\\AppData\\Local\\Android\\ndk
    sdk.dir=C\:\\Users\\user\\AppData\\Local\\Android\\sdk
    
  8. In my $PROJECT_DIR\app\build.gradle file I have:

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 23
        buildToolsVersion "23.0.2"
    
        defaultConfig {
            applicationId "com.company.android.myapp"
            minSdkVersion 21
            targetSdkVersion 23
            versionCode 1
            versionName "1.0"
    
            ndk {
                moduleName "live555"
            }
    
            sourceSets.main {
                jni.srcDirs = []
                jniLibs.srcDir "src\\main\\libs"
            }
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
    
    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        testCompile 'junit:junit:4.12'
        compile 'com.android.support:appcompat-v7:23.1.1'
    }
    
  9. I then run ndk-build in the $PROJECT_DIR\app\src\main\jni folder.

ndk-build 命令会生成以下文件夹结构/文件输出:
$PROJECT_DIR
|--app
|--|--src
|--|--|--main
|--|--|--|--libs
|--|--|--|--|--armeabi
|--|--|--|--|--|--liblive555.so
|--|--|--|--|--|--libstlport_shared.so
|--|--|--|--|--armeabi-v7a
|--|--|--|--|--|--liblive555.so
|--|--|--|--|--|--libstlport_shared.so
|--|--|--|--obj
|--|--|--|--|--local
|--|--|--|--|--|--armeabi
|--|--|--|--|--|--|--objs
|--|--|--|--|--|--|--liblive555.so
|--|--|--|--|--|--|--libstlport_shared.so
|--|--|--|--|--|--armeabi-v7a
|--|--|--|--|--|--|--objs
|--|--|--|--|--|--|--liblive555.so
|--|--|--|--|--|--|--libstlport_shared.so

当我从 Build | Make Project 菜单选项构建项目时,Android 视图中的项目结构如下所示:
app
|--manifests
|--java
|--jniLibs
|--|--armeabi
|--|--|--liblive555.so
|--|--|--libstlport_shared.so
|--|--armeabi-v7a
|--|--|--liblive555.so
|--|--|--libstlport_shared.so
|--res

我从中添加了一个 Live555Ndk.java 文件来引用 live555 库。它包含以下内容:

package com.company.android.myapp;

public class Live555Ndk {

    static {
        System.loadLibrary("live555");
    }

}

然而,我不知道如何开始在现有的共享对象上创建对象实例和调用live555库中的方法。是否有人能指点一下我正确的方向?

感谢任何见解。

更新 02/15/2016

好的,我根据mcwise的建议从我的app\build.gradle文件中删除了ndk {}块。

我想我现在已经理解了这个工作原理,但我仍然无法引用live555库。我启动了一个新的Android项目,其中包含一个活动和相应的布局文件。我添加了一个jniLibs文件夹,并将armeabi\liblive555.so等文件复制到该文件夹中。我添加了之前提到的Live555Ndk.java文件,其中包括静态构造函数和对SystemloadLibrary("live555");的调用。我还添加了一个调用public native boolean isThisMediaSession();的语句。然后,我使用javah生成了一个位于jni文件夹内的头文件。然后我创建了相应的.cpp文件来创建方法实现。然而,我不能包含来自liblive555.so的任何头文件。就像Android Studio甚至没有意识到live555库的存在一样。因此,我不能有像#include <live555/MediaSession.hh>这样的语句。我错过了其他步骤吗?这个Android项目只有.so文件,没有源代码。我需要将live555源代码添加到jni文件夹中吗?


你的 Android.mkApplication.mk 内容被交换了。可能只是在这个文本中,而不是在现实生活中。 - Alex Cohn
请检查 https://dev59.com/ClXTa4cB1Zd3GeqP361B#5520886 是否解决了您的问题。关键是您需要一些包装器来建立您(Java)应用和live555库之间的通信。 - Alex Cohn
当你说“所以,我不能有这样的一行:#include <live555/MediaSession.hh>”时,问题不是很清楚。是否有错误消息?代码是否无法编译?您确定头文件的路径正确吗? - Francesca Nannizzi
@bullsy,我正在尝试解决的问题是如何使Android Studio或gradle知道live555及其头文件的存在。我拉取了hello-gl2 NDK示例的源代码,并且成功地使它工作。然而,我不明白他们是如何能够只需将ldLibs.addAll(["log", "GLESv2"])添加到android.ndk {}块中,而gradle就知道从哪里获取这些库,更重要的是头文件。我该如何才能在访问live555库的.cpp文件中说#include "MediaSession.hh" - Rob Droid
我明白了 - 这些示例依赖于一些实验性的功能,例如ndk{}块。我更新了我的答案,展示了如何修改Android.mk文件。 - Francesca Nannizzi
显示剩余2条评论
1个回答

4

请查看由Google开发的许多Android NDK示例。你可以在这里找到它们。

hello-gl2示例是一个很好的起点。

gl_code.cpp向你展示如何创建可以从Java调用的JNI代码。特别注意代码的这一部分,它定义了两个方法并将它们暴露给Java层:

extern "C" {
  JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env,
    jobject obj,  jint width, jint height);
  JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, 
    jobject obj);
};

JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_init(JNIEnv * env, jobject obj,  jint width, jint height)
{
  setupGraphics(width, height);
}

JNIEXPORT void JNICALL Java_com_android_gl2jni_GL2JNILib_step(JNIEnv * env, jobject obj)
{
  renderFrame();
}

GL2JNILib.java展示了如何从Java中调用gl_code.cpp中定义的方法。

public class GL2JNILib {

  static {
    System.loadLibrary("gl2jni");
   }

  /**
   * @param width the current view width
   * @param height the current view height
   */
   public static native void init(int width, int height);
   public static native void step();
}

更新:

要构建一个依赖于live555库的C++模块,您需要将以下部分添加到Android.mk中:

include $(CLEAR_VARS)
LOCAL_MODULE := your_module
LOCAL_SRC_FILES := your_module_file.cpp
LOCAL_SHARED_LIBRARIES := live555
include $(BUILD_SHARED_LIBRARY)

请参考以下文档:


请查看我上面更新的帖子。我对此有了更深入的理解,但是我无法包含我已添加到应用程序jniLibs文件夹中的live555库的任何头文件。就像Android Studio根本不知道那个库一样。谢谢您可能能够提供的任何额外帮助。 - Rob Droid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接