Android应用跳转Activity无报错崩溃,求助排查方案
首先,咱们来拆解你遇到的问题:扫码后闪退、WIN DEATH日志,手动输入正常但调试失效,加sleep能缓解——这些现象指向几个核心问题:主线程阻塞、Activity初始化错误、参数传递失误,下面逐个解决:
1. 修复ReaderQR的初始化bug
看你的ReaderQR代码,onCreate里调用QrScanner(this.mScannerView)时,mScannerView还未初始化(处于null状态),而且QrScanner方法根本没用到传入的View参数,直接重新创建扫描视图,这会导致布局加载混乱,甚至Camera资源泄漏,是闪退的潜在诱因之一。
修复后的ReaderQR代码:
import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import com.google.zxing.Result; import com.psa.dkd.R; import me.dm7.barcodescanner.zxing.ZXingScannerView; public class ReaderQR extends AppCompatActivity implements ZXingScannerView.ResultHandler { private ZXingScannerView mScannerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 直接初始化扫描视图,跳过无用的中间方法 mScannerView = new ZXingScannerView(this); setContentView(mScannerView); mScannerView.setResultHandler(this); mScannerView.startCamera(); setTitle("Pass it over the code!"); } @Override public void onPause() { super.onPause(); mScannerView.stopCamera(); } public void handleResult(Result rawResult) { Intent returnIntent = new Intent(); returnIntent.putExtra("code", rawResult.getText()); setResult(Activity.RESULT_OK, returnIntent); // 加个小延迟再finish,确保Intent完全传递 new Handler().postDelayed(() -> finish(), 100); } }
2. 移除GetCarDetails中阻塞主线程的get()调用
这是导致WIN DEATH的核心原因!你在主线程里调用AsyncTask.get(),会强制主线程等待异步任务完成——主线程被卡死,无法处理系统的窗口消息,系统就会判定应用无响应,直接销毁窗口(也就是你看到的WIN DEATH日志)。
修复方法:用onPostExecute处理异步结果,彻底避免主线程阻塞:
import android.app.Activity; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Toast; import com.psa.dkd.R; import com.psa.dkd.utils.SessionManagement; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.util.HashMap; import static com.psa.dkd.utils.Misc.jsonToMap; public class GetCarDetails extends Activity { private String car_code; private String server; private String worker_id; private HashMap<String, String> car_data; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_get_details); findViewById(R.id.mainSpinner2).setVisibility(View.VISIBLE); SessionManagement session = new SessionManagement(GetCarDetails.this); this.server = session.getUserDetails().get("server"); this.worker_id = session.getUserDetails().get("id"); this.car_code = getIntent().getExtras().getString("car_code"); // 直接执行AsyncTask,无需postDelayed和阻塞式get() new getCarData().execute("APP/getCarDetails.php", car_code, worker_id); } public class getCarData extends AsyncTask<String, String, String> { @Override protected String doInBackground(String... params) { String text = ""; BufferedReader reader = null; try { URL url = new URL(server + params[0]); JSONObject postDataParams = new JSONObject(); postDataParams.put("code", params[1]); // 修复参数错误:原代码把car_code当成user_id传递,现在改为正确的worker_id参数 postDataParams.put("user_id", params[2]); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(15000); conn.setConnectTimeout(15000); conn.setRequestMethod("POST"); conn.setDoInput(true); conn.setDoOutput(true); DataOutputStream wr = new DataOutputStream(conn.getOutputStream()); String param = "json=" + URLEncoder.encode(postDataParams.toString(), "UTF-8"); wr.write(param.getBytes()); wr.flush(); wr.close(); reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } text = sb.toString(); return text; } catch (Exception e) { Log.d("ERROR FETCHING DATA", "Exception: " + e.getMessage()); return "Exception: " + e.getMessage(); } } @Override protected void onPostExecute(String result) { super.onPostExecute(result); findViewById(R.id.mainSpinner2).setVisibility(View.GONE); try { Log.d("TEST", "RECEIVED: " + result); car_data = jsonToMap(result); if (car_data.get("result").equals("1")) { Bundle b = new Bundle(); b.putString("car_code", car_code); Intent i = new Intent(GetCarDetails.this, JobSelectActivity.class); i.putExtras(b); startActivity(i); finish(); } else { String message = car_data.get("result").equals("0") ? "Nothing scheduled" : "This one is done, take another"; Toast.makeText(GetCarDetails.this, message, Toast.LENGTH_LONG).show(); Intent mainIntent = new Intent(GetCarDetails.this, ReadChassisActivity.class); startActivity(mainIntent); finish(); } } catch (JSONException e) { Log.d("TESTE", e.toString()); Toast.makeText(getApplicationContext(), "Error has happened", Toast.LENGTH_LONG).show(); Intent choiceIntent = new Intent(GetCarDetails.this, ReadChassisActivity.class); startActivity(choiceIntent); finish(); } } } }
3. 规范ReadChassisActivity的请求码
你的BARCODE_READER_REQUEST_CODE未初始化,默认值为0,虽然能工作,但容易和系统默认请求码冲突,建议定义成常量:
private static final int BARCODE_READER_REQUEST_CODE = 100;
为什么加sleep能缓解?
加1秒sleep本质是让主线程在启动GetCarDetails前短暂等待,给AsyncTask的网络请求留出一点缓冲时间,避免主线程立即被get()阻塞。但这只是临时方案,解决主线程阻塞才是根本。
调试问题的修复说明
修复上述问题后,主线程不再被阻塞,调试断点应该能正常触发了——之前调试不可靠就是因为主线程卡死,调试器无法正常和应用交互。
内容的提问来源于stack exchange,提问作者edwardffs

