AndroidAssetResourceProvider.cpp
Go to the documentation of this file.
2 
3 #if IV_ENABLE_ANDROID_JNI
4 
6 
7 #include <android/asset_manager.h>
8 #include <android/asset_manager_jni.h>
9 #include <glfm.h>
10 #include <array>
11 
12 #include <fstream>
13 
14 namespace iv
15 {
16 
17 class AndroidAsset_streambuf : public std::streambuf
18 {
19 public:
20  static constexpr int const BufferCapacity = 128;
21 
22  AndroidAsset_streambuf( AAsset * asset, ClientMarker const * cm ) :
23  cm( cm ),
24  asset( asset ),
25  buffer(),
26  bufsize( 0 ),
27  bufpos( 0 )
28  {
29  }
30 
31  ~AndroidAsset_streambuf()
32  {
33  }
34 
35  virtual int underflow() override
36  {
37  // read data to buffer
38  int received = AAsset_read( this->asset, this->buffer.data(), AndroidAsset_streambuf::BufferCapacity );
39 
40  // check data status
41  if( received < 0 )
42  this->cm->warning( SRC_INFO, "Failed to read android asset data (errcode ", received, ")." );
43 
44  if( received <= 0 )
45  return traits_type::eof();
46 
47  // assign buffer
48  setg( this->buffer.data(), this->buffer.data(), this->buffer.data() + received );
49 
50  // return success
51  return traits_type::to_int_type( *gptr() );
52  }
53 
54 private:
55  ClientMarker const * cm;
56  AAsset * asset;
57 
58  std::array< char, AndroidAsset_streambuf::BufferCapacity > buffer;
59  int bufsize;
60  int bufpos;
61 };
62 
63 class AndroidAsset_istream : public std::istream
64 {
65 public:
66  AndroidAsset_istream( AAsset * asset, ClientMarker const * cm ) :
67  std::istream( new AndroidAsset_streambuf( asset, cm ) )
68  {
69  }
70 
71  ~AndroidAsset_istream()
72  {
73  delete this->rdbuf();
74  }
75 };
76 
77 static AAssetManager * l_GetAndroidAssetManager()
78 {
79  return glfmAndroidGetActivity()->assetManager;
80 }
81 
82 AndroidAssetResourceProvider::AndroidAssetResourceProvider( Instance * inst, size_t priority, std::string const & root_path ) :
83  StreamResourceProvider( inst, priority ),
84  cm( inst, this, "AndroidAssetResourceProvider" ),
85  root( root_path )
86 {
87  this->cm.inherits( this->StreamResourceProvider::cm );
88 }
89 
90 void AndroidAssetResourceProvider::with_stream( ResourcePath const & path, std::function< void( std::istream & ) > const & f ) const
91 {
92  LambdaLogTrace _log_trace(
93  [&]( std::ostream & out )
94  {
95  out << "Android asset '" << this->toFsPath( path ) << "':" << std::endl;
96  }
97  );
98 
99  // get input filename
100  //std::string rpath = this->toFsPath( path );
101  std::string rpath = path.string();
102  if( rpath.size() > 0 )
103  rpath.erase( 0, 1 );
104 
105  // open stream
106  AAsset * asset = AAssetManager_open( l_GetAndroidAssetManager(), rpath.c_str(), AASSET_MODE_STREAMING );
107 
108  if( !asset )
109  {
110  this->cm.warning( SRC_INFO, "Failed to open android asset '", rpath, "'." );
111  return;
112  }
113 
114  AndroidAsset_istream in( asset, &this->cm );
115 
116  f( in );
117 
118  AAsset_close( asset );
119 }
120 
121 void AndroidAssetResourceProvider::with_metadata_stream( std::function< void( std::istream & ) > const & f ) const
122 {
123  this->with_stream( ResourcePath( "/metadata.json" ), f );
124 }
125 
126 /*
127 static void PrintDir( AAssetManager * asset_manager, const char * dirpath )
128 {
129  auto dir = AAssetManager_openDir( asset_manager, dirpath );
130  if( dir )
131  {
132  TextOutput << "AndroidAssetResourceProvider: dir '"<<dirpath<<"': " << endl;
133  while( auto name = AAssetDir_getNextFileName( dir ) )
134  TextOutput << " '" << name << "'" << endl;
135  AAssetDir_close( dir );
136  }
137  else
138  {
139  TextOutput << "AndroidAssetResourceProvider: dir '"<<dirpath<<"': <failed to open>" << endl;
140  }
141 }
142 */
143 /*
144 bool AndroidAssetResourceProvider::has_stream_path( ResourcePath const & path )
145 {
146  // join paths
147  std::string rpath = this->toFsPath( path );
148 
149  // try to open it
150  AAsset * asset = AAssetManager_open( l_GetAndroidAssetManager(), rpath.c_str(), AASSET_MODE_STREAMING );
151 
152  if( !asset )
153  return false;
154 
155  AAsset_close( asset );
156 
157  return true;
158 }
159 */
160 std::string AndroidAssetResourceProvider::toFsPath( ResourcePath path ) const
161 {
162  return path.to_real_path( this->root.c_str() );
163 }
164 
165 }
166 
167 #endif