I have a question.
What would I do I use the OpenJPEG on Android?
(I'm "j2k_to_image" is primarily want to use.)
I would like you to tell me how do I write a makefile.
Thanks in advance.
I was able to build + use OpenJPEG to load JPEG2000 images into my app using the following outline. You'll have to customize it according to your environment and how you want to utilize it. My answer provides rough guidelines along with specific answers to the major stumbling blocks I encountered (what my Android.mk and Application.mk files should be, as well as how to deal with the fact that the OpenJPEG library requires cmake).
Since we're talking OpenJPEG, this answer assumes you are familiar with and plan to use the Android NDK for your app. It also assumes you are using the Eclipse version of the Android IDE. The answer also assumes you are familiar with how static libraries work with the Android NDK and how to reference them into your main app. You can extend my answer below to create a shared library or to include the code directly into your app. If you are unfamiliar with these prerequisites, stackoverflow and Google can help.
I was successful with Android NDK r8e and OpenJPEG 2.0.0.
Steps:
Download and expand OpenJPEG 2.0.0 from http://www.openjpeg.org/index.php?menu=download
Create a native project in Eclipse. I created a project that allows me to utilize OpenJPEG as a static library
Within the jni folder of my project, I utilized the following for my Application.mk and my Android.mk files. See below.
Create a custom opj_config.h. OpenJPEG is meant to be compiled with cmake. I didn't want to deal with it for a number of reasons -- none of my other content relies on it (so it would add another layer of complexity), I'm on Windows (which doesn't have it built-in, and this stackoverflow post references android-cmake, the docs for android-cmake indicate that it may not work on Windows). See below for my opj_config.h. It should work for you. Make sure you put it somewhere in your include paths.
Build the Android NDK static library project
Reference your static library into your main project
With that, I was able to successfully load a JPEG2000 image into my Android NDK-based app.
Application.mk:
APP_ABI := all
APP_PLATFORM := android-9
APP_MODULES := openjpeg
Android.mk (you will have to customize all of the paths below):
# Taken from https://stackoverflow.com/questions/4036191/sources-from-subdirectories-in-makefile
# The trailing slash is required.
rwildcard=$(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2))
ALL_CPPS := $(call rwildcard,../../openjpeg-2.0.0/src/lib/openjp2,*.c)
ALL_CPPS += $(call rwildcard,../../openjpeg-2.0.0/src/lib/openjpip,*.c)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := openjpeg
LOCAL_C_INCLUDES := /path/to/openjpeg-2.0.0/src/lib/openjp2
LOCAL_SRC_FILES := $(addprefix ../,$(ALL_CPPS))
LOCAL_CFLAGS = -DUSE_JPIP
include $(BUILD_STATIC_LIBRARY)
opj_config.h (normally cmake creates this for the platform you're building for -- but as I mention above, I didn't want to deal with cmake, so I hand-created this file):
#ifndef OPJ_CONFIG_H
#define OPJ_CONFIG_H
#define OPJ_PACKAGE_VERSION "2.0.0"
#define HAVE_INTTYPES_H 1
#define HAVE_MEMORY_H 1
#define HAVE_STDINT_H 1
#ifndef HAVE_STDLIB_H // I had a conflict with this somewhere else in my project -- good form dictates that I should probably ifndef guard the other defines in this file as well....that is a TODO for later
#define HAVE_STDLIB_H 1
#endif
#define HAVE_STRINGS_H 1
#define HAVE_STRING_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_UNISTD_H 1
// I'm not utilizing libpng or libtiff, so don't set these
//#cmakedefine HAVE_LIBPNG #HAVE_LIBPNG#
//#cmakedefine HAVE_PNG_H #HAVE_PNG_H#
//#cmakedefine HAVE_LIBTIFF #HAVE_LIBTIFF#
//#cmakedefine HAVE_TIFF_H #HAVE_TIFF_H#
#define HAVE_SSIZE_T 1
//#cmakedefine _LARGEFILE_SOURCE
//#cmakedefine _LARGE_FILES
//#cmakedefine _FILE_OFFSET_BITS #_FILE_OFFSET_BITS#
#define HAVE_FSEEKO 1
//#cmakedefine HAVE_LIBLCMS1
//#cmakedefine HAVE_LIBLCMS2
//#cmakedefine HAVE_LCMS1_H
//#cmakedefine HAVE_LCMS2_H
#endif // OPJ_CONFIG_H
Related
I'm writing an app that should use functions from tinyalsa through ndk, I just want to call functions defined by tinyalsa like pcm_open() from my native functions implementations.
I have tried following the documentation about using prebuilt libraries in Android/ndk/docs/PREBUILTS.html but I can't get it working.
Could you please tell how could I do it?
Thanks
I could do it, the process is the next:
Copy tinyalsa.so to ~/Android/ndk/platforms/android-18/arch-arm/usr/lib
Copy asoundlib.h to ~/Android/ndk/platforms/android-18/arch-arm/usr/include
Platform-18 is the one I'm using. It can be specified in Application.mk with the line
APP_PLATFORM := android-18
After adding it to the ndk platform include it in the file where the native functions are implemented
#include <asoundlib.h>
Tell the compiler that we are going to need this library. In Android.mk
LOCAL_LDLIBS := -ltinyalsa
This worked for me :)
I am building AOSP for a device. Is there a way to get the current AOSP version at native code compile time? I am looking for something similar to the LINUX_VERSION_CODE and KERNEL_VERSION(X,Y,Z) directives in Linux. More specifically, I would like to do something that looks like this in one of my own AOSP add-on projects:
#if (ANDROID_VERSION_CODE >= ANDROID_VERSION(4,2,1))
... compile something ...
#else
... compile something else...
#endif
Probably, you can use PLATFORM_VERSION and/or PLATFORM_SDK_VERSION, please see version_defaults.mk
The PLATFORM_VERSION is defined in the AOSP build directory:
build/core/version_defaults.mk:
ifeq "" "$(PLATFORM_VERSION)"
# This is the canonical definition of the platform version,
# which is the version that we reveal to the end user.
# Update this value when the platform version changes (rather
# than overriding it somewhere else). Can be an arbitrary string.
PLATFORM_VERSION := 5.1
endif
In a makefile of your product (or anywhere else) define the following make variables and pass them as macros to the compiler:
# Passing Android version to C compiler
PLATFORM_VERSION_MAJOR := $(word 1, $(subst ., ,$(PLATFORM_VERSION)))
PLATFORM_VERSION_MINOR := $(word 2, $(subst ., ,$(PLATFORM_VERSION)))
PLATFORM_VERSION_REVISION := $(word 3, $(subst ., ,$(PLATFORM_VERSION)))
COMMON_GLOBAL_CFLAGS += -DPLATFORM_VERSION_MAJOR=$(PLATFORM_VERSION_MAJOR) \
-DPLATFORM_VERSION_MINOR=$(PLATFORM_VERSION_MINOR)
ifneq ($(PLATFORM_VERSION_REVISION),)
COMMON_GLOBAL_CFLAGS += -DPLATFORM_VERSION_REVISION=$(PLATFORM_VERSION_REVISION)
endif
Define a header file with the version code:
android_version.h:
#define ANDROID_VERSION(major, minor, rev) \
((rev) | (minor << 8) | (major << 16))
#ifndef PLATFORM_VERSION_REVISION
#define PLATFORM_VERSION_REVISION 0
#endif
#define ANDROID_VERSION_CODE ANDROID_VERSION( \
PLATFORM_VERSION_MAJOR, \
PLATFORM_VERSION_MINOR, \
PLATFORM_VERSION_REVISION)
Now, to make compile time decisions based on android version simply include the android_version.h file and use pre-processer #if's.
I have started developing a very simple Android application that consists of three parts:
the Java application itself
a pre-built shared library (we'll call it libfoo)
another shared library that uses the pre-built library (we'll call it libfoowrapper)
The file system looks something like this:
jni
Android.mk
libfoo.so
foowrapper.c
The Android.mk file contains the following contents:
LOCAL_PATH := $(call my-dir)
#==============================
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILT_SHARED_LIBRARY)
#=========================
include $(CLEAR_VARS)
LOCAL_MODULE := foowrapper
LOCAL_SRC_FILES := foowrapper.c
LOCAL_SHARED_LIBRARIES := foo-prebuilt
include $(BUILD_SHARED_LIBRARY)
When I build the application in Eclipse, things seem to work fine - no errors are reported. However, when I upload the application to my Samsung Discover (running Android 4.0.4), I get the following error in the log:
03-05 21:20:27.859: E/AndroidRuntime(20324): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1936]: 102 could not load needed library 'libfoo.so.0' for 'libfoowrapper.so' (load_library[1091]: Library 'libfoo.so.0' not found)
Why is the Dalvik looking for a .so.0 file instead of a .so file? What changes do I need to make to my app to get rid of this error?
At least in the Linux world, every shared library has a special name called the soname. The soname has the prefix lib, the name of the library, the phrase .so, followed by a period and a version number that is incremented whenever the interface changes (as a special exception, the lowest-level C libraries don't start with lib). A fully-qualified soname includes as a prefix the directory it's in; on a working system a fully-qualified soname is simply a symbolic link to the shared library's real name.
Every shared library also has a real name, which is the filename containing the actual library code. The real name adds to the soname a period, a minor number, another period, and the release number. The last period and release number are optional. The minor number and release number support configuration control by letting you know exactly what version(s) of the library are installed. Note that these numbers might not be the same as the numbers used to describe the library in documentation, although that does make things easier.
Reference: Linux Standard Base
Edit:
It seems this is not an uncommon problem, haven't seen any real solutions to it, but perhaps this will get you started to finding something that works for you.
Problem with LOCAL_SRC_FILES when using PREBUILT_SHARED_LIBRARY
https://groups.google.com/forum/#!topic/android-ndk/_UhNpRJlA1k
Creating non-versioned shared libraries for android
http://www.opengis.ch/2011/11/23/creating-non-versioned-shared-libraries-for-android/
Library 'libproj.so.0' not found
https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/ai3tu0XXs88
What I want to do (high-level): use qsort_r on Android.
There is no default implementation. So I've grabbed one from BSD. Unfortunately it needs fls functions which is also unavailable on Android. So I've grabbed Apple Open Source Libc library and copied ARM implementation into an inline assembly. Now I'm getting this:
Assembler messages:
Error: selected processor does not support Thumb mode `clz r3,r0'
Error: cannot honor width suffix -- `rsb r0,r3,#32'
AFAIR ARM-6 doesn't support it in Thumb mode. So how can I force non-Thumb mode for this one file, or is pure C implementation available for fls?
(and God, why do I have to play such low-level just to have qsort_r...)
In your Android.mk file, here is how to set things up to compile thumb, arm and neon versions of your code. The assembly language source files need to have the "S" capitalized in the makefile, but the actual name doesn't need to be capitalized. The suffixes ".arm" and ".arm.neon" are only in the makefile and not part of the name (e.g. the files below are named main.c, main_asm.s, test.c and test_asm.s).
LOCAL_ARM_MODE := arm # remove this if you want thumb mode
LOCAL_ARM_NEON := true # remove this if you want armv5 mode
# this flag will allow neon intrinsics in your C files
LOCAL_CFLAGS := -mfpu=neon -march=armv7
LOCAL_SRC_FILES := \
main.c.arm \
test.c.arm.neon \
main_asm.S.arm \
test_asm.S.arm.neon \
I think I spent most of yesterday unsuccessfully wrestling with this, any help would greatly appreciated and make me extremely happy! Even a next step to try to find the root of the issue is something I'm stuck on at the moment!
I have an Android 2.2 project that's trying to reference a prebuilt LuaJIT static library but ndk-build gives me this error:
test_android.cpp:25: undefined reference to `luaL_newstate'
I built LuaJIT as liblua.a, I've placed that in the root of my JNI directory with the relevant headers. I've have one Android.mk as shown below:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := lua
LOCAL_SRC_FILES := liblua.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_CFLAGS := -Werror
LOCAL_SRC_FILES := test_android.cpp
LOCAL_LDLIBS := -llog -lGLESv2
LOCAL_STATIC_LIBRARIES := lua
include $(BUILD_SHARED_LIBRARY)
In test_andrdoid.cpp I've got this code:
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
void test()
{
lua_State* lua = lua_open();
}
This seems like a linker error, for some reason the static library file is not being correctly referenced. But, to me, the makefile seems correct.
Any help would be greatly appreciated!
To start with: is there anyway to see how everything is being linked
together and if my shared library module is really get access
to the static library?
Additional Information
Here's extra information that I think could be relevant!
Building the library
Maybe it's the static lib file that's not correct? (Is there anywhere I could download a prebuilt one to check?). I made it with this script (from the LuaJIT website). I'm using the latest stable LuaJIT, 1.1.8
NDK=/cygdrive/c/android-ndk-r8b
NDKABI=8
NDKVER=$NDK/toolchains/arm-linux-androideabi-4.4.3
NDKP=$NDKVER/prebuilt/linux-x86/bin/arm-linux-androideabi-
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm"
make linux HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF"
This builds fine and creates a liblua.a in the /src/ directory. (I ran nm on it and it lists out all the function prototypes I'd expect). I don't know if there's anything else I can do to ensure it's really a build for ARM?
NDKABI=8 means I'm targeting Android 2.2
Setting up the test Android Project
I create a brand new 2.2 android project using this command:
android create project --target 3 --name test --path . --activity TestActivity --package com.test
Target 3 maps to Android 2.2 on my system (using android list devices).
I create the jni folder and have a test_android.h and test_android.cpp. Then I use ndk-build to build them - which works fine when I'm not trying to reference LuaJIT. When I do try and use Lua I get the following error:
Full Error Message
Cygwin : Generating dependency file converter script
Compile++ thumb : test <= test_android.cpp
In file included from jni/test_android.h:3:0, from jni/test_android.cpp:2:
C:/android-ndk-r8b/platforms/android-8/arch-arm/usr/include/jni.h:592:13: note:
the mangling of 'va_list' has changed in GCC 4.4
Prebuilt : liblua.a <= jni/
StaticLibrary : libstdc++.a
SharedLibrary : libtest.so
obj/local/armeabi/objs/test/test_android.o: In function `test()':
C:\Users\Grrr\Documents\mycode\static_lib_test/jni/test_android.cpp:25: undefined reference to `luaL_newstate'
collect2: ld returned 1 exit status
/cygdrive/c/android-ndk-r8b/build/core/build-binary.mk:378: recipe for target `obj/local/armeabi/libtest.so' failed make: *** [obj/local/armeabi/libtest.so] Error 1
Most of the issues I've seen searching around are due to the local library include order, as I only have one library this shouldn't be an issue and suggests I've managed to get something more fundamental wrong :)
Update
I've since built normal Lua and added that as prebuilt static library and it works fine. I suspect its how I've built LuaJIT but I'm not sure how to correctly build it, or find a working prebuilt version.
The linking for this was fine, or at least the makefile was.
The problem was the LuaJIT library wasn't built for ARM (I used objdump -a lualib.a, to check this). I downloaded the latest LuaJIT, ran the script under linux and got an ARM library. Everything links nicely now!