Search code examples
javaandroidbroadcastreceiverandroid-broadcastreceiver

Async Task inside BroadcastReceiver onReceive method not running?


I have a working app which sends String data from application's input textfield to TCP server on my PC. I have added BroadcastReceiver class to send message to computer when it's received. Application receives messages(Toast is working), but I can't make it send received message to PC.

No Errors. Application just skips methods called.

How Do I Call a method inside onReceive?

Thank You for any help!

public class SmsReceiver extends BroadcastReceiver {
String phone;
String message;

@Override
public void onReceive(Context context, Intent intent) {
    Bundle intentExtras = intent.getExtras();

    if (intentExtras != null) {
        // Get Messages
        Object[] sms = (Object[]) intentExtras.get("pdus");

        for (int i = 0; i < sms.length; ++i) {
            // Parse Each Message
            SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]);

            phone = smsMessage.getOriginatingAddress();
            message = smsMessage.getMessageBody().toString();
            System.out.println("Message is: "+message);
            Log.i("sth","message "+message);

            //What i have tried
            sendMessage(message);

            //creating instance
            MessageSender messageSender = new MessageSender();
            messageSender.execute(message);

            //calling metod from MainActivity
            ((MainActivity)context.getApplicationContext()).send2(message);

            MainActivity.send2(message);

            //toast is working fine
            Toast.makeText(context,"Alert:"+ phone + ": " + message, Toast.LENGTH_SHORT).show();
        }
    }
}
public void sendMessage(String s)
{
    MessageSender messageSender = new MessageSender();
    messageSender.execute(s);
}

MainActivity

public class MainActivity extends AppCompatActivity {

EditText e1;

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

    e1 = (EditText)findViewById(R.id.editText);
    //This works
    MessageSender messageSender = new MessageSender();
    messageSender.execute("App launched!");
}

//On Button click. Working good.
public void send(View v)
{
    MessageSender messageSender = new MessageSender();
    messageSender.execute(e1.getText().toString());
}
//For test purposes
public static void send2(String s)
{
    MessageSender messageSender = new MessageSender();
    messageSender.execute(s);
}

MessageSender

public class MessageSender extends AsyncTask<String,Void,Void>
{
Socket s;
DataOutputStream dos;
PrintWriter pw;

@Override
public Void doInBackground(String... voids) {

    String message = voids[0];
try {
    s = new Socket("192.168.1.69", 7800);
    pw = new PrintWriter(s.getOutputStream());
    pw.write(message);
    pw.flush();
    pw.close();
    s.close();

}catch(IOException e)
{
    e.printStackTrace();
}
    return null;
}

}

Added server code:

  public class MyServerFrame extends javax.swing.JFrame 
  {
  static Socket s;
   static ServerSocket ss;
  static InputStreamReader isr;
  static BufferedReader br;
  static String message;public MyServerFrame() 
 {

}

public static void main(String args[]) 
{   
    try 
    {
        ss = new ServerSocket(7800);
        while(true)
        {
            s=ss.accept();
            isr = new InputStreamReader(s.getInputStream());
            br = new BufferedReader(isr);
            StringBuilder everything = new StringBuilder();
            String line;
            while( (line = reader.readLine()) != null) 
            {
               everything.append(line);
            }
            message = everything.toString();//multiple to onelinestring 
            System.out.println(message);
        }   
    }catch (IOException e) 
    {
        e.printStackTrace();
    }
}

}


Solution

  • The problem is that since you are executing the Network Request using an Async Task in the onReceive method, the onReceive method returns before the AsyncTask executes since an Async Task is Asynchronous. Therefore the process that is running the onRequest method becomes a low priority since the onReceive method has returned and the operating system will kill it before your Async Task actually executes.

    Here are two solutions:

    First ensure that the receiver is declared in your Android manifest, then do one of the following.

    1. Instead of calling an Async Task to execute your network request, create a service and use the service to run the network code.

    2. You can call the goAsync() method in the onReceive method to tell the system to give the receiver more time to execute its Async Task. The code for this would be something like this:

      @Override
      public void onReceive(final Context context, final Intent intent) {
      //create a pending intend that you will pass to the Async task so you can tell the system when the Async Task finished so that it can recycle.
      final PendingResult pendingResult = goAsync();
       AsyncTask<String, Integer, String> asyncTask = new AsyncTask<String,  Integer, String>() {
          @Override
          protected String doInBackground(String... params) {
              //put the network calling code in here
      
              // Must call finish() so the BroadcastReceiver can be recycled.
              pendingResult.finish();
              return data;
          }
      };
      asyncTask.execute();
       }
      

    The second way I believe would be simpler, so I would reccomend using that as it doesnt require you to create a whole new service.