J2ME Bluetooth

0

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);
        }
    }

}
0

Witam

Również korzystam z tej książki i z programu od Ciebie z minimalnymi zmianami. Do połaczenia wykorzystuje nokie e61 oraz nokie 6103.
W przypadku gdy w nokii e61 robie "stwórz grę" a w nokii 6301 "dołącz do gry", urzadzenia się wyszukują program jest odpalany. Na ekranie e61 zostaje wypisana informacja o nacisnietym danym klawiszu w noki 6301.
W przypadku gdy w nokii 6301 robie "stwórz grę" a w nokii e61 "dołącz do gry", nokia 6301 szuka urządzeń przez około 20sec po czym wychodzi z aplikacji.

Co może być przyczyną że aplikacja działa tylko w jedną stronę?
Maniek89 być może u Ciebie jest ten problem.

Pozdrawiam

1 użytkowników online, w tym zalogowanych: 0, gości: 1