Android调用高德地图定位、poi检索、导航功能

在App中使用地图定位十分常见,购物功能的可以直接定位当前位置,发动态功能可以定位当前位置发出,社交功能可以定位周边用户等等。这里我使用高德地图定位当前位置并显示地址和经纬度。

github代码传送门

先上效果图:


实现步骤:

1. 创建应用获取key:

接入第三方无一例外,去高德地图官网注册账号并创建应用。填入包名和keystore的Sha1。

创建应用
获取Sha1,输入命令keytool -v -list -keystore keystore文件路径
  • 获取调试版Sha1:

进入.android目录

cd .android

输入命令获取

keytool -v -list -keystore debug.keystore

过程截图:


image.png
  • 获取正式版Sha1:

输入命令获取接正式keystore路径

keytool -v -list -keystore ../../xxx.keystore

过程截图:


image.png
创建完成获取Key:
image.png

2. 接入SDK

添加定位库

compile 'com.amap.api:location:latest.integration'

添加2D地图库

compile 'com.amap.api:map2d:latest.integration'

添加地图权限:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />

在<application></application>中设置地图key

        <meta-data
            android:name="com.amap.api.v2.apikey"
            android:value="db1fde13fd28fb07223212dd8e9eef72" />

3. 代码实现(带每一步功能注释):

实现思路:创建MapView显示地图;设置定位定位监听,设置定位参数,在activate激活后启动定位;在定位回调中获取经纬度,在将地图移动到定位位置,在该经纬度上添加覆盖图标。详细代码如下:

  1. 地图控件:
    <com.amap.api.maps2d.MapView
        android:id="@+id/mapview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
  1. 定位类AmapActivity完整代码:
public class MainActivity extends BasePermissionActivity implements LocationManager.ILocationCallBack {
    private MapView mapview;
    private AMap aMap;
    private LocationSource.OnLocationChangedListener mListener;//定位监听器
    private LocationManager locationManager;
    /**
     * 纬度
     */
    protected double lat = 39.90;
    /**
     * 经度
     */
    protected double lgt = 116.38;
    /**
     * 地点名
     */
    private String location = "北京天安门";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mapview = findViewById(R.id.mapview);

        mapview.onCreate(savedInstanceState);

        setLocationMap();
        addInfoWindow();
    }

    /**
     * 设置地图定位属性
     */
    private void setLocationMap() {
        if (aMap == null) {
            aMap = mapview.getMap();
        }
        setLocationCallBack();

        aMap.setMapType(AMap.MAP_TYPE_NORMAL);
        //设置定位监听
        aMap.setLocationSource(new LocationSource() {
            @Override
            public void activate(OnLocationChangedListener onLocationChangedListener) {
                mListener = onLocationChangedListener;
                locationManager.startLocation(MainActivity.this);
            }

            @Override
            public void deactivate() {
                mListener = null;
            }
        });
        //设置缩放级别
        aMap.moveCamera(CameraUpdateFactory.zoomTo(15));
        //显示定位层并可触发,默认false
        aMap.setMyLocationEnabled(true);
    }

    /**
     * 根据经纬度调用地图定位
     */
    private void setLocationCallBack() {
        locationManager = new LocationManager();

        //根据获取的经纬度,将地图移动到定位位置
        aMap.moveCamera(CameraUpdateFactory.changeLatLng(new com.amap.api.maps2d.model.LatLng(lat, lgt)));
        //添加定位图标,并弹出标注弹框
        aMap.addMarker(locationManager.getMarkerOption(location, lat, lgt));
    }

    @Override
    public void callBack(String str, double lat, double lgt, AMapLocation aMapLocation) {
        getCurLant(str, lat, lgt);
    }

    /**
     * 进入导航页
     *
     * @param curPos
     * @param curLat
     * @param curLgt
     */
    private void getCurLant(String curPos, double curLat, double curLgt) {
        Poi start = new Poi(curPos, new LatLng(curLat, curLgt), "");
        Poi end = new Poi(location, new LatLng(lat, lgt), "");
        AmapNaviPage.getInstance().showRouteActivity(this, new AmapNaviParams(start, null, end, AmapNaviType.DRIVER), null);
    }

    /**
     * 添加悬浮标注框
     */
    private void addInfoWindow() {

        aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
            @Override
            public View getInfoWindow(Marker marker) {
                View infoWindow = getLayoutInflater().inflate(R.layout.view_latlgt_marker, null);

                TextView tvLat = infoWindow.findViewById(R.id.tv_lat);
                TextView tvLgt = infoWindow.findViewById(R.id.tv_lgt);
                tvLat.setText("纬度:" + lat);
                tvLgt.setText("经度:" + lgt);

                return infoWindow;
            }

            @Override
            public View getInfoContents(Marker marker) {
                return null;
            }
        });
    }

    /**
     * 发起导航
     */
    private void startNavigation() {
        String[] permissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION};
        requestPermissions(permissions, new PermissionListener() {
            @Override
            public void onGranted() {
                locationManager.startLocation(MainActivity.this);
                locationManager.setLocationCallBack(MainActivity.this);
            }

            @Override
            public void onDenied(List<String> deniedPermissions) {

            }
        });
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapview.onSaveInstanceState(outState);
    }

    @Override
    public void onResume() {
        super.onResume();

        mapview.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();

        mapview.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (mapview != null) {
            mapview.onDestroy();
        }
    }

    @Override
    public void onPointerCaptureChanged(boolean hasCapture) {

    }

    public void poi(View view) {
        startActivity(new Intent(MainActivity.this, PoiActivity.class));
    }

    public void navigation(View view) {
        startNavigation();
    }
}

  1. 定位参数设置和定位回调LocationUtil类完整代码:
import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import android.text.TextUtils;
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.maps2d.model.LatLng;
import com.amap.api.maps2d.model.MarkerOptions;

/**
 * create by libo
 * create on 2018/11/15
 * description 高德定位工具类
 */
public class LocationManager implements AMapLocationListener {
    private ILocationCallBack callBack;

    public LocationManager() {

    }

    public void startLocation(Context context) {
        AMapLocationClientOption mLocationOption = new AMapLocationClientOption();
        AMapLocationClient mLocationClient = new AMapLocationClient(context);
        mLocationClient.setLocationListener(this);
        mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); //设置定位模式
        mLocationOption.setOnceLocation(true);
        mLocationOption.setOnceLocationLatest(true);
        mLocationOption.setNeedAddress(true);  //是否返回地址信息
        mLocationOption.setWifiActiveScan(false);
        mLocationOption.setMockEnable(false);
        mLocationOption.setLocationCacheEnable(false);
        mLocationClient.setLocationOption(mLocationOption);
        mLocationClient.startLocation();
    }

    public static boolean isLocationEnabled(Context context) {
        int locationMode;
        String locationProviders;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
            } catch (Settings.SettingNotFoundException e) {
                e.printStackTrace();
                return false;
            }
            return locationMode != Settings.Secure.LOCATION_MODE_OFF;
        } else {
            locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            return !TextUtils.isEmpty(locationProviders);
        }
    }

    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        if (aMapLocation == null) {
            return;
        }

        if (aMapLocation.getErrorCode() == 0) {
            double lat = aMapLocation.getLatitude();//获取纬度
            double lgt = aMapLocation.getLongitude();//获取经度
            String country = aMapLocation.getCountry();//国家信息
            String province = aMapLocation.getProvince();//省信息
            String city = aMapLocation.getCity();//城市信息
            String district = aMapLocation.getDistrict();//城区信息
            String street = aMapLocation.getStreet();//街道信息

            if (callBack != null) {
                callBack.callBack(country + province + city + district + street,lat,lgt,aMapLocation);
            }
        }
    }

    /**
     * 自定义图标
     * @return
     */
    public MarkerOptions getMarkerOption(String str, double lat, double lgt) {
        MarkerOptions markerOptions = new MarkerOptions();
//        markerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.coordinate));
        markerOptions.position(new LatLng(lat,lgt));
        markerOptions.title(str);
        markerOptions.snippet("纬度:" + lat + "   经度:" + lgt);
        markerOptions.period(100);
        return markerOptions;
    }

    public interface ILocationCallBack {
        void callBack(String str, double lat, double lgt, AMapLocation aMapLocation);
    }

    public void setLocationCallBack(ILocationCallBack callBack){
        this.callBack = callBack;
    }
}

传入当前经纬度得到起点的Poi,传入终点经纬度得到终点Poi,开启导航:
    /**
     * 进入导航页
     *
     * @param curPos
     * @param curLat
     * @param curLgt
     */
    private void getCurLant(String curPos, double curLat, double curLgt) {
        Poi start = new Poi(curPos, new LatLng(curLat, curLgt), "");
        Poi end = new Poi(location, new LatLng(lat, lgt), "");
        AmapNaviPage.getInstance().showRouteActivity(this, new AmapNaviParams(start, null, end, AmapNaviType.DRIVER), null);
    }

记得需要在Androidmanifest文件中注册导航activity

        <activity android:name="com.amap.api.navi.AmapRouteActivity"
            android:theme="@android:style/Theme.NoTitleBar"
            android:configChanges="orientation|keyboardHidden|screenSize" />
Poi搜索周边地址:

先开启调用定位当前位置,然后使用PoiSearch类进行搜索,回调获得poiResult,获取PoiItem集合,就是周边位置信息集合。

public class PoiActivity extends AppCompatActivity implements AMapLocationListener, PoiSearch.OnPoiSearchListener {
    private RecyclerView recyclerView;
    private PoiAdapter poiAdapter;
    private ArrayList<PoiItem> poiDatas = new ArrayList<>();
    private AMapLocationClient mlocationClient;
    private LatLonPoint searchLatlonPoint;
    private PoiSearch poisearch;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_poi);

        recyclerView = findViewById(R.id.recyclerview);
        setPoiAdapter();

        initLocation();
        startLocation();
    }

    private void setPoiAdapter() {
        poiAdapter = new PoiAdapter(getApplicationContext(), poiDatas);
        recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
        recyclerView.setAdapter(poiAdapter);
    }

    /**
     * 初始化定位,设置回调监听
     */
    private void initLocation() {
        mlocationClient = new AMapLocationClient(this);  //初始化client
        mlocationClient.setLocationListener(this);  // 设置定位监听
    }

    /**
     * 开始定位
     */
    private void startLocation() {
        mlocationClient.setLocationOption(getOption());  //设置定位参数
        mlocationClient.startLocation();  // 启动定位
    }

    /**
     * 设置定位参数
     *
     * @return 定位参数类
     */
    private AMapLocationClientOption getOption() {
        AMapLocationClientOption mOption = new AMapLocationClientOption();
        mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选,设置定位模式,可选的模式有高精度、仅设备、仅网络。默认为高精度模式
        mOption.setHttpTimeOut(30000);//可选,设置网络请求超时时间。默认为30秒。在仅设备模式下无效
        mOption.setNeedAddress(true);//可选,设置是否返回逆地理地址信息。默认是true
        mOption.setLocationCacheEnable(false);//设置是否返回缓存中位置,默认是true
        mOption.setOnceLocation(true);//可选,设置是否单次定位。默认是false
        return mOption;
    }

    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        if (aMapLocation != null && aMapLocation.getErrorCode() == 0) {
            searchLatlonPoint = new LatLonPoint(aMapLocation.getLatitude(), aMapLocation.getLongitude());

            if (searchLatlonPoint != null) {
                doSearchQuery(searchLatlonPoint);
            }
        }
    }

    /**
     * 搜索周边poi
     *
     * @param centerpoint
     */
    private void doSearchQuery(LatLonPoint centerpoint) {
        PoiSearch.Query query = new PoiSearch.Query("", "", "");
        query.setPageSize(30);
        query.setPageNum(0);
        poisearch = new PoiSearch(this, query);
        poisearch.setOnPoiSearchListener(this);
        poisearch.setBound(new PoiSearch.SearchBound(centerpoint, 500, true));
        poisearch.searchPOIAsyn();
    }

    @Override
    public void onPoiSearched(PoiResult poiResult, int resultCode) {
        if (resultCode == AMapException.CODE_AMAP_SUCCESS) {
            if (poiResult != null && poiResult.getPois().size() > 0) {
                List<PoiItem> poiItems = poiResult.getPois();
                poiDatas.addAll(poiItems);
                poiAdapter.notifyDataSetChanged();
            } else {
                Toast.makeText(this, "无搜索结果", Toast.LENGTH_SHORT).show();
            }
        } else {
            Toast.makeText(this, "搜索失败", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onPoiItemSearched(PoiItem poiItem, int i) {

    }

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

    /**
     * 销毁定位
     */
    private void destroyLocation() {
        if (null != mlocationClient) {
            mlocationClient.onDestroy();
            mlocationClient = null;
        }
    }
}

错误情况检查:

  1. Key是否配置错误
  2. 在onCreate中调用mapView.onCreate(savedInstanceState);
  3. mapView.onPause()、mapView.onDestroy()、mapView.onResume()、mapView.onSaveInstanceState(outState)是否都已调用且不写错
  4. aMap.setMyLocationEnabled(true)设置显示定位层并可触发
  5. 手机是否开启定位
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容