程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> J2ME >> 開發J2ME聯網應用程序

開發J2ME聯網應用程序

編輯:J2ME

  盡管目前的無線網絡不夠理想,手機聯網還是給我們開發人員不小的震撼的。畢竟這真的是件神奇的事情,不是嗎?本文將講述如何應用J2ME平台中的通用聯網框架開發聯網的應用程序。

  首先,必須說明一點:MIDP中規定,任何移動信息設備都必須提供通過http協議的支持,而像其他的通信方式例如socket是設備相關的。有些手機會支持,有些則不支持。這裡只大概的說明一下http協議相關的內容,如果不了解這個方面的知識請參考http協議。在Javax.microedition.io裡面是大量的接口,只有一個connector類,當然在midp2.0裡面添加了對push技術的支持,這個留做以後講。connector類提供的最重要的方法是open()方法,它的返回值為Connection,你可以對他進行轉換得到你需要的類型,比如我們以http協議訪問服務器。

void postViaHttpConnection(String url) throws IOException {
    HttpConnection c = null;
    InputStream is = null;
    OutputStream os = null;
    int rc;
    try {
      c = (HttpConnection)Connector.open(url);
      // Set the request method and headers
      c.setRequestMethod(HttpConnection.POST);
      c.setRequestProperty("If-ModifIEd-Since",
        "29 Oct 1999 19:43:31 GMT");
      c.setRequestProperty("User-Agent",
        "Profile/MIDP-2.0 Configuration/CLDC-1.0");
      c.setRequestProperty("Content-Language", "en-US");
      // Getting the output stream may flush the headers
      os = c.openOutputStream();
      os.write("LIST gamesn".getBytes());
      os.flush();      // Optional, getResponseCode will flush
      // Getting the response code will open the connection,
      // send the request, and read the HTTP response headers.
      // The headers are stored until requested.
      rc = c.getResponseCode();
      if (rc != HttpConnection.HTTP_OK) {
        throw new IOException("HTTP response code: " + rc);
      }
      is = c.openInputStream();
      // Get the ContentType
      String type = c.getType();
      processType(type);
      // Get the length and process the data
      int len = (int)c.getLength();
      if (len > 0) {
         int actual = 0;
         int bytesread = 0 ;
         byte[] data = new byte[len];
         while ((bytesread != len) && (actual != -1)) {
          actual = is.read(data, bytesread, len - bytesread);
          bytesread += actual;
         }
        process(data);
      } else {
        int ch;
        while ((ch = is.read()) != -1) {
          process((byte)ch);
        }
      }
    } catch (ClassCastException e) {
      throw new IllegalArgumentException("Not an HTTP URL");
    } finally {
      if (is != null)
        is.close();
      if (os != null)
        os.close();
      if (c != null)
        c.close();
    }
  }

  上面的代碼是我取自API doc(建議多讀一下api doc)。

  下面根據自己的經驗說明一下聯網中比較重要的問題:

  我們應該明白這是如何工作的,手機發送請求通過無線網絡傳輸到運營商的WAP網關,WAP網關將請求轉發到web服務器,服務器可以用CGI,ASP,servlet/JSP等構建。服務器處理後會把響應轉發到WAP網關,WAP網關再把它發送到手機上。WAP網關對我們開發人員來說是透明的我們不用管它。

  如果在你的聯網程序上看不到Thread,Runnable這樣的字眼,那麼你的程序是不能運行的。因為考慮到網絡的因素,為了避免操作堵塞。你必須把聯網動作放到另外一個線程去運行,而不能在主線程運行。最好當聯網的時候提供給用戶一個等待的界面比如作一個動畫界面。我下面提供的例子中沒有用,因為我想把這個單獨出來以後談。

  通常聯網的應用程序的界面是比較多的,最好我們使用MVC的模式來實現界面的導航。關於這個方面的說明我以前有文章講述

  考慮好你想如何傳遞你數據,這一點是非常重要的。你可以用GET方法也可以使用POST方法,推薦後者。因為get方法只能是通過URL編碼的傳輸。而POST更加靈活,配合DataInputStream、DataOutputStream來使用更是方便。必須清楚我們如何接受數據是跟數據如何發送過來相關的,例如在clIEnt端writeUTF(message);writeInt(4);writeBoolean(true),那麼接受就應該readUTF();readInt();readBoolean();如果發送過來數據長度是可用的,那麼我們可以建立一個適當的數組來接受,如果不可用我們就要一個適當容量的數組來接受。

  下面我提供一個實例來說明以上的問題,在應用程序中我們輸入任意字符,通過連接server得到響應並顯示出來。server我用servlet寫的非常簡單,只是在受到的內容後面加上“haha”,程序我安裝到自己的手機上運行沒有任何問題,就是GPRS網絡不夠快。Server是tomcat5實現的,關於如何部署servlet的問題超出了本文的討論范圍。我只提供代碼,推薦用Eclipse+Lomboz開發J2EE程序。

package com.north;
import Java.io.DataInputStream;
import Java.io.DataOutputStream;
import Java.io.IOException;
import Javax.servlet.ServletException;
import Javax.servlet.http.HttpServlet;
import Javax.servlet.http.HttpServletRequest;
import Javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
 HttpServletResponse response) throws ServletException, IOException {
 DataInputStream dis = new DataInputStream(request.getInputStream());
 String result = dis.readUTF();
 DataOutputStream DOS = new DataOutputStream(response.getOutputStream());
 DOS.writeUTF(result+"haha");
 DOS.close();
 dis.close();
 }
protected void doPost(HttpServletRequest request,
 HttpServletResponse response) throws ServletException, IOException {
 doGet(request,response);
 }
}

  聯網的時候一定按照如下的流程做

  建立連接,設置傳輸方式推薦POST,設置方法頭

  打開輸出流,傳輸數據給服務器

  判斷相應的狀態碼,進入不同流程控制,注意錯誤處理。如果OK則開始接受數據

  關閉連接和流

  下面是客戶端的代碼,對錯誤處理沒有考慮太多。一共是5個class

import Javax.microedition.midlet.MIDlet;
import Javax.microedition.midlet.MIDletStateChangeException;
  
public class HttpCommMIDlet extends MIDlet
{
  
  private UIController uicontroller;
 
  protected void startApp() throws MIDletStateChangeException
  {
        uicontroller = new UIController(this);
    uicontroller.init();
  
  }
  
  protected void pauseApp()
  {
      }
  
  protected void destroyApp(boolean arg0) throws MIDletStateChangeException
  {
  
  }
  
}
import Java.io.IOException;
  
import Javax.microedition.lcdui.Display;
import Javax.microedition.lcdui.Displayable;
public class UIController
{
  
  private HttpCommMIDlet midlet;
  private InputCanvas inputUI;
  private DisplayCanvas displayUI;
  private Display display;
  private HttpCommHandler httpHandler;
  
public UIController(HttpCommMIDlet midlet)
  {
    this.midlet = midlet;
    
  }
  
  public static class EventID
  {
    public static final int CONNECT_TO_SERVER = 0;
    public static final int DISPLAY_BACK_TO_INPUT = 1;
  }
  
  public void init()
  {
    display = Display.getDisplay(midlet);
    httpHandler = new HttpCommHandler(
        "http://yourip:8088/http/myservlet");
    inputUI = new InputCanvas(this);
    displayUI = new DisplayCanvas(this);
    display.setCurrent(inputUI);
  }
  
  public void setCurrent(Displayable disp)
  {
    display.setCurrent(disp);
  }
  
  public void handleEvent(int EventID, Object[] obj)
  {
    new EventHandler(EventID, obj).start();
  }
  
  private class EventHandler extends Thread
  {
    private int eventID;
    private Object[] obj;
    private Displayable backUI;
  
    public EventHandler(int eventID, Object[] obj)
    {
      this.eventID = eventID;
      this.obj = obj;
    }
  
    public void run()
    {
      synchronized (this)
      {
        run(eventID, obj);
      }
    }
  
    private void run(int eventID, Object[] obj)
    {
      switch (eventID)
      {
        case EventID.CONNECT_TO_SERVER:
        {
          try
          {
  
            String result = httpHandler
                .sendMessage((String) obj[0]);
            displayUI.init(result);
            setCurrent(displayUI);
            break;
          } catch (IOException e)
          {
            
          }
        }
        case EventID.DISPLAY_BACK_TO_INPUT:
        {
          setCurrent(inputUI);
          break;
        }
        default:
          break;
      }
    }
  };
  
}
  
import Javax.microedition.lcdui.Command;
import Javax.microedition.lcdui.CommandListener;
import Javax.microedition.lcdui.Displayable;
import Javax.microedition.lcdui.Form;
import Javax.microedition.lcdui.StringItem;
import Javax.microedition.lcdui.TextFIEld;
  
public class InputCanvas extends Form implements CommandListener
{
  private UIController uicontroller;
  private TextField inputFIEld;
  private StringItem result;
  public static final Command okCommand = new Command("OK", Command.OK, 1);
  
  public InputCanvas(UIController uicontroller)
  {
    super("Http Comunication");
    this.uicontroller = uicontroller;
    inputField = new TextField("Input:", null, 20, TextFIEld.ANY);
    this.append(inputFIEld);
    this.addCommand(okCommand);
    this.setCommandListener(this);
  }
  
  public void commandAction(Command arg0, Displayable arg1)
  {
    
    if (arg0 == okCommand)
    {
      String input = inputFIEld.getString();
      uicontroller.handleEvent(UIController.EventID.CONNECT_TO_SERVER,
          new Object[] { input });
    }
  
  }
  
}
  
import Java.io.*;
  
import Javax.microedition.io.Connector;
import Javax.microedition.io.HttpConnection;
  
public class HttpCommHandler
{
  private String URL;
  
  public HttpCommHandler(String URL)
  {
    this.URL = URL;
  }
  
  public String sendMessage(String message) throws IOException
  {
    HttpConnection httpConn;
    DataInputStream input;
    DataOutputStream output;
    String result;
    try
    {
      httpConn = open();
      output = this.openDataOutputStream(httpConn);
      output.writeUTF(message);
      output.close();
      input = this.openDataInputStream(httpConn);
      result = input.readUTF();
      closeConnection(httpConn,input,output);
      return result;
  
}
  
    finally
    {
  
    }
  
  }
  
  public HttpConnection open() throws IOException
  {
    try
    {
      HttpConnection connection = (HttpConnection) Connector.open(URL);
  
      connection.setRequestProperty("User-Agent", System
          .getProperty("microedition.profiles"));
      connection.setRequestProperty("Content-Type",
          "application/octet-stream");
      connection.setRequestMethod(HttpConnection.POST);
  
      return connection;
    } catch (IOException ioe)
    {
  
      throw ioe;
    }
  
  }
  
  private DataInputStream openDataInputStream(HttpConnection conn)
      throws IOException
  
  {
    int code = conn.getResponseCode();
    if (code == HttpConnection.HTTP_OK)
    {
      return conn.openDataInputStream();
    } else
    {
      throw new IOException();
    }
  }
  
  private DataOutputStream openDataOutputStream(HttpConnection conn)
      throws IOException
  {
    return conn.openDataOutputStream();
  }
  
  private void closeConnection(HttpConnection conn, DataInputStream dis,
      DataOutputStream DOS)
  {
    if(conn!= null)
    {
      try
      {
        conn.close();
      }
      catch(IOException e)
      {}
    }
    
    if(dis!=null)
    {
      try
      {
        dis.close();
      }
      catch(IOException e)
      {}
    }
    
    if(DOS!=null)
    {
      try
      {
        DOS.close();
      }
      catch(IOException e)
      {}
    }
    
  }
  
}
  
import Javax.microedition.lcdui.Command;
import Javax.microedition.lcdui.CommandListener;
import Javax.microedition.lcdui.Displayable;
import Javax.microedition.lcdui.Form;
import Javax.microedition.lcdui.StringItem;
  
public class DisplayCanvas extends Form implements CommandListener
{
  private UIController uicontroller;
  private StringItem result;
  private int index = 0;
  private boolean first = true;
  public static Command backCommand = new Command("Back", Command.BACK, 2);
  
  public DisplayCanvas(UIController uicontroller)
  {
    super("Result");
    this.uicontroller = uicontroller;
    result = new StringItem("you have input:", null);
    this.addCommand(backCommand);
    this.setCommandListener(this);
  
  }
  
  public void init(String message)
  {
    if (first)
    {
      result.setText(message);
      index = this.append(result);
      first = false;
    }
    else
    {
      this.delete(index);
      result.setText(message);
      this.append(result);
    }
  
  }
  
  public void commandAction(Command arg0, Displayable arg1)
  {
    uicontroller.handleEvent(UIController.EventID.DISPLAY_BACK_TO_INPUT,
        null);
  
  }
  
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved