Android Studio地圖開發(百度地圖)
阿新 • • 發佈:2019-02-19
第一步、配置環境
1.申請百度地圖key
- 首先到百度地圖開放平臺,登入賬號,然後到如下介面
- 點選“建立應用”,到如下介面,填寫應用名稱,應用型別選擇“Android SDK”
- 獲取釋出版SHA1和開發版SHA1,連結如下百度提供的獲取SHA1的方法,注意,SHA1是基於檔案.jks得到的,開發版SHA1為你除錯的時候用到的,是基於debug.jks得到;釋出版為你釋出app或apk時用到的,是基於你自己建立的xxx.jks得到。如果你只填發布版SHA1得到的key,除錯的時候是顯示不出百度地圖的,切記!!!
2.匯入基本的百度地圖jar包和so檔案
- 列在libs目錄下匯入jar包,這裡只是最簡單的BaiduLBS_Android.jar, 如下圖
- 在main資料夾下建立jniLibs目錄,匯入so檔案,如下圖。這裡注意armeabi目錄和x86目錄,裡面的so檔案是一樣的,只是為了不同的CPU(arm,x86)而設定。如果你只有armeabi,那麼你在x86虛擬機器執行就顯示不出百度地圖!!!
第二步,基本開發
基本功能是定位,根據經緯度、地址查詢等簡單操作。
- 在AndroidManifest.xml檔案下新增許可權信心、百度key等
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.wanglei.mymap">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- 訪問精確位置的許可權 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 這個許可權用於進行網路定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 獲取運營商資訊,用於支援提供運營商資訊相關的介面-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<!-- 百度地圖key -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="KlXVjLVaGQZUk5z8i13mAPL805aFXE8n" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote">
</service>
</application>
</manifest>
- 在activity_main.xml裡新增控制元件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
android:id="@+id/linearLayout1"
android:visibility="gone"
>
<EditText
android:layout_width="120dp"
android:layout_height="match_parent"
android:hint="經度"
android:id="@+id/editText_lg" />
<EditText
android:layout_width="120dp"
android:layout_height="match_parent"
android:hint="緯度"
android:id="@+id/editText_la" />
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="前往"
android:id="@+id/button_llsearch"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal"
android:id="@+id/linearLayout2"
android:visibility="gone"
>
<EditText
android:layout_width="240dp"
android:layout_height="match_parent"
android:hint="地址"
android:id="@+id/editText_site" />
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:hint="前往"
android:id="@+id/button_sitesearch"/>
</LinearLayout>
<com.baidu.mapapi.map.MapView
android:id="@+id/baiduMapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
</LinearLayout>
- 在menu目錄下新增menu_item.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.zhangyi.baidumap_test.MainActivity">
<item
android:id="@+id/menu_item_mylocation"
android:title="我的位置"
app:showAsAction="never" />
<item
android:id="@+id/menu_item_llsearch"
android:title="經緯度搜索"
app:showAsAction="never" />
<item
android:id="@+id/menu_item_sitesearch"
android:title="地址搜尋"
app:showAsAction="never" />
</menu>
- 在MainActivity.java
package com.example.wanglei.mymap;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
public class MainActivity extends ActionBarActivity {
private MapView myMapView = null;//地圖控制元件
private BaiduMap myBaiduMap;//百度地圖物件
private LocationClient mylocationClient;//定位服務客戶物件
private MylocationListener mylistener;//重寫的監聽類
private Context context;
private double myLatitude;//緯度,用於儲存自己所在位置的緯度
private double myLongitude;//經度,用於儲存自己所在位置的經度
private float myCurrentX;
private BitmapDescriptor myIconLocation1;//圖示1,當前位置的箭頭圖示
// private BitmapDescriptor myIconLocation2;//圖表2,前往位置的中心圖示
private MyOrientationListener myOrientationListener;//方向感應器類物件
private MyLocationConfiguration.LocationMode locationMode;//定點陣圖層顯示方式
// private MyLocationConfiguration.LocationMode locationMode2;//定點陣圖層顯示方式
private LinearLayout myLinearLayout1; //經緯度搜索區域1
private LinearLayout myLinearLayout2; //地址搜尋區域2
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// requestWindowFeature(Window.FEATURE_NO_TITLE);
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
this.context = this;
initView();
initLocation();
}
private void initView() {
myMapView = (MapView) findViewById(R.id.baiduMapView);
myBaiduMap = myMapView.getMap();
//根據給定增量縮放地圖級別
MapStatusUpdate msu= MapStatusUpdateFactory.zoomTo(18.0f);
myBaiduMap.setMapStatus(msu);
}
private void initLocation() {
locationMode = MyLocationConfiguration.LocationMode.NORMAL;
//定位服務的客戶端。宿主程式在客戶端宣告此類,並呼叫,目前只支援在主執行緒中啟動
mylocationClient = new LocationClient(this);
mylistener = new MylocationListener();
//註冊監聽器
mylocationClient.registerLocationListener(mylistener);
//配置定位SDK各配置引數,比如定位模式、定位時間間隔、座標系型別等
LocationClientOption mOption = new LocationClientOption();
//設定座標型別
mOption.setCoorType("bd09ll");
//設定是否需要地址資訊,預設為無地址
mOption.setIsNeedAddress(true);
//設定是否開啟gps進行定位
mOption.setOpenGps(true);
//設定掃描間隔,單位是毫秒 當<1000(1s)時,定時定位無效
int span = 1000;
mOption.setScanSpan(span);
//設定 LocationClientOption
mylocationClient.setLocOption(mOption);
//初始化圖示,BitmapDescriptorFactory是bitmap 描述資訊工廠類.
myIconLocation1 = BitmapDescriptorFactory.fromResource(R.drawable.location_marker);
// myIconLocation2 = BitmapDescriptorFactory.fromResource(R.drawable.icon_target);
//配置定點陣圖層顯示方式,三個引數的構造器
MyLocationConfiguration configuration
= new MyLocationConfiguration(locationMode, true, myIconLocation1);
//設定定點陣圖層配置資訊,只有先允許定點陣圖層後設置定點陣圖層配置資訊才會生效,參見 setMyLocationEnabled(boolean)
myBaiduMap.setMyLocationConfigeration(configuration);
myOrientationListener = new MyOrientationListener(context);
//通過介面回撥來實現實時方向的改變
myOrientationListener.setOnOrientationListener(new MyOrientationListener.OnOrientationListener() {
@Override
public void onOrientationChanged(float x) {
myCurrentX = x;
}
});
}
/*
*建立選單操作
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId())
{
/*
*第一個功能,返回自己所在的位置,箭頭表示
*/
case R.id.menu_item_mylocation://返回當前位置
getLocationByLL(myLatitude, myLongitude);
break;
/*
*第二個功能,根據經度和緯度前往位置
*/
case R.id.menu_item_llsearch://根據經緯度搜索地點
myLinearLayout1 = (LinearLayout) findViewById(R.id.linearLayout1);
//經緯度輸入區域1可見
myLinearLayout1.setVisibility(View.VISIBLE);
final EditText myEditText_lg = (EditText) findViewById(R.id.editText_lg);
final EditText myEditText_la = (EditText) findViewById(R.id.editText_la);
Button button_ll = (Button) findViewById(R.id.button_llsearch);
button_ll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final double mylg = Double.parseDouble(myEditText_lg.getText().toString());
final double myla = Double.parseDouble(myEditText_la.getText().toString());
getLocationByLL(myla, mylg);
//隱藏前面經緯度輸入區域
myLinearLayout1.setVisibility(View.GONE);
// Toast.makeText(context, "", Toast.LENGTH_SHORT).show();
//隱藏輸入法鍵盤
InputMethodManager imm =(InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
});
break;
/*
*第三個功能,根據地址名前往所在的位置
*/
case R.id.menu_item_sitesearch://根據地址搜尋
myLinearLayout2 = (LinearLayout) findViewById(R.id.linearLayout2);
//顯示地址搜尋區域2
myLinearLayout2.setVisibility(View.VISIBLE);
final EditText myEditText_site = (EditText) findViewById(R.id.editText_site);
Button button_site = (Button) findViewById(R.id.button_sitesearch);
button_site.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String site_str = myEditText_site.getText().toString();
new Thread(new Runnable() {
@Override
public void run() {
AddressToLatitudeLongitude at = new AddressToLatitudeLongitude(site_str);
at.getLatAndLngByAddress();
getLocationByLL(at.getLatitude(), at.getLongitude());
}
}).start();
//隱藏前面地址輸入區域
myLinearLayout2.setVisibility(View.GONE);
//隱藏輸入法鍵盤
InputMethodManager imm = (InputMethodManager) getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
});
break;
}
return super.onOptionsItemSelected(item);
}
/*
*根據經緯度前往
*/
public void getLocationByLL(double la, double lg)
{
//地理座標的資料結構
LatLng latLng = new LatLng(la, lg);
//描述地圖狀態將要發生的變化,通過當前經緯度來使地圖顯示到該位置
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
myBaiduMap.setMapStatus(msu);
}
/*
*定位請求回撥介面
*/
public class MylocationListener implements BDLocationListener
{
//定位請求回撥介面
private boolean isFirstIn=true;
//定位請求回撥函式,這裡面會得到定位資訊
@Override
public void onReceiveLocation(BDLocation bdLocation) {
//BDLocation 回撥的百度座標類,內部封裝瞭如經緯度、半徑等屬性資訊
//MyLocationData 定位資料,定位資料建造器
/*
* 可以通過BDLocation配置如下引數
* 1.accuracy 定位精度
* 2.latitude 百度緯度座標
* 3.longitude 百度經度座標
* 4.satellitesNum GPS定位時衛星數目 getSatelliteNumber() gps定位結果時,獲取gps鎖定用的衛星數
* 5.speed GPS定位時速度 getSpeed()獲取速度,僅gps定位結果時有速度資訊,單位公里/小時,預設值0.0f
* 6.direction GPS定位時方向角度
* */
myLatitude = bdLocation.getLatitude();
myLongitude = bdLocation.getLongitude();
MyLocationData data = new MyLocationData.Builder()
.direction(myCurrentX)//設定圖示方向
.accuracy(bdLocation.getRadius())//getRadius 獲取定位精度,預設值0.0f
.latitude(myLatitude)//百度緯度座標
.longitude(myLongitude)//百度經度座標
.build();
//設定定位資料, 只有先允許定點陣圖層後設置資料才會生效,參見 setMyLocationEnabled(boolean)
myBaiduMap.setMyLocationData(data);
//判斷是否為第一次定位,是的話需要定位到使用者當前位置
if (isFirstIn) {
//根據當前所在位置經緯度前往
getLocationByLL(myLatitude, myLongitude);
isFirstIn = false;
//提示當前所在地址資訊
// Toast.makeText(context, bdLocation.getAddrStr(), Toast.LENGTH_SHORT).show();
}
}
}
/*
*定位服務的生命週期,達到節省
*/
@Override
protected void onStart() {
super.onStart();
//開啟定位,顯示位置圖示
myBaiduMap.setMyLocationEnabled(true);
if(!mylocationClient.isStarted())
{
mylocationClient.start();
}
myOrientationListener.start();
}
@Override
protected void onStop() {
super.onStop();
//停止定位
myBaiduMap.setMyLocationEnabled(false);
mylocationClient.stop();
myOrientationListener.stop();
}
@Override
protected void onResume() {
super.onResume();
myMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
myMapView.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
myMapView.onDestroy();
}
}
- MainActivity.java同一目錄,AddressToLatitudeLongitude.java
package com.example.wanglei.mymap;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
/**
* Created by wanglei on 2017/6/20.
* 根據百度地圖API,根據地址得到經緯度
*/
public class AddressToLatitudeLongitude {
private String address = "哈爾濱";//地址
private double Latitude = 45.7732246332393;//緯度
private double Longitude = 126.65771685544611;//經度
public AddressToLatitudeLongitude(String addr_str) {
this.address = addr_str;
}
/*
*根據地址得到地理座標
*/
public void getLatAndLngByAddress(){
String addr = "";
String lat = "";
String lng = "";
try {
addr = java.net.URLEncoder.encode(address,"UTF-8");//編碼
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String url = String.format("http://api.map.baidu.com/geocoder/v2/?"
+"address=%s&ak=4rcKAZKG9OIl0wDkICSLx8BA&output=json",addr);
URL myURL = null;
URLConnection httpsConn = null;
//進行轉碼
try {
myURL = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
httpsConn = (URLConnection) myURL.openConnection();//建立連線
if (httpsConn != null) {
InputStreamReader insr = new InputStreamReader(//傳輸資料
httpsConn.getInputStream(), "UTF-8");
BufferedReader br = new BufferedReader(insr);
String data = null;
if ((data = br.readLine()) != null) {
System.out.println(data);
//這裡的data為以下的json格式字串,因為簡單,所以就不使用json解析了,直接字串處理
//{"status":0,"result":{"location":{"lng":118.77807440802562,"lat":32.05723550180587},"precise":0,"confidence":12,"level":"城市"}}
lat = data.substring(data.indexOf("\"lat\":")+("\"lat\":").length(), data.indexOf("},\"precise\""));
lng = data.substring(data.indexOf("\"lng\":")+("\"lng\":").length(), data.indexOf(",\"lat\""));
}
insr.close();
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
this.Latitude = Double.parseDouble(lat);
this.Longitude = Double.parseDouble(lng);
}
public Double getLatitude() {
return this.Latitude;
}
public Double getLongitude() {
return this.Longitude;
}
public static void main(String[] args) {
AddressToLatitudeLongitude at = new AddressToLatitudeLongitude("安徽省亳州市亳州一中");
at.getLatAndLngByAddress();
System.out.println(at.getLatitude() + " " + at.getLongitude());
}
}
- 如上,MyOrientationListener.java
package com.example.wanglei.mymap;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
public class MyOrientationListener implements SensorEventListener{
private SensorManager mSensorManager;
private Sensor mSensor;
private Context mContext;
private float lastX;
private OnOrientationListener mOnOrientationListener;
public MyOrientationListener(Context context)
{
this.mContext=context;
}
public void start()
{
mSensorManager= (SensorManager) mContext
.getSystemService(Context.SENSOR_SERVICE);
if(mSensorManager!= null)
{
//獲得方向感測器
mSensor=mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
}
//判斷是否有方向感測器
if(mSensor!=null)
{
//註冊監聽器
mSensorManager.registerListener(this,mSensor,SensorManager.SENSOR_DELAY_UI);
}
}
public void stop()
{
mSensorManager.unregisterListener(this);
}
//方向改變
@Override
public void onSensorChanged(SensorEvent event) {
if(event.sensor.getType()==Sensor.TYPE_ORIENTATION)
{
float x=event.values[SensorManager.DATA_X];
if(Math.abs(x-lastX)>1.0)
{
if(mOnOrientationListener!=null)
{
mOnOrientationListener.onOrientationChanged(x);
}
}
lastX=x;
}
}
public void setOnOrientationListener(OnOrientationListener listener)
{
mOnOrientationListener=listener;
}
public interface OnOrientationListener
{
void onOrientationChanged(float x);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}