From 7224476ee10f7264a03b6cea308a22b57c47c4a8 Mon Sep 17 00:00:00 2001 From: Filip Wasil Date: Tue, 7 Oct 2014 16:23:56 +0200 Subject: [PATCH] Android JNI asset extraction support (API 9+) Signed-off-by: Filip Wasil --- CMakeLists.txt | 2 + CREDITS | 3 + code/CMakeLists.txt | 10 + code/DefaultIOStream.h | 3 + include/assimp/config.h | 8 + .../port/AndroidJNI/AndroidJNIIOSystem.h | 92 ++++++++++ port/AndroidJNI/AndroidJNIIOSystem.cpp | 173 ++++++++++++++++++ port/AndroidJNI/CMakeLists.txt | 6 + port/AndroidJNI/README.txt | 27 +++ 9 files changed, 324 insertions(+) create mode 100644 include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h create mode 100644 port/AndroidJNI/AndroidJNIIOSystem.cpp create mode 100644 port/AndroidJNI/CMakeLists.txt create mode 100644 port/AndroidJNI/README.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 717184691..97d4b68bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,8 @@ set(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_M set(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev) set(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names") +option(ASSIMP_ANDROID_JNIIOSYSTEM "Android JNI IOSystem support is active" OFF) + if((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW) add_definitions(-fPIC) # this is a very important switch and some libraries seem now to have it.... # hide all not-exported symbols diff --git a/CREDITS b/CREDITS index 5d45a9e92..2e7485fb7 100644 --- a/CREDITS +++ b/CREDITS @@ -148,3 +148,6 @@ Bugfixes for uv-tanget calculation. - Jonne Nauha Ogre Binary format support + +- Filip Wasil, Tieto Poland Sp. z o.o. +Android JNI asset extraction support diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index c11a9b42a..f636fc535 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -725,6 +725,13 @@ ADD_LIBRARY( assimp ${assimp_src} ) SET_PROPERTY(TARGET assimp PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX}) TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES}) + +if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM) + set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI/) + add_subdirectory(../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH} ../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}) + target_link_libraries(assimp android_jniiosystem) +endif(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM) + SET_TARGET_PROPERTIES( assimp PROPERTIES VERSION ${ASSIMP_VERSION} SOVERSION ${ASSIMP_SOVERSION} # use full version @@ -751,6 +758,9 @@ INSTALL( TARGETS assimp COMPONENT ${LIBASSIMP_COMPONENT}) INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev) INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev) +if (ASSIMP_ANDROID_JNIIOSYSTEM) + INSTALL( FILES assimp/${ANDROID_JNI_PATH}/AndroidJNIIOSystem.h DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/${ANDROID_JNI_PATH} COMPONENT assimp-dev) +endif(ASSIMP_ANDROID_JNIIOSYSTEM) if(MSVC AND ASSIMP_INSTALL_PDB) install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${ASSIMP_DEBUG_POSTFIX}.pdb diff --git a/code/DefaultIOStream.h b/code/DefaultIOStream.h index da1eed0b8..6ddf94c23 100644 --- a/code/DefaultIOStream.h +++ b/code/DefaultIOStream.h @@ -56,6 +56,9 @@ namespace Assimp { class DefaultIOStream : public IOStream { friend class DefaultIOSystem; +#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) + friend class AndroidJNIIOSystem; +#endif //__ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) protected: DefaultIOStream (); diff --git a/include/assimp/config.h b/include/assimp/config.h index 6bd31aada..56ef8f3b5 100644 --- a/include/assimp/config.h +++ b/include/assimp/config.h @@ -841,6 +841,14 @@ enum aiComponent */ #define AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS "IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS" + /** @brief Specifies whether the Android JNI asset extraction is supported. + * + * Turn on this option if you want to manage assets in native + * Android application without having to keep the internal directory and asset + * manager pointer. + */ + #define AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT "AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT" + // --------------------------------------------------------------------------- /** @brief Specifies whether the IFC loader skips over diff --git a/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h b/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h new file mode 100644 index 000000000..ad6940253 --- /dev/null +++ b/include/assimp/port/AndroidJNI/AndroidJNIIOSystem.h @@ -0,0 +1,92 @@ +/* +Open Asset Import Library (assimp) +---------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp team +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the +following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------------------------- +*/ + +/** @file Android implementation of IOSystem using the standard C file functions. + * Aimed to ease the acces to android assets */ + +#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) +#ifndef AI_ANDROIDJNIIOSYSTEM_H_INC +#define AI_ANDROIDJNIIOSYSTEM_H_INC + +#include "../code/DefaultIOSystem.h" +#include +#include +#include + +namespace Assimp { + +// --------------------------------------------------------------------------- +/** Android extension to DefaultIOSystem using the standard C file functions */ +class AndroidJNIIOSystem : public DefaultIOSystem +{ +public: + + /** Initialize android activity data */ + std::string mApkWorkspacePath; + AAssetManager* mApkAssetManager; + + /** Constructor. */ + AndroidJNIIOSystem(ANativeActivity* activity); + + /** Destructor. */ + ~AndroidJNIIOSystem(); + + // ------------------------------------------------------------------- + /** Tests for the existence of a file at the given path. */ + bool Exists( const char* pFile) const; + + // ------------------------------------------------------------------- + /** Opens a file at the given path, with given mode */ + IOStream* Open( const char* strFile, const char* strMode); + + // ------------------------------------------------------------------------------------------------ + // Inits Android extractor + void AndroidActivityInit(ANativeActivity* activity); + + // ------------------------------------------------------------------------------------------------ + // Extracts android asset + bool AndroidExtractAsset(std::string name); + +}; + +} //!ns Assimp + +#endif //AI_ANDROIDJNIIOSYSTEM_H_INC +#endif //__ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) diff --git a/port/AndroidJNI/AndroidJNIIOSystem.cpp b/port/AndroidJNI/AndroidJNIIOSystem.cpp new file mode 100644 index 000000000..4e8f19187 --- /dev/null +++ b/port/AndroidJNI/AndroidJNIIOSystem.cpp @@ -0,0 +1,173 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2012, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. + +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the + following disclaimer in the documentation and/or other + materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its + contributors may be used to endorse or promote products + derived from this software without specific prior + written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ + +/** @file Android extension of DefaultIOSystem using the standard C file functions */ + + +#include +#if __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Assimp; + +// ------------------------------------------------------------------------------------------------ +// Constructor. +AndroidJNIIOSystem::AndroidJNIIOSystem(ANativeActivity* activity) +{ + AndroidActivityInit(activity); +} + +// ------------------------------------------------------------------------------------------------ +// Destructor. +AndroidJNIIOSystem::~AndroidJNIIOSystem() +{ + // nothing to do here +} + +// ------------------------------------------------------------------------------------------------ +// Tests for the existence of a file at the given path. +bool AndroidJNIIOSystem::Exists( const char* pFile) const +{ + AAsset* asset = AAssetManager_open(mApkAssetManager, pFile, + AASSET_MODE_UNKNOWN); + FILE* file = ::fopen( (mApkWorkspacePath + getOsSeparator() + std::string(pFile)).c_str(), "rb"); + + if (!asset && !file) + { + __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset manager can not find: %s", pFile); + return false; + } + + __android_log_print(ANDROID_LOG_ERROR, "Assimp", "Asset exists"); + if (file) + ::fclose( file); + return true; +} + +// ------------------------------------------------------------------------------------------------ +// Inits Android extractor +void AndroidJNIIOSystem::AndroidActivityInit(ANativeActivity* activity) +{ + mApkWorkspacePath = activity->internalDataPath; + mApkAssetManager = activity->assetManager; +} + +// ------------------------------------------------------------------------------------------------ +// Extracts android asset +bool AndroidJNIIOSystem::AndroidExtractAsset(std::string name) +{ + std::string newPath = mApkWorkspacePath + getOsSeparator() + name; + + DefaultIOSystem io; + + // Do not extract if extracted already + if ( io.Exists(newPath.c_str()) ) { + __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset already extracted"); + return true; + } + // Open file + AAsset* asset = AAssetManager_open(mApkAssetManager, name.c_str(), + AASSET_MODE_UNKNOWN); + std::string assetContent; + + if (asset != NULL) { + // Find size + off_t assetSize = AAsset_getLength(asset); + + // Prepare input buffer + assetContent.resize(assetSize); + + // Store input buffer + AAsset_read(asset, &assetContent[0], assetSize); + + // Close + AAsset_close(asset); + + // Prepare output buffer + std::ofstream assetExtracted(newPath.c_str(), + std::ios::out | std::ios::binary); + if (!assetExtracted) { + __android_log_print(ANDROID_LOG_ERROR, "assimp", + "Can not open output file"); + } + + // Write output buffer into a file + assetExtracted.write(assetContent.c_str(), strlen(assetContent.c_str())); + assetExtracted.close(); + + __android_log_print(ANDROID_LOG_DEFAULT, "Assimp", "Asset extracted"); + } else { + __android_log_print(ANDROID_LOG_ERROR, "assimp", "Asset not found: %s", name.c_str()); + return false; + } + return true; +} + +// ------------------------------------------------------------------------------------------------ +// Open a new file with a given path. +IOStream* AndroidJNIIOSystem::Open( const char* strFile, const char* strMode) +{ + ai_assert(NULL != strFile); + ai_assert(NULL != strMode); + + std::string fullPath(mApkWorkspacePath + getOsSeparator() + std::string(strFile)); + if (Exists(strFile)) + AndroidExtractAsset(std::string(strFile)); + + FILE* file = ::fopen( fullPath.c_str(), strMode); + + if( NULL == file) + return NULL; + + __android_log_print(ANDROID_LOG_ERROR, "assimp", "AndroidIOSystem: file %s opened", fullPath.c_str()); + return new DefaultIOStream(file, fullPath); +} + +#undef PATHLIMIT +#endif // __ANDROID__ and __ANDROID_API__ > 9 and defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT) diff --git a/port/AndroidJNI/CMakeLists.txt b/port/AndroidJNI/CMakeLists.txt new file mode 100644 index 000000000..ddc718850 --- /dev/null +++ b/port/AndroidJNI/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 2.8) + +include_directories(./) +include_directories(./../../) +add_library(android_jniiosystem STATIC AndroidJNIIOSystem.cpp) +TARGET_LINK_LIBRARIES(android_jniiosystem android log) diff --git a/port/AndroidJNI/README.txt b/port/AndroidJNI/README.txt new file mode 100644 index 000000000..337772025 --- /dev/null +++ b/port/AndroidJNI/README.txt @@ -0,0 +1,27 @@ +--- Description --- + +This module provides a facade to io stream access to files +behind android asset manager within Android native application. +- It is built as a static library +- It requires Android NDK with android API > 9 support. + +--- Building --- + +To use this module please provide following cmake defines: + +-DASSIMP_ANDROID_JNIIOSYSTEM=ON +-DCMAKE_TOOLCHAIN_FILE=$SOME_PATH/android.toolchain.cmake + +"SOME_PATH" is a path to your cmake android toolchain script. + +--- Code --- + +#include + +... + +Assimp::Importer* importer = new Assimp::Importer(); +Assimp::AndroidJNIIOSystem* ioSystem = new Assimp::AndroidJNIIOSystem(app->activity); +importer->SetIOHandler(ioSystem); + +...