1. 程式人生 > >百度地圖sdk的簡單應用

百度地圖sdk的簡單應用

最近研究了很多的第三方sdk,今天稍微簡單的研究下百度sdk,打個基礎,做個記錄,方便以後深入研究,

本文主要實現百度地圖基本的型別和定位自己的位置功能

最終效果圖如下:


進入介面後,會自動定位到自己的位置,然後有幾個基本的型別,都是很基本的功能,如果以後有這方面的需求,在繼續深入研究

進入百度開發中心

沒有賬號的註冊一個賬號吧

小夥伴可以自行勾選

然後點選下載開發包

把lib檔案拷貝到自己的工程裡面去

然後在src/main/目錄下新建jniLibs目錄

放入.so檔案

上面這些配置,官網都有記載的,主要是功能的實現和一些bug的出現是個比較煩人的問題

記得在build.gradle(app)裡面加上

sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

好,接下來去申請key

點選建立應用

這裡主要講解一下發布版的sha1怎麼獲取

獲得這個應該不難,就不細說了

我們都有預設的debug.keystore的,用這個測試好了,當然你有自己的簽名檔案的話,直接用自己的簽名檔案

找到自己的.android檔案,然後找到debug.keystore

進入debug.keystore所在的目錄

直接敲keytool -list -v -keystore debug.keystore 

然後輸入密令android

就能得到了

然後輸入包名,包名在我們的每個java檔案上面都有的

這樣提交後,我們就有獲得appkey了,

填寫到manifest中,如下

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.anlaiye.swt.baidumapdemo">

    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="這裡輸入你的appkey就行了" />

        <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" >
            <intent-filter>
                <action android:name="com.baidu.location.service_v2.2" >
                </action>
            </intent-filter>
        </service>
    </application>


    <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_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

我們在使用百度地圖相關功能的時候,都需要先例項化,但是每一次都例項化就比較麻煩,所以從上面的配置檔案中可以看到我建立了一個application,

程式碼很簡單,就是例項化了百度地圖SDK

package com.anlaiye.swt.baidumapdemo;

import android.app.Application;

import com.baidu.mapapi.SDKInitializer;

/**
 * Created by pc on 2016/12/14.
 */

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        SDKInitializer.initialize(this);
    }
}

接下來上佈局檔案
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.baidu.mapapi.map.MapView
        android:id="@+id/bmapView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:clickable="true" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/select_type"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="選擇型別" />

        <Button
            android:id="@+id/dingwei"
            android:onClick="location"
            android:text="定位自己"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
</LinearLayout>
mapview就是百度地圖的介面,你需要設定多大就設定多大

我下面加了按鈕,實現一些功能

這是type.xml的程式碼

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent">

    <LinearLayout
        android:layout_marginBottom="35dp"
        android:background="@android:color/transparent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="weixin"
            android:text="衛星圖" />

        <Button

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:onClick="nomal"
            android:text="正常圖" />

        <Button

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="none"
            android:text="空白圖" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:onClick="jiaotong"
            android:text="交通圖" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="hotjiaotong"
            android:text="熱力交通圖" />
    </LinearLayout>


</RelativeLayout>


每個按鈕都加了onclick事件,直接寫在了mainactivity中
package com.anlaiye.swt.baidumapdemo;

import android.app.Dialog;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.PopupWindow;

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 AppCompatActivity implements View.OnClickListener {
    private MapView mMapView = null;
    private BaiduMap mBaiduMap;
    private Button type_button;
    private Dialog dialog;
    private PopupWindow mPopupWindow;
    private LocationManager mgr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //在使用SDK各元件之前初始化context資訊,傳入ApplicationContext
        //注意該方法要再setContentView方法之前實現
        SDKInitializer.initialize(this);
        setContentView(R.layout.activity_main);
        //獲取地圖控制元件引用

        mMapView = (MapView) findViewById(R.id.bmapView);
        mBaiduMap = mMapView.getMap();
        type_button = (Button) findViewById(R.id.select_type);
        type_button.setOnClickListener(this);

        initOritationListener();
        initMyLocation();

    }

    public void weixin(View view) {
        //衛星地圖
        mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
//        dialog.cancel();

    }

    public void nomal(View view) {
        //正常地圖
        mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
//        dialog.cancel();
    }

    public void none(View view) {
        //空白圖
        mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NONE);
//        dialog.cancel();
    }


    public void jiaotong(View view) {
        //交通圖
        mBaiduMap.setTrafficEnabled(true);
//        dialog.cancel();
    }

    public void hotjiaotong(View view) {
        //熱力交通圖
        mBaiduMap.setBaiduHeatMapEnabled(true);
//        dialog.cancel();
    }

   /**
     * 定位的客戶端
     */
    private LocationClient mLocationClient;
    /**
     * 定位的監聽器
     */
    public MyLocationListener mMyLocationListener;
    /**
     * 當前定位的模式
     */
    private MyLocationConfiguration.LocationMode mCurrentMode = MyLocationConfiguration.LocationMode.NORMAL;
    /***
     * 是否是第一次定位
     */
    private volatile boolean isFristLocation = true;

    /**
     * 最新一次的經緯度
     */
    private double mCurrentLantitude;
    private double mCurrentLongitude;
    /**
     * 當前的精度
     */
    private float mCurrentAccracy;
    /**
     * 方向感測器的監聽器
     */
    private MyOrientationListener myOrientationListener;
    /**
     * 方向感測器X方向的值
     */
    private int mXDirection;

    private void initOritationListener()
    {
        myOrientationListener = new MyOrientationListener(
                getApplicationContext());
        myOrientationListener
                .setOnOrientationListener(new MyOrientationListener.OnOrientationListener()
                {
                    @Override
                    public void onOrientationChanged(float x)
                    {
                        mXDirection = (int) x;

                        // 構造定位資料
                        MyLocationData locData = new MyLocationData.Builder()
                                .accuracy(mCurrentAccracy)
                                // 此處設定開發者獲取到的方向資訊,順時針0-360
                                .direction(mXDirection)
                                .latitude(mCurrentLantitude)
                                .longitude(mCurrentLongitude).build();
                        // 設定定位資料
                        mBaiduMap.setMyLocationData(locData);
                        // 設定自定義圖示
                        BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory
                                .fromResource(R.mipmap.navi_map_gps_locked);
                        MyLocationConfiguration config = new MyLocationConfiguration(mCurrentMode, true, mCurrentMarker);
                        mBaiduMap.setMyLocationConfigeration(config);

                    }
                });
    }
    /**
     * 初始化定位相關程式碼
     */
    private void initMyLocation() {
        // 定位初始化
        mLocationClient = new LocationClient(this);
        mMyLocationListener = new MyLocationListener();
        mLocationClient.registerLocationListener(mMyLocationListener);
        // 設定定位的相關配置
        LocationClientOption option = new LocationClientOption();
        option.setOpenGps(true);// 開啟gps
        option.setCoorType("bd09ll"); // 設定座標型別
        option.setScanSpan(1000);
        mLocationClient.setLocOption(option);
    }

    public void location(View view) {

        LatLng ll = new LatLng(mCurrentLantitude, mCurrentLongitude);
        MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);
        mBaiduMap.animateMapStatus(u);
    }


    @Override
    protected void onStart() {
        // 開啟圖層定位
        mBaiduMap.setMyLocationEnabled(true);
        if (!mLocationClient.isStarted()) {
            mLocationClient.start();
        }
        // 開啟方向感測器
        myOrientationListener.start();
        super.onStart();
    }

    @Override
    protected void onStop() {
        // 關閉圖層定位
        mBaiduMap.setMyLocationEnabled(false);
        mLocationClient.stop();

        // 關閉方向感測器
        myOrientationListener.stop();
        super.onStop();
    }

    public class MyLocationListener implements BDLocationListener {
        @Override
        public void onReceiveLocation(BDLocation location) {

            // map view 銷燬後不在處理新接收的位置
            if (location == null || mMapView == null)
                return;
            // 構造定位資料
            MyLocationData locData = new MyLocationData.Builder()
                    .accuracy(location.getRadius())
                    // 此處設定開發者獲取到的方向資訊,順時針0-360
                    .direction(mXDirection).latitude(location.getLatitude())
                    .longitude(location.getLongitude()).build();
            mCurrentAccracy = location.getRadius();
            // 設定定位資料
            mBaiduMap.setMyLocationData(locData);
            mCurrentLantitude = location.getLatitude();
            mCurrentLongitude = location.getLongitude();
            // 設定自定義圖示
            BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory
                    .fromResource(R.mipmap.navi_map_gps_locked);
            MyLocationConfiguration config = new MyLocationConfiguration(mCurrentMode, true, mCurrentMarker);
            mBaiduMap.setMyLocationConfigeration(config);
            // 第一次定位時,將地圖位置移動到當前位置
            if (isFristLocation) {
                isFristLocation = false;
                LatLng ll = new LatLng(location.getLatitude(),
                        location.getLongitude());
                MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll);
                mBaiduMap.animateMapStatus(u);
            }
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //在activity執行onDestroy時執行mMapView.onDestroy(),實現地圖生命週期管理
        mMapView.onDestroy();
    }

    @Override
    protected void onResume() {
        super.onResume();
        //在activity執行onResume時執行mMapView. onResume (),實現地圖生命週期管理
        mMapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        //在activity執行onPause時執行mMapView. onPause (),實現地圖生命週期管理
        mMapView.onPause();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.select_type:
                //這是對話方塊展示,都可以實現,稍微調整一下位置
           /*     View typeview = LayoutInflater.from(this).inflate(R.layout.type, null);
                dialog = new Dialog(this, R.style.CustomDialog);
                dialog.setContentView(typeview);
                Window dialogWindow = dialog.getWindow();
//                WindowManager.LayoutParams lp = dialogWindow.getAttributes();
                dialogWindow.setGravity(Gravity.BOTTOM | Gravity.LEFT);
                dialog.show();*/
                //這是popwindows方式展示
                View typeview = LayoutInflater.from(this).inflate(R.layout.type, null);
                mPopupWindow = new PopupWindow(typeview, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, true);
                mPopupWindow.setTouchable(true);
                mPopupWindow.setOutsideTouchable(true);
                mPopupWindow.getContentView().setFocusableInTouchMode(true);
                mPopupWindow.getContentView().setFocusable(true);
                mPopupWindow.setBackgroundDrawable(new BitmapDrawable(getResources(), (Bitmap) null));//這句加上之後,點選背景才能去掉popwindows
                mPopupWindow.showAtLocation(type_button, Gravity.BOTTOM | Gravity.LEFT, 0, 0);
                break;
        }
    }
}

都註釋的很詳細,這裡參考了鴻洋大神的百度sdk開發,不過鴻洋大神那個時候的sdk比較老了,所以我在看了後,用現在最新的重新實現了一下這些簡單的功能,做個記錄,

下面是MyOrientationListener的程式碼,用來監聽定位後相關的操作

package com.anlaiye.swt.baidumapdemo;

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 Context context;
	private SensorManager sensorManager;
	private Sensor sensor;
	
	private float lastX ; 
	
	private OnOrientationListener onOrientationListener ; 

	public MyOrientationListener(Context context)
	{
		this.context = context;
	}

	// 開始
	public void start()
	{
		// 獲得感測器管理器
		sensorManager = (SensorManager) context
				.getSystemService(Context.SENSOR_SERVICE);
		if (sensorManager != null)
		{
			// 獲得方向感測器
			sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
		}
		// 註冊
		if (sensor != null)
		{//SensorManager.SENSOR_DELAY_UI
			sensorManager.registerListener(this, sensor,
					SensorManager.SENSOR_DELAY_UI);
		}

	}

	// 停止檢測
	public void stop()
	{
		sensorManager.unregisterListener(this);
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy)
	{
		
	}

	@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 )
            {
            	onOrientationListener.onOrientationChanged(x);
            }
//            Log.e("DATA_X", x+"");
            lastX = x ; 
            
        }  
	}
	
	public void setOnOrientationListener(OnOrientationListener onOrientationListener)
	{
		this.onOrientationListener = onOrientationListener ;
	}
	
	
	public interface OnOrientationListener 
	{
		void onOrientationChanged(float x);
	}

}
好了,簡單的功能實現都在這裡了

有很多人的地圖只有網格沒有,地圖出來,這種情況一般是appkey的問題,也就是你的sha1值可能不對,(包名寫錯的人還是很少的)

230 uid: -1 appid -1 msg: APP Scode碼校驗失敗

比如這個錯誤

http://download.csdn.net/detail/qq_15527709/9715042

可以在這裡下載apk安裝到手機上面,輸入包名,獲取sha1值