求助:需获取定位的Android App启动即崩溃(Logcat无报错)
定位App崩溃问题排查与修复方案
嘿,我帮你找出了几个直接导致App崩溃的核心问题,咱们一步步来解决:
1. 成员变量初始化时机错误导致空指针崩溃
你把TextView txtLocation = findViewById(R.id.txtLocation);放在了类的成员变量位置,这时候Activity还没执行onCreate方法,布局也还没通过setContentView加载完成,findViewById肯定会返回null。后续调用txtLocation.setText()的时候,就会触发NullPointerException直接崩溃。
修复:
把TextView的初始化移到setContentView之后,放在onCreate方法内部:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 移到这里,布局加载完成后再获取控件 TextView txtLocation = findViewById(R.id.txtLocation); // 后续定位逻辑... }
2. 权限判断逻辑写反,且未处理权限申请流程
你当前的权限判断条件逻辑有误:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_DENIED || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_DENIED)
虽然!= PERMISSION_DENIED等同于== PERMISSION_GRANTED,但这种写法不规范,更重要的是:如果用户没授权权限,你直接跳过了定位逻辑,但没有触发权限申请流程,用户永远无法授权,而且后续也没有重试机制。
修复:
先检查权限是否已授予,未授予则主动申请,申请后处理回调:
// 把LocationListener定义为Activity成员变量,方便权限回调复用 private LocationListener locationListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView txtLocation = findViewById(R.id.txtLocation); LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); locationListener = new LocationListener() { @Override public void onLocationChanged(Location location) { String locationText = String.format("Latitude: %s et longitude: %s", location.getLatitude(), location.getLongitude()); Log.d("GPS", locationText); txtLocation.setText(locationText); } @Override public void onStatusChanged(String provider, int status, Bundle extras) {} @Override public void onProviderEnabled(String provider) {} @Override public void onProviderDisabled(String provider) {} }; // 正确的权限判断逻辑 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) { // 已有权限,启动定位 assert locationManager != null; locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 10, locationListener); } else { // 无权限,申请定位权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, 1001); // 1001是自定义请求码,可自行修改 } } // 重写权限申请回调方法 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1001) { boolean hasGranted = false; // 检查是否有至少一个权限被授予 for (int result : grantResults) { if (result == PackageManager.PERMISSION_GRANTED) { hasGranted = true; break; } } if (hasGranted) { // 授权成功,重新启动定位 LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); assert locationManager != null; locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 10, locationListener); } else { // 权限被拒绝,提示用户 Toast.makeText(this, "需要定位权限才能获取位置信息", Toast.LENGTH_SHORT).show(); } } }
3. setText传入错误参数类型导致资源找不到崩溃
你写的这行代码有问题:
txtLocation.setText(Log.d("GPS", String.format("Latitude%s et longitude %s", location.getLatitude(), location.getLongitude())));
Log.d()的返回值是int类型(返回日志写入的字符数),而TextView.setText(int)会把这个int当成字符串资源的ID,系统找不到对应ID的资源时,就会抛出Resources$NotFoundException导致崩溃。
修复:
把日志打印和setText分开,先格式化好字符串,再分别处理:
String locationText = String.format("Latitude: %s et longitude: %s", location.getLatitude(), location.getLongitude()); Log.d("GPS", locationText); txtLocation.setText(locationText);
额外注意事项
- 别忘了在
AndroidManifest.xml中声明定位权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- 真机测试时要打开GPS,模拟器可以通过开发者选项模拟定位信息。
内容的提问来源于stack exchange,提问作者Vayhuit
相关产品推荐
相关产品推荐

