android-gif-drawable使用之有坑未填
至于为什么使用 android-gif-drawable
1 ,性能更高比其它开源控件或Glide,
2 ,提供gif播放完成后的监听和重置功能
android studio开发完后,一切正常运行,代码如下:
//显示gif
private fun showCombo() {
mGif = GifDrawable(resources,R.drawable.gift_combo)
mGif?.loopCount==1
mGif?.addAnimationListener(object : AnimationListener {
override fun onAnimationCompleted(loopNumber: Int) {
mGiftCombo.visibility = View.GONE
mLiveIdGroup2.visibility = View.VISIBLE
mHeartLayout.visibility = View.VISIBLE
mLiveGiftBtn.visibility = View.VISIBLE
mLiveLike.visibility = View.VISIBLE
}
})
if(mGiftCombo.visibility!=View.VISIBLE){
mGiftCombo.visibility = View.VISIBLE
mGiftCombo.setImageDrawable(mGif)
}
}
//连击重置事件
mGif?.reset()
但通过jenkins 打后,出现问题,连击的view 显示不出现。
出现该问题后,首先想到的是混淆问题,查看 github readme文件后,新增如下图所示配置,打包后还是不行,
gif2.png还有什么环境因素会影响到? 之前听说过android-gif-drawable 是由C/C++来完成的,由于查看远程引用的包中没有相应的so文件 ,所以从github中找到之前的 android-gif-drawable-1.2.15.aar 包下载 ,本地直接引用arr ,但经过jenkin打包后还是不行, 解压apk查看so库确实也在arm64-v8a架构下的 libpl_droidsonroids_gif.so 的存在 如下图:
gif5.png是不是自己的手机不支持该cpu架构呢?按如下教程查看
如何查看Android手机CPU类型是armeabi,armeabi-v7a,还是arm64-v8a
手机开启USB调试后,连上电脑,在Terminal中输入命令:
adb shell getprop ro.product.cpu.abi
显示cpu 架构为 arm64-v8a ,,,也不是该问题造成的,
目前的方法只能去掉混淆配置,然后由Jenkins打包后 一步一步跟断点,看看是那里报的异常了,
通过该方法最终定位到如下该行代码:
gif6.png
报错信息为:
This file can not be opened as a file descriptor; it is probably compressed
网上查到的信息测试后无果
This file can not be opened as a file descriptor; it is probably compressed
Android中有个很恶心的潜规则,就是当assets或是raw目录下单个压缩文件大小超过1024K之后,编译期appt会去强行处理此文件,使得我们运行期读取的时候会收到一个
This file can not be opened as a file descriptor; it is probably compressed
要解决这个问题可以将文件扩展名改为mp3或是wma这类的就OK了
gif7.png
从图中可以看到我们gif 图为 240k ,并没有超过1024K,
如下文章也未能解决该问题:
AssetManager.openFd(String fileName)读取assets下文件报错解决方案
FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed
由于本期预约茅台项目需求上线急
该方案暂无解(具体和LInux上android studio的环境配置有关,可能和NDK有关,但本电脑并无使用NDK配置为什么可以运行成功呢?) 只能找备选方案。
1,播放动画,我们可以使用帧动画,但该连击特效时长2种,用到的图片会比较多,该方案不太可以。
2,做直播送礼物功能的时候,用到了 SVGA 动画 ,设想我能不能让UI 把 gif转成 SVGA然后播放它呢,只要 SVGA解析, 播放的时候不是特别耗时2秒多点也可以接受。说干就干,下午 UI给了SVGA后,编码 测试通过, 每次播放的时间为 1988左右,,,,
3,考虑到产品要求 播放完整的动画时长为2秒,由于 读SVGA本质上会经过读IO流,然后解析成相应的帧,,所以我们可以把该步提前完成保存到内存中,当点击连击按钮后,直接开始播放动画。
代码如下所示:
/**
* 加载解析svga,缓存 SVGAVideoEntity,为开播动画做准备
* @param context
* @param function
* @param <T>
*/
public static <T> void obtainSvgaDoubleClickAnimator(Context context, Consumer<T> function) {
try {
String svgaName = "ic_duoble_click.svga";
SVGAParser parser = new SVGAParser(context);
parser.parse(svgaName, new SVGAParser.ParseCompletion() {
@Override
public void onComplete(SVGAVideoEntity svgaVideoEntity) {
//解析动画成功,到这里才真正的显示动画
if (function != null) {
try {
function.accept((T) svgaVideoEntity);
} catch (Exception e) {
}
}
}
@Override
public void onError() {
}
});
} catch (Exception e) {
}
}
/**
* 连击开始动画
*/
private fun startSVGAAnimation() {
mSVGAVideoEntity?.let {
if(mLiveIdGroup2.visibility != View.GONE){
mLiveIdGroup2.visibility = View.GONE
}
if(mHeartLayout.visibility != View.GONE){
mHeartLayout.visibility = View.GONE
}
if(mLiveGiftBtn.visibility != View.GONE){
mLiveGiftBtn.visibility = View.GONE
}
if(mLiveLike.visibility != View.GONE){
mLiveLike.visibility = View.GONE
}
mGiftCombo.callback = null
mGiftCombo.stopAnimation()
mGiftCombo.callback = mSVGACallback;
mGiftCombo.visibility = View.VISIBLE
mGiftCombo.loops = 1
mGiftCombo.setVideoItem(it)
mGiftCombo.startAnimation()
}
}
gift8.png
参考文章:
android-gif-drawable
安卓项目实战之Gif图片加载的最佳实践android-gif-drawable开源库的使用
关注我的github
https://github.com/fuyuguang
带你了解更多项目实践中的bug