Android GPS 定位流程

Android P 代码:http://androidxref.com/9.0.0_r3/

上一篇幅我们梳理了位置开关打开的一个流程,这里我们梳理下请求Gps定位的一个流程

这里我们假设一个app发起Gps定位,首先调用 LocationManager 接口,通过AIDL最终调用到 LocationManagerService 里面的  requestLocationUpdates 方法:

http://androidxref.com/9.0.0_r3/xref/frameworks/base/location/java/android/location/LocationManager.java#requestLocationUpdates

553    @RequiresPermission(anyOf = {
 
 ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
554    public void requestLocationUpdates(String provider, long minTime, float minDistance,
555            LocationListener listener) {
556        checkProvider(provider);
557        checkListener(listener);
558
559        LocationRequest request = LocationRequest.createFromDeprecatedProvider(  ---> 封装成LocationRequest,作为参数传下去
560                provider, minTime, minDistance, false);
561        requestLocationUpdates(request, listener, null, null);
562    }

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/LocationManagerService.java#requestLocationUpdates

2061    public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2062            PendingIntent intent, String packageName) {
2063        if (request == null) request = DEFAULT_LOCATION_REQUEST;
2064        checkPackageName(packageName);
2065        int allowedResolutionLevel = getCallerAllowedResolutionLevel();   ---> 这里指的就是 fine、coarse、no location data 三种
2066        checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2067                request.getProvider());
2068        WorkSource workSource = request.getWorkSource();
2069        if (workSource != null && !workSource.isEmpty()) {
2070            checkDeviceStatsAllowed();
2071        }
2072        boolean hideFromAppOps = request.getHideFromAppOps();
2073        if (hideFromAppOps) {
2074            checkUpdateAppOpsAllowed();
2075        }
2076        boolean callerHasLocationHardwarePermission =
2077                mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2078                        == PERMISSION_GRANTED;
2079        LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel,
2080                callerHasLocationHardwarePermission);
2081
2082        final int pid = Binder.getCallingPid();
2083        final int uid = Binder.getCallingUid();
2084        // providers may use public location API's, need to clear identity
2085        long identity = Binder.clearCallingIdentity();
2086        try {
2087            // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2088            // a location.
2089            checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
2090
2091            synchronized (mLock) {
2092                Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
2093                        packageName, workSource, hideFromAppOps);
2094                requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);  ---> 继续看下这个
2095            }
2096        } finally {
2097            Binder.restoreCallingIdentity(identity);
2098        }
2099    }
2101    private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2102            int pid, int uid, String packageName) {
2103        // Figure out the provider. Either its explicitly request (legacy use cases), or
2104        // use the fused provider
2105        if (request == null) request = DEFAULT_LOCATION_REQUEST;
2106        String name = request.getProvider();   ---> 获取此时的provide,下面就是根据这个provide决定走GPS还是走network,所以不能为空
2107        if (name == null) {
2108            throw new IllegalArgumentException("provider name must not be null");
2109        }
### Android GPS 定位 Framework 的工作流程 #### 1. **硬件层面** GPS 数据的采集始于设备中的 GPS 芯片。该芯片通过天线接收卫星信号并解析成原始定位数据。这些数据通常以 NMEA (National Marine Electronics Association) 协议的形式存在,这是一种标准化的数据格式,用于描述位置、速度和其他导航信息[^1]。 #### 2. **Linux 驱动层** 在 Android 设备中,GPS 模块与操作系统之间的通信依赖于 Linux 内核驱动程序。此驱动负责管理 GPS 芯片与系统间的 I/O 操作,并将接收到的 NMEA 数据传递给更高层次的软件栈。具体来说,它会将数据写入特定的文件节点(如 `/dev/gps` 或其他路径),以便后续组件读取[^2]。 #### 3. **HAL 层** Hardware Abstraction Layer (HAL) 是连接底层硬件和上层框架的关键部分。对于 GPS 功能而言,HAL 提供了一组 API 接口,允许 Android 系统访问 GPS 模块的功能而无需关心具体的实现细节。当有新的 NMEA 句子到达时,HAL 将其转发至 Framework 层处理[^2]。 #### 4. **Framework 层** 进入 Framework 后,主要由 `LocationManagerService` 和相关类来管理和分发位置更新事件。以下是几个重要环节: - **注册监听器** 应用开发者可以调用 `addNmeaListener()` 方法设置一个回调函数,在每次收到新 NMEA 字符串时触发相应的逻辑操作。例如,在样例代码片段中展示了如何打印每条消息的内容到控制台[^1]。 - **权限验证** 在实际开发过程中需要注意申请必要的权限声明,比如 `ACCESS_FINE_LOCATION`, `ACCESS_COARSE_LOCATION` 等,否则无法正常获取地理位置信息。 - **数据转换与优化** 原始的 NMEA 数据可能并不完全适合直接展示或者进一步计算使用,因此在此阶段还涉及到坐标系变换以及误差修正等工作。 #### 5. **应用层** 最后一步就是把经过加工后的地理坐标呈现给最终用户界面或者是作为输入参数参与某些业务场景下的运算过程。例如地图标注当前位置点、规划出行路线等功能均属于这一范畴内的典型应用场景之一。 ```java public class GpsTestActivity extends AppCompatActivity { private LocationManager locationManager; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); // 初始化服务对象实例化 locationManager = (LocationManager)getSystemService(LOCATION_SERVICE); try{ // 添加NMEA监听者 locationManager.addNmeaListener(new GpsStatus.NmeaListener(){ @Override public void onNmeaReceived(long timestamp,String nmea){ Log.d("GpsTest","Timestamp:"+timestamp+",Data:"+nmea); } }); }catch(SecurityException e){ e.printStackTrace(); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值