0

i am using MainActivity for bluetooth connection and sending and receiving messages over it, each of them having a different thread. now i am launching a fragment from this activity and in that fragment i am sending string to main acitivity by using MainActivity code for sending message but my UI is hanging while doing this.. could anyone plz help me up getting overcome this problem. this is my MainActivity code:

public class MainActivity extends AppCompatActivity
    implements NavigationDrawerFragment.NavigationDrawerCallbacks {

/**
 * Fragment managing the behaviors, interactions and presentation of the navigation drawer.
 */
private NavigationDrawerFragment mNavigationDrawerFragment;

/**
 * Used to store the last screen title. For use in {@link #restoreActionBar()}.
 */
private CharSequence mTitle;

String address = null;
BluetoothAdapter myBluetoothadpt = null;
BluetoothSocket btSocket = null;
private boolean isBtConnected = false;
static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BluetoothDevice device=null;

static ConnectedThread manageConnectedSocket;

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

    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
    mTitle = getTitle();

    // Set up the drawer.
    mNavigationDrawerFragment.setUp(
            R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout));



 //   myBluetoothadpt = BluetoothAdapter.getDefaultAdapter();
  //  device = myBluetoothadpt.getRemoteDevice("98:D3:31:20:7F:FB");

    //  ConnectThread ct = new ConnectThread(device);
    // ct.start();


}

@Override
protected void onResume() {
    super.onResume();
    if (!myBluetoothadpt.isEnabled()) {
        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableIntent,1);

    }
}
public static void sendMessage(String s){
    Log.d("track", "sendMessage ");
    manageConnectedSocket.write(s.getBytes());

}
@Override
public void onNavigationDrawerItemSelected(int position) {
    Fragment myFragment=null;
    switch (position){
        case 0:
        myFragment=new Home();
        break;
        case 1:
            myFragment=new Hall();
            break;
        case 2:
            myFragment=new Room1();
            break;
        case 3:
            myFragment=new Room2();
            break;
        case 4:
            myFragment=new Room3();
            break;
        case 5:
            myFragment=new Kitchen();
            break;
        case 6:
            myFragment=new Other();
            break;
        case 7:
            myFragment=new Help();
            break;
        case 8:
            myFragment=new ContactUs();
            break;


    }
    // update the main content by replacing fragments
    FragmentManager fragmentManager = getSupportFragmentManager();
    fragmentManager.beginTransaction()
            .replace(R.id.container, myFragment)
            .commit();
}

public void onSectionAttached(int number) {
    switch (number) {
        case 1:
            mTitle = getString(R.string.title_section1);

            break;
        case 2:
            mTitle = getString(R.string.title_section2);
            break;
        case 3:
            mTitle = getString(R.string.title_section3);
            break;
    }
}

public void restoreActionBar() {
    ActionBar actionBar = getSupportActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
    actionBar.setDisplayShowTitleEnabled(true);
    actionBar.setTitle(mTitle);
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    if (!mNavigationDrawerFragment.isDrawerOpen()) {
        // Only show items in the action bar relevant to this screen
        // if the drawer is not showing. Otherwise, let the drawer
        // decide what to show in the action bar.
        getMenuInflater().inflate(R.menu.main, menu);
        restoreActionBar();
        return true;
    }
    return super.onCreateOptionsMenu(menu);
}

@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;
    }
    if (item.getItemId() == R.id.action_example) {
        Intent serverIntent = new Intent(MainActivity.this, DeviceListActivity.class);
        startActivityForResult(serverIntent, 1);
        return true;
    }

    return super.onOptionsItemSelected(item);
}


public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
        String address = data.getExtras()
                .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);


        BluetoothDevice device = myBluetoothadpt.getRemoteDevice(address);
        ConnectThread ct = new ConnectThread(device);

    ct.start();

}
}

/**
 * A placeholder fragment containing a simple view.
 */
public static class PlaceholderFragment extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
    public static PlaceholderFragment newInstance(int sectionNumber) {
        PlaceholderFragment fragment = new PlaceholderFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    public PlaceholderFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);
        return rootView;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        ((MainActivity) activity).onSectionAttached(
                getArguments().getInt(ARG_SECTION_NUMBER));
    }
}
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(myUUID);
        } catch (IOException e) { }
        mmSocket = tmp;
        btSocket=mmSocket;
    }

    public void run() {
        // Cancel discovery because it will slow down the connection
        myBluetoothadpt.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)
        manageConnectedSocket=new ConnectedThread(btSocket);
    }

    /** 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 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) {

        }
    }

    /* Call this from the main activity to send data to the remote device */
    public void write(byte[] bytes) {
        try {
            Log.d("track", "in write" + bytes.toString());

            // mmOutStream.flush();
            mmOutStream.write(bytes);
            // mmOutStream.flush();

        } catch (IOException e) { }
    }

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

}

here is my fragment:

public class Hall extends Fragment {
 ToggleButton t1h;


  @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

       t1h.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {


            if (isChecked) {

                String s = "t1o";
                Log.d("track", "onCheckedChanged " + isChecked);
                MainActivity.sendMessage(s);  // this is the method of   MAINACTIVITY which then handles sending message over bluetooth



            } else {
                editor.putBoolean("t1hState", t1h.isChecked());
                String s = "t1f";
                Log.d("track", "onCheckedChanged " + isChecked);


                MainActivity.sendMessage(s);

            }

        }
    });
}
}

2 Answers2

0

You should avoid putting non-UI related things on the main thread. When you do so, it causes the main thread to hang (and do the non-UI related work).

Therefore, you should delegate these jobs to AsyncTask to help you do the job and display the results when completed.

A good example of the implement can be found at: AsyncTask Android example

Community
  • 1
  • 1
sihao
  • 431
  • 2
  • 11
  • I have to send the message a no. Of times.. So how should i call execute() for that?i mean it will call doinbackground() every time then.. – shubham paralikar Apr 11 '16 at 18:08
  • yes, you put the logic to handle your message sending in doInBackground() and call execute() whenever you need to send – sihao Apr 11 '16 at 19:47
  • one way to optimize would be to collate the messages and send them all at once if the time of delivery is not of a concern – sihao Apr 11 '16 at 19:48
  • yeah, but regardless you have to use threading to solve your "hang" issue.. a slightly more advanced method is to use a threadpool to handle that – sihao Apr 12 '16 at 04:16
0

Your UI is hanged because you are sending message in current or main thread. if you want send data in background without effecting your current thread then use AsyncTask and create separated thread and put action in PostExcute() function of AsyncTask.