You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击连接树莓派按钮时App崩溃,求原因及解决方案

问题:点击连接树莓派按钮后App崩溃,AsyncTask相关问题排查

当点击按钮连接树莓派时,App出现崩溃现象:TextView会显示“Checking Inventory”,但随即崩溃,同时树莓派端的程序也终止。我推测问题可能与AsyncTask相关,但无法确定。以下是我的代码:

public class MainActivity extends AppCompatActivity { 
    TextView results; 
    public String response; 
    private static final String TAG = "MainActivity"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        results = findViewById(R.id.countTextView); 
        Button thingBtn = findViewById(R.id.thingBtn); 
        thingBtn.setOnClickListener(new View.OnClickListener() { 
            @Override 
            public void onClick(View v) { 
                results.setText("Checking Inventory"); 
                new ConnectTask().execute(); 
            } 
        }); 
    } 

    public String Authentication = "we gucci"; 

    public class ConnectTask extends AsyncTask<String, Void, String>{ 
        @Override 
        protected void onPreExecute() { 
            Log.d(TAG, "AsyncTask starting"); 
            super.onPreExecute(); 
        } 

        @Override 
        protected String doInBackground(String... message) { 
            try { 
                Log.d(TAG, "Attempting to Connect to Socket"); 
                InetAddress serverAddress = InetAddress.getByName("192.168.1.11"); //must change later!!! 
                Socket house = new Socket(serverAddress, 5060); 
                Log.d(TAG, "Connected to Socket on (" + serverAddress + ", " + house.getPort() + ")"); 
                BufferedOutputStream bos =new BufferedOutputStream(house.getOutputStream()); 
                bos.write(Authentication.getBytes("UTF-8")); 
                bos.flush(); 
                BufferedReader serverResponse = new BufferedReader(new InputStreamReader(house.getInputStream())); 
                response = serverResponse.readLine(); 
                Log.d(TAG, "Server response: " + response); 
                house.close(); 
                Log.d(TAG, "socket closed"); 
            }catch (IOException e) { 
                System.exit(1); 
            } 
            return response; 
        } 

        @Override 
        protected void onPostExecute(String response){ 
            Log.d(TAG, response); 
            results.setText(response); 
        } 
    } 
}
问题分析与解决方案

嘿,我来帮你搞定这个崩溃问题!你猜的没错,问题确实和AsyncTask的使用以及异常处理有关,主要有这几个关键点:

1. 致命错误:System.exit(1)直接终止应用进程

在doInBackground的异常捕获块里,你调用了System.exit(1)——这会直接杀死整个Android应用进程,这就是App瞬间崩溃的核心原因!当网络连接出现任何IO异常(比如树莓派没开机、IP不对、端口没监听),你的代码直接强制退出了应用,这完全不符合Android的异常处理逻辑。

解决方法:
移除System.exit(1),改为捕获异常并返回错误信息,比如:

catch (IOException e) {
    Log.e(TAG, "Socket connection failed: " + e.getMessage());
    return "Connection failed: " + e.getMessage();
}

2. 成员变量response存在线程安全隐患

你把response定义为MainActivity的成员变量,在doInBackground里赋值,然后在onPostExecute里使用。但AsyncTask的doInBackground是在后台线程执行,onPostExecute在主线程,虽然这里不会有并发赋值,但依赖成员变量传递结果是不规范的,而且如果多次执行AsyncTask,成员变量可能被覆盖,导致结果混乱。

解决方法:
直接使用doInBackground的返回值作为onPostExecute的参数,完全不需要成员变量response。修改后,doInBackground里直接返回读取到的结果或者错误信息,onPostExecute直接用传入的参数即可。

3. 未处理网络操作的其他潜在异常

比如InetAddress.getByName可能抛出UnknownHostException(属于IOException的子类,但最好明确处理),还有读取流时可能出现的异常,另外,Socket连接应该放在try-with-resources块里,确保资源自动关闭,避免内存泄漏。

优化后的完整代码示例:

public class MainActivity extends AppCompatActivity { 
    TextView results; 
    private static final String TAG = "MainActivity"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
        results = findViewById(R.id.countTextView); 
        Button thingBtn = findViewById(R.id.thingBtn); 
        thingBtn.setOnClickListener(v -> { 
            results.setText("Checking Inventory"); 
            new ConnectTask().execute(); 
        }); 
    } 

    private final String Authentication = "we gucci"; 

    public class ConnectTask extends AsyncTask<String, Void, String>{ 
        @Override 
        protected void onPreExecute() { 
            super.onPreExecute(); 
            Log.d(TAG, "AsyncTask starting"); 
        } 

        @Override 
        protected String doInBackground(String... message) { 
            // 使用try-with-resources自动关闭Socket、流资源
            try (Socket house = new Socket("192.168.1.11", 5060);
                 BufferedOutputStream bos = new BufferedOutputStream(house.getOutputStream());
                 BufferedReader serverResponse = new BufferedReader(new InputStreamReader(house.getInputStream()))) {

                Log.d(TAG, "Connected to Socket on (" + house.getInetAddress() + ", " + house.getPort() + ")");
                bos.write(Authentication.getBytes("UTF-8"));
                bos.flush();
                
                String response = serverResponse.readLine();
                Log.d(TAG, "Server response: " + response);
                return response != null ? response : "Empty response from server";

            } catch (UnknownHostException e) {
                Log.e(TAG, "Unknown host: " + e.getMessage());
                return "Error: Could not find the device";
            } catch (IOException e) {
                Log.e(TAG, "Connection error: " + e.getMessage());
                return "Error: Failed to connect to device";
            }
        } 

        @Override 
        protected void onPostExecute(String result){ 
            super.onPostExecute(result);
            Log.d(TAG, "Received result: " + result);
            results.setText(result);
        } 
    } 
}

额外建议

  • 从Android API 30开始,AsyncTask已经被标记为废弃,推荐使用Coroutines(协程)或者ExecutorService来处理后台任务,代码会更简洁且易于维护。
  • 确保你的App已经申请了INTERNET权限,在AndroidManifest.xml里添加:
<uses-permission android:name="android.permission.INTERNET" />
  • 树莓派端的程序终止,可能是因为App崩溃时Socket连接被强制关闭,导致树莓派端的程序没有处理断开的情况,建议在树莓派的代码里添加异常捕获,处理客户端断开的场景。

内容的提问来源于stack exchange,提问作者Zachary Acosta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:12:45