0

I am using 3th fragment in my app. When i come to 3.fragment i want to send message other devices with bluetooth. But my log said :

The application may be doing too much work on its main thread.

And than my AcceptedThread lock. So my ConnectedThread empty. I cant send any thing. How can i fix it ? This is my bluetoothservice code:

public class BluetoothConnectionService {
    private static final String TAG = "BluetoothConnectionServ";

    private static final String appName = "MYAPP";

    private static final UUID MY_UUID_INSECURE =
            UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    private final BluetoothAdapter mBluetoothAdapter;
    Context mContext;

    private AcceptThread mInsecureAcceptThread;

    private ConnectThread mConnectThread;
    private BluetoothDevice mmDevice;
    private UUID deviceUUID;
    ProgressDialog mProgressDialog;

    private ConnectedThread mConnectedThread;

    public BluetoothConnectionService(Context context) {
        mContext = context;
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        start();
    }


    /**
     * This thread runs while listening for incoming connections. It behaves
     * like a server-side client. It runs until a connection is accepted
     * (or until cancelled).
     */
    private class AcceptThread extends Thread {

        // The local server socket
        private final BluetoothServerSocket mmServerSocket;

        public AcceptThread(){
            BluetoothServerSocket tmp = null;

            // Create a new listening server socket
            try{
                tmp = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(appName, MY_UUID_INSECURE);

                Log.d(TAG, "AcceptThread: Setting up Server using: " + MY_UUID_INSECURE);
            }catch (IOException e){
                Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
            }

            mmServerSocket = tmp;
        }

        public void run(){
            Log.d(TAG, "run: AcceptThread Running.");

            BluetoothSocket socket = null;

            try{
                // This is a blocking call and will only return on a
                // successful connection or an exception
                Log.d(TAG, "run: RFCOM server socket start.....");

                socket = mmServerSocket.accept();
                Log.d(TAG, "run: RFCOM server socket accepted connection.");

            }catch (IOException e){
                Log.e(TAG, "AcceptThread: IOException: " + e.getMessage() );
            }

            //talk about this is in the 3rd
            if(socket != null){
                Log.d(TAG, "run: Connected is active");

                connected(socket,mmDevice);
            }

            Log.i(TAG, "END mAcceptThread ");
        }

        public void cancel() {
            Log.d(TAG, "cancel: Canceling AcceptThread.");
            try {
                mmServerSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "cancel: Close of AcceptThread ServerSocket failed. " + e.getMessage() );
            }
        }

    }

    /**
     * This thread runs while attempting to make an outgoing connection
     * with a device. It runs straight through; the connection either
     * succeeds or fails.
     */
    private class ConnectThread extends Thread {
        private BluetoothSocket mmSocket;

        public ConnectThread(BluetoothDevice device, UUID uuid) {
            Log.d(TAG, "ConnectThread: started.");
            mmDevice = device;
            deviceUUID = uuid;
        }

        public void run(){
            BluetoothSocket tmp = null;
            Log.i(TAG, "RUN mConnectThread ");

            // Get a BluetoothSocket for a connection with the
            // given BluetoothDevice
            try {
                Log.d(TAG, "ConnectThread: Trying to create InsecureRfcommSocket using UUID: "
                        +MY_UUID_INSECURE );
                tmp = mmDevice.createRfcommSocketToServiceRecord(deviceUUID);
            } catch (IOException e) {
                Log.e(TAG, "ConnectThread: Could not create InsecureRfcommSocket " + e.getMessage());
            }

            mmSocket = tmp;

            // Always cancel discovery because it will slow down a connection
            mBluetoothAdapter.cancelDiscovery();

            // Make a connection to the BluetoothSocket

            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                mmSocket.connect();

                Log.d(TAG, "run: ConnectThread connected.");
            } catch (IOException e) {
                // Close the socket
                try {
                    mmSocket.close();
                    Log.d(TAG, "run: Closed Socket.");
                } catch (IOException e1) {
                    Log.e(TAG, "mConnectThread: run: Unable to close connection in socket " + e1.getMessage());
                }
                Log.d(TAG, "run: ConnectThread: Could not connect to UUID: " + MY_UUID_INSECURE );
            }

            //will talk about this in the 3rd video

            connected(mmSocket,mmDevice);
        }
        public void cancel() {
            try {
                Log.d(TAG, "cancel: Closing Client Socket.");
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "cancel: close() of mmSocket in Connectthread failed. " + e.getMessage());
            }
        }
    }



    /**
     * Start the chat service. Specifically start AcceptThread to begin a
     * session in listening (server) mode. Called by the Activity onResume()
     */
    public synchronized void start() {
        Log.d(TAG, "start");

        // Cancel any thread attempting to make a connection
        if (mConnectThread != null) {
            mConnectThread.cancel();
            mConnectThread = null;
        }

        if (mInsecureAcceptThread == null) {
            mInsecureAcceptThread = new AcceptThread();
            mInsecureAcceptThread.start();
        }
    }

    /**
     AcceptThread starts and sits waiting for a connection.
     Then ConnectThread starts and attempts to make a connection with the other devices AcceptThread.
     **/

    public void startClient(BluetoothDevice device,UUID uuid){
        Log.d(TAG, "startClient: Started.");

        //initprogress dialog
        mProgressDialog = ProgressDialog.show(mContext,"Connecting Bluetooth"
                ,"Please Wait...",true);

        mConnectThread = new ConnectThread(device, uuid);
        mConnectThread.start();
    }

    /**
     Finally the ConnectedThread which is responsible for maintaining the BTConnection, Sending the data, and
     receiving incoming data through input/output streams respectively.
     **/
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket) {
            Log.d(TAG, "ConnectedThread: Starting.");

            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            //dismiss the progressdialog when connection is established
            try{
                mProgressDialog.dismiss();
            }catch (NullPointerException e){
                e.printStackTrace();
            }


            try {
                tmpIn = mmSocket.getInputStream();
                tmpOut = mmSocket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }

            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) {
                // Read from the InputStream
                try {
                    bytes = mmInStream.read(buffer);
                    String incomingMessage = new String(buffer, 0, bytes);
                    Log.d(TAG, "InputStream: " + incomingMessage);
                    Intent incomingMessageIntent = new Intent("incomingMessage");

                    incomingMessageIntent.putExtra("theMessage", incomingMessage);
                    LocalBroadcastManager.getInstance(mContext).sendBroadcast(incomingMessageIntent);

                } catch (IOException e) {
                    Log.e(TAG, "write: Error reading Input Stream. " + e.getMessage() );
                    break;
                }
            }
        }







        //Call this from the main activity to send data to the remote device
        public void write(byte[] bytes) {
            String text = new String(bytes, Charset.defaultCharset());
            Log.d(TAG, "write: Writing to outputstream: " + text);
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) {
                Log.e(TAG, "write: Error writing to output stream. " + e.getMessage() );
            }
        }

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

    private void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) {
        Log.d(TAG, "connected: Starting.");

        // Start the thread to manage the connection and perform transmissions
        mConnectedThread = new ConnectedThread(mmSocket);
        mConnectedThread.start();
    }

    /**
     * Write to the ConnectedThread in an unsynchronized manner
     *
     * @param out The bytes to write
     * @see ConnectedThread#write(byte[])
     */
    public void write(byte[] out) {
        // Create temporary object
        ConnectedThread r;
        if(mConnectedThread==null){
return;
        }
        // Synchronize a copy of the ConnectedThread
        Log.d(TAG, "write: Write Called.");
        //perform the write
        mConnectedThread.write(out);
    }

}
Milind Mevada
  • 3,145
  • 1
  • 14
  • 22
CKocar
  • 566
  • 9
  • 25
  • 2
    https://stackoverflow.com/questions/14678593/the-application-may-be-doing-too-much-work-on-its-main-thread – AskNilesh Jul 23 '18 at 12:34
  • i already read that – CKocar Jul 23 '18 at 12:35
  • I have a a lot of fragment. And fragment call another fragment. This is wrong ? or not ? – CKocar Jul 23 '18 at 12:36
  • *I have a a lot of fragment. And fragment call another fragment. This is wrong* **No** – AskNilesh Jul 23 '18 at 12:37
  • Possible duplicate of [The application may be doing too much work on its main thread](https://stackoverflow.com/questions/14678593/the-application-may-be-doing-too-much-work-on-its-main-thread) – d0bry Jul 23 '18 at 13:45

3 Answers3

1

I had this error a long time ago when I was making requests to my server. I created an IntentService to handle these requests and this problem disappeared. Here is a good example that show how to create one!

Put the messages you want to send to another devices inside this IntentService!

Rodrigo Gontijo
  • 587
  • 1
  • 9
  • 21
  • I have a MainActivty and i call signfragment in here and than i call bluetooth list fragment and than i am calling another 3 fragment adapter in here so i am calling fragment in fragment a lot of. Is this a mistake or not ? – CKocar Jul 23 '18 at 12:42
  • No, its no a mistake! Fragments are made to do it! – Rodrigo Gontijo Jul 23 '18 at 12:46
  • I am new for android so i dont know how can i use intentservice at my app thank you for your link i am try i hope this time i will fix :/ – CKocar Jul 23 '18 at 12:48
  • 2
    All your code seems right (I'm from a mobile version and it's hard to read well the code in small display) however your Service.write() method directly executes the Thread.write() method instead of sending a Message/signal (to that Thread) to let it executes the Write procedure. This is the base of a Thread communication: each ASYNC command slould be notified/queued to that Thread instead of executing it directly from the Main/UI Thread. – emandt Jul 23 '18 at 12:48
  • Actually my 2nd fragment getting value other devices succesfull but 3th fragment cant send other devices because servicejava lock with this log:The application may be doing too much work on its main thread. – CKocar Jul 23 '18 at 12:51
  • @emandt you are correct, but instead of using asyncTask, it´s a better code pratice to use a IntentService, because it comes with a Queue of the requisitions "embedded". – Rodrigo Gontijo Jul 23 '18 at 12:52
  • Post your results later for us! And if work, dont forget to upvote and mark as accepted! See u. – Rodrigo Gontijo Jul 23 '18 at 12:56
  • So, for the just write function, i will create IntentService right ? or all Bluetooth service method ? – CKocar Jul 23 '18 at 13:00
  • 1
    I don't suggest to use AsyncTasks that are a complete different thing. I suggest to use the NORMAL Thread Communication using Messages. IntentServices will involves a complete different development procedure, so it's more long and difficult (not so much but...) – emandt Jul 23 '18 at 13:01
  • Okey. Thank you – CKocar Jul 23 '18 at 13:02
  • How can i do ? i am looking 3 days for this error but i can not find any solution. – CKocar Jul 23 '18 at 13:45
  • https://stackoverflow.com/questions/51493431/fragment-bluetooth-service-and-fragment-connection please check my new question – CKocar Jul 24 '18 at 10:38
  • I'm waitng my answer acceptance here.... I answer to 20 persons each day but most of them doesn't flag my answers,and it's quite frustrating. – emandt Jul 24 '18 at 11:03
  • I'm waitng my answer acceptance here.... I answer to 20 persons each day but most of them doesn't flag my answers,and it's quite frustrating(2) – Rodrigo Gontijo Jul 24 '18 at 13:01
1

You can create a self stopping service when your bluetooth operation is done. Don't forget to add the service in your manifest. Start it like that :

startService(new Intent(this, MyTemporaryService.class));

And here is the service class :

public class MyTemporaryService extends Service {

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    return START_NOT_STICKY;

}

@Override
public void onCreate() {
    super.onCreate();

    try {

        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {

                // Execute you method in that background thread, so we do not block main thread.

                myCodeToExecute();

                // stop the service when myCodeToExecute method is finished;

                stopSelf();

            }

        });

        thread.start();

    } catch (Exception e) {

        stopSelf();

    } catch (Error e2) {

        stopSelf();

    }


}


}

And add in your manifest :

    <service android:name="com.myApp.MyTemporaryService" android:enabled="true"
    />
Samet
  • 917
  • 12
  • 26
  • Thank you very much.Also my bluetooth service not include in manifest file maybe my problem cause this thing. :) – CKocar Jul 24 '18 at 05:57
  • If the service is not in manifest normally it will tell you in logcat. I don't remember very well. Maybe it is related to your problem. Anyway the self stopping service I provided should work. – Samet Jul 24 '18 at 14:20
  • can you help me this question ? https://stackoverflow.com/questions/51556090/how-can-i-connect-same-bluetooth-line – CKocar Jul 27 '18 at 13:04
0

The problem is that your "mConnectedThread.write(out);" is not executed in the Thread (as you wrote in the comment) but in the Service (that uses/shares the same thread of the graphic interface). You have to create an HandleThread and send a Message to it when you want to do the "write()" action.

emandt
  • 2,547
  • 2
  • 16
  • 20
  • Yes i am using graph. How can i use HandleThread on BluetoothService please help me. Thank you – CKocar Jul 23 '18 at 12:44
  • You have to create an Handler from the Thread and then use "mHandler.sendMessge(Message.obtain(mHandler, TH_MESSAGE_WRITE, 0, 0, buffer))" from any other thread. Obliviously inside the Handler you have to read the previously sent Message, extract the Buffer and then execute your Thread.write() method. Example from a different project but same method of solution: https://stackoverflow.com/questions/51458200/syncing-progressbar-with-handler/51458427#51458427 – emandt Jul 23 '18 at 12:54
  • PS: from that link/example DON'T use "Looper.getMainLooper()" or you fall in the same issue as before. Just use the base "new Handler() {}" without explicitly set a Looper. – emandt Jul 23 '18 at 12:57
  • I can not use handler for this please check my new topic https://stackoverflow.com/questions/51493431/fragment-bluetooth-service-and-fragment-connection – CKocar Jul 24 '18 at 10:38