更新下飞信协议的研究

我很早很早前就抓包研究过下飞信协议,那时还比较简单,除了访问导航服务器获得通信服务器ip外,之后只用和通信服务器联系就可以了。最近在做adium的飞信插件,原来用libfetion.cn的库的,那个全包装完了,就不用自己操心了,现在我改用fetion for pidgin的开源版的库,就可以自己做些补充改进了。其实它工作得还挺好的,只是小细节问题也不断,所以我打算重新研究下飞信协议。

升级到最新的飞信官方版,3.5.2540,然后把抓包工具升级了一下。嗯,这里推荐一下这个叫科来网络分析系统的软件,是个国产工具,个人抓包用它的免费技术交流版就可以了。我感觉很好用,哈,可能只是因为全中文界面? read more

Android用NDK和整套源码下编译JNI的不同

前些天要写个jni程序,因为才几行代码,想着用ndk开发可能容易些,就先研究了下。不过最终我的代码虽然只有几行,但需要libdl,因为用到了dlopen一类的函数,只能又换到用android源码体系下编译。
不过两个都用了下,就发现了些不同。我其实并不能确定这些是不是实际存在的差异的,我只是拿ndk的sample和我见到的android源码里的jni代码做的比较
1. ndk支持的库很少,所以用以前最好先看看自己需要的功能是不是已经包括了,省得白忙活。不过人家是有解释的,说ndk里有的库才是稳定的,其它的建议你不要用。嗯,google总是这一套说辞,不公开的api也是。至于要看android源码中多了哪些库,make modules后grep一下lib开头的应该就是了,不过也不是所有都能用啦。
2. 注册函数的方法是不同的。举例说,我在com/evan129/jnitest/jniutils.java有个native int foo()方法,需要在jni中实现
在ndk中,你只要实现这个函数,然后函数名是以jint java_com_evan129_jnitest_jniutils_foo(jnienv* env, jobject thiz) 命名既可。也就是说,如果你的jni只要实现这个函数,并且功能也很简单的话,那么你的jni c/cpp文件里只需要这一个函数就完事了。
但在android源码中编译jni代码是不同的,jni中的函数名无所谓。不过你至少还需要加一个
jniexport jint jnicall jni_onload(javavm* vm, void* reserved)方法,这个方法你可以找个现有的复制一把就行,检查运行环境的。然后主要是这个方法中会调用(*env).registernatives函数,在这里把jni中的方法和java文件中的方法关联起来。
看起来像是ndk自动补上了这部分工作,我并不清楚原理啦。
3. 有个很诡异的区别,自动传入的jnienv* env好像不是一个东西。因为在android源码中使用这个env一般是如env->newstringutf(…),而ndk中sample里的一处是(*env)->newstringutf(…) 这env和*env差很大吧。但两处函数传入的都是jnienv* env,我只能怀疑jnienv的定义是不是都是不同的。

末了,就是说下我这个很简单的jni折腾了我两天的一个问题。如前所说,我是用android源码来编译的,自己在packages/app/下建了pinyinjni工程,下面有个jni目录,每次直接用mmm packages/app/pinyinjni/jni来编译。jni目录下的android.mk中指定的名字是这样的local_module := libpinyin 每次编译都很顺利,生成了libpinyin.so。但是我在java文件里,system.loadlibrary(“libpinyin”)总是失败。感谢paranoia@newsmth帮我解决了这个问题,告诉我在loadlibrary时用”pinyin”。但是,这个事情实在太奇怪了,那文件名是libpinyin.so啊,而且我在这里用/data/data/…/libpinyin.so这种完整路径也会失败,我以前虽然没写过jni,但调用过,用完整路径指定jni so文件应该不会有问题的。或者,从另一个角度想,如果我local_module的名字不是用lib开头的,那它调用时应该用什么名字?这个”lib”前缀又是哪步删除的?我没有多做测试了,但是猜想ndk中应该是没有这种诡异的问题的。

Git-svn实在是有够慢

今天中午11点开始git svn checkout三个android源码副本,本地网络,网速超好,到下午五点,正好结束

objects数分别是135246, 95115, 108101。这还ok啦,毕竟svn 历史比较多。然后7pm前开始作svn源取下来后的一些操作,git gc, unpack一类的,到现在还有两个才压缩一半,最快的一个开始writing objects。不知道一个通宵搞不搞得完这些操作。

Howto change the startup animation of Android OS

the statup animation means the one you see before the launcher application comes out.
it was a line with a red point goes from left to right again and again before, in android 1.0. currently, on cupcake, it’s a text string, “android”, with shine goes from left to right.
i found someone add an advertisement logo to that animation in a customized rom. so i studied how to remove that, or make a new one by myself.

finally, i found it out. there are 2 pictures under frameworks/base/core/res/assets/images:
android-logo-mask.png
android-logo-shine.png

the 1st one is the background. then, you can edit it with picture editor, like add your own name on it.
well, after edited it, you need to build framework-res out, with command “make framework-res”. then, you will get a new framework-res.apk. but usually, you can not use this file to replace the one in the rom/firmware for real devices, like g1, g2. since, some resources are not under the same version.
what i do is pull out the original framework-res.apk from the rom. unzip both this framework-res.apk and the one i made by myself. replace the 2 pictures under assests/images with the one i made before. notice, you can not replace the files with the png files you edited, but not compiled.
then zip out framework-res.apk again, and sign with signapk tool. now you can use the new framework-res.apk to replace the original one.

糟糕的G1性能。。

今天工作需要,对g1上的数据操作做benchmark,真恐怖啊。删两千条短信要15分钟,zeze..
read more

试用git-svn

首先介绍下mac os x上用macports怎么安装git-svn,网上很多文章都说git在1.5.3版本后自带git-svn了,但我运行git svn提示是没有这个命令的。我的git是因为原来要下载android源码时,按google的说明,用sudo port install git-core安装的。
网上搜了半天,才知道结果,还有人自己编译的,依赖比较多,我觉得太麻烦了。简单来说,如果原来已经像上面说的已经装了git-core的话,需要先sudo port uninstall git-core。安装的话,是用sudo port install git-core +svn这个命令,就会在编译时带上+svn参数了

入门介绍的文章还是比较多的,比如 http://www.robinlu.com/blog/archives/194
在第一步git svn clone时确实比较花时间。看输出的log,似乎是首先取svn上最早的一个版本下来,然后不停的取下一个新版本的更新的部分。所以时间确实比较久,导出我们公司svn的trunk用了两个钟头才完。不过导出后,所有的svn log在本地都有记录了。目录并没有大多少。网上文章一般说在导出后需要做一次git gc。但是我目前用的这个版本git version 1.6.2.1,似乎已经会在git svn clone完后自动做一次git gc了。

刚刚开始使用,才第一次用它提交了个代码。再有心得时再补充吧

写了个Adium的飞信插件

下载页面请看这里 http://www.evan129.com/mywork/fetion-plugin-for-adium/

周末花了一天半写的。以前虽然看过点cocoa入门的文章,但从来没有试过,没有一个想做的东西,就不是很有热情投入去学习。因为我很早就研究过飞信的协议,曾经还做过一个java版的,所以本来想自己实现协议部分的。但完成了登录部分后,就发觉实在太麻烦了,一门不熟悉的语言,要处理字符串和线程一类的很让人头疼。于是就用了libfetion的库啦。这库用起来还是挺方便的,可惜出来都快一整年了,功能还是很少,比如没有读好友头像,传文件一类的。

打算接下来写篇关于adium插件开发的文章。嗯

Android中要小心的一种内存泄露

今天把android-developers blog上的一些文章看了下,有篇文章《avoiding memory leaks》虽然以前也扫了眼,今天再看了一遍,觉得好bt啊。

private static Drawable sBackground;
 
@Override
protected void onCreate(Bundle state) {
  super.onCreate(state);
 
  TextView label = new TextView(this);
  label.setText("Leaks are bad");
 
  if (sBackground == null) {
    sBackground = getDrawable(R.drawable.large_bitmap);
  }
  label.setBackgroundDrawable(sBackground);
 
  setContentView(label);
}

这段代码看得出会内存泄露么?按文中解释说,因为setbackgrounddrawable时,会在drawable中把label这个textview设为callback,就是说drawable中对label有引用,而label中对当前activity的context也有引用。所以当转屏时,系统自动重新建立ui时,原有的整个activity都不能被回收。

作为一个普通的java程序员,真的能想到这个么?文档里也没有提示过,没看到这篇文章,又没自己去看drawable的源代码的开发者,怎么能猜到这个。至少在我第一印象中,我是觉得drawable对象只是类似于image的一类对象。系统竟然在我不注意的时候自动设置了callback。唉,我得检查检查自己的代码中有没有这样的问题了。我不知道除了这个drawable外,还有没有其它类似的东西,真是防不胜防啊

03-15增: 不过我想了下,好像也有点不对啊
当第二次重设label.setbackgrounddrawable(sbackground);时,应该是把sbackground的
callback改回成当前的label啦。那这时gc不就应该能工作么

Android platform study tips

belows are some tips for getting/building/patching android source code.

1. getting source
i’m not sure if you could download source code fast, if yes, skip this. but it took me more than 10 hours to finish getting the source code. the main git server limits to 3 connections from 1 ip address, so you can repo sync 3 projects together. for me, i start “repo sync”, “repo sync kernel” and “repo sync prebuilt” together, for the kernel and prebuilt projects are larger, and they could finish before repo sync touch them. well, you can also start “repo sync external/webkit” first, for it’s not from the git server.

2. building source

added on 11-03, 2008. today i installed a clean ubuntu linux 8.10, and did these steps to prepare the installation
$ sudo apt-get install git-core gnupg
$ sudo apt-get install flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl
$ sudo apt-get install zlib1g-dev
$ sudo apt-get install valgrind
(this step is optional, its size is about 22m)
$ sudo apt-get install python2.5
$ sudo apt-get install sun-java5-jdk
warning: do not use sun-java6-jdk,or you will meet below error when you do “make sdk”
docs droiddoc: out/target/common/docs/dx
javadoc: error – in doclet class droiddoc, method start has thrown an
exception java.lang.reflect.invocationtargetexception
com.sun.tools.javac.code.symbol$completionfailure: class file for
sun.util.resources.openlistresourcebundle not found

in the document, it says run “make” in the root path of the android code. the result of “make” is generating system.img. for getting the whole runnable sdk, you can run “make sdk”. the sdk will be putted in out/host/your_os/sdk/. by the way, it’s said “make -j2″ may make it faster.
you can enable ccache with
export use_ccache=1
pls also set a cache dir with “export ccache_dir=your_cache_dir”

after once make the whole projects, if you modify some code, you do not need to re-compile the whole projects with “make”. run
$. build/envsetup.sh
in the android source code dir. and you can use “mmm” command to compile a project. like “mmm packages/apps/contacts”. well, if you change some code like frameworks/base/core/java/android/widget/listview.java, you need to run “mmm frameworks/base”, for only frameworks/base is a project, others are only part of this project. there would be a file named “android.mk” under the root of a project.

today, i tried to fix some bug in contacts application. for testing the changes, if you run “make && make sdk” again, it would take a long time. you can easily do as i did:
1. modify code
2. $mmm packages/apps/contacts
if there’re compiling errors, go back to 1
3. make snod
with this command, it will build a new system.img very quickly.
4. $cp out/target/product/generic/system.img out/host/your_os/sdk/your_sdk_path/tools/lib/images/
5. $out/host/your_os/sdk/your_sdk_path/tools/emulator -wipe-data

it took about 2 minutes for me on my macbook pro with 2ghz cpu.
well, you cannot use “make snod” for all the situations. it would not check the dependences. if you change some code in the framework which will effect other applications, please use a clean make.

3. project layout
most of the classes you see in the android sdk reference are in frameworks/base/core/java
and the resources like android.r.layout.simple_list_item_1 is defined in frameworks/base/core/res/res/layout

build in applications are in packages/apps

to be continued..

Android源码研究Tips

从去年12月开始写android程序开始,都差不多快一年了。上月google终于公开了android的较完整的源码。最近几天,闲来无事时就给他们提交一些补丁。

这里讲一些开发中的技巧,或许对大家有帮助,转载请注明出处:
下载源码
首先一个问题是http://source.android.com/在国内访问有时,甚至是大多时候,是有问题的。那么怎么翻墙就需要大家自己解决了。其实只是为了看源码的话,问题并不大,源码更新的站点还是可以正常连接的,但是如果有打算要提交patch,那么用tor都有些麻烦,我是找了个vpn出去的。获取源码请参照

http://source.android.com/download

嗯,我这里也可以给一些简单的步骤介绍吧:
1. 你的系统需要是linux或者是mac os x。需要先安装git-core和gnupg,在debian/ubuntu linux上,可以用apt-get获取,mac上使用macports吧。额外的,在mac上你需要先安装xcode 2.4以上版本,另外再用macports安装gmake, libsdl。 事实上编译期还会有问题,这在http://source.android.com/download页文档中没有提及,缺失ncursor和zlib库,也需要单独安装(这个在mail list里有讨论,或许我晚些可以补全些)。

2008-11-03 补 正好干净安装了ubuntu linux 8.10记录一下需要的东西
注意可能blog中会自动折行,请以$来区分新行
$ sudo apt-get install git-core gnupg (gnupg实际已自带)
$ sudo apt-get install flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl
$ sudo apt-get install zlib1g-dev
$ sudo apt-get install valgrind (可选,有21m大,我觉得一般人是用不到的)
$ sudo apt-get install python2.5 (实际上不用装,ubuntu 8.10已经自带)
$ sudo apt-get install sun-java5-jdk
注意,不要用 sun-java6-jdk, 不然在make sdk,具体来说是make doc这一步中,遇到这个错误:
docs droiddoc: out/target/common/docs/dx
javadoc: error – in doclet class droiddoc, method start has thrown an
exception java.lang.reflect.invocationtargetexception
com.sun.tools.javac.code.symbol$completionfailure: class file for
sun.util.resources.openlistresourcebundle not found

2. 下载repo脚本,放到/bin目录下,加上可执行权限
$ curl http://android.git.kernel.org/repo > repo
$ sudo mv repo /bin
$ sudo chmod a+x /bin/repo
其实文档中是把这个放在个人用户的~/bin目录下,但是要改path,我嫌麻烦而已就放/bin下了

3. 创建一个放置源码的文件夹,如叫myandroid。这里要注意下,需要区分大小写的分区,linux下一般是用ext3的,是符合要求的,而mac下默认的分区是不区分大小写的,请自行创建分区。但是事实上,我以前测试过,在非大小写敏感分区上,直接make会报错,但修改makefile后直接跳过检查这一步,最终是可以成功编译的。

4. 在myandroid目录中执行
$ repo init -u git://android.git.kernel.org/platform/manifest.git
中间会提示输入电子邮件什么的,如果你打算要提交patch的话,用google accounts注册过的邮箱

5. 在myandroid中执行 repo sync就可以开始下载源码了
但是这一步非常慢,这里有些文档中没有的技巧了:
测试发现,主站点是限三线程连接的,也就是说你可以同时开三个窗口做不同部分下载,
我建议是第一个窗口直接执行repo sync,第二个窗口执行repo sync kernel,第三个窗口执行repo sync prebuilt
因为kernel和prebuilt这两个工程比较大。
有时因为多次频繁连接,会有服务器端拒绝连接的错误,此时等两三分钟再重试就好了
repo的使用请看repo help。如果只是要学习源码的话,那只用repo sync一个命令就行。repo sync不带参数的话会更新所有子项目,可以repo sync project_path来指定更新项目。 那么project_path在哪可以找到呢?myandroid/.repo/manifests/default.xml (你至少需要先repo init过才有这些东西)

编译源码
当repo sync全部完毕时,进入myandroid目录,首先执行make,大约会耗时一个小时左右(在我的一代macbook pro上大概是这时间)。make最后会生成system.img。看到mail list里有人问这个干嘛用,其实是文档里没有完全写清楚。一般来说,我想普通人还需要的是make sdk这一步,会在myandroid/out/host/your_os/sdk中生成sdk。和从google官方下载下来的sdk差不多,可以直接运行了

在进行过一次完整的make后,以后对一些程序的修改,大可不必重新make sdk,因为make sdk实在太慢了。
先在myandroid目录下执行
$ . build/envsetup.sh
然后你就会多出几个可用的命令。在改了contacts项目后,可以简单的执行mmm packages/apps/contacts/来单独编译这个部分。为了可以直接测试改动,需要生成新的system.img,在myandroid目录下执行
make snod即可
当然,如果你改动的是emulator或者其它外围相关的,而非系统内部的东西,就不只是要重新生成system.img了

修改测试
这个周末,我提交了大约四到五个patch。主要是联系人程序相关的一些bug修正。如果你是想修改build in的程序,像联系人这样的,最好先在编译前把contacts包删去,这样编译出来的system.img不带contacts程序会方便很多,可以直接用eclipse开发contacts程序,在这个模拟器上调试。像一般情况下,contacts是带在system.img内的,对程序修改后想测试,比较麻烦,需要先运行emulator,然后adb uninstall掉原先的程序,再安装自己的,并且如果数据没卸干净,会有permission出错或uid不否而报错的情况。最最麻烦的是,每次重启emulator,build in的程序在被adb uninstall后又会出现,这个问题在真机上不会出现。所以我建议你直接去掉contacts再编译个system.img出来,不过今天的几个修改都比较简单,我全部都是改一点就用mmm重新编译contacts程序,然后用make snod来出一个新的system.img,覆盖掉sdk目录下旧有的文件,来测试。这个过程熟练了一般两分多钟可以测一把。