From 3c81ee74104845d47afffe8bed8bf30986c73c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Sat, 4 Jul 2020 19:53:18 +0800 Subject: [PATCH 01/33] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E6=9B=BF=E6=8D=A2=20SVGAImageView=20=E5=86=85?= =?UTF-8?q?=E5=BC=82=E6=AD=A5=E8=A7=A3=E6=9E=90=E6=95=B0=E6=8D=AE=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../opensource/svgaplayer/SVGAImageView.kt | 144 ++++++++---------- 1 file changed, 61 insertions(+), 83 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index 557845ea..20a181fe 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -12,13 +12,17 @@ import android.view.View import android.view.animation.LinearInterpolator import android.widget.ImageView import com.opensource.svgaplayer.utils.SVGARange +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import java.lang.ref.WeakReference import java.net.URL /** * Created by PonyCui on 2017/3/29. */ -open class SVGAImageView : ImageView { +@Suppress("NewApi") +open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0) + : ImageView(context, attrs, defStyleAttr, defStyleRes) { enum class FillMode { Backward, @@ -35,7 +39,7 @@ open class SVGAImageView : ImageView { private var mVideoItem: SVGAVideoEntity? = null private var mAnimator: ValueAnimator? = null - private var mItemClickAreaListener : SVGAClickAreaListener? = null + private var mItemClickAreaListener: SVGAClickAreaListener? = null private var mAntiAlias = true private var mAutoPlay = true private var mDrawable: SVGADrawable? = null @@ -44,29 +48,11 @@ open class SVGAImageView : ImageView { private var mStartFrame = 0 private var mEndFrame = 0 - constructor(context: Context?) : super(context) { - setSoftwareLayerType() - } - - constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) { - setSoftwareLayerType() - attrs?.let { loadAttrs(it) } - } - - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { - setSoftwareLayerType() - attrs?.let { loadAttrs(it) } - } - - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { - setSoftwareLayerType() - attrs?.let { loadAttrs(it) } - } - - private fun setSoftwareLayerType() { + init { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { - this.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + this.setLayerType(View.LAYER_TYPE_SOFTWARE, null) } + attrs?.let { loadAttrs(it) } } private fun loadAttrs(attrs: AttributeSet) { @@ -78,17 +64,41 @@ open class SVGAImageView : ImageView { typedArray.getString(R.styleable.SVGAImageView_fillMode)?.let { if (it == "0") { fillMode = FillMode.Backward - } - else if (it == "1") { + } else if (it == "1") { fillMode = FillMode.Forward } } typedArray.getString(R.styleable.SVGAImageView_source)?.let { - ParserSourceThread(this, it).start() + parserSource(it) } typedArray.recycle() } + private fun parserSource(source: String) { + // 使用弱引用解决内存泄漏 + val ref = WeakReference(this) + + // 在后台启动一个新的协程并继续 + GlobalScope.launch { + val parser = SVGAParser(context) + if (source.startsWith("http://") || source.startsWith("https://")) { + parser.decodeFromURL(URL(source), createParseCompletion(ref)) + } else { + parser.decodeFromAssets(source, createParseCompletion(ref)) + } + } + } + + private fun createParseCompletion(ref: WeakReference): SVGAParser.ParseCompletion { + return object : SVGAParser.ParseCompletion { + override fun onComplete(videoItem: SVGAVideoEntity) { + ref.get()?.startAnimation(videoItem) + } + + override fun onError() {} + } + } + private fun startAnimation(videoItem: SVGAVideoEntity) { this@SVGAImageView.post { videoItem.antiAlias = mAntiAlias @@ -113,10 +123,9 @@ open class SVGAImageView : ImageView { } private fun play(range: SVGARange?, it: SVGAVideoEntity, drawable: SVGADrawable, reverse: Boolean) { - mDrawable = drawable; + mDrawable = drawable mStartFrame = Math.max(0, range?.location ?: 0) - mEndFrame = Math.min(it.frames - 1, ((range?.location ?: 0) + (range?.length - ?: Int.MAX_VALUE) - 1)) + mEndFrame = Math.min(it.frames - 1, ((range?.location ?: 0) + (range?.length ?: Int.MAX_VALUE) - 1)) val animator = ValueAnimator.ofInt(mStartFrame, mEndFrame) animator.interpolator = LinearInterpolator() animator.duration = ((mEndFrame - mStartFrame + 1) * (1000 / it.FPS) / generateScale()).toLong() @@ -135,20 +144,17 @@ open class SVGAImageView : ImageView { private fun generateScale(): Double { var scale = 1.0 try { - val animatorClass = Class.forName("android.animation.ValueAnimator") - animatorClass?.let { clazz -> - clazz.getDeclaredField("sDurationScale")?.let { field -> - field.isAccessible = true - field.getFloat(animatorClass).let { value -> - scale = value.toDouble() - } - if (scale == 0.0) { - field.setFloat(animatorClass, 1.0f) - scale = 1.0 - Log.e("SVGAPlayer", "The animation duration scale has been reset to 1.0x," + - " because you closed it on developer options.") - } - } + val animatorClass = Class.forName("android.animation.ValueAnimator") ?: return scale + val field = animatorClass.getDeclaredField("sDurationScale") ?: return scale + field.isAccessible = true + field.getFloat(animatorClass).let { value -> + scale = value.toDouble() + } + if (scale == 0.0) { + field.setFloat(animatorClass, 1.0f) + scale = 1.0 + Log.e("SVGAPlayer", "The animation duration scale has been reset to 1.0x," + + " because you closed it on developer options.") } } catch (ignore: Exception) { } @@ -169,9 +175,9 @@ open class SVGAImageView : ImageView { stopAnimation() if (!clearsAfterStop) { if (fillMode == FillMode.Backward) { - mDrawable!!.currentFrame = mStartFrame + mDrawable?.currentFrame = mStartFrame } else if (fillMode == FillMode.Forward) { - mDrawable!!.currentFrame = mEndFrame + mDrawable?.currentFrame = mEndFrame } } callback?.onFinished() @@ -241,14 +247,15 @@ open class SVGAImageView : ImageView { return super.onTouchEvent(event) } event?.let { - if(event.action == MotionEvent.ACTION_DOWN){ - val drawable = drawable as? SVGADrawable ?: return false - for((key,value) in drawable.dynamicItem.mClickMap){ - if (event.x >= value[0] && event.x <= value[2] && event.y >= value[1] && event.y <= value[3]) { - mItemClickAreaListener?.let { - it.onClick(key) - return true - } + if(event.action != MotionEvent.ACTION_DOWN) { + return super.onTouchEvent(event) + } + val drawable = drawable as? SVGADrawable ?: return false + for ((key, value) in drawable.dynamicItem.mClickMap) { + if (event.x >= value[0] && event.x <= value[2] && event.y >= value[1] && event.y <= value[3]) { + mItemClickAreaListener?.let { + it.onClick(key) + return true } } } @@ -274,35 +281,6 @@ open class SVGAImageView : ImageView { } } - /** - * 解析资源线程,不持有外部引用 - */ - private class ParserSourceThread(view: SVGAImageView, val source: String) : Thread() { - /** - * 使用弱引用解决内存泄漏 - */ - private val weakReference = WeakReference(view) - private val parser = SVGAParser(view.context) - - override fun run() { - if (source.startsWith("http://") || source.startsWith("https://")) { - parser.parse(URL(source), createCallback()) - } else { - parser.parse(source, createCallback()) - } - } - - private fun createCallback(): SVGAParser.ParseCompletion { - return object : SVGAParser.ParseCompletion { - override fun onComplete(videoItem: SVGAVideoEntity) { - weakReference.get()?.startAnimation(videoItem) - } - - override fun onError() {} - } - } - } // end of ParserSourceThread - private class AnimatorListener(view: SVGAImageView) : Animator.AnimatorListener { private val weakReference = WeakReference(view) @@ -331,4 +309,4 @@ open class SVGAImageView : ImageView { weakReference.get()?.onAnimatorUpdate(animation) } } // end of AnimatorUpdateListener -} +} \ No newline at end of file From 0c53982c441440693904e777d751c254470a0d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 12:38:05 +0800 Subject: [PATCH 02/33] =?UTF-8?q?fix=20SVGAImageView=20=E5=86=85=E5=AD=98?= =?UTF-8?q?=E5=9B=9E=E6=94=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../opensource/svgaplayer/SVGAImageView.kt | 98 ++++++++++--------- .../com/opensource/svgaplayer/SVGAParser.kt | 5 +- .../opensource/svgaplayer/SVGAVideoEntity.kt | 25 ++--- .../svgaplayer/utils/BitmapUtils.kt | 78 +++++++++++++++ 4 files changed, 147 insertions(+), 59 deletions(-) create mode 100644 library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index 20a181fe..333466db 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -37,12 +37,10 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr var fillMode: FillMode = FillMode.Forward var callback: SVGACallback? = null - private var mVideoItem: SVGAVideoEntity? = null private var mAnimator: ValueAnimator? = null private var mItemClickAreaListener: SVGAClickAreaListener? = null private var mAntiAlias = true private var mAutoPlay = true - private var mDrawable: SVGADrawable? = null private val mAnimatorListener = AnimatorListener(this) private val mAnimatorUpdateListener = AnimatorUpdateListener(this) private var mStartFrame = 0 @@ -116,22 +114,21 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr fun startAnimation(range: SVGARange?, reverse: Boolean = false) { stopAnimation(false) - val drawable = drawable as? SVGADrawable ?: return - drawable.cleared = false - drawable.scaleType = scaleType - play(range, drawable.videoItem, drawable, reverse) + play(range, reverse) } - private fun play(range: SVGARange?, it: SVGAVideoEntity, drawable: SVGADrawable, reverse: Boolean) { - mDrawable = drawable + private fun play(range: SVGARange?, reverse: Boolean) { + val drawable = getSVGADrawable() ?: return + setupDrawable() mStartFrame = Math.max(0, range?.location ?: 0) - mEndFrame = Math.min(it.frames - 1, ((range?.location ?: 0) + (range?.length ?: Int.MAX_VALUE) - 1)) + val videoItem = drawable.videoItem + mEndFrame = Math.min(videoItem.frames - 1, ((range?.location ?: 0) + (range?.length ?: Int.MAX_VALUE) - 1)) val animator = ValueAnimator.ofInt(mStartFrame, mEndFrame) animator.interpolator = LinearInterpolator() - animator.duration = ((mEndFrame - mStartFrame + 1) * (1000 / it.FPS) / generateScale()).toLong() + animator.duration = ((mEndFrame - mStartFrame + 1) * (1000 / videoItem.FPS) / generateScale()).toLong() animator.repeatCount = if (loops <= 0) 99999 else loops - 1 animator.addUpdateListener(mAnimatorUpdateListener) - animator.addListener(mAnimatorListener); + animator.addListener(mAnimatorListener) if (reverse) { animator.reverse() } else { @@ -140,6 +137,19 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr mAnimator = animator } + private fun setupDrawable() { + val drawable = getSVGADrawable() ?: return + drawable.cleared = false + drawable.scaleType = scaleType + drawable.videoItem.reqHeight = height + drawable.videoItem.reqWidth = width + Log.d("SVGAImageView", "height:$height width:$width") + } + + private fun getSVGADrawable(): SVGADrawable? { + return drawable as? SVGADrawable + } + @Suppress("UNNECESSARY_SAFE_CALL") private fun generateScale(): Double { var scale = 1.0 @@ -162,25 +172,25 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr } private fun onAnimatorUpdate(animator: ValueAnimator?) { - if (mDrawable == null) { - return - } - mDrawable!!.currentFrame = animator?.animatedValue as Int - val percentage = (mDrawable!!.currentFrame + 1).toDouble() / mDrawable!!.videoItem.frames.toDouble() - callback?.onStep(mDrawable!!.currentFrame, percentage) + val drawable = getSVGADrawable() ?: return + drawable.currentFrame = animator?.animatedValue as Int + val percentage = (drawable.currentFrame + 1).toDouble() / drawable.videoItem.frames.toDouble() + callback?.onStep(drawable.currentFrame, percentage) } private fun onAnimationEnd(animation: Animator?) { isAnimating = false stopAnimation() - if (!clearsAfterStop) { + val drawable = getSVGADrawable() + if (!clearsAfterStop && drawable != null) { if (fillMode == FillMode.Backward) { - mDrawable?.currentFrame = mStartFrame + drawable.currentFrame = mStartFrame } else if (fillMode == FillMode.Forward) { - mDrawable?.currentFrame = mEndFrame + drawable.currentFrame = mEndFrame } } callback?.onFinished() + stopAnimation(true) } fun pauseAnimation() { @@ -196,8 +206,19 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr mAnimator?.cancel() mAnimator?.removeAllListeners() mAnimator?.removeAllUpdateListeners() - (drawable as? SVGADrawable)?.let { - it.cleared = clear + if (clear) { + getSVGADrawable()?.cleared = true + setImageDrawable(null) + } + clearAudio() + } + + private fun clearAudio() { + getSVGADrawable()?.videoItem?.audios?.forEach { audio -> + audio.playID?.let { + getSVGADrawable()?.videoItem?.soundPool?.stop(it) + } + audio.playID = null } } @@ -205,20 +226,19 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr setVideoItem(videoItem, SVGADynamicEntity()) } - fun setVideoItem(videoItem: SVGAVideoEntity?, dynamicItem: SVGADynamicEntity?) { + fun setVideoItem(videoItem: SVGAVideoEntity?, dynamicItem: SVGADynamicEntity = SVGADynamicEntity()) { if (videoItem == null) { setImageDrawable(null) - return + } else { + val drawable = SVGADrawable(videoItem, dynamicItem) + drawable.cleared = clearsAfterStop + setImageDrawable(drawable) } - val drawable = SVGADrawable(videoItem, dynamicItem ?: SVGADynamicEntity()) - drawable.cleared = clearsAfterStop - setImageDrawable(drawable) - this.mVideoItem = videoItem } fun stepToFrame(frame: Int, andPlay: Boolean) { pauseAnimation() - val drawable = drawable as? SVGADrawable ?: return + val drawable = getSVGADrawable() ?: return drawable.currentFrame = frame if (andPlay) { startAnimation() @@ -243,11 +263,8 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr @SuppressLint("ClickableViewAccessibility") override fun onTouchEvent(event: MotionEvent?): Boolean { - if (mVideoItem == null) { - return super.onTouchEvent(event) - } event?.let { - if(event.action != MotionEvent.ACTION_DOWN) { + if (event.action != MotionEvent.ACTION_DOWN) { return super.onTouchEvent(event) } val drawable = drawable as? SVGADrawable ?: return false @@ -266,19 +283,8 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr override fun onDetachedFromWindow() { super.onDetachedFromWindow() - clearAudio() - mAnimator?.cancel() - mAnimator?.removeAllListeners() - mAnimator?.removeAllUpdateListeners() - } - - private fun clearAudio() { - this.mVideoItem?.audios?.forEach { audio -> - audio.playID?.let { - this.mVideoItem?.soundPool?.stop(it) - } - audio.playID = null - } + stopAnimation(true) + setImageDrawable(null) } private class AnimatorListener(view: SVGAImageView) : Animator.AnimatorListener { diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt index 2abd0a42..35ab0669 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt @@ -23,10 +23,9 @@ import java.util.zip.ZipInputStream private var fileLock: Int = 0 class SVGAParser(context: Context?) { - private var mContextRef = WeakReference(context) + private var mContextRef = WeakReference(context) interface ParseCompletion { - fun onComplete(videoItem: SVGAVideoEntity) fun onError() } @@ -87,9 +86,11 @@ class SVGAParser(context: Context?) { companion object { internal var threadPoolExecutor = Executors.newCachedThreadPool() + fun setThreadPoolExecutor(executor: ThreadPoolExecutor) { threadPoolExecutor = executor } + private var mShareParser = SVGAParser(null) fun shareParser(): SVGAParser { return mShareParser diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index a335f8a8..121d7656 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -1,13 +1,13 @@ package com.opensource.svgaplayer import android.graphics.Bitmap -import android.graphics.BitmapFactory import android.media.AudioAttributes import android.media.AudioManager import android.media.SoundPool import com.opensource.svgaplayer.entities.SVGAAudioEntity import com.opensource.svgaplayer.entities.SVGAVideoSpriteEntity import com.opensource.svgaplayer.proto.MovieEntity +import com.opensource.svgaplayer.utils.BitmapUtils import com.opensource.svgaplayer.utils.SVGARect import org.json.JSONObject import java.io.File @@ -15,8 +15,6 @@ import java.io.FileInputStream import java.io.FileOutputStream import java.util.* -private val options = BitmapFactory.Options() - /** * Created by PonyCui on 16/6/18. */ @@ -39,6 +37,9 @@ class SVGAVideoEntity { var frames: Int = 0 private set + + internal var reqHeight = 0 + internal var reqWidth = 0 internal var sprites: List = listOf() internal var audios: List = listOf() internal var soundPool: SoundPool? = null @@ -96,21 +97,20 @@ class SVGAVideoEntity { private fun resetImages(obj: JSONObject) { obj.optJSONObject("images")?.let { imgObjects -> imgObjects.keys().forEach { imageKey -> - options.inPreferredConfig = Bitmap.Config.RGB_565 var filePath = cacheDir.absolutePath + "/" + imgObjects[imageKey] - var bitmap = if (File(filePath).exists()) BitmapFactory.decodeFile(filePath, options) else null + var bitmap = if (File(filePath).exists()) createBitmap(filePath) else null val bitmapKey = imageKey.replace(".matte", "") if (bitmap != null) { images.put(bitmapKey, bitmap) } else { // bitmap.matte : bitmap var filePath = cacheDir.absolutePath + "/" + imgObjects[imageKey] + ".png" - var bitmap = if (File(filePath).exists()) BitmapFactory.decodeFile(filePath, options) else null + var bitmap = if (File(filePath).exists()) createBitmap(filePath) else null if (bitmap != null) { images.put(bitmapKey, bitmap) } else { (cacheDir.absolutePath + "/" + imageKey + ".png").takeIf { File(it).exists() }?.let { - BitmapFactory.decodeFile(it, options)?.let { + createBitmap(filePath)?.let { images.put(bitmapKey, it) } } @@ -123,7 +123,6 @@ class SVGAVideoEntity { private fun resetImages(obj: MovieEntity) { obj.images?.entries?.forEach { val imageKey = it.key - options.inPreferredConfig = Bitmap.Config.RGB_565 val byteArray = it.value.toByteArray() if (byteArray.count() < 4) { return@forEach @@ -131,18 +130,18 @@ class SVGAVideoEntity { val fileTag = byteArray.slice(IntRange(0, 3)) if (fileTag[0].toInt() == 73 && fileTag[1].toInt() == 68 && fileTag[2].toInt() == 51) { } else { - val bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.count(), options) + val bitmap = BitmapUtils.decodeSampledBitmapFromByteArray(byteArray,reqWidth, reqHeight) if (bitmap != null) { images[imageKey] = bitmap } else { it.value.utf8()?.let { var filePath = cacheDir.absolutePath + "/" + it - var bitmap = if (File(filePath).exists()) BitmapFactory.decodeFile(filePath, options) else null + var bitmap = if (File(filePath).exists()) createBitmap(filePath) else null if (bitmap != null) { images.put(imageKey, bitmap) } else { (cacheDir.absolutePath + "/" + imageKey + ".png").takeIf { File(it).exists() }?.let { - BitmapFactory.decodeFile(it, options)?.let { + createBitmap(it)?.let { images.put(imageKey, it) } } @@ -153,6 +152,10 @@ class SVGAVideoEntity { } } + private fun createBitmap(filePath: String): Bitmap? { + return BitmapUtils.decodeSampledBitmapFromFile(filePath, reqWidth, reqHeight) + } + private fun resetSprites(obj: JSONObject) { val mutableList: MutableList = mutableListOf() obj.optJSONArray("sprites")?.let { diff --git a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt b/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt new file mode 100644 index 00000000..ddd314b1 --- /dev/null +++ b/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt @@ -0,0 +1,78 @@ +package com.opensource.svgaplayer.utils + +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import android.util.Log + +/** + * + * Create by im_dsd 2020/7/4 21:10 + */ +object BitmapUtils { + + fun decodeSampledBitmapFromFile( + fileName: String, + reqWidth: Int, + reqHeight: Int + ): Bitmap { + // First decode with inJustDecodeBounds=true to check dimensions + return BitmapFactory.Options().run { + inJustDecodeBounds = true + inPreferredConfig = Bitmap.Config.RGB_565 + BitmapFactory.decodeFile(fileName, this) + + // Calculate inSampleSize + inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight) + + // Decode bitmap with inSampleSize set + inJustDecodeBounds = false + BitmapFactory.decodeFile(fileName, this) + } + } + + fun decodeSampledBitmapFromByteArray( + byteArray: ByteArray, + reqWidth: Int, + reqHeight: Int + ): Bitmap { + // First decode with inJustDecodeBounds=true to check dimensions + return BitmapFactory.Options().run { + inJustDecodeBounds = true + inPreferredConfig = Bitmap.Config.RGB_565 + BitmapFactory.decodeByteArray(byteArray, 0, byteArray.count(), this) + + // Calculate inSampleSize + inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight) + + // Decode bitmap with inSampleSize set + inJustDecodeBounds = false + + BitmapFactory.decodeByteArray(byteArray, 0, byteArray.count(), this) + } + } + + private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { + // Raw height and width of image + val (height: Int, width: Int) = options.run { outHeight to outWidth } + var inSampleSize = 1 + if (reqHeight <= 0 || reqWidth <= 0) { + Log.d("BitmapUtils", "inSampleSize:$inSampleSize height:$height width$width reqHeight$reqHeight reqWidth$reqWidth" ) + return inSampleSize + } + if (height > reqHeight || width > reqWidth) { + + val halfHeight: Int = height / 2 + val halfWidth: Int = width / 2 + + // Calculate the largest inSampleSize value that is a power of 2 and keeps both + // height and width larger than the requested height and width. + while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) { + inSampleSize *= 2 + } + } + + Log.d("BitmapUtils", "inSampleSize:$inSampleSize height:$height width$width reqHeight$reqHeight reqWidth$reqWidth" ) + return inSampleSize + } + +} \ No newline at end of file From 62c9ca9b45f869a70f9996db4a4995e0d2f91e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 13:35:55 +0800 Subject: [PATCH 03/33] review code --- library/build.gradle | 1 + .../com/opensource/svgaplayer/SVGADrawable.kt | 11 ++++- .../opensource/svgaplayer/SVGAImageView.kt | 40 ++++++------------- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/library/build.gradle b/library/build.gradle index 793d0c5d..0d9d417e 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -32,6 +32,7 @@ dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.squareup.wire:wire-runtime:2.3.0-RC1' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7" } repositories { mavenCentral() diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt b/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt index a8cfdf00..04aa78ec 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt @@ -42,7 +42,7 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE } } - override fun setAlpha(alpha: Int) { } + override fun setAlpha(alpha: Int) {} override fun getOpacity(): Int { return PixelFormat.TRANSPARENT @@ -52,4 +52,13 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE } + internal fun clearAudio() { + videoItem.audios.forEach { audio -> + audio.playID?.let { + videoItem.soundPool?.stop(it) + } + audio.playID = null + } + } + } \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index 333466db..bc03865d 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -101,7 +101,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr this@SVGAImageView.post { videoItem.antiAlias = mAntiAlias setVideoItem(videoItem) - (drawable as? SVGADrawable)?.scaleType = scaleType + getSVGADrawable()?.scaleType = scaleType if (mAutoPlay) { startAnimation() } @@ -157,9 +157,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr val animatorClass = Class.forName("android.animation.ValueAnimator") ?: return scale val field = animatorClass.getDeclaredField("sDurationScale") ?: return scale field.isAccessible = true - field.getFloat(animatorClass).let { value -> - scale = value.toDouble() - } + scale = field.getFloat(animatorClass).toDouble() if (scale == 0.0) { field.setFloat(animatorClass, 1.0f) scale = 1.0 @@ -190,7 +188,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr } } callback?.onFinished() - stopAnimation(true) + stopAnimation() } fun pauseAnimation() { @@ -210,16 +208,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr getSVGADrawable()?.cleared = true setImageDrawable(null) } - clearAudio() - } - - private fun clearAudio() { - getSVGADrawable()?.videoItem?.audios?.forEach { audio -> - audio.playID?.let { - getSVGADrawable()?.videoItem?.soundPool?.stop(it) - } - audio.playID = null - } + getSVGADrawable()?.clearAudio() } fun setVideoItem(videoItem: SVGAVideoEntity?) { @@ -263,17 +252,15 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr @SuppressLint("ClickableViewAccessibility") override fun onTouchEvent(event: MotionEvent?): Boolean { - event?.let { - if (event.action != MotionEvent.ACTION_DOWN) { - return super.onTouchEvent(event) - } - val drawable = drawable as? SVGADrawable ?: return false - for ((key, value) in drawable.dynamicItem.mClickMap) { - if (event.x >= value[0] && event.x <= value[2] && event.y >= value[1] && event.y <= value[3]) { - mItemClickAreaListener?.let { - it.onClick(key) - return true - } + if (event?.action != MotionEvent.ACTION_DOWN) { + return super.onTouchEvent(event) + } + val drawable = getSVGADrawable() ?: return false + for ((key, value) in drawable.dynamicItem.mClickMap) { + if (event.x >= value[0] && event.x <= value[2] && event.y >= value[1] && event.y <= value[3]) { + mItemClickAreaListener?.let { + it.onClick(key) + return true } } } @@ -284,7 +271,6 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr override fun onDetachedFromWindow() { super.onDetachedFromWindow() stopAnimation(true) - setImageDrawable(null) } private class AnimatorListener(view: SVGAImageView) : Animator.AnimatorListener { From 9b902e21d592377a96a1bce6ba337f611ada1408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 13:56:20 +0800 Subject: [PATCH 04/33] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=B8=BA=E4=BF=AE=E6=94=B9=E5=86=85=E5=AD=98?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=81=9A=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../opensource/svgaplayer/SVGAVideoEntity.kt | 95 ++++++++++--------- 1 file changed, 52 insertions(+), 43 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index 121d7656..8395e1a9 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -7,6 +7,7 @@ import android.media.SoundPool import com.opensource.svgaplayer.entities.SVGAAudioEntity import com.opensource.svgaplayer.entities.SVGAVideoSpriteEntity import com.opensource.svgaplayer.proto.MovieEntity +import com.opensource.svgaplayer.proto.MovieParams import com.opensource.svgaplayer.utils.BitmapUtils import com.opensource.svgaplayer.utils.SVGARect import org.json.JSONObject @@ -20,6 +21,7 @@ import java.util.* */ class SVGAVideoEntity { + // FIXME: 2020/7/6 必须移除 protected fun finalize() { this.soundPool?.release() this.soundPool = null @@ -27,6 +29,7 @@ class SVGAVideoEntity { } var antiAlias = true + var movieItem: MovieEntity? = null var videoSize = SVGARect(0.0, 0.0, 0.0, 0.0) private set @@ -37,7 +40,6 @@ class SVGAVideoEntity { var frames: Int = 0 private set - internal var reqHeight = 0 internal var reqWidth = 0 internal var sprites: List = listOf() @@ -46,73 +48,80 @@ class SVGAVideoEntity { internal var images = HashMap() private var cacheDir: File - constructor(obj: JSONObject, cacheDir: File) { + constructor(json: JSONObject, cacheDir: File) { this.cacheDir = cacheDir - obj.optJSONObject("movie")?.let { - it.optJSONObject("viewBox")?.let { - videoSize = SVGARect(0.0, 0.0, it.optDouble("width", 0.0), it.optDouble("height", 0.0)) - } - FPS = it.optInt("fps", 20) - frames = it.optInt("frames", 0) - } + json.optJSONObject("movie")?.let(this::setup) try { - resetImages(obj) + parserImages(json) } catch (e: Exception) { e.printStackTrace() } catch (e: OutOfMemoryError) { e.printStackTrace() } - resetSprites(obj) + resetSprites(json) } - var movieItem: MovieEntity? = null - - internal constructor(obj: MovieEntity, cacheDir: File) { - this.movieItem = obj + internal constructor(entity: MovieEntity, cacheDir: File) { + this.movieItem = entity this.cacheDir = cacheDir - obj.params?.let { movieParams -> - videoSize = SVGARect(0.0, 0.0, (movieParams.viewBoxWidth - ?: 0.0f).toDouble(), (movieParams.viewBoxHeight ?: 0.0f).toDouble()) - FPS = movieParams.fps ?: 20 - frames = movieParams.frames ?: 0 - } + entity.params?.let (this::setup) + try { - resetImages(obj) + parserImages(entity) } catch (e: Exception) { e.printStackTrace() } catch (e: OutOfMemoryError) { e.printStackTrace() } - resetSprites(obj) + resetSprites(entity) + } + + private fun setup(movieObject: JSONObject) { + movieObject.optJSONObject("viewBox")?.let { viewBoxObject -> + val width = viewBoxObject.optDouble("width", 0.0) + val height = viewBoxObject.optDouble("height", 0.0) + videoSize = SVGARect(0.0, 0.0, width, height) + } + FPS = movieObject.optInt("fps", 20) + frames = movieObject.optInt("frames", 0) + } + + private fun setup(movieParams: MovieParams) { + val width = (movieParams.viewBoxWidth ?: 0.0f).toDouble() + val height = (movieParams.viewBoxHeight ?: 0.0f).toDouble() + videoSize = SVGARect(0.0, 0.0, width, height) + FPS = movieParams.fps ?: 20 + frames = movieParams.frames ?: 0 } internal fun prepare(callback: () -> Unit) { - this.movieItem?.let { - resetAudios(it) { + if (movieItem == null) { + callback() + } else { + resetAudios(movieItem!!) { callback() } - } ?: callback() + } } - private fun resetImages(obj: JSONObject) { - obj.optJSONObject("images")?.let { imgObjects -> - imgObjects.keys().forEach { imageKey -> - var filePath = cacheDir.absolutePath + "/" + imgObjects[imageKey] + private fun parserImages(json: JSONObject) { + val imageJson = json.optJSONObject("images") ?: return + imageJson.keys().forEach { key -> + val filePath = cacheDir.absolutePath + "/" + imageJson[key] + val bitmap = if (File(filePath).exists()) createBitmap(filePath) else null + val bitmapKey = key.replace(".matte", "") + if (bitmap != null) { + images[bitmapKey] = bitmap + } else { + // bitmap.matte : bitmap + var filePath = cacheDir.absolutePath + "/" + imageJson[key] + ".png" var bitmap = if (File(filePath).exists()) createBitmap(filePath) else null - val bitmapKey = imageKey.replace(".matte", "") if (bitmap != null) { - images.put(bitmapKey, bitmap) + images[bitmapKey] = bitmap } else { - // bitmap.matte : bitmap - var filePath = cacheDir.absolutePath + "/" + imgObjects[imageKey] + ".png" - var bitmap = if (File(filePath).exists()) createBitmap(filePath) else null - if (bitmap != null) { - images.put(bitmapKey, bitmap) - } else { - (cacheDir.absolutePath + "/" + imageKey + ".png").takeIf { File(it).exists() }?.let { - createBitmap(filePath)?.let { - images.put(bitmapKey, it) - } + (cacheDir.absolutePath + "/" + key + ".png").takeIf { File(it).exists() }?.let { + createBitmap(filePath)?.let { + images.put(bitmapKey, it) } } } @@ -120,7 +129,7 @@ class SVGAVideoEntity { } } - private fun resetImages(obj: MovieEntity) { + private fun parserImages(obj: MovieEntity) { obj.images?.entries?.forEach { val imageKey = it.key val byteArray = it.value.toByteArray() From 9f9d433fe677a664a52757591920027bd6c5887a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 14:11:43 +0800 Subject: [PATCH 05/33] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=B8=BA=E4=BF=AE=E6=94=B9=E5=86=85=E5=AD=98?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=81=9A=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../opensource/svgaplayer/SVGAVideoEntity.kt | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index 8395e1a9..9b59536b 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -46,10 +46,10 @@ class SVGAVideoEntity { internal var audios: List = listOf() internal var soundPool: SoundPool? = null internal var images = HashMap() - private var cacheDir: File + private var mCacheDir: File constructor(json: JSONObject, cacheDir: File) { - this.cacheDir = cacheDir + this.mCacheDir = cacheDir json.optJSONObject("movie")?.let(this::setup) try { parserImages(json) @@ -63,7 +63,7 @@ class SVGAVideoEntity { internal constructor(entity: MovieEntity, cacheDir: File) { this.movieItem = entity - this.cacheDir = cacheDir + this.mCacheDir = cacheDir entity.params?.let (this::setup) try { @@ -105,30 +105,30 @@ class SVGAVideoEntity { } private fun parserImages(json: JSONObject) { - val imageJson = json.optJSONObject("images") ?: return - imageJson.keys().forEach { key -> - val filePath = cacheDir.absolutePath + "/" + imageJson[key] - val bitmap = if (File(filePath).exists()) createBitmap(filePath) else null - val bitmapKey = key.replace(".matte", "") - if (bitmap != null) { + val imgJson = json.optJSONObject("images") ?: return + imgJson.keys().forEach { imgKey -> + val filePath = generateBitmapFilePath(imgJson[imgKey].toString(), imgKey) + if (filePath.isNotEmpty()) { + val bitmapKey = imgKey.replace(".matte", "") + val bitmap = createBitmap(filePath) ?: return@forEach images[bitmapKey] = bitmap - } else { - // bitmap.matte : bitmap - var filePath = cacheDir.absolutePath + "/" + imageJson[key] + ".png" - var bitmap = if (File(filePath).exists()) createBitmap(filePath) else null - if (bitmap != null) { - images[bitmapKey] = bitmap - } else { - (cacheDir.absolutePath + "/" + key + ".png").takeIf { File(it).exists() }?.let { - createBitmap(filePath)?.let { - images.put(bitmapKey, it) - } - } - } } } } + private fun generateBitmapFilePath(imgName: String, imgKey: String): String { + val path = mCacheDir.absolutePath + "/" + imgName + val path1 = "$path.png" + val path2 = mCacheDir.absolutePath + "/" + imgKey + ".png" + + return when { + File(path).exists() -> path + File(path1).exists() -> path1 + File(path2).exists() -> path2 + else -> "" + } + } + private fun parserImages(obj: MovieEntity) { obj.images?.entries?.forEach { val imageKey = it.key @@ -144,12 +144,12 @@ class SVGAVideoEntity { images[imageKey] = bitmap } else { it.value.utf8()?.let { - var filePath = cacheDir.absolutePath + "/" + it + var filePath = mCacheDir.absolutePath + "/" + it var bitmap = if (File(filePath).exists()) createBitmap(filePath) else null if (bitmap != null) { images.put(imageKey, bitmap) } else { - (cacheDir.absolutePath + "/" + imageKey + ".png").takeIf { File(it).exists() }?.let { + (mCacheDir.absolutePath + "/" + imageKey + ".png").takeIf { File(it).exists() }?.let { createBitmap(it)?.let { images.put(imageKey, it) } @@ -165,6 +165,7 @@ class SVGAVideoEntity { return BitmapUtils.decodeSampledBitmapFromFile(filePath, reqWidth, reqHeight) } + private fun resetSprites(obj: JSONObject) { val mutableList: MutableList = mutableListOf() obj.optJSONArray("sprites")?.let { From d6b98c8cc5aebe4637a4b896b75fe1e4c4cab3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 14:24:34 +0800 Subject: [PATCH 06/33] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=B8=BA=E4=BF=AE=E6=94=B9=E5=86=85=E5=AD=98?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=81=9A=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../opensource/svgaplayer/SVGAVideoEntity.kt | 41 ++++++++----------- .../svgaplayer/utils/BitmapUtils.kt | 4 +- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index 9b59536b..61caf378 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -129,43 +129,34 @@ class SVGAVideoEntity { } } + private fun createBitmap(filePath: String): Bitmap? { + if (filePath.isNotEmpty()) { + return null + } + return BitmapUtils.decodeSampledBitmapFromFile(filePath, reqWidth, reqHeight) + } + private fun parserImages(obj: MovieEntity) { - obj.images?.entries?.forEach { - val imageKey = it.key - val byteArray = it.value.toByteArray() + obj.images?.entries?.forEach { entry -> + val byteArray = entry.value.toByteArray() if (byteArray.count() < 4) { return@forEach } val fileTag = byteArray.slice(IntRange(0, 3)) if (fileTag[0].toInt() == 73 && fileTag[1].toInt() == 68 && fileTag[2].toInt() == 51) { - } else { - val bitmap = BitmapUtils.decodeSampledBitmapFromByteArray(byteArray,reqWidth, reqHeight) - if (bitmap != null) { - images[imageKey] = bitmap - } else { - it.value.utf8()?.let { - var filePath = mCacheDir.absolutePath + "/" + it - var bitmap = if (File(filePath).exists()) createBitmap(filePath) else null - if (bitmap != null) { - images.put(imageKey, bitmap) - } else { - (mCacheDir.absolutePath + "/" + imageKey + ".png").takeIf { File(it).exists() }?.let { - createBitmap(it)?.let { - images.put(imageKey, it) - } - } - } - } - } + return@forEach + } + val filePath = generateBitmapFilePath(entry.value.utf8(), entry.key) + createBitmap(byteArray, filePath)?.let { bitmap -> + images[entry.key] = bitmap } } } - private fun createBitmap(filePath: String): Bitmap? { - return BitmapUtils.decodeSampledBitmapFromFile(filePath, reqWidth, reqHeight) + private fun createBitmap(byteArray: ByteArray, filePath: String): Bitmap? { + return BitmapUtils.decodeSampledBitmapFromByteArray(byteArray, reqWidth, reqHeight) ?: createBitmap(filePath) } - private fun resetSprites(obj: JSONObject) { val mutableList: MutableList = mutableListOf() obj.optJSONArray("sprites")?.let { diff --git a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt b/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt index ddd314b1..e8bbb39d 100644 --- a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt +++ b/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt @@ -14,7 +14,7 @@ object BitmapUtils { fileName: String, reqWidth: Int, reqHeight: Int - ): Bitmap { + ): Bitmap? { // First decode with inJustDecodeBounds=true to check dimensions return BitmapFactory.Options().run { inJustDecodeBounds = true @@ -34,7 +34,7 @@ object BitmapUtils { byteArray: ByteArray, reqWidth: Int, reqHeight: Int - ): Bitmap { + ): Bitmap? { // First decode with inJustDecodeBounds=true to check dimensions return BitmapFactory.Options().run { inJustDecodeBounds = true From fe30523cda07a102b2227862a30ef8bbb3bb710d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 14:53:33 +0800 Subject: [PATCH 07/33] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=B8=BA=E4=BF=AE=E6=94=B9=E5=86=85=E5=AD=98?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=81=9A=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/opensource/svgaplayer/SVGADrawable.kt | 2 +- .../opensource/svgaplayer/SVGAVideoEntity.kt | 169 +++++++++++------- .../svgaplayer/drawer/SGVADrawer.kt | 2 +- .../svgaplayer/drawer/SVGACanvasDrawer.kt | 8 +- 4 files changed, 104 insertions(+), 77 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt b/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt index 04aa78ec..5ca36f43 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt @@ -53,7 +53,7 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE } internal fun clearAudio() { - videoItem.audios.forEach { audio -> + videoItem.audioList.forEach { audio -> audio.playID?.let { videoItem.soundPool?.stop(it) } diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index 61caf378..0656a2f8 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -4,8 +4,10 @@ import android.graphics.Bitmap import android.media.AudioAttributes import android.media.AudioManager import android.media.SoundPool +import android.os.Build import com.opensource.svgaplayer.entities.SVGAAudioEntity import com.opensource.svgaplayer.entities.SVGAVideoSpriteEntity +import com.opensource.svgaplayer.proto.AudioEntity import com.opensource.svgaplayer.proto.MovieEntity import com.opensource.svgaplayer.proto.MovieParams import com.opensource.svgaplayer.utils.BitmapUtils @@ -21,13 +23,6 @@ import java.util.* */ class SVGAVideoEntity { - // FIXME: 2020/7/6 必须移除 - protected fun finalize() { - this.soundPool?.release() - this.soundPool = null - this.images.clear() - } - var antiAlias = true var movieItem: MovieEntity? = null @@ -42,10 +37,10 @@ class SVGAVideoEntity { internal var reqHeight = 0 internal var reqWidth = 0 - internal var sprites: List = listOf() - internal var audios: List = listOf() + internal var spriteList: List = emptyList() + internal var audioList: List = emptyList() internal var soundPool: SoundPool? = null - internal var images = HashMap() + internal var imageMap = HashMap() private var mCacheDir: File constructor(json: JSONObject, cacheDir: File) { @@ -98,7 +93,7 @@ class SVGAVideoEntity { if (movieItem == null) { callback() } else { - resetAudios(movieItem!!) { + setupAudios(movieItem!!) { callback() } } @@ -111,7 +106,7 @@ class SVGAVideoEntity { if (filePath.isNotEmpty()) { val bitmapKey = imgKey.replace(".matte", "") val bitmap = createBitmap(filePath) ?: return@forEach - images[bitmapKey] = bitmap + imageMap[bitmapKey] = bitmap } } } @@ -148,7 +143,7 @@ class SVGAVideoEntity { } val filePath = generateBitmapFilePath(entry.value.utf8(), entry.key) createBitmap(byteArray, filePath)?.let { bitmap -> - images[entry.key] = bitmap + imageMap[entry.key] = bitmap } } } @@ -157,77 +152,113 @@ class SVGAVideoEntity { return BitmapUtils.decodeSampledBitmapFromByteArray(byteArray, reqWidth, reqHeight) ?: createBitmap(filePath) } - private fun resetSprites(obj: JSONObject) { + private fun resetSprites(json: JSONObject) { val mutableList: MutableList = mutableListOf() - obj.optJSONArray("sprites")?.let { - for (i in 0 until it.length()) { - it.optJSONObject(i)?.let { - mutableList.add(SVGAVideoSpriteEntity(it)) + json.optJSONArray("sprites")?.let { item -> + for (i in 0 until item.length()) { + item.optJSONObject(i)?.let { entryJson -> + mutableList.add(SVGAVideoSpriteEntity(entryJson)) } } } - sprites = mutableList.toList() + spriteList = mutableList.toList() } - private fun resetSprites(obj: MovieEntity) { - sprites = obj.sprites?.map { + private fun resetSprites(entity: MovieEntity) { + spriteList = entity.sprites?.map { return@map SVGAVideoSpriteEntity(it) } ?: listOf() } - private fun resetAudios(obj: MovieEntity, completionBlock: () -> Unit) { - obj.audios?.takeIf { it.isNotEmpty() }?.let { audios -> - var soundLoaded = 0 - val soundPool = if (android.os.Build.VERSION.SDK_INT >= 21) { - SoundPool.Builder().setAudioAttributes(AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build()) - .setMaxStreams(Math.min(12, audios.count())) - .build() - } else { - SoundPool(Math.min(12, audios.count()), AudioManager.STREAM_MUSIC, 0) - } - val audiosFile = HashMap() - soundPool.setOnLoadCompleteListener { _, _, _ -> - soundLoaded++ - if (soundLoaded >= audios.count()) { - completionBlock() - } + private fun setupAudios(entity: MovieEntity, completionBlock: () -> Unit) { + if (entity.audios == null || entity.audios.isEmpty()) { + run(completionBlock) + } + setupSoundPool(entity, completionBlock) + val audiosFileMap = generateAudioFileMap(entity) + this.audioList = entity.audios.map { audio -> + return@map createSvgaAudioEntity(audio, audiosFileMap) + } + } + + private fun createSvgaAudioEntity(audio: AudioEntity, audiosFileMap: HashMap): SVGAAudioEntity { + val item = SVGAAudioEntity(audio) + val startTime = (audio.startTime ?: 0).toDouble() + val totalTime = (audio.totalTime ?: 0).toDouble() + if (totalTime.toInt() == 0) { + // 除数不能为 0 + return item + } + audiosFileMap[audio.audioKey]?.let { + val fis = FileInputStream(it) + val length = fis.available().toDouble() + val offset = ((startTime / totalTime) * length).toLong() + item.soundID = soundPool?.load(fis.fd, offset, length.toLong(), 1) + fis.close() + } + return item + } + + private fun generateAudioFileMap(entity: MovieEntity): HashMap { + val audiosDataMap = generateAudioMap(entity) + val audiosFileMap = HashMap() + if (audiosDataMap.count() > 0) { + audiosDataMap.forEach { + val tmpFile = File.createTempFile(it.key + "_tmp", ".mp3") + val fos = FileOutputStream(tmpFile) + fos.write(it.value) + fos.flush() + fos.close() + audiosFileMap[it.key] = tmpFile } - val audiosData = HashMap() - obj.images?.entries?.forEach { - val imageKey = it.key - val byteArray = it.value.toByteArray() - if (byteArray.count() < 4) { - return@forEach - } - val fileTag = byteArray.slice(IntRange(0, 3)) - if (fileTag[0].toInt() == 73 && fileTag[1].toInt() == 68 && fileTag[2].toInt() == 51) { - audiosData[imageKey] = byteArray - } + } + return audiosFileMap + } + + private fun generateAudioMap(entity: MovieEntity): HashMap { + val audiosDataMap = HashMap() + entity.images?.entries?.forEach { + val imageKey = it.key + val byteArray = it.value.toByteArray() + if (byteArray.count() < 4) { + return@forEach } - if (audiosData.count() > 0) { - audiosData.forEach { - val tmpFile = File.createTempFile(it.key + "_tmp", ".mp3") - val fos = FileOutputStream(tmpFile) - fos.write(it.value) - fos.flush() - fos.close() - audiosFile[it.key] = tmpFile - } + val fileTag = byteArray.slice(IntRange(0, 3)) + if (fileTag[0].toInt() == 73 && fileTag[1].toInt() == 68 && fileTag[2].toInt() == 51) { + audiosDataMap[imageKey] = byteArray } - this.audios = audios.map { audio -> - val item = SVGAAudioEntity(audio) - audiosFile[audio.audioKey]?.let { - val fis = FileInputStream(it) - item.soundID = soundPool.load(fis.fd, (((audio.startTime - ?: 0).toDouble() / (audio.totalTime - ?: 0).toDouble()) * fis.available().toDouble()).toLong(), fis.available().toLong(), 1) - fis.close() - } - return@map item + } + return audiosDataMap + } + + private fun setupSoundPool(entity: MovieEntity, completionBlock: () -> Unit) { + var soundLoaded = 0 + soundPool = generateSoundPool(entity); + soundPool?.setOnLoadCompleteListener { _, _, _ -> + soundLoaded++ + if (soundLoaded >= entity.audios.count()) { + completionBlock() } - this.soundPool = soundPool - } ?: kotlin.run(completionBlock) + } } + private fun generateSoundPool(entity: MovieEntity) = if (Build.VERSION.SDK_INT >= 21) { + val attributes = AudioAttributes.Builder() + .setUsage(AudioAttributes.USAGE_MEDIA) + .build() + SoundPool.Builder().setAudioAttributes(attributes) + .setMaxStreams(12.coerceAtMost(entity.audios.count())) + .build() + } else { + SoundPool(12.coerceAtMost(entity.audios.count()), AudioManager.STREAM_MUSIC, 0) + } + + internal fun clear() { + soundPool?.release() + soundPool = null + audioList = emptyList() + spriteList = emptyList() + imageMap.clear() + } } diff --git a/library/src/main/java/com/opensource/svgaplayer/drawer/SGVADrawer.kt b/library/src/main/java/com/opensource/svgaplayer/drawer/SGVADrawer.kt index 8b7320a1..b7e0c7de 100644 --- a/library/src/main/java/com/opensource/svgaplayer/drawer/SGVADrawer.kt +++ b/library/src/main/java/com/opensource/svgaplayer/drawer/SGVADrawer.kt @@ -17,7 +17,7 @@ open internal class SGVADrawer(val videoItem: SVGAVideoEntity) { inner class SVGADrawerSprite(val matteKey: String?, val imageKey: String?, val frameEntity: SVGAVideoSpriteFrameEntity) internal fun requestFrameSprites(frameIndex: Int): List { - return videoItem.sprites.mapNotNull { + return videoItem.spriteList.mapNotNull { if (frameIndex >= 0 && frameIndex < it.frames.size) { it.imageKey?.let { imageKey -> if (!imageKey.endsWith(".matte") && it.frames[frameIndex].alpha <= 0.0) { diff --git a/library/src/main/java/com/opensource/svgaplayer/drawer/SVGACanvasDrawer.kt b/library/src/main/java/com/opensource/svgaplayer/drawer/SVGACanvasDrawer.kt index 269bfafb..4aa793b8 100644 --- a/library/src/main/java/com/opensource/svgaplayer/drawer/SVGACanvasDrawer.kt +++ b/library/src/main/java/com/opensource/svgaplayer/drawer/SVGACanvasDrawer.kt @@ -1,17 +1,13 @@ package com.opensource.svgaplayer.drawer -import android.annotation.TargetApi import android.graphics.* import android.os.Build import android.text.* -import android.text.style.StyleSpan -import android.widget.FrameLayout import android.widget.ImageView import com.opensource.svgaplayer.SVGADynamicEntity import com.opensource.svgaplayer.SVGAVideoEntity import com.opensource.svgaplayer.entities.SVGAVideoShapeEntity import java.lang.Exception -import java.lang.reflect.Field /** * Created by cuiminghui on 2017/3/29. @@ -157,7 +153,7 @@ internal class SVGACanvasDrawer(videoItem: SVGAVideoEntity, val dynamicItem: SVG } private fun playAudio(frameIndex: Int) { - this.videoItem.audios.forEach { audio -> + this.videoItem.audioList.forEach { audio -> if (audio.startFrame == frameIndex) { this.videoItem.soundPool?.let { soundPool -> audio.soundID?.let {soundID -> @@ -193,7 +189,7 @@ internal class SVGACanvasDrawer(videoItem: SVGAVideoEntity, val dynamicItem: SVG val isHidden = dynamicItem.dynamicHidden[imageKey] == true if (isHidden) { return } val bitmapKey = imageKey.replace(".matte", "") - val drawingBitmap = (dynamicItem.dynamicImage[bitmapKey] ?: videoItem.images[bitmapKey]) ?: return + val drawingBitmap = (dynamicItem.dynamicImage[bitmapKey] ?: videoItem.imageMap[bitmapKey]) ?: return val frameMatrix = shareFrameMatrix(sprite.frameEntity.transform) val paint = this.sharedValues.sharedPaint() paint.isAntiAlias = videoItem.antiAlias From 9f18ee9cd904022dea82737a408cd02f99ec46e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 15:00:00 +0800 Subject: [PATCH 08/33] =?UTF-8?q?drawable=20=E7=9A=84=E5=9B=9E=E6=94=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/opensource/svgaplayer/SVGADrawable.kt | 4 ++++ .../src/main/java/com/opensource/svgaplayer/SVGAImageView.kt | 3 +++ 2 files changed, 7 insertions(+) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt b/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt index 5ca36f43..2dc7d804 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt @@ -61,4 +61,8 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE } } + internal fun release() { + clearAudio() + videoItem.clear() + } } \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index bc03865d..ea2e413f 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -206,6 +206,9 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr mAnimator?.removeAllUpdateListeners() if (clear) { getSVGADrawable()?.cleared = true + // 回收内存 + getSVGADrawable()?.release() + // 清除对 drawable 的引用 setImageDrawable(null) } getSVGADrawable()?.clearAudio() From dea8e74df53c0cacd106d5a6fe66736dde04eeec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 15:49:56 +0800 Subject: [PATCH 09/33] review --- .../main/java/com/opensource/svgaplayer/SVGAImageView.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index bc03865d..df380898 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -188,7 +188,11 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr } } callback?.onFinished() - stopAnimation() + // 不是循环播放时,手动停止一下 + if ((animation as ValueAnimator).repeatCount <= 0) { + // 要根据用户设置的 clearsAfterStop 状态判断,不可手动置 true + stopAnimation() + } } fun pauseAnimation() { From 67b3b9186546346e8ff6e6496966779ef0978c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 16:01:27 +0800 Subject: [PATCH 10/33] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../svgaplayer/AnimationFromAssetsActivity.java | 8 +++++++- .../java/com/opensource/svgaplayer/SVGAImageView.kt | 12 +++++++++++- .../java/com/opensource/svgaplayer/SVGAParser.kt | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java index 05d2e492..91e00b9b 100644 --- a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java +++ b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java @@ -4,6 +4,7 @@ import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; +import android.util.Log; import android.view.View; import com.opensource.svgaplayer.SVGAImageView; @@ -13,6 +14,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.logging.Logger; public class AnimationFromAssetsActivity extends Activity { @@ -35,7 +37,10 @@ public void onClick(View view) { } private void loadAnimation() { - SVGAParser.Companion.shareParser().decodeFromAssets(this.randomSample(), new SVGAParser.ParseCompletion() { + String fileName = this.randomSample(); + Log.d("AssetsActivity", fileName); + + SVGAParser.Companion.shareParser().decodeFromAssets(fileName, new SVGAParser.ParseCompletion() { @Override public void onComplete(@NotNull SVGAVideoEntity videoItem) { animationView.setVideoItem(videoItem); @@ -65,6 +70,7 @@ private String randomSample() { samples.add("MerryChristmas.svga"); } return samples.get((int) Math.floor(Math.random() * samples.size())); +// return "Rocket.svga"; } } diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index df380898..205414e8 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -178,7 +178,6 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr private fun onAnimationEnd(animation: Animator?) { isAnimating = false - stopAnimation() val drawable = getSVGADrawable() if (!clearsAfterStop && drawable != null) { if (fillMode == FillMode.Backward) { @@ -187,7 +186,9 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr drawable.currentFrame = mEndFrame } } + callback?.onFinished() + Log.d("## onAnimationEnd", "onFinished") // 不是循环播放时,手动停止一下 if ((animation as ValueAnimator).repeatCount <= 0) { // 要根据用户设置的 clearsAfterStop 状态判断,不可手动置 true @@ -196,6 +197,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr } fun pauseAnimation() { + Log.d("## pauseAnimation", "") stopAnimation(false) callback?.onPause() } @@ -205,6 +207,8 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr } fun stopAnimation(clear: Boolean) { + Log.d("## stopAnimation", "cancel") + mAnimator?.cancel() mAnimator?.removeAllListeners() mAnimator?.removeAllUpdateListeners() @@ -282,17 +286,21 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr override fun onAnimationRepeat(animation: Animator?) { weakReference.get()?.callback?.onRepeat() + Log.d("## onAnimationRepeat", (animation as ValueAnimator).repeatCount.toString()) } override fun onAnimationEnd(animation: Animator?) { + Log.d("## onAnimationEnd", (animation as ValueAnimator).repeatCount.toString()) weakReference.get()?.onAnimationEnd(animation) } override fun onAnimationCancel(animation: Animator?) { + Log.d("## onAnimationCancel", (animation as ValueAnimator).duration.toString()) weakReference.get()?.isAnimating = false } override fun onAnimationStart(animation: Animator?) { + Log.d("## onAnimationStart", (animation as ValueAnimator).duration.toString()) weakReference.get()?.isAnimating = true } } // end of AnimatorListener @@ -302,6 +310,8 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr private val weakReference = WeakReference(view) override fun onAnimationUpdate(animation: ValueAnimator?) { + Log.d("## onAnimationUpdate", (animation as ValueAnimator).repeatCount.toString()) + weakReference.get()?.onAnimatorUpdate(animation) } } // end of AnimatorUpdateListener diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt index 35ab0669..8a5628c7 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt @@ -85,7 +85,7 @@ class SVGAParser(context: Context?) { var fileDownloader = FileDownloader() companion object { - internal var threadPoolExecutor = Executors.newCachedThreadPool() + internal var threadPoolExecutor = Executors.newSingleThreadExecutor() fun setThreadPoolExecutor(executor: ThreadPoolExecutor) { threadPoolExecutor = executor From 4c50963a9120ce39d26dcd68a395ee481a2bc996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 16:15:37 +0800 Subject: [PATCH 11/33] test --- .../ponycui_home/svgaplayer/AnimationFromAssetsActivity.java | 2 +- .../src/main/java/com/opensource/svgaplayer/SVGAImageView.kt | 2 +- .../src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java index 91e00b9b..c42f3ac4 100644 --- a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java +++ b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java @@ -70,7 +70,7 @@ private String randomSample() { samples.add("MerryChristmas.svga"); } return samples.get((int) Math.floor(Math.random() * samples.size())); -// return "Rocket.svga"; +// return "gradientBorder.svga"; } } diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index dc8a8e20..79754863 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -188,9 +188,9 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr } callback?.onFinished() - Log.d("## onAnimationEnd", "onFinished") // 不是循环播放时,手动停止一下 if ((animation as ValueAnimator).repeatCount <= 0) { + Log.d("## onAnimationEnd", "onFinished") // 要根据用户设置的 clearsAfterStop 状态判断,不可手动置 true stopAnimation() } diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index 0656a2f8..37094af3 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -125,7 +125,7 @@ class SVGAVideoEntity { } private fun createBitmap(filePath: String): Bitmap? { - if (filePath.isNotEmpty()) { + if (filePath.isEmpty()) { return null } return BitmapUtils.decodeSampledBitmapFromFile(filePath, reqWidth, reqHeight) From 025a95aa033dfe6e98d2ef0dca050b3e7e372ac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 16:31:05 +0800 Subject: [PATCH 12/33] =?UTF-8?q?=E8=B0=83=E6=95=B4=20SVGAVideoEntity=20?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=88=9D=E5=A7=8B=E5=8C=96=E6=97=B6=E6=9C=BA?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E4=BC=A0=E9=80=92=20View=20size=20=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=20Bitmp=20=E7=BC=A9=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AnimationFromAssetsActivity.java | 2 - .../opensource/svgaplayer/SVGAImageView.kt | 3 +- .../opensource/svgaplayer/SVGAVideoEntity.kt | 75 ++++++++++++------- 3 files changed, 47 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java index c42f3ac4..be8a6a0e 100644 --- a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java +++ b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java @@ -14,7 +14,6 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.logging.Logger; public class AnimationFromAssetsActivity extends Activity { @@ -70,7 +69,6 @@ private String randomSample() { samples.add("MerryChristmas.svga"); } return samples.get((int) Math.floor(Math.random() * samples.size())); -// return "gradientBorder.svga"; } } diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index 79754863..68e12630 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -141,8 +141,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr val drawable = getSVGADrawable() ?: return drawable.cleared = false drawable.scaleType = scaleType - drawable.videoItem.reqHeight = height - drawable.videoItem.reqWidth = width + drawable.videoItem.init(width, height) Log.d("SVGAImageView", "height:$height width:$width") } diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index 37094af3..796ed384 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -35,43 +35,22 @@ class SVGAVideoEntity { var frames: Int = 0 private set - internal var reqHeight = 0 - internal var reqWidth = 0 + private var reqHeight = 0 + private var reqWidth = 0 internal var spriteList: List = emptyList() internal var audioList: List = emptyList() internal var soundPool: SoundPool? = null internal var imageMap = HashMap() private var mCacheDir: File + private var mJsonMovie: JSONObject? = null constructor(json: JSONObject, cacheDir: File) { - this.mCacheDir = cacheDir - json.optJSONObject("movie")?.let(this::setup) - try { - parserImages(json) - } catch (e: Exception) { - e.printStackTrace() - } catch (e: OutOfMemoryError) { - e.printStackTrace() - } - resetSprites(json) - } - - internal constructor(entity: MovieEntity, cacheDir: File) { - this.movieItem = entity - this.mCacheDir = cacheDir - entity.params?.let (this::setup) - - try { - parserImages(entity) - } catch (e: Exception) { - e.printStackTrace() - } catch (e: OutOfMemoryError) { - e.printStackTrace() - } - resetSprites(entity) + mJsonMovie = json + mCacheDir = cacheDir + json.optJSONObject("movie")?.let(this::setupByJson) } - private fun setup(movieObject: JSONObject) { + private fun setupByJson(movieObject: JSONObject) { movieObject.optJSONObject("viewBox")?.let { viewBoxObject -> val width = viewBoxObject.optDouble("width", 0.0) val height = viewBoxObject.optDouble("height", 0.0) @@ -81,7 +60,13 @@ class SVGAVideoEntity { frames = movieObject.optInt("frames", 0) } - private fun setup(movieParams: MovieParams) { + internal constructor(entity: MovieEntity, cacheDir: File) { + this.movieItem = entity + this.mCacheDir = cacheDir + entity.params?.let (this::setupByMovie) + } + + private fun setupByMovie(movieParams: MovieParams) { val width = (movieParams.viewBoxWidth ?: 0.0f).toDouble() val height = (movieParams.viewBoxHeight ?: 0.0f).toDouble() videoSize = SVGARect(0.0, 0.0, width, height) @@ -89,6 +74,38 @@ class SVGAVideoEntity { frames = movieParams.frames ?: 0 } + internal fun init(reqWidth:Int, reqHeight:Int) { + this.reqWidth = reqWidth + this.reqHeight = reqHeight + if (mJsonMovie != null) { + parsResourceByJson() + } else if (movieItem != null) { + parsResourceByMovie() + } + } + + private fun parsResourceByJson() { + try { + parserImages(mJsonMovie!!) + } catch (e: Exception) { + e.printStackTrace() + } catch (e: OutOfMemoryError) { + e.printStackTrace() + } + resetSprites(mJsonMovie!!) + } + + private fun parsResourceByMovie() { + try { + parserImages(movieItem!!) + } catch (e: Exception) { + e.printStackTrace() + } catch (e: OutOfMemoryError) { + e.printStackTrace() + } + resetSprites(movieItem!!) + } + internal fun prepare(callback: () -> Unit) { if (movieItem == null) { callback() From 3e0544216ace9b2b276adf691e9a5318603bbbaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 17:16:05 +0800 Subject: [PATCH 13/33] =?UTF-8?q?=E6=9A=B4=E9=9C=B2=20bitmap=20=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../opensource/svgaplayer/SVGAVideoEntity.kt | 15 ++++---- .../svgaplayer/bitmap/BitmapCreator.kt | 27 ++++++++++++++ .../svgaplayer/bitmap/SVGABitmapCreator.kt | 37 +++++++++++++++++++ 3 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt create mode 100644 library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index 796ed384..ac60ea98 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -5,12 +5,13 @@ import android.media.AudioAttributes import android.media.AudioManager import android.media.SoundPool import android.os.Build +import android.util.Log import com.opensource.svgaplayer.entities.SVGAAudioEntity import com.opensource.svgaplayer.entities.SVGAVideoSpriteEntity import com.opensource.svgaplayer.proto.AudioEntity import com.opensource.svgaplayer.proto.MovieEntity import com.opensource.svgaplayer.proto.MovieParams -import com.opensource.svgaplayer.utils.BitmapUtils +import com.opensource.svgaplayer.bitmap.SVGABitmapCreator import com.opensource.svgaplayer.utils.SVGARect import org.json.JSONObject import java.io.File @@ -77,6 +78,7 @@ class SVGAVideoEntity { internal fun init(reqWidth:Int, reqHeight:Int) { this.reqWidth = reqWidth this.reqHeight = reqHeight + Log.d("SVGAVideoEntity", "init reqHeight$reqHeight reqWidth$reqWidth" ) if (mJsonMovie != null) { parsResourceByJson() } else if (movieItem != null) { @@ -142,10 +144,8 @@ class SVGAVideoEntity { } private fun createBitmap(filePath: String): Bitmap? { - if (filePath.isEmpty()) { - return null - } - return BitmapUtils.decodeSampledBitmapFromFile(filePath, reqWidth, reqHeight) + Log.d("SVGAVideoEntity", "createBitmap reqHeight$reqHeight reqWidth$reqWidth" ) + return SVGABitmapCreator.createBitmap(filePath, reqWidth, reqHeight) } private fun parserImages(obj: MovieEntity) { @@ -166,7 +166,8 @@ class SVGAVideoEntity { } private fun createBitmap(byteArray: ByteArray, filePath: String): Bitmap? { - return BitmapUtils.decodeSampledBitmapFromByteArray(byteArray, reqWidth, reqHeight) ?: createBitmap(filePath) + val bitmap = SVGABitmapCreator.createBitmap(byteArray, reqWidth, reqHeight) + return bitmap?:createBitmap(filePath) } private fun resetSprites(json: JSONObject) { @@ -250,7 +251,7 @@ class SVGAVideoEntity { private fun setupSoundPool(entity: MovieEntity, completionBlock: () -> Unit) { var soundLoaded = 0 - soundPool = generateSoundPool(entity); + soundPool = generateSoundPool(entity) soundPool?.setOnLoadCompleteListener { _, _, _ -> soundLoaded++ if (soundLoaded >= entity.audios.count()) { diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt new file mode 100644 index 00000000..d645759c --- /dev/null +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt @@ -0,0 +1,27 @@ +package com.opensource.svgaplayer.bitmap + +import android.graphics.Bitmap + +/** + * + * Create by im_dsd 2020/7/6 16:35 + */ +interface BitmapCreator { + /** + * 创建 bitmap + * + * @param filePath 文件路径 + * @param reqWidth 期望的宽 + * @param reqHeight 期望的高 + */ + fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int): Bitmap? + + /** + * 创建 bitmap + * + * @param byteArray bitmap byte array + * @param reqWidth 期望的宽 + * @param reqHeight 期望的高 + */ + fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int): Bitmap? +} \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt new file mode 100644 index 00000000..001b34da --- /dev/null +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt @@ -0,0 +1,37 @@ +package com.opensource.svgaplayer.bitmap + +import android.graphics.Bitmap +import com.opensource.svgaplayer.utils.BitmapUtils + +/** + * bitmap 构建器具 + * + * Create by im_dsd 2020/7/6 16:40 + */ +object SVGABitmapCreator { + private var mCreator: BitmapCreator? = null; + + fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int): Bitmap? { + if (filePath.isEmpty()) { + return null + } + if (mCreator != null) { + return mCreator?.createBitmap(filePath, reqWidth, reqHeight) + } + return BitmapUtils.decodeSampledBitmapFromFile(filePath, reqWidth, reqHeight) + } + + fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int): Bitmap? { + if (mCreator != null) { + return mCreator?.createBitmap(byteArray, reqWidth, reqHeight) + } + return BitmapUtils.decodeSampledBitmapFromByteArray(byteArray, reqWidth, reqHeight) + } + + /** + * 设置属于自己的构造器,但是要保证在 bitmap 使用期间不会调用 bitmap.recycle() + */ + fun setBitmapCreator(creator: BitmapCreator) { + mCreator = creator + } +} \ No newline at end of file From 14c16f1ee7a5fc13f0c89a2e7e319c3e3f172207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 18:24:19 +0800 Subject: [PATCH 14/33] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20Bitmap=20=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../opensource/svgaplayer/SVGAVideoEntity.kt | 50 +++++++++++++------ .../svgaplayer/bitmap/BitmapCreator.kt | 4 +- .../bitmap/BitmapCreatorCallBack.kt | 11 ++++ .../svgaplayer/bitmap/SVGABitmapCreator.kt | 22 +++++--- 4 files changed, 63 insertions(+), 24 deletions(-) create mode 100644 library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallBack.kt diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index ac60ea98..85742a98 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -6,17 +6,19 @@ import android.media.AudioManager import android.media.SoundPool import android.os.Build import android.util.Log +import com.opensource.svgaplayer.bitmap.BitmapCreatorCallBack +import com.opensource.svgaplayer.bitmap.SVGABitmapCreator import com.opensource.svgaplayer.entities.SVGAAudioEntity import com.opensource.svgaplayer.entities.SVGAVideoSpriteEntity import com.opensource.svgaplayer.proto.AudioEntity import com.opensource.svgaplayer.proto.MovieEntity import com.opensource.svgaplayer.proto.MovieParams -import com.opensource.svgaplayer.bitmap.SVGABitmapCreator import com.opensource.svgaplayer.utils.SVGARect import org.json.JSONObject import java.io.File import java.io.FileInputStream import java.io.FileOutputStream +import java.lang.ref.WeakReference import java.util.* /** @@ -44,6 +46,7 @@ class SVGAVideoEntity { internal var imageMap = HashMap() private var mCacheDir: File private var mJsonMovie: JSONObject? = null + private val mRef = WeakReference(this) constructor(json: JSONObject, cacheDir: File) { mJsonMovie = json @@ -122,11 +125,18 @@ class SVGAVideoEntity { val imgJson = json.optJSONObject("images") ?: return imgJson.keys().forEach { imgKey -> val filePath = generateBitmapFilePath(imgJson[imgKey].toString(), imgKey) - if (filePath.isNotEmpty()) { - val bitmapKey = imgKey.replace(".matte", "") - val bitmap = createBitmap(filePath) ?: return@forEach - imageMap[bitmapKey] = bitmap + if (filePath.isEmpty()) { + return } + val bitmapKey = imgKey.replace(".matte", "") + createBitmap(filePath, object : BitmapCreatorCallBack { + override fun onCreateComplete(bitmap: Bitmap?) { + if (bitmap == null) { + return + } + mRef.get()?.imageMap?.put(bitmapKey, bitmap) + } + }) } } @@ -143,9 +153,9 @@ class SVGAVideoEntity { } } - private fun createBitmap(filePath: String): Bitmap? { - Log.d("SVGAVideoEntity", "createBitmap reqHeight$reqHeight reqWidth$reqWidth" ) - return SVGABitmapCreator.createBitmap(filePath, reqWidth, reqHeight) + private fun createBitmap(filePath: String, callback: BitmapCreatorCallBack) { + Log.d("SVGAVideoEntity", "createBitmap reqHeight$reqHeight reqWidth$reqWidth") + SVGABitmapCreator.createBitmap(filePath, reqWidth, reqHeight, callback) } private fun parserImages(obj: MovieEntity) { @@ -159,15 +169,27 @@ class SVGAVideoEntity { return@forEach } val filePath = generateBitmapFilePath(entry.value.utf8(), entry.key) - createBitmap(byteArray, filePath)?.let { bitmap -> - imageMap[entry.key] = bitmap - } + createBitmap(byteArray, filePath, object : BitmapCreatorCallBack { + override fun onCreateComplete(bitmap: Bitmap?) { + if (bitmap == null) { + return + } + mRef.get()?.imageMap?.put(entry.key, bitmap) + } + }) } } - private fun createBitmap(byteArray: ByteArray, filePath: String): Bitmap? { - val bitmap = SVGABitmapCreator.createBitmap(byteArray, reqWidth, reqHeight) - return bitmap?:createBitmap(filePath) + private fun createBitmap(byteArray: ByteArray, filePath: String, callback: BitmapCreatorCallBack) { + SVGABitmapCreator.createBitmap(byteArray, reqWidth, reqHeight, object : BitmapCreatorCallBack { + override fun onCreateComplete(bitmap: Bitmap?) { + if (bitmap != null) { + callback.onCreateComplete(bitmap) + } else { + createBitmap(filePath, callback) + } + } + }) } private fun resetSprites(json: JSONObject) { diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt index d645759c..bc10df13 100644 --- a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt @@ -14,7 +14,7 @@ interface BitmapCreator { * @param reqWidth 期望的宽 * @param reqHeight 期望的高 */ - fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int): Bitmap? + fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallBack): Bitmap? /** * 创建 bitmap @@ -23,5 +23,5 @@ interface BitmapCreator { * @param reqWidth 期望的宽 * @param reqHeight 期望的高 */ - fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int): Bitmap? + fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallBack): Bitmap? } \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallBack.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallBack.kt new file mode 100644 index 00000000..1acfe249 --- /dev/null +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallBack.kt @@ -0,0 +1,11 @@ +package com.opensource.svgaplayer.bitmap + +import android.graphics.Bitmap + +/** + * + * Create by im_dsd 2020/7/6 17:59 + */ +interface BitmapCreatorCallBack { + fun onCreateComplete(bitmap: Bitmap?) +} \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt index 001b34da..54dd274c 100644 --- a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt @@ -1,6 +1,5 @@ package com.opensource.svgaplayer.bitmap -import android.graphics.Bitmap import com.opensource.svgaplayer.utils.BitmapUtils /** @@ -11,21 +10,28 @@ import com.opensource.svgaplayer.utils.BitmapUtils object SVGABitmapCreator { private var mCreator: BitmapCreator? = null; - fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int): Bitmap? { + fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallBack) { if (filePath.isEmpty()) { - return null + callback.onCreateComplete(null) } if (mCreator != null) { - return mCreator?.createBitmap(filePath, reqWidth, reqHeight) + mCreator?.createBitmap(filePath, reqWidth, reqHeight, callback) + } else { + val bitmap = BitmapUtils.decodeSampledBitmapFromFile(filePath, reqWidth, reqHeight) + callback.onCreateComplete(bitmap) } - return BitmapUtils.decodeSampledBitmapFromFile(filePath, reqWidth, reqHeight) } - fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int): Bitmap? { + fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallBack) { + if (byteArray.isEmpty()) { + return + } if (mCreator != null) { - return mCreator?.createBitmap(byteArray, reqWidth, reqHeight) + mCreator?.createBitmap(byteArray, reqWidth, reqHeight, callback) + } else { + val bitmap = BitmapUtils.decodeSampledBitmapFromByteArray(byteArray, reqWidth, reqHeight) + callback.onCreateComplete(bitmap) } - return BitmapUtils.decodeSampledBitmapFromByteArray(byteArray, reqWidth, reqHeight) } /** From ecbd9b525ed8540ae7722f5a9da089e68bcd3655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 18:29:59 +0800 Subject: [PATCH 15/33] review code --- .gitignore | 1 + .../com/opensource/svgaplayer/SVGAVideoEntity.kt | 12 ++++++------ .../opensource/svgaplayer/bitmap/BitmapCreator.kt | 6 ++---- ...apCreatorCallBack.kt => BitmapCreatorCallback.kt} | 2 +- .../svgaplayer/bitmap/SVGABitmapCreator.kt | 4 ++-- 5 files changed, 12 insertions(+), 13 deletions(-) rename library/src/main/java/com/opensource/svgaplayer/bitmap/{BitmapCreatorCallBack.kt => BitmapCreatorCallback.kt} (82%) diff --git a/.gitignore b/.gitignore index 80e61319..c4507d8a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ /build /captures *.iml +/SVGAPlayer \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index 85742a98..58cbdc26 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -6,7 +6,7 @@ import android.media.AudioManager import android.media.SoundPool import android.os.Build import android.util.Log -import com.opensource.svgaplayer.bitmap.BitmapCreatorCallBack +import com.opensource.svgaplayer.bitmap.BitmapCreatorCallback import com.opensource.svgaplayer.bitmap.SVGABitmapCreator import com.opensource.svgaplayer.entities.SVGAAudioEntity import com.opensource.svgaplayer.entities.SVGAVideoSpriteEntity @@ -129,7 +129,7 @@ class SVGAVideoEntity { return } val bitmapKey = imgKey.replace(".matte", "") - createBitmap(filePath, object : BitmapCreatorCallBack { + createBitmap(filePath, object : BitmapCreatorCallback { override fun onCreateComplete(bitmap: Bitmap?) { if (bitmap == null) { return @@ -153,7 +153,7 @@ class SVGAVideoEntity { } } - private fun createBitmap(filePath: String, callback: BitmapCreatorCallBack) { + private fun createBitmap(filePath: String, callback: BitmapCreatorCallback) { Log.d("SVGAVideoEntity", "createBitmap reqHeight$reqHeight reqWidth$reqWidth") SVGABitmapCreator.createBitmap(filePath, reqWidth, reqHeight, callback) } @@ -169,7 +169,7 @@ class SVGAVideoEntity { return@forEach } val filePath = generateBitmapFilePath(entry.value.utf8(), entry.key) - createBitmap(byteArray, filePath, object : BitmapCreatorCallBack { + createBitmap(byteArray, filePath, object : BitmapCreatorCallback { override fun onCreateComplete(bitmap: Bitmap?) { if (bitmap == null) { return @@ -180,8 +180,8 @@ class SVGAVideoEntity { } } - private fun createBitmap(byteArray: ByteArray, filePath: String, callback: BitmapCreatorCallBack) { - SVGABitmapCreator.createBitmap(byteArray, reqWidth, reqHeight, object : BitmapCreatorCallBack { + private fun createBitmap(byteArray: ByteArray, filePath: String, callback: BitmapCreatorCallback) { + SVGABitmapCreator.createBitmap(byteArray, reqWidth, reqHeight, object : BitmapCreatorCallback { override fun onCreateComplete(bitmap: Bitmap?) { if (bitmap != null) { callback.onCreateComplete(bitmap) diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt index bc10df13..30ee3430 100644 --- a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt @@ -1,7 +1,5 @@ package com.opensource.svgaplayer.bitmap -import android.graphics.Bitmap - /** * * Create by im_dsd 2020/7/6 16:35 @@ -14,7 +12,7 @@ interface BitmapCreator { * @param reqWidth 期望的宽 * @param reqHeight 期望的高 */ - fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallBack): Bitmap? + fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallback) /** * 创建 bitmap @@ -23,5 +21,5 @@ interface BitmapCreator { * @param reqWidth 期望的宽 * @param reqHeight 期望的高 */ - fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallBack): Bitmap? + fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallback) } \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallBack.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallback.kt similarity index 82% rename from library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallBack.kt rename to library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallback.kt index 1acfe249..203f595d 100644 --- a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallBack.kt +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallback.kt @@ -6,6 +6,6 @@ import android.graphics.Bitmap * * Create by im_dsd 2020/7/6 17:59 */ -interface BitmapCreatorCallBack { +interface BitmapCreatorCallback { fun onCreateComplete(bitmap: Bitmap?) } \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt index 54dd274c..de01bb19 100644 --- a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt @@ -10,7 +10,7 @@ import com.opensource.svgaplayer.utils.BitmapUtils object SVGABitmapCreator { private var mCreator: BitmapCreator? = null; - fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallBack) { + fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallback) { if (filePath.isEmpty()) { callback.onCreateComplete(null) } @@ -22,7 +22,7 @@ object SVGABitmapCreator { } } - fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallBack) { + fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallback) { if (byteArray.isEmpty()) { return } From ce97ef14d7027cc10aa695f1d4a9060042ed3ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 19:09:01 +0800 Subject: [PATCH 16/33] =?UTF-8?q?review=20code=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/opensource/svgaplayer/SVGAImageView.kt | 11 ----------- .../main/java/com/opensource/svgaplayer/SVGAParser.kt | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index 68e12630..c0e51dae 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -142,7 +142,6 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr drawable.cleared = false drawable.scaleType = scaleType drawable.videoItem.init(width, height) - Log.d("SVGAImageView", "height:$height width:$width") } private fun getSVGADrawable(): SVGADrawable? { @@ -189,14 +188,12 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr callback?.onFinished() // 不是循环播放时,手动停止一下 if ((animation as ValueAnimator).repeatCount <= 0) { - Log.d("## onAnimationEnd", "onFinished") // 要根据用户设置的 clearsAfterStop 状态判断,不可手动置 true stopAnimation() } } fun pauseAnimation() { - Log.d("## pauseAnimation", "") stopAnimation(false) callback?.onPause() } @@ -206,8 +203,6 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr } fun stopAnimation(clear: Boolean) { - Log.d("## stopAnimation", "cancel") - mAnimator?.cancel() mAnimator?.removeAllListeners() mAnimator?.removeAllUpdateListeners() @@ -288,21 +283,17 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr override fun onAnimationRepeat(animation: Animator?) { weakReference.get()?.callback?.onRepeat() - Log.d("## onAnimationRepeat", (animation as ValueAnimator).repeatCount.toString()) } override fun onAnimationEnd(animation: Animator?) { - Log.d("## onAnimationEnd", (animation as ValueAnimator).repeatCount.toString()) weakReference.get()?.onAnimationEnd(animation) } override fun onAnimationCancel(animation: Animator?) { - Log.d("## onAnimationCancel", (animation as ValueAnimator).duration.toString()) weakReference.get()?.isAnimating = false } override fun onAnimationStart(animation: Animator?) { - Log.d("## onAnimationStart", (animation as ValueAnimator).duration.toString()) weakReference.get()?.isAnimating = true } } // end of AnimatorListener @@ -312,8 +303,6 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr private val weakReference = WeakReference(view) override fun onAnimationUpdate(animation: ValueAnimator?) { - Log.d("## onAnimationUpdate", (animation as ValueAnimator).repeatCount.toString()) - weakReference.get()?.onAnimatorUpdate(animation) } } // end of AnimatorUpdateListener diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt index 8a5628c7..35ab0669 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt @@ -85,7 +85,7 @@ class SVGAParser(context: Context?) { var fileDownloader = FileDownloader() companion object { - internal var threadPoolExecutor = Executors.newSingleThreadExecutor() + internal var threadPoolExecutor = Executors.newCachedThreadPool() fun setThreadPoolExecutor(executor: ThreadPoolExecutor) { threadPoolExecutor = executor From b2cf0cd9b8cf365a2f3366a5fa83a7bacb029331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 20:24:28 +0800 Subject: [PATCH 17/33] =?UTF-8?q?=E6=8F=90=E5=8F=96=E5=9B=9E=E6=94=B6?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../opensource/svgaplayer/SVGAImageView.kt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index c0e51dae..a816ba1f 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -189,7 +189,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr // 不是循环播放时,手动停止一下 if ((animation as ValueAnimator).repeatCount <= 0) { // 要根据用户设置的 clearsAfterStop 状态判断,不可手动置 true - stopAnimation() + release() } } @@ -207,13 +207,18 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr mAnimator?.removeAllListeners() mAnimator?.removeAllUpdateListeners() if (clear) { - getSVGADrawable()?.cleared = true - // 回收内存 - getSVGADrawable()?.release() - // 清除对 drawable 的引用 - setImageDrawable(null) + release() + } else { + getSVGADrawable()?.clearAudio() } - getSVGADrawable()?.clearAudio() + } + + private fun release() { + getSVGADrawable()?.cleared = true + // 回收内存 + getSVGADrawable()?.release() + // 清除对 drawable 的引用 + setImageDrawable(null) } fun setVideoItem(videoItem: SVGAVideoEntity?) { From 8f5df11087ea20f2023adc28df323e03b4957823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Mon, 6 Jul 2020 20:53:35 +0800 Subject: [PATCH 18/33] review code --- .../com/opensource/svgaplayer/SVGAImageView.kt | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index a816ba1f..36752962 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -176,6 +176,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr private fun onAnimationEnd(animation: Animator?) { isAnimating = false + stopAnimation() val drawable = getSVGADrawable() if (!clearsAfterStop && drawable != null) { if (fillMode == FillMode.Backward) { @@ -184,13 +185,10 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr drawable.currentFrame = mEndFrame } } - - callback?.onFinished() - // 不是循环播放时,手动停止一下 - if ((animation as ValueAnimator).repeatCount <= 0) { - // 要根据用户设置的 clearsAfterStop 状态判断,不可手动置 true + if (clearsAfterStop && (animation as ValueAnimator).repeatCount <= 0) { release() } + callback?.onFinished() } fun pauseAnimation() { @@ -206,11 +204,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr mAnimator?.cancel() mAnimator?.removeAllListeners() mAnimator?.removeAllUpdateListeners() - if (clear) { - release() - } else { - getSVGADrawable()?.clearAudio() - } + getSVGADrawable()?.cleared = clear } private fun release() { @@ -281,6 +275,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr override fun onDetachedFromWindow() { super.onDetachedFromWindow() stopAnimation(true) + release() } private class AnimatorListener(view: SVGAImageView) : Animator.AnimatorListener { From 8440d028301fb23c9d0c3f110d110829a9d2647f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Tue, 7 Jul 2020 00:46:38 +0800 Subject: [PATCH 19/33] Update SVGAVideoEntity.kt --- .../src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index 58cbdc26..d48a6df0 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -212,6 +212,7 @@ class SVGAVideoEntity { private fun setupAudios(entity: MovieEntity, completionBlock: () -> Unit) { if (entity.audios == null || entity.audios.isEmpty()) { + // 为啥会有音轨? run(completionBlock) } setupSoundPool(entity, completionBlock) @@ -287,6 +288,7 @@ class SVGAVideoEntity { .setUsage(AudioAttributes.USAGE_MEDIA) .build() SoundPool.Builder().setAudioAttributes(attributes) + // 报错的点,看看音频数量 .setMaxStreams(12.coerceAtMost(entity.audios.count())) .build() } else { From 21e5be0435769397fa65a8f440fddd2e13d5ed67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Tue, 7 Jul 2020 11:32:12 +0800 Subject: [PATCH 20/33] debug & rename --- .../java/com/opensource/svgaplayer/SVGADrawable.kt | 10 ++++------ .../java/com/opensource/svgaplayer/SVGAImageView.kt | 8 ++++---- .../java/com/opensource/svgaplayer/SVGAVideoEntity.kt | 1 + .../com/opensource/svgaplayer/utils/BitmapUtils.kt | 2 -- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt b/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt index 2dc7d804..9c538f2e 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGADrawable.kt @@ -42,7 +42,9 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE } } - override fun setAlpha(alpha: Int) {} + override fun setAlpha(alpha: Int) { + + } override fun getOpacity(): Int { return PixelFormat.TRANSPARENT @@ -52,17 +54,13 @@ class SVGADrawable(val videoItem: SVGAVideoEntity, val dynamicItem: SVGADynamicE } - internal fun clearAudio() { + internal fun clear() { videoItem.audioList.forEach { audio -> audio.playID?.let { videoItem.soundPool?.stop(it) } audio.playID = null } - } - - internal fun release() { - clearAudio() videoItem.clear() } } \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index 36752962..17d14fdc 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -186,7 +186,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr } } if (clearsAfterStop && (animation as ValueAnimator).repeatCount <= 0) { - release() + clear() } callback?.onFinished() } @@ -207,10 +207,10 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr getSVGADrawable()?.cleared = clear } - private fun release() { + private fun clear() { getSVGADrawable()?.cleared = true // 回收内存 - getSVGADrawable()?.release() + getSVGADrawable()?.clear() // 清除对 drawable 的引用 setImageDrawable(null) } @@ -275,7 +275,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr override fun onDetachedFromWindow() { super.onDetachedFromWindow() stopAnimation(true) - release() + clear() } private class AnimatorListener(view: SVGAImageView) : Animator.AnimatorListener { diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index d48a6df0..b5081ab1 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -214,6 +214,7 @@ class SVGAVideoEntity { if (entity.audios == null || entity.audios.isEmpty()) { // 为啥会有音轨? run(completionBlock) + return } setupSoundPool(entity, completionBlock) val audiosFileMap = generateAudioFileMap(entity) diff --git a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt b/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt index e8bbb39d..7defd7a3 100644 --- a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt +++ b/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt @@ -56,7 +56,6 @@ object BitmapUtils { val (height: Int, width: Int) = options.run { outHeight to outWidth } var inSampleSize = 1 if (reqHeight <= 0 || reqWidth <= 0) { - Log.d("BitmapUtils", "inSampleSize:$inSampleSize height:$height width$width reqHeight$reqHeight reqWidth$reqWidth" ) return inSampleSize } if (height > reqHeight || width > reqWidth) { @@ -71,7 +70,6 @@ object BitmapUtils { } } - Log.d("BitmapUtils", "inSampleSize:$inSampleSize height:$height width$width reqHeight$reqHeight reqWidth$reqWidth" ) return inSampleSize } From c92d5e7735bb6c520c56751db6743692d4323544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Tue, 7 Jul 2020 12:58:05 +0800 Subject: [PATCH 21/33] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BitmapUtils.kt => SVGABitmapDecoder.kt} | 11 ++--- .../opensource/svgaplayer/SVGAVideoEntity.kt | 47 +++++-------------- .../svgaplayer/bitmap/BitmapCreator.kt | 25 ---------- .../bitmap/BitmapCreatorCallback.kt | 11 ----- .../svgaplayer/bitmap/SVGABitmapCreator.kt | 43 ----------------- 5 files changed, 17 insertions(+), 120 deletions(-) rename library/src/main/java/com/opensource/svgaplayer/{utils/BitmapUtils.kt => SVGABitmapDecoder.kt} (93%) delete mode 100644 library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt delete mode 100644 library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallback.kt delete mode 100644 library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt diff --git a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt b/library/src/main/java/com/opensource/svgaplayer/SVGABitmapDecoder.kt similarity index 93% rename from library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt rename to library/src/main/java/com/opensource/svgaplayer/SVGABitmapDecoder.kt index 7defd7a3..b0532640 100644 --- a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGABitmapDecoder.kt @@ -1,16 +1,16 @@ -package com.opensource.svgaplayer.utils +package com.opensource.svgaplayer import android.graphics.Bitmap import android.graphics.BitmapFactory -import android.util.Log /** + * bitmap 解码器 * * Create by im_dsd 2020/7/4 21:10 */ -object BitmapUtils { +internal object SVGABitmapDecoder { - fun decodeSampledBitmapFromFile( + fun decodeBitmapFromFile( fileName: String, reqWidth: Int, reqHeight: Int @@ -30,7 +30,7 @@ object BitmapUtils { } } - fun decodeSampledBitmapFromByteArray( + fun decodeBitmapFromByteArray( byteArray: ByteArray, reqWidth: Int, reqHeight: Int @@ -72,5 +72,4 @@ object BitmapUtils { return inSampleSize } - } \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index b5081ab1..b8db2c06 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -5,9 +5,6 @@ import android.media.AudioAttributes import android.media.AudioManager import android.media.SoundPool import android.os.Build -import android.util.Log -import com.opensource.svgaplayer.bitmap.BitmapCreatorCallback -import com.opensource.svgaplayer.bitmap.SVGABitmapCreator import com.opensource.svgaplayer.entities.SVGAAudioEntity import com.opensource.svgaplayer.entities.SVGAVideoSpriteEntity import com.opensource.svgaplayer.proto.AudioEntity @@ -18,7 +15,6 @@ import org.json.JSONObject import java.io.File import java.io.FileInputStream import java.io.FileOutputStream -import java.lang.ref.WeakReference import java.util.* /** @@ -46,7 +42,6 @@ class SVGAVideoEntity { internal var imageMap = HashMap() private var mCacheDir: File private var mJsonMovie: JSONObject? = null - private val mRef = WeakReference(this) constructor(json: JSONObject, cacheDir: File) { mJsonMovie = json @@ -81,7 +76,6 @@ class SVGAVideoEntity { internal fun init(reqWidth:Int, reqHeight:Int) { this.reqWidth = reqWidth this.reqHeight = reqHeight - Log.d("SVGAVideoEntity", "init reqHeight$reqHeight reqWidth$reqWidth" ) if (mJsonMovie != null) { parsResourceByJson() } else if (movieItem != null) { @@ -129,14 +123,10 @@ class SVGAVideoEntity { return } val bitmapKey = imgKey.replace(".matte", "") - createBitmap(filePath, object : BitmapCreatorCallback { - override fun onCreateComplete(bitmap: Bitmap?) { - if (bitmap == null) { - return - } - mRef.get()?.imageMap?.put(bitmapKey, bitmap) - } - }) + val bitmap = createBitmap(filePath) + if (bitmap != null) { + imageMap[bitmapKey] = bitmap + } } } @@ -153,9 +143,8 @@ class SVGAVideoEntity { } } - private fun createBitmap(filePath: String, callback: BitmapCreatorCallback) { - Log.d("SVGAVideoEntity", "createBitmap reqHeight$reqHeight reqWidth$reqWidth") - SVGABitmapCreator.createBitmap(filePath, reqWidth, reqHeight, callback) + private fun createBitmap(filePath: String): Bitmap? { + return SVGABitmapDecoder.decodeBitmapFromFile(filePath, reqWidth, reqHeight) } private fun parserImages(obj: MovieEntity) { @@ -169,27 +158,15 @@ class SVGAVideoEntity { return@forEach } val filePath = generateBitmapFilePath(entry.value.utf8(), entry.key) - createBitmap(byteArray, filePath, object : BitmapCreatorCallback { - override fun onCreateComplete(bitmap: Bitmap?) { - if (bitmap == null) { - return - } - mRef.get()?.imageMap?.put(entry.key, bitmap) - } - }) + createBitmap(byteArray, filePath)?.let { bitmap -> + imageMap[entry.key] = bitmap + } } } - private fun createBitmap(byteArray: ByteArray, filePath: String, callback: BitmapCreatorCallback) { - SVGABitmapCreator.createBitmap(byteArray, reqWidth, reqHeight, object : BitmapCreatorCallback { - override fun onCreateComplete(bitmap: Bitmap?) { - if (bitmap != null) { - callback.onCreateComplete(bitmap) - } else { - createBitmap(filePath, callback) - } - } - }) + private fun createBitmap(byteArray: ByteArray, filePath: String): Bitmap? { + val bitmap = SVGABitmapDecoder.decodeBitmapFromByteArray(byteArray, reqWidth, reqHeight) + return bitmap ?: createBitmap(filePath) } private fun resetSprites(json: JSONObject) { diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt deleted file mode 100644 index 30ee3430..00000000 --- a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreator.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.opensource.svgaplayer.bitmap - -/** - * - * Create by im_dsd 2020/7/6 16:35 - */ -interface BitmapCreator { - /** - * 创建 bitmap - * - * @param filePath 文件路径 - * @param reqWidth 期望的宽 - * @param reqHeight 期望的高 - */ - fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallback) - - /** - * 创建 bitmap - * - * @param byteArray bitmap byte array - * @param reqWidth 期望的宽 - * @param reqHeight 期望的高 - */ - fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallback) -} \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallback.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallback.kt deleted file mode 100644 index 203f595d..00000000 --- a/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapCreatorCallback.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.opensource.svgaplayer.bitmap - -import android.graphics.Bitmap - -/** - * - * Create by im_dsd 2020/7/6 17:59 - */ -interface BitmapCreatorCallback { - fun onCreateComplete(bitmap: Bitmap?) -} \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt deleted file mode 100644 index de01bb19..00000000 --- a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapCreator.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.opensource.svgaplayer.bitmap - -import com.opensource.svgaplayer.utils.BitmapUtils - -/** - * bitmap 构建器具 - * - * Create by im_dsd 2020/7/6 16:40 - */ -object SVGABitmapCreator { - private var mCreator: BitmapCreator? = null; - - fun createBitmap(filePath: String, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallback) { - if (filePath.isEmpty()) { - callback.onCreateComplete(null) - } - if (mCreator != null) { - mCreator?.createBitmap(filePath, reqWidth, reqHeight, callback) - } else { - val bitmap = BitmapUtils.decodeSampledBitmapFromFile(filePath, reqWidth, reqHeight) - callback.onCreateComplete(bitmap) - } - } - - fun createBitmap(byteArray: ByteArray, reqWidth: Int, reqHeight: Int, callback: BitmapCreatorCallback) { - if (byteArray.isEmpty()) { - return - } - if (mCreator != null) { - mCreator?.createBitmap(byteArray, reqWidth, reqHeight, callback) - } else { - val bitmap = BitmapUtils.decodeSampledBitmapFromByteArray(byteArray, reqWidth, reqHeight) - callback.onCreateComplete(bitmap) - } - } - - /** - * 设置属于自己的构造器,但是要保证在 bitmap 使用期间不会调用 bitmap.recycle() - */ - fun setBitmapCreator(creator: BitmapCreator) { - mCreator = creator - } -} \ No newline at end of file From 04694cd2f0d62f640d67c4d18a4e36de0babe2cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Tue, 7 Jul 2020 13:01:31 +0800 Subject: [PATCH 22/33] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E7=9A=84=E7=BA=BF=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/build.gradle | 1 - .../opensource/svgaplayer/SVGAImageView.kt | 19 ++++++------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/library/build.gradle b/library/build.gradle index 0d9d417e..793d0c5d 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -32,7 +32,6 @@ dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.squareup.wire:wire-runtime:2.3.0-RC1' implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7" } repositories { mavenCentral() diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index 17d14fdc..d41784a2 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -12,8 +12,6 @@ import android.view.View import android.view.animation.LinearInterpolator import android.widget.ImageView import com.opensource.svgaplayer.utils.SVGARange -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import java.lang.ref.WeakReference import java.net.URL @@ -73,17 +71,12 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr } private fun parserSource(source: String) { - // 使用弱引用解决内存泄漏 - val ref = WeakReference(this) - - // 在后台启动一个新的协程并继续 - GlobalScope.launch { - val parser = SVGAParser(context) - if (source.startsWith("http://") || source.startsWith("https://")) { - parser.decodeFromURL(URL(source), createParseCompletion(ref)) - } else { - parser.decodeFromAssets(source, createParseCompletion(ref)) - } + val refImgView = WeakReference(this) + val parser = SVGAParser(context) + if (source.startsWith("http://") || source.startsWith("https://")) { + parser.decodeFromURL(URL(source), createParseCompletion(refImgView)) + } else { + parser.decodeFromAssets(source, createParseCompletion(refImgView)) } } From 8555f9681d713d08295b0cb5b4a0785e39b6a6d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Tue, 7 Jul 2020 13:18:28 +0800 Subject: [PATCH 23/33] review code --- .../src/main/java/com/opensource/svgaplayer/SVGAImageView.kt | 5 ++--- .../main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index d41784a2..7d7e74ec 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -202,7 +202,6 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr private fun clear() { getSVGADrawable()?.cleared = true - // 回收内存 getSVGADrawable()?.clear() // 清除对 drawable 的引用 setImageDrawable(null) @@ -212,11 +211,11 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr setVideoItem(videoItem, SVGADynamicEntity()) } - fun setVideoItem(videoItem: SVGAVideoEntity?, dynamicItem: SVGADynamicEntity = SVGADynamicEntity()) { + fun setVideoItem(videoItem: SVGAVideoEntity?, dynamicItem: SVGADynamicEntity?) { if (videoItem == null) { setImageDrawable(null) } else { - val drawable = SVGADrawable(videoItem, dynamicItem) + val drawable = SVGADrawable(videoItem, dynamicItem ?: SVGADynamicEntity()) drawable.cleared = clearsAfterStop setImageDrawable(drawable) } diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index b8db2c06..cfeddd4f 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -189,7 +189,6 @@ class SVGAVideoEntity { private fun setupAudios(entity: MovieEntity, completionBlock: () -> Unit) { if (entity.audios == null || entity.audios.isEmpty()) { - // 为啥会有音轨? run(completionBlock) return } @@ -266,7 +265,6 @@ class SVGAVideoEntity { .setUsage(AudioAttributes.USAGE_MEDIA) .build() SoundPool.Builder().setAudioAttributes(attributes) - // 报错的点,看看音频数量 .setMaxStreams(12.coerceAtMost(entity.audios.count())) .build() } else { From dde6b168cc8307a131695df0f2846718a52a37cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Tue, 7 Jul 2020 13:49:39 +0800 Subject: [PATCH 24/33] review --- .../AnimationFromAssetsActivity.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java index be8a6a0e..cdd1e6a9 100644 --- a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java +++ b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java @@ -4,7 +4,6 @@ import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; -import android.util.Log; import android.view.View; import com.opensource.svgaplayer.SVGAImageView; @@ -36,16 +35,13 @@ public void onClick(View view) { } private void loadAnimation() { - String fileName = this.randomSample(); - Log.d("AssetsActivity", fileName); - - SVGAParser.Companion.shareParser().decodeFromAssets(fileName, new SVGAParser.ParseCompletion() { - @Override - public void onComplete(@NotNull SVGAVideoEntity videoItem) { - animationView.setVideoItem(videoItem); - animationView.stepToFrame(0, true); - } - @Override + SVGAParser.Companion.shareParser().decodeFromAssets(this.randomSample(), new SVGAParser.ParseCompletion() { + @Override + public void onComplete(@NotNull SVGAVideoEntity videoItem) { + animationView.setVideoItem(videoItem); + animationView.stepToFrame(0, true); + } + @Override public void onError() { } From 4380fd2cff4075ed6b9d0e91f538cba329c5f069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Tue, 7 Jul 2020 13:52:47 +0800 Subject: [PATCH 25/33] review --- .gitignore | 1 - .../ponycui_home/svgaplayer/AnimationFromAssetsActivity.java | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c4507d8a..80e61319 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,3 @@ /build /captures *.iml -/SVGAPlayer \ No newline at end of file diff --git a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java index cdd1e6a9..447ed070 100644 --- a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java +++ b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java @@ -41,6 +41,7 @@ public void onComplete(@NotNull SVGAVideoEntity videoItem) { animationView.setVideoItem(videoItem); animationView.stepToFrame(0, true); } + @Override public void onError() { From 227bb9406b5758ee443c9ad02de9a2a865bc1ba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Tue, 7 Jul 2020 18:15:21 +0800 Subject: [PATCH 26/33] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../svgaplayer/SVGABitmapDecoder.kt | 75 ------------------- .../svgaplayer/SVGADynamicEntity.kt | 5 +- .../opensource/svgaplayer/SVGAImageView.kt | 16 ++-- .../com/opensource/svgaplayer/SVGAParser.kt | 8 +- .../opensource/svgaplayer/SVGAVideoEntity.kt | 53 ++++++------- .../bitmap/SVGABitmapByteArrayDecoder.kt | 16 ++++ .../svgaplayer/bitmap/SVGABitmapDecoder.kt | 36 +++++++++ .../bitmap/SVGABitmapFileDecoder.kt | 16 ++++ .../svgaplayer/utils/BitmapUtils.kt | 32 ++++++++ 9 files changed, 136 insertions(+), 121 deletions(-) delete mode 100644 library/src/main/java/com/opensource/svgaplayer/SVGABitmapDecoder.kt create mode 100644 library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapByteArrayDecoder.kt create mode 100644 library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt create mode 100644 library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapFileDecoder.kt create mode 100644 library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGABitmapDecoder.kt b/library/src/main/java/com/opensource/svgaplayer/SVGABitmapDecoder.kt deleted file mode 100644 index b0532640..00000000 --- a/library/src/main/java/com/opensource/svgaplayer/SVGABitmapDecoder.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.opensource.svgaplayer - -import android.graphics.Bitmap -import android.graphics.BitmapFactory - -/** - * bitmap 解码器 - * - * Create by im_dsd 2020/7/4 21:10 - */ -internal object SVGABitmapDecoder { - - fun decodeBitmapFromFile( - fileName: String, - reqWidth: Int, - reqHeight: Int - ): Bitmap? { - // First decode with inJustDecodeBounds=true to check dimensions - return BitmapFactory.Options().run { - inJustDecodeBounds = true - inPreferredConfig = Bitmap.Config.RGB_565 - BitmapFactory.decodeFile(fileName, this) - - // Calculate inSampleSize - inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight) - - // Decode bitmap with inSampleSize set - inJustDecodeBounds = false - BitmapFactory.decodeFile(fileName, this) - } - } - - fun decodeBitmapFromByteArray( - byteArray: ByteArray, - reqWidth: Int, - reqHeight: Int - ): Bitmap? { - // First decode with inJustDecodeBounds=true to check dimensions - return BitmapFactory.Options().run { - inJustDecodeBounds = true - inPreferredConfig = Bitmap.Config.RGB_565 - BitmapFactory.decodeByteArray(byteArray, 0, byteArray.count(), this) - - // Calculate inSampleSize - inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight) - - // Decode bitmap with inSampleSize set - inJustDecodeBounds = false - - BitmapFactory.decodeByteArray(byteArray, 0, byteArray.count(), this) - } - } - - private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { - // Raw height and width of image - val (height: Int, width: Int) = options.run { outHeight to outWidth } - var inSampleSize = 1 - if (reqHeight <= 0 || reqWidth <= 0) { - return inSampleSize - } - if (height > reqHeight || width > reqWidth) { - - val halfHeight: Int = height / 2 - val halfWidth: Int = width / 2 - - // Calculate the largest inSampleSize value that is a power of 2 and keeps both - // height and width larger than the requested height and width. - while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) { - inSampleSize *= 2 - } - } - - return inSampleSize - } -} \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGADynamicEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGADynamicEntity.kt index 4b5ac5e4..f578c479 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGADynamicEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGADynamicEntity.kt @@ -8,7 +8,6 @@ import android.text.StaticLayout import android.text.TextPaint import java.net.HttpURLConnection import java.net.URL -import kotlin.concurrent.thread /** * Created by cuiminghui on 2017/3/30. @@ -29,8 +28,6 @@ class SVGADynamicEntity { internal var dynamicDrawer: HashMap Boolean> = hashMapOf() - - //点击事件回调map internal var mClickMap : HashMap = hashMapOf() internal var dynamicIClickArea: HashMap = hashMapOf() @@ -98,7 +95,7 @@ class SVGADynamicEntity { fun setClickArea(clickKey: List) { for(itemKey in clickKey){ - dynamicIClickArea.put(itemKey,object : IClickAreaListener{ + dynamicIClickArea.put(itemKey,object : IClickAreaListener { override fun onResponseArea(key: String, x0: Int, y0: Int, x1: Int, y1: Int) { mClickMap.let { if(it.get(key) == null){ diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index 7d7e74ec..26913bfb 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -134,7 +134,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr val drawable = getSVGADrawable() ?: return drawable.cleared = false drawable.scaleType = scaleType - drawable.videoItem.init(width, height) + drawable.videoItem.parserResourceWithViewSize(width, height) } private fun getSVGADrawable(): SVGADrawable? { @@ -184,6 +184,13 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr callback?.onFinished() } + private fun clear() { + getSVGADrawable()?.cleared = true + getSVGADrawable()?.clear() + // 清除对 drawable 的引用 + setImageDrawable(null) + } + fun pauseAnimation() { stopAnimation(false) callback?.onPause() @@ -200,13 +207,6 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr getSVGADrawable()?.cleared = clear } - private fun clear() { - getSVGADrawable()?.cleared = true - getSVGADrawable()?.clear() - // 清除对 drawable 的引用 - setImageDrawable(null) - } - fun setVideoItem(videoItem: SVGAVideoEntity?) { setVideoItem(videoItem, SVGADynamicEntity()) } diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt index 35ab0669..90f062ae 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt @@ -12,7 +12,9 @@ import java.net.HttpURLConnection import java.net.URL import java.security.MessageDigest import java.util.concurrent.Executors +import java.util.concurrent.ThreadFactory import java.util.concurrent.ThreadPoolExecutor +import java.util.concurrent.atomic.AtomicInteger import java.util.zip.Inflater import java.util.zip.ZipInputStream @@ -79,13 +81,15 @@ class SVGAParser(context: Context?) { } return cancelBlock } - } var fileDownloader = FileDownloader() companion object { - internal var threadPoolExecutor = Executors.newCachedThreadPool() + private val threadNum = AtomicInteger(0) + internal var threadPoolExecutor = Executors.newCachedThreadPool { runable -> + Thread("SVGAParser-Thread-${threadNum.getAndIncrement()}") + } fun setThreadPoolExecutor(executor: ThreadPoolExecutor) { threadPoolExecutor = executor diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index cfeddd4f..b05f875f 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -5,6 +5,8 @@ import android.media.AudioAttributes import android.media.AudioManager import android.media.SoundPool import android.os.Build +import com.opensource.svgaplayer.bitmap.SVGABitmapByteArrayDecoder +import com.opensource.svgaplayer.bitmap.SVGABitmapFileDecoder import com.opensource.svgaplayer.entities.SVGAAudioEntity import com.opensource.svgaplayer.entities.SVGAVideoSpriteEntity import com.opensource.svgaplayer.proto.AudioEntity @@ -73,46 +75,33 @@ class SVGAVideoEntity { frames = movieParams.frames ?: 0 } - internal fun init(reqWidth:Int, reqHeight:Int) { - this.reqWidth = reqWidth - this.reqHeight = reqHeight - if (mJsonMovie != null) { - parsResourceByJson() - } else if (movieItem != null) { - parsResourceByMovie() + internal fun prepare(callback: () -> Unit) { + if (movieItem == null) { + callback() + } else { + setupAudios(movieItem!!) { + callback() + } } } - private fun parsResourceByJson() { - try { - parserImages(mJsonMovie!!) - } catch (e: Exception) { - e.printStackTrace() - } catch (e: OutOfMemoryError) { - e.printStackTrace() - } - resetSprites(mJsonMovie!!) - } + internal fun parserResourceWithViewSize(reqWidth: Int, reqHeight: Int) { + this.reqWidth = reqWidth + this.reqHeight = reqHeight - private fun parsResourceByMovie() { try { - parserImages(movieItem!!) + if (mJsonMovie != null) { + parserImages(mJsonMovie!!) + resetSprites(mJsonMovie!!) + } else if (movieItem != null) { + parserImages(movieItem!!) + resetSprites(movieItem!!) + } } catch (e: Exception) { e.printStackTrace() } catch (e: OutOfMemoryError) { e.printStackTrace() } - resetSprites(movieItem!!) - } - - internal fun prepare(callback: () -> Unit) { - if (movieItem == null) { - callback() - } else { - setupAudios(movieItem!!) { - callback() - } - } } private fun parserImages(json: JSONObject) { @@ -144,7 +133,7 @@ class SVGAVideoEntity { } private fun createBitmap(filePath: String): Bitmap? { - return SVGABitmapDecoder.decodeBitmapFromFile(filePath, reqWidth, reqHeight) + return SVGABitmapFileDecoder.decodeBitmapFrom(filePath, reqWidth, reqHeight) } private fun parserImages(obj: MovieEntity) { @@ -165,7 +154,7 @@ class SVGAVideoEntity { } private fun createBitmap(byteArray: ByteArray, filePath: String): Bitmap? { - val bitmap = SVGABitmapDecoder.decodeBitmapFromByteArray(byteArray, reqWidth, reqHeight) + val bitmap = SVGABitmapByteArrayDecoder.decodeBitmapFrom(byteArray, reqWidth, reqHeight) return bitmap ?: createBitmap(filePath) } diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapByteArrayDecoder.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapByteArrayDecoder.kt new file mode 100644 index 00000000..0c1dba64 --- /dev/null +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapByteArrayDecoder.kt @@ -0,0 +1,16 @@ +package com.opensource.svgaplayer.bitmap + +import android.graphics.Bitmap +import android.graphics.BitmapFactory + +/** + * 通过字节码解码 Bitmap + * + * Create by im_dsd 2020/7/7 17:50 + */ +internal object SVGABitmapByteArrayDecoder : SVGABitmapDecoder() { + + override fun onDecode(data: ByteArray, ops: BitmapFactory.Options): Bitmap? { + return BitmapFactory.decodeByteArray(data, 0, data.count(), ops) + } +} \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt new file mode 100644 index 00000000..18184f5a --- /dev/null +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt @@ -0,0 +1,36 @@ +package com.opensource.svgaplayer.bitmap + +import android.graphics.Bitmap +import android.graphics.BitmapFactory +import com.opensource.svgaplayer.utils.BitmapUtils + +/** + * Bitmap 解码器 + * + * 需要加载的数据类型 + * + * Create by im_dsd 2020/7/7 17:39 + */ +internal abstract class SVGABitmapDecoder { + + fun decodeBitmapFrom(data: T, reqWidth: Int, reqHeight: Int): Bitmap? { + return BitmapFactory.Options().run { + // 如果期望的宽高是合法的, 则开启检测尺寸模式 + inJustDecodeBounds = (reqWidth > 0 && reqHeight > 0) + inPreferredConfig = Bitmap.Config.RGB_565 + + val bitmap = onDecode(data, this) + if (!inJustDecodeBounds) { + return bitmap + } + + // Calculate inSampleSize + inSampleSize = BitmapUtils.calculateInSampleSize(this, reqWidth, reqHeight) + // Decode bitmap with inSampleSize set + inJustDecodeBounds = false + onDecode(data, this) + } + } + + abstract fun onDecode(data: T, ops: BitmapFactory.Options): Bitmap? +} \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapFileDecoder.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapFileDecoder.kt new file mode 100644 index 00000000..edca5bcd --- /dev/null +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapFileDecoder.kt @@ -0,0 +1,16 @@ +package com.opensource.svgaplayer.bitmap + +import android.graphics.Bitmap +import android.graphics.BitmapFactory + +/** + * 通过文件解码 Bitmap + * + * Create by im_dsd 2020/7/7 17:50 + */ +internal object SVGABitmapFileDecoder : SVGABitmapDecoder() { + + override fun onDecode(data: String, ops: BitmapFactory.Options): Bitmap? { + return BitmapFactory.decodeFile(data, ops) + } +} \ No newline at end of file diff --git a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt b/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt new file mode 100644 index 00000000..0825785b --- /dev/null +++ b/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt @@ -0,0 +1,32 @@ +package com.opensource.svgaplayer.utils + +import android.graphics.BitmapFactory + +/** + * + * Create by im_dsd 2020/7/7 17:59 + */ +internal object BitmapUtils { + + fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { + // Raw height and width of image + val (height: Int, width: Int) = options.run { outHeight to outWidth } + var inSampleSize = 1 + if (reqHeight <= 0 || reqWidth <= 0) { + return inSampleSize + } + if (height > reqHeight || width > reqWidth) { + + val halfHeight: Int = height / 2 + val halfWidth: Int = width / 2 + + // Calculate the largest inSampleSize value that is a power of 2 and keeps both + // height and width larger than the requested height and width. + while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) { + inSampleSize *= 2 + } + } + + return inSampleSize + } +} \ No newline at end of file From ce2c51b1c6843721538d61df90715c95b9796284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Tue, 7 Jul 2020 18:18:58 +0800 Subject: [PATCH 27/33] =?UTF-8?q?=E5=BC=82=E6=AD=A5=20decodeFromAssets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/opensource/svgaplayer/SVGAImageView.kt | 2 +- .../main/java/com/opensource/svgaplayer/SVGAParser.kt | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index 26913bfb..36b61754 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -190,7 +190,7 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr // 清除对 drawable 的引用 setImageDrawable(null) } - + fun pauseAnimation() { stopAnimation(false) callback?.onPause() diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt index 90f062ae..ee26a378 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt @@ -12,7 +12,6 @@ import java.net.HttpURLConnection import java.net.URL import java.security.MessageDigest import java.util.concurrent.Executors -import java.util.concurrent.ThreadFactory import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.atomic.AtomicInteger import java.util.zip.Inflater @@ -110,11 +109,12 @@ class SVGAParser(context: Context?) { Log.e("SVGAParser", "在配置 SVGAParser context 前, 无法解析 SVGA 文件。") } try { - mContextRef.get()?.assets?.open(name)?.let { - this.decodeFromInputStream(it, buildCacheKey("file:///assets/$name"), callback, true) + threadPoolExecutor.execute { + mContextRef.get()?.assets?.open(name)?.let { + this.decodeFromInputStream(it, buildCacheKey("file:///assets/$name"), callback, true) + } } - } - catch (e: java.lang.Exception) { + } catch (e: java.lang.Exception) { this.invokeErrorCallback(e, callback) } } From 5d2f3e4166d52ff6409237f035d2423147b6f4d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Tue, 7 Jul 2020 21:28:09 +0800 Subject: [PATCH 28/33] review code --- library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt index ee26a378..2d07d9b3 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt @@ -86,8 +86,8 @@ class SVGAParser(context: Context?) { companion object { private val threadNum = AtomicInteger(0) - internal var threadPoolExecutor = Executors.newCachedThreadPool { runable -> - Thread("SVGAParser-Thread-${threadNum.getAndIncrement()}") + internal var threadPoolExecutor = Executors.newCachedThreadPool { r -> + Thread(r, "SVGAParser-Thread-${threadNum.getAndIncrement()}") } fun setThreadPoolExecutor(executor: ThreadPoolExecutor) { From 852d21547a968941a5d6544915990aa3a518c906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Wed, 8 Jul 2020 17:30:11 +0800 Subject: [PATCH 29/33] =?UTF-8?q?=E5=9C=A8=E8=A7=A3=E6=9E=90=E7=9A=84?= =?UTF-8?q?=E6=97=B6=E5=80=99=E8=AE=BE=E7=BD=AE=E6=AF=8F=E5=B8=A7=E7=9A=84?= =?UTF-8?q?=20size?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AnimationFromAssetsActivity.java | 7 ++- .../AnimationFromNetworkActivity.java | 9 ++- .../opensource/svgaplayer/SVGAImageView.kt | 1 - .../com/opensource/svgaplayer/SVGAParser.kt | 24 +++++-- .../opensource/svgaplayer/SVGAVideoEntity.kt | 62 +++++++++++-------- .../svgaplayer/bitmap/SVGABitmapDecoder.kt | 2 + .../svgaplayer/utils/BitmapUtils.kt | 3 + 7 files changed, 71 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java index cdd1e6a9..bb1864db 100644 --- a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java +++ b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java @@ -4,6 +4,7 @@ import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; +import android.util.Log; import android.view.View; import com.opensource.svgaplayer.SVGAImageView; @@ -35,7 +36,11 @@ public void onClick(View view) { } private void loadAnimation() { - SVGAParser.Companion.shareParser().decodeFromAssets(this.randomSample(), new SVGAParser.ParseCompletion() { + SVGAParser svgaParser = SVGAParser.Companion.shareParser(); + svgaParser.setFrameSize(100,100); + String name = this.randomSample(); + Log.d("SVGA", "## name " + name); + svgaParser.decodeFromAssets(name, new SVGAParser.ParseCompletion() { @Override public void onComplete(@NotNull SVGAVideoEntity videoItem) { animationView.setVideoItem(videoItem); diff --git a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromNetworkActivity.java b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromNetworkActivity.java index a27735f3..645c03c7 100644 --- a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromNetworkActivity.java +++ b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromNetworkActivity.java @@ -4,6 +4,8 @@ import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; +import android.util.Log; +import android.view.ViewGroup; import com.opensource.svgaplayer.SVGAImageView; import com.opensource.svgaplayer.SVGAParser; @@ -23,15 +25,18 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); animationView = new SVGAImageView(this); animationView.setBackgroundColor(Color.GRAY); - loadAnimation(); setContentView(animationView); + loadAnimation(); } private void loadAnimation() { try { // new URL needs try catch. - SVGAParser.Companion.shareParser().decodeFromURL(new URL("https://github.com/yyued/SVGA-Samples/blob/master/posche.svga?raw=true"), new SVGAParser.ParseCompletion() { + SVGAParser svgaParser = SVGAParser.Companion.shareParser(); + svgaParser.setFrameSize(100,100); + svgaParser.decodeFromURL(new URL("https://github.com/yyued/SVGA-Samples/blob/master/posche.svga?raw=true"), new SVGAParser.ParseCompletion() { @Override public void onComplete(@NotNull SVGAVideoEntity videoItem) { + Log.d("##","## FromNetworkActivity load onComplete"); animationView.setVideoItem(videoItem); animationView.startAnimation(); } diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt index 36b61754..4c1913f4 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAImageView.kt @@ -134,7 +134,6 @@ open class SVGAImageView @JvmOverloads constructor(context: Context, attrs: Attr val drawable = getSVGADrawable() ?: return drawable.cleared = false drawable.scaleType = scaleType - drawable.videoItem.parserResourceWithViewSize(width, height) } private fun getSVGADrawable(): SVGADrawable? { diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt index ee26a378..affb133c 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAParser.kt @@ -26,6 +26,12 @@ private var fileLock: Int = 0 class SVGAParser(context: Context?) { private var mContextRef = WeakReference(context) + @Volatile + private var mFrameWidth: Int = 0 + + @Volatile + private var mFrameHeight: Int = 0 + interface ParseCompletion { fun onComplete(videoItem: SVGAVideoEntity) fun onError() @@ -86,15 +92,16 @@ class SVGAParser(context: Context?) { companion object { private val threadNum = AtomicInteger(0) - internal var threadPoolExecutor = Executors.newCachedThreadPool { runable -> - Thread("SVGAParser-Thread-${threadNum.getAndIncrement()}") + private var mShareParser = SVGAParser(null) + + internal var threadPoolExecutor = Executors.newCachedThreadPool { r -> + Thread(r, "SVGAParser-Thread-${threadNum.getAndIncrement()}") } fun setThreadPoolExecutor(executor: ThreadPoolExecutor) { threadPoolExecutor = executor } - private var mShareParser = SVGAParser(null) fun shareParser(): SVGAParser { return mShareParser } @@ -104,6 +111,11 @@ class SVGAParser(context: Context?) { mContextRef = WeakReference(context) } + fun setFrameSize(frameWidth: Int, frameHeight: Int) { + mFrameWidth = frameWidth + mFrameHeight = frameHeight + } + fun decodeFromAssets(name: String, callback: ParseCompletion?) { if (mContextRef.get() == null) { Log.e("SVGAParser", "在配置 SVGAParser context 前, 无法解析 SVGA 文件。") @@ -149,7 +161,7 @@ class SVGAParser(context: Context?) { } else { inflate(bytes)?.let { - val videoItem = SVGAVideoEntity(MovieEntity.ADAPTER.decode(it), File(cacheKey)) + val videoItem = SVGAVideoEntity(MovieEntity.ADAPTER.decode(it), File(cacheKey), mFrameWidth, mFrameHeight) videoItem.prepare { this.invokeCompleteCallback(videoItem, callback) } @@ -222,7 +234,7 @@ class SVGAParser(context: Context?) { File(cacheDir, "movie.binary").takeIf { it.isFile }?.let { binaryFile -> try { FileInputStream(binaryFile).use { - this.invokeCompleteCallback(SVGAVideoEntity(MovieEntity.ADAPTER.decode(it), cacheDir), callback) + this.invokeCompleteCallback(SVGAVideoEntity(MovieEntity.ADAPTER.decode(it), cacheDir, mFrameWidth, mFrameHeight), callback) } } catch (e: Exception) { cacheDir.delete() @@ -244,7 +256,7 @@ class SVGAParser(context: Context?) { } byteArrayOutputStream.toString().let { JSONObject(it).let { - this.invokeCompleteCallback(SVGAVideoEntity(it, cacheDir), callback) + this.invokeCompleteCallback(SVGAVideoEntity(it, cacheDir, mFrameWidth, mFrameHeight), callback) } } } diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index b05f875f..ea9cb83a 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -36,19 +36,30 @@ class SVGAVideoEntity { var frames: Int = 0 private set - private var reqHeight = 0 - private var reqWidth = 0 internal var spriteList: List = emptyList() internal var audioList: List = emptyList() internal var soundPool: SoundPool? = null internal var imageMap = HashMap() private var mCacheDir: File - private var mJsonMovie: JSONObject? = null + private var mFrameHeight = 0 + private var mFrameWidth = 0 - constructor(json: JSONObject, cacheDir: File) { - mJsonMovie = json + constructor(json: JSONObject, cacheDir: File) : this(json, cacheDir, 0, 0) + + constructor(json: JSONObject, cacheDir: File, frameWidth: Int, frameHeight: Int) { + mFrameWidth = frameWidth + mFrameHeight = frameHeight mCacheDir = cacheDir - json.optJSONObject("movie")?.let(this::setupByJson) + val movieObject = json.optJSONObject("movie") ?: return + setupByJson(movieObject) + try { + parserImages(movieObject) + } catch (e: Exception) { + e.printStackTrace() + } catch (e: OutOfMemoryError) { + e.printStackTrace() + } + resetSprites(movieObject) } private fun setupByJson(movieObject: JSONObject) { @@ -61,10 +72,21 @@ class SVGAVideoEntity { frames = movieObject.optInt("frames", 0) } - internal constructor(entity: MovieEntity, cacheDir: File) { - this.movieItem = entity + constructor(entity: MovieEntity, cacheDir: File) : this(entity, cacheDir, 0, 0) + + constructor(entity: MovieEntity, cacheDir: File, frameWidth: Int, frameHeight: Int) { + this.mFrameWidth = frameWidth + this.mFrameHeight = frameHeight this.mCacheDir = cacheDir - entity.params?.let (this::setupByMovie) + entity.params?.let(this::setupByMovie) + try { + parserImages(entity) + } catch (e: Exception) { + e.printStackTrace() + } catch (e: OutOfMemoryError) { + e.printStackTrace() + } + resetSprites(entity) } private fun setupByMovie(movieParams: MovieParams) { @@ -86,22 +108,8 @@ class SVGAVideoEntity { } internal fun parserResourceWithViewSize(reqWidth: Int, reqHeight: Int) { - this.reqWidth = reqWidth - this.reqHeight = reqHeight - - try { - if (mJsonMovie != null) { - parserImages(mJsonMovie!!) - resetSprites(mJsonMovie!!) - } else if (movieItem != null) { - parserImages(movieItem!!) - resetSprites(movieItem!!) - } - } catch (e: Exception) { - e.printStackTrace() - } catch (e: OutOfMemoryError) { - e.printStackTrace() - } + this.mFrameWidth = reqWidth + this.mFrameHeight = reqHeight } private fun parserImages(json: JSONObject) { @@ -133,7 +141,7 @@ class SVGAVideoEntity { } private fun createBitmap(filePath: String): Bitmap? { - return SVGABitmapFileDecoder.decodeBitmapFrom(filePath, reqWidth, reqHeight) + return SVGABitmapFileDecoder.decodeBitmapFrom(filePath, mFrameWidth, mFrameHeight) } private fun parserImages(obj: MovieEntity) { @@ -154,7 +162,7 @@ class SVGAVideoEntity { } private fun createBitmap(byteArray: ByteArray, filePath: String): Bitmap? { - val bitmap = SVGABitmapByteArrayDecoder.decodeBitmapFrom(byteArray, reqWidth, reqHeight) + val bitmap = SVGABitmapByteArrayDecoder.decodeBitmapFrom(byteArray, mFrameWidth, mFrameHeight) return bitmap ?: createBitmap(filePath) } diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt index 18184f5a..f459d20e 100644 --- a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt @@ -2,6 +2,7 @@ package com.opensource.svgaplayer.bitmap import android.graphics.Bitmap import android.graphics.BitmapFactory +import android.util.Log import com.opensource.svgaplayer.utils.BitmapUtils /** @@ -26,6 +27,7 @@ internal abstract class SVGABitmapDecoder { // Calculate inSampleSize inSampleSize = BitmapUtils.calculateInSampleSize(this, reqWidth, reqHeight) + Log.d("##SVGA","## SVGABitmapDecoder inSampleSize $inSampleSize") // Decode bitmap with inSampleSize set inJustDecodeBounds = false onDecode(data, this) diff --git a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt b/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt index 0825785b..f888f3d7 100644 --- a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt +++ b/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt @@ -1,6 +1,7 @@ package com.opensource.svgaplayer.utils import android.graphics.BitmapFactory +import android.util.Log /** * @@ -12,6 +13,8 @@ internal object BitmapUtils { // Raw height and width of image val (height: Int, width: Int) = options.run { outHeight to outWidth } var inSampleSize = 1 + Log.d("##SVGA","## calculateInSampleSize $reqWidth $reqHeight $width $height") + if (reqHeight <= 0 || reqWidth <= 0) { return inSampleSize } From 294a60b48d99af3d94fbd2b2923c3283e6a423db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Wed, 8 Jul 2020 18:57:06 +0800 Subject: [PATCH 30/33] review code --- .../src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index ea9cb83a..c52a2a60 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -78,6 +78,7 @@ class SVGAVideoEntity { this.mFrameWidth = frameWidth this.mFrameHeight = frameHeight this.mCacheDir = cacheDir + this.movieItem = entity entity.params?.let(this::setupByMovie) try { parserImages(entity) From db9ddf25b627782b1df0faa5fd4046d34591eea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Wed, 8 Jul 2020 19:59:21 +0800 Subject: [PATCH 31/33] test --- .../svgaplayer/AnimationFromAssetsActivity.java | 2 +- .../java/com/opensource/svgaplayer/SVGAVideoEntity.kt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java index bb1864db..5004228f 100644 --- a/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java +++ b/app/src/main/java/com/example/ponycui_home/svgaplayer/AnimationFromAssetsActivity.java @@ -37,9 +37,9 @@ public void onClick(View view) { private void loadAnimation() { SVGAParser svgaParser = SVGAParser.Companion.shareParser(); - svgaParser.setFrameSize(100,100); String name = this.randomSample(); Log.d("SVGA", "## name " + name); + svgaParser.setFrameSize(100, 100); svgaParser.decodeFromAssets(name, new SVGAParser.ParseCompletion() { @Override public void onComplete(@NotNull SVGAVideoEntity videoItem) { diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index c52a2a60..13ed15f0 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -50,16 +50,16 @@ class SVGAVideoEntity { mFrameWidth = frameWidth mFrameHeight = frameHeight mCacheDir = cacheDir - val movieObject = json.optJSONObject("movie") ?: return - setupByJson(movieObject) + val movieJsonObject = json.optJSONObject("movie") ?: return + setupByJson(movieJsonObject) try { - parserImages(movieObject) + parserImages(json) } catch (e: Exception) { e.printStackTrace() } catch (e: OutOfMemoryError) { e.printStackTrace() } - resetSprites(movieObject) + resetSprites(json) } private fun setupByJson(movieObject: JSONObject) { From 977144525e921ead4d80f29731b7d3db5f8e0887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Wed, 8 Jul 2020 21:39:20 +0800 Subject: [PATCH 32/33] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt index 13ed15f0..4e9e16f4 100644 --- a/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt +++ b/library/src/main/java/com/opensource/svgaplayer/SVGAVideoEntity.kt @@ -108,11 +108,6 @@ class SVGAVideoEntity { } } - internal fun parserResourceWithViewSize(reqWidth: Int, reqHeight: Int) { - this.mFrameWidth = reqWidth - this.mFrameHeight = reqHeight - } - private fun parserImages(json: JSONObject) { val imgJson = json.optJSONObject("images") ?: return imgJson.keys().forEach { imgKey -> From 2d7dd24858676974acf0a6b8d7d65dd63966d9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A3=E5=9C=A3=E8=BE=BE?= Date: Wed, 8 Jul 2020 20:04:13 +0800 Subject: [PATCH 33/33] review code --- .../BitmapSampleSizeCalculator.kt} | 8 +++----- .../com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt | 5 +---- 2 files changed, 4 insertions(+), 9 deletions(-) rename library/src/main/java/com/opensource/svgaplayer/{utils/BitmapUtils.kt => bitmap/BitmapSampleSizeCalculator.kt} (74%) diff --git a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapSampleSizeCalculator.kt similarity index 74% rename from library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt rename to library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapSampleSizeCalculator.kt index f888f3d7..e1ea015e 100644 --- a/library/src/main/java/com/opensource/svgaplayer/utils/BitmapUtils.kt +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/BitmapSampleSizeCalculator.kt @@ -1,19 +1,17 @@ -package com.opensource.svgaplayer.utils +package com.opensource.svgaplayer.bitmap import android.graphics.BitmapFactory -import android.util.Log /** * * Create by im_dsd 2020/7/7 17:59 */ -internal object BitmapUtils { +internal object BitmapSampleSizeCalculator { - fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { + fun calculate(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { // Raw height and width of image val (height: Int, width: Int) = options.run { outHeight to outWidth } var inSampleSize = 1 - Log.d("##SVGA","## calculateInSampleSize $reqWidth $reqHeight $width $height") if (reqHeight <= 0 || reqWidth <= 0) { return inSampleSize diff --git a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt index f459d20e..8816fbb0 100644 --- a/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt +++ b/library/src/main/java/com/opensource/svgaplayer/bitmap/SVGABitmapDecoder.kt @@ -2,8 +2,6 @@ package com.opensource.svgaplayer.bitmap import android.graphics.Bitmap import android.graphics.BitmapFactory -import android.util.Log -import com.opensource.svgaplayer.utils.BitmapUtils /** * Bitmap 解码器 @@ -26,8 +24,7 @@ internal abstract class SVGABitmapDecoder { } // Calculate inSampleSize - inSampleSize = BitmapUtils.calculateInSampleSize(this, reqWidth, reqHeight) - Log.d("##SVGA","## SVGABitmapDecoder inSampleSize $inSampleSize") + inSampleSize = BitmapSampleSizeCalculator.calculate(this, reqWidth, reqHeight) // Decode bitmap with inSampleSize set inJustDecodeBounds = false onDecode(data, this)