diff --git a/cmake/OpenCVDetectAndroidSDK.cmake b/cmake/OpenCVDetectAndroidSDK.cmake index 38430e214e..4f26a78ece 100644 --- a/cmake/OpenCVDetectAndroidSDK.cmake +++ b/cmake/OpenCVDetectAndroidSDK.cmake @@ -274,6 +274,17 @@ macro(add_android_project target path) file(GLOB_RECURSE android_proj_jni_files "${path}/jni/*.c" "${path}/jni/*.h" "${path}/jni/*.cpp" "${path}/jni/*.hpp") ocv_list_filterout(android_proj_jni_files "\\\\.svn") + foreach(lib "opencv_java") + get_property(f TARGET ${lib} PROPERTY LOCATION) + get_filename_component(f_name ${f} NAME) + add_custom_command( + OUTPUT "${android_proj_bin_dir}/libs/${ANDROID_NDK_ABI_NAME}/${f_name}" + COMMAND ${CMAKE_COMMAND} -E copy "${f}" "${android_proj_bin_dir}/libs/${ANDROID_NDK_ABI_NAME}/${f_name}" + DEPENDS "${lib}" VERBATIM + COMMENT "Embedding ${f}") + list(APPEND android_proj_file_deps "${android_proj_bin_dir}/libs/${ANDROID_NDK_ABI_NAME}/${f_name}") + endforeach() + if(android_proj_jni_files AND EXISTS ${path}/jni/Android.mk AND NOT DEFINED JNI_LIB_NAME) # find local module name in Android.mk file to build native lib file(STRINGS "${path}/jni/Android.mk" JNI_LIB_NAME REGEX "LOCAL_MODULE[ ]*:=[ ]*.*" ) @@ -307,6 +318,7 @@ macro(add_android_project target path) # copy opencv_java, tbb if it is shared and dynamicuda if present if FORCE_EMBED_OPENCV flag is set if(android_proj_FORCE_EMBED_OPENCV) set(native_deps ${android_proj_NATIVE_DEPS}) + list(REMOVE_ITEM native_deps "opencv_java") # filter out gpu module as it is always static library on Android list(REMOVE_ITEM native_deps "opencv_gpu") if(ENABLE_DYNAMIC_CUDA) diff --git a/cmake/templates/OpenCV.mk.in b/cmake/templates/OpenCV.mk.in index 66d476b895..d85ed2bb84 100644 --- a/cmake/templates/OpenCV.mk.in +++ b/cmake/templates/OpenCV.mk.in @@ -110,6 +110,10 @@ else OPENCV_INSTALL_MODULES:=on endif +ifeq ($(OPENCV_INSTALL_MODULES),) + OPENCV_INSTALL_MODULES:=on +endif + define add_opencv_module include $(CLEAR_VARS) LOCAL_MODULE:=opencv_$1 diff --git a/modules/java/generator/src/java/android+OpenCVLoader.java b/modules/java/generator/src/java/android+OpenCVLoader.java index 2c05272c22..c220f19588 100644 --- a/modules/java/generator/src/java/android+OpenCVLoader.java +++ b/modules/java/generator/src/java/android+OpenCVLoader.java @@ -1,12 +1,15 @@ package org.opencv.android; import android.content.Context; +import android.util.Log; /** * Helper class provides common initialization methods for OpenCV library. */ public class OpenCVLoader { + private static final String TAG = "OpenCVLoader"; + /** * OpenCV Library version 2.4.2. */ @@ -62,6 +65,11 @@ public class OpenCVLoader */ public static final String OPENCV_VERSION_2_4_12 = "2.4.12"; + /** + * OpenCV Library version 2.4.13. + */ + public static final String OPENCV_VERSION_2_4_13 = "2.4.13"; + /** * Loads and initializes OpenCV library from current application package. Roughly, it's an analog of system.loadLibrary("opencv_java"). * @return Returns true is initialization of OpenCV was successful. @@ -91,6 +99,11 @@ public class OpenCVLoader public static boolean initAsync(String Version, Context AppContext, LoaderCallbackInterface Callback) { + if (initDebug()) { + Callback.onManagerConnected(LoaderCallbackInterface.SUCCESS); + return true; + } + Log.w(TAG, "OpenCV binaries are not packaged with application. Trying to use OpenCV Manager..."); return AsyncServiceHelper.initOpenCV(Version, AppContext, Callback); } } diff --git a/platforms/android/build_sdk.py b/platforms/android/build_sdk.py old mode 100755 new mode 100644 index 7d52eab9c0..7251948d7b --- a/platforms/android/build_sdk.py +++ b/platforms/android/build_sdk.py @@ -10,13 +10,13 @@ class Fail(Exception): def __str__(self): return "ERROR" if self.t is None else self.t -def execute(cmd, shell=False): +def execute(cmd, shell=False, allowFail=False): try: log.info("Executing: %s" % cmd) retcode = subprocess.call(cmd, shell=shell) if retcode < 0: raise Fail("Child was terminated by signal:" %s -retcode) - elif retcode > 0: + elif retcode > 0 and not allowFail: raise Fail("Child returned: %s" % retcode) except OSError as e: raise Fail("Execution failed: %d / %s" % (e.errno, e.strerror)) @@ -45,44 +45,37 @@ def check_dir(d, create=False, clean=False): os.makedirs(d) return d -def determine_engine_version(manifest_path): - with open(manifest_path, "rt") as f: - return re.search(r'android:versionName="(\d+\.\d+)"', f.read(), re.MULTILINE).group(1) - def determine_opencv_version(version_hpp_path): # version in 2.4 - CV_VERSION_EPOCH.CV_VERSION_MAJOR.CV_VERSION_MINOR.CV_VERSION_REVISION # version in master - CV_VERSION_MAJOR.CV_VERSION_MINOR.CV_VERSION_REVISION-CV_VERSION_STATUS with open(version_hpp_path, "rt") as f: data = f.read() + epoch = re.search(r'^#define\W+CV_VERSION_EPOCH\W+(\d+)$', data, re.MULTILINE).group(1) major = re.search(r'^#define\W+CV_VERSION_MAJOR\W+(\d+)$', data, re.MULTILINE).group(1) minor = re.search(r'^#define\W+CV_VERSION_MINOR\W+(\d+)$', data, re.MULTILINE).group(1) revision = re.search(r'^#define\W+CV_VERSION_REVISION\W+(\d+)$', data, re.MULTILINE).group(1) - version_status = re.search(r'^#define\W+CV_VERSION_STATUS\W+"([^"]*)"$', data, re.MULTILINE).group(1) - return "%(major)s.%(minor)s.%(revision)s%(version_status)s" % locals() + revision = '' if revision == '0' else '.' + revision + return "%(epoch)s.%(major)s.%(minor)s%(revision)s" % locals() #=================================================================================================== class ABI: - def __init__(self, platform_id, name, toolchain, cmake_name=None): + def __init__(self, platform_id, name, toolchain, api_level=8, cmake_name=None): self.platform_id = platform_id # platform code to add to apk version (for cmake) self.name = name # general name (official Android ABI identifier) self.toolchain = toolchain # toolchain identifier (for cmake) + self.api_level = api_level self.cmake_name = cmake_name # name of android toolchain (for cmake) if self.cmake_name is None: self.cmake_name = self.name def __str__(self): return "%s (%s)" % (self.name, self.toolchain) - def haveIPP(self): - return self.name == "x86" or self.name == "x86_64" ABIs = [ - ABI("2", "armeabi-v7a", "arm-linux-androideabi-4.8", cmake_name="armeabi-v7a with NEON"), - ABI("1", "armeabi", "arm-linux-androideabi-4.8"), - ABI("3", "arm64-v8a", "aarch64-linux-android-4.9"), - ABI("5", "x86_64", "x86_64-4.9"), - ABI("4", "x86", "x86-4.8"), - ABI("7", "mips64", "mips64el-linux-android-4.9"), - ABI("6", "mips", "mipsel-linux-android-4.8") + ABI("2", "armeabi-v7a", "arm-linux-androideabi-4.6", cmake_name="armeabi-v7a with NEON"), + ABI("1", "armeabi", "arm-linux-androideabi-4.6"), + ABI("4", "x86", "x86-clang3.1", api_level=9), + ABI("6", "mips", "mipsel-linux-android-4.6", api_level=9) ] #=================================================================================================== @@ -91,38 +84,30 @@ class Builder: def __init__(self, workdir, opencvdir): self.workdir = check_dir(workdir, create=True) self.opencvdir = check_dir(opencvdir) - self.extra_modules_path = None self.libdest = check_dir(os.path.join(self.workdir, "o4a"), create=True, clean=True) self.docdest = check_dir(os.path.join(self.workdir, "javadoc"), create=True, clean=True) self.resultdest = check_dir(os.path.join(self.workdir, "OpenCV-android-sdk"), create=True, clean=True) - self.extra_packs = [] self.opencv_version = determine_opencv_version(os.path.join(self.opencvdir, "modules", "core", "include", "opencv2", "core", "version.hpp")) - self.engine_version = determine_engine_version(os.path.join(self.opencvdir, "platforms", "android", "service", "engine", "AndroidManifest.xml")) self.use_ccache = True def get_toolchain_file(self): return os.path.join(self.opencvdir, "platforms", "android", "android.toolchain.cmake") - def get_engine_apk_dest(self, engdest): - return os.path.join(engdest, "platforms", "android", "service", "engine", ".build") - - def add_extra_pack(self, ver, path): - if path is None: - return - self.extra_packs.append((ver, check_dir(path))) - def clean_library_build_dir(self): for d in ["CMakeCache.txt", "CMakeFiles/", "bin/", "libs/", "lib/", "package/", "install/samples/"]: rm_one(d) - def build_library(self, abi, do_install): + def build_library(self, abi, do_install, build_docs): cmd = [ "cmake", "-GNinja", "-DCMAKE_TOOLCHAIN_FILE='%s'" % self.get_toolchain_file(), - "-DWITH_OPENCL=OFF", - "-DWITH_CUDA=OFF", - "-DWITH_IPP=%s" % ("ON" if abi.haveIPP() else "OFF"), + "-DINSTALL_CREATE_DISTRIB=ON", + #"-DWITH_OPENCL=OFF", + "-DWITH_CUDA=OFF", "-DBUILD_opencv_gpu=OFF", + "-DBUILD_opencv_nonfree=OFF", + "-DWITH_TBB=OFF", + "-DWITH_IPP=OFF", "-DBUILD_EXAMPLES=OFF", "-DBUILD_TESTS=OFF", "-DBUILD_PERF_TESTS=OFF", @@ -130,68 +115,28 @@ class Builder: "-DBUILD_ANDROID_EXAMPLES=ON", "-DINSTALL_ANDROID_EXAMPLES=ON", "-DANDROID_STL=gnustl_static", - "-DANDROID_NATIVE_API_LEVEL=9", + "-DANDROID_NATIVE_API_LEVEL=%s" % abi.api_level, "-DANDROID_ABI='%s'" % abi.cmake_name, - "-DWITH_TBB=ON", "-DANDROID_TOOLCHAIN_NAME=%s" % abi.toolchain ] - if self.extra_modules_path is not None: - cmd.append("-DOPENCV_EXTRA_MODULES_PATH='%s'" % self.extra_modules_path) - cmd.append(self.opencvdir) if self.use_ccache == True: cmd.append("-DNDK_CCACHE=ccache") if do_install: cmd.extend(["-DBUILD_TESTS=ON", "-DINSTALL_TESTS=ON"]) + if do_install and build_docs: + cmd.extend(["-DBUILD_DOCS=ON"]) execute(cmd) if do_install: - execute(["ninja"]) - for c in ["libs", "dev", "java", "samples"]: + execute(["cmake", "--build", "."]) + if do_install and build_docs: + execute(["cmake", "--build", ".", "--target", "docs"]) + for c in ["libs", "dev", "java", "samples"] + (["docs"] if do_install and build_docs else []): execute(["cmake", "-DCOMPONENT=%s" % c, "-P", "cmake_install.cmake"]) else: - execute(["ninja", "install/strip"]) - - def build_engine(self, abi, engdest): - cmd = [ - "cmake", - "-GNinja", - "-DCMAKE_TOOLCHAIN_FILE='%s'" % self.get_toolchain_file(), - "-DANDROID_ABI='%s'" % abi.cmake_name, - "-DBUILD_ANDROID_SERVICE=ON", - "-DANDROID_PLATFORM_ID=%s" % abi.platform_id, - "-DWITH_CUDA=OFF", - "-DWITH_OPENCL=OFF", - "-DWITH_IPP=OFF", - self.opencvdir - ] - execute(cmd) - apkdest = self.get_engine_apk_dest(engdest) - # Add extra data - apkxmldest = check_dir(os.path.join(apkdest, "res", "xml"), create=True) - apklibdest = check_dir(os.path.join(apkdest, "libs", abi.name), create=True) - for ver, d in self.extra_packs + [("3.1.0", os.path.join(self.libdest, "lib"))]: - r = ET.Element("library", attrib={"version": ver}) - log.info("Adding libraries from %s", d) - - for f in glob.glob(os.path.join(d, abi.name, "*.so")): - log.info("Copy file: %s", f) - shutil.copy2(f, apklibdest) - if "libnative_camera" in f: - continue - log.info("Register file: %s", os.path.basename(f)) - n = ET.SubElement(r, "file", attrib={"name": os.path.basename(f)}) - - if len(list(r)) > 0: - xmlname = os.path.join(apkxmldest, "config%s.xml" % ver.replace(".", "")) - log.info("Generating XML config: %s", xmlname) - ET.ElementTree(r).write(xmlname, encoding="utf-8") - - execute(["ninja", "opencv_engine"]) - execute(["ant", "-f", os.path.join(apkdest, "build.xml"), "debug"], - shell=(sys.platform == 'win32')) - # TODO: Sign apk + execute(["cmake", "--build", ".", "--target", "install/strip"]) def build_javadoc(self): classpaths = [os.path.join(self.libdest, "bin", "classes")] @@ -201,6 +146,7 @@ class Builder: classpaths.append(os.path.join(dir, f)) cmd = [ "javadoc", + "-encoding", "UTF-8", "-header", "OpenCV %s" % self.opencv_version, "-nodeprecated", "-footer", 'OpenCV %s Documentation' % self.opencv_version, @@ -211,9 +157,9 @@ class Builder: ] for _, dirs, _ in os.walk(os.path.join(self.libdest, "src", "org", "opencv")): cmd.extend(["org.opencv." + d for d in dirs]) - execute(cmd) + execute(cmd, allowFail=True) # FIXIT javadoc currenly reports some errors - def gather_results(self, engines): + def gather_results(self, with_samples_apk): # Copy all files root = os.path.join(self.libdest, "install") for item in os.listdir(root): @@ -226,13 +172,6 @@ class Builder: log.info("Copy file: %s", item) shutil.copy2(item, os.path.join(self.resultdest, name)) - # Copy engines for all platforms - for abi, engdest in engines: - log.info("Copy engine: %s (%s)", abi, engdest) - f = os.path.join(self.get_engine_apk_dest(engdest), "bin", "opencv_engine-debug.apk") - resname = "OpenCV_%s_Manager_%s_%s.apk" % (self.opencv_version, self.engine_version, abi) - shutil.copy2(f, os.path.join(self.resultdest, "apk", resname)) - # Copy javadoc log.info("Copy docs: %s", self.docdest) shutil.copytree(self.docdest, os.path.join(self.resultdest, "sdk", "java", "javadoc")) @@ -244,6 +183,9 @@ class Builder: if os.path.isdir(item): for name in ["build.xml", "local.properties", "proguard-project.txt"]: rm_one(os.path.join(item, name)) + if not with_samples_apk: + if re.search(r'\.apk$', item): # reduce size of SDK + rm_one(item) #=================================================================================================== @@ -254,11 +196,10 @@ if __name__ == "__main__": parser.add_argument("opencv_dir", help="Path to OpenCV source dir") parser.add_argument('--ndk_path', help="Path to Android NDK to use for build") parser.add_argument('--sdk_path', help="Path to Android SDK to use for build") - parser.add_argument("--extra_modules_path", help="Path to extra modules to use for build") - parser.add_argument('--sign_with', help="Sertificate to sign the Manager apk") - parser.add_argument('--build_doc', action="store_true", help="Build javadoc") + parser.add_argument('--build_doc', action="store_true", help="Build documentation") + parser.add_argument('--build_javadoc', action="store_true", help="Build javadoc") parser.add_argument('--no_ccache', action="store_true", help="Do not use ccache during library build") - parser.add_argument('--extra_pack', action='append', help="provide extra OpenCV libraries for Manager apk in form :, for example '2.4.11:unpacked/sdk/native/libs'") + parser.add_argument('--with_samples_apk', action="store_true", help="Include samples APKs") args = parser.parse_args() log.basicConfig(format='%(message)s', level=log.DEBUG) @@ -274,27 +215,13 @@ if __name__ == "__main__": builder = Builder(args.work_dir, args.opencv_dir) - if args.extra_modules_path is not None: - builder.extra_modules_path = os.path.abspath(args.extra_modules_path) - if args.no_ccache: builder.use_ccache = False log.info("Detected OpenCV version: %s", builder.opencv_version) - log.info("Detected Engine version: %s", builder.engine_version) - if args.extra_pack: - for one in args.extra_pack: - i = one.find(":") - if i > 0 and i < len(one) - 1: - builder.add_extra_pack(one[:i], one[i+1:]) - else: - raise Fail("Bad extra pack provided: %s, should be in form ':'" % one) - - engines = [] for i, abi in enumerate(ABIs): do_install = (i == 0) - engdest = check_dir(os.path.join(builder.workdir, "build_service_%s" % abi.name), create=True, clean=True) log.info("=====") log.info("===== Building library for %s", abi) @@ -302,20 +229,12 @@ if __name__ == "__main__": os.chdir(builder.libdest) builder.clean_library_build_dir() - builder.build_library(abi, do_install) + builder.build_library(abi, do_install, build_docs=args.build_doc) - log.info("=====") - log.info("===== Building engine for %s", abi) - log.info("=====") - - os.chdir(engdest) - builder.build_engine(abi, engdest) - engines.append((abi.name, engdest)) - - if args.build_doc: + if args.build_doc or args.build_javadoc: builder.build_javadoc() - builder.gather_results(engines) + builder.gather_results(with_samples_apk=args.with_samples_apk) log.info("=====") log.info("===== Build finished") diff --git a/platforms/android/service/CMakeLists.txt b/platforms/android/service/CMakeLists.txt index c99b71392f..7b1522bf79 100644 --- a/platforms/android/service/CMakeLists.txt +++ b/platforms/android/service/CMakeLists.txt @@ -2,5 +2,3 @@ if(BUILD_ANDROID_SERVICE) add_subdirectory(engine) #add_subdirectory(engine_test) endif() - -install(FILES "readme.txt" DESTINATION "apk/" COMPONENT libs) diff --git a/platforms/android/service/doc/JavaHelper.rst b/platforms/android/service/doc/JavaHelper.rst index 6be46d61a3..3c3762b9e3 100644 --- a/platforms/android/service/doc/JavaHelper.rst +++ b/platforms/android/service/doc/JavaHelper.rst @@ -79,3 +79,11 @@ OpenCV version constants .. data:: OPENCV_VERSION_2_4_11 OpenCV Library version 2.4.11 + +.. data:: OPENCV_VERSION_2_4_12 + + OpenCV Library version 2.4.12 + +.. data:: OPENCV_VERSION_2_4_13 + + OpenCV Library version 2.4.13 diff --git a/platforms/android/service/readme.txt b/platforms/android/service/readme.txt index 51853c24e5..c8230e38d8 100644 --- a/platforms/android/service/readme.txt +++ b/platforms/android/service/readme.txt @@ -1,6 +1,8 @@ How to select the proper version of OpenCV Manager -------------------------------------------------- +DEPRECATED: This information is outdated since OpenCV 2.4.12 + Since version 1.7 several packages of OpenCV Manager are built. Every package is targeted for some specific hardware platform and includes corresponding OpenCV binaries. So, in most cases OpenCV Manager uses built-in version of OpenCV. Separate package with OpenCV binaries is currently used in diff --git a/samples/android/face-detection/jni/Android.mk b/samples/android/face-detection/jni/Android.mk index 6b6642602d..cf20dff2b5 100644 --- a/samples/android/face-detection/jni/Android.mk +++ b/samples/android/face-detection/jni/Android.mk @@ -3,7 +3,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) #OPENCV_CAMERA_MODULES:=off -#OPENCV_INSTALL_MODULES:=off #OPENCV_LIB_TYPE:=SHARED include ../../sdk/native/jni/OpenCV.mk