Android定位--GPS定位与LBS基站定位

虽然现在第三方的定位非常强大,非常方便,但是我们在只需要很简单的定位,且不想用第三方的时候,我们可以自己动动手,基于GPS卫星定位和LBS基站定位的方式获取当前位置。

GPS定位

1.权限申请

首先我们需要申请权限,6.0以下系统在mainfest文件申请,因为需要通过网络获取经纬度对应的详细地址,所以需要INTERNET权限。代码如下:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/> 

6.0以上系统需要在Activity里面动态申请权限,首先判断定位权限是否被用户允许,如果没有允许,就需要申请定位权限。

//检查定位权限是否已经允许
if (ContextCompat.checkSelfPermission(this,
        Manifest.permission.ACCESS_FINE_LOCATION)
        != PackageManager.PERMISSION_GRANTED) {
    //申请定位权限
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
            PERMISSIONS_FINE_LOCATION);
} else {
    //定位权限已经被允许
}

当申请权限的时候,会弹出提示用户是否允许申请的权限:
这里写图片描述

2.通过LocationManager获取定位

LocationManager的使用还是非常简单的,首先拿到他的实例,然后通过public void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener);方法设置监听并请求定位。

LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

/**
 * GPS定位监听器
 */
LocationListener locationListener = new LocationListener() {

    /**
     * 位置信息变化时触发
     */
    @Override
    public void onLocationChanged(Location location) {
        //位置信息变化时触发
        LogUtils.i(TAG, "纬度:" + location.getLatitude() + "  经度:" + location.getLongitude()
                + "  海拔:" + location.getAltitude() + "  时间:" +
                TimeUtils.milliseconds2String(location.getTime(), TimeUtils.TimeFormat.yyyy_MM_dd_HH$mm$ss));
        GPSLocation.this.location = location;
    }

    /**
     * GPS状态变化时触发
     */
    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        LogUtils.i(provider);
        switch (status) {
            //GPS状态为可见时
            case LocationProvider.AVAILABLE:
                LogUtils.i(TAG, "当前GPS状态为可见状态");
                break;
            //GPS状态为不在服务区
            case LocationProvider.OUT_OF_SERVICE:
                LogUtils.i(TAG, "当前GPS状态为不在服务区状态");
                location = null;
                break;
            //GPS状态为暂停服务时
            case LocationProvider.TEMPORARILY_UNAVAILABLE:
                LogUtils.i(TAG, "当前GPS状态为暂停服务状态");
                location = null;
                break;
        }
    }

    /**
     * 被用户开启后调用
     */
    @Override
    public void onProviderEnabled(String provider) {
        LogUtils.i(TAG, "用户打开了GPS");
    }

    /**
     * 被用户关闭后调用
     */
    @Override
    public void onProviderDisabled(String provider) {
        LogUtils.i(TAG, "用户关闭了GPS");
        location = null;
    }
};

/**
 * 绑定监听
 * 参数1,设备:有GPS_PROVIDER和NETWORK_PROVIDER两种,前者是GPS,后者是GPRS以及WIFI定位
 * 参数2,位置更新的最小时间间隔,以毫秒为单位
 * 参数3,位置变化最小距离:当位置距离变化超过此值时,将更新位置信息,单位米
 * 参数4,监听
 * 备注:参数2和3,如果参数3不为0,则以参数3为准;参数3为0,则通过时间来定时更新;两者为0,则随时刷新
 */
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10 * 1000, 100, locationListener);

通过上面的代码我们可以看到,定位的信息都是通过LocationListener监听回调的onLocationChanged(Location location)方法的参数传递回来,Location里面保存了经纬度以及海拔等信息。如果我们需要将经纬度转换为详细地理位置,则需要再想办法;
通过免费接口http://api.cellocation.com/regeo/?lat=34.232525&lon=108.91308166666667&output=json 可以将经纬度以详细地理位置返回给我们。

LBS基站定位

同样需要权限许可,有上面的权限即可

基站定位需要LBS数据仓库提供支持,我这里使用http://www.cellocation.com/interfac/提供的免费接口。
基站定位需要
* MCC: 国家代码:中国代码 460
* MNC,移动设备网络代码(Mobile Network Code,MNC),中国移动 = 00,中国联通 = 01, 中国电信 = 03 05 11
* LAC,Location Area Code,位置区域码;
* CID,Cell Identity,基站编号,是个16位的数据(范围是0到65535)。

所以我们先将这几个参数获取到,通过TelephonyManager可以获取我们需要的基站信息。具体代码如下:

/**
 *  基站信息
 *  MCC: 国家代码:中国代码 460
 *  MNC,移动设备网络代码(Mobile Network Code,MNC),中国移动 = 00,中国联通 = 01, 中国电信 = 03 05 11
 *  LAC,Location Area Code,位置区域码;
 *  CID,Cell Identity,基站编号,是个16位的数据(范围是0到65535)。
 */
public static class StationInfo{
    private int MCC;
    private int MNC;
    private int LAC;
    private int CID;
    get and set...
}


/**
 * 获取基站信息
 */
private StationInfo getCellInfo() {
    StationInfo stationInfo = new StationInfo();

    /** 调用API获取基站信息 */
    TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);

    if (!hasSimCard(mContext)){ //判断有没有sim卡,如果没有安装sim卡下面则会异常
        Toast.makeText(mContext,"请安装sim卡",Toast.LENGTH_LONG).show();
        return null;
    }
    String operator = telephonyManager.getNetworkOperator();
    LogUtils.e("operator","operator="+operator);
    int mcc = Integer.parseInt(operator.substring(0, 3));
    int mnc = Integer.parseInt(operator.substring(3));

    //参考http://www.cellocation.com/interfac/
    int cid = 0;
    int lac = 0;
    if (mnc == 11 || mnc == 03 || mnc == 05){  //03 05 11 为电信CDMA
        CdmaCellLocation location = (CdmaCellLocation) telephonyManager.getCellLocation();
        //这里的值可根据接口需要的参数获取
        cid = location.getBaseStationId();
        lac = location.getNetworkId();
        mnc = location.getSystemId();    
    } else {
        GsmCellLocation location = (GsmCellLocation) telephonyManager.getCellLocation();
        cid = location.getCid();
        lac = location.getLac();
    }

    /** 将获得的数据放到结构体中 */
    stationInfo.setMCC(mcc);
    stationInfo.setMNC(mnc);
    stationInfo.setLAC(lac);
    stationInfo.setCID(cid);

    return stationInfo;
}

接下来将获取到的 MCC, MNC, LAC, CID 数据通过接口请求获取经纬度和详细位置:

/**
 * 通过此方法请求定位信息
 */
public void request() {
    String url = "http://api.cellocation.com/cell/?mcc=%1$s&mnc=%2$s&lac=%3$s&ci=%4$s&output=json";

    StationInfo info = getCellInfo();

    if (info == null) {
        listener.onFailed();
        return;
    }
    LogUtils.i(info.toString());
    url = String.format(url, info.getMCC(), info.getMNC(), info.getLAC(), info.getCID());
    //通过网络请求获取经纬度和详细位置
    getLocation(url);
}

下面我们看一下效果图:
这里写图片描述

其实我这里测试LBS定位比GPS定位出来的详细信息更加准确,GPS定位超级费电,可能是我这手机比较low,打开一会儿手机就发热,电池掉的也飞快。

GIT地址: https://code.csdn.net/chengliang0315/locationtest.git

压缩包 : http://download.csdn.net/detail/chengliang0315/9724818

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值