Witam, chcę napisać małą grę w statki na komórkę korzystającą z bluetooth do gry w trybie multiplayer. Stworzyłem więc na razie prostą aplikacje która ma za zadanie jedynie utworzyć połączenie między telefonami i wysyłać wciśnięte klawisze, jest to przykład z książki z której się uczę. Problem jednak w tym, że to cudo nie działa, mianowicie gdy na jednym urządzeniu wybiorę "Dołącz do gry" a na drugim "Stwórz grę" to owszem wykryje mi urządzenie, ale gdy je wybiorę to nic się nie zmienia, a jedynie wraca do wyszukiwania i po chwili znów pokazuje, że znalazło to samo urządzenie. Będę wdzięczny za wszelką pomoc, jest to moja pierwsza aplikacja w J2ME wiec może się na zbyt głęboką wodę rzuciłem, ale przecież tylko tak można nauczyć się pływać ;) Oto kod poszczególnych klas:
package hello;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class BattleShip extends MIDlet implements CommandListener {
private Display display;
public BattleShip() {
display = Display.getDisplay(this);
}
public Display getMidletDisplay(){
return display;
}
public void startApp() {
String name;
ClientServerSelect select = new ClientServerSelect(this);
display.setCurrent(select);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void exit(){
destroyApp(false);
notifyDestroyed();
}
public void commandAction(Command c, Displayable s) {
switch(c.getCommandType()){
case Command.EXIT:
exit();
break;
}
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hello;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
/**
*
* @author Maniek
*/
public class BluetoothConnection {
private StreamConnection streamConnection;
private InputStream inputStream;
private OutputStream outputStream;
private String localName;
private String remoteName;
private String url;
public BluetoothConnection(StreamConnection con, String ln, String rn) throws IOException{
localName = ln;
remoteName = rn;
url = "";
streamConnection = con;
openStreams();
}
public BluetoothConnection(String urlStrings, String ln, String rn) throws IOException{
localName = ln;
remoteName = rn;
url = urlStrings;
connect();
}
private void connect() throws IOException{
streamConnection = (StreamConnection) Connector.open(url);
openStreams();
}
private void openStreams() throws IOException{
inputStream = streamConnection.openInputStream();
outputStream = streamConnection.openOutputStream();
}
synchronized public void close(){
try{
outputStream.close();
inputStream.close();
if(streamConnection != null){
streamConnection.close();
streamConnection = null;
}
}
catch(IOException e){}
}
public void writeInt(int c) throws IOException{
outputStream.write((int)c);
outputStream.flush();
}
public int readInt() throws IOException{
return inputStream.read();
}
public String getLocalName() { return localName;}
public String getRemoteName() { return remoteName;}
protected void setRemoteName(String rn) {remoteName = rn;}
public boolean isClosed() {return streamConnection == null;}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hello;
import java.util.Vector;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.TextBox;
/**
*
* @author Maniek
*/
public class ClientConnectionScreen implements CommandListener, DiscoveryListener {
private Vector znalezione = new Vector();
private Vector usługi = new Vector();
private static final int MAJOR_DEVICE_CLASS_PHONE = 0x0200;
private static final int SERVICE_NAME_BASE_LANGUAGE = 0x0100;
private final String serviceUUID = "C7E0AF6060F111DFA08A0800200C9A66";
private final int serviceAttributes [] = {SERVICE_NAME_BASE_LANGUAGE};
BattleShip midlet;
private DiscoveryAgent discoveryAgent;
public ClientConnectionScreen(BattleShip midlet){
this.midlet = midlet;
TextBox tb = new TextBox("Proszę czekać...","Poszukuję graczy...",50,0);
midlet.getMidletDisplay().setCurrent(tb);
try{
discoveryAgent = LocalDevice.getLocalDevice().getDiscoveryAgent();
}
catch(Exception e){
String message = "Błąd przy próbie uzyskania właściwości urządzenia: "+e.getMessage();
System.out.println(message);
}
try{
discoveryAgent.startInquiry(DiscoveryAgent.LIAC, this);
}
catch(BluetoothStateException e){
System.out.println("Błąd zapytania");
}
}
public void commandAction(Command c, Displayable d) {
if(c.getCommandType() == Command.CANCEL)
{
midlet.startApp();
}
}
public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
if(cod.getMajorDeviceClass() == MAJOR_DEVICE_CLASS_PHONE){
if(!znalezione.contains(btDevice)){
znalezione.addElement(btDevice);
}
}
}
public void inquiryCompleted(int discType) {
UUID[] serviceUidsToSearch = new UUID[]{
new UUID(serviceUUID,false)};
if(discType == INQUIRY_COMPLETED){
if(znalezione.size()!=0){
for(int i = 0; i<znalezione.size();i++){
try{
discoveryAgent.searchServices(serviceAttributes, serviceUidsToSearch, (RemoteDevice)znalezione.elementAt(i), this);
}
catch(BluetoothStateException e){
System.out.println("Błąd usługi");
}
}
}
else{
midlet.startApp();
}
}
}
public void serviceSearchCompleted(int transID, int respCode) {
new SearchResult(midlet,usługi);
}
public void servicesDiscovered(int transID, ServiceRecord[] servRec) {
usługi.addElement(servRec[0]);
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hello;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
/**
*
* @author Maniek
*/
public class ClientServerSelect extends List implements CommandListener {
private BattleShip midlet;
public ClientServerSelect(BattleShip midlet){
super("Wybierz rolę:",List.IMPLICIT);
this.midlet = midlet;
append("Dołącz do gry",null);
append("Stwórz grę",null);
addCommand(new Command("Wybierz",Command.OK,1));
addCommand(new Command("Wyjdź",Command.EXIT,1));
setCommandListener(this);
}
public void commandAction(Command c, Displayable d) {
if(c.equals(List.SELECT_COMMAND) || (c.getCommandType() == Command.OK)){
int i = getSelectedIndex();
String s = getString(i);
if(s.equals("Dołącz do gry")){
new ServerConnectionScreen(midlet);
}
else if(s.equals("Stwórz grę")){
new ClientConnectionScreen(midlet);
}
}
else if(c.getCommandType() == Command.EXIT){
midlet.exit();
}
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hello;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Vector;
import javax.microedition.lcdui.*;
/**
*
* @author Maniek
*/
public class NumberCanvas extends Canvas implements CommandListener{
private BluetoothConnection[] btConnections;
private BattleShip midlet;
private boolean isServer;
private Vector consoleStrings = new Vector();
private static final int numRowsInConsole = 6;
public NumberCanvas(BluetoothConnection[] btConns, BattleShip _midlet, boolean _isServer)
{
midlet = _midlet;
isServer = _isServer;
btConnections = btConns;
for(int i=0; i<btConnections.length; i++){
ReceiveThread rt = new ReceiveThread(i);
rt.start();
}
addCommand(new Command("Wyjdz", Command.CANCEL, 1));
setCommandListener(this);
}
public BluetoothConnection getConnection(int index){
return btConnections[index];
}
public void commandAction(Command c, Displayable s){
if(c.getCommandType()==Command.CANCEL){
close();
midlet.startApp();//startUI
}
}
private synchronized void close(){
for(int i=0; i<btConnections.length; i++){
btConnections[i].close();
}
}
public void updateRemoteChar(int index, int c){
if(true == isServer){
for(int i=0; i<btConnections.length; i++){
if(i != index)
sendIntegerToPeer(i,(int)c);
}
}
Log("Przeslano do mnie: " +c);
}
private void sendIntegerToPeer(int peerIndex, int c)
{
BluetoothConnection connection = btConnections[peerIndex];
try{
connection.writeInt(c);
}catch(IOException e){
connection.close();
}
}
class ReceiveThread extends Thread
{
private int index;
public ReceiveThread(int i){
index = i;
}
public void run()
{
int inp;
while(true){
try{
inp = getConnection(index).readInt();
}catch(IOException e){
getConnection(index).close();
return;
}
if( inp == -1){
getConnection(index).close();
return;
}
updateRemoteChar(index, inp);
}
}
}
public void paint(Graphics g){
drawConsole(g);
}
public void keyPressed(int keyCode){
byte c;
switch(keyCode){
case KEY_NUM0: c = 0; break;
case KEY_NUM1: c = 1; break;
case KEY_NUM2: c = 2; break;
case KEY_NUM3: c = 3; break;
case KEY_NUM4: c = 4; break;
case KEY_NUM5: c = 5; break;
case KEY_NUM6: c = 6; break;
case KEY_NUM7: c = 7; break;
case KEY_NUM8: c = 8; break;
case KEY_NUM9: c = 9; break;
default: return;
}
if(true==isServer){
for(int i=0; i<btConnections.length; i++)
{
sendIntegerToPeer(i,c);}
}else {
sendIntegerToPeer(0, c);
}
Log("Nacisnolem klawisz: " + c);
}
private void Log(String message){
consoleStrings.addElement(message);
while(consoleStrings.size()> numRowsInConsole)
consoleStrings.removeElementAt(0);
repaint();
serviceRepaints();
}
private void drawConsole(Graphics g){
Font f;
int y,h;
g.setColor(255, 255, 255);
g.fillRect(0,0,getWidth(), getHeight());
g.setColor(0,0,255);
f = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM);
g.setFont(f);
y=0; h=16;
for(int i=0; i<consoleStrings.size(); i++){
g.drawString((String)consoleStrings.elementAt(i),0 , y, Graphics.TOP | Graphics.LEFT);
y+=h;
}
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hello;
import java.io.IOException;
import java.util.Vector;
import javax.bluetooth.DataElement;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.ServiceRecord;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.List;
/**
*
* @author Maniek
*/
public class SearchResult extends List implements CommandListener {
private Command createGame;
private Command mainMenu;
private Command searchAgain;
private BattleShip midlet;
private Vector znalezioneUsługi;
private static final int SERVICE_NAME_BASE_LANGUAGE = 0x0100;
public SearchResult(BattleShip midlet, Vector usługi){
super("Wybierz:",List.IMPLICIT);
this.midlet = midlet;
znalezioneUsługi = usługi;
createGame = new Command("Stworz grę",Command.OK,1);
mainMenu = new Command("Menu",Command.EXIT,1);
searchAgain = new Command("Szukaj ponownie",Command.SCREEN,1);
addCommand(createGame);
addCommand(mainMenu);
addCommand(searchAgain);
setCommandListener(this);
addFoundServicesToSelectionList();
midlet.getMidletDisplay().setCurrent(this);
}
private void addFoundServicesToSelectionList(){
System.out.println("Znaleziono: "+znalezioneUsługi.size());
for(int i = 0 ; i<znalezioneUsługi.size();i++){
ServiceRecord sr = (ServiceRecord) znalezioneUsługi.elementAt(i);
DataElement de = sr.getAttributeValue(SERVICE_NAME_BASE_LANGUAGE);
String rname = (String) de.getValue();
append(rname,null);
}
}
private void makeConnections(){
int i = getSelectedIndex();
ServiceRecord selected = (ServiceRecord) znalezioneUsługi.elementAt(i);
MakeConnectionsThread t = new MakeConnectionsThread(selected);
t.start();
}
public void commandAction(Command c, Displayable s){
int com = c.getCommandType();
switch(com){
case Command.OK:
makeConnections();
break;
case Command.EXIT:
midlet.startApp();
break;
default:
ClientConnectionScreen ccs = new ClientConnectionScreen(midlet);
break;
}
}
public void devicesConnected(BluetoothConnection[] connections){
//nowy ekran gry
NumberCanvas nc = new NumberCanvas(connections,midlet,true);
midlet.getMidletDisplay().setCurrent(nc);
}
private class MakeConnectionsThread extends Thread{
ServiceRecord selected;
MakeConnectionsThread(ServiceRecord selected){
this.selected = selected;
}
public void run(){
BluetoothConnection[] btConnections = new BluetoothConnection[1];
try{
String connectionURL = selected.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT,false);
DataElement de = selected.getAttributeValue(SERVICE_NAME_BASE_LANGUAGE);
String rname = (String) de.getValue();
String localName = LocalDevice.getLocalDevice().getFriendlyName();
btConnections[0] = new BluetoothConnection(connectionURL,localName,rname);
// btConnections[0].writeString(localName);
}
catch(IOException e){
System.out.println("Błąd przy próbie utworzenia połaczenia");
}
devicesConnected(btConnections);
}
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package hello;
import java.util.Timer;
import java.util.TimerTask;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
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;
/**
*
* @author Maniek
*/
public class ServerConnectionScreen extends TimerTask implements CommandListener{
private static final int MAX_BAR_VALUE = 10;
private static final int TIMER_FREQUENCY = 200;
private final String serviceUUID = "C7E0AF6060F111DFA08A0800200C9A66";
private final String connectionParameters = ";authorize=false;authenticate=false;encrypt=false";
BattleShip midlet;
private Gauge gauge;
private Timer taskTimer;
private LocalDevice localDevice;
private StreamConnectionNotifier notifier;
private String localName;
private int previousDiscoverabilityMode = -1;
public ServerConnectionScreen(BattleShip midlet){
this.midlet = midlet;
gauge = new Gauge("Czekam na połączenie...",false,MAX_BAR_VALUE,0);
Command cmdStop = new Command("Anuluj",Command.CANCEL,1);
Form form = new Form("");
form.append(gauge);
form.addCommand(cmdStop);
form.setCommandListener(this);
midlet.getMidletDisplay().setCurrent(form);
taskTimer = new Timer();
taskTimer.scheduleAtFixedRate(this, 0, TIMER_FREQUENCY);
try{
localDevice = LocalDevice.getLocalDevice();
}
catch(Exception e){
localDevice = null;
return;
}
try{
localName = LocalDevice.getLocalDevice().getFriendlyName();
saveDiscoverability();
localDevice.setDiscoverable(DiscoveryAgent.LIAC);
}
catch(BluetoothStateException e){
return;
}
AcceptAndOpenThread t = new AcceptAndOpenThread();
t.start();
}
private void saveDiscoverability(){
try{
previousDiscoverabilityMode = LocalDevice.getLocalDevice().getDiscoverable();
}
catch(Exception e) {}
}
private void restoreDiscoverability(){
try{
if(previousDiscoverabilityMode != -1){
localDevice.setDiscoverable(previousDiscoverabilityMode);
}
}
catch(Exception e) {}
}
public void run() {
int time = gauge.getValue()+1;
if(time>gauge.getMaxValue()){
time = 0;
}
gauge.setValue(time);
}
protected void stop(){
cancel();
taskTimer.cancel();
}
public void connectionDiscoveryFinished(BluetoothConnection btConnection){
restoreDiscoverability();
if(btConnection == null){
stop();
midlet.startApp();
}
else{
//ekran gry
NumberCanvas nc = new NumberCanvas(new BluetoothConnection[]{btConnection},midlet,false);
midlet.getMidletDisplay().setCurrent(nc);
stop();
}
}
public void commandAction(Command c, Displayable d) {
switch(c.getCommandType()){
case Command.CANCEL:
closeNotifier();
stop();
restoreDiscoverability();
midlet.startApp();
break;
}
}
synchronized private void closeNotifier(){
if(notifier != null){
try{
notifier.close();
}
catch(Exception e){
notifier = null;
}
}
}
private class AcceptAndOpenThread extends Thread{
public void run(){
BluetoothConnection btConnection;
try{
notifier = (StreamConnectionNotifier) Connector.open("btspp://localhost:"+serviceUUID+";name="+localName+connectionParameters);
StreamConnection streamConnection = (StreamConnection) notifier.acceptAndOpen();
btConnection = new BluetoothConnection(streamConnection,localName,"Host");
}
catch(Exception e){
btConnection = null;
}
closeNotifier();
connectionDiscoveryFinished(btConnection);
}
}
}