前言
今天,我們一起來聊聊有關地圖方面的內容吧。
目前比較好的地圖第三方分別如下:
百度地圖 API地址:http://lbsyun.baidu.com/ ;
高德地圖 API地址:http://lbs.amap.com/ ;
騰訊地圖 API地址:http://lbs.qq.com/;
谷歌Baba的大地圖 API地址:http://maps.googleapis.com/。
經過網上簡單搜索後,簡單得出以下結論:
百度地圖,功能齊全,牛掰,無奈地圖更新不是很及時;
高德地圖,專注地圖n餘年,開發文檔以及後續支持比較好,蘋果手機內置地圖也同樣爲高德地圖(大高德666~);
騰訊地圖,沒怎麼使用過;
谷歌Baba大地圖,貌似需要翻牆,比較心累~
So,經過簡單瞭解後,讓我們愉快的開啓玩轉高德地圖之旅吧~
開啓高德地圖探索之旅
一. 查看官方攻略
這個就很簡單了,我們找到高德地圖API,按照官方溜達溜達去。
點擊進入,選擇 “開發與支持” 在點擊”Android 地圖 SDK”
首先我們需要註冊成爲高德地圖開發者,這裏不做過多說明。
接下來在控制檯創建應用,如下圖:
之後點擊創建Key,高德hint給的很全面,大家按照要求來即可。
關於獲取SHA1,大家可以參考LZ之前寫的博文:AndroidStudio獲取SHA1值
獲取到key,我們一起粗略瞭解下官方提供相關知識。
谷歌官方將地圖相關SDK區分爲五大類,如下圖:
在這裏,大家可能會疑問,2D地圖 3D地圖,這又是什麼鬼?別急,下面爲大家附上官方解釋。
LZ果斷選擇3D地圖,不要問爲什麼,就是喜歡新的!!!
下載完成之後,運行的時候需要在高德上申請key,否則無法運行!
最好還是下載SDK所有的,都看看,也耽誤不了多少功夫。
如下圖,簡介明瞭,大家根據需求去進行開發,這裏就不做過多說明了。
該瞭解的也差不多了,下面開啓擼碼之路~
二. 編碼路漫漫其修遠兮,吾必將上下而求索。
第一步,配置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"/>
設置高德Key
<!-- 項目第三方key配置模塊 -->
<!-- 高德地圖key -->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="98e3f4440af277a2f390b724602168f7(這裏填寫個人申請的key即可)"/>
第二步,向工程中添加地圖所需so庫以及引入開發包
首先添加so文件,在src/main/目錄下新建jniLibs目錄,並將文件放入其中,LZ這裏只兼容armeabi以及arm64-v8a;
有關armeabi簡單知識,大家可查閱LZ之前總結的博文:
添加完成後,如下所示:
接下來,配置dependencies,由於我們第一個目標是要實現顯示地圖,所以我們要在項目的build.gradle中添加如下一行地址即可。
compile ‘com.amap.api:3dmap:latest.integration’
如下圖:
之後點擊右上方的sync now,萬能的死丟丟會親自下載相關包~
第三步,初始化地圖容器
在我們的layout中,添加地圖控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="cn.hlq.gaodemapdemo.map.GaoDeLocationActivity">
<com.amap.api.maps.MapView
android:id="@+id/id_gaode_location_map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Activity管理地圖生命週期
package cn.hlq.gaodemapdemo.map;
import android.app.Activity;
import android.os.Bundle;
import com.amap.api.maps.AMap;
import com.amap.api.maps.MapView;
import cn.hlq.gaodemapdemo.R;
/**
* create by heliquan at 2017年5月4日23:26:59
*/
public class GaoDeLocationActivity extends Activity {
private MapView mapView;
private AMap aMap;
@Override
protected void onResume() {
super.onResume();
// 重新繪製加載地圖
mapView.onResume();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gao_de_location);
initView();
// 創建地圖
mapView.onCreate(savedInstanceState);
}
@Override
protected void onPause() {
super.onPause();
// 暫停地圖的繪製
mapView.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 銷燬地圖
mapView.onDestroy();
}
/**
* 重寫此方法,在activity執行onSaveInstanceState時執行mMapView.onSaveInstanceState (outState),保存地圖當前的狀態
*
* @param outState
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
private void initView() {
// 實例化地圖控件
mapView = (MapView) findViewById(R.id.id_gaode_location_map);
}
}
在這裏也簡單爲大家拓展下小知識。
第四步,顯示地圖
private void initView() {
// 實例化地圖控件
mapView = (MapView) findViewById(R.id.id_gaode_location_map);
if (aMap == null) {
// 顯示地圖
aMap = mapView.getMap();
}
}
第五步,查看我們的成果
到此,地圖顯示,我們已經完成了~
接下來,開啓定位之旅~
第一步,引入定位依賴~
compile ‘com.amap.api:location:latest.integration’
第二步,添加高德地圖定位服務
<!-- 項目Service模塊 -->
<!-- GaoDeLocationService --> <service android:name="com.amap.api.location.APSService"/>
第三步,實現定位監聽,重寫三個方法
implements <font color="#FF0000" style="box-sizing: border-box;">LocationSource, AMapLocationListener</font>
LZ在這裏就直接貼代碼了,相關注釋也寫的很明確了~!
@TargetApi(Build.VERSION_CODES.N)
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
// 解析AMapLocation對象
// 判斷AMapLocation對象不爲空,當定位錯誤碼類型爲0時定位成功
if (aMapLocation != null) {
if (aMapLocation.getErrorCode() == 0) {
aMapLocation.getLocationType(); // 獲取當前定位結果來源,如網絡定位結果,詳見定位類型表
aMapLocation.getLatitude(); // 獲取緯度
aMapLocation.getLongitude(); // 獲取經度
aMapLocation.getAccuracy(); // 獲取精度信息
aMapLocation.getAddress(); // 地址,如果option中設置isNeedAddress爲false,則沒有此結果,網絡定位結果中會有地址信息,GPS定位不返回地址信息。
aMapLocation.getCountry(); // 國家信息
aMapLocation.getProvince(); // 省信息
aMapLocation.getCity(); // 城市信息
aMapLocation.getDistrict(); // 城區信息
aMapLocation.getStreet(); // 街道信息
aMapLocation.getStreetNum(); // 街道門牌號信息
aMapLocation.getCityCode(); // 城市編碼
aMapLocation.getAdCode(); // 地區編碼
aMapLocation.getAoiName(); // 獲取當前定位點的AOI信息
aMapLocation.getBuildingId(); // 獲取當前室內定位的建築物Id
aMapLocation.getFloor(); // 獲取當前室內定位的樓層
aMapLocation.getGpsAccuracyStatus(); // 獲取GPS的當前狀態
// 獲取定位時間
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date(aMapLocation.getTime());
df.format(date);
// 設置縮放級別
aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
// 將地圖移動到定位點
aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude())));
// 點擊定位按鈕 能夠將地圖的中心移動到定位點
mListener.onLocationChanged(aMapLocation);
} else {
// 定位失敗時,可通過ErrCode(錯誤碼)信息來確定失敗的原因,errInfo是錯誤信息,詳見錯誤碼錶。
Log.e("HLQ_Struggle", "location Error, ErrCode:"
+ aMapLocation.getErrorCode() + ", errInfo:"
+ aMapLocation.getErrorInfo());
}
}
}
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
mListener = onLocationChangedListener;
}
@Override
public void deactivate() {
mListener = null;
}
第四步,初始化高德地圖以及基本配置並開啓定位
aMap.getUiSettings().setZoomControlsEnabled(false);
// 設置地圖默認的指南針是否顯示
aMap.getUiSettings().setCompassEnabled(true);
// 設置定位監聽
aMap.setLocationSource(this);
// 設置默認定位按鈕是否顯示
aMap.getUiSettings().setMyLocationButtonEnabled(true);
// 設置爲true表示顯示定位層並可觸發定位,false表示隱藏定位層並不可觸發定位,默認是false
aMap.setMyLocationEnabled(true);
aMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE);
初始化高德地圖,開啓定位
/**
* 初始化高德地圖
*/
public void initGaoDeMap() {
// 初始化定位
mLocationClient = new AMapLocationClient(getApplicationContext());
// 設置高德地圖定位回調監聽
mLocationClient.setLocationListener(this);
// 初始化AMapLocationClientOption對象
mLocationOption = new AMapLocationClientOption();
// 高精度定位模式:會同時使用網絡定位和GPS定位,優先返回最高精度的定位結果,以及對應的地址描述信息
// 設置定位模式爲AMapLocationMode.Hight_Accuracy,高精度模式
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
// 低功耗定位模式:不會使用GPS和其他傳感器,只會使用網絡定位(Wi-Fi和基站定位);
//設置定位模式爲AMapLocationMode.Battery_Saving,低功耗模式。
// mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Battery_Saving);
// 僅用設備定位模式:不需要連接網絡,只使用GPS進行定位,這種模式下不支持室內環境的定位,自 v2.9.0 版本支持返回地址描述信息。
// 設置定位模式爲AMapLocationMode.Device_Sensors,僅設備模式。
// mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Device_Sensors);
// SDK默認採用連續定位模式,時間間隔2000ms
// 設置定位間隔,單位毫秒,默認爲2000ms,最低1000ms。
mLocationOption.setInterval(3000);
// 設置定位同時是否需要返回地址描述
//設置是否返回地址信息(默認返回地址信息)
mLocationOption.setNeedAddress(true);
// 設置是否強制刷新WIFI,默認爲強制刷新。每次定位主動刷新WIFI模塊會提升WIFI定位精度,但相應的會多付出一些電量消耗。
// 設置是否強制刷新WIFI,默認爲true,強制刷新。
mLocationOption.setWifiActiveScan(true);
// 設置是否允許模擬軟件Mock位置結果,多爲模擬GPS定位結果,默認爲false,不允許模擬位置。
// 設置是否允許模擬位置,默認爲false,不允許模擬位置
mLocationOption.setMockEnable(false);
// 設置定位請求超時時間,默認爲30秒
// 單位是毫秒,默認30000毫秒,建議超時時間不要低於8000毫秒。
mLocationOption.setHttpTimeOut(50000);
// 設置是否開啓定位緩存機制
// 緩存機制默認開啓,可以通過以下接口進行關閉。
// 當開啓定位緩存功能,在高精度模式和低功耗模式下進行的網絡定位結果均會生成本地緩存,不區分單次定位還是連續定位。GPS定位結果不會被緩存。
// 關閉緩存機制
mLocationOption.setLocationCacheEnable(false);
// 設置是否只定位一次,默認爲false
mLocationOption.setOnceLocation(false);
// 給定位客戶端對象設置定位參數
mLocationClient.setLocationOption(mLocationOption);
// 啓動高德地圖定位
mLocationClient.startLocation();
}
擼了一會兒碼,現在來瞅瞅效果吧~
咦,這個時候大家可能會問了,怎麼移動別的地方之後還是會定位到當前呢?表急,讓我們一起來看看這個問題究竟是什麼導致的,當然LZ能力有限,只能簡單推測,不正之處歡迎指正~
懷着這個問題,讓我們一起來回顧下之前的代碼,大概如下:
-
我們設置高德地圖爲連續的精度定位,且在回調的時候,我們會根據當前獲取到的經度緯度去移動當某個點。這時候,大家會不會知道在哪兒動手腳可以簡單,快速解決這個問題了呢?
解決辦法如下:
if(isFirstLocation){
// 設置縮放級別
aMap.moveCamera(CameraUpdateFactory.zoomTo(17));
// 將地圖移動到定位點
aMap.moveCamera(CameraUpdateFactory.changeLatLng(new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude())));
// 點擊定位按鈕 能夠將地圖的中心移動到定位點
mListener.onLocationChanged(aMapLocation);
isFirstLocation=false;
}
此時,我們再次運行看看效果如何~
結束語
到現在,我們已經實現關於高德地圖顯示,定位,以及在實現定位過程中間出現的小插曲,相信大家看到這裏已經掌握了關於高德地圖的顯示以及定位。