From 10a67fd9f8300c0b9bd9ab9205e21fee01012abe Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 10 Jan 2018 13:33:43 -0800 Subject: [PATCH] Fix unpack resources on android --- android/app/src/main/cpp/native.cpp | 96 ++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 29 deletions(-) diff --git a/android/app/src/main/cpp/native.cpp b/android/app/src/main/cpp/native.cpp index 90d8d55af9..c6e3ee2070 100644 --- a/android/app/src/main/cpp/native.cpp +++ b/android/app/src/main/cpp/native.cpp @@ -1,3 +1,7 @@ +#include + + +#include #include #include #include @@ -12,6 +16,8 @@ #include #include +#include + void tempMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { if (!message.isEmpty()) { const char * local=message.toStdString().c_str(); @@ -36,33 +42,65 @@ void tempMessageHandler(QtMsgType type, const QMessageLogContext& context, const } } -void unpackAndroidAssets() { - const QString SOURCE_PREFIX { "assets:/" }; - const QString DEST_PREFIX = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/"; - QStringList filesToCopy; - QString dateStamp; - { - QFile file("assets:/cache_assets.txt"); - if (!file.open(QIODevice::ReadOnly)) { - throw std::runtime_error("Failed to open cache file list"); - } - QTextStream in(&file); - dateStamp = DEST_PREFIX + "/" + in.readLine(); - while (!in.atEnd()) { - QString line = in.readLine(); - filesToCopy << line; - } - file.close(); - } - qDebug() << "Checking date stamp" << dateStamp; +AAssetManager* g_assetManager = nullptr; - if (QFileInfo(dateStamp).exists()) { +void withAssetData(const char* filename, const std::function& callback) { + auto asset = AAssetManager_open(g_assetManager, filename, AASSET_MODE_BUFFER); + if (!asset) { + throw std::runtime_error("Failed to open file"); + } + auto buffer = AAsset_getBuffer(asset); + off64_t size = AAsset_getLength64(asset); + callback(size, buffer); + AAsset_close(asset); +} + +QStringList readAssetLines(const char* filename) { + QStringList result; + withAssetData(filename, [&](off64_t size, const void* data){ + QByteArray buffer = QByteArray::fromRawData((const char*)data, size); + { + QTextStream in(&buffer); + while (!in.atEnd()) { + QString line = in.readLine(); + result << line; + } + } + }); + return result; +} + +void copyAsset(const char* sourceAsset, const QString& destFilename) { + withAssetData(sourceAsset, [&](off64_t size, const void* data){ + QFile file(destFilename); + if (!file.open(QFile::ReadWrite | QIODevice::Truncate)) { + throw std::runtime_error("Unable to open output file for writing"); + } + if (!file.resize(size)) { + throw std::runtime_error("Unable to resize output file"); + } + auto mapped = file.map(0, size); + if (!mapped) { + throw std::runtime_error("Unable to map output file"); + } + memcpy(mapped, data, size); + file.close(); + }); +} + +void unpackAndroidAssets() { + const QString DEST_PREFIX = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/"; + + QStringList filesToCopy = readAssetLines("cache_assets.txt"); + QString dateStamp = filesToCopy.takeFirst(); + QString dateStampFilename = DEST_PREFIX + dateStamp; + qDebug() << "Checking date stamp" << dateStamp; + if (QFileInfo(dateStampFilename).exists()) { return; } auto rootDir = QDir::root(); for (const auto& fileToCopy : filesToCopy) { - auto sourceFileName = SOURCE_PREFIX + fileToCopy; auto destFileName = DEST_PREFIX + fileToCopy; auto destFolder = QFileInfo(destFileName).absoluteDir(); if (!destFolder.exists()) { @@ -78,19 +116,18 @@ void unpackAndroidAssets() { } } - qDebug() << "Copying from" << sourceFileName << "to" << destFileName; - if (!QFile(sourceFileName).copy(destFileName)) { - throw std::runtime_error("Failed to unpack cache files"); - } + qDebug() << "Copying asset " << fileToCopy << "to" << destFileName; + copyAsset(fileToCopy.toStdString().c_str(), destFileName); } { qDebug() << "Writing date stamp" << dateStamp; - QFile file(dateStamp); - if (file.open(QIODevice::ReadWrite)) { - QTextStream(&file) << "touch" << endl; - file.close(); + QFile file(dateStampFilename); + if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) { + throw std::runtime_error("Can't write date stamp"); } + QTextStream(&file) << "touch" << endl; + file.close(); } } @@ -98,6 +135,7 @@ extern "C" { JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnCreate(JNIEnv* env, jobject obj, jobject instance, jobject asset_mgr) { qDebug() << "nativeOnCreate On thread " << QThread::currentThreadId(); + g_assetManager = AAssetManager_fromJava(env, asset_mgr); auto oldMessageHandler = qInstallMessageHandler(tempMessageHandler); unpackAndroidAssets(); qInstallMessageHandler(oldMessageHandler);