@@ -27,6 +27,10 @@ private var isUnzipping = false
2727class SVGAParser (context : Context ? ) {
2828 private var mContext = context?.applicationContext
2929
30+ init {
31+ SVGACache .onCreate(context)
32+ }
33+
3034 @Volatile
3135 private var mFrameWidth: Int = 0
3236
@@ -118,6 +122,7 @@ class SVGAParser(context: Context?) {
118122
119123 fun init (context : Context ) {
120124 mContext = context.applicationContext
125+ SVGACache .onCreate(mContext)
121126 }
122127
123128 fun setFrameSize (frameWidth : Int , frameHeight : Int ) {
@@ -134,7 +139,7 @@ class SVGAParser(context: Context?) {
134139 LogUtils .info(TAG , " ================ decode from assets ================" )
135140 threadPoolExecutor.execute {
136141 mContext?.assets?.open(name)?.let {
137- this .decodeFromInputStream(it, buildCacheKey(" file:///assets/$name " ), callback, true )
142+ this .decodeFromInputStream(it, SVGACache . buildCacheKey(" file:///assets/$name " ), callback, true )
138143 }
139144 }
140145 } catch (e: java.lang.Exception ) {
@@ -148,24 +153,102 @@ class SVGAParser(context: Context?) {
148153 return null
149154 }
150155 LogUtils .info(TAG , " ================ decode from url ================" )
151- return if (this .isCached(buildCacheKey(url))) {
156+ val cacheKey = SVGACache .buildCacheKey(url);
157+ return if (SVGACache .isCached(cacheKey)) {
152158 LogUtils .info(TAG , " this url cached" )
153159 threadPoolExecutor.execute {
154- this .decodeFromCacheKey(buildCacheKey(url), callback)
160+ if (SVGACache .isDefaultCache()) {
161+ this .decodeFromCacheKey(cacheKey, callback)
162+ } else {
163+ this ._decodeFromCacheKey (cacheKey, callback)
164+ }
155165 }
156- null
157- }
158- else {
166+ return null
167+ } else {
159168 LogUtils .info(TAG , " no cached, prepare to download" )
160169 fileDownloader.resume(url, {
161- this .decodeFromInputStream(it, this .buildCacheKey(url), callback)
170+ if (SVGACache .isDefaultCache()) {
171+ this .decodeFromInputStream(it, cacheKey, callback)
172+ } else {
173+ this ._decodeFromInputStream (it, cacheKey, callback)
174+ }
162175 }, {
163176 this .invokeErrorCallback(it, callback)
164177 })
165178 }
166179 }
167180
168- fun decodeFromInputStream (inputStream : InputStream , cacheKey : String , callback : ParseCompletion ? , closeInputStream : Boolean = false) {
181+ fun _decodeFromCacheKey (cacheKey : String , callback : ParseCompletion ? ) {
182+ val svga = SVGACache .buildCacheFile(cacheKey)
183+ try {
184+ LogUtils .info(TAG , " binary change to entity" )
185+ FileInputStream (svga).use {
186+ LogUtils .info(TAG , " binary change to entity success" )
187+ this .invokeCompleteCallback(
188+ SVGAVideoEntity (
189+ MovieEntity .ADAPTER .decode(it),
190+ SVGACache .buildCacheDir(cacheKey),
191+ mFrameWidth,
192+ mFrameHeight
193+ ), callback
194+ )
195+ }
196+ } catch (e: Exception ) {
197+ LogUtils .error(TAG , " binary change to entity fail" , e)
198+ SVGACache .buildCacheDir(cacheKey).delete()
199+ svga.delete()
200+ this .invokeErrorCallback(e, callback)
201+ }
202+ }
203+
204+ fun _decodeFromInputStream (
205+ inputStream : InputStream ,
206+ cacheKey : String ,
207+ callback : ParseCompletion ?
208+ ) {
209+ threadPoolExecutor.execute {
210+ try {
211+ readAsBytes(inputStream)?.let { bytes ->
212+ LogUtils .info(TAG , " decode from input stream, inflate start" )
213+ inflate(bytes)?.let { inflateBytes ->
214+ threadPoolExecutor.execute {
215+ SVGACache .buildCacheFile(cacheKey).let { cacheFile ->
216+ cacheFile.takeIf { ! it.exists() }?.createNewFile()
217+ FileOutputStream (cacheFile).write(inflateBytes)
218+ }
219+ }
220+ val videoItem = SVGAVideoEntity (
221+ MovieEntity .ADAPTER .decode(inflateBytes),
222+ File (cacheKey),
223+ mFrameWidth,
224+ mFrameHeight
225+ )
226+ videoItem.prepare {
227+ LogUtils .info(TAG , " decode from input stream, inflate end" )
228+ this .invokeCompleteCallback(videoItem, callback)
229+ }
230+ } ? : this .invokeErrorCallback(
231+ Exception (" inflate(bytes) cause exception" ),
232+ callback
233+ )
234+ } ? : this .invokeErrorCallback(
235+ Exception (" readAsBytes(inputStream) cause exception" ),
236+ callback
237+ )
238+ } catch (e: Exception ) {
239+ this .invokeErrorCallback(e, callback)
240+ } finally {
241+ inputStream.close()
242+ }
243+ }
244+ }
245+
246+ fun decodeFromInputStream (
247+ inputStream : InputStream ,
248+ cacheKey : String ,
249+ callback : ParseCompletion ? ,
250+ closeInputStream : Boolean = false
251+ ) {
169252 if (mContext == null ) {
170253 LogUtils .error(TAG , " 在配置 SVGAParser context 前, 无法解析 SVGA 文件。" )
171254 return
@@ -176,9 +259,9 @@ class SVGAParser(context: Context?) {
176259 readAsBytes(inputStream)?.let { bytes ->
177260 if (bytes.size > 4 && bytes[0 ].toInt() == 80 && bytes[1 ].toInt() == 75 && bytes[2 ].toInt() == 3 && bytes[3 ].toInt() == 4 ) {
178261 LogUtils .info(TAG , " decode from zip file" )
179- if (! buildCacheDir(cacheKey).exists() || isUnzipping) {
262+ if (! SVGACache . buildCacheDir(cacheKey).exists() || isUnzipping) {
180263 synchronized(fileLock) {
181- if (! buildCacheDir(cacheKey).exists()) {
264+ if (! SVGACache . buildCacheDir(cacheKey).exists()) {
182265 isUnzipping = true
183266 LogUtils .info(TAG , " no cached, prepare to unzip" )
184267 ByteArrayInputStream (bytes).use {
@@ -193,14 +276,26 @@ class SVGAParser(context: Context?) {
193276 } else {
194277 LogUtils .info(TAG , " decode from input stream, inflate start" )
195278 inflate(bytes)?.let {
196- val videoItem = SVGAVideoEntity (MovieEntity .ADAPTER .decode(it), File (cacheKey), mFrameWidth, mFrameHeight)
279+ val videoItem = SVGAVideoEntity (
280+ MovieEntity .ADAPTER .decode(it),
281+ File (cacheKey),
282+ mFrameWidth,
283+ mFrameHeight
284+ )
197285 videoItem.prepare {
198286 LogUtils .info(TAG , " decode from input stream, inflate end" )
199287 this .invokeCompleteCallback(videoItem, callback)
200288 }
201- } ? : LogUtils .error(TAG , " inflate(bytes) cause exception" )
289+
290+ } ? : this .invokeErrorCallback(
291+ Exception (" inflate(bytes) cause exception" ),
292+ callback
293+ )
202294 }
203- } ? : LogUtils .error(TAG , " readAsBytes(inputStream) cause exception" )
295+ } ? : this .invokeErrorCallback(
296+ Exception (" readAsBytes(inputStream) cause exception" ),
297+ callback
298+ )
204299 } catch (e: java.lang.Exception ) {
205300 this .invokeErrorCallback(e, callback)
206301 } finally {
@@ -251,10 +346,6 @@ class SVGAParser(context: Context?) {
251346 }
252347 }
253348
254- private fun isCached (cacheKey : String ): Boolean {
255- return buildCacheDir(cacheKey).exists()
256- }
257-
258349 private fun decodeFromCacheKey (cacheKey : String , callback : ParseCompletion ? ) {
259350 LogUtils .info(TAG , " ================ decode from cache ================" )
260351 LogUtils .debug(TAG , " decodeFromCacheKey called with cacheKey : $cacheKey " )
@@ -311,30 +402,14 @@ class SVGAParser(context: Context?) {
311402 }
312403 }
313404
314- private fun buildCacheKey (str : String ): String {
315- val messageDigest = MessageDigest .getInstance(" MD5" )
316- messageDigest.update(str.toByteArray(charset(" UTF-8" )))
317- val digest = messageDigest.digest()
318- var sb = " "
319- for (b in digest) {
320- sb + = String .format(" %02x" , b)
321- }
322- return sb
323- }
324-
325- private fun buildCacheKey (url : URL ): String = buildCacheKey(url.toString())
326-
327- private fun buildCacheDir (cacheKey : String ): File = File (mContext?.cacheDir?.absolutePath + " /" + cacheKey + " /" )
328-
329405 private fun readAsBytes (inputStream : InputStream ): ByteArray? {
330406 ByteArrayOutputStream ().use { byteArrayOutputStream ->
331407 val byteArray = ByteArray (2048 )
332408 while (true ) {
333409 val count = inputStream.read(byteArray, 0 , 2048 )
334410 if (count <= 0 ) {
335411 break
336- }
337- else {
412+ } else {
338413 byteArrayOutputStream.write(byteArray, 0 , count)
339414 }
340415 }
@@ -362,7 +437,7 @@ class SVGAParser(context: Context?) {
362437
363438 private fun unzip (inputStream : InputStream , cacheKey : String ) {
364439 LogUtils .info(TAG , " ================ unzip prepare ================" )
365- val cacheDir = this .buildCacheDir(cacheKey)
440+ val cacheDir = SVGACache .buildCacheDir(cacheKey)
366441 cacheDir.mkdirs()
367442 try {
368443 BufferedInputStream (inputStream).use {
0 commit comments