星期二, 九月 09, 2008

MIDP ON ZAURUS

MIDP ON ZAURUS

前两天编译了给Zaurus用的无线网卡驱动。用Zaurus上网还是太慢了点,所以在想手机软件有很多都是比较小的,在Zaurus上运行应该速度会更快点,而且现在手机软件也很丰富了。上网搜索后找到这里 。 下载安装了

首先试玩经常用的Opera Mini.

运行之后出错,很是郁闷。到网站查找发现最新release的me4se已经是2.2.0版本,下载后在PC上运行opera很好,可以工作。所以替换掉/opt/QtPalmtop/midp/me4se.jar在Zaurus上运行抛出异常。方法找不到 NoSuchMethod : BufferedImage<init>(III)。 看来使用到了zaurus 不支持的API,没办法只好自己修改。下载me4se-src-2.2.0.zip 。 检查发现org.me4se.scm.ScmWrapper的第137行附近用到了
new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
这是Zaurus不支持的,改为
getGraphicsConfiguration().createCompatibleImage(size.width, size.height);
检查其他的Zaurus不支持的API发现org.me4se.psi.java1.gcf.socket.SocketConnectionImpl.getAddress()里面用到了
return socket.getRemoteSocketAddress().toString();
改为
return socket.getInetAddress().toString() + ":" + socket.getPort();
重新打包成me4se.jar文件(注意原来的me4se.jar包里面有些文件不是从source编译而来的,把它们带进去) 再次运行出错如下:
java.lang.NullPointerException: at javax.microedition.midlet.ApplicationManager.launch(Lorg/me4se/impl/JadFile;)V(Unknown Source) at org.me4se.MIDletRunner.main([Ljava/lang/String;)V(Unknown Source) java.lang.NullPointerException: at f.<init>()V(Unknown Source) at Browser.startApp()V(Unknown Source) at javax.microedition.midlet.ApplicationManager.start()V(Unknown Source) at org.me4se.MIDletRunner.main([Ljava/lang/String;)V(Unknown Source)
这个就比较麻烦了,PC正常而Zaurus上不正常,究竟环境有什么不一样呢?Opera的代码都是混淆过的,很难调试。只好请出ASM的字节码处理工具 使用ASM3.1 。 首先做了一个Visitor,在类f的构造函数里的所有mv.visitVarInsn后面加入System.out.println(i++); MyMethodVisitor里的代买片段如下:
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); mv.visitIntInsn(BIPUSH, i++); mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(I)V");
最后定位到如下两个指令:
mv.visitFieldInsn(GETSTATIC, "a", "g", "Ljava/lang/String;"); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "length", "()I");
a.g是null,取长度当然出错。这个a.g在PC上运行时输出的是lemontopic。 追查a.g是在a.Z()V的方法里设置的,这个方法是从/v文件里读取的字符串,也就是说在Zaurus上面没有能正确读出这个文件。把v文件解压出来,做了一个小程序Test:
public static void main(String[] args) throws IOException { DataInputStream ds = new DataInputStream(T.class.getResourceAsStream("v")); System.out.println(ds.readInt()); ds.close(); }
正确的输出了整数72。把这个class和v文件打包成jar后再运行出错。不知道为什么?(谁知道的告诉我一下) 不管怎样把Opera Mini里的v文件解压到当前路径。 运行还是出错,发现修改midp里的 -Djava.class.path 改为-Xbootclasspath/a:之后可以从当前路径加载v文件。 成功进入Opera Mini的界面,不过提示不能连接网络。 检查得知zaurus的personal profile里面有一个javax.micromedia.io的包,和MIDP里的包名一样,并且排在ClassPath的前面。所以加载的是personal profile的io包。 修改midp使用-Xbootclasspath/p:,这样me4se.jar里的包会排在前面,运行Opera mini后可以正常访问网页。 终于成功。

试玩MGTalk

IM工具我一直用Gtalk。MGTalk在手机上用起来很方便。 MGTalk要用https登录Google的服务器。zaurus用的是jdk1.3的personal profile。不支持SSL连接。 首先从Sun下载jsse 。 按照说明修改/opt/QtPalmtop/j2me/lib/security/java.security文件 加入:
security.provider.3=com.sun.net.ssl.internal.ssl.Provider
修改midp加入
JSSE=/opt/QtPalmtop/j2me/lib/ext JSSEJAR=$JSSE/jnet.jar:$JSSE/jcert.jar:$JSSE/jsse.jar -Xbootclasspath/p:$JSSEJAR -Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol
其次,me4se-2.2.0里面还没有支持https连接,从me4se的cvs取下最新的包含https支持的代码,替换2.2里面的。一共是两个包:
org.me4se.psi.java1.gcf.http org.me4se.psi.java1.gcf.https
再次运行MGTalk后出错如下:
java.security.cert.CertificateException: untrusted server certificate chain
忘记添加cacerts了,从PC拷贝%JRE_HOME%/lib/security/cacerts到/opt/QtPalmtop/j2me/lib/security 后运行提示SSL implementation not available。 打开-Djavax.net.debug=all,从Log中看到,在init truststore之后出现:
java.security.cert.CertificateParsingException: java.io.IOException
subject key, Unknown key spec
上Google检索之后找到Bug ID: 6656520 。上面说到,JRE5,JRE6的cacerts里新加了aol的根证书,jdk1.4.2不能识别,我的zaurus肯定也不能识别。
copy %JRE_HOME%/lib/security/cacerts ./ keytool -delete -alias aolcaroot1 -keystore cacerts keytool -delete -alias aolcaroot2 -keystore cacerts
用这个新生成的cacerts。运行MGTalk,成功连接到Google的服务器。

遗留问题:

  • 为什么不能读取Jar里面的v文件?
  • me4se的CVS版里面用到了BufferedImage<init>(III),这个方法可以用GraphicsConfiguration().createCompatibleImage(size.width, size.height);代替,但是BufferedImage.TYPE_INT_ARGB这个参数如何实现还不知道。
  • me4se里还不好输入中文。(已解决 )
附我对me4se的修改

没有评论:

发表评论