Welcome, and well met.
Recent Posts
Webp解码RGB_565问题记录
最近遇到自定义webp解码使用rgb565时出现颜色错乱的问题,查了比较长时间,总结一下过程。
开始时怀疑代码逻辑有问题,于是写demo测试native代码逻辑,尝试修改Bitmap的一些属性,确认代码逻辑正确。
然后考虑到用系统解码api和官方ndk sample中的webp解码示例都正常,怀疑是不是对libwebp的调用方式有问题,于是去看源码。先从简单的ndk sample开始看,发现调用方式是一样的,然后看了系统webp解码部分源码,发现系统使用的解码函数不一样,尝试换成跟系统一样的函数,问题依然存在。由于官方示例并没有将图片解码成Bitmap,所以接着仔细看系统源码的解码过程,看是不是在某些细节里有特殊处理,最后没有发现有特殊的地方。
看了几天源码无果后,最后想到是不是解码得到的Bitmap的底层像素数据不一样,而不是对Bitmap的设置不一样,于是写测试代码获取Bitmap的像素字节数组,对2种方式解码得到的Bitmap的像素数据进行比较,发现同一像素的2个字节的位置刚好相反。
[74, 105, -125, -18, ...] [105, 74, -18, -125, ...] 到这里终于有点眉目了,后面就去找导致位置相反的原因,然后在libwebp源码定义像素格式的地方发现了一段注释,感觉很可能跟WEBP_SWAP_16BITS_CSP有关,但在代码中没有找到这个变量。
// ... // RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... // In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for // these two modes: // RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], .
read more
Android task
singleTask and FLAG_ACTIVITY_NEW_TASK 根据下面引用的官方文档的说法,singleTask和FLAG_ACTIVITY_NEW_TASK的行为是一致的,但是根据实际测试结果,二者的行为是有差别的。
This produces the same behavior as the “singleTask” launchMode value, discussed in the previous section.
二者在决定activity属于哪个task上是一致的,都根据taskAffinity(如果没设,默认为包名)来决定activity属于哪个task,如果当前存在一个名称跟taskAffinity相同的task,则将activity置于已有的这个task,否则创建一个新task,并将activity作为这个task的根activity。
二者在启动activity的行为上是不一致的,如果activity所属的task已存在且task中已存在这个activity的实例,二者都会将整个task移到前台,但singleTask会关闭这个activity上面的所有activity,并调用这个activity的onNewIntent方法,而对于FLAG_ACTIVITY_NEW_TASK,如果启动的activity是这个task的根activity,不做任何事情,否则会创建一个新的activity。
Exported activity 启动其他app的exported activity时,会忽略launchMode,此时只能用FLAG_ACTIVITY_NEW_TASK来创建新task。
startActivityForResult 调用startActivityForResult来启动activity时,如果使用了FLAG_ACTIVITY_NEW_TASK,启动activity后会立即收到onActivityResult回调,且finish启动的activity后不会再收到onActivityResult回调,而使用singleTask和singleInstance则是正常的行为。
read more
Android memory leak
Leak because of system bug PhoneStateListener leak Below 7.0 a non static inner class IPhoneStateListener.Stub callback in PhoneStateListener references to outside PhoneStateListener, even caller has been destroyed and “un-registered” the PhoneStateListener, the references coming from: Native Stack –> PhoneStateListener –> Context(Activity).
A wrapper class wraps a weak reference of PhoneStateListener can be used to avoid this memory leak.
Caution: The original PhoneStateListener object must be referenced by caller class, otherwise the weak reference in the wrapper class will get null.
read more