概述
目前,很多手機已經具備了藍牙功能。雖然MIDP2.0沒有包括藍牙API,但是JCP定義了JSR82, Java APIs for Bluetooth Wireless Technology (JABWT).這是一個可選API,很多支持MIDP2.0的手機已經實現了,比如Nokia 6600, Nokia 6670,NOKIA7610等等。對於一個開發者來說,如果目標平台支持JSR82的話,在製作聯網對戰類型遊戲或者套用的時候,藍牙是一個相當不錯的選擇。本文給出了一個最簡單的藍牙套用的J2ME程式,用以幫助開發者快速的掌握JSR82。該程式分別在2台藍牙設備上安裝後,一台設備作為服務端先運行,一台設備作為客戶端後運行。在服務端上我們發布了一個服務,該服務的功能是把客戶端發過來的字元串轉變為大寫字元串。客戶端起動並搜尋到服務端的服務後,我們就可以從客戶端的輸入框裡輸入任意的字元串,傳送到服務端去,同時觀察服務端的反饋結果。本文並不具體講述藍牙的運行機制和JSR82的API結構,關於這些知識點,請參考本文的參考資料一節,這些參考資料會給你一個權威的精確的解釋。
實例代碼
該程式包括3個java檔案。一個是MIDlet,另外2個為服務端GUI和客戶端GUI。該程式已經在wtk22模擬器和NOKIA 6600,Nokia 6670兩款手機上測試通過。StupidBTMIDlet.java
import javax.microedition.lcdui.Aler
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Lis
import javax.microedition.midlet.MIDle
import javax.microedition.midlet.MIDletStateChangeException;
/**
* @author Jagie
*
* MIDlet
*/
public class StupidBTMIDlet extends MIDlet implements CommandListener {
List lis
ServerBox sb;
ClientBox cb;
/*
* (non-Javadoc)
*
* @see javax.microedition.midlet.MIDlet#startApp()
*/
protected void startApp() throws MIDletStateChangeException {
list = new List("傻瓜藍牙入門", List.IMPLICIT);
list.append("Client", null);
list.append("Server", null);
list.setCommandListener(this);
Display.getDisplay(this).setCurrent(list);
}
/**
* debug方法
* @param s 要顯示的字串
*/
public void showString(String s) {
Displayable dp = Display.getDisplay(this).getCurrent();
Alert al = new Alert(null, s, null, AlertType.INFO);
al.setTimeout(2000);
Display.getDisplay(this).setCurrent(al, dp);
}
/**
* 顯示主選單
*
*/
public void showMainMenu() {
Display.getDisplay(this).setCurrent(list);
}
protected void pauseApp() {
// TODO Auto-generated method stub
}
public void commandAction(Command com, Displayable disp) {
if (com == List.SELECT_COMMAND) {
List list = (List) disp;
int index = list.getSelectedIndex();
if (index == 1) {
if (sb == null) {
sb = new ServerBox(this);
}
sb.setString(null);
Display.getDisplay(this).setCurrent(sb);
} else {
//每次都生成新的客戶端實例
cb = null;
System.gc();
cb = new ClientBox(this);
Display.getDisplay(this).setCurrent(cb);
}
}
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO Auto-generated method stub
}
}
ClientBox.java
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Gauge;
import javax.microedition.lcdui.StringItem;
import javax.microedition.lcdui.TextField;
//jsr082 API
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgen
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
/**
* 客戶端GUI
* @author Jagie
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class ClientBox extends Form implements Runnable, CommandListener,
DiscoveryListener {
//字串輸入框
TextField input = new TextField(null, "", 50, TextField.ANY);
//loger
StringItem result = new StringItem("結果:", "");
private DiscoveryAgent discoveryAgen
private UUID【】 uuidSe
//回響服務的UUID
private static final UUID ECHO_SERVER_UUID = new UUID(
"F0E0D0C0B0A000908070605040302010", false);
//設備集合
Vector devices = new Vector();
//服務集合
Vector records = new Vector();
//服務搜尋的事務id集合
int【】 transIDs;
StupidBTMIDlet midle
public ClientBox(StupidBTMIDlet midlet) {
super("");
this.midlet=midle
this.append(result);
this.addCommand(new Command("取消",Command.CANCEL,1));
this.setCommandListener(this);
new Thread(this).start();
}
public void commandAction(Command arg0, Displayable arg1) {
if(arg0.getCommandType()==Command.CANCEL){
midlet.showMainMenu();
}else{
//匿名內部Thread,訪問遠程服務。
Thread fetchThread=new Thread(){
public void run(){
for(int i=0;irecords.size();i++){
ServiceRecord sr=(ServiceRecord)records.elementAt(i);
if(accessService(sr)){
//訪問到一個可用的服務即可
break;
}
}
}
};
fetchThread.start();
}
}
private boolean accessService(ServiceRecord sr){
boolean result=false;
try {
String url = sr.getConnectionURL(
ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);
StreamConnectionconn = (StreamConnection) Connector.open(url);
DataOutputStream dos=conn.openDataOutputStream();
dos.writeUTF(input.getString());
dos.close();
DataInputStream dis=conn.openDataInputStream();
String echo=dis.readUTF();
dis.close();
showInfo("反饋結果是:"+echo);
result=true;
} catch (IOException e) {
}
return resul
}
public synchronized void run() {
//發現設備和服務的過程中,給用戶以Gauge
Gauge g=new Gauge(null,false,Gauge.INDEFINITE,Gauge.CONTINUOUS_RUNNING);
this.append(g);
showInfo("藍牙初始化...");
boolean isBTReady = false;
try {
LocalDevice localDevice = LocalDevice.getLocalDevice();
discoveryAgent = localDevice.getDiscoveryAgent();
isBTReady = true;
} catch (Exception e) {
e.printStackTrace();
}
if (!isBTReady) {
showInfo("藍牙不可用");
//刪除Gauge
this.delete(1);
return;
}
uuidSet = new UUID;
//標誌我們的回響服務的UUID集合
uuidSet【0】 = new UUID(0x1101);
uuidSet = ECHO_SERVER_UUID;
try {
discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);
} catch (BluetoothStateException e) {
}