2 NokiaS60模拟器异常退出
症状:模拟器自动关闭,没提示任何错误
原因:使用了Nokia UI API中的灯光或振动控制,而Nokia S60部分机型和对应的模拟器不支持这两个特性.
3 NokiaS60 UI API bug
1 旋转后,并以clip的方式向缓冲上贴图,clip无效
2 无法创建透明muttable Image
此两点,致命伤,带来许多不变
4 Nokia S60的几个问题
(1) 不能每帧调用 System.gc(),否则严重降低fps
(2) Nokia S60机器的不同机型对于translate 和 setClip的处理不一样。在Nokia N-Gage QD等机型中,setClip是相对于translate以后的坐标计算的,而在Nokia 6600,6670等机型中,setClip不受translate的影响,永远只相对于屏幕左上角(0,0)点计算。所以如果在Nokia6670中,使用先translate再setClip的方法画子图,则会出现错误。为了统一代码,在Nokia S60中不要使用translate,即使用,两次translate之间不要进行setClip.修改后的画子图函数为:
public static void drawSubImg(Graphics g,Image img,int x,int y,int sx,int sy,int swidth,int sheight)
{
g.setClip(x,y,swidth,sheight);
g.drawImage(img,x-sx,y-sy,GLT) ;
g.setClip(0,0,width,height) ;
}
(3) 部分Nokia机型(6600,6670等)退出后报错null pointer exception的解决方法
不要在在主while循环中调用destroyApp,而改成检测一个标志,退出主循环后再调用destroyApp
boolean exit ;
...
while(!exit){
...
if(...){
exit = true ;
}
...
}
destroyApp(true);
注:可在destroyApp内部调用notifyDestroyed
5 Nokia"不能运行应用程序"错误新解
Nokia手机运行J2ME程序的时候出现“不能运行应用程序”的错误,一般都是内存不足引起的,但今天遇到这样的错误,却发现是另一个原因。即当使用nokia的UI API,DirectGraphics的drawImage时,如果旋转参数设置不当,也会出现“不能运行应用程序”的错误。
6 Nokia系统bug两则
(1) Nokia7650(V4.46)应用程序目录显示bug
应用程序安装后,打开应用程序目录,显示错误提示:
"程序已关闭 MidpUi USER9",应用程序目录无法进入。
分析后发现,原来是新安装的应用程序没有在mainfest.mf中的
midlet-1属性中指定应用程序图标,导致程序目录无法显示图标。
在我所见到NokiaS40机器上和NGageQD上,如果图标没指定或指定了但
不存在,将显示默认的图标。
此bug对于其它版本的7650或者其他机型是否存在尚不得知。
解决方法:使用seleQ将7650c:\system\midp中刚安装的程序目录删掉,即可正常进入应用程序目录。
在应用中使用自己的应用程序图标,并正确设置,以避免让用户遭遇到此bug。
(2) Nokia3100(v3.10)游戏目录振动设置与应用程序中使用振动冲突的bug
在Nokia3100等机型中,提供了一个游戏目录管理游戏类应用。该目录
可以设置目录中的游戏运行时是否发声,振动和使用网络。对于
Nokia3100(V3.10)如果将振动设置关掉,而在应用程序中使用了振动,则
会产生一个异常。此bug是在10个月之前发现的,记不清是哪个异常了。
此bug对于其它版本的3100或者其他机型是否存在尚不得知。
解决方法:在应用程序中使用振动的地方增加异常处理。
7 Motorola手机J2ME应用问题
(1) 应用程序图标
必须在jad 文件Midlet-Icon属性中指定图标文件,Midlet-1中指定的图标无效
Moto V系列图标大小应为15*15,其他尺寸无法显示。
(2) 左右软键问题
Motorola手机操作系统设定是:右软键确认,左软键取消。所以,我们的程序应该和这个习惯保持一致。
(3) Key Code
Moto V的key code不同于其他Midp2.0机器
左软键:21
右软键: 22
中键: 20
up: 1
down: 6
left: 2
right: 5
(2005.12.31注:在遇到新机型时,先测试一下keyCode比较好)
8 MIDP2.0 Canvas全屏问题
MIDP2.0 Canvas可以调用setFullScreenMode(true)将Canvas设置成全屏,但设置成全屏后新的Canvas width & height的获得对于不同手机却并不一样。
(1) MotoV系列
调用setFullScreenMode(true)后,将触发sizeChanged事件,此事件从系统接受两个参数,即为Canvas全屏后的width & height,通过这个事件可以获得新的宽高。
protected void sizeChanged(int w, int h)
{
width = w ;
height = h ;
}
但要注意,此事件并不是同步的,就是说如果你调用了setFullScreenMode(true)之后,立即使用新的width,height,有可能获得错误的结果。
(2) SE K700
调用setFullScreenMode(true)后,不会触发sizeChanged,而是通过getWidth和getHeight获得新的宽高。SE的setFullScreenMode调用后是立即返回的,所以可以获得正确的width & height
对于其他机型暂时还不了解
----------------移植问题-------------------
1 键盘响应
不同的机型对于键盘事件的响应不一样。经过我的测试,Nokia 7210,3100一次只能接受一个按键信息。(我写了个测试程序,发现如果一个键被按下后没有松开,则KeyPressed事件不会再产生,即其他键的按下操作无效)所以,用缓冲处理控制精灵运动时,如果规定只能四方向运动。如果up已按下,再按下left,精灵的运动方向并不会改变。不过将按键缓冲。按下up,按下left不释放,松开up---精灵就会向左运动。(在松开up后产生了left的KeyPressed事件!奇怪吗?松开up后我并没有进行"按下"left这个动作--left键在up松开前就被按下了且没有松开。似乎机器一直在监测键盘上各键的状态,并且有一个等待队列。)
在wtk的标准模拟器上就不同了。它可以接受多个按键“同时”按下的事件。所以如果用四个并列的if处理,精灵是可以斜着运动的。如果用if else处理,则如果已经按下一个方向键,然后再按下另一个,是否能改变方向受到if else 语句中顺序的影响。即,如果是 if(up) else if(left),则会先检查up键,所以如果已经按下了left,再按up是可以向上运动的,反过来就不行了。(这个自然:)
其它的机型由于手头没有机器,我也没试过。应该也是如此吧。
2 多机型移植经验谈
开发的时候平台是Nokia 40,然后移植到Nokia 60, Moto V, SE等,总结一下大概需要几个版本。
1。 Nokia 40版, 使用Midp1.0+Nokia UI API
2。 Nokia 60版, 使用Midp1.0+NOkia UI API
3. Nokia Midp2.0版,如6600,7610,使用Midp2.0
4。Moto V版,使用Midp2.0
5。 SE版,使用Midp2.0
6. 三星s100,s200,c100,使用Midp2.0
几点开发经验:
1。各机型之间最大的差别就是屏幕大小不同。所以游戏中要能自适应屏幕大小
2。不使用Midp2.0的GameAPI会比较方便移植,只要自己封装切图,旋转等函数即可。NokiaUI API和Midp2。0都支持图片选转。2.0支持的更好。注意Nokia 60不支持创建可变的透明图片,所以要用其他方法代替。
3。NOkia 6600,7610的UI API有问题(图片旋转),所以用了Midp2.0代替
4。支持MIDP2。0的机器程序大致相同,其中MOto,SE,SX都差不多。但也有细微差别。如SE不支持全屏。所以screenSizeChanged方法无效。
5。说说声音播放。NOkia s40上我坚决不用声音,一是容量限制,二是太难听。其他机型都可以支持midi和wav.不过没有发现可以同时播放2个midi的机型,moto v和se都可以同时播放midi和wav,nokia则不行。
3 移植一法
近日观察某些游戏的源代码(反编译后的),发现有个方法挺方便游戏的移植的。定义一个接口(比如stringTable)将游戏中所用到的静态字符串都定义为接口的常量。然后,让使用到这些字符串的类实现stringTable接口。这样移植的时候只要修改接口里面的字符串就行了。当然,对于游戏中坐标的定位,最好使用getWidth(),getHeight()还有Font类的方法stringWidth,不要定死了。这样的话,移植工作就比较轻松了。
4 检测机型
在J2ME开发中,往往遇到根据不同机型做不同事情的情况,比如Nokia3650的键盘比较特殊,Nokia7650不支持mmapi,所以需要获得机型信息。
下面是一段简单的代码
public static void checkPlatform()
{
String platform = System.getProperty("microedition.platform") ;
String tmp = null ;
if(platform.length()==9)
tmp = platform ;
else if(platform.length()>9){
tmp = platform.substring(0,9) ;
}
if(tmp!=null){
if(tmp.equals("Nokia3650")){
is3650 = true ;
}
else if(tmp.equals("Nokia7650")){
is7650 = true ;
}
}
}
获得机型信息还包括版本号等等,所以要截取前面的几个字符比较。
不过得到的机型字符串有时并不保险,如早期的Nokia N-Gage获得得并不是N-Gage,不过3650和7650还是可以的








