下面是很常见的GPS获取经纬度的代码:
LocationManager locationManager;
String serviceName = Context.LOCATION_SERVICE;
locationManager = (LocationManager) this.getSystemService(serviceName);
// 查找到服务信息
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE); // 高精度
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW); // 低功耗
String provider = locationManager.getBestProvider(criteria, true); // 获取GPS信息
Location location = locationManager.getLastKnownLocation(provider); // 通过GPS获取位置
updateToNewLocation(location);
// 设置监听器,自动更新的最小时间为间隔N秒(1秒为1*1000,这样写主要为了方便)或最小位移变化超过N米
locationManager.requestLocationUpdates(provider, 100 * 1000, 500,
locationListener);
Criteria类,源码(很容易理解的赋值语句):
public class Criteria implements Parcelable {
public Criteria() {}
public void setAccuracy(int accuracy) {
if (accuracy < NO_REQUIREMENT || accuracy > ACCURACY_COARSE) {
throw new IllegalArgumentException("accuracy=" + accuracy);
}
if (accuracy == ACCURACY_FINE) {
mHorizontalAccuracy = ACCURACY_HIGH;
} else {
mHorizontalAccuracy = ACCURACY_LOW;
}
}
public void setPowerRequirement(int level) {
if (level < NO_REQUIREMENT || level > POWER_HIGH) {
throw new IllegalArgumentException("level=" + level);
}
mPowerRequirement = level;
}
public void setAltitudeRequired(boolean altitudeRequired) {
mAltitudeRequired = altitudeRequired;
}
...
..
..
...
然后接触的就是一个叫做LocationManager的类,它中间用到的几个函数是:getBestProvider 和 getLastKnownLocation ,以及 requestLocationUpdate 这三个函数
public String getBestProvider(Criteria criteria, boolean enabledOnly) {
if (criteria == null) {
throw new IllegalArgumentException("criteria==null");
}
try {
return mService.getBestProvider(criteria, enabledOnly);
} catch (RemoteException ex) {
Log.e(TAG, "getBestProvider: RemoteException", ex);
}
return null;
}
这个函数里面的mService是什么呢?查看代码发现:
private ILocationManager mService;
出来另外一个类,ILocationManager.aidl里面有了声明
interface ILocationManager
{
String getBestProvider(in Criteria criteria, boolean enabledOnly);
}
在编译后会变为ILocationManager.java,然而真正的实现实在LocationManagerService.java里面(frameworks/base/services/java/com/android/server/)
public class LocationManagerService extends ILocationManager.Stub implements Runnable {
public String getBestProvider(Criteria criteria, boolean enabledOnly) {
List<String> goodProviders = getProviders(criteria, enabledOnly);
if (!goodProviders.isEmpty()) {
return best(goodProviders).getName();
}
// Make a copy of the criteria that we can modify
criteria = new Criteria(criteria);
// Loosen power requirement
int power = criteria.getPowerRequirement();
while (goodProviders.isEmpty() && (power != Criteria.NO_REQUIREMENT)) {
power = nextPower(power);
criteria.setPowerRequirement(power);
goodProviders = getProviders(criteria, enabledOnly);
}
if (!goodProviders.isEmpty()) {
return best(goodProviders).getName();
}
// Loosen accuracy requirement
int accuracy = criteria.getAccuracy();
while (goodProviders.isEmpty() && (accuracy != Criteria.NO_REQUIREMENT)) {
accuracy = nextAccuracy(accuracy);
criteria.setAccuracy(accuracy);
goodProviders = getProviders(criteria, enabledOnly);
}
if (!goodProviders.isEmpty()) {
return best(goodProviders).getName();
}
// Remove bearing requirement
criteria.setBearingRequired(false);
goodProviders = getProviders(criteria, enabledOnly);
if (!goodProviders.isEmpty()) {
return best(goodProviders).getName();
}
// Remove speed requirement
criteria.setSpeedRequired(false);
goodProviders = getProviders(criteria, enabledOnly);
if (!goodProviders.isEmpty()) {
return best(goodProviders).getName();
}
// Remove altitude requirement
criteria.setAltitudeRequired(false);
goodProviders = getProviders(criteria, enabledOnly);
if (!goodProviders.isEmpty()) {
return best(goodProviders).getName();
}
return null;
}
}
这段代码看起很长,但是就两步:一是用getProviders函数去给goodProviders赋值;二是从goodProviders中获得最好的,使用的是best(goodProviders)函数。然后我们一个一个击破,先来看getProviders函数
public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
try {
synchronized (mLock) {
return _getProvidersLocked(criteria, enabledOnly);
}
} catch (SecurityException se) {
throw se;
} catch (Exception e) {
Slog.e(TAG, "getProviders got exception:", e);
return null;
}
}
这里面用了另外一个函数,_getProviders,继续查看源码
private List<String> _getProvidersLocked(Criteria criteria, boolean enabledOnly) {
if (LOCAL_LOGV) {
Slog.v(TAG, "getProviders");
}
ArrayList<String> out = new ArrayList<String>(mProviders.size());
for (int i = mProviders.size() - 1; i >= 0; i--) {
LocationProviderInterface p = mProviders.get(i);
String name = p.getName();
if (isAllowedProviderSafe(name)) {
if (enabledOnly && !isAllowedBySettingsLocked(name)) {
continue;
}
if (criteria != null && !p.meetsCriteria(criteria)) {
continue;
}
out.add(name);
}
}
return out;
}
原来就是判断provider是否安全,然后放在一个ArrayList里面,然后来看best函数,注释我就直接写在代码里了
private LocationProviderInterface best(List<String> providerNames) {
ArrayList<LocationProviderInterface> providers;
//给ArrayList类型的providers赋值完成初始化工作
synchronized (mLock) {
providers = new ArrayList<LocationProviderInterface>(providerNames.size());
for (String name : providerNames) {
providers.add(mProvidersByName.get(name));
}
}
//如果只有一个provider,那就直接返回第一个
if (providers.size() < 2) {
return providers.get(0);
}
//根据耗电量去排序
Collections.sort(providers, new LpPowerComparator());
int power = providers.get(0).getPowerRequirement();
if (power < providers.get(1).getPowerRequirement()) {
return providers.get(0);
}
int idx, size;
ArrayList<LocationProviderInterface> tmp = new ArrayList<LocationProviderInterface>();
idx = 0;
size = providers.size();
while ((idx < size) && (providers.get(idx).getPowerRequirement() == power)) {
tmp.add(providers.get(idx));
idx++;
}
//根据精度去进行排排序
Collections.sort(tmp, new LpAccuracyComparator());
int acc = tmp.get(0).getAccuracy();
if (acc < tmp.get(1).getAccuracy()) {
return tmp.get(0);
}
ArrayList<LocationProviderInterface> tmp2 = new ArrayList<LocationProviderInterface>();
idx = 0;
size = tmp.size();
while ((idx < size) && (tmp.get(idx).getAccuracy() == acc)) {
tmp2.add(tmp.get(idx));
idx++;
}
//根据范围去进行排序然后返回结果
Collections.sort(tmp2, new LpCapabilityComparator());
return tmp2.get(0);
}
下面的两个函数跟上面几乎一样,我就不再解释了。
getLastKnown函数也一样用的mService
public Location getLastKnownLocation(String provider) {
if (provider == null) {
throw new IllegalArgumentException("provider==null");
}
try {
return mService.getLastKnownLocation(provider);
} catch (RemoteException ex) {
Log.e(TAG, "getLastKnowLocation: RemoteException", ex);
return null;
}
它的源函数为
public Location getLastKnownLocation(String provider) {
if (LOCAL_LOGV) {
Slog.v(TAG, "getLastKnownLocation: " + provider);
}
try {
synchronized (mLock) {
return _getLastKnownLocationLocked(provider);
}
} catch (SecurityException se) {
throw se;
} catch (Exception e) {
Slog.e(TAG, "getLastKnownLocation got exception:", e);
return null;
}
}
private Location _getLastKnownLocationLocked(String provider) {
checkPermissionsSafe(provider);
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
return null;
}
if (!isAllowedBySettingsLocked(provider)) {
return null;
}
return mLastKnownLocation.get(provider);
}
requestLocationUpdate同理
public void requestLocationUpdates(long minTime, float minDistance, Criteria criteria, PendingIntent intent) {
if (criteria == null) {
throw new IllegalArgumentException("criteria==null");
}
if (intent == null) {
throw new IllegalArgumentException("intent==null");
}
_requestLocationUpdates(null, criteria, minTime, minDistance, false, intent);
}
private void _requestLocationUpdates(String provider, Criteria criteria,
long minTime, float minDistance, boolean singleShot, PendingIntent intent) {
if (minTime < 0L) {
minTime = 0L;
}
if (minDistance < 0.0f) {
minDistance = 0.0f;
}
try {
mService.requestLocationUpdatesPI(provider, criteria, minTime, minDistance, singleShot, intent);
} catch (RemoteException ex) {
Log.e(TAG, "requestLocationUpdates: RemoteException", ex);
}
}
源函数为
public void requestLocationUpdatesPI(String provider, Criteria criteria,
long minTime, float minDistance, boolean singleShot, PendingIntent intent) {
if (criteria != null) {
// FIXME - should we consider using multiple providers simultaneously
// rather than only the best one?
// Should we do anything different for single shot fixes?
provider = getBestProvider(criteria, true);
if (provider == null) {
throw new IllegalArgumentException("no providers found for criteria");
}
}
try {
synchronized (mLock) {
requestLocationUpdatesLocked(provider, minTime, minDistance, singleShot,
getReceiver(intent));
}
} catch (SecurityException se) {
throw se;
} catch (IllegalArgumentException iae) {
throw iae;
} catch (Exception e) {
Slog.e(TAG, "requestUpdates got exception:", e);
}
}
private void requestLocationUpdatesLocked(String provider, long minTime, float minDistance,
boolean singleShot, Receiver receiver) {
LocationProviderInterface p = mProvidersByName.get(provider);
if (p == null) {
throw new IllegalArgumentException("provider=" + provider);
}
checkPermissionsSafe(provider);
// so wakelock calls will succeed
final int callingUid = Binder.getCallingUid();
boolean newUid = !providerHasListener(provider, callingUid, null);
long identity = Binder.clearCallingIdentity();
try {
UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, singleShot,
receiver, callingUid);
UpdateRecord oldRecord = receiver.mUpdateRecords.put(provider, r);
if (oldRecord != null) {
oldRecord.disposeLocked();
}
if (newUid) {
p.addListener(callingUid);
}
boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
if (isProviderEnabled) {
long minTimeForProvider = getMinTimeLocked(provider);
p.setMinTime(minTimeForProvider, mTmpWorkSource);
// try requesting single shot if singleShot is true, and fall back to
// regular location tracking if requestSingleShotFix() is not supported
if (!singleShot || !p.requestSingleShotFix()) {
p.enableLocationTracking(true);
}
} else {
// Notify the listener that updates are currently disabled
receiver.callProviderEnabledLocked(provider, false);
}
if (LOCAL_LOGV) {
Slog.v(TAG, "_requestLocationUpdates: provider = " + provider + " listener = " + receiver);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}