Android移动开发-在Android项目里调用基于高德地图API实现定位

基于地理位置服务的Android平台的开发对Android移动开发来说是非常重要的,基于地理位置服务的Android平台的开发是主要用于Android系统作为载体,我们可以利用定位出的位置进行许多丰富多彩的操作。比如说天气预报程序可以根据用户所在的位置自动选择城市,发微博的时候我们可以向朋友晒一下自己的地理位置,不认识路的时候随时打开地图就可以查询路线;如果你出门打车用滴滴或Uber打车,你可以看到附近司机所在的位置,当你创建订单时司机可以获取你所在的位置;如果想获取自己所在位置的周边的服务,我们可以打开高德地图或美团就能获取到的周边的小吃、银行、医院和电影院等。

那么如何在Android项目里调用基于高德地图API实现定位的开发呢?

  • 申请高德地图API Key

要想在自己的应用程序里加入高德地图的功能,首先必须申请一个API Key。你得拥有一个高德地图账号才能申请,申请好高德地图账号后那么就得在高德地图开放平台注册成为一名高德地图开发者。登录高德地图账号,并打开http://lbs.amap.com/这个网址,具体是怎样申请高德地图API Key的请看我之前发表的博客“Android移动开发-在Android项目里调用基于百度地图API实现定位”的文章,高德地图API Key的申请与百度地图API Key的申请相似,所以这里就不详细来说明。

  • 创建项目

按以下步骤新建一个 Empty Activity 的应用项目。

  1. 启动 Android Studio。如果您看到 Welcome to Android Studio 对话框,请选择 Start a new Android Studio project,否则,请点击 Android Studio 菜单栏中的 File,然后点击 New->New Project,按提示输入您的应用名称、公司域和项目位置。 然后点击 Next。
  2. 选择您的应用所需的机型。 如果您不能确定自己的需要,只需选择 Phone and Tablet。然后点击 Next。
  3. 在“Add an activity to Mobile”对话框中选择 Empty Activity。 然后点击 Next。
  4. 按提示输入 Activity 名称、布局名称和标题。 使用默认值即可。 然后点击 Finish。
  • 下载并安装地图开发包

官网下载按照需求下载开发包并解压。
以5.4.0版本的地图功能为例,解压后,得到一个 AMap3DMap_5.4.0.jar 文件和一个 armeabi 文件夹(文件夹中包含:libgdinamapv4sdk752.so、libgdinamapv4sdk752ex.so、libtbt3631.so、libwtbt144.so 四个so文件)。
操作步骤具体请参考 开发指南中的 Android Stuido 的jar和so文件安装步骤。

这里写图片描述

so的配置也可以参考demo给出的目录结构,如下图所示,在app工程路径下,新建libs,并在libs目录下放入对应不同CPU架构的so文件。这样工程并不会自动加载libs下的so,需在gradle编译时,通过加入代码: jniLibs.srcDir ‘libs’ 来说明so的路径为该libs路径。

这里写图片描述

这里写图片描述

工程配置还需要把jar包集成到自己的工程中,如图上图所示,放入libs目录下。对于每个jar文件,右键-选择Add As Library,导入到工程中。对应在build.gradle生成工程所依赖的jar文件说明,如下图所示:

这里写图片描述

  • 在AndroidManifest.xml清单文件中添加开发密钥,如下图所示:

这里写图片描述

  • 在AndroidManifest.xml清单文件中添加所需权限,如下图所示:
    <!--地图包、搜索包需要的基础权限-->

    <!--允许程序打开网络套接字-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--允许程序设置内置sd卡的写权限-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!--允许程序获取网络状态-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!--允许程序访问WiFi网络信息-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <!--允许程序读写手机状态和身份-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <!--允许程序访问CellID或WiFi热点来获取粗略的位置-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

    <!--用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    <!--用于访问GPS定位-->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
    <!--用于获取运营商信息,用于支持提供运营商信息相关的接口-->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
    <!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
    <!--用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
    <!--用于访问网络,网络定位需要上网-->
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <!--用于读取手机当前的状态-->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
    <!--用于写入缓存数据到扩展存储卡-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <!--用于申请调用A-GPS模块-->
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
    <!--用于申请获取蓝牙信息进行室内定位-->
    <uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
  • 在布局xml文件中添加地图控件
    <!-- 使用高德地图的提供的MapView -->
    <com.amap.api.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
  • 在应用添加地图定位的功能

在AndroidManifest.xml清单文件中声明SERVICE组件,每个APP拥有自己单独的定位SERVICE。

        <service 
            android:name="com.amap.api.location.APSService">
        </service>
  • 在应用添加地图的其它功能(定位地图、卫星地图、解析地图和导航地图等)
package com.fukaimei.gaodemaptest1;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.PopupMenu;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

public class MainActivity extends Activity implements AMapLocationListener,
        LocationSource {

    private static final int WRITE_COARSE_LOCATION_REQUEST_CODE = 0;
    private MapView mapView = null;
    private AMap aMap;
    PopupMenu popup = null;
    //定位需要的声明
    private AMapLocationClient mLocationClient = null;//定位发起端
    private AMapLocationClientOption mLocationOption = null;//定位参数
    private LocationSource.OnLocationChangedListener mListener = null;//定位监听器
    //标识,用于判断是否只显示一次定位信息和用户重新定位
    private boolean isFirstLoc = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取地图控件引用
        mapView = (MapView) findViewById(R.id.map);
        //在activity执行onCreate时执行mapView.onCreate(savedInstanceState),创建地图
        mapView.onCreate(savedInstanceState);
        //初始化地图控制器对象
        init();
        //设置显示定位按钮 并且可以点击
        UiSettings settings = aMap.getUiSettings();
        //设置定位监听
        aMap.setLocationSource(this);
        // 是否显示定位按钮
        settings.setMyLocationButtonEnabled(true);
        // 是否可触发定位并显示定位层
        aMap.setMyLocationEnabled(true);
        //定位的小图标
        MyLocationStyle myLocationStyle = new MyLocationStyle();
        myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.icon_geo));
        myLocationStyle.radiusFillColor(android.R.color.transparent);
        myLocationStyle.strokeColor(android.R.color.transparent);
        aMap.setMyLocationStyle(myLocationStyle);
        // 开启定位
        initLoc();
        RadioButton rb = (RadioButton) findViewById(R.id.gps);
        // 为GPS单选按钮设置监听器
        rb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView
                    , boolean isChecked) {
                //初始化地图控制器对象
                init();
                //设置显示定位按钮 并且可以点击
                UiSettings settings = aMap.getUiSettings();
                //设置定位监听
                aMap.setLocationSource(MainActivity.this);
                // 是否显示定位按钮
                settings.setMyLocationButtonEnabled(true);
                // 是否可触发定位并显示定位层
                aMap.setMyLocationEnabled(true);
                //定位的小图标
                MyLocationStyle myLocationStyle = new MyLocationStyle();
                myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.icon_geo));
                myLocationStyle.radiusFillColor(android.R.color.transparent);
                myLocationStyle.strokeColor(android.R.color.transparent);
                aMap.setMyLocationStyle(myLocationStyle);
                // 开启定位
                initLoc();
            }
        });
        Button bn = (Button) findViewById(R.id.loc);
        final TextView latTv = (TextView) findViewById(R.id.lat);
        final TextView lngTv = (TextView) findViewById(R.id.lng);
        bn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 获取用户输入的经度、纬度值
                String lng = lngTv.getEditableText().toString().trim();
                String lat = latTv.getEditableText().toString().trim();
                if (lng.equals("") || lat.equals("")) {
                    Toast.makeText(MainActivity.this, "经度或纬度不能为空!", Toast.LENGTH_SHORT).show();
                } else {
                    // 设置根据用户输入的地址定位
                    ((RadioButton) findViewById(R.id.manual)).setChecked(true);
                    double dLng = Double.parseDouble(lng);
                    double dLat = Double.parseDouble(lat);
                    // 将用户输入的经度、纬度封装成LatLng
                    LatLng pos = new LatLng(dLat, dLng);
                    // 创建一个设置经纬度的CameraUpdate
                    CameraUpdate cu = CameraUpdateFactory.changeLatLng(pos);
                    // 更新地图的显示区域
                    aMap.moveCamera(cu);
                    // 创建MarkerOptions对象
                    MarkerOptions markerOptions = new MarkerOptions();
                    // 设置MarkerOptions的添加位置
                    markerOptions.position(pos);
                    // 设置MarkerOptions的标题
                    markerOptions.title("天津科技大学");
                    // 设置MarkerOptions的摘录信息
                    markerOptions.snippet("学生第十四公寓");
                    // 设置MarkerOptions的图标
                    markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
                    markerOptions.draggable(true);
                    // 添加MarkerOptions(实际上就是添加Marker)
                    Marker marker = aMap.addMarker(markerOptions);
                    // 设置默认显示的信息窗
                    marker.showInfoWindow();
                    // 创建MarkerOptions、并设置它的各种属性
                    MarkerOptions markerOptions1 = new MarkerOptions();
                    markerOptions1.position(new LatLng(39.087068, 117.709404))
                            .title("天津科技大学(泰达校区)") // 设置标题
                            .icon(BitmapDescriptorFactory
                                    .defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA))
                            .draggable(true);
                    // 使用集合封装多个图标,这样可为MarkerOptions设置多个图标
                    ArrayList<BitmapDescriptor> giflist = new ArrayList<>();
                    giflist.add(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE));
                    giflist.add(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
                    giflist.add(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW));
                    // 再创建一个MarkerOptions、并设置它的各种属性
                    MarkerOptions markerOptions2 = new MarkerOptions()
                            .position(new LatLng(39.08742458176533, 117.7064895629883))
                            // 为MarkerOptions设置多个图标
                            .icons(giflist)
                            .title("天津科技大学-体育馆")
                            .draggable(true)
                            // 设置图标的切换频率
                            .period(10);
                    // 使用ArrayList封装多个MarkerOptions,即可一次添加多个Marker
                    ArrayList<MarkerOptions> optionList = new ArrayList<>();
                    optionList.add(markerOptions1);
                    optionList.add(markerOptions2);
                    // 批量添加多个Marker
                    aMap.addMarkers(optionList, true);
                }
            }
        });
        ToggleButton tb = (ToggleButton) findViewById(R.id.tb);
        tb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    // 设置使用卫星地图
                    aMap.setMapType(AMap.MAP_TYPE_SATELLITE);
                } else {
                    // 设置使用普通地图
                    aMap.setMapType(AMap.MAP_TYPE_NORMAL);
                }
            }
        });
    }

    // 初始化AMap对象
    void init() {
        if (aMap == null) {
            aMap = mapView.getMap();
            // 创建一个设置放大级别的CameraUpdate
            CameraUpdate cu = CameraUpdateFactory.zoomTo(20);
            // 设置地图的默认放大级别
            aMap.moveCamera(cu);
            // 创建一个更改地图倾斜度的CameraUpdate
            CameraUpdate tiltUpdate = CameraUpdateFactory.changeTilt(30);
            // 改变地图的倾斜度
            aMap.moveCamera(tiltUpdate);
        }
    }

    //定位
    private void initLoc() {

//          SDK在Android 6.0以上的版本需要进行运行检测的动态权限如下:
//                Manifest.permission.ACCESS_COARSE_LOCATION,
//                Manifest.permission.ACCESS_FINE_LOCATION,
//                Manifest.permission.WRITE_EXTERNAL_STORAGE,
//                Manifest.permission.READ_EXTERNAL_STORAGE,
//                Manifest.permission.READ_PHONE_STATE

        //这里用到ACCESS_FINE_LOCATION与ACCESS_COARSE_LOCATION权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            //申请WRITE_EXTERNAL_STORAGE权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    WRITE_COARSE_LOCATION_REQUEST_CODE);//自定义的code
        } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            //申请WRITE_EXTERNAL_STORAGE权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                    WRITE_COARSE_LOCATION_REQUEST_CODE);//自定义的code
        }
        //初始化定位
        mLocationClient = new AMapLocationClient(getApplicationContext());
        //设置定位回调监听
        mLocationClient.setLocationListener(this);
        //初始化定位参数
        mLocationOption = new AMapLocationClientOption();
        //设置定位模式为高精度模式,Battery_Saving为低功耗模式,Device_Sensors是仅设备模式
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
        //设置是否返回地址信息(默认返回地址信息)
        mLocationOption.setNeedAddress(true);
        //设置是否只定位一次,默认为false
        mLocationOption.setOnceLocation(false);
        //设置是否强制刷新WIFI,默认为强制刷新
        mLocationOption.setWifiActiveScan(true);
        //设置是否允许模拟位置,默认为false,不允许模拟位置
        mLocationOption.setMockEnable(false);
        //设置定位间隔,单位毫秒,默认为2000ms
        mLocationOption.setInterval(2000);
        //给定位客户端对象设置定位参数
        mLocationClient.setLocationOption(mLocationOption);
        //启动定位
        mLocationClient.startLocation();
    }

    //定位回调函数
    @Override
    public void onLocationChanged(AMapLocation amapLocation) {

        if (amapLocation != null) {
            if (amapLocation.getErrorCode() == 0) {
                //定位成功回调信息,设置相关消息
                amapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见官方定位类型表
                amapLocation.getLatitude();//获取纬度
                amapLocation.getLongitude();//获取经度
                amapLocation.getAccuracy();//获取精度信息
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = new Date(amapLocation.getTime());
                df.format(date);//定位时间
                amapLocation.getAddress();  // 地址,如果option中设置isNeedAddress为false,则没有此结果,网络定位结果中会有地址信息,GPS定位不返回地址信息。
                amapLocation.getCountry();  // 国家信息
                amapLocation.getProvince();  // 省信息
                amapLocation.getCity();  // 城市信息
                amapLocation.getDistrict();  // 城区信息
                amapLocation.getStreet();  // 街道信息
                amapLocation.getStreetNum();  // 街道门牌号信息
                amapLocation.getCityCode();  // 城市编码
                amapLocation.getAdCode();//地区编码

                // 如果不设置标志位,此时再拖动地图时,它会不断将地图移动到当前的位置
                if (isFirstLoc) {
                    //设置缩放级别
                    aMap.moveCamera(CameraUpdateFactory.zoomTo(20));
                    //将地图移动到定位点
                    aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(amapLocation.getLatitude(),
                            amapLocation.getLongitude())));
                    //点击定位按钮 能够将地图的中心移动到定位点
                    mListener.onLocationChanged(amapLocation);
                    //添加图钉
                    aMap.addMarker(getMarkerOptions(amapLocation));
                    //获取定位信息
                    StringBuffer buffer = new StringBuffer();
                    buffer.append(amapLocation.getCountry() + "" + amapLocation.getProvince()
                            + "" + amapLocation.getCity() + "" + amapLocation.getProvince()
                            + "" + amapLocation.getDistrict() + "" + amapLocation.getStreet()
                            + "" + amapLocation.getStreetNum());
                    Toast.makeText(getApplicationContext(), buffer.toString(), Toast.LENGTH_LONG).show();
                    isFirstLoc = false;
                }
            } else {
                //显示错误信息ErrCode是错误码,errInfo是错误信息,详见错误码表。
                Log.e("AmapError", "location Error, ErrCode:"
                        + amapLocation.getErrorCode() + ", errInfo:"
                        + amapLocation.getErrorInfo());
                Toast.makeText(getApplicationContext(), "定位失败", Toast.LENGTH_LONG).show();
            }
        }
    }

    //  自定义一个图钉,并且设置图标,当我们点击图钉时,显示设置的信息
    private MarkerOptions getMarkerOptions(AMapLocation amapLocation) {
        //设置图钉选项
        MarkerOptions options = new MarkerOptions();
        //图标
        options.icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_geo));
        //位置
        options.position(new LatLng(amapLocation.getLatitude(), amapLocation.getLongitude()));
        StringBuffer buffer = new StringBuffer();
        buffer.append(amapLocation.getCountry() + "" + amapLocation.getProvince() + ""
                + amapLocation.getCity() +  "" + amapLocation.getDistrict()
                + "" + amapLocation.getStreet() + "" + amapLocation.getStreetNum());
        //标题
        options.title(buffer.toString());
        //子标题
        options.snippet("(您目前所在的位置)");
        //设置多少帧刷新一次图片资源
        options.period(60);
        return options;
    }

    public void onPopupMenuClick(View v) {
        // 创建PopupMenu对象
        popup = new PopupMenu(this, v);
        // 将R.menu.menu_main菜单资源加载到popup菜单中
        getMenuInflater().inflate(R.menu.menu_main, popup.getMenu());
        // 为popup菜单的菜单项单击事件绑定事件监听器
        popup.setOnMenuItemClickListener(
                new PopupMenu.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem item) {
                        if (item.getItemId() == R.id.loc_map) {  // 开启定位地图模式
                            Intent intent1 = new Intent(MainActivity.this, MainActivity.class);
                            startActivity(intent1);
                        } else if (item.getItemId() == R.id.parse_map) {  // 开启解析地图模式
                            Intent intent2 = new Intent(MainActivity.this, ParseMapActivity.class);
                            startActivity(intent2);
                        } else if (item.getItemId() == R.id.search_map) {  // 开启搜索地图模式
                            Intent intent3 = new Intent(MainActivity.this, SearchMapActivity.class);
                            startActivity(intent3);
                        } else if (item.getItemId() == R.id.nav_map) {  // 开启导航地图模式
                            Intent intent4 = new Intent(MainActivity.this, NavMapActivity.class);
                            startActivity(intent4);
                        }
                        return true;
                    }
                });
        popup.show();
    }

    // 激活定位
    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        mListener = onLocationChangedListener;
    }

    // 停止定位
    @Override
    public void deactivate() {
        mListener = null;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //在activity执行onDestroy时执行mapView.onDestroy(),销毁地图
        mapView.onDestroy();
    }

    @Override
    protected void onResume() {
        super.onResume();
        //在activity执行onResume时执行mapView.onResume (),重新绘制加载地图
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        //在activity执行onPause时执行mapView.onPause (),暂停地图的绘制
        mapView.onPause();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        //在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState),保存地图当前的状态
        mapView.onSaveInstanceState(outState);
    }
}
  • 完成以上步骤后,运行程序,即可在您的应用中显示相应的功能,如下地图:

这里写图片描述 这里写图片描述

这里写图片描述 这里写图片描述


Demo程序源码下载地址一(GitHub)
Demo程序源码下载地址二(Gitee)

猜你喜欢

转载自blog.csdn.net/fukaimei/article/details/78755718