Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Do You Use .so Shared Library in Java Android Studio Project

I've been working at this problem for the past couple of days. I am trying to use live555 (http://www.live555.com/), a C/C++ streaming media server, as a library in a Java Android Studio project. I have been able to use ndk-build to create a set of .so files, but I cannot find any documentation for how to now utilize the library within my Java application. Here is my setup:

  • Windows 8.1 64-bit
  • Oracle JDK 1.8
  • Android Studio 1.5.1
  • Gradle 1.5.0
  • Build Tools 23.0.2

Steps taken to get where I am thus far:

  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.

The ndk-build command results in the following folder structure/file output:
$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

When I build the project from the Build | Make Project menu option, I have a Project structure in the Android view that looks like:
app
|--manifests
|--java
|--jniLibs
|--|--armeabi
|--|--|--liblive555.so
|--|--|--libstlport_shared.so
|--|--armeabi-v7a
|--|--|--liblive555.so
|--|--|--libstlport_shared.so
|--res

I addedd a Live555Ndk.java file to my project from which to begin referencing the live555 library. It contains:

package com.company.android.myapp;

public class Live555Ndk {

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

}

However, I do not know how to start creating object instances and calling methods on the live555 library now that I have the shared objects. Can anyone point me in the right direction?

Thank you for any insight.

UPDATE 02/15/2016

OK, I've removed the ndk {} block from my app\build.gradle file based on the below advice of mcwise.

I think I've wrapped my mind around how this works now, but I'm still not able to reference the live555 library. I started a new Android project with with a single activity and corresponding layout file. I added a jniLibs folder and copied in the armeabi\liblive555.so etc files into that folder. I added in the Live555Ndk.java file I previously mentioned with the static constructor and call to SystemloadLibrary("live555");. I also added a call to public native boolean isThisMediaSession();. I then used javah to generate a header file inside a jni folder. I then created the corresponding .cpp file to create the method implementation. However, I cannot include any header file from liblive555.so. It's like Android Studio is not even aware of the existence of the live555 library. So, I cannot have a line such as #include <live555/MediaSession.hh>. Am I missing an additional step? This Android project only has the .so files, not the sources. Do I need to add the live555 sources to the jni folder?

like image 931
Rob Droid Avatar asked Feb 12 '16 17:02

Rob Droid


1 Answers

Check out the many Android NDK samples developed by Google. You can find them here.

The hello-gl2 example is a good place to start.

gl_code.cpp shows you how to create JNI code which can be called from Java. Pay particular attention to this part of the code, which defines two methods and makes them visible to the Java layer:

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 shows you how to call the methods defined in gl_code.cpp from Java.

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();
}

UPDATE:

To build a C++ module which relies on the live555 library, you'll need to add the following section to Android.mk:

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

See this documentation for reference:

  • Android.mk (LOCAL_SHARED_LIBRARIES)
  • Using prebuilt libraries (syntax is the same for downstream modules)
like image 97
Francesca Nannizzi Avatar answered Sep 29 '22 12:09

Francesca Nannizzi