- 浏览: 118933 次
- 性别:
- 来自: 武汉
最新评论
-
常思己过:
楼主,下载链接出现问题,可否修改下
Gtalk基本功能完成 -
hurryup911:
学习以下!!!顶
Android:将音视和视频结合起来! -
luya615:
“要符合中国国情。”
Blackberry(黑莓) 邮件收发功能
一、J2ME中需要的Java基础知识
现在有大部分人,都是从零开始学J2ME的,学习J2ME的时候,总是从Java基础开始学习,而且现在讲Java基础的书籍中都是以J2SE来讲基础,这就给学习造成了一些不必要的麻烦,下面将J2ME中用到的和不需要的Java基础知识做一个简单的说明。
J2ME中使用到的Java基础知识:
1、Java语法基础:包括基本数据类型、关键字、运算符等等
2、面向对象的思想:类和对象的概念,继承和多态等等。
3、异常处理
4、多线程a
J2ME中没有用到的Java基础知识:
1、JDK中javac和java命令的使用
2、Java基础中的很多类在J2ME中没有,或者类中的方法做了大量的精简。所以建议在J2ME中熟悉类库。
3、Applet、AWT、Swing这些知识在J2ME中根本使用不到。
简单说这么多,希望学J2ME的朋友们能少走一些弯路,不足之处希望大家积极指正和补充。
二、J2ME中暂时无法完成的功能
列一些J2ME中暂时无法完成的功能,希望大家能积极补充:
1、在手机中不更改代码实现移植,主要指游戏。
2、动态修改按钮文字。
3、在Canvas上接受中文输入。
4、操作本地资源、例如地址本、已收短信息等。
5、制作破坏性的手机病毒。
6、其他等待大家来补充。
三、J2ME的跨平台性
J2ME技术源于Java,所以也具有JVM的优势,可以在支持Java的平台上进行移植,但是现在的J2ME技术在跨平台上却做的很糟糕,我们来简单看一下原因:
1、手机的屏幕尺寸不一:
这个主要在界面制作上。如果你使用的是高级用户界面,比如你做的是应用开发或者用户登陆、用户注册这样的通用功能时,一般没有什么问题。
如果你使用的是低级用户界面,比如你做的是游戏,那么你就需要考虑这个问题了。
2、厂商的扩展API不统一:
例如Nokia的扩展API类库UI系列,在别的手机上或者没有实现,或者包名不同等等。
3、手机平台上实现的bug:
例如Nokia的7650在实现双缓冲上有bug,那么在这种机型上运行的软件就不能使用双缓冲。其他NOKIA上的一些bug,可以参看:http://blog.csdn.net/Mailbomb/archive/2005/03/24/329123.aspx
4、手机性能问题。
不同手机的可用内存、最大jar文件都有要求,例如Nokia S40的大部分手机支持的最大jar文件为64K,最大可用内容为210K。
所以现在的手机软件,特别是游戏都提供支持的机型列表,也才有了手机游戏移植人员的存在。
四、学习J2ME可以从事的工作种类
现在J2ME技术可以说相当的火暴,这里介绍一些学好了J2ME之后可以从事的工作的种类:
1、J2ME游戏开发人员
根据游戏策划或者文档要求,在某种特定的机型(以Nokia S40或S60居多)开发游戏程序。
这是现在大部分J2ME程序员从事的工作。
需要熟练掌握:高级用户界面、低级用户界面、线程,如果是网络游戏,还需要熟练网络编程。
2、J2ME应用开发人员
现在的移动应用还不是很多,但是还是出现了一些,特别是移动定位以及移动商务相关的内容。
需要熟练掌握:高级用户界面、线程和网络编程。
3、J2ME游戏移植人员
参照源代码,将可以在一个平台上可以运行的游戏移植到其他平台上去。例如将Nokia S40的游戏移植到S60上,或者索爱的T618等等。
主要是控制屏幕坐标,有些可能需要替换一些API。
需要熟悉各平台之间的差异以及相关的技术参数,比如屏幕大小、最大jar文件尺寸等等。
五、J2ME程序设计的几个原则
1、使用面向对象编程。
虽然使用面向过程编程可以减小文件的尺寸,但是为了以后维护的方便和利于扩展,还是要使用面向对象编程。
2、使用MVC模式
将模型、界面和控制分离。现在很多的程序将三者合一,但是如果你做的程序比较大的话,还是建议你进行分离。
3、自动存储用户设定
使用RMS来存储用户的信息,例如存储用户上次输入的用户名、密码、用户对于系统的设定等,这样不仅可以减少用户的输入,而且对用户友好。很多程序甚至做了自动登陆等。
4、一些系统设置允许用户关闭。如背景音乐、背景灯显示等。
5、将低级用户界面的绘制动作放在一个独立的线程里面去。
6、在需要大量时间才能完成的工作时,给用户一个等待界面。
六、从模拟器到真机测试
对于J2ME开发者来说,模拟器给我们带来了很多方便,比如可以在模拟器中调试程序以及很方便的察看程序的效果,但是模拟器也给我们带来了一些问题,比如模拟器实现的bug等等,所以进行真机测试是必须的。
1、为什么要进行真机测试?
因为模拟器程序可能存在bug,以及真机的性能有限,所以必须进行真机测试。
2、如何将程序传输到机器中?
将程序传输到机器中有如下方式:
a) OTA下载
b) 使用数据线传输
c) 红外传输
d) 蓝牙
你可以根据条件,选择合适的方式。
3、 真机测试主要测什么?
真机测试的内容很多,主要测试以下几个方面:
a) 程序的功能
b) 程序的操作性,是否易操作
c) 程序的大小,比如Nokia S40系列的手机大部分接受的最大文件尺寸为64K
d) 程序运行速度,速度是否可以忍受。
七、从WTK到厂商SDK
对于J2ME爱好者来说,基本上大家都是从SUN的WTK(J2ME Wireless Toolkit)开始的,但是对于实际应用来说,仅仅使用WTK是远远不够的,所以在学习过程中,必须完成从WTK到SDK的跨越。
1、厂商SDK的下载地址?
http://blog.csdn.net/Mailbomb/archive/2005/01/01/236606.aspx
2、厂商SDK和WTK有什么不同?
厂商SDK最简单的理解就是在WTK的基础上增加了自己的模拟器和自己的扩展API。
也就是说,你在使用厂商的SDK时,可以使用厂商的扩展类库,例如Nokia的UI类库,和厂商自己的模拟器而已。
每个厂商的扩展API都不多,而且不尽相同。
3、如何使用?
有些厂商SDK的使用都和WTK相同,例如SamSung。
Nokia提供了独立的界面来开发,但是这个界面在实际开发中使用不多。
4、厂商SDK的问题
厂商SDK实现过程中,有一些bug,而且和真机实现不一致。例如NOKIA的混音播放问题等等。
八、在J2ME中获得手机IMEI的方法
IMEI是Internation mobile entity identification的简称,在手机中输入*#06#可以显示该数字,长度为15位,全球唯一,永远不会冲突,所以可以作为识别用户的一个标志。
下面是在J2ME中获得IMEI的方法:
1、MOTO系列的手机可以通过读取系统的IMEI属性获得,代码如下:
String imei = System.getProperty("IMEI");
2、SIEMENS系列的手机可以通过读取系统的com.siemens.IMEI属性获得,代码如下:
String imei = System.getProperty("com.siemens.IMEI");
九、J2ME网络连接中显示问题的解决办法
在网络编程中,有些时候会出现一些在没有接收到网络数据就显示界面的,造成界面显示不符合要求(例如公告显示,会先显示公告的背景图片再显示公告信息),这里提一个简单的解决办法给大家:
解决这种情况的方法分成三个步骤:
1、在需要显示的界面中,调用发送网络数据的方法。每次显示时调用该构造方法,不调用Display的setCurrent方法显示。
2、显示等待界面(例如进度条等),给用户提示,在进行网络连接。
3、在处理网络反馈的数据完以后,调用Display的setCurrent方法显示显示当前界面。
十、增强J2ME的String能力——分割字符串
从JDK1.4以后,String类中新增了split方法来实现字符串的分割,但是在J2ME中却没有该方法(MIDP2.0中也没有实现),但是在实际使用过程中,有些时候的确要用到这种操作,这里将我以前实现的一段代码和大家共享:
/** * 分割字符串,原理:检测字符串中的分割字符串,然后取子串 * @param original 需要分割的字符串 * @paran regex 分割字符串 * @return 分割后生成的字符串数组 */ private static String[] split(String original,String regex) //获得匹配子串的位置 //设置取子串的起始位置 //获得匹配子串的位置 //取结束的子串 |
十一、J2ME在低级用户界面上分行显示文字
在J2ME的低级用户界面开发中,经常会遇到需要在Canvas上显示大量的文字,例如关于界面、游戏说明、游戏公告等信息。如果在设计时,将文字的内容和长度都固定,既不利于修改也不利于维护。下面介绍一个简单的方法,实现一个简单、可维护性强的方式。
实现方法:
1、将需要显示的所有信息做成一个字符串。
2、编写一个将该字符串按照要求转换为字符串数组的方法。
3、将转换后的数组以循环的方式显示在Canvas上。
通过这样三个步骤,则修改显示的信息时,只需要修改包含显示信息的字符串即可,自己书写的方法可以按照以前的标准重新分割新的字符串。如果需要修改每行显示的字符个数,则只需要修改自己书写的方法即可。
通过这样一种实现方式,可以很方便的实现显示一些比较长的文本信息,即使是可变长度的字符串也没有问题。
十二、J2ME中使用记录存储系统(RMS)存储信息
在MIDP中,没有文件的概念,所以永久存储一般只能依靠记录存储系统实现,关于记录存储系统的简介,可以参看教程:http://www-900.ibm.com/developer ... -wi-rms/index.shtml
下面是一些记录存储系统的常用编码介绍:
1、打开记录集:
打开记录集使用RecordStore里面的静态方法openRecordStore,示例代码如下:
RecordStore rs = RecordStore.openRecordStore(“username”,true);
这样就打开了一个名称为rs的记录集,其中username为记录集的名称,该名称可以根据需要来取,第二个参数代表是否则没有时创建新的记录集,true代表在该记录集不存在时,创建新的记录集,false代表不创建。
如果在打开记录集时,该记录集不存在,则抛出RecordStoreNotFoundException异常,所以检测记录集是否已创建可以使用该异常。
注意:记录集打开以后记得关闭。
2、向记录集中写入数据
2.1增加数据
向已经打开的记录集中添加数据,需要使用addRecord方法,示例代码:
byte[] bytes = {1,2,3};
int id = rs. addRecord(bytes,0,bytes.length);
该代码将字节数组bytes的全部内容写入到记录集中,该方法的返回值为该信息的id,注意:id从1开始,而不是从0开始。
你可以循环使用该方法向记录集中写入多条数据。
2.2修改数据
修改已经存在的记录集中指定id的数据,需要使用setRecord方法,示例代码:
byte[] bytes = {1,2,3};
rs. setRecord(1,bytes,0,bytes.length);
以上代码的作用是将字节数组bytes的全部内容写入到id为1的记录集rs中。
该操作会覆盖已有的数据。
说明:有些时候,你需要将信息写入到记录集中的第一条记录中,则可以结合以上两个方法,则第一次时向记录集增加数据,以后来进行修改。
3、从记录集中读出数据
从记录集中读取已有数据,需要使用getRecord方法,示例代码:
byte[] bytes = rs. getRecord(1);
该代码从记录集rs中读取第一条数据,将读取到的数据放在bytes数组中。
在读取数据时,可以获得记录集中id的个数,可以使用getNumRecords方法获得
综合代码为:
int number = rs. getNumRecords();
int id = 1;
if(id >0 && id < number)
{
byte[] bytes = rs. getRecord(1);
}
4、从记录集中删除记录
从记录集中删除记录的方法有两种:逻辑删除和物理删除。
逻辑删除是指给删除的记录打标记。
物理删除是指从物理上删除该记录,但是该记录的id不能被重用,也就是说该id不会被继续使用。例如一个记录集中有5个记录,假设你删除了id为3的数据,则剩余记录的id依然为1、2、4、5。这给便历带来了一定的麻烦。
5、便历记录集
便历记录集,即访问记录集中的所有数据,有两个方法,详见:
http://gceclub.sun.com.cn/NASApp/sme/controller/teclist?tid=0103
6、其他操作
删除记录集
删除记录集不同于删除记录,需要使用deleteRecordStore方法,示例代码:
RecordStore. deleteRecordStore(“username”);
该代码删除名称为username的记录集。
十三、J2ME加密数据的一个第三方开源免费类库介绍
在J2ME编程中,经常遇到一些数据在存储或者传输时需要加密,下面介绍一个第三方的加密类库的一些资料:
加密类库的官方主页:http://www.bouncycastle.org/
介绍的文章:
中文:http://18900.motorola.com/ewa_portal/develope/jc_j2messl_5_1.jsp
英文:http://www.javaworld.com/javawor ... -1220-wireless.html
该文章的源代码包含使用的一些方法。
备注:因为该类库提供的功能比较强大,所以类库的尺寸比较大,最后在发布时需要将类库中不需要的类删除
十四、如何播放声音
在J2ME中,处理声音需要使用到Mobile Media API(MMAPI),该包是MIDP1.0的可选包,在MIDP2.0中已经包含了这个包。所以如果你使用MIDP1.0的话,请确认你的运行环境是否支持。
一般手机支持的声音文件格式为wav、mid和mpg等。具体请查阅你的手机说明文档。
在声音处理中,有很多处理的方式,这里说一下最常用的情况,播放JAR文件中的wav文件。
播放声音文件的流程:
1、按照一定的格式读取声音文件。
播放JAR文件中的声音文件一般是将声音文件处理成流的形式。示例代码:
InputStream is = this.getClass().getResourceAsStream("/Autorun.wav");
其中Autorun.wav文件位于JAR文件的根目录下,如果位于别的目录,需要加上目录名称,如/res /Autorun.wav。
2、将读取到的内容传递给播放器。
将流信息传递给播放器,播放器按照一定的格式来进行解码操作,示例代码:
Player player = Manager.createPlayer(is,"audio/x-wav");
其中第一个参数为流对象,第二个参数为声音文件的格式。
3、播放声音。
使用Player对象的start方法,可以将声音播放出来,示例代码:
player.start();
在播放声音时也可以设定声音播放的次数,可以使用Player类中的setLoopCount方法来实现,具体可查阅API文档。
下面是在NOKIA S60模拟器中测试通过。代码如下:
package sound; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import javax.microedition.media.*; import java.io.*; public class SoundMIDlet extends MIDlet /** Main method */ /** Handle pausing the MIDlet */ /** Handle destroying the MIDlet */ |
十五、J2ME 3D编程的一些资料
随着J2ME技术的发展,以及硬件速度的提升,3D游戏程序将慢慢的变成主流,最近想学习这一块的编程,所以收集了一些资料,和大家一起分享:
1、JSR184
JSR184是Nokia公司起草的一个关于3D API的规范,下载地址为:
http://www.forum.nokia.com/main/1,,1_0_10,00.html#jsr184
2、Nokia的3D编程资料
http://www.forum.nokia.com/main/1,6566,21,00.html
3、3D引擎
一个简单的开放源代码的3D游戏引擎
http://www.j2me.com.cn/Soft_Show.asp?SoftID=19
国内一个合作开发3D引擎的项目:
http://gceclub.sun.com.cn/NASApp ... =11&thread=8593
4、一款3D游戏产品
http://games.sina.com.cn/newgames/2004/04/040217696.shtml
5、支持3D的开发工具
当前一些高端的手机支持3D开发,支持3D开发的开发工具中,通用的有SUN的J2MEWTK2.2。专用的是厂商提高的支持JSR184的SDK。
十六、3D编程——第一个3D程序
参考WTK2.2提供的demo,完成了第一个3D程序,虽然很简单,而且有些问题还不是很清楚,还是把代码共享出来和愿意学习J2ME 3D编程的朋友一起学习。
关于代码的编译和运行说明如下:
1、以下代码在J2ME WTK2.2下面编译通过。
2、代码分为两个文件:First3DCanvas.java和First3DMIDlet.java。
3、使用J2ME WTK2.2建立新的工程,主MIDlet类为:first3d. First3DMIDlet
4、将代码保存在你的工程目录下的first3d目录下。
5、将J2ME WTK安装目录下的apps\Demo3D\res\com\superscape\m3g\wtksamples\retainedmode\content目录中的swerve.m3g文件复制到你的工程目录下的res目录下。
6、你的工程建立后,设置工程,通过WTK界面中的“设置”按钮打开设置窗口,在“API选择”中,设置“目标平台”为:自定义;“简档”为“MIDP2.0”;“配置”为“CLDC1.1”;选中“Mobile 3D Graphics for J2ME(JSR184)”。
7、这样你就可以编译和运行以下代码了。
源代码如下:
// First3DMIDlet.java public void pauseApp() {} public void destroyApp(boolean unconditional) {} // First3Dcanvas.java public void run() |
十七、在J2ME网络编程中使用CMWAP代理
在中国移动提供的网络连接中,分为CMNET和CMWAP两种,其中CMNET可以无限制的访问互联网络,资费比较贵。CMWAP类似一个HTTP的代码,只能访问支持HTTP的应用,但是资费便宜,稳定性比较差。
在实际的J2ME网络编程中,一般需要提供以CMWAP代理的方式连接网络,在J2ME中,连接的代码和直接连接有所不同,代码如下:
HttpConnection http = (HttpConnection)Connector.open(("http://10.0.0.172/"+url);
http.setRequestProperty("X-Online-Host",ServerName);
例如你需要访问的地址为:http://www.test.com/login/loginServlet则上面的代码就为:
HttpConnection http = (HttpConnection)Connector.open(("http://10.0.0.172/" + "login/loginServlet");
http.setRequestProperty("X-Online-Host","www.test.com");
在实际使用过程中,只需要使用实际需要访问的地址的域名或者IP来代替ServerName,例如示例中的“www.test.com”,使用后续的地址类代替代码中的url,例如示例中的“login/loginServlet”,就可以实际的使用CMWAP代理来进行连接了。
十八、J2ME中的时间处理全攻略
时间处理在程序开发中相当常见,下面对于时间处理做一个简单的说明。
一、时间的表达方式
时间在J2ME中有两种表达方式:
1、以和GMT1970年1月1号午夜12点和现在相差的毫秒数来代表
这种方式适合比较两个时间之间的差值。
2、以对象的形式来表达
二、时间处理的相关类
时间处理在J2ME中涉及三个类:
1、System类
long time = System. currentTimeMillis();
使用该方法可以获得当前时间,时间的表达方式为上面提到的第一种。
2、Date类
Date date = new Date();
获得当前时间,使用对象的形式来进行表达。
3、Calendar类
Calendar calendar = Calendar. getInstance();
三、时间处理的具体操作
1、以上三种表达方式的转换:
a)将System类获得的时间转换为Date对象
Date date = new Date(System. currentTimeMillis());
b)将Date类型的对象转换为Calendar类型的对象
Calendar calendar = Calendar. getInstance();
Date date = new Date();
calendar.setTime(date);
2、使用Calendar完成一些日期操作:
Calendar是时间处理中最常用也是功能最强大的类,可以用它来获得某个时间的日期、星期几等信息。
获得日期:
Calendar calendar = Calendar. getInstance();
……
int day = calendar.get(Calendar. DATE);
获得日期、年份、星期的操作和这个类似。
需要注意的是:Calendar中表示月份的数字和实际相差1,即1月用数字0表示,2月用数字1表示,……12月用数字11表示。
十九、J2ME中随机数字处理全攻略
在程序中生成随机数字,用处比较,如人工智能领域等等,这里对于在J2ME中生成随机数的操作进行一个简单的整理,希望对大家能有帮助。
J2ME和J2SE不同,不能使用Math类的random来生成随机数字,只能使用java.util包的Random类来生成随机数字。
1、创建Random类型的对象:
Random random = new Random();
Random random = new Random(10010010);
以上两种是创建Random对象的方式,第一种使用默认构造方法,和以下的代码作用完全等价:
Random random = new Random(System. currentTimeMillis());
相当与使用当前时间作为种子数字来进行创建。
第二种方式通过自己来指定种子数字来进行创建。
大家可以根据需要使用以上两种方式的任一种。
2、生成随机数字:
创建好了随机对象以后,我们就可以来生成随机数字了:
生成随机整数:
int k = random.nextInt();
生成随机长整数:
long l = random.nextLong();
3、生成指定范围的数字:
例如生成0-10之间的随机数字:
int k = random.nextInt();
int j = Math.abs(k % 10);
首先生成一个随机整数k,然后用k和10取余,最后使用Math类的abs方法取绝对值,获得0-10之间的随机数字。
获得0-15之间的随机数,类似:
int k = random.nextInt();
int j = Math.abs(k % 15);
获得10-20之间的随机数字:
int k = random.nextInt();
int j = Math.abs(k % 10) + 10;
二十、在J2ME手机编程中使用字体
在J2ME手机编程中,可以通过使用字体类——Font在低级用户界面中,获得更好的表现效果,那么如何使用Font类呢?
首先,由于手机设备的限制,手机中支持的字体类型很有限,所以在J2ME中只能使用手机支持的默认字体来构造Font类对象。下面是创建Font类的对象时使用的方法:
getFont(int face,int style,int size);
例如:
Font font = Font.getFont(Font.FACE_SYSTEM,Font.STYLE_BOLD,Font. SIZE_MEDIUM);
无论哪一个参数,都只能使用系统设置的数值,这些数值具体的大小在不同的手机上可能不同。下面对于其中的三个参数的取值做详细的介绍:
face参数指字体的外观,其的取值:
FACE_MONOSPACE——等宽字体
FACE_PROPORTIONAL——均衡字体
FACE_SYSTEM——系统字体
style参数指字体的样式,其的取值:
STYLE_BOLD——粗体
STYLE_ITALIC——斜体
STYLE_PLAIN——普通
STYLE_UNDERLINED——下划线
STYLE_BOLD | STYLE_ITALIC——粗斜体
STYLE_UNDERLINED | STYLE_BOLD——带下划线粗体
STYLE_UNDERLINED | STYLE_ITALIC——带下划线斜体
STYLE_UNDERLINED | STYLE_ITALIC | STYLE_BOLD——带下划线的粗斜体
size参数指字体的大小,其的取值:
SIZE_SMALL——小
SIZE_MEDIUM——中
SIZE_LARGE——大
通过上面的参数的值,可以组合出你需要的字体对象。
下面是一些常用的字体操作:
1. 获得系统的默认字体:
Font font = Font.getDefaultFont();
2. 在panit方法内部,假设Graphics参数的名称为g,则获得当前字体的方法是:
Font font = g.getFont();
3. 在panit方法内部,假设Graphics参数的名称为g,则设置当前字体的方法是:
g.setFont(font);
其中font为你构造好的字体对象。
4. 在MIDP2.0中,List可以设置每行的字体格式,方法是:
list.setFont(0,font);
则上面的代码是将list中的第一行设置为font类型的字体。
二十一、在J2ME手机程序开发中使用颜色
在J2ME手机开发过程中,需要经常用到颜色来进行绘制,增强程序的表现效果,下面就介绍一下如何使用颜色。
由于J2ME技术比较简单,所以没有实现专门的颜色类,而只是使用RGB的概念来代表颜色。这里简单介绍一下RGB的概念,颜色是由红(Red)、绿(Green)、蓝(Blue)三原色组成的,所以可以使用这三个颜色的组合来代表一种具体的颜色,其中R、G、B的每个数值都位于0-255之间。在表达颜色的时候,即可以使用三个数字来表达,也可以使用一个格式如0X00RRGGBB这样格式的十六进制来表达,下面是常见颜色的表达形式:
红色:(255,0,0)或0x00FF0000
绿色:(0,255,0)或0x0000FF00
蓝色:(255,255,255)或0x00FFFFFF
其他颜色也可以通过上面的方式组合出来。
知道了颜色的表达方式以后,下面来介绍一下如何在J2ME程序中使用颜色,涉及的方法均在Graphics类中,有以下几个:
1.getColor():
获得当前使用的颜色,返回值是0x00RRGGBB格式的数字。例如:
int color = g.getColor();
其中g为Graphics类型的对象。
2.setColor(int RGB):
设置使用的颜色。例如:
g.setColor(0x00ff0000);
3.setColor(int red, int green, int blue)
和上面的方法作用一样,例如:
g.setColor(255,0,0);
在设置了Graphics使用的颜色以后,再进行绘制的时候,就可以绘制指定的颜色了。
二十二、在J2ME联网应用中获得客户端的手机号码
在J2ME程序开发过程中,为了一定的需要,经常需要来获得用户的手机号码,但是这个功能却在标准的J2ME类库中没有提供。
在使用中国移动的CMWAP方式连接网络时,中国移动会将用户的手机号码放在一个名称为x-up-calling-line-id的头信息中,可以通过读取该头信息,获得用户的手机号码,具体代码如下:
String usermphone = http.getHeader("x-up-calling-line-id");
其中http是HttpConnction类型的对象。
二十三、使用J2ME发送手机短信息
在程序中,发送短信息的方式一般有三种:
1、 使用程序在网络上发送短信息,例如各大网站的短信业务。这种方式是通过程序将信息发送给运营商的网关服务器,然后通过运营商的网络发送给手机。
2、 在计算机中,通过数据线连接到手机,然后通过手机来发送短信息。这种方式是通过使用AT指令来实现。爱立信手机的AT指令你可以在以下地址找到:http://mobilityworld.ericsson.com.cn/development/download_hit.asp
3、 通过在手机中运行的程序来发送短信息。这个正是本文实现的方式。
在J2ME中,如果想发送短信息,需要使用WMA包,MIDP2.0中已经包含,MIDP1.0中可以通过厂商提供的扩展API实现,和WMA的类库基本一样。
下面是使用WMA向指定手机号码发送短信息的一个方法,很简单。当然WMA也提供了其他的方式来发送更多的内容。
// SMSUtil.java package my.util; import javax.wireless.messaging.*; import javax.microedition.io.*; /** * 发送文本短信息的方法 */ public class SMSUtil { /** * 给指定号码发送短信息 * @param content 短信息内容 * @param phoneNumber 手机号码 * @return 发送成功返回true,否则返回false */ public static boolean send(String content,String phoneNumber) { //返回值 boolean result = true; try { //地址 String address = "sms://+" + phoneNumber; //建立连接 MessageConnection conn = (MessageConnection)Connector.open(address); //设置短信息类型为文本,短信息有文本和二进制两种类型 TextMessage msg = (TextMessage)conn.newMessage(MessageConnection.TEXT_MESSAGE); //设置信息内容 msg.setPayloadText(content); //发送 conn.send(msg); } catch(Exception e) { result = false; //未处理 } return result; } } |
二十四、使用简单的J2ME程序测试MIDlet的生命周期
在MIDlet程序学习中,生命周期是一个比较抽象的概念。其实生命周期就是一个简单的规定,规定了MIDlet中的每个方法,什么时候被系统调用。下面是一个示例代码,在每个方法的内部都输出一条语句,可以根据程序的输出结果来验证各方法被调用的顺序,具体代码如下:
//文件名:LifeCircleMIDlet.java import javax.microedition.midlet.*; /** * 测试MIDlet的生命周期 */ public class LifeCircleMIDlet extends MIDlet { /** * 默认构造方法 */ public LifeCircleMIDlet() { System.out.println("默认构造方法"); } /** * 启动方法 */ public void startApp() { System.out.println("startApp方法"); } /** * 暂停方法 */ public void pauseApp() { System.out.println("pauseApp方法"); } /** * 销毁方法 * @param b */ public void destroyApp(boolean b) { System.out.println("destroyApp方法"); } } |
在J2WTK中运行该程序时,可以使用浏览器中的“MIDlet”菜单中的暂停和恢复菜单,模拟暂停事件。
二十五、使用OTA来发布你的程序
众所周知,J2ME程序发布的形式主要有:OTA、数据线传输、红外和蓝牙传输等。这里简单说说如何通过OTA来发布你的程序。
OTA是Over The Air的简写,也就是通过网络下载,这是主要的发布形式之一。现在的百宝箱都是采用这种形式。
使用OTA来发布程序,需要如下几个步骤:
1、在你的WEB服务器上添加对于jad和jar文件的MIME支持。
后缀名:jad
MIME类型:text/vnd.sun.j2me.app-descriptor
后缀名:jar
MIME类型:application/java-archive
2、发布WML页面:
例如你的jar文件名test.jad,则最简单的下载页面是:
<?xml version="1.0"?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.3//EN" "http://www.wapforum.org/DTD/wml13.dtd"> <wml> <card id="card1" title="Download Midlet"> <a href="test.jad">test</a> _fcksavedurl=""test.jad">test</a>" </card> </wml> |
你可以将以上代码保存在WEB服务器上,例如保存为text.wml
3、修改jad文件:
在jad文件中增加 MIDlet-Jar-URL: http://domain/directory/test.jar
其中的http://domain/directory/test.jar为你的jar文件的路径。
经过上面的设置,你就可以将你的wml页面路径作为你的WAP下载页面发布了。用户只需要在手机上输入这个路径就可以访问和下载你的程序了。
J2ME游戏开发笔记整编版
1 J2ME中查表法使用三角函数
CLDC和MIDP都没有提供三角函数,而且CLDC1.0中也没有浮点数,所以我们的选择是查表。使用8位定点数的sin和cos表。下面是wtk自带demo中的代码,只提供了有限的几个角度,实际使用时根据需要细化角度值。
// sines of angles 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, all *256 // angle is in degrees/10, i.e. 0..36 for full circle // angle is in degrees/10, i.e. 0..36 for full circle |
(注:有一些算法可以生成三角函数值,这样只要在游戏载入时生成一下函数表即可,节省一些数据)
2 J2ME中使用随机数
产生0~n之间的随机数:
(ran.nextInt()>>>1)%n
或
(ran.nextInt()&0x7FFFFFFF)%n
产生-n~0之间的随机数:
(ran.nextInt() | 0x80000000 )%n
3 尝试IO优化
正在开发的一个游戏,由于读地图的时候做了图片切割,所以速度比较慢。(在我开发上一个游戏的时候,读取地图时没有装载切割图片,速度非常快,看来IO操作的速度和createImage,drawImage相比是微不足道的)对于IO的优化也许根本不会明显的提高速度,但我还是试了一下。
分析了一下代码,在最初的代码中为了比较方便的读取各种类型的数据,使用DataInputStream套接InputStream。可是我仔细看了一下我读取得数据,居然都是byte,唯一的一个char也是被我用两个byte手工组装起来的。这下,DataInputStream看来是不需要了。于是我做了个实验,没改动之前读取地图耗时1242ms,将DataInputStream去掉直接使用InputStream耗时1065ms,虽然每次试验的结果都稍有不同,但大概还是节约了200ms左右。
还能再加快点吗?再观察一下代码,我发现数据是通过多次的read操作读取进来的。太过频繁的io操作会不会降低速度呢?如果用一个字节数组作缓冲一次性将数据都读进来会不会快点?嗯,试一试才知道。但是我怎么知道一个流的大小呢?InputStream的avaliable方法总是返回-1啊!打开两次流,第一次先计算大小?对了,还有一个方法。直接将文件大小写到文件前面。地图文件是用自己的编辑器生成的,知道大小很容易。于是我在文件前面用两个byte纪录了文件的大小,先从流中读取2个byte,得到文件大小后,再用read(byte[],int,int)方法将整个流读取到缓冲中。然后,我的所有数据操作都从缓冲中读取。好,试验一下,结果是:1154ms。阿? 慢了近100ms。事实证明了这个猜想是错误的。原因?也许只有了解KVM的机制才知道。
弄完速度的问题,我又觉得读取文件的try块太大了,因为是边读边处理数据,所以try块变得很大。try块太大会增加class文件的大小。于是我用一个方法将读取byte的操作封装起来,当然这个方法是声明为private static的,但究竟能不能内联,只有编译器和kvm才知道。在这个方法内部从流中读取一个字节的时候采用了try,catch结构,这就使一个大try块分散成若干小try块。试验了一下,耗时1089ms,诶,还是慢了点。现在对于速度的要求比空间更高,更何况减小try块节省的10几个字节打包后基本忽略不计了。所以这个优化又失败了。
小结:能使用简单流的时候就不要使用复杂流,不要太相信理论上的说法,只有试了才知道。
注:试验数据是Nokia3100手机的实机测试数据,在Nokia 3300上这个数据更小些,最快约800多ms
4 压缩还是不压缩
做J2ME的都知道Midlet Suite的容量实在太小了,于是不免想做点压缩。前些天,我就尝试了一次压缩。我自己定义的地图文件里有3层数据,其中2,3层有大片连续分布的相同的值。 唉?我一琢磨,使用一个简单的行长编码压缩,仅对这个值进行行长编码,算法很简单速度又不慢,却可以大大减小地图文件的大小。看起来真的很不错诶!说干就干,忙了半天,又改地图编辑器,又改游戏中读地图的代码。总算搞定,试了一下,原来2.23k的一个文件被压缩到900多字节。好像很不错啊,接着我打了个jar包,却突然发现这个jar文件好像并没有比原来小阿!似乎还大了点。我连忙找出备份的代码,果然原来的jar更小点!怎么回事啊??我突然想到,jar本身就是压缩格式的。难道。。。我赶快用winrar打开两次的jar文件观察。~~~~~原来如此!原来的jar中,2.23k的文件的包大小为185字节,而我现在的jar中,900多字节的文件的包大小为216字节。也就是说,我自己先压缩一遍的文件打包后还不如不压缩的小!
看来自己做压缩之前,一定要先看看你想压缩的文件在包里面的大小。还有对于png文件,使用某些工具优化后,在包里面的大小却变大了。这个还真是要注意阿~!
(05.12.31注:某些压缩算法确实比zip压缩效率要高,可以使用,不过副作用是解压导致loading时间变长)
(2006.5注:有些时候,需要节省一下内存,可以将数据打包压缩一下,package & compress模式,存在内存中,需要时解压)
5 同时多处异常
程序出现exception时,在一个外包函数处捕获到了,显示为函数a出现异常,然后去a中捕获却没捕获成功,但是仍然发生了异常.
原来是外包函数中调用的另一个函数b也产生了同样的异常.
同时多处异常-小心!
----------------开发工具问题-----------------
1 Eclipse Tips
1.在工具条上有个文本形象的按钮"show source of selected element only".当编辑类的某个成员(方法或域)时,按下这个按钮,则当前窗口会只显示你正在编辑的类成员.再按一下则恢复.
2.显示java文件行号.菜单中选择Window->Preferences打开Preferences窗口后选择Java->Editor,在右边的选项中选中Show line numbers.
显示非java文件行号.在Preferences窗口中选择Workbench->Editors->Text Editor,同样右边的选项中选中Show line numbers.
3.编辑代码时,按ctrl+/可以注释当前行或选中的多行代码;按Atrl+/可以显示自动完成代码的提示。
4.选中代码,按 ctrl+shift+F 格式化代码
5.输入syso,按atrl+/可出来 System.out.println("") ;
2 运行Nokia模拟器的一个注意事项
这是一个老问题了,原来用WTK的时候就有,在WTK中启动Nokia的模拟器,如果先前已经打了包,那么运行的是打包的程序,想当年经常会很郁闷为什么改动了没效果,后来养成一个习惯,将jar装到手机测试后随手删除。
今天用JBuilder的时候又碰到了这个问题,也是Nokia的模拟器,如果已经建立了一个archive,那么Nokia模拟器运行的总是包,呵呵,所以要么将archive从project中remove,要么每次都rebuilder这个archive。
3 Eclipse集成Motorola模拟器
在Eclipse的菜单/工具条中选择Run->External Tools,打开面板后,选择program,然后new一个新的配置
1 在Location中填入Moto模拟器的路径,如:C:\Program Files\Motorola\SDK v4.2 for J2ME\EmulatorA.1\bin\emujava.exe,Moto的不同模拟器支持n种不同机型,需要看moto sdk的文档才知道。
2 在Arguments里填入执行的参数,包括jad路径,模拟器使用的机型。如:"${project_loc}\deployed\${project_name}.jad" -deviceFile Resources\V600.props
我是让模拟器执行deployed里面的jad/jar,${project_loc}是工程路径,${project_name}是工程名。这里选择的机型是V600.
说明:这种方法的局限在于只能执行jar,所以每次运行前必须打包。实际使用前需要为没种机型配置一个run,由于使用了通配参数,所以所有的工程都可以使用一个配置
(05.12.31注:现在某些MotoSDK已经可以和Eclipse集成了!)
4 初次使用JBuilder 7-若干小问题
(1) MobileSet问题
JBuilder7需另外安装MobileSet, Mobileset自带了一个WTK. 如果不安装MobileSet,JB7配置JDK时不能自动识别WTK,安装MobileSet后,可以通过配置JDK的方法加入新的WTK
(2) 资源文件问题
JBuilder的所有源文件都应该放在source path中,可以在工程属性中设置source path,资源文件也一样。既可以和源文件放在一个source path(即文件夹)中,也可以放在另外的source path中。需要注意的是,JBuilder只默认识别一定数量的后缀,如png,如果你使用了其他后缀的资源文件,如dat,bin,需要先把该文件通过add files加入到工程中,选择文件属性,设置为copy,这样该后缀的文件就被识别为资源文件了。
(3) 光标不对问题
最简单的办法-改字体,我改成了第一种字体(JB7中),感觉和默认字体没什么不同。至于这个问题的根本解决方法网上有文论述。
(4) 鼠标滚轮无效问题
据说这个问题只在JB7和以下版本中存在,原因是只有J2SDK1.4以上才支持滚轮,所以需要将JB7的JDK改成1.4的. 方法是修改JBuilder7\bin\jdk.config文件,将javapath和addpath两行修改,例如:
# javapath ../jdk1.3.1/jre/bin/hotspot/jvm.dll
javapath Y:\j2sdk1.4.2\jre\bin\server\jvm.dll
# addpath ../jdk1.3.1/lib/tools.jar
addpath Y:\j2sdk1.4.2\lib\tools.jar
5 百宝箱应用编译打包事宜
1 编译时,设置javac 的target vm为1.1即可通过移动检测。wtk中无法实现。在Eclipse中可以在java-compiler-Compliance and Classfiles中做以下设置:
Compiler compliance level: 1.4
Generated .class files compatibility: 1.1
Source compatibility: 1.3
(2005.12.31注:JBuilder中也有类似的选项,如果使用命令行或Ant,都只要将javac的targetVm参数设置为 target 1.1)
2 用eclispe打混淆包。但eclipse编写jad中文会出现乱码,所以用wtk编写正确的jad,然后用wtk打包(注意不能覆盖eclispe打的包),这是为了用wtk获得正确的jad和manifest文件。将elcipse打包出的jar解压,用wtk生成的mainifest代替原jar中的mainifest文件,然后用winrar打包(zip格式,可选最大压缩,注意要选择所有的文件后打包,不要将外面的整个目录打包).最后将jad中的jar size改为这个最新的jar的字节数。
(2005.12.31注:我不用eclipse很多年,据说现在的eclipse me新版没这问题了,我当时用的时候eclipse me的版本才0.4.6)
另:1. Nokia S60,SE k700机器中显示的游戏名字为MIDlet-1中的名字,而Nokia40为MIDlet-Name中的名字
2. 根据sp提供的资料Nokia 7650 游戏不能用中文名(其实NGageQD可以)
----------------机型相关问题-----------------
1 Nokia S60 IO操作内存泄漏不可不察
Nokia7650,3650
游戏运行过程中,有时会出现“存储已满”的对话框,出现的位置不固定
游戏运行过程中,有时出现“应用程序错误 NullPointerExcept”,“程序已关闭 MidpUi”的对话框
游戏运行过程中,有时会出现“程序已关闭 MidpUi ViewSrv 9”的对话框,出现的位置不固定
其实这个问题是由S60的getResourceAsStream方法内存泄漏的bug引起的,由于每次切换地图时io操作都要读取大量数据,内存泄漏积累到一定程度就引起了“存储已满”,白屏,死机,进而会引起null pointer异常等。解决方法是尽量减少io操作的次数。如果内存够大就一次将资源读入。
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
相关推荐
j2me 基础框架 及基础知识可以帮助入门
j2me 的 基础知识的总结 j2me中各种基础类的介绍
试题本身在开发过程中没有什么太大的意义,只是给初学者特供一个j2me基础知识掌握情况的参考。
J2ME基础知识: (1)J2ME概述 (2)建立开发环境 (3)应用程序设计
J2ME相关资源,介绍J2ME的相关基础知识,图片加载、网络连接问题、进度条相关问题
可以教会大家简单的运行j2me中的HTTP联网方式,进行手机之间的通讯
关于的基本开发知识和一些小游戏的源代码。。。
J2ME_移动通信介绍J2ME_移动通信介绍J2ME_移动通信介绍J2ME_移动通信介绍J2ME_移动通信介绍J2ME_移动通信介绍
j2me 的基础文章,很基础,还不错,值得一看。
这个实例可以教会大家简单的使用手机上的蓝牙技术
J2ME开发大全、J2ME基础、J2ME环境搭建
J2ME的相关专题,包括JAVA基础和JAVA在手机及嵌入式平台上的开发知识
J2me 基础学习 rpg游戏开发学习 对于初学者来说 很好用
J2ME开发 J2ME开发 J2ME开发 J2ME开发
j2me的新手教程(j2me)是入门开始一步一步教你成为高手,很快来学习吧!
j2me基础讲解及代码,含完全PPT及代码
j2me手机游戏开发基础
j2me基础教程是初学者必看的资源,包括j2me环境的搭建 ,j2me网络与web服务等
J2ME API J2ME API J2ME API J2ME API J2ME API
为爱好J2ME者提供好在教材文档,里面涵盖了J2ME在全部教学过