Bluetooth socket blockiert App

B

BitCrasher

Neues Mitglied
0
Guten Abend zusammen,

mein Name ist Jeremy und ich bin neu hier im Forum. Ich arbeite zur Zeit an einer App mit der ich einen RFduino ansteuern kann. Aktuell bin ich soweit, dass ich erfolgreich Bluetoothgeräte discovern und mit dem Bluetoothdevice weiterarbeiten kann.
Nun zu meinem Problem:
Sobald ich versuche mit mmsocket.connect() eine Verbindung zum Microcontroller aufzubauen funktioniert das auch ( eine grüne LED bestätigt mir eine Verbindung zu einem Bluetoothgerät). Jedoch Zeitgleich verrennt sich meine App in der connect() - Methode und findet erst wieder einen Ausgang, sobald ich meinen Controller stromlos schalte und damit die Verbindung cute.
Ich hoffe einer von euch kann mir meinen Fehler aufzeigen.

Code:
    public class ListViewActivityAnz extends ActionBarActivity implements OnTouchListener {
    private static final String NAME = null ;
    public List<BTmodel> btModel;
    public Boolean Sperre = true;
    private BluetoothAdapter btAdapter;
    public Boolean hochfahren = true;
    public Boolean runterfahren = true;
    BTmodel test = new BTmodel();
    MainActivity test2 = new MainActivity();
    public OutputStream myOutputStream;
    public UUID MY_UUID = UUID.fromString("a46dd62b-318c-4bfc-8e4d-21475a4e379b");
    BluetoothSocket sock = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        try {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_list_view_activity_anz);
            Intent intent = getIntent();
            String toasttext = intent.getStringExtra("selected");
            String mac = toasttext.substring(toasttext.lastIndexOf("MAC: ") + 6);

            btAdapter = BluetoothAdapter.getDefaultAdapter();
            BluetoothDevice btdevice = btAdapter.getRemoteDevice(mac);
            ConnectThread ct = new ConnectThread(btdevice);


            Toast.makeText(ListViewActivityAnz.this, btdevice.getName(), Toast.LENGTH_SHORT).show();
            Toast.makeText(this, "a" + ct.mmSocket.isConnected(), Toast.LENGTH_SHORT).show();
            ct.run();
            ct.cancel();
            //setupUI();


        }
        catch (Exception e) { }
        {
            Thread.currentThread().interrupt();
        }

    }

    private void setupUI()
    {
        TextView Message = (TextView) findViewById(R.id.status2);



    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;

        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            // Use a temporary object that is later assigned to mmSocket,
            // because mmSocket is final
            BluetoothSocket tmp = null;
            mmDevice = device;

            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try {
                // MY_UUID is the app's UUID string, also used by the server code
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) { }
            mmSocket = tmp;
        }

        public void run() {
            // Cancel discovery because it will slow down the connection
            btAdapter.cancelDiscovery();

            try {
                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception
                mmSocket.connect();

            } catch (IOException connectException) {
                // Unable to connect; close the socket and get out
                try {
                    mmSocket.close();
                } catch (IOException closeException) { }
                return;
            }

            // Do work to manage the connection (in a separate thread)
            new ConnectedThread(mmSocket);
        }

        /** Will cancel an in-progress connection, and close the socket */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }

    private class ConnectedThread extends Thread {
        private static final int MESSAGE_READ = 0;
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the input and output streams, using temp objects because
            // member streams are final
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) { }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            byte[] buffer = new byte[1024];  // buffer store for the stream
            int bytes; // bytes returned from read()

            // Keep listening to the InputStream until an exception occurs
            while (true) {
                try {
                    // Read from the InputStream
                    bytes = mmInStream.read(buffer);
                    // Send the obtained bytes to the UI activity
                    Handler mHandler=null;
                    mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                            .sendToTarget();
                } catch (IOException e) {
                    break;
                }
            }
        }

        /* Call this from the main activity to send data to the remote device */
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) { }
        }

        /* Call this from the main activity to shutdown the connection */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_list_view_activity_anz, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return false;
    }


}
 
Code:
            ct.run();
            ct.cancel();

Warum das?

Threads startet man mit start() nicht mit run()...

Wenn man das unbedingt so wie du es im Code machst dann tue den ganzen try catch block in einen Thread am besten:

Code:
new Thread()
{
    //hier den try-catch-block einfügen oder deine run() und cancel() Methode einfach. Am Besten eigentlich alles was zur BT Verbindung zu tun aht heir rein. Bei Toast muss das wieder auf dem UI Thread ausgeführt werden da bietet sich runOnThread() an
}.start();


sonst läufst du darauf hinaus etwas auf dem UI Thread zu tun was man nicht tun sollte...Bluetoothverbindungen gehören da z.B. dazu
 
Zuletzt bearbeitet:
Jaiel schrieb:
Code:
            ct.run();
            ct.cancel();

Warum das?

war eigentlich nur mal ein Versuch ob sich das ganze auch wieder beenden lässt. Aber soweit kommt das Programm garnicht.

Ich werde das dann mal so Versuchen.
Danke schon mal und ich bin gerne für weitere Tipps offen.
 
Guten Morgen,

nun läuft das auch meine Activity wieder. Tatsächlich lag es "nur" an dem run(); .

Jetzt habe ich aber ein neues Problem. Wenn ich die Aktivity verlasse, möchte ich, dass die Verbindung wieder unterbrochen wird um Akkuressourcen zu sparen.
Dazu habe ich ich eine reset-Methode die erst meinen in/outputstream schließen (soll) und dann meinen socket.
Diese Methode ruf ich im ondestroy auf. aber es passiert nichts....
Habe das Ganze im try-catch gekapselt, aber ich bekomm werden eine Fehlermeldung noch wird die Verbindung beendet, erst bei manuellem deaktivieren meines Bluetooth am Handy(wo es mir ja logisch ist).

Was ich vergessen hab...
Obwohl der microcontroller eine Verbindung meldet ist der mmSocket auf false
 
Zuletzt bearbeitet:
BitCrasher schrieb:
Guten Morgen,

nun läuft das auch meine Activity wieder. Tatsächlich lag es "nur" an dem run(); .

Jetzt habe ich aber ein neues Problem. Wenn ich die Aktivity verlasse, möchte ich, dass die Verbindung wieder unterbrochen wird um Akkuressourcen zu sparen.
Dazu habe ich ich eine reset-Methode die erst meinen in/outputstream schließen (soll) und dann meinen socket.
Diese Methode ruf ich im ondestroy auf. aber es passiert nichts....
Habe das Ganze im try-catch gekapselt, aber ich bekomm werden eine Fehlermeldung noch wird die Verbindung beendet, erst bei manuellem deaktivieren meines Bluetooth am Handy(wo es mir ja logisch ist).

Was ich vergessen hab...
Obwohl der microcontroller eine Verbindung meldet ist der mmSocket auf false

Die onDestroy Methode wird erst aufgerufen, wenn die Activity komplett beendet ist und auch nicht mehr im Hintergrund läuft. Ich denke du solltest stattdessen die onPause oder onStop Methode verwenden.

Hier steht wann onPause, onStop und onDestroy aufgerufen werden: Activity | Android Developers
 
Daaaaniel schrieb:
.... Ich denke du solltest stattdessen die onPause oder onStop Methode verwenden.

Hier steht wann onPause, onStop und onDestroy aufgerufen werden: Activity | Android Developers

Diese Variante habe ich auch scho versucht. Die cancel-Methode läuft auch durch, aber hat keine Auswirkungen auf meine Verbindung. Hat es eventuell damit zu tun auf welche weise ich die Verbindung Aufbaue...
Entschuldigt bitte mein endloses Gefrage. Ich bin mir der ganzen Materie einfach nicht wirklich vertraut.
Ich leg gleich noch meinen aktuelle Code bei:

Code:
public class ListViewActivityAnz extends ActionBarActivity implements OnTouchListener {
    private static final String NAME = null ;
    private static final String TAG = null;
    public List<BTmodel> btModel;
    public Boolean Sperre = true;
    private BluetoothAdapter btAdapter;
    public Boolean hochfahren = true;
    public Boolean runterfahren = true;
    BTmodel test = new BTmodel();
    MainActivity test2 = new MainActivity();
    public OutputStream myOutputStream;
    //private BluetoothServerSocket mmServerSocket; //a46dd62b-318c-4bfc-8e4d-21475a4e379b
        public BluetoothDevice btdevice;
    public UUID MY_UUID = UUID.fromString("a46dd62b-318c-4bfc-8e4d-21475a4e379b");
    public BluetoothSocket mmSocket;
    public BluetoothDevice mmDevice;
    public InputStream mmInStream;
    public OutputStream mmOutStream;


    @Override
    protected void onCreate(Bundle savedInstanceState) {


            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_list_view_activity_anz);
            Intent intent = getIntent();
            String toasttext = intent.getStringExtra("selected");
            String mac = toasttext.substring(toasttext.lastIndexOf("MAC: ") + 6);

            btAdapter = BluetoothAdapter.getDefaultAdapter();
            btdevice = btAdapter.getRemoteDevice(mac);
            ConnectThread ct = new ConnectThread(btdevice);
            ct.start();
            ConnectedThread ctd = new ConnectedThread(mmSocket);

            setupUI();

            Toast.makeText(ListViewActivityAnz.this, btdevice.getName(), Toast.LENGTH_SHORT).show();
            //((TextView) (findViewById(R.id.status))).setText("Es wurde" + intent.getStringExtra("selected") + "gewählt!");
            //Toast.makeText(this,  "a"+ct..isConnected(), Toast.LENGTH_SHORT).show();
            Toast.makeText(this, "a" + mmSocket.isConnected(), Toast.LENGTH_SHORT).show();


    }

    private void setupUI()
    {


        TextView Message = (TextView) findViewById(R.id.status2);
        final Button key = (Button)findViewById(R.id.buttonentriegeln);
        key.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Toast.makeText(ListViewActivityAnz.this, "gedrueckt", Toast.LENGTH_SHORT).show();
                String example = "ffffff00ff";
                byte[] test = example.getBytes();
                senden(test);
            }
        });
    }

    private void resetConnection() {
        if (mmInStream != null) {
            try {mmInStream.close();} catch (Exception e) {Toast.makeText(this, "Funzt ned1", Toast.LENGTH_SHORT).show();}
            mmInStream = null;
        }

        if (mmOutStream != null) {
            try {mmOutStream.close();} catch (Exception e) {Toast.makeText(this, "Funzt ned2", Toast.LENGTH_SHORT).show();}
            mmOutStream = null;
        }

        if (mmSocket != null) {
            try {mmSocket.close();} catch (Exception e) {Toast.makeText(this, "Funzt ned3", Toast.LENGTH_SHORT).show();}
            mmSocket = null;
        }

    }


 

    private class ConnectThread extends Thread {
        //private final BluetoothSocket mmSocket;
        //private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) {
            // Use a temporary object that is later assigned to mmSocket,
            // because mmSocket is final
            BluetoothSocket tmp = null;
            mmDevice = device;

            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try {
                // MY_UUID is the app's UUID string, also used by the server code
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            } catch (IOException e) { }
            mmSocket = tmp;
        }

        public void run() {
            // Cancel discovery because it will slow down the connection
            btAdapter.cancelDiscovery();

            try {
                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception
                mmSocket.connect();
            } catch (IOException connectException) {
                // Unable to connect; close the socket and get out
                try {
                    mmSocket.close();
                } catch (IOException closeException) { }
                return;
            }

            // Do work to manage the connection (in a separate thread)
            new ConnectedThread(mmSocket);
        }

        /** Will cancel an in-progress connection, and close the socket */
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }

    private class ConnectedThread extends Thread {
        private static final int MESSAGE_READ = 0;
        //private final BluetoothSocket mmSocket;
        //private final InputStream mmInStream;
        //private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            // Get the input and output streams, using temp objects because
            // member streams are final
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) { }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            byte[] buffer = new byte[1024];  // buffer store for the stream
            int bytes; // bytes returned from read()

            // Keep listening to the InputStream until an exception occurs
            while (true) {
                try {
                    // Read from the InputStream
                    bytes = mmInStream.read(buffer);
                    // Send the obtained bytes to the UI activity
                    Handler mHandler=null;
                    mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                            .sendToTarget();
                } catch (IOException e) {
                    break;
                }
            }
        }

        /* Call this from the main activity to send data to the remote device */
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) { }
        }

        /* Call this from the main activity to shutdown the connection */
        public void cancel() {
            Toast.makeText(ListViewActivityAnz.this, "cancel", Toast.LENGTH_SHORT).show();
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_list_view_activity_anz, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onPause()
    {
        super.onPause();
        ConnectThread ct = new ConnectThread(btdevice);
        ConnectedThread ctd = new ConnectedThread(mmSocket);
        try {
            mmInStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            mmOutStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ctd.cancel();
        ct.cancel();
    }


    @Override
    protected void onStop() {
        super.onStop();

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        try {
            resetConnection();
        }
        catch (Exception e){
            Toast.makeText(this, "Fehler ondestroy", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return false;
    }


}
 
Es reicht nicht nur den BluetoothSocket mit close() zu beenden. Solange die beiden Stream mmInStream und mmOutStream nicht geschlossen werden, bleibt dein Thread bestehen. Der Thread wird nicht automatisch beendet, wenn die Activity beendet wird. Und der Thread kann dann auf Objekte zu greifen, die nicht mehr existieren (NullPointerException).

Wie @Daaaaniel anmerkte, solltest du den Socket und die Streams geschlossen haben, wenn die Activity sich nicht mehr im Vordergrund befindet (Lifecycle).
Aber du solltest nicht damit warten, bis onPause() aufgerufen wird. Alle Sockets und Streams sollten sofort geschlossen werde, wenn sie nicht mehr gebraucht werden. Jeder offene Socket, der nicht geschlossen wird, saugt die Batterie leer, und ist eine potentielle Fehlerquelle.

Nachtrag: Streams werden nicht automatisch beendet.
 
Zuletzt bearbeitet:
okay, das habe ich soweit verstanden. Dafür habe ich nun einen Button eingerichtet der mir solange ich ihn gedrückt halte eine Verbindung aufrechterhalten soll, aber sobald ich ihn loslasse passiert wieder nichts. Und ich hab doch nach der reihe meine mmInStream, mmOutStream und dann meinen mmSocket beendet(zumindest versucht). Dafür hab ich den gleich Code genutzt wie in der onPause.
Nutze ich die falschen Berfehle oder Methoden?

Ich bin langsam etwas überfordert. :-(
 
// Do work to manage the connection (in a separate thread)
new ConnectedThread(mmSocket);

wazu initialisierst du einen anonymen thread der nichts tut?
 
Jaiel schrieb:
// Do work to manage the connection (in a separate thread)
new ConnectedThread(mmSocket);

wazu initialisierst du einen anonymen thread der nichts tut?
Das kann ich auch nicht sagen, hab den Code auch nur kopiert.
Habe die Zeile nun entfernt, aber damit hat sich nichts wirklich geändert.

Ich verstehe leider immernoch nicht warum meine Verbindung bestehen bleibt, obwohl ich sorgfälltig alles schließe.
Die Methoden laufen ja Problemlos durch nur bringen sie nichts....
gibts es noch einen weiteren Befehl außer close() ?
auf der developer-seite hab ich nichts anderes gefunden.
 

Ähnliche Themen

Manny87
  • Manny87
Antworten
11
Aufrufe
159
swa00
swa00
R
  • Robby1950
2
Antworten
23
Aufrufe
1.004
Robby1950
R
netfreak
  • netfreak
Antworten
10
Aufrufe
454
netfreak
netfreak
Zurück
Oben Unten