Асинхронная задача внутри BroadcastReceiver onReceive метод не работает?
У меня есть работающее приложение, которое отправляет данные String из входного текстового поля приложения на TCP-сервер на моем ПК. Я добавил класс BroadcastReceiver для отправки сообщения на компьютер при его получении. Приложение получает сообщения (тост работает), но я не могу заставить его отправлять полученное сообщение на ПК.
Нет ошибок. Приложение просто пропускает вызываемые методы.
Как я могу вызвать метод внутри onReceive?
Спасибо за любую помощь!
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);
}
Основная деятельность
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;
}
}
Добавлен код сервера:
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();
}
}
}
2 ответа
Проблема заключается в том, что, поскольку вы выполняете сетевой запрос с помощью асинхронной задачи в методе onReceive, метод onReceive возвращается до выполнения AsyncTask, поскольку асинхронная задача асинхронна. Поэтому процесс, который выполняет метод onRequest, становится низким приоритетом, так как метод onReceive был возвращен, и операционная система уничтожит его до того, как ваша асинхронная задача фактически выполнится.
Вот два решения:
Сначала убедитесь, что получатель объявлен в манифесте Android, а затем выполните одно из следующих действий.
Вместо вызова асинхронной задачи для выполнения сетевого запроса создайте службу и используйте службу для запуска сетевого кода.
Вы можете позвонить
goAsync()
метод в методе onReceive, чтобы сообщить системе, чтобы у получателя было больше времени для выполнения своей асинхронной задачи. Код для этого будет выглядеть примерно так:@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(); }
Второй способ, на мой взгляд, будет проще, поэтому я бы рекомендовал использовать его, так как он не требует создания совершенно нового сервиса.
Спасибо SteelToe за то, что привели меня к этому тривиальному решению:
Получатель не был объявлен в файле манифеста.