Reference
Introduction
- Check Android Version
- Most of Example does not run completely on Lollipop because native camera are not supported by OpenCV 2.4.10. libnative_camera_r5.0.0.so does not exist yet.
- Download Android source code and compile it
- For full build including "OpenCV Manager(or Engine)" android platform source tree is needed. Check my previous post (http://jylee-world.blogspot.kr/2013/11/android-platform-nexus-4-rooting.html)
- We get opencv_engine.apk(including libOpenCVEngine.so and libOpenCVEngine_jni.so) by setting source tree.
- Download android NDK and set ANDROID_NDK
- Download android SDK and set ANDROID_SDK
- Setup for cmake (explained in detail in the next sections)
- Modify cmake_android_arm.sh
- Combine cmake_android_service.sh)
- Apply minor source modifications (explained in detail in the next sections)
- cmake
- make
I use opencv-2.4.10-release, android-ndk-r9d(NDK), adt-bundle-linux-x86_64-20140702(SDK), android-4.4.2_r1 (Android Source)
Prerequisite
Unfortunately the following list is not complete.
build-essentilal cmake ant ...blah blah
Create platform_source.properties file in Android source tree
When cmake start to compile, opencv-2.4.10/modules/androidcamera/CMakeLists.txt needs this file to parse ${ANDROID_VERSION}. I use 4.4 instead of 4.4.2 because opencv-2.4.10 source code does not support 4.4.2.
cat ./android-4.4.2_r1/development/sdk/platform_source.properties
Pkg.Desc=Android SDK Platform 4.4
Pkg.UserSrc=false
Platform.Version=4.4
Platform.CodeName=KitKat
Pkg.Revision=1
AndroidVersion.ApiLevel=19
AndroidVersion.CodeName=kitkat
Layoutlib.Api=10
Layoutlib.Revision=1
Platform.MinToolsRev=22
Generating Makefines using cmake
There are some scripts for building opencv for android in directory ./platforms/scripts. Documents such as (http://answers.opencv.org/question/3699/building-android-manager-from-git-repository/ ) recommend to use ./platforms/scripts/cmake_android_arm.sh for arm android machines. But this scripts is not complete. I use the following option for my NEXUS4 machine. (I don't like to follow auto parsing by scripts.)
-DANDROID_ABI="armeabi-v7a with NEON"
-DANDROID_TOOLCHAIN_NAME="arm-linux-androideabi-4.8"
-DANDROID_NATIVE_API_LEVEL=19
And I add the following options for building OpenCV Manager.
-DBUILD_ANDROID_SERVICE=ON
-DBUILD_ANDROID_PACKAGE=ON
-DANDROID_SOURCE_TREE=<my android platform directory>
-DANDROID_PRODUCT=mako /* for NEXUX4 */
And options for building camera. This is not required.
-DBUILD_ANDROID_CAMERA_WRAPPER=ON
So my final script is ...
cmake -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DCMAKE_TOOLCHAIN_FILE=../android/android.toolchain.cmake \
-DANDROID_ABI="armeabi-v7a with NEON" \
-DANDROID_TOOLCHAIN_NAME="arm-linux-androideabi-4.8" \
-DANDROID_NATIVE_API_LEVEL=19 \
-DBUILD_ANDROID_CAMERA_WRAPPER=ON \
-DBUILD_ANDROID_SERVICE=ON \
-DBUILD_ANDROID_PACKAGE=ON \
-DANDROID_SOURCE_TREE=/home/rofox/work/android/android-4.4.2_r1/platform \
-DANDROID_PRODUCT=mako $@ ../..
Code Change for package setup
Even though you build your own libnative_camera_rX.X.X.so, unless you modify CMakeLists.txt in platforms/android/package prebuilt libraries in 3rdparty/lib/armeabi-v7a/lib*.so are copied to OpenCV_2.4.10_binary_pack_armv7a_neon-release-unsigned.apk instead of yours. The following code is my own setup.
diff --git a/platforms/android/package/CMakeLists.txt b/platforms/android/package/CMakeLists.txt
index b48a55a..4770fdb 100644
--- a/platforms/android/package/CMakeLists.txt
+++ b/platforms/android/package/CMakeLists.txt
@@ -79,7 +79,9 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E remove ${android_proj_target_files}
COMMAND ${CMAKE_COMMAND} -E make_directory "${PACKAGE_DIR}/src"
COMMAND ${CMAKE_COMMAND} -E make_directory "${PACKAGE_DIR}/libs/${ANDROID_NDK_ABI_NAME}/"
- ${CAMERA_LIB_COMMANDS}
+ #${CAMERA_LIB_COMMANDS}
+ COMMAND ${CMAKE_COMMAND} -E copy "${OpenCV_BINARY_DIR}/lib/${ANDROID_NDK_ABI_NAME}/libopencv_info.so" "${PACKAGE_DIR}/libs/${ANDROID_NDK_ABI_NAME}/"
+ COMMAND ${CMAKE_COMMAND} -E copy "${OpenCV_BINARY_DIR}/lib/${ANDROID_NDK_ABI_NAME}/libnative_camera_r${ANDROID_VERSION}.so" "${PACKAGE_DIR}/libs/${ANDROID_NDK_ABI_NAME}/"
COMMAND ${CMAKE_COMMAND} -E copy "${opencv_java_location}" "${PACKAGE_DIR}/libs/${ANDROID_NDK_ABI_NAME}/"
COMMAND ${ANDROID_EXECUTABLE} --silent update project --path "${PACKAGE_DIR}" --target "${android_proj_sdk_target}" --name "${target_name}"
COMMAND ${ANT_EXECUTABLE} -q -noinput -k release
Signing OpenCV_2.4.10_binary_pack_armv7a_neon-release-unsigned.apk
If you try "adb install OpenCV_2.4.10_binary_pack_armv7a_neon-release-unsigned.apk" without any manipulation, you will fail with the following message.
$ adb install OpenCV_2.4.10_binary_pack_armv7a_neon-release-unsigned.apk
2823 KB/s (6458213 bytes in 2.233s)
pkg: /data/local/tmp/OpenCV_2.4.10_binary_pack_armv7a_neon-release-unsigned.apk
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]
Generated Binary pack package is not signed in release mode. I do not
know yet How to build DEBUG mode without release mode signing. Anyway it
is easy to sign this package. I prefer using command line to GUI tool.
Use keytool to generate keystore, which is located in Java SDK tools.
$ keytool -genkey -v -keystore ~/myrelease.keystore -alias android_sign -keyalg RSA -keysize 2048 -validity 10000
Enter keystore password:
Re-enter new password:
What is your first and last name?
[Unknown]: <type your_name>
What is the name of your organizational unit?
[Unknown]: <type your organization unit>
What is the name of your organization?
[Unknown]: <type your organization>
What is the name of your City or Locality?
[Unknown]: <type your city>
What is the name of your State or Province?
[Unknown]: <type your state>
What is the two-letter country code for this unit?
[Unknown]: <type your country code, in my case 82 for korea>
Is CN=<your_name>, OU=<your unit>, O=<your organization>, L=<your city>, ST=<your state>, C=<your country code> correct?
[no]: yes
Generating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 10,000 days
for: CN=<your_name>, OU=<your unit>, O=<your organization>,
L=<your city>, ST=<your state>, C=<your country code>
Enter key password for <android_sign>
(RETURN if same as keystore password):
Re-enter new password:
[Storing <home_dir>/myrelease.keystore]
After then sign using the generated myrelease. keystore
$ jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ~/myrelease.keystore OpenCV_2.4.10_binary_pack_armv7a_neon-release-unsigned.apk android_sign
Enter Passphrase for keystore:
adding: META-INF/MANIFEST.MF
adding: META-INF/ANDROID_.SF
adding: META-INF/ANDROID_.RSA
signing: res/drawable/icon.png
signing: AndroidManifest.xml
signing: resources.arsc
signing: classes.dex
signing: lib/armeabi-v7a/libnative_camera_r4.0.3.so
signing: lib/armeabi-v7a/libnative_camera_r4.2.0.so
signing: lib/armeabi-v7a/libnative_camera_r3.0.1.so
signing: lib/armeabi-v7a/libopencv_java.so
signing: lib/armeabi-v7a/libnative_camera_r2.3.3.so
signing: lib/armeabi-v7a/libnative_camera_r2.2.0.so
signing: lib/armeabi-v7a/libnative_camera_r4.1.1.so
signing: lib/armeabi-v7a/libnative_camera_r4.3.0.so
signing: lib/armeabi-v7a/libnative_camera_r4.4.0.so
signing: lib/armeabi-v7a/libnative_camera_r4.0.0.so
jar signed.
Warning:
No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (2042-06-19) or after any future revocation date.
Verification is ...
$ jarsigner -verify -verbose -certs OpenCV_2.4.10_binary_pack_armv7a_neon-release-unsigned.apk
s 1286 Sun Feb 01 20:43:14 KST 2015 META-INF/MANIFEST.MF
...
...
[certificate is valid from 2/1/15 8:41 PM to 6/19/42 8:41 PM]
[CertPath not validated: Path does not chain with any of the trust anchors]
s = signature was verified
m = entry is listed in manifest
k = at least one certificate was found in keystore
i = at least one certificate was found in identity scope
jar verified.
Warning:
This jar contains entries whose certificate chain is not validated.
This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (2042-06-19) or after any future revocation date.
Now you can install using "adb install"
Minor Corrections
I found some errors. These are maybe caused by Android Source Version mismatch. But I try to correct them by myself. Most of them are INCLUDE directory setup and undefined LOG functions. They are easy to resolve.
diff --git a/modules/androidcamera/camera_wrapper/CMakeLists.txt b/modules/androidcamera/camera_wrapper/CMakeLists.txt
index d08e2c4..b8d9326 100644
--- a/modules/androidcamera/camera_wrapper/CMakeLists.txt
+++ b/modules/androidcamera/camera_wrapper/CMakeLists.txt
@@ -2,7 +2,7 @@ SET (the_target native_camera_r${ANDROID_VERSION})
project(${the_target})
-link_directories("${ANDROID_SOURCE_TREE}/out/target/product/generic/system/lib")
+link_directories("${ANDROID_SOURCE_TREE}/out/target/product/${ANDROID_PRODUCT}/system/lib")
if (ANDROID_VERSION VERSION_LESS "4.1")
INCLUDE_DIRECTORIES(BEFORE
diff --git a/platforms/android/package/CMakeLists.txt b/platforms/android/package/CMakeLists.txt
index b48a55a..4770fdb 100644
--- a/platforms/android/package/CMakeLists.txt
+++ b/platforms/android/package/CMakeLists.txt
@@ -79,7 +79,9 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E remove ${android_proj_target_files}
COMMAND ${CMAKE_COMMAND} -E make_directory "${PACKAGE_DIR}/src"
COMMAND ${CMAKE_COMMAND} -E make_directory "${PACKAGE_DIR}/libs/${ANDROID_NDK_ABI_NAME}/"
- ${CAMERA_LIB_COMMANDS}
+ #${CAMERA_LIB_COMMANDS}
+ COMMAND ${CMAKE_COMMAND} -E copy "${OpenCV_BINARY_DIR}/lib/${ANDROID_NDK_ABI_NAME}/libopencv_info.so" "${PACKAGE_DIR}/libs/${ANDROID_NDK_ABI_NAME}/"
+ COMMAND ${CMAKE_COMMAND} -E copy "${OpenCV_BINARY_DIR}/lib/${ANDROID_NDK_ABI_NAME}/libnative_camera_r${ANDROID_VERSION}.so" "${PACKAGE_DIR}/libs/${ANDROID_NDK_ABI_NAME}/"
COMMAND ${CMAKE_COMMAND} -E copy "${opencv_java_location}" "${PACKAGE_DIR}/libs/${ANDROID_NDK_ABI_NAME}/"
COMMAND ${ANDROID_EXECUTABLE} --silent update project --path "${PACKAGE_DIR}" --target "${android_proj_sdk_target}" --name "${target_name}"
COMMAND ${ANT_EXECUTABLE} -q -noinput -k release
diff --git a/platforms/android/service/engine/CMakeLists.txt b/platforms/android/service/engine/CMakeLists.txt
index b1cac93..7dd9b64 100644
--- a/platforms/android/service/engine/CMakeLists.txt
+++ b/platforms/android/service/engine/CMakeLists.txt
@@ -71,6 +71,7 @@ include_directories(
"${ANDROID_SOURCE_TREE}/frameworks/base/include"
"${ANDROID_SOURCE_TREE}/system/core/include"
"${ANDROID_SOURCE_TREE}/frameworks/base/core/jni"
+ "${ANDROID_SOURCE_TREE}/frameworks/native/include"
)
add_library(${engine}_jni SHARED ${engine_jni_files})
diff --git a/platforms/android/service/engine/jni/BinderComponent/BnOpenCVEngine.cpp b/platforms/android/service/engine/jni/BinderComponent/BnOpenCVEngine.cpp
index fccb329..bda5364 100644
--- a/platforms/android/service/engine/jni/BinderComponent/BnOpenCVEngine.cpp
+++ b/platforms/android/service/engine/jni/BinderComponent/BnOpenCVEngine.cpp
@@ -5,6 +5,8 @@
#include
#include
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+
using namespace android;
BnOpenCVEngine::~BnOpenCVEngine()
diff --git a/platforms/android/service/engine/jni/BinderComponent/HardwareDetector.cpp b/platforms/android/service/engine/jni/BinderComponent/HardwareDetector.cpp
index b842987..5ebfefa 100644
--- a/platforms/android/service/engine/jni/BinderComponent/HardwareDetector.cpp
+++ b/platforms/android/service/engine/jni/BinderComponent/HardwareDetector.cpp
@@ -5,6 +5,7 @@
#include "StringUtils.h"
#include
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
using namespace std;
int GetCpuID()
diff --git a/platforms/android/service/engine/jni/BinderComponent/OpenCVEngine.cpp b/platforms/android/service/engine/jni/BinderComponent/OpenCVEngine.cpp
index 6c17e22..aac0f5e 100644
--- a/platforms/android/service/engine/jni/BinderComponent/OpenCVEngine.cpp
+++ b/platforms/android/service/engine/jni/BinderComponent/OpenCVEngine.cpp
@@ -11,6 +11,11 @@
#include
#include
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+
using namespace android;
const int OpenCVEngine::Platform = DetectKnownPlatforms();
diff --git a/platforms/android/service/engine/jni/JNIWrapper/JavaBasedPackageManager.cpp b/platforms/android/service/engine/jni/JNIWrapper/JavaBasedPackageManager.cpp
index d202d65..4c72267 100644
--- a/platforms/android/service/engine/jni/JNIWrapper/JavaBasedPackageManager.cpp
+++ b/platforms/android/service/engine/jni/JNIWrapper/JavaBasedPackageManager.cpp
@@ -5,6 +5,11 @@
#undef LOG_TAG
#define LOG_TAG "JavaBasedPackageManager"
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+
using namespace std;
JavaBasedPackageManager::JavaBasedPackageManager(JavaVM* JavaMashine, jobject MarketConnector):
diff --git a/platforms/android/service/engine/jni/JNIWrapper/OpenCVEngine_jni.cpp b/platforms/android/service/engine/jni/JNIWrapper/OpenCVEngine_jni.cpp
index dac4916..6c0f0d6 100644
--- a/platforms/android/service/engine/jni/JNIWrapper/OpenCVEngine_jni.cpp
+++ b/platforms/android/service/engine/jni/JNIWrapper/OpenCVEngine_jni.cpp
@@ -10,6 +10,11 @@
#undef LOG_TAG
#define LOG_TAG "OpenCVEngine/JNI"
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+
using namespace android;
sp OpenCVEngineBinder = NULL;
diff --git a/platforms/android/service/engine/jni/JNIWrapper/OpenCVLibraryInfo.cpp b/platforms/android/service/engine/jni/JNIWrapper/OpenCVLibraryInfo.cpp
index e7dc6d2..36646cb 100644
--- a/platforms/android/service/engine/jni/JNIWrapper/OpenCVLibraryInfo.cpp
+++ b/platforms/android/service/engine/jni/JNIWrapper/OpenCVLibraryInfo.cpp
@@ -3,6 +3,11 @@
#include
#include
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+
JNIEXPORT jlong JNICALL Java_org_opencv_engine_OpenCVLibraryInfo_open
(JNIEnv * env, jobject, jstring str)
{
diff --git a/platforms/android/service/engine/jni/NativeService/CommonPackageManager.cpp b/platforms/android/service/engine/jni/NativeService/CommonPackageManager.cpp
index 5c5022f..ce71be8 100644
--- a/platforms/android/service/engine/jni/NativeService/CommonPackageManager.cpp
+++ b/platforms/android/service/engine/jni/NativeService/CommonPackageManager.cpp
@@ -9,6 +9,11 @@
#undef LOG_TAG
#define LOG_TAG "CommonPackageManager"
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+
using namespace std;
vector CommonPackageManager::GetInstalledVersions()
diff --git a/platforms/android/service/engine/jni/NativeService/PackageInfo.cpp b/platforms/android/service/engine/jni/NativeService/PackageInfo.cpp
index ca364b4..a49bb27 100644
--- a/platforms/android/service/engine/jni/NativeService/PackageInfo.cpp
+++ b/platforms/android/service/engine/jni/NativeService/PackageInfo.cpp
@@ -8,6 +8,11 @@
#include
#include
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+
using namespace std;
map PackageInfo::InitPlatformNameMap()
diff --git a/platforms/android/service/engine/jni/Tests/HardwareDetectionTest.cpp b/platforms/android/service/engine/jni/Tests/HardwareDetectionTest.cpp
index 8e7dfab..f8b5604 100644
--- a/platforms/android/service/engine/jni/Tests/HardwareDetectionTest.cpp
+++ b/platforms/android/service/engine/jni/Tests/HardwareDetectionTest.cpp
@@ -147,10 +147,12 @@ TEST(CpuID, CheckMips)
}
#endif
#else
+#if defined(USE_TEGRA_HW_DETECTOR)
TEST(TegraDetector, Detect)
{
EXPECT_TRUE(DetectTegra() != 0);
}
+#endif
TEST(CpuID, CheckArmV7)
{
diff --git a/platforms/android/service/engine/jni/Tests/OpenCVEngineTest.cpp b/platforms/android/service/engine/jni/Tests/OpenCVEngineTest.cpp
index b0bb6d5..6f4c8e8 100644
--- a/platforms/android/service/engine/jni/Tests/OpenCVEngineTest.cpp
+++ b/platforms/android/service/engine/jni/Tests/OpenCVEngineTest.cpp
@@ -13,6 +13,11 @@
#include
#include
+#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
+#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__))
+#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__))
+#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
+
using namespace android;
class ServiceStarter
No comments:
Post a Comment