android中利用GPS获取位置信息的源码分析

下面是很常见的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);
    }
}


转载于:https://my.oschina.net/kutengshe/blog/418651

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值