J2ME程序开发全方位基础讲解汇总(1)
J2ME中暂时无法完成的功能
列一些J2ME中暂时无法完成的功能,希望大家能积极补充:
1、在手机中不更改代码实现移植,主要指游戏。
2、动态修改按钮文字。
3、在Canvas上接受中文输入。
4、操作本地资源、例如地址本、已收短信息等。
5、制作破坏性的手机病毒。
6、其他等待大家来补充。
J2ME程序设计的几个原则
1、使用面向对象编程。
虽然使用面向过程编程可以减小文件的尺寸,但是为了以后维护的方便和利于扩展,还是要使用面向对象编程。
2、使用MVC模式
将模型、界面和控制分离。现在很多的程序将三者合一,但是如果你做的程序比较大的话,还是建议你进行分离。
3、自动存储用户设定
使用RMS来存储用户的信息,例如存储用户上次输入的用户名、密码、用户对于系统的设定等,这样不仅可以减少用户的输入,而且对用户友好。很多程序甚至做了自动登陆等。
4、一些系统设置允许用户关闭。如背景音乐、背景灯显示等。
5、将低级用户界面的绘制动作放在一个独立的线程里面去。
6、在需要大量时间才能完成的工作时,给用户一个等待界面。
在J2ME中获得手机IMEI的方法
IMEI是Internationmobileentityidentification的简称,在手机中输入*#06#可以显示该数字,长度为15位,全球唯一,永远不会冲突,所以可以作为识别用户的一个标志。
下面是在J2ME中获得IMEI的方法:
1、MOTO系列的手机可以通过读取系统的IMEI属性获得,代码如下:
Stringimei=System.getProperty("IMEI");
2、SIEMENS系列的手机可以通过读取系统的com.siemens.IMEI属性获得,代码如下:
Stringimei=System.getProperty("com.siemens.IMEI");
J2ME网络连接中显示问题的解决办法
在网络编程中,有些时候会出现一些在没有接收到网络数据就显示界面的,造成界面显示不符合要求(例如公告显示,会先显示公告的背景图片再显示公告信息),这里提一个简单的解决办法给大家:
解决这种情况的方法分成三个步骤:
1、在需要显示的界面中,调用发送网络数据的方法。每次显示时调用该构造方法,不调用Display的setCurrent方法显示。
2、显示等待界面(例如进度条等),给用户提示,在进行网络连接。
3、在处理网络反馈的数据完以后,调用Display的setCurrent方法显示显示当前界面。
增强J2ME的String能力——分割字符串
从JDK1.4以后,String类中新增了split方法来实现字符串的分割,但是在J2ME中却没有该方法(MIDP2.0中也没有实现),但是在实际使用过程中,有些时候的确要用到这种操作,这里将我以前实现的一段代码和大家共享:
/**
*分割字符串,原理:检测字符串中的分割字符串,然后取子串
*@paramoriginal需要分割的字符串
*@paranregex分割字符串
*@return分割后生成的字符串数组
*/
privatestaticString[]split(Stringoriginal,Stringregex)
{
//取子串的起始位置
intstartIndex=0;
//将结果数据先放入Vector中
Vectorv=newVector();
//返回的结果字符串数组
String[]str=null;
//存储取子串时起始位置
intindex=0;
//获得匹配子串的位置
startIndex=original.indexOf(regex);
//System.out.println("0"+startIndex);
//如果起始字符串的位置小于字符串的长度,则证明没有取到字符串末尾。
//-1代表取到了末尾
while(startIndex { Stringtemp=original.substring(index,startIndex); System.out.println(""+startIndex); //取子串 v.addElement(temp); //设置取子串的起始位置 index=startIndex+regex.length(); //获得匹配子串的位置 startIndex=original.indexOf(regex,startIndex+regex.length()); } //取结束的子串 v.addElement(original.substring(index+1-regex.length())); //将Vector对象转换成数组 str=newString[v.size()]; for(inti=0;i { str[i]=(String)v.elementAt(i); } //返回生成的数组 returnstr; } J2ME程序开发全方位基础讲解汇总(2) J2ME在低级用户界面上分行显示文字 在J2ME的低级用户界面开发中,经常会遇到需要在Canvas上显示大量的文字,例如关于界面、游戏说明、游戏公告等信息。如果在设计时,将文字的内容和长度都固定,既不利于修改也不利于维护。下面介绍一个简单的方法,实现一个简单、可维护性强的方式。 实现方法: 1、将需要显示的所有信息做成一个字符串。 2、编写一个将该字符串按照要求转换为字符串数组的方法。 3、将转换后的数组以循环的方式显示在Canvas上。 通过这样三个步骤,则修改显示的信息时,只需要修改包含显示信息的字符串即可,自己书写的方法可以按照以前的标准重新分割新的字符串。如果需要修改每行显示的字符个数,则只需要修改自己书写的方法即可。 通过这样一种实现方式,可以很方便的实现显示一些比较长的文本信息,即使是可变长度的字符串也没有问题。 J2ME中使用记录存储系统(RMS)存储信息 在MIDP中,没有文件的概念,所以永久存储一般只能依靠记录存储系统实现,下面是一些记录存储系统的常用编码介绍: 1、打开记录集: 打开记录集使用RecordStore里面的静态方法openRecordStore,示例代码如下: RecordStorers=RecordStore.openRecordStore(“username”,true); 这样就打开了一个名称为rs的记录集,其中username为记录集的名称,该名称可以根据需要来取,第二个参数代表是否则没有时创建新的记录集,true代表在该记录集不存在时,创建新的记录集,false代表不创建。 如果在打开记录集时,该记录集不存在,则抛出RecordStoreNotFoundException异常,所以检测记录集是否已创建可以使用该异常。 注意:记录集打开以后记得关闭。 2、向记录集中写入数据 2.1增加数据 向已经打开的记录集中添加数据,需要使用addRecord方法,示例代码: byte[]bytes={1,2,3}; intid=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方法获得 综合代码为: intnumber=rs.getNumRecords(); intid=1; if(id>0&&id 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、其他操作 6.1删除记录集 删除记录集不同于删除记录,需要使用deleteRecordStore方法,示例代码: RecordStore.deleteRecordStore(“username”); 该代码删除名称为username的记录集。 十四、如何播放声音 在J2ME中,处理声音需要使用到MobileMediaAPI(MMAPI),该包是MIDP1.0的可选包,在MIDP2.0中已经包含了这个包。所以如果你使用MIDP1.0的话,请确认你的运行环境是否支持。 一般手机支持的声音文件格式为wav、mid和mpg等。具体请查阅你的手机说明文档。 在声音处理中,有很多处理的方式,这里说一下最常用的情况,播放JAR文件中的wav文件。 播放声音文件的流程: 1、按照一定的格式读取声音文件。 播放JAR文件中的声音文件一般是将声音文件处理成流的形式。示例代码: InputStreamis=this.getClass().getResourceAsStream("/Autorun.wav"); 其中Autorun.wav文件位于JAR文件的根目录下,如果位于别的目录,需要加上目录名称,如/res/Autorun.wav。 2、将读取到的内容传递给播放器。 将流信息传递给播放器,播放器按照一定的格式来进行解码操作,示例代码: Playerplayer=Manager.createPlayer(is,"audio/x-wav"); 其中第一个参数为流对象,第二个参数为声音文件的格式。 3、播放声音。 使用Player对象的start方法,可以将声音播放出来,示例代码: player.start(); 在播放声音时也可以设定声音播放的次数,可以使用Player类中的setLoopCount方法来实现,具体可查阅API文档。 下面是在NOKIAS60模拟器中测试通过。代码如下: packagesound; importjavax.microedition.midlet.*; importjavax.microedition.lcdui.*; importjavax.microedition.media.*; importjava.io.*; publicclassSoundMIDletextendsMIDlet{ privatePlayerplayer=null; /**Constructor*/ publicSoundMIDlet(){ try{ InputStreamis=this.getClass().getResourceAsStream("/Autorun.wav"); player=Manager.createPlayer(is,"audio/x-wav"); }catch(IOExceptione){ System.out.println("1:"+e); }catch(MediaExceptione){ System.out.println("2:"+e); }catch(Exceptione){ System.out.println("3:"+e); } } /**Mainmethod*/ publicvoidstartApp(){ if(player!=null){ try{ player.start(); }catch(MediaExceptione){ System.out.println("4:"+e); } } } /**HandlepausingtheMIDlet*/ publicvoidpauseApp(){ } /**HandledestroyingtheMIDlet*/ publicvoiddestroyApp(booleanunconditional){ } } J2ME程序开发全方位基础讲解汇总(3) 在J2ME网络编程中使用CMWAP代理 在中国移动提供的网络连接中,分为CMNET和CMWAP两种,其中CMNET可以无限制的访问互联网络,资费比较贵。CMWAP类似一个HTTP的代码,只能访问支持HTTP的应用,但是资费便宜,稳定性比较差。 在实际的J2ME网络编程中,一般需要提供以CMWAP代理的方式连接网络,在J2ME中,连接的代码和直接连接有所不同,代码如下: HttpConnectionhttp=(HttpConnection)Connector.open(("http://10.0.0.172/"+url); http.setRequestProperty("X-Online-Host",ServerName); 例如你需要访问的地址为:http://www.test.com/login/loginServlet 则上面的代码就为: HttpConnectionhttp=(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类 longtime=System.currentTimeMillis(); 使用该方法可以获得当前时间,时间的表达方式为上面提到的第一种。 2、Date类 Datedate=newDate(); 获得当前时间,使用对象的形式来进行表达。 3、Calendar类 Calendarcalendar=Calendar.getInstance(); 三、时间处理的具体操作 1、以上三种表达方式的转换: a)将System类获得的时间转换为Date对象 Datedate=newDate(System.currentTimeMillis()); b)将Date类型的对象转换为Calendar类型的对象 Calendarcalendar=Calendar.getInstance(); Datedate=newDate(); calendar.setTime(date); 2、使用Calendar完成一些日期操作: Calendar是时间处理中最常用也是功能最强大的类,可以用它来获得某个时间的日期、星期几等信息。 获得日期: Calendarcalendar=Calendar.getInstance(); …… intday=calendar.get(Calendar.DATE); 获得日期、年份、星期的操作和这个类似。 需要注意的是:Calendar中表示月份的数字和实际相差1,即1月用数字0表示,2月用数字1表示,……12月用数字11表示。 J2ME中随机数字处理全攻略 在程序中生成随机数字,用处比较,如人工智能领域等等,这里对于在J2ME中生成随机数的操作进行一个简单的整理,希望对大家能有帮助。 J2ME和J2SE不同,不能使用Math类的random来生成随机数字,只能使用java.util包的Random类来生成随机数字。 1、创建Random类型的对象: Randomrandom=newRandom(); Randomrandom=newRandom(10010010); 以上两种是创建Random对象的方式,第一种使用默认构造方法,和以下的代码作用完全等价: Randomrandom=newRandom(System.currentTimeMillis()); 相当与使用当前时间作为种子数字来进行创建。 第二种方式通过自己来指定种子数字来进行创建。 大家可以根据需要使用以上两种方式的任一种。 2、生成随机数字: 创建好了随机对象以后,我们就可以来生成随机数字了: 生成随机整数: intk=random.nextInt(); 生成随机长整数: longl=random.nextLong(); 3、生成指定范围的数字: 例如生成0-10之间的随机数字: intk=random.nextInt(); intj=Math.abs(k%10); 首先生成一个随机整数k,然后用k和10取余,最后使用Math类的abs方法取绝对值,获得0-10之间的随机数字。 获得0-15之间的随机数,类似: intk=random.nextInt(); intj=Math.abs(k%15); 获得10-20之间的随机数字: intk=random.nextInt(); intj=Math.abs(k%10)+10; 在J2ME手机编程中使用字体 在J2ME手机编程中,可以通过使用字体类——Font在低级用户界面中,获得更好的表现效果,那么如何使用Font类呢? 首先,由于手机设备的限制,手机中支持的字体类型很有限,所以在J2ME中只能使用手机支持的默认字体来构造Font类对象。下面是创建Font类的对象时使用的方法: getFont(intface,intstyle,intsize); 例如: Fontfont=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.获得系统的默认字体: Fontfont=Font.getDefaultFont(); 2.在panit方法内部,假设Graphics参数的名称为g,则获得当前字体的方法是: Fontfont=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格式的数字。例如: intcolor=g.getColor(); 其中g为Graphics类型的对象。 2.setColor(intRGB): 设置使用的颜色。例如: g.setColor(0x00ff0000); 3.setColor(intred,intgreen,intblue) 和上面的方法作用一样,例如: g.setColor(255,0,0); 在设置了Graphics使用的颜色以后,再进行绘制的时候,就可以绘制指定的颜色了。 在J2ME联网应用中获得客户端的手机号码 在J2ME程序开发过程中,为了一定的需要,经常需要来获得用户的手机号码,但是这个功能却在标准的J2ME类库中没有提供。 在使用中国移动的CMWAP方式连接网络时,中国移动会将用户的手机号码放在一个名称为x-up-calling-line-id的头信息中,可以通过读取该头信息,获得用户的手机号码,具体代码如下: Stringusermphone=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 packagemy.util; importjavax.wireless.messaging.*; importjavax.microedition.io.*; /** *发送文本短信息的方法 */ publicclassSMSUtil{ /** *给指定号码发送短信息 *@paramcontent短信息内容 *@paramphoneNumber手机号码 *@return发送成功返回true,否则返回false */ publicstaticbooleansend(Stringcontent,StringphoneNumber){ //返回值 booleanresult=true; try{ //地址 Stringaddress="sms://+"+phoneNumber; //建立连接 MessageConnectionconn=(MessageConnection)Connector.open(address); //设置短信息类型为文本,短信息有文本和二进制两种类型 TextMessagemsg=(TextMessage)conn.newMessage(MessageConnection.TEXT_MESSAGE); //设置信息内容 msg.setPayloadText(content); //发送 conn.send(msg); }catch(Exceptione){ result=false; //未处理 } returnresult; } }