Skip to content

Commit b93a4fa

Browse files
committed
fix(SVGAParser): 修复 SVGACache type 为 FILE 类型时,svga 播放失败
1 parent 629d06c commit b93a4fa

File tree

1 file changed

+66
-115
lines changed

1 file changed

+66
-115
lines changed

library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt

Lines changed: 66 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -180,148 +180,79 @@ class SVGAParser(context: Context?) {
180180
if (SVGACache.isDefaultCache()) {
181181
this.decodeFromCacheKey(cacheKey, callback, alias = urlPath)
182182
} else {
183-
this._decodeFromCacheKey(cacheKey, callback, playCallback, alias = urlPath)
183+
this.decodeFromSVGAFileCacheKey(cacheKey, callback, playCallback, alias = urlPath)
184184
}
185185
}
186186
return null
187187
} else {
188188
LogUtils.info(TAG, "no cached, prepare to download")
189189
fileDownloader.resume(url, {
190-
if (SVGACache.isDefaultCache()) {
191-
this.decodeFromInputStream(
192-
it,
193-
cacheKey,
194-
callback,
195-
false,
196-
playCallback,
197-
alias = urlPath
198-
)
199-
} else {
200-
this._decodeFromInputStream(
201-
it,
202-
cacheKey,
203-
callback,
204-
playCallback,
205-
alias = urlPath
206-
)
207-
}
190+
this.decodeFromInputStream(
191+
it,
192+
cacheKey,
193+
callback,
194+
false,
195+
playCallback,
196+
alias = urlPath
197+
)
208198
}, {
209199
LogUtils.error(
210-
TAG,
211-
"================ svga file: $url download fail ================"
200+
TAG,
201+
"================ svga file: $url download fail ================"
212202
)
213203
this.invokeErrorCallback(it, callback, alias = urlPath)
214204
})
215205
}
216206
}
217207

218208
/**
219-
* 读取解析本地缓存的svga文件.
209+
* 读取解析本地缓存的 svga 文件.
220210
*/
221-
fun _decodeFromCacheKey(
211+
fun decodeFromSVGAFileCacheKey(
222212
cacheKey: String,
223213
callback: ParseCompletion?,
224214
playCallback: PlayCallback?,
225215
alias: String? = null
226216
) {
227-
val svga = SVGACache.buildSvgaFile(cacheKey)
228-
try {
229-
LogUtils.info(TAG, "$alias cache.binary change to entity")
230-
FileInputStream(svga).use { inputStream ->
231-
try {
217+
threadPoolExecutor.execute {
218+
try {
219+
LogUtils.info(TAG, "================ decode $alias from svga cachel file to entity ================")
220+
FileInputStream(SVGACache.buildSvgaFile(cacheKey)).use { inputStream ->
232221
readAsBytes(inputStream)?.let { bytes ->
233-
LogUtils.info(TAG, "cache.inflate start")
234-
inflate(bytes)?.let { inflateBytes ->
235-
LogUtils.info(TAG, "cache.inflate success")
236-
val videoItem = SVGAVideoEntity(
237-
MovieEntity.ADAPTER.decode(inflateBytes),
222+
if (isZipFile(bytes)) {
223+
this.decodeFromCacheKey(cacheKey, callback, alias)
224+
} else {
225+
LogUtils.info(TAG, "inflate start")
226+
inflate(bytes)?.let {
227+
LogUtils.info(TAG, "inflate complete")
228+
val videoItem = SVGAVideoEntity(
229+
MovieEntity.ADAPTER.decode(it),
238230
File(cacheKey),
239231
mFrameWidth,
240232
mFrameHeight
233+
)
234+
LogUtils.info(TAG, "SVGAVideoEntity prepare start")
235+
videoItem.prepare({
236+
LogUtils.info(TAG, "SVGAVideoEntity prepare success")
237+
this.invokeCompleteCallback(videoItem, callback, alias)
238+
},playCallback)
239+
240+
} ?: this.invokeErrorCallback(
241+
Exception("inflate(bytes) cause exception"),
242+
callback,
243+
alias
241244
)
242-
videoItem.prepare({
243-
LogUtils.info(TAG, "cache.prepare success")
244-
this.invokeCompleteCallback(videoItem, callback, alias)
245-
},playCallback)
246-
} ?: doError("cache.inflate(bytes) cause exception", callback, alias)
247-
} ?: doError("cache.readAsBytes(inputStream) cause exception", callback, alias)
248-
} catch (e: Exception) {
249-
this.invokeErrorCallback(e, callback, alias)
250-
} finally {
251-
inputStream.close()
252-
}
253-
}
254-
} catch (e: Exception) {
255-
LogUtils.error(TAG, "$alias cache.binary change to entity fail", e)
256-
svga.takeIf { it.exists() }?.delete()
257-
this.invokeErrorCallback(e, callback, alias)
258-
}
259-
}
260-
261-
private fun doError(
262-
error: String,
263-
callback: ParseCompletion?,
264-
alias: String?
265-
) {
266-
LogUtils.info(TAG, error)
267-
this.invokeErrorCallback(
268-
Exception(error),
269-
callback,
270-
alias
271-
)
272-
}
273-
274-
/**
275-
* 读取解析来自URL的svga文件.并缓存成本地文件
276-
*/
277-
fun _decodeFromInputStream(
278-
inputStream: InputStream,
279-
cacheKey: String,
280-
callback: ParseCompletion?,
281-
playCallback: PlayCallback?,
282-
alias: String? = null
283-
) {
284-
threadPoolExecutor.execute {
285-
try {
286-
LogUtils.info(TAG, "================ $alias _inputStream change to entity ================")
287-
readAsBytes(inputStream)?.let { bytes ->
288-
threadPoolExecutor.execute {
289-
SVGACache.buildSvgaFile(cacheKey).let { cacheFile ->
290-
try {
291-
cacheFile.takeIf { !it.exists() }?.createNewFile()
292-
FileOutputStream(cacheFile).write(bytes)
293-
} catch (e: Exception) {
294-
LogUtils.error(TAG, "create cache file fail.", e)
295-
cacheFile.delete()
296-
}
297245
}
298-
}
299-
LogUtils.info(TAG, "inputStream inflate start")
300-
inflate(bytes)?.let { inflateBytes ->
301-
LogUtils.info(TAG, "inputStream inflate success")
302-
val videoItem = SVGAVideoEntity(
303-
MovieEntity.ADAPTER.decode(inflateBytes),
304-
File(cacheKey),
305-
mFrameWidth,
306-
mFrameHeight
307-
)
308-
// 里面soundPool如果解析时load同一个svga的声音文件会出现无回调的情况,导致这里的callback不执行,
309-
// 原因暂时未知.目前解决方案是公开imageview,drawable,entity的clear(),然后在播放带声音
310-
// 的svgaimageview处,把解析完的drawable或者entity缓存下来,下次直接播放.用完再调用clear()
311-
// 在ImageView添加clearsAfterDetached,用于控制imageview在onDetach的时候是否要自动调用clear.
312-
// 以暂时缓解需要为RecyclerView缓存drawable或者entity的人士.用完记得调用clear()
313-
LogUtils.info(TAG, "SVGAVideoEntity prepare start")
314-
videoItem.prepare({
315-
LogUtils.info(TAG, "SVGAVideoEntity prepare success")
316-
this.invokeCompleteCallback(videoItem, callback, alias)
317-
}, playCallback)
318-
} ?: doError("inflate(bytes) cause exception", callback, alias)
319-
} ?: doError("readAsBytes(inputStream) cause exception", callback, alias)
320-
} catch (e: Exception) {
246+
} ?: this.invokeErrorCallback(
247+
Exception("readAsBytes(inputStream) cause exception"),
248+
callback,
249+
alias
250+
)
251+
}
252+
} catch (e: java.lang.Exception) {
321253
this.invokeErrorCallback(e, callback, alias)
322254
} finally {
323-
inputStream.close()
324-
LogUtils.info(TAG, "================ $alias _inputStream change to entity end ================")
255+
LogUtils.info(TAG, "================ decode $alias from svga cachel file to entity end ================")
325256
}
326257
}
327258
}
@@ -331,7 +262,7 @@ class SVGAParser(context: Context?) {
331262
cacheKey: String,
332263
callback: ParseCompletion?,
333264
closeInputStream: Boolean = false,
334-
playCallback: PlayCallback?=null,
265+
playCallback: PlayCallback? = null,
335266
alias: String? = null
336267
) {
337268
if (mContext == null) {
@@ -342,7 +273,7 @@ class SVGAParser(context: Context?) {
342273
threadPoolExecutor.execute {
343274
try {
344275
readAsBytes(inputStream)?.let { bytes ->
345-
if (bytes.size > 4 && bytes[0].toInt() == 80 && bytes[1].toInt() == 75 && bytes[2].toInt() == 3 && bytes[3].toInt() == 4) {
276+
if (isZipFile(bytes)) {
346277
LogUtils.info(TAG, "decode from zip file")
347278
if (!SVGACache.buildCacheDir(cacheKey).exists() || isUnzipping) {
348279
synchronized(fileLock) {
@@ -359,6 +290,20 @@ class SVGAParser(context: Context?) {
359290
}
360291
this.decodeFromCacheKey(cacheKey, callback, alias)
361292
} else {
293+
if (!SVGACache.isDefaultCache()) {
294+
// 如果 SVGACache 设置类型为 FILE
295+
threadPoolExecutor.execute {
296+
SVGACache.buildSvgaFile(cacheKey).let { cacheFile ->
297+
try {
298+
cacheFile.takeIf { !it.exists() }?.createNewFile()
299+
FileOutputStream(cacheFile).write(bytes)
300+
} catch (e: Exception) {
301+
LogUtils.error(TAG, "create cache file fail.", e)
302+
cacheFile.delete()
303+
}
304+
}
305+
}
306+
}
362307
LogUtils.info(TAG, "inflate start")
363308
inflate(bytes)?.let {
364309
LogUtils.info(TAG, "inflate complete")
@@ -561,6 +506,12 @@ class SVGAParser(context: Context?) {
561506
}
562507
}
563508

509+
// 是否是 zip 文件
510+
private fun isZipFile(bytes: ByteArray): Boolean {
511+
return bytes.size > 4 && bytes[0].toInt() == 80 && bytes[1].toInt() == 75 && bytes[2].toInt() == 3 && bytes[3].toInt() == 4
512+
}
513+
514+
// 解压
564515
private fun unzip(inputStream: InputStream, cacheKey: String) {
565516
LogUtils.info(TAG, "================ unzip prepare ================")
566517
val cacheDir = SVGACache.buildCacheDir(cacheKey)

0 commit comments

Comments
 (0)