【问题标题】:Application crashes when UI thread waits for AsyncTaskUI 线程等待 AsyncTask 时应用程序崩溃
【发布时间】:2014-04-25 13:44:33
【问题描述】:

我正在 Android 中创建一个应用程序,其中每当用户收到新的短信 (SMS) 时,它首先在服务器上发送,如果服务器回复为 true,则广播被中止,否则我们广播它。

现在的问题是我们无法在 UI 线程上与服务器通信,所以为了克服这个问题,我们必须使用某种线程来执行后台操作,因此我使用 AsyncTask 与服务器通信。这是我的代码:

安卓应用:

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);

     }

}
}

我无法理解的问题是,每当我使用callServer.get()while (callServer.getStatus().toString() == "RUNNING"){} 时,我的应用程序崩溃了,因为我必须等待服务器回复i.e: true or false,所以如果服务器回复为真,我可以中止广播.

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'

注意:当我的应用程序在服务器上发送请求时收到消息,我的服务器端代码运行良好。 我还通过创建简单的客户端服务器应用程序测试了我的服务器端代码。 我的服务器在我的本地机器上运行,所以我没有任何网络问题。

我也尝试过 FutureTask,但是我遇到了同样的问题。 任何帮助将不胜感激。

【问题讨论】:

  • 这听起来很像恶意软件/勒索软件。如果你有一个合法的应用程序,你可能需要将你的规则压缩成可以在设备上缓存和执行的东西。

标签: java android multithreading android-asynctask futuretask


【解决方案1】:

这就是您不想使用.get() 的原因。这实际上会阻止您的主 UI 等待AsyncTask 的执行结果,因此您的应用将获得ANR。不要使用它。

相反,在您处理完 onPostExecute() 方法后,将结果分配给某个 Activity 的变量。

【讨论】:

  • 如果我不阻止 UI 线程,那么在我收到服务器回复之前,SMS 将被广播。我必须等到服务器回复..
  • 为什么不直接在onPostExecute() 上调用一个函数作为最后一条语句来发送该短信?
【解决方案2】:

callServer.get() 调用 get 会阻塞等待结果的 ui 线程。你永远不应该阻塞 ui 线程。您无需致电get()。调用get() 将使其不再异步。

callServer.execute() 调用 doInBackground 就足够了。

【讨论】:

  • 如果我不阻止 UI 线程,那么在我收到服务器回复之前将广播 SMS 我必须等待服务器回复...
  • @MubashirAli 你需要知道 asynctask 是如何工作的。您可以在doInBackground 中返回结果,并在onPostExecute 中获取结果。 developer.android.com/reference/android/os/AsyncTask.html。在 doInBackground 返回结果中进行后台处理,然后在 onPostExecute 中执行所需的任何操作
  • 但是这里的问题是你不能在 onPostExecute 方法中中止广播...@Overrideprotected void onPostExecute(String result) {abortBroadcast();}我试过这个但它不起作用。请再次阅读我的查询,我必须等待服务器回复才能中止广播...谢谢
  • @MubashirAli 服务器什么时候回复?在doInbackground计算之后??所以在onPostExecute 中这样做就可以了。再次阅读文档
  • return (dataInputStream.readBoolean() == true) ? "true" : "false"; 在这个代码片段中我得到服务器回复这是 doInbackground 方法的最后一条语句...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-02
  • 2019-09-08
  • 1970-01-01
  • 2018-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多