所以我正在尝试为我的应用添加一些功能,以便它可以允许用户在编辑框中获取其位置而不必键入它。
目前我有一个“工作示例”,但其中有一个奇怪的错误:第一次启动应用程序并单击按钮获取位置时,应用程序崩溃。它不会再发生,除非你重新安装应用程序,它再次只会崩溃一次。这似乎只发生在Android 6.0 +设备上(4.4和5.0都没有崩溃)。 有时它并没有真正获得位置,只是一直返回null。
我想有更好的方法来获取位置,但这是我第一次尝试获取用户的位置,所以我不知道。
所以我的问题基本上就是2个问题 - 是否有更好的方法可以获得适用于Android 4.4+的位置以及为什么我的应用程序会因为非常奇怪的错误而崩溃。
错误:
system_process E/ActivityManager: Sending non-protected broadcast projekt.substratum.APP_CRASHED from system 820:system/1000 pkg android
java.lang.Throwable
at com.android.server.am.ActivityManagerService.checkBroadcastFromSystem(ActivityManagerService.java:17973)
at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:18545)
at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:18636)
at android.app.ContextImpl.sendBroadcast(ContextImpl.java:881)
at com.android.server.am.AppErrors.crashApplicationInner(AppErrors.java:370)
at com.android.server.am.AppErrors.crashApplication(AppErrors.java:305)
at com.android.server.am.ActivityManagerService.handleApplicationCrashInner(ActivityManagerService.java:13554)
at com.android.server.am.ActivityManagerService.handleApplicationCrash(ActivityManagerService.java:13536)
at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:1660)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2813)
at android.os.Binder.execTransact(Binder.java:565)
我正在使用的位置类(不是由我编写的,只进行了少量编辑)
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
public class ProviderLocationTracker implements LocationListener,LocationTracker {
// The minimum distance to change Updates in meters
private static final long MIN_UPDATE_DISTANCE = 10;
// The minimum time between updates in milliseconds
private static final long MIN_UPDATE_TIME = 1000 * 60;
private LocationManager lm;
public enum ProviderType{
NETWORK,
GPS
};
private String provider;
private Location lastLocation;
private long lastTime;
private boolean isRunning;
private LocationUpdateListener listener;
public ProviderLocationTracker(Context context, ProviderType type) {
lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
Criteria crit = new Criteria();
crit.setAccuracy(Criteria.ACCURACY_FINE);
if(type == ProviderType.NETWORK){
provider = LocationManager.NETWORK_PROVIDER;
}
else{
provider = LocationManager.GPS_PROVIDER;
}
provider = lm.getBestProvider(crit, true);
}
public String returnProvider(){
return provider;
}
public void start(){
if(isRunning){
//Already running, do nothing
return;
}
//The provider is on, so start getting updates. Update current location
isRunning = true;
lm.requestLocationUpdates(provider, MIN_UPDATE_TIME,MIN_UPDATE_DISTANCE, this);
lastLocation = null;
lastTime = 0;
return;
}
public void start(LocationUpdateListener update) {
start();
listener = update;
}
public void stop(){
if(isRunning){
lm.removeUpdates(this);
isRunning = false;
listener = null;
}
}
public boolean hasLocation(){
if(lastLocation == null){
return false;
}
if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
return false; //stale
}
return true;
}
public boolean hasPossiblyStaleLocation(){
if(lastLocation != null){
return true;
}
return lm.getLastKnownLocation(provider)!= null;
}
public Location getLocation(){
if(lastLocation == null){
return null;
}
if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
return null; //stale
}
return lastLocation;
}
public Location getPossiblyStaleLocation(){
if(lastLocation != null) {
return lastLocation;
}
return lm.getLastKnownLocation(provider);
}
public void onLocationChanged(Location newLoc) {
long now = System.currentTimeMillis();
if(listener != null){
listener.onUpdate(lastLocation, lastTime, newLoc, now);
}
lastLocation = newLoc;
lastTime = now;
}
public void onProviderDisabled(String arg0) {
}
public void onProviderEnabled(String arg0) {
}
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
}
获取按钮单击侦听器上的位置:
if (checkLocationPermission()) {
if (ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
//Request location updates:
getLocation();
}
}
getLocation方法:
public void getLocation(){
//In case we havent started it somehow, just returns if we did
location.start();
double alti;
double longti;
if(location.hasLocation()){
if (location.getLocation() != null) {
alti = location.getLocation().getLatitude();
longti = location.getLocation().getLongitude();
locationText.setText(alti +","+longti);
}else{
locationText.setText("1Couldn't get location, check your GPS/NETWORK");
}
}else{
if (location.getPossiblyStaleLocation() != null) {
alti = location.getPossiblyStaleLocation().getLatitude();
longti = location.getPossiblyStaleLocation().getLongitude();
locationText.setText(alti + "," + longti);
}else{
locationText.setText("2Couldn't get location, check your GPS/NETWORK");
}
}
}
解决了崩溃问题,正如@Giovanni Terlingen所说,这是由我手机上的主题引擎引起的。剩下的问题是GPS定位并不总是有效 - 对于较旧的手机,它不能通过GPS获得位置,但Criteria无论如何都将GPS指定为提供商。 有没有更好的方法可以将设备的位置从KitKat转移到可能的奥利奥?
答案 0 :(得分:1)
这似乎只发生在Android 6.0 +设备上
自Android 6.0起,引入了权限。确保您的应用在Android 6.0及更高版本上具有位置访问权限。您应该通知用户您想要访问他/她的位置。请参阅此有用链接:
https://developer.android.com/training/permissions/requesting.html