第一行代码——第十一章:Android特色开发——基于位置的服务

目录:

11.1 基于位置的服务简介

11.2 申请API Key

11.3 使用百度定位

11.3.1 准备LBS SDK

11.3.2 确定自己位置的经纬度

11.3.3 选择定位模式

11.3.4 看得懂的位置信息

11.4 使用百度地图

11.4.1 让地图显示出来

11.4.2 移动到我的位置

11.4.3 让“我”显示在地图上

11.5 Git 时间——版本控制工具的高级用法

11.5.1 分支的用法

11.5.2 与远程版本库协作

11.6 小结与点评


知识点:

11.1 基于位置的服务简介

基于位置的服务简称LBS,主要的工作原理是利用无线电通讯网络或 GPS 等定位方式来确定出移动设备所在的位置。

LBS 所围绕的核心就是要确定出用户所在的位置。通常有两种技术:

  • GPS 定位
     基于手机内置的 GPS 硬件直接和卫星交互来获取当前的经纬度信息,精确度高,但只能室外使用,室内基本无法接收到卫星的信号。

  • 网络定位
     根据手机当前网络附近的三个基站进行测速,以此计算出手机和每个基站之间的距离,再通过三角定位确定一个大概位置,精确度一般,但室内外均可使用。

本章主要学习百度在 LBS 方面提供的一些功能。

11.2 申请API Key

要想在自己的应用程序里使用百度LBS功能,必须要申请一个API Key,你得拥有一个百度账号,并打开http://developer.baidu.com/user/info 这个网址,在这里填写一些注册信息即可。

创建应用 

è¿éåå¾çæè¿°

è¿éåå¾çæè¿°

那么这个发布版SHA1和开发版SHA1 又是个什么东西呢?

这是我么申请API Key所必须要填写的字段,指的是打包程序时所用签名文件的SHA1指纹,通过Android Studio 点击右侧工具栏Gradle 项目名  app tasks android 双击 signingReport 

如此 即可看到这是Android 自动生成用于测试的签名文件,而当程序发布时需要创建一个正式的签名文件 然后在cmd中输入如下命令:
keytool -list -v -keystore <签名文件路径>  即可。

11.3 使用百度定位

11.3.1 准备LBS SDK

在编码之前,先将百度 LBS 开放平台的 SDK 准备好,下载地址:http://lbsyun.baidu.com/sdk/download

本章会用到基础地图和基础定位这两个 SDK,下载完后对该压缩包解压,libs 目录里就有我们所需要的一切了:

压缩包libs目录下的内容

下面把 libs 目录里的内容拷贝到我们的项目中:
 (1)把 BaiduLBS_Android.jar 拷贝到项目 app 模块中的 libs 目录:

将 jar 包放置到 libs 目录中

(2)展开 src/main 目录,右击该目录→New→Directory,创建一个名为 jniLibs 的目录,用来存放 so 包,然后把压缩包里的其他所以目录直接复制到这里:

将 so 文件放置到 jniLibs 目录中

另外,记得点击顶部工具栏中的 Sync 按钮(下图中最左边的按钮)将 BaiduLBS_Android.jar 添加到当前项目的引用中。

AS 顶部工具栏

以上就把 LBS 的 SDK 都准备好了。

11.3.2 确定自己位置的经纬度

首先在 AndroidManifest 中添加开发密钥、所需权限等信息:
 (1)在 application 中添加开发密钥

<application>  
    <meta-data  
        android:name="com.baidu.lbsapi.API_KEY"  
        android:value="开发者 key" />  
</application>

(2)添加所需权限

<!-- 百度 LBS 相关权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

(3)再注册一个百度 LBS SDK 中的服务

<service
    android:name="com.baidu.location.f"
    android:enabled="true"
    android:process=":remote">
</service>

接下来在布局添加个 TextView 来显示当前位置的经纬度:

public class LocationActivity extends AppCompatActivity {
    
    private LocationClient mLocationClient;
    
    private TextView tv_show_location;// 显示当前位置信息

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 构建 LocationClient 实例
        mLocationClient = new LocationClient(getApplicationContext());
        // 注册一个定位监听器
        mLocationClient.registerLocationListener(new MyLocationListener());
        setContentView(R.layout.activity_location);
        
        tv_show_location = (TextView) findViewById(R.id.tv_show_location);

        // 声明权限,将权限添加到list集合中再一次性申请
        List<String> permissionList = new ArrayList<>();
        if (ActivityCompat.checkSelfPermission(LocationActivity.this,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }
        if (ActivityCompat.checkSelfPermission(LocationActivity.this,
                Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
        }
        if (ActivityCompat.checkSelfPermission(LocationActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
        if (!permissionList.isEmpty()) {
            String[] permissions = permissionList.toArray(new String[permissionList.size()]);
            ActivityCompat.requestPermissions(LocationActivity.this,permissions,1);
        }else {
            requestLocation();
        }
    }

    /**
     * 开始地理位置定位
     */
    private void requestLocation() {
        mLocationClient.start();
    }


    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        switch (requestCode){
            case 1:
                if (grantResults.length > 0 ){
                    for (int result : grantResults){
                        if (result != PackageManager.PERMISSION_GRANTED){
                            ToastUtils.showShort("必须同意所有权限才能使用本程序");
                            finish();
                            return;
                        }
                    }
                    requestLocation();
                }else {
                    ToastUtils.showShort("发生未知错误");
                    finish();
                }
                break;

            default:
                break;
        }
    }
    
    // 监听器
    public class MyLocationListener implements BDLocationListener{

        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            StringBuilder currentLocation = new StringBuilder();
            currentLocation.append("纬度:").append(bdLocation.getLatitude()).append("\n");
            currentLocation.append("经线:").append(bdLocation.getAltitude()).append("\n");
            currentLocation.append("定位方式:");
            if (bdLocation.getLocType() == BDLocation.TypeGpsLocation){
                currentLocation.append("GPS");
            } else if (bdLocation.getLocType() == BDLocation.TypeNetWorkLocation){
                currentLocation.append("网络");
            }
            tv_show_location.setText(currentLocation);
        }
    }
}

地理位置定位的结果

在默认情况下,调用 LocationClient 的 start() 的方法只会定位一次,若要实时更新当前的位置,还需添加如下代码:

public class LocationActivity extends AppCompatActivity {

    . . .

   /**
     * 开始地理位置定位
     */
    private void requestLocation() {
        initLocation();
        mLocationClient.start();
    }

    private void initLocation() {
        // 创建LocationClientOption 对象
        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(5000);  //5秒钟更新下当前位置
        mLocationClient.setLocOption(option);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocationClient.stop();//停止定位
    }
}

这样界面上的经纬度信息就会跟着位置变化一起变化。

11.3.3 选择定位模式

GPS功能必须要由用户主动去开启才行,不然任何应用程序都无法使用GPS获取到手机当前的位置信息。

共有3种模式:

  • Hight_Accuracy
     高精度模式(默认模式),会在GPS信号正常的情况下优先使用GPS定位,在无法接收GPS信号时用网络定位。

  • Battery_Saving
     节电模式,只会使用网络定位。

  • Device_Sensors
     传感器模式,只会使用GPS定位。

强制使用Gps进行定位。

option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);

11.3.4 看得懂的位置信息

虽然我们获取到了经纬度,但是一般人是根本看不懂的,接下来学习如何获取看得懂的位置信息吧。

private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(5000);  
        //需要获取当前位置的详细信息
        option.setIsNeedAddress(true);
        mLocationClient.setLocOption(option);
    }

    // 监听器
    public class MyLocationListener implements BDLocationListener{

        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            StringBuilder currentLocation = new StringBuilder();
            currentLocation.append("纬度:").append(bdLocation.getLatitude()).append("\n");
            currentLocation.append("经线:").append(bdLocation.getAltitude()).append("\n");
            currentLocation.append("国家:").append(bdLocation.getCountry()).append("\n");
            currentLocation.append("省:").append(bdLocation.getProvince()).append("\n");
            currentLocation.append("市:").append(bdLocation.getCity()).append("\n");
            currentLocation.append("区:").append(bdLocation.getDistrict()).append("\n");
            currentLocation.append("街道:").append(bdLocation.getStreet()).append("\n");
            currentLocation.append("定位方式:");
            if (bdLocation.getLocType() == BDLocation.TypeGpsLocation){
                currentLocation.append("GPS");
            } else if (bdLocation.getLocType() == BDLocation.TypeNetWorkLocation){
                currentLocation.append("网络");
            }
            tv_show_location.setText(currentLocation);
        }
    }

11.4 使用百度地图

11.4.1 让地图显示出来

需要用到百度提供的自定义控件 MapView

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.wonderful.myfirstcode.chapter11.MapActivity">
    
    <!-- 显示地图控件 -->
    <com.baidu.mapapi.map.MapView
        android:id="@+id/map_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"/>

</RelativeLayout>

活动中的代码:

对于生命周期的处理,是为了资源的及时释放

public class MapActivity extends AppCompatActivity {

    private MapView mapView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 初始化操作,在 setContentView() 方法前调用
        SDKInitializer.initialize(getApplicationContext()); 
        setContentView(R.layout.activity_map);

        mapView = (MapView) findViewById(R.id.map_view);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }
}

效果图:

11.4.2 移动到我的位置

百度 LBS SDK 的 API 中提供了一个** BaiduMap** 类,是地图的总控制器,有了它就能对地图进行各种各样的操作了。获取其实例如下:

BaiduMap baiduMap = mapView.getMap();

  百度地图将缩放级别的取值范围限定在3到19之间,也可取小数点位,值越大地图显示信息越精细,如把缩放级别设置成12.5,可以这样写:

MapStatusUpdate update = MapStatusUpdateFactory.zoomTo(12.5f);
baiduMap.animateMapStatus(update);

  若要让地图移动到某个经纬度上,可以借助 LatLng 类,如将地图移动到北纬39.915°、东经116.404°,可以这样写:

LatLng ll = new LatLng(39.915,116.404);
MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
baiduMap.animateMapStatus(update);

  接下来实现下 “移动到我的位置” 这个功能,修改活动中代码如下:

public class MapActivity extends AppCompatActivity {

    private LocationClient mLocationClient;

    private MapView mapView;

    private BaiduMap baiduMap;

    // 避免多次调用animateMapStatus() 方法
    private boolean isFirstLocate = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLocationClient = new LocationClient(getApplicationContext());
        mLocationClient.registerLocationListener(new MyLocationListener());
        SDKInitializer.initialize(getApplicationContext());
        setContentView(R.layout.activity_map);

        mapView = (MapView) findViewById(R.id.map_view);
        baiduMap = mapView.getMap();
        . . .
    }

   /**
     * 把地图移动到当前位置
     * @param location
     */
    private void navigateTo(BDLocation location){
        if (isFirstLocate){
            LatLng ll = new LatLng(location.getLatitude(),location.getLongitude());
            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
            baiduMap.animateMapStatus(update);
            update = MapStatusUpdateFactory.zoomTo(16f);
            baiduMap.animateMapStatus(update);
            isFirstLocate = false;
        }
    }

    // 监听器
    public class MyLocationListener implements BDLocationListener{

        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            if (bdLocation.getLocType() == BDLocation.TypeGpsLocation ||
                    bdLocation.getLocType() == BDLocation.TypeNetWorkLocation){
                navigateTo(bdLocation);
            }
        }
    }

    . . .
}

 

11.4.3 让“我”显示在地图上

  百度 LBS SDK 当中提供了一个 MyLocationData.Builder 类,这个类是用来封装设备当前所在位置的,只需将经纬度信息传入到它相应的方法就可以,如下:

MyLocationData.Builder locationBuilder = new MyLocationData.Builder();
locationBuilder.latitude(39.915);
locationBuilder.longitude(116.404);

  设置完要封装的信息后调用 MyLocationData.Builder 类中的 build() 方法,就会生成一个 MyLocationData 实例,把这个实例传入到 BaiduMap 的 setMyLocationData() 方法中,就可以让设备当前位置显示在地图上了,如下:

MyLocationData locationData = locationBuilder.build();
baiduMap.setMyLocationData(locationData);

  下面贴上完整的代码:

public class MapActivity extends AppCompatActivity {

    private LocationClient mLocationClient;

    private MapView mapView;

    private BaiduMap baiduMap;

    private boolean isFirstLocate = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLocationClient = new LocationClient(getApplicationContext());
        mLocationClient.registerLocationListener(new MyLocationListener());
        SDKInitializer.initialize(getApplicationContext());
        setContentView(R.layout.activity_map);

        mapView = (MapView) findViewById(R.id.map_view);
        baiduMap = mapView.getMap();
        baiduMap.setMyLocationEnabled(true);

        // 声明权限,将权限添加到list集合中再一次性申请
        List<String> permissionList = new ArrayList<>();
        if (ActivityCompat.checkSelfPermission(MapActivity.this,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }
        if (ActivityCompat.checkSelfPermission(MapActivity.this,
                Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
        }
        if (ActivityCompat.checkSelfPermission(MapActivity.this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
        if (!permissionList.isEmpty()) {
            String[] permissions = permissionList.toArray(new String[permissionList.size()]);
            ActivityCompat.requestPermissions(MapActivity.this,permissions,1);
        }else {
            requestLocation();
        }
    }

    /**
     * 开始地理位置定位
     */
    private void requestLocation() {
        initLocation();
        mLocationClient.start();
    }

    private void initLocation() {
        LocationClientOption option = new LocationClientOption();
        option.setScanSpan(5000);  //5秒钟更新下当前位置
        option.setIsNeedAddress(true);
        mLocationClient.setLocOption(option);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        switch (requestCode){
            case 1:
                if (grantResults.length > 0 ){
                    for (int result : grantResults){
                        if (result != PackageManager.PERMISSION_GRANTED){
                            ToastUtils.showShort("必须同意所有权限才能使用本程序");
                            finish();
                            return;
                        }
                    }
                    requestLocation();
                }else {
                    ToastUtils.showShort("发生未知错误");
                    finish();
                }
                break;

            default:
                break;
        }
    }

    /**
     * 把地图移动到当前位置
     * @param location
     */
    private void navigateTo(BDLocation location){
        if (isFirstLocate){
            LatLng ll = new LatLng(location.getLatitude(),location.getLongitude());
            MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
            baiduMap.animateMapStatus(update);
            update = MapStatusUpdateFactory.zoomTo(16f);
            baiduMap.animateMapStatus(update);
            isFirstLocate = false;
        }
        
        MyLocationData.Builder locationBuilder = new MyLocationData.Builder();
        locationBuilder.latitude(location.getLatitude());
        locationBuilder.longitude(location.getLongitude());
        MyLocationData locationData = locationBuilder.build();
        baiduMap.setMyLocationData(locationData);
    }

    // 监听器
    public class MyLocationListener implements BDLocationListener{

        @Override
        public void onReceiveLocation(BDLocation bdLocation) {
            if (bdLocation.getLocType() == BDLocation.TypeGpsLocation ||
                    bdLocation.getLocType() == BDLocation.TypeNetWorkLocation){
                navigateTo(bdLocation);
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLocationClient.stop();
        mapView.onDestroy();
        baiduMap.setMyLocationEnabled(false);
    }
}

  关于百度 LBS SDK 的用法入门就介绍到这,更多用法参考官方网站:http://lbsyun.baidu.com/ 。建议根据官网开发指南来进行学习。

11.5 Git 时间——版本控制工具的高级用法

11.5.1 分支的用法

11.5.2 与远程版本库协作

关于Git 相关的内容请移驾:

https://blog.csdn.net/lhk147852369/article/details/84307580

11.6 小结与点评

郭霖总结:

不得不说,本章中学到的知识应该还算是蛮有趣的吧?在这次的Android特色开发环节中我们主要学习了基于位置服务的工作原理和用法,借助百度提供的LBS SDK,我们可以随时确定自己当前位置的经纬度,并且还能获取到具体的省、市、区、街道等地址。之后又学习了百度地图的用法,不仅成功地将地图信息显示了出来,还综合利用了前面所学到的定位技术实现了一个较为完整的例子。

除了基于位置的服务之外,本章Git时间中继续对Git的用法进行了更深一一步的探究, 使得我们对分支和远程版本库的使用都有了一一定层次的了解。

那么关于Android特色开发的内容就讲到这里,下一章中我们将会学习Android 5.0系统中新增的套全新的知识点一 Material Design。

我的总结:

这章本人并没有写任何的代码,(代码来源:网络)而是进行了通读,因为对于百度地图这一块,在我用到的时候会去看百度的官方文档,毕竟官方的东西才是最新的不是。不仅仅是百度地图,其他任何三方的东西,希望大家能够在官方去学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值