随着MTK的流行,使现在的J2ME虚拟机市场上品牌众多,除了索爱,Nokia S40,Moto,三星,LG等国际大品牌的虚拟机,更是有MTK,展讯内置的一些不知名的虚拟机,因此当初Write Once,Run AnyWhere变成了Write Once,Debug AnyWhere了。对于一个没有经验的J2ME程序员来说,开发一个兼容性高的软件变成了噩梦,不断的在不同手机,不同平台上打log,在这台手机上解决了这个问题,跑到另外一台机器上问题有重新了,噢,my god!我不干了。别急!我写这篇文章的目的就是要告诉大家,对于这中状况,我们也不是束手无策的。下面就等我慢慢的道来解决之道。
预期读者
本文主要适合那些有经验的J2ME程序员在优化软件,或者是需要考虑软件兼容性时的参考文档。
Jblend 平台
JBlend 是一家日本的嵌入式虚拟机厂家生产的J2ME虚拟机,此虚拟机大量的用于低端手机平台,本人发现有使用此虚拟机的平台有,MTK,MOTO。
官方网站:http://www.aplixcorp.com/chs/index.html 。
索尼爱立信平台
索爱的虚拟机平台是:Java Platform。最新版本是8。索爱的平台在性能上,程序的稳定性方面要优于其他虚拟机平台。而且APIs方面的bug也很少,在网络支持方面也很优秀。基本上不会因为你忘记关闭连接而导致连接泄漏。
官方网站:http://developer.sonyericsson.com/site/zhcn/docs_and_tools/p_docs_and_tools.jsp
S40平台
S40平台是Nokia针对S60智能操作系统推出适应低端手机的手机操作系统,相对其他虚拟机平台来说,S40虚拟机对J2ME的支持相对比较完善,而且稳定些,不过网络环境这块,S40对网络资源泄漏特别关注,具体不同的手机,对同时打开多个连接有限制,这里建议大家做个测试,就不再累赘了。
官方网站:http://www.forum.nokia.com/
S40平台详解:http://tech.sina.com.cn/mobile/n/2006-09-22/1053107637.shtml
S60 平台
Nokia 智能机平台下的J2ME虚拟机。相对S40来说,S60支持的特性比较多,而且有些比较特殊的用法,比如获取系统相关属性的时候就是其中之一。
什么是JCP?
JCP(Java Community Process) 是一个开放的国际组织,主要由Java开发者以及被授权者组成,职能是发展和更新Java技术规范、参考实现(RI)、技术兼容包(TCK)。Java技 术和JCP两者的原创者都是SUN计算机公司。然而,JCP已经由SUN于1995年创造Java的非正式过程,演进到如今有数百名来自世界各地Java 代表成员一同监督Java发展的正式程序。 JCP维护的规范包括J2ME、J2SE、J2EE,XML,OSS,JAIN等。组织成员可以提交JSR(Java Specification Requests),通过特定程序以后,进入到下一版本的规范里面。 所有声称符合J2EE规范的J2EE类产品(应用服务器、应用软件、开发工具等),必须通过该 组织提供的TCK兼容性测试(需要购买测试包),通过该测试后,需要缴纳J2EE商标使用费。两项完成,即是通过J2EE认证(Authorized Java Licensees of J2EE)。
什么是JSR?
JSR是Java Specification Requests的缩写,意思是Java 规范请求。是指向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求。任何人都可以提交JSR,以向Java平台增添新的API和服务。JSR已成为Java界的一个重要标准。
下面是J2ME JSR规范列表
名称
|
内容
|
JSR118
|
MIDP2.1规范。定义了MIDP相关的接口,高级UI,低级UI,RMS,网络相关的APIs
|
JSR82
|
定义了蓝牙接口相关的APIs
|
JSR135
|
MobileMediaAPI,定义了多媒体相关开发的组件APIs
|
JSR172
|
1.一个轻量级的标准XML解析器 2.WebServices的远程调用API 其中这个JSR172实现的轻量级的XML解析器是JAXP1.2(JavaAPIforXMLProcessing)的一个子集。我们可以查看WTK提供的API看到j2me-xml提供的类一共只有12个,这说明这个轻量级的XML解析器是适合在移动电话这种资源受限设备上运行的。
|
JSR75
|
JSR75(PDAOptionalPackagesfortheJ2METMPlatform)中定义了两个可选包: PIM(ThePersonalInformationManagement)API,提供对个人信息数据的访问,一般包括名片夹,日历项,和待办事项。 FC(TheFileConnection)APIs,提供对本地文件系统的访问。
|
JSR177
|
安全APIs
|
JSR211
|
ContentHander内容处理APIs,可以调用此API打开相应的文件,比如你可以打开jar安装文件,打开mp3。
|
JSR239
|
OpenGL@ES。主要用于图形相关操作
|
JSR179
|
LocationAPIs主要是用于LBS服务
|
JSR180
|
SIPAPIs
SIP是一个应用层的信令控制协议。用于创建、修改和释放一个或多个参与者的会话。这些会话可以好似Internet多媒体会议、IP电话或多媒体分发。会话的参与者可以通过组播(multicast)、网状单播(unicast)或两者的混合体进行通信。
|
JSR184
|
Mobile3DGraphicsAPIs,3D图形开发。
|
JSR229
|
手机支付APIs
|
JSR234
|
手机高级多媒体支持,可以支持更丰富的多媒体操作
|
JSR238
|
国际化支持APIs
|
JSR248
|
JSR248:MobileServiceArchitectureMSA移动服务架构。
MSAforCLDC规范定义了移动电话上的下一代Java平台,当然是基于CLDC的J2ME平台。
MSAforCLDC的目的是为了减少J2ME平台的API分裂,为开发者定义一个高操作性的应用程序和服务环境。
JTWI(JavaTechnologyforWirelessIndustry,JSR185)定义了一系列的规范来强制实现JTWI规范的设备必须实现某些JSR,例如MIDP2.0,WMA和MMAPI等。MSAforCLDC可以认为是JTWI的第2版,它规定了一个高度集中的J2ME平台运行环境。
|
检查JSR支持
检查JSR的支持简单的方式有两种:
1. 是通过System.getProperty("property_name")的方式进行判断,一般如果存在相关的APIs支持,它会返回一个非null字符串。
检测代码
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->System.getProperty(property_key);
public String getInfo(String info) {
if (info == null) {
return "<unknown>";
} else {
return info;
}
}
2. 通过Class.forName(clase_name)的方式。
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->private boolean hasClassExit(String aClassName) {
try {
Class.forName(aClassName);
return true;
} catch (Exception e) {
return false;
}
}
上面的检测代码相对比较简单,而且也容易理解,关键是那些JSR 支持的属性名称,或者APIs的写法。
下面是部分属性名称,仅供参考。
Systemproperty
|
Description
|
Value
|
microedition.platform
|
|
DefinedinCLDC1.0andCLDC1.1.
|
microedition.encoding
|
|
AlwaysreturnsISO-8859-1.
|
microedition.configuration
|
|
DefinedinCLDC1.0andCLDC1.1.
|
microedition.profiles
|
|
依赖于底层实现
|
microedition.locale*
|
JSR37
|
依赖于底层实现
|
microedition.commports
|
|
依赖于底层实现
|
microedition.hostname
|
|
localhost
|
microedition.profiles
|
|
MIDP2.0
|
file.separator
|
文件分割符
|
依赖于底层实现(/,/)
|
microedition.pim.version
|
JSR75
|
1.0
|
microedition.smartcardslots
|
JSR177
|
依赖于底层实现
|
microedition.location.version
|
JSR179
|
1.0
|
microedition.sip.version
|
JSR180
|
1.0
|
microedition.m3g.version
|
JSR184
|
1.0
|
microedition.jtwi.version
|
JSR185
|
1.0
|
wireless.messaging.sms.smsc
|
JSR205
|
依赖于底层实现
|
wireless.messaging.mms.mmsc
|
JSR205
|
依赖于底层实现
|
CHAPI-Version
|
JSR211
|
JSR211
|
|
|
|
Nokia的一些系统参数
|
com.nokia.network.access
|
网络参数
|
pd-GSM
pd.EDGE-EDGE
pd.3G-3G
pd.HSDPA-3G
csd-GSMCSD/HSCSD
bt_pan-BluetoothPANnetwork
wlan-WIFI
na-无任何网络
|
com.nokia.mid.dateformat
|
日期格式
|
Yy/mm/dd
|
com.nokia.mid.timeformat
|
时间格式
|
hh:mm
|
com.nokia.memoryramfree
|
动态内存分配
Note:S60第3版不支持
|
|
com.nokia.mid.batterylevel
|
电池状态
|
|
com.nokia.mid.countrycode
|
城市代码
|
|
com.nokia.mid.networkstatus
|
网络工作状态
|
|
com.nokia.mid.networkavailability
|
网络是否激活状态
|
|
com.nokia.mid.networkid
|
网络ID
|
返回2个值
NetworkID
网络简称
|
com.nokia.mid.networksignal
|
|
|
com.nokia.mid.cellid
|
Cellid
|
基站信息ID
|
com.nokia.mid.imei
|
Imei号
|
手机唯一标识号
|
com.nokia.mid.imsi
|
|
应用程序属性
应用程序属性值是在应用程序描述符文件或者MANIFEST文件中定义的,当我们部署应用程序的时候可以定义应用程序属性。比如下面是一个典型的JAD文件内容。
MIDlet-1: HttpWrapperMidlet,httpwrapper.HttpWrapperMIDlet
MIDlet-Jar-Size: 16315
MIDlet-Jar-URL: HttpWrapper.jar
MIDlet-Name: HttpWrapper
MIDlet-Vendor: Vendor
MIDlet-Version: 1.0
MicroEdition-Configuration: CLDC-1.0
MicroEdition-Profile: MIDP-1.0
Which-Locale: en
其中Which-Locale就是应用程序属性值,我们可以通过MIDlet的成员方法getAppProperty()来得到它,代码片断如下:
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->import javax.microedition.midlet.*;
public class MyMIDlet extends MIDlet {
private String suiteName;
private String which_locale;
public MyMIDlet(){
suiteName = getAppProperty( "MIDlet-Name" );
which_locale = getAppProperty("Which-Locale");
}
//这里省略了其他代码
}
属性值对大小写是敏感的,如果属性值在底层系统、JAD文件和Manifest文件中都没有定义的话,那么将返回Null。
简单的Demo
下面是简单的测试环境的代码,有经验的朋友可以很容易就就跑起来。
代码片段
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->/**
* getSysInfo
*/
private void getSysInfo() {
addInfo("Microedition Configuration: ",
getInfo(System.getProperty("microedition.configuration")));
addInfo("Microedition Profiles: ",
getInfo(System.getProperty("microedition.profiles")));
addInfo("microedition.jtwi.version:",
getInfo(System.getProperty("microedition.jtwi.version")));
addInfo("microedition.platform:",
getInfo(System.getProperty("microedition.platform")));
addInfo("microedition.locale:",
getInfo(System.getProperty("microedition.locale")));
addInfo("default encoding:",
getInfo(System.getProperty("microedition.encoding")));
addInfo("microedition.commports",
getInfo(System.getProperty("microedition.commports")));
addInfo("microedition.hostname",
getInfo(System.getProperty("microedition.hostname")));
//microedition.smartcardslots
addInfo(" microedition.smartcardslots",
getInfo(System.getProperty(" microedition.smartcardslots")));
addInfo("com.nokia.network.access",
getInfo(System.getProperty("com.nokia.network.access")));
addInfo("com.nokia.mid.dateformat",
getInfo(System.getProperty("com.nokia.mid.dateformat")));
addInfo("com.nokia.mid.timeformat",
getInfo(System.getProperty("com.nokia.mid.timeformat")));
addInfo("com.nokia.memoryramfree",
getInfo(System.getProperty("com.nokia.memoryramfree")));
addInfo("com.nokia.mid.batterylevel",
getInfo(System.getProperty("com.nokia.mid.batterylevel")));
addInfo("com.nokia.mid.countrycode",
getInfo(System.getProperty("com.nokia.mid.countrycode")));
addInfo("com.nokia.mid.networkstatus",
getInfo(System.getProperty("com.nokia.mid.networkstatus")));
addInfo("com.nokia.mid.networksignal",
getInfo(System.getProperty("com.nokia.mid.networksignal")));
addInfo("com.nokia.mid.networkid",
getInfo(System.getProperty("com.nokia.mid.networkid")));
addInfo("com.nokia.mid.networkavailability",
getInfo(System.getProperty("com.nokia.mid.networkavailability")));
addInfo("com.nokia.mid.cellid",
getInfo(System.getProperty("com.nokia.mid.cellid")));
addInfo("com.nokia.mid.imei",
getInfo(System.getProperty("com.nokia.mid.imei")));
addInfo("com.nokia.mid.imsi",
getInfo(System.getProperty("com.nokia.mid.imsi")));
String[] timeZoneIDs = java.util.TimeZone.getAvailableIDs();
StringBuffer timeZonesBuffer = new StringBuffer();
for (int i = 0; i < timeZoneIDs.length; i++) {
timeZonesBuffer.append(timeZoneIDs[i]).append('/n');
}
addInfo("Total memory:",
Long.toString(Runtime.getRuntime().totalMemory()) + " bytes");
addInfo("Free memory:",
Long.toString(Runtime.getRuntime().freeMemory()) + " bytes");
addInfo("Available TimeZones:", timeZonesBuffer.toString());
addInfo("Default TimeZone:", java.util.TimeZone.getDefault().getID());
addInfo("com.siemens.mp.lcdui.Image", hasClassExit("com.siemens.mp.lcdui.Image") + "");
addInfo("com.motorola.phonebook.PhoneBookRecord",hasClassExit("com.motorola.phonebook.PhoneBookRecord") + "");
addInfo("com.motorola.Dialer", hasClassExit("com.motorola.Dialer") + "");
addInfo("com.jblend.util.Case", hasClassExit("com.jblend.util.Case") + "");
addInfo("com.samsung.util.AudioClip", hasClassExit("com.samsung.util.AudioClip") + "");
addInfo("com.mot.iden.multimedia.Lighting", hasClassExit("com.mot.iden.multimedia.Lighting") + "");
}
private boolean hasClassExit(String aClassName) {
try {
Class.forName(aClassName);
return true;
} catch (Exception e) {
return false;
}
}
public String getInfo(String info) {
if (info == null) {
return "<unknown>";
} else {
return info;
}
}
public void addInfo(String name, String value) {
iForm.append(new StringItem(name, value));
}
代码片段2
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->public void collectInfos(TestClient midlet, Display display) {
try {
Class.forName("javax.microedition.media.control.VideoControl");
addInfo("MMAPI: ", "yes" );
addInfo("MMAPI-Version: ",getInfo(System.getProperty("microedition.media.version")) );
} catch (ClassNotFoundException e) {
addInfo("MMAPI: ", "no" );
}
try {
Class.forName("javax.wireless.messaging.Message");
addInfo("WMAPI 1.1: ", "yes" );
try {
Class.forName("javax.wireless.messaging.MultipartMessage");
addInfo("WMAPI 2.0: ", "yes" );
} catch (ClassNotFoundException e) {
addInfo("WMAPI 2.0: ", "no" );
}
} catch (ClassNotFoundException e) {
addInfo("WMAPI 1.1: ", "no" );
}
try {
Class.forName("javax.bluetooth.DiscoveryAgent");
addInfo("Bluetooth-API: ", "yes" );
try {
Class.forName("javax.obex.ClientSession");
addInfo("Bluetooth-Obex-API: ", "yes" );
} catch (ClassNotFoundException e) {
addInfo("Bluetooth-Obex-API: ", "no" );
}
} catch (ClassNotFoundException e) {
addInfo("Bluetooth-API: ", "no" );
}
try {
Class.forName("javax.microedition.m3g.Graphics3D");
addInfo("M3G-API: ", "yes" );
} catch (ClassNotFoundException e) {
addInfo("M3G-API: ", "no" );
}
try {
Class.forName("javax.microedition.pim.PIM");
addInfo("PIM-API: ", "yes" );
} catch (ClassNotFoundException e) {
addInfo("PIM-API: ", "no" );
}
try {
Class.forName("javax.microedition.io.file.FileSystemRegistry");
addInfo("FileConnection-API: ", "yes" );
} catch (ClassNotFoundException e) {
addInfo("FileConnection-API: ", "no" );
}
try {
Class.forName("javax.microedition.location.Location");
addInfo("Location-API: ", "yes" );
} catch (java.lang.Throwable e) {
addInfo("Location-API: ", "no" );
}
try {
Class.forName("javax.microedition.xml.rpc.Operation");
addInfo("WebServices-API: ", "yes" );
} catch (ClassNotFoundException e) {
addInfo("WebServices-API: ", "no" );
}
try {
Class.forName("javax.microedition.sip.SipConnection");
addInfo("SIP-API: ", "yes" );
} catch (ClassNotFoundException e) {
addInfo("SIP-API: ", "no" );
}
try {
Class.forName("com.nokia.mid.ui.FullCanvas");
addInfo("Nokia-UI-API: ", "yes" );
} catch (ClassNotFoundException e) {
addInfo("Nokia-UI-API: ", "no" );
}
try {
Class.forName("com.siemens.mp.MIDlet");
addInfo("Siemens-Extension-API: ", "yes" );
try {
Class.forName("com.siemens.mp.color_game.GameCanvas");
addInfo("Siemens-ColorGame-API: ", "yes" );
} catch (ClassNotFoundException e) {
addInfo("Siemens-ColorGame-API: ", "no" );
}
} catch (ClassNotFoundException e) {
addInfo("Siemens-Extension-API: ", "no" );
}
}
附表:属性表
表1MMAPI属性
属性名称
|
属性作用
|
supports.mixing
|
代表手机是否支持混音(同时播放多个Player),返回值为“true”或“false”
|
supports.audio.capture
|
代表手机是否支持声音捕获(录音),返回值为“true”或“false”
|
supports.video.capture
|
代表手机是否支持视频捕获(录像),返回值为“true”或“false”
|
supports.recording
|
代表手机是否支持记录(record),返回值为“true”或“false”
|
audio.encodings
|
代表手机支持的声音格式,返回值格式为“encoding=audio/wav”,多个格式之间使用至少一个空格进行间隔
|
video.encodings
|
代表手机支持的视频格式,返回值格式为“encoding=video/3gpp”,多个格式之间使用至少一个空格进行间隔
|
video.snapshot.encodings
|
代表手机使用getSnapshot方法获得的视频快照格式,返回值格式为“encoding=png”,多个格式之间使用至少一个空格进行间隔
|
streamable.contents
|
代表手机支持的流媒体格式,返回null代表不支持
|
表2WirelessMessagingAPI属性
属性名称
|
属性作用
|
wireless.messaging.sms.smsc
|
代表手机发送短信时的短信服务中心号码
|
表3FileConnectionAPI
属性名称
|
属性作用
|
fileconn.dir.photos
|
代表手机中存储照片和其它图片的目录,例如“file:///c:/Myfiles/Images/”
|
fileconn.dir.videos
|
代表手机中存储视频的目录,例如“file:///c:/Myfiles/Videoclips/”
|
fileconn.dir.tones
|
代表手机中存储声音的目录,例如“file:///c:/Myfiles/Tones/”
|
fileconn.dir.memorycard
|
代表手机中存储卡的根目录。例如“file:///d:/”
|
fileconn.dir.private (NokiaS40不支持)
|
代表手机中MIDlet的私有工作目录,例如“file:///c:/System/MIDlets/[1015f294]/scratch”
|
fileconn.dir.photos.name
|
代表手机中图片目录的名称,例如“Images”
|
fileconn.dir.videos.name
|
代表手机中视频目录的名称,例如“Videoclips”
|
fileconn.dir.tones.name
|
代表手机中声音目录的名称,例如“Soundclips”
|
file.separator
|
代表手机中的文件分隔符,例如“/”
|
fileconn.dir.memorycard.name
|
代表手机中存储卡的名称,例如“Memorycard”
|
分享到:
相关推荐
开发易于移植的J2ME游戏.doc 开发易于移植的J2ME游戏.doc
J2ME开发 J2ME开发 J2ME开发 J2ME开发
资源名称:J2ME开发详解工具篇J2ME开发详解-工具篇,相当基础的文章,主要是根据目前比较热门的手机,像诺基亚、西门子、摩托罗拉等品牌手机程序的IDE开发工具,主要讲解配置及一些基础知识。 资源太大,传百度网盘...
J2me嵌入式开发,环境配置步步截图,以及实例测试
J2ME开发详解工具篇 pdf J2ME开发详解工具篇 pdf
J2ME游戏开发 J2ME游戏开发 J2ME游戏开发
j2me游戏开发j2me游戏开发j2me游戏开发j2me游戏开发j2me游戏开发j2me游戏开发j2me游戏开发
j2ME游戏开发详解j2ME游戏开发详解j2ME游戏开发详解j2ME游戏开发详解j2ME游戏开发详解j2ME游戏开发详解j2ME游戏开发详解j2ME游戏开发详解j2ME游戏开发详解
J2ME应用软件测试指南.pdf
完整的教程,绝不像那些人骗子一样是用来骗分的
针对诺基亚、摩托罗拉等手机开发环境介绍两款开发工具,并附有图片,手把手教你如何开发
本教程首先介绍了 j2me 开发体系,然后深入各个MIDP2.0 API,最后是搭建平台的知识。 第一章 “J2ME 技术概述”让你在学习J2ME 以前知道什么是J2ME。本章介绍了J2ME 平 台的体系结构和MIDlet 生命周期的概念。为以后...
J2ME项目测试文档,J2ME项目测试文档,非常实用
J2me音频测试工具
J2ME移动开发实战精解教学J2ME移动开发实战精解教学
《J2ME手机游戏开发技术详解》《J2ME手机游戏开发技术详解》《J2ME手机游戏开发技术详解》《J2ME手机游戏开发技术详解》《J2ME手机游戏开发技术详解》《J2ME手机游戏开发技术详解》《J2ME手机游戏开发技术详解》...
J2ME游戏开发实例讲解J2ME游戏开发实例讲解J2ME游戏开发实例讲解
自己做的一个j2me下载测试软件,用于连续下载测试用,耗流量软件
J2ME开发大全J2ME开发大全 J2ME开发大全J2ME开发大全
j2me手机游戏开发中免不了测试手机支持的各种参数。本midlet测试精心编写了一系列参数的测试。