[转帖]J2ME程序开发全方位基础讲解汇总

一、J2ME中需要的Java基础知识
       现在有大部分人,都是从零开始学J2ME的,学习J2ME的时候,总是从Java基础开始学习,而且现在讲Java基础的书籍中都是以J2SE来讲基础,这就给学习造成了一些不必要的麻烦,下面将J2ME中用到的和不需要的Java基础知识做一个简单的说明。
       J2ME中使用到的Java基础知识:
    1、Java语法基础:包括基本数据类型、关键字、运算符等等
    2、面向对象的思想:类和对象的概念,继承和多态等等。
    3、异常处理
    4、多线程
  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)
{
     //取子串的起始位置
     int startIndex = 0;
     //将结果数据先放入Vector中
     Vector v = new Vector();
     //返回的结果字符串数组
     String[] str = null;
     //存储取子串时起始位置
     int index = 0;

     //获得匹配子串的位置
     startIndex = original.indexOf(regex);
     //System.out.println("0" + startIndex);
     //如果起始字符串的位置小于字符串的长度,则证明没有取到字符串末尾。
     //-1代表取到了末尾
     while(startIndex < original.length() && startIndex != -1)
     {
           String temp = 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 = new String[v.size()];
     for(int i=0;i
     {
          str[i] = (String)v.elementAt(i);
     }
    
     //返回生成的数组
     return str;
}

十一、J2ME在低级用户界面上分行显示文字
  在J2ME的低级用户界面开发中,经常会遇到需要在Canvas上显示大量的文字,例如关于界面、游戏说明、游戏公告等信息。如果在设计时,将文字的内容和长度都固定,既不利于修改也不利于维护。下面介绍一个简单的方法,实现一个简单、可维护性强的方式。
  实现方法:
    1、将需要显示的所有信息做成一个字符串。
    2、编写一个将该字符串按照要求转换为字符串数组的方法。
    3、将转换后的数组以循环的方式显示在Canvas上。
  通过这样三个步骤,则修改显示的信息时,只需要修改包含显示信息的字符串即可,自己书写的方法可以按照以前的标准重新分割新的字符串。如果需要修改每行显示的字符个数,则只需要修改自己书写的方法即可。
  通过这样一种实现方式,可以很方便的实现显示一些比较长的文本信息,即使是可变长度的字符串也没有问题。

十二、J2ME中使用记录存储系统(RMS)存储信息
  在MIDP中,没有文件的概念,所以永久存储一般只能依靠记录存储系统实现,关于记录存储系统的简介,可以参看教程:http://www-900.ibm.com/developerWorks/cn/java/j-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/javaworld/jw-12-2002/jw-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
{
  private Player player = null;
  /** Constructor */
  public SoundMIDlet()
       {
             try
             {
                   InputStream is = this.getClass().getResourceAsStream("/Autorun.wav");
                   player = Manager.createPlayer(is,"audio/x-wav");
             }
             catch(IOException e)
             {
                   System.out.println("1:" + e);
             }
             catch(MediaException e)
             {
                   System.out.println("2:" + e);
             }
             catch(Exception e)
             {
                   System.out.println("3:" + e);
             }
      }

      /** Main method */
      public void startApp()
      {
             if(player != null)
             {
                   try
                   {
              player.start();
                   }
                   catch(MediaException e)
                   {
              System.out.println("4:" + e);
                   }
             }
       }

       /** Handle pausing the MIDlet */
       public void pauseApp()
       {
       }

       /** Handle destroying the MIDlet */
       public void destroyApp(boolean unconditional)
       {
       }
}

十五、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/sme/jive/thread.jsp?forum=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
package first3d;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class First3DMIDlet extends MIDlet
{
      private First3DCanvas displayable = new First3DCanvas();
      public void startApp()
      {
            Display.getDisplay(this).setCurrent(displayable);
      }

      public void pauseApp() {}

      public void destroyApp(boolean unconditional) {}
}

// First3Dcanvas.java
package first3d;
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
import java.util.*;
/**
* 第一个3D程序
*/
public class First3DCanvas extends Canvas implements Runnable
{
      /**World对象*/
      private World myWorld = null;
      /**Graphics3D对象*/
      private Graphics3D g3d = Graphics3D.getInstance();
      /**Camera对象*/
      private Camera cam = null;
      private int viewport_x;
      private int viewport_y;
      private int viewport_width;
      private int viewport_height;
      private long worldStartTime = 0;
      //重绘时间
      private int validity = 0;
     
      public First3DCanvas()
      {
            //启动重绘界面的线程
            Thread thread = new Thread(this);
            thread.start();
            try
            {
                   //导入3D图片
                   myWorld = (World) Loader.load("/swerve.m3g")[0];
                   viewport_x = 0;
                   viewport_y = 0;
                   viewport_width = getWidth();
                   viewport_height = getHeight();
                   cam = myWorld.getActiveCamera();
                   //设置cam对象
                   float[] params = new float[4];
                   int type = cam.getProjection(params);
                   if (type != Camera.GENERIC)
                   {
                          //calculate window aspect ratio
                          float waspect = viewport_width / viewport_height;
                          if (waspect < params[1])
                          {
                                float height = viewport_width / params[1];
                                viewport_height = (int) height;
                                viewport_y = (getHeight() - viewport_height) / 2;
                          }
                          else
                          {
                                float width = viewport_height * params[1];
                                viewport_width = (int) width;
                                viewport_x = (getWidth() - viewport_width) / 2;
                          }
                   }
                   worldStartTime = System.currentTimeMillis();
            }
            catch (Exception e) {}
      }
     
      protected void paint(Graphics g)
      {
            //清除背景
            g.setColor(0x00);
            g.fillRect(0, 0, getWidth(), getHeight());
            //和3D对象绑定
            g3d.bindTarget(g);
            g3d.setViewport(viewport_x, viewport_y, viewport_width, viewport_height);
            long startTime = System.currentTimeMillis() - worldStartTime;
            validity = myWorld.animate((int)startTime);
            try
            {
                   g3d.render(myWorld);
            }
            finally
            {
                   g3d.releaseTarget();
            }
      }

      public void run()
      {
            try
            {
                   while(true)
                   {
                         //重绘图形
                         repaint(viewport_x, viewport_y, viewport_width, viewport_height);
                   }
            }
            catch(Exception e){}
      }
}

十七、在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>
  </card>
  </wml>
  你可以将以上代码保存在WEB服务器上,例如保存为text.wml
  3、修改jad文件:
  在jad文件中增加 MIDlet-Jar-URL: http://domain/directory/test.jar
  其中的http://domain/directory/test.jar为你的jar文件的路径。
  经过上面的设置,你就可以将你的wml页面路径作为你的WAP下载页面发布了。用户只需要在手机上输入这个路径就可以访问和下载你的程序了。
作者Blog:http://blog.csdn.net/Mailbomb/

相关推荐
这是本新书,有中文版。我看了下内容,挺好的,介绍了用Midp1.0实现2.0的Game API。找到了英文版的书 不知道站上有没有人发过。个人觉得很有参考价值。为论坛做贡献,把连接发上来吧。希望斑竹能注意一下。 这书真的不错,给大家推荐一下。 第1部分 什么是J2ME 第1章 J2ME的历史 1.1 Java Oak 1.2 Java在Sun公司的成长 1.3 什么是Java 1.4 Java的多个版本 1.5 到处都是微型设备 1.6 小型软件 1.7 结语 第2章 J2ME概述 2.1 J2ME 2.2 J2ME体系结构 2.3 MIDP 2.4 MIDP 2.0 2.5 结语 第3章 支持J2ME的设备 3.1 移动设备总览 3.2 结语 第2部分 代码 第4章 开发环境 4.1 获取工具 4.2 安装工具 4.3 MIDlet预热 4.4 创建包 4.5 J2ME WTK 4.6 使用其他开发环境 4.7 结语 第5章 J2ME API 5.1 MIDP API概述 5.2 MIDlet应用程序 5.3 使用定时器 5.4 网络 5.5 永久性数据(RMS) 5.6 用户界面(LCDUI) 5.7 结语 第6章 设备专用库 6.1 设备专用库 6.2 诺基亚 6.3 西门子 6.4 摩托罗拉 6.5 其他扩展 6.6 结语 第7章 游戏时间 7.1 游戏时间 7.2 游戏设计 7.3 应用程序类 7.4 菜单 7.5 游戏屏幕 7.6 游戏循环 7.7 加入图像 7.8 角色 7.9 输入处理 7.10 碰撞检测 7.11 游戏结束 7.12 结语 第3部分 游戏开发 第8章 游戏项目 8.1 游戏发展情况 8.2 游戏类型 8.3 设计自己的游戏 8.4 开发进程 8.5 你的思路 8.6 结语 第9章 图像 9.1 精灵基础知识 9.2 高级精灵处理 9.3 结语 第10章 动作 10.1 动作 10.2 基本的运动 10.3 以某个夹角方向运动 10.4 高级运动 10.5 碰撞检测 10.6 角色 10.7 敌人 10.8 结语 第11章 游戏世界 11.1 游戏世界 11.2 创建一个图块引擎 11.3 构建游戏世界 11.4 高级对象管理技术 11.5 结语 第12章 游戏 12.1 游戏屏幕 12.2 游戏状态 12.3 游戏的主角 12.4 处理损伤 12.5 进度的存储和加载 12.6 结语 第13章 游戏前端 13.1 前端概述 13.2 应用程序类 13.3 菜单 13.4 闪屏 13.5 结语 第14章 设备移植 14.1 定制诺基亚版本 14.2 构建系统 14.3 多设备构建 14.4 结语 第15章 优化 15.1 速度,完美的速度 15.2 优化 15.3 结语 第16章 本地化 16.1 本地化处理 16.2 结语 第4部分 销售、销售,还是销售 第17章 商业材料 17.1 游戏指南 17.2 为游戏截图 17.3 为游戏录制动画 17.4 公司介绍 17.5 结语 第18章 销售渠道 18.1 J2ME商业模型 18.2 通向市场之路 18.3 接触发行商的方式 18.4 交易 18.5 结语 第5部分 下面是什么 第19章 CLDC 1.1和MIDP 2.0 19.1 下一代MIDP 19.2 MIDP 2.0 程序开发 19.3 声音 19.4 增强的LCDUI 19.5 游戏API 19.6 通信 19.7 结语 第20章 isometric游戏 20.1 什么是isometric投影 20.2 图形 20.3 结语 第21章 光线投射 21.1 什么是光线投射 21.2 基本原理 21.3 引擎 21.4 高级特性 21.5 结语 第22章 网络连接 22.1 移动连接 22.2 联网游戏 22.3 一个简单的网络MIDlet 22.4 服务端 22.5 星际大战的在线排行榜 22.6 高级网络编程 22.7 结语 附录A Java 2入门 A1 Java 2 A2 Java程序 A3 对象无处不在 A4 基本语法 A5 面向对象高级编程技术 A6 异常 A7 Package、Import和CLASSPATH
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页