【问题标题】:Android Programming: Having trouble with TCP through a AsyncTaskAndroid 编程:通过 AsyncTask 遇到 TCP 问题
【发布时间】:2012-12-29 04:18:06
【问题描述】:

我遇到的这个问题是我的程序只能通过 AsyncTask 通过 TCP 发送我的字符串一次。我已经读过 AsyncTask 只能运行一次,并且在它运行后应该被释放,如果我需要发送另一个命令,我应该创建另一个线程实例并使用新实例来发送新命令。但是,无论出于何种原因,当我尝试创建 AsyncTask 的第二个实例时,什么都没有发生。有一点值得注意。我在 onPostExecute 例程中添加了一个日志命令,但我从未看到日志消息。

我的 Android 清单文件中有以下内容:

<uses-permission android:name="android.permission.INTERNET/> 

这是调用异步任务的主活动线程中的代码。

public void SendCommand(int DeviceID, String DeviceName, String CommandName)
{
    //Get the IP address and the port in order to communicate with the device
    DatabaseHelper dbHelper = new DatabaseHelper(MainActivity.this);
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    String dbQuery = "SELECT * FROM " + dbHelper.System_Table + ", " + dbHelper.Devices_Table + ", " +
            dbHelper.Device_Commands_Table + " WHERE " + dbHelper.System_Table + "." + dbHelper.Attribute_Device_ID +
            " = " + String.valueOf(DeviceID) + " AND " + dbHelper.Devices_Table + "." + dbHelper.Attribute_Device_ID +
            " = " + String.valueOf(DeviceID) + " AND " + dbHelper.Device_Commands_Table + "." + dbHelper.Attribute_Device_ID +
            " = " + String.valueOf(DeviceID) + ";";
    Cursor c = db.rawQuery(dbQuery, null);
    String IPAddress = "";
    int Port = 0;
    String DeviceCommand = "";
    if (c.getCount() > 0)
    {
        int Finished = 0;
        while (c.moveToNext() && Finished == 0)
        {
            int iColumnDeviceName = c.getColumnIndex(dbHelper.Attribute_Device_Name);
            int iColumnDeviceCommandName = c.getColumnIndex(dbHelper.Attribute_Command_Name);
            final String CheckDeviceName = c.getString(iColumnDeviceName);
            final String CheckCommandName = c.getString(iColumnDeviceCommandName);
            if (DeviceName.equals(CheckDeviceName) && CheckCommandName.equals(CommandName))
            {
                Finished = 1;
                int iColumnIPAddress = c.getColumnIndex(dbHelper.Attribute_Device_IP);
                int iColumnPort = c.getColumnIndex(dbHelper.Attribute_Device_Port);
                int iColumnDeviceCommandString = c.getColumnIndex(dbHelper.Attribute_Command_String);
                IPAddress = c.getString(iColumnIPAddress);
                Port = c.getInt(iColumnPort);
                DeviceCommand = c.getString(iColumnDeviceCommandString);
                DeviceCommand = DeviceCommand.replace("<CR>", "\r");
                Log.d("Device Command To Send", DeviceCommand);
            }
        }
        c.close();
        dbHelper.close();
        ArrayList<String> passing = new ArrayList<String>();
        ArrayList<String> result = new ArrayList<String>();
        passing.add(IPAddress);
        passing.add(String.valueOf(Port));
        passing.add(DeviceCommand);
        SendCommand SC = new SendCommand();
        SC.execute(passing, result);
    }
}

这是上面例程创建实例并执行的单独类文件。

public class SendCommand extends AsyncTask<ArrayList<String>, Void, ArrayList<String>>
{
    @Override
    protected void onPreExecute()
    {
        //progress bar
    }

    @Override
    protected ArrayList<String> doInBackground(ArrayList<String>... passing)
    {
        Log.d("Async Task", "Started to send command.");
        //Get the connection info and command to send from the caller
        String Data = passing[0].toString();
        int StopAt = Data.indexOf(",");
        String IPAddress = Data.toString().substring(1, StopAt);
        Data = Data.replace("[" + IPAddress + ", ", "");
        StopAt = Data.indexOf(",");
        int Port = Integer.parseInt(Data.toString().substring(0, StopAt));
        Data = Data.replace(Port + ", ", "");
        StopAt = Data.indexOf("]");
        String DeviceCommand = Data.toString().substring(0, StopAt);
        Send_Command(IPAddress, Port, DeviceCommand);
        return null;
    }

    protected void onPostExecute(Long result)
    {
        Log.d("Async Task", "Command Sent");
    }

    private void Send_Command(String IPAddress, int Port, String DeviceCommand)
    {
        //Setup the connection parameters
        SocketAddress SA = new InetSocketAddress(IPAddress, Port);
        int Timeout = 2000;
        Socket socket = new Socket();

        try
        {
            //Attempt to connect to the device
            socket.connect(SA, Timeout);
            int Count = 0;
            int Kill = 0;
            while (socket.isConnected() == false && Kill == 1)
            {
                //Waiting for the connection
                Count = Count + 1;
                if (Count == Timeout)
                {
                    Kill = 1;
                    Log.d("Connection Status", "Timed out");
                }
            }
            if (socket.isConnected() == true)
            {
                //send the command
                BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                wr.write(DeviceCommand);
                wr.flush();
                Log.d("Sent Device Command", DeviceCommand);
                //listen for the response
                BufferedReader rd = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String Response;
                while ((Response = rd.readLine()) != null)
                {
                    Log.d("Received Device Response", Response);
                }
                rd.close();
            }
            //close the socket once the response is received
            socket.close();
        }
        catch (UnknownHostException e)
        {
            Log.d("UnknownHostException", "Something bad happened");
        }
        catch (IOException e)
        {
            Log.d("IOException", "Something bad happened");
        }
        finally
        {
            if (socket != null)
            {
                try
                {
                    socket.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
}

这是我尝试通过 tcp 发送两个命令后的日志。

01-14 23:53:29.773: D/Device Command To Send(31643): PN
01-14 23:53:29.773: D/Async Task(31643): Started to send command.
01-14 23:53:30.108: D/Sent Device Command(31643): PN
01-14 23:53:30.273: D/Received Device Response(31643): R
01-14 23:53:31.918: D/Device Command To Send(31643): PF

我可以看到第一次启动 AsyncTask 并发送命令以及接收来自目标设备的响应。但是我在日志中没有看到“Async Task”、“Command Sent”,所以 onPostExecute 没有执行。

对我做错了什么有什么想法吗?

【问题讨论】:

    标签: android tcp android-asynctask


    【解决方案1】:

    目前您没有从 AsyncTask 覆盖 onPostExecute,因此将您的 onPostExecute 签名更改为:

    @Override
    protected void onPostExecute(ArrayList<String> result)//<Change Long
                                                          // to ArrayList<String>
      {
           Log.d("Async Task", "Command Sent");
      }
    

    【讨论】:

      【解决方案2】:

      您的onPostExecute 签名错误。

      protected void onPostExecute(Long result)
      

      应该是

      protected void onPostExecute(ArrayList<String> result)
      

      使用@Override 注释可能也很好。

      在您的Send_Command 中添加一些额外的调试消息,AsyncTask 可能挂在那里。

      【讨论】:

      • 哇,感谢您的超快速响应。我按照建议对 onPostExecute 进行了调整,但它仍然没有显示在日志文件中或运行 AsyncTask 的新实例。如果线程不会自行死亡,有没有办法杀死它?
      • 谢谢。当我下班回家后,我将添加更多日志记录以更详细地跟踪异步任务。
      • 对于那些觉得需要投反对票的人,请记住我是 android 编程和 java 的新手。我来自 Windows 并编程 AMX/Crestron 系统以及一些爱好 .net 编程。因此,如果我犯了您认为微不足道的错误,请保留负面判断而不发表评论。相反,请帮助其他用户。 :) 非常感谢帮助的人。我刚到家,我现在将进行更多日志记录,看看是否能解决问题。
      • 好吧,我现在感觉很蠢。问题是我的 while ((Response = rd.readLine()) != null) 循环中有一个无限循环。一旦我修复了该循环,AsyncTask 的实例就会像魅力一样工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-07
      相关资源
      最近更新 更多