天天看點

百度地圖API使用一、開發者平台使用二、定位代碼實作

最近項目要接入地圖定位,選擇位置的功能,乙方用了百度地圖,記錄一下使用過程。

功能:

可以拖動marker改變定位位置;

點選POI清單對象,mark移動到相應位置;

點選定位回到目前位置。

ps: 搜尋功能暫時沒需要就沒加,也比較簡單。

目錄

一、開發者平台使用

一、申請ak

二、添加相應jar包和so檔案

二、定位代碼實作

一、xml布局

二、recyc

目錄

一、開發者平台使用

一、申請ak

二、添加相應jar包和so檔案

二、定位代碼實作

一、xml布局

二、activity實作

三、recycleadapter

leadapter

三、activity實作

一、開發者平台使用

一、申請ak

注冊個百度地圖開放平台的賬号,建立一個應用 http://lbsyun.baidu.com/

百度地圖API使用一、開發者平台使用二、定位代碼實作

SHA1值的生成,參考這個百度地圖論壇置頂的文章:

http://bbs.lbsyun.baidu.com/forum.php?mod=viewthread&tid=106461&highlight=230

二、添加相應jar包和so檔案

去開發者平台上下載下傳需要的包,複制到AS裡面:

我選了定位,地圖和搜尋的3個包,引入搜尋包是因為,BaiduMap對象的點選事件監聽接口的資料是經緯度對象,

用百度地圖提供的GeoCoder類,可以根據經緯度查找傳回位址,POI,經緯度等資訊。

百度地圖API使用一、開發者平台使用二、定位代碼實作

複制到項目裡面:

百度地圖API使用一、開發者平台使用二、定位代碼實作

把jar包作為項目依賴添加:

File --> Project Structure -->選中app 的dependence,點選 + 号,選中BaiduLBS_Android.jar 包,即可把此jar包添加為項目依賴,上圖裡面jar檔案也出現三角号,可以點開檢視了。

百度地圖API使用一、開發者平台使用二、定位代碼實作

把libs 檔案添加進依賴:

repositories {
    flatDir {
        dirs 'libs'
    }
}
           

二、定位代碼實作

一、xml布局

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


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/search_list">

        <com.baidu.mapapi.map.MapView
            android:id="@+id/mapView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clickable="true"/>

        <! 顯示目前定位位置>
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="10dp"
            android:background="@drawable/bg_location_name"
            android:orientation="vertical"
            android:paddingLeft="8dp"
            android:paddingRight="8dp"
            android:visibility="visible">

            <TextView
                android:id="@+id/tv_addr"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="5dp"
                android:text="坐标更新"
                android:textColor="@color/white"
                android:textSize="14sp"/>
        </LinearLayout>


        <! 點選回到目前位置>
        <LinearLayout
            android:id="@+id/my_location"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:clickable="true"
            android:focusable="true"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="40dp"
            android:layout_marginLeft="16dp"
            android:layout_marginStart="16dp"
            android:background="@drawable/bg_location">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@mipmap/location"/>
        </LinearLayout>

    </RelativeLayout>


    <! 顯示附近POI資訊>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/search_list"
        android:layout_width="match_parent"
        android:layout_height="230dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true">

    </android.support.v7.widget.RecyclerView>


</RelativeLayout>
           

二、activity實作

我用MVP模式寫的,其實不是标準的mvp,邏輯和資料處理放在presenter裡面了,沒有用model進行資料處理。

1、contract類:

/**
 * 百度地圖定位 contract
 */

public interface MapViewContract {

    interface View extends BusinessView<Presenter> {
        void showAddr(ReverseGeoCodeResult result);
    }

    abstract class Presenter extends BusinessPresenter<View> {
        public Presenter(BusinessActivity activity, View view) {
            super(activity, view);
        }
        //将mapView對象傳過來,用來執行個體化BaiduMap對象
        public abstract void getAddr(MapView mMapView);
        public abstract void backToCurrentLocation();//回到目前位置
        public abstract void setMarkLocation(LatLng latLng);//設定marker位置

    }


}
           

2、activity

/**
 * 可拖動 marker 定位
 */

public class MapViewActivity extends BusinessActivity<MapViewContract.Presenter> implements MapViewContract.View, View.OnClickListener, LocationItemAdapter.onItemClickListener {

    private MapView mMapView;
    private TextView tvAddr;
    private String locationAdrr = "";
    private LinearLayout myLocation;
    private RecyclerView searchListRecycle;
    private LocationItemAdapter adapter;
    private List<PoiInfo> poiInfoList = new ArrayList<>();

    private double longitude;
    private double latitude;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map_view);
        new MapViewPresenter(this, this);
        setTitle("選擇位置");
        showAheadLayout();
        getAheadTextView().setText("确定");
        initView();
    }

    private void initView() {
        mMapView = (MapView) findViewById(R.id.mapView);
        tvAddr = (TextView) findViewById(R.id.tv_addr);
        getPresenter().getAddr(mMapView);
        myLocation = (LinearLayout) findViewById(R.id.my_location);
        myLocation.setOnClickListener(this);
        searchListRecycle = (RecyclerView) findViewById(R.id.search_list);

        adapter = new LocationItemAdapter();
        adapter.setItemList(poiInfoList);
        adapter.setListener(this);
        searchListRecycle.setLayoutManager(new LinearLayoutManager(this));
        searchListRecycle.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        searchListRecycle.setAdapter(adapter);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.my_location:
                //marker回到目前位置
                getPresenter().backToCurrentLocation();
                break;
        }
    }


    //點選确定,傳回定位的結果
    @Override
    public void onBarItemClick(ToolBarButton id) {
        if (id == ToolBarButton.AHEAD) {
            Intent intent = new Intent();
            intent.putExtra(KeyName.ADDR_NAME, locationAdrr);
            intent.putExtra(KeyName.ADDR_NAME_longitude,longitude);
            intent.putExtra(KeyName.ADDR_NAME_latitude,latitude);
            setResult(IntentCode.RESULT_ADDR_NAME, intent);
            finish();
        }
        super.onBarItemClick(id);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Override
    protected void onDestroy() {
        mMapView.onDestroy();
        mMapView = null;
        super.onDestroy();

    }

    //擷取到定位資訊和周圍POI,傳回結果,view展示資料
    @Override
    public void showAddr(ReverseGeoCodeResult result) {
        tvAddr.setText(result.getAddress());
        locationAdrr = result.getAddress();
        longitude = result.getLocation().longitude;
        latitude = result.getLocation().latitude;
        this.poiInfoList = result.getPoiList();
        adapter.setItemList(poiInfoList);
        adapter.notifyDataSetChanged();
    }

    //點選POI清單的對象,更新資料,設定marker位置
    @Override
    public void onItemClick(PoiInfo data, int position) {
        if (null != data) {
            tvAddr.setText(data.address);
            locationAdrr = data.address;
            longitude = data.location.longitude;
            latitude = data.location.latitude;
            getPresenter().setMarkLocation(data.location);
        }
    }
}
           

3、presenter類

/**
 * 百度地圖定位 presenter
 */

public class MapViewPresenter extends MapViewContract.Presenter implements OnGetGeoCoderResultListener, OnGetPoiSearchResultListener {
    private BaiduMap mBaiduMap = null;
    private MyLocationData locData; //定位資料包
    private Marker marker;//位置标志
    boolean isFirstLoc = true; // 是否首次定位
    LocationClient mLocClient;
    GeoCoder mSearch = null; // 搜尋子產品,根據經緯度擷取位置資訊,也可去掉地圖子產品獨立使用
    PoiSearch mPoiSearch;//搜尋附近POI,可用于根據關鍵字搜尋位置

    public MapViewPresenter(BusinessActivity activity, MapViewContract.View view) {
        super(activity, view);
    }

    @Override
    public void getAddr(MapView mMapView) {
        mBaiduMap = mMapView.getMap();
        //設定類型
        mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
        mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomTo(18f));
        // 開啟定位圖層
        mBaiduMap.setMyLocationEnabled(true);

        //用application對象初始化LocationClient 對象
        mLocClient = new LocationClient(getActivity().getApplicationContext());
        //設定位置監聽器
        mLocClient.registerLocationListener(listener);

        LocationClientOption option = new LocationClientOption();
        option.setIsNeedAddress(true);//是否要位址
        option.setOpenGps(true);
        option.setCoorType("bd09ll"); // 設定坐标類型
        //設定定位模式:高精度,低功耗,僅裝置
        option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        //可選,預設0,即僅定位一次,設定發起連續定位請求的間隔需要大于等于1000ms才是有效的    
        option.setScanSpan(3000);

        mLocClient.setLocOption(option);
        mLocClient.start();


        //對Marker的點選事件
        mBaiduMap.setOnMarkerClickListener(new BaiduMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(Marker marker) {
                //擷取marker中的資料
                searchNearBy(marker.getPosition());
                return false;
            }
        });

        //Map點選事件,點選地圖移動marker
        mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() {
            @Override
            public void onMapClick(LatLng latLng) {
                //設定marker位置,将marker移動到點選地圖位置
                marker.setPosition(latLng);

                //反Geo搜尋,根據經緯度搜尋位置和POI資訊
                searchNearBy(marker.getPosition());

            }

            @Override
            public boolean onMapPoiClick(MapPoi mapPoi) {
                //同上
                marker.setPosition(mapPoi.getPosition());
                searchNearBy(marker.getPosition());

                return false;
            }
        });

        //對Marker的拖拽事件
        mBaiduMap.setOnMarkerDragListener(new BaiduMap.OnMarkerDragListener() {
            @Override
            public void onMarkerDrag(Marker marker) {

            }

            @Override
            public void onMarkerDragEnd(Marker marker) {
                //根據經緯度擷取位置和POI資訊
                searchNearBy(marker.getPosition());
            }

            @Override
            public void onMarkerDragStart(Marker marker) {

            }
        });

        // 初始化搜尋子產品,注冊事件監聽
        mSearch = GeoCoder.newInstance();
        mSearch.setOnGetGeoCodeResultListener(this);

        //初始化POI搜尋對象,可根據關鍵字搜尋位址,但是此處我沒有使用它
        mPoiSearch = PoiSearch.newInstance();
        mPoiSearch.setOnGetPoiSearchResultListener(this);
    }

    //點選回到目前位置
    @Override
    public void backToCurrentLocation() {
        mLocClient.start();
    }

    //點選POI清單的item,對應移動marker到相應位置
    @Override
    public void setMarkLocation(LatLng latLng) {
        if (null != marker) {
            marker.setPosition(latLng);
            MapStatus.Builder builder = new MapStatus.Builder();
            builder.target(latLng).zoom(18.0f);
            mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
        }
    }


    /***
     * 定位結果回調,在此方法中處理定位結果
     */
    BDAbstractLocationListener listener = new BDAbstractLocationListener() {
        @Override
        public void onReceiveLocation(BDLocation bdLocation) {

            // map view 銷毀後不在處理新接收的位置
            if (mLocClient == null || null == bdLocation) {
                return;
            }

            //構造定位資料
            locData = new MyLocationData.Builder()
                    .accuracy(bdLocation.getRadius())
                    .latitude(bdLocation.getLatitude())
                    .longitude(bdLocation.getLongitude())
                    // 此處設定開發者擷取到的方向資訊,順時針0-360
                    .direction(100)
                    .build();

            mBaiduMap.setMyLocationData(locData);
            LatLng ll = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());

            MapStatus.Builder builder = new MapStatus.Builder();
            builder.target(ll).zoom(18.0f);
            
//更新地圖狀态
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));

            //根據經緯度搜尋位址和POI資訊
            searchNearBy(ll);

            //隻有第一次定位的時候,構造marker對象
            if (isFirstLoc) {

                isFirstLoc = false;

                BitmapDescriptor bitmap = BitmapDescriptorFactory.fromResource(R.mipmap.locationmark);
                // 建構MarkerOption,用于在地圖上添加Marker
                OverlayOptions option = new MarkerOptions()
                        .position(ll) //mark出現的位置
                        .icon(bitmap) //mark圖示
                        .draggable(true);//mark可拖動
                //在地圖上添加Marker并顯示
                marker = (Marker) mBaiduMap.addOverlay(option);

            } else {
                //不是第一次定位,設定marker移動到目前定位的位置
                if (null != marker) {
                    marker.setPosition(ll);
                }
            }


            mLocClient.stop();
        }
    };

    //根據經緯度,用GeoCoder 對象反geo編碼擷取到位置資訊
    public void searchNearBy(LatLng latLng) {
        if (null != latLng) {
            mSearch.reverseGeoCode(new ReverseGeoCodeOption()
                    .location(latLng));
        } else {
            ToastUtil.toast("未找到結果");
        }

    }

    //反geo搜尋的 OnGetGeoCodeResultListener傳回資料接口
    @Override
    public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
        if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
            ToastUtil.toast("未能找到結果");
            return;
        }
        getView().showAddr(result);
    }

    //geo搜尋的 OnGetGeoCodeResultListener傳回資料接口,此處用不到
    @Override
    public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //退出時銷毀定位
        mLocClient.stop();
        //退出時關閉定位圖層
        mBaiduMap.setMyLocationEnabled(false);
        mSearch.destroy();
    }

    /**
     * 通過經緯度 和 關鍵字 搜尋poi,此處沒有用到
     *
     * @param latLng
     */
    private void search(LatLng latLng, String name) {
        if (null != name) {
            mPoiSearch.searchNearby(new PoiNearbySearchOption().keyword(name)
                    .location(latLng).radius(500).pageNum(1));
        } else {
            ToastUtil.toast("未找到結果");
            //view 的POI清單顯示空
        }
    }

    //mPoiSearch.setOnGetPoiSearchResultListener監聽器傳回資料接口,此處沒用到
    //可用于關鍵字搜尋位置資訊和POI資訊
    @Override
    public void onGetPoiResult(PoiResult poiResult) {
        if (poiResult == null || poiResult.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {
            ToastUtil.toast("未找到結果");
            return;
        }
        if (poiResult.error == SearchResult.ERRORNO.NO_ERROR) {
            ToastUtil.toast("poi 數目:" + poiResult.getAllPoi().size());
            return;
        }
    }

    @Override
    public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {

    }

    @Override
    public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {

    }
}
           

三、recycleadapter

/**
 * 百度地圖定位,顯示POI
 */

public class LocationItemAdapter extends RecyclerView.Adapter<LocationItemAdapter.ViewHolder> implements View.OnClickListener {

    private List<PoiInfo> itemList;
    private onItemClickListener listener;
    private int position;

    public void setListener(onItemClickListener listener) {
        this.listener = listener;
    }

    public void setItemList(List<PoiInfo> itemList) {
        this.itemList = itemList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_map_location, parent, false);

        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.tvName.setText(itemList.get(position).name);
        holder.tvAddress.setText(itemList.get(position).address);
        holder.itemView.setTag(itemList.get(position));
        this.position = position;
        holder.rootView.setOnClickListener(this);

    }

    @Override
    public int getItemCount() {
        if (null != itemList) {
            return itemList.size();
        }
        return 0;
    }

    @Override
    public void onClick(View v) {
        PoiInfo data = (PoiInfo) v.getTag();
        if (null != data && null != listener) {
            listener.onItemClick(data, position);
        }
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public View rootView;
        public TextView tvName;
        public TextView tvAddress;

        public ViewHolder(View rootView) {
            super(rootView);
            this.rootView = rootView;
            this.tvName = (TextView) rootView.findViewById(R.id.tv_name);
            this.tvAddress = (TextView) rootView.findViewById(R.id.tv_address);
        }

    }

    public interface onItemClickListener {
        void onItemClick(PoiInfo data, int position);
    }
}
           

注:手勢操作管理

UiSettings settings=mBaiduMap.getUiSettings();
settings.setAllGesturesEnabled(false);   //關閉一切手勢操作
settings.setZoomGesturesEnabled(false);//是否允許縮放手勢