0

I am creating an application in Android in which whenever a user receives new Text message (SMS) it is first sent on server and if server replies true the Broadcast is aborted else we Broadcast it.

Now the problem is we can not communicate with server on UI thread, so to overcome this problem we have to use some kind of thread to perform background operations, therefore I am using AsyncTask to communicate with server. Here is my code:

Android App:

public class IncomingSms extends BroadcastReceiver {

// Get the object of SmsManager
final SmsManager sms = SmsManager.getDefault();
public static String message;

public void onReceive(final Context context, Intent intent) {

    // Retrieves a map of extended data from the intent.
    final Bundle bundle = intent.getExtras();
    String senderNum;
    try {

        if (bundle != null) {

            final Object[] pdusObj = (Object[]) bundle.get("pdus");

            for (int i = 0; i < pdusObj.length; i++) {

                SmsMessage currentMessage = SmsMessage
                        .createFromPdu((byte[]) pdusObj[i]);
                String phoneNumber = currentMessage
                        .getDisplayOriginatingAddress();

                senderNum = phoneNumber;
                message = currentMessage.getDisplayMessageBody();
                CallServer callServer = new CallServer();
                callServer.execute();
                Log.d("textmsg", callServer.getStatus().toString());

                /*
                  while (callServer.getStatus().toString() == "RUNNING") {
                  //Log.d("textmsg", "working in loop"); }
                 */

                if(callServer.get() == "true")
                    abortBroadcast();

                Log.d("textmsg", callServer.getStatus().toString() + "done");

                // Show Alert
                Toast toast = Toast.makeText(context, "senderNum: "
                        + senderNum + ", message: " + message,
                        Toast.LENGTH_LONG);
                toast.show();

            } // end for loop
        } // bundle is null

    } catch (Exception e) {
        Log.e("SmsReceiver", "Exception smsReceiver" + e);

    }
}

private class CallServer extends AsyncTask<String, String, String> {
    @SuppressLint("NewApi")
    protected String doInBackground(String... arg0) {
        Socket socket = null;
        DataOutputStream dataOutputStream = null;
        DataInputStream dataInputStream = null;

        try {
            socket = new Socket("192.168.1.100", 8081);
            Log.d("textmsg", "connected");
            dataOutputStream = new DataOutputStream(
                    socket.getOutputStream());
            dataInputStream = new DataInputStream(socket.getInputStream());
            if (!message.isEmpty()) {
                dataOutputStream.writeBytes(message);

                return (dataInputStream.readBoolean() == true) ? "true"
                        : "false";
            }
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            Log.e("error", e.toString());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            Log.e("error", e.toString());
        }

        return "false";
    }

     @Override protected void onPostExecute(String result){

         Log.d("textmsg", result);

     }

}
}

The problem which I can not understand is that whenever I use callServer.get() or while (callServer.getStatus().toString() == "RUNNING"){} my application crashes I am doing this because I have to wait for server reply i.e: true or false so if server replies true I can abort the broadcast.

LogCat:
D/textmsg(29494): RUNNING
D/textmsg(29494): connected
I/dalvikvm(29399): threadid=3: reacting to signal 3
I/dalvikvm(29494): Wrote stack traces to '/data/anr/traces.txt'

Note: My Server Side code is working perfectly as I receive message when my application sends request on server. I have also tested my server side code by creating simple client server application. My server is running on my local machine so I don't have any network issue.

I have also tried FutureTask however I was facing same problem. Any help would be greatly appreciated.

  • This sounds suspiciously like malware/ransomware. If you have a legitimate application, you will probably need to condense your rules down to something that can be cached and executed on the device. – Chris Stratton Apr 25 '14 at 14:35

2 Answers2

2

And that's why you don't want to use .get(). This will actually block your main UI waiting for the result of the AsyncTask execution, so your app will get ANR. Don't use it.

Instead, assign the result once you're done processing your onPostExecute() method to some Activity's variable.

nKn
  • 13,691
  • 9
  • 45
  • 62
  • if I do not block UI thread than SMS will be broadcasted before i get reply from server. I have to wait until server reply.. – Mubashir Ali Apr 25 '14 at 13:53
  • 1
    And why not just call a function on `onPostExecute()` as the last statement, that would send that SMS? – nKn Apr 25 '14 at 13:57
1

callServer.get() calling get blocks the ui thread waiting for the result. You should never block the ui thread. You need not call get(). Calling get() will make it asynchronous no more.

callServer.execute() invokes doInBackground which is enough.

Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • if I do not block UI thread than SMS will be broadcasted before i get reply from server I have to wait for server reply... – Mubashir Ali Apr 25 '14 at 13:51
  • @MubashirAli you need to know how asynctask works. You can return result in `doInBackground` and get the result in `onPostExecute`. http://developer.android.com/reference/android/os/AsyncTask.html. Do background processing in doInBackground return result and then do whatever is required in onPostExecute – Raghunandan Apr 25 '14 at 13:52
  • but the problem here is that you cant abort the Broadcast in onPostExecute method... `@Override` `protected void onPostExecute(String result) {` `abortBroadcast();` `}` I tried this but it does not work. Please read my Query again, I have to wait for server to reply so I can abort the broadcast... thanks – Mubashir Ali Apr 25 '14 at 14:01
  • @MubashirAli when does you server reply? after doInbackground computation?? So doing it in `onPostExecute` is just fine. read the docs again – Raghunandan Apr 25 '14 at 14:02
  • `return (dataInputStream.readBoolean() == true) ? "true" : "false";` in this code fragment i get the server reply this is the last statement of doInbackground method... – Mubashir Ali Apr 25 '14 at 14:06
  • treturn true/false in `doInbackground`. In `onPostExecute` based on the booelan value do whatever is required. – Raghunandan Apr 25 '14 at 14:08