summaryrefslogtreecommitdiff
path: root/platform/android/src/asset_manager_file_source.cpp
blob: 404177ba956d734d442cd8a3d4a209ad0cf89b38 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include "asset_manager_file_source.hpp"

#include <mbgl/storage/file_source_request.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/util.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/util/url.hpp>

#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>

namespace mbgl {

class AssetManagerFileSource::Impl {
public:
    Impl(ActorRef<Impl>, AAssetManager* assetManager_) : assetManager(assetManager_) {
    }

    void request(const std::string& url, ActorRef<FileSourceRequest> req) {
        // Note: AssetManager already prepends "assets" to the filename.
        const std::string path = mbgl::util::percentDecode(url.substr(8));

        Response response;

        if (AAsset* asset = AAssetManager_open(assetManager, path.c_str(), AASSET_MODE_BUFFER)) {
            response.data = { { reinterpret_cast<const char*>(AAsset_getBuffer(asset)),
                                static_cast<size_t>(AAsset_getLength64(asset)) },
                              false };
            AAsset_close(asset);
        } else {
            response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound,
                                                               "Could not read asset");
        }

        req.invoke(&FileSourceRequest::setResponse, response);
    }

private:
    AAssetManager* assetManager;
};

AssetManagerFileSource::AssetManagerFileSource(jni::JNIEnv& env, jni::Object<android::AssetManager> assetManager_)
    : assetManager(assetManager_.NewGlobalRef(env)),
      impl(std::make_unique<util::Thread<Impl>>("AssetManagerFileSource",
          AAssetManager_fromJava(&env, jni::Unwrap(**assetManager)))) {
}

AssetManagerFileSource::~AssetManagerFileSource() = default;

std::unique_ptr<AsyncRequest> AssetManagerFileSource::request(const Resource& resource, Callback callback) {
    auto req = std::make_unique<FileSourceRequest>(std::move(callback));

    impl->actor().invoke(&Impl::request, resource.url, req->actor());

    return std::move(req);
}

} // namespace mbgl