If you mean the AndroidResourceProvider from NoesisGUI 1.2, it was using the AAssetManager API available through Android NDK. It also worked when OBB files were specified.
Here is the code that can be easily adapted to work with NoesisGUI 2 provider architecture:
#ifndef __RESOURCE_ANDROIDRESOURCEPROVIDER_H__
#define __RESOURCE_ANDROIDRESOURCEPROVIDER_H__
#include <Noesis.h>
#include <NsResource/AndroidResourceProviderApi.h>
#include <NsResource/ResourceProvider.h>
// Forward declarations
//@{
struct AAssetManager;
//@}
namespace Noesis
{
namespace Resource
{
#ifdef NS_COMPILER_MSVC
#pragma warning(push)
#pragma warning(disable: 4251 4275)
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Provider of resources stored inside an .apk or .obb Android file
////////////////////////////////////////////////////////////////////////////////////////////////////
class NS_RESOURCE_ANDROIDRESOURCEPROVIDER_API AndroidResourceProvider: public ResourceProvider
{
public:
AndroidResourceProvider(AAssetManager* assetManager, const NsChar* dataPath,
const NsChar* obbFile);
~AndroidResourceProvider();
private:
Ptr<Core::IStream> RequestFile(const NsChar* name);
private:
AAssetManager* mAssetManager;
void* mObbHandle;
NsString mDataPath;
};
#ifdef NS_COMPILER_MSVC
#pragma warning(pop)
#endif
}
}
#endif
#include <NsResource/AndroidResourceProvider.h>
#ifdef NS_PLATFORM_ANDROID
#include <NsCore/IStream.h>
#include <NsCore/ReflectionImplement.h>
#include <android/asset_manager.h>
#include <android/log.h>
#include "unzip.h"
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Noesis", __VA_ARGS__))
using namespace Noesis;
using namespace Noesis::Core;
using namespace Noesis::Resource;
namespace Noesis
{
namespace Resource
{
////////////////////////////////////////////////////////////////////////////////////////////////////
class AndroidFile : public BaseComponent, public IStream
{
public:
AndroidFile(AAsset* asset) : mAsset(asset)
{
}
~AndroidFile()
{
Close();
}
/// From IStream
//@{
NsBool CanSeek() const
{
return true;
}
void SetPosition(NsSize pos)
{
if (AAsset_seek(mAsset, pos, SEEK_SET) < 0)
{
NS_ERROR("Can't seek to the specified position");
}
}
NsSize GetPosition() const
{
off_t pos = AAsset_seek(mAsset, 0, SEEK_CUR);
if (pos < 0)
{
NS_ERROR("Can't get current position");
}
return pos;
}
void SetLength(NsSize length)
{
NS_ERROR("Can't set stream length");
}
NsSize GetLength() const
{
return AAsset_getLength(mAsset);
}
NsBool CanRead() const
{
return true;
}
void Read(void* buffer, NsSize size)
{
int readBytes = AAsset_read(mAsset, buffer, size);
if (readBytes < 0 || static_cast<NsSize>(readBytes) < size)
{
NS_ERROR("Can't read specified bytes");
}
}
NsBool CanWrite() const
{
return false;
}
void Write(const void* buffer, NsSize size)
{
NS_ERROR("Can't write to stream");
}
void Flush()
{
}
void Close()
{
AAsset_close(mAsset);
}
//@}
private:
AAsset* mAsset;
NS_IMPLEMENT_INLINE_REFLECTION(AndroidFile, BaseComponent)
{
NsImpl<IStream>();
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
class ObbFile : public BaseComponent, public IStream
{
public:
ObbFile(void* obbHandle, const unz_file_info& info) : mBuffer(0), mSize(info.uncompressed_size),
mPosition(0)
{
mBuffer = new NsByte[mSize];
int readBytes = unzReadCurrentFile(obbHandle, mBuffer, mSize);
if (readBytes < 0 || static_cast<NsSize>(readBytes) < mSize)
{
LOGI("Unable to read all data from OBB");
NS_ERROR("Unable to read all data from OBB");
}
unzCloseCurrentFile(obbHandle);
}
~ObbFile()
{
Close();
}
/// From IStream
//@{
NsBool CanSeek() const
{
return true;
}
void SetPosition(NsSize pos)
{
if (pos > mSize)
{
NS_ERROR("Can't set stream position");
}
mPosition = pos;
}
NsSize GetPosition() const
{
return mPosition;
}
void SetLength(NsSize length)
{
NS_ERROR("Can't set stream length");
}
NsSize GetLength() const
{
return mSize;
}
NsBool CanRead() const
{
return true;
}
void Read(void* buffer, NsSize size)
{
if (mPosition + size > mSize)
{
NS_ERROR("Can't read specified bytes");
}
memcpy(buffer, &mBuffer[mPosition], size);
mPosition += size;
}
NsBool CanWrite() const
{
return false;
}
void Write(const void* buffer, NsSize size)
{
NS_ERROR("Can't write to stream");
}
void Flush()
{
}
void Close()
{
delete[] mBuffer;
mSize = 0;
mPosition = 0;
}
//@}
private:
NsByte* mBuffer;
NsSize mSize;
NsSize mPosition;
NS_IMPLEMENT_INLINE_REFLECTION(ObbFile, BaseComponent)
{
NsImpl<IStream>();
}
};
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
AndroidResourceProvider::AndroidResourceProvider(AAssetManager* assetManager,
const NsChar* dataPath, const NsChar* obbFile) : mAssetManager(assetManager), mObbHandle(0),
mDataPath(dataPath)
{
if (String::FindLast(obbFile, ".obb") > 0)
{
LOGI("Using OBB File");
// Extract obb file name from StreamingAssets path
NsInt start = String::FindFirst(obbFile, "/", 0);
if (start < 0)
{
start = 0;
}
NsInt end = String::FindLast(obbFile, "!", 0);
if (end < 0)
{
end = String::Length(obbFile);
}
NsString obb(&obbFile[start], end - start);
LOGI("OBB = %s", obbFile);
mObbHandle = unzOpen(obb.c_str());
if (mObbHandle == 0)
{
NS_ERROR("Unable to open OBB file '%s'", obb.c_str());
}
mDataPath = "assets/";
mDataPath += dataPath;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
AndroidResourceProvider::~AndroidResourceProvider()
{
if (mObbHandle != 0)
{
unzClose(mObbHandle);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Ptr<IStream> AndroidResourceProvider::RequestFile(const NsChar* name)
{
NsString assetPath = mDataPath + name;
LOGI("RequestFile(%s)", assetPath.c_str());
if (mObbHandle != 0)
{
if (unzLocateFile(mObbHandle, assetPath.c_str(), 1) == UNZ_OK)
{
unz_file_info info;
if (unzGetCurrentFileInfo(mObbHandle, &info, 0, 0, 0, 0, 0, 0) == UNZ_OK)
{
if (unzOpenCurrentFile(mObbHandle) == UNZ_OK)
{
LOGI("Creating ObbFile Stream [%u]", (unsigned int)info.uncompressed_size);
return *new ObbFile(mObbHandle, info);
}
}
}
}
else
{
NS_ASSERT(mAssetManager);
AAsset* asset = AAssetManager_open(mAssetManager, assetPath.c_str(), AASSET_MODE_STREAMING);
if (asset != 0)
{
return *new AndroidFile(asset);
}
}
return Ptr<IStream>::Null();
}
#endif
Anyway, in order to update the Android integration sample we will have to implement the same provider.