Skip to content
This repository has been archived by the owner on Feb 6, 2023. It is now read-only.

Commit

Permalink
Merge pull request #382 from svga/perf_sound_pool_feature
Browse files Browse the repository at this point in the history
SVGASoundManager 优化以及其他 issue 修复
  • Loading branch information
PonyCui authored Aug 18, 2021
2 parents ffb1656 + 7616a13 commit d2ca3e6
Show file tree
Hide file tree
Showing 15 changed files with 448 additions and 218 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# SVGAPlayer-Android CHANGELOG (2021-03-02)

## [2.6.0](2021-08-18)

## Features

* feat(SVGASoundManager): Added SVGASoundManager to control SVGA audio, you need to manually call the init method to initialize, otherwise follow the default audio loading logic.
* feat(SVGAParser): SVGAParser#decodeFromAssets and SVGAParser#decodeFromURL add a parameter, which can be null. It is used to send the audio file back to the developer. The developer can control the audio playback by himself. If this parameter is set, the audio part will not be processed internally.
* feat(SVGAParser): Add aliases to the log section to facilitate developers to troubleshoot problems
* feat(SVGACache): Open cache cleaning method: SVGACache#clearCache().

### Bug Fixes

* refactor(ILogger): Remove redundant api.
* fix(SoundPool): Added SVGASoundManager to solve the problem that the internal SoundPool does not load audio occasionally.
* fix(SVGAParser): Zip Path Traversal Vulnerability.
* fix(SVGAParser): link reuse problem.

## [2.5.15](https://github.com/svga/SVGAPlayer-Android/compare/2.5.14...2.5.15) (2021-03-02)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void onClick(View view) {
}
});
SVGALogger.INSTANCE.setLogEnabled(true);
SVGASoundManager.Companion.get().init();
SVGASoundManager.INSTANCE.init();
loadAnimation();
setContentView(animationView);
}
Expand Down
66 changes: 56 additions & 10 deletions library/src/main/java/com/opensource/svgaplayer/SVGACache.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
package com.opensource.svgaplayer

import android.content.Context
import com.opensource.svgaplayer.utils.log.LogUtils
import java.io.File
import java.net.URL
import java.security.MessageDigest


/**
* SVGA 缓存管理
*/
object SVGACache {
enum class Type {
DEFAULT,
FILE
}

private const val TAG = "SVGACache"
private var type: Type = Type.DEFAULT
private var cacheDir: String = "/"
get() {
if (field != "/") {
val dir = File(field)
if (!dir.exists()) {
dir.mkdirs()
}
}
return field
}


fun onCreate(context: Context?) {
onCreate(context, Type.DEFAULT)
Expand All @@ -27,22 +41,54 @@ object SVGACache {
this.type = type
}

// fun clearCache(context: Context?){
// context ?: return
// cacheDir = "${context.cacheDir.absolutePath}/svga/"
// File(cacheDir).takeIf { it.exists() }?.delete()
// }
/**
* 清理缓存
*/
fun clearCache() {
if (!isInitialized()) {
LogUtils.error(TAG, "SVGACache is not init!")
return
}
SVGAParser.threadPoolExecutor.execute {
clearDir(cacheDir)
LogUtils.info(TAG, "Clear svga cache done!")
}
}

// 清除目录下的所有文件
internal fun clearDir(path: String) {
try {
val dir = File(path)
dir.takeIf { it.exists() }?.let { parentDir ->
parentDir.listFiles()?.forEach { file ->
if (!file.exists()) {
return@forEach
}
if (file.isDirectory) {
clearDir(file.absolutePath)
}
file.delete()
}
}
} catch (e: Exception) {
LogUtils.error(TAG, "Clear svga cache path: $path fail", e)
}
}

fun isInitialized(): Boolean {
return "/" != cacheDir&&File(cacheDir).exists()
return "/" != cacheDir && File(cacheDir).exists()
}

fun isDefaultCache(): Boolean = type == Type.DEFAULT

fun isCached(cacheKey: String): Boolean {
return (if (isDefaultCache()) buildCacheDir(cacheKey) else buildSvgaFile(
cacheKey
)).exists()
return if (isDefaultCache()) {
buildCacheDir(cacheKey)
} else {
buildSvgaFile(
cacheKey
)
}.exists()
}

fun buildCacheKey(str: String): String {
Expand Down
16 changes: 8 additions & 8 deletions library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE
fun resume() {
videoItem.audioList.forEach { audio ->
audio.playID?.let {
if (SVGASoundManager.get().isInit()){
SVGASoundManager.get().resume(it)
if (SVGASoundManager.isInit()){
SVGASoundManager.resume(it)
}else{
videoItem.soundPool?.resume(it)
}
Expand All @@ -69,8 +69,8 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE
fun pause() {
videoItem.audioList.forEach { audio ->
audio.playID?.let {
if (SVGASoundManager.get().isInit()){
SVGASoundManager.get().pause(it)
if (SVGASoundManager.isInit()){
SVGASoundManager.pause(it)
}else{
videoItem.soundPool?.pause(it)
}
Expand All @@ -81,8 +81,8 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE
fun stop() {
videoItem.audioList.forEach { audio ->
audio.playID?.let {
if (SVGASoundManager.get().isInit()){
SVGASoundManager.get().stop(it)
if (SVGASoundManager.isInit()){
SVGASoundManager.stop(it)
}else{
videoItem.soundPool?.stop(it)
}
Expand All @@ -93,8 +93,8 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE
fun clear() {
videoItem.audioList.forEach { audio ->
audio.playID?.let {
if (SVGASoundManager.get().isInit()){
SVGASoundManager.get().stop(it)
if (SVGASoundManager.isInit()){
SVGASoundManager.stop(it)
}else{
videoItem.soundPool?.stop(it)
}
Expand Down
58 changes: 38 additions & 20 deletions library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.animation.LinearInterpolator
Expand All @@ -19,22 +18,32 @@ import java.net.URL
/**
* Created by PonyCui on 2017/3/29.
*/
open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
: ImageView(context, attrs, defStyleAttr) {
open class SVGAImageView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ImageView(context, attrs, defStyleAttr) {

private val TAG = "SVGAImageView"

enum class FillMode {
Backward,
Forward,
Clear,
}

var isAnimating = false
private set

var loops = 0
var clearsAfterStop = true
var clearsAfterDetached = true

@Deprecated(
"It is recommended to use clearAfterDetached, or manually call to SVGAVideoEntity#clear." +
"If you just consider cleaning up the canvas after playing, you can use FillMode#Clear.",
level = DeprecationLevel.WARNING
)
var clearsAfterStop = false
var clearsAfterDetached = false
var fillMode: FillMode = FillMode.Forward
var callback: SVGACallback? = null

Expand All @@ -57,15 +66,21 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr
private fun loadAttrs(attrs: AttributeSet) {
val typedArray = context.theme.obtainStyledAttributes(attrs, R.styleable.SVGAImageView, 0, 0)
loops = typedArray.getInt(R.styleable.SVGAImageView_loopCount, 0)
clearsAfterStop = typedArray.getBoolean(R.styleable.SVGAImageView_clearsAfterStop, true)
clearsAfterDetached = typedArray.getBoolean(R.styleable.SVGAImageView_clearsAfterDetached, true)
clearsAfterStop = typedArray.getBoolean(R.styleable.SVGAImageView_clearsAfterStop, false)
clearsAfterDetached = typedArray.getBoolean(R.styleable.SVGAImageView_clearsAfterDetached, false)
mAntiAlias = typedArray.getBoolean(R.styleable.SVGAImageView_antiAlias, true)
mAutoPlay = typedArray.getBoolean(R.styleable.SVGAImageView_autoPlay, true)
typedArray.getString(R.styleable.SVGAImageView_fillMode)?.let {
if (it == "0") {
fillMode = FillMode.Backward
} else if (it == "1") {
fillMode = FillMode.Forward
when (it) {
"0" -> {
fillMode = FillMode.Backward
}
"1" -> {
fillMode = FillMode.Forward
}
"2" -> {
fillMode = FillMode.Clear
}
}
}
typedArray.getString(R.styleable.SVGAImageView_source)?.let {
Expand Down Expand Up @@ -178,16 +193,19 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr
isAnimating = false
stopAnimation()
val drawable = getSVGADrawable()
if (!clearsAfterStop && drawable != null) {
if (fillMode == FillMode.Backward) {
drawable.currentFrame = mStartFrame
} else if (fillMode == FillMode.Forward) {
drawable.currentFrame = mEndFrame
if (drawable != null) {
when (fillMode) {
FillMode.Backward -> {
drawable.currentFrame = mStartFrame
}
FillMode.Forward -> {
drawable.currentFrame = mEndFrame
}
FillMode.Clear -> {
drawable.cleared = true
}
}
}
if (clearsAfterStop && (animation as ValueAnimator).repeatCount <= 0) {
clear()
}
callback?.onFinished()
}

Expand Down Expand Up @@ -274,7 +292,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr

override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
stopAnimation(true)
stopAnimation(clearsAfterDetached)
if (clearsAfterDetached) {
clear()
}
Expand Down
Loading

0 comments on commit d2ca3e6

Please sign in to comment.