9

I am making an application which uses bluetooth connection. I am calling bluetooth connection in onCreate() and closing it in onDestroy() of MainActivity:

// Bluetooth
private Bluetooth bt;
private boolean registered = false;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    bt = new Bluetooth(this);
    bt.enableBluetooth();
    bt.setCommunicationCallback(this);
    bt.connectToName(bt.getBluetoothDevice(this));
    IntentFilter filter = new    IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
    registerReceiver(mReceiver, filter);
    registered = true;
}

@Override    
public void onDestroy() {
    super.onDestroy();
    if(registered) {
        unregisterReceiver(mReceiver);
        registered=false;
    }
    bt.removeCommunicationCallback();
    bt.disconnect();
    if (handler != null && runnable != null) {
        handler.removeCallbacks(runnable);
    }
}

The app also supports LANDSCAPE and PORTRAIT modes (using two different layouts). When screen is rotated, the MainActivity calls the onCreate() and onDestroy functions, due to different layout. For that reason, I got the following error:

@@@ ABORTING: INVALID HEAP ADDRESS IN dlfree addr=0x5a71aa38
A/libc: Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 1051 (le.bluetoothled)

As I found in the Invalid heap address and fatal signal 11, it was from BluetoothSocket's close() method. First, I think that we don't need close bluetooth when we rotate the screen, hence, I tried to use the method to detect rotation event of phone and ignore closing when the rotation happen, however, it does not work. Hence, I think we may need to close bluetooth when screen rotation, but I got the above error. I have no idea how can I solve this, could you help me to solve that issue? I am using this Bluetooth lib with disconnect() as follows:

public void disconnect() {
        try {
            socket.close();
        } catch (IOException e) {
            if(communicationCallback!=null)
                communicationCallback.onError(e.getMessage());
        }
    }

As my current solution is using sleep. I added Thread.sleep (1000) before close socket. It is working. But I think it is not a very good solution.

Community
  • 1
  • 1
Jame
  • 3,746
  • 6
  • 52
  • 101
  • What is your `Bluetooth` class? Is it a `Service`? – Bryan Sep 21 '16 at 15:09
  • No. It just normal class as https://github.com/omaflak/Bluetooth-Library/blob/master/bluetooth/src/main/java/me/aflak/bluetooth/Bluetooth.java – Jame Sep 21 '16 at 15:11
  • What happens when one of the threads you create for bluetooth connection is still running and you rotate the device? They keep reference to the old activity. You are trying to clear the reference to the activity callback but also you check in another thread if it is null. That is not safe. – masp Sep 21 '16 at 18:34
  • you can put your bluetooth-related codes in a service so you won't need to keep on reconnecting every time your app rotates. if your project requirement is not very strict. :) – user1506104 Sep 26 '16 at 13:35

4 Answers4

2

You MUST NOT use Bluetooth - related stuff inside Activity (see SOLID) principles. Activity is just a UI. You should create separate Service, which will be running independently from UI in background and managing all Bluetooth - related action. From your Activity bind to that Service in onResume() method and unbind from it in onPause() method. You can get bt- control interface from ServiceConnection, passed by Service during binding. There is a great Bluetooth example from Google - https://github.com/googlesamples/android-BluetoothChat . The only drawback - it uses Handler for passing messages. I've modified it slightely - now there is another thread, receiving all state messages and calling callback. Feel free to use this code: https://github.com/AlexShutov/LEDLights

Alex Shutov
  • 3,217
  • 2
  • 13
  • 11
0

You can add Fragment inside your activity and call setRetainInstnce this fragment to handle orientations changes. Move your logic with bluetooth into the Fragment. Take a look how to implement this here and here.

Community
  • 1
  • 1
Volodymyr
  • 6,393
  • 4
  • 53
  • 84
0

try this code

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    //disconnect your bluetooth
}
subrahmanyam boyapati
  • 2,836
  • 1
  • 18
  • 28
0

Add this tag in manifest file in respected activity tag. After Adding this tag to manifest in respected activity, Activity can retain their state and during change in orientation onDestroy() is not called and bluetooth socket is not closed.

android:configChanges="keyboardHidden|orientation|screenSize"

Rahil Ali
  • 957
  • 10
  • 25