@@ -27,6 +27,10 @@ private var isUnzipping = false
27
27
class SVGAParser (context : Context ? ) {
28
28
private var mContext = context?.applicationContext
29
29
30
+ init {
31
+ SVGACache .onCreate(context)
32
+ }
33
+
30
34
@Volatile
31
35
private var mFrameWidth: Int = 0
32
36
@@ -118,6 +122,7 @@ class SVGAParser(context: Context?) {
118
122
119
123
fun init (context : Context ) {
120
124
mContext = context.applicationContext
125
+ SVGACache .onCreate(mContext)
121
126
}
122
127
123
128
fun setFrameSize (frameWidth : Int , frameHeight : Int ) {
@@ -134,7 +139,7 @@ class SVGAParser(context: Context?) {
134
139
LogUtils .info(TAG , " ================ decode from assets ================" )
135
140
threadPoolExecutor.execute {
136
141
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 )
138
143
}
139
144
}
140
145
} catch (e: java.lang.Exception ) {
@@ -148,24 +153,102 @@ class SVGAParser(context: Context?) {
148
153
return null
149
154
}
150
155
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)) {
152
158
LogUtils .info(TAG , " this url cached" )
153
159
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
+ }
155
165
}
156
- null
157
- }
158
- else {
166
+ return null
167
+ } else {
159
168
LogUtils .info(TAG , " no cached, prepare to download" )
160
169
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
+ }
162
175
}, {
163
176
this .invokeErrorCallback(it, callback)
164
177
})
165
178
}
166
179
}
167
180
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
+ ) {
169
252
if (mContext == null ) {
170
253
LogUtils .error(TAG , " 在配置 SVGAParser context 前, 无法解析 SVGA 文件。" )
171
254
return
@@ -176,9 +259,9 @@ class SVGAParser(context: Context?) {
176
259
readAsBytes(inputStream)?.let { bytes ->
177
260
if (bytes.size > 4 && bytes[0 ].toInt() == 80 && bytes[1 ].toInt() == 75 && bytes[2 ].toInt() == 3 && bytes[3 ].toInt() == 4 ) {
178
261
LogUtils .info(TAG , " decode from zip file" )
179
- if (! buildCacheDir(cacheKey).exists() || isUnzipping) {
262
+ if (! SVGACache . buildCacheDir(cacheKey).exists() || isUnzipping) {
180
263
synchronized(fileLock) {
181
- if (! buildCacheDir(cacheKey).exists()) {
264
+ if (! SVGACache . buildCacheDir(cacheKey).exists()) {
182
265
isUnzipping = true
183
266
LogUtils .info(TAG , " no cached, prepare to unzip" )
184
267
ByteArrayInputStream (bytes).use {
@@ -193,14 +276,26 @@ class SVGAParser(context: Context?) {
193
276
} else {
194
277
LogUtils .info(TAG , " decode from input stream, inflate start" )
195
278
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
+ )
197
285
videoItem.prepare {
198
286
LogUtils .info(TAG , " decode from input stream, inflate end" )
199
287
this .invokeCompleteCallback(videoItem, callback)
200
288
}
201
- } ? : LogUtils .error(TAG , " inflate(bytes) cause exception" )
289
+
290
+ } ? : this .invokeErrorCallback(
291
+ Exception (" inflate(bytes) cause exception" ),
292
+ callback
293
+ )
202
294
}
203
- } ? : LogUtils .error(TAG , " readAsBytes(inputStream) cause exception" )
295
+ } ? : this .invokeErrorCallback(
296
+ Exception (" readAsBytes(inputStream) cause exception" ),
297
+ callback
298
+ )
204
299
} catch (e: java.lang.Exception ) {
205
300
this .invokeErrorCallback(e, callback)
206
301
} finally {
@@ -251,10 +346,6 @@ class SVGAParser(context: Context?) {
251
346
}
252
347
}
253
348
254
- private fun isCached (cacheKey : String ): Boolean {
255
- return buildCacheDir(cacheKey).exists()
256
- }
257
-
258
349
private fun decodeFromCacheKey (cacheKey : String , callback : ParseCompletion ? ) {
259
350
LogUtils .info(TAG , " ================ decode from cache ================" )
260
351
LogUtils .debug(TAG , " decodeFromCacheKey called with cacheKey : $cacheKey " )
@@ -311,30 +402,14 @@ class SVGAParser(context: Context?) {
311
402
}
312
403
}
313
404
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
-
329
405
private fun readAsBytes (inputStream : InputStream ): ByteArray? {
330
406
ByteArrayOutputStream ().use { byteArrayOutputStream ->
331
407
val byteArray = ByteArray (2048 )
332
408
while (true ) {
333
409
val count = inputStream.read(byteArray, 0 , 2048 )
334
410
if (count <= 0 ) {
335
411
break
336
- }
337
- else {
412
+ } else {
338
413
byteArrayOutputStream.write(byteArray, 0 , count)
339
414
}
340
415
}
@@ -362,7 +437,7 @@ class SVGAParser(context: Context?) {
362
437
363
438
private fun unzip (inputStream : InputStream , cacheKey : String ) {
364
439
LogUtils .info(TAG , " ================ unzip prepare ================" )
365
- val cacheDir = this .buildCacheDir(cacheKey)
440
+ val cacheDir = SVGACache .buildCacheDir(cacheKey)
366
441
cacheDir.mkdirs()
367
442
try {
368
443
BufferedInputStream (inputStream).use {
0 commit comments