天天看點

Android 地圖導航開發

在相關下載下傳裡下載下傳最新的庫檔案。将so檔案的壓縮檔案解壓出來,把對應架構下的so檔案放入開發者自己APP的對應架構下的檔案夾中(建議全部放入以提高程式相容性),将locSDK_6.X.jar檔案拷貝到工程的libs目錄下,這樣您就可以在程式中使用百度定位SDK了。

使用eclipse開發的開發者,隻需要将SO的檔案夾放到libs下即可;使用AndroidStutio的開發者除了上述操作,還需要在build.gradle中配置SO的使用,如下所示:

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

開發者如果開發的是系統應用,則隻在工程中配置SO還是不夠的,還需要手動把對應架構的SO拷貝到/system/lib下,如果是位系統的話需要将位的SO拷貝到/sytem/lib64下。

注意:每次新版本的定位SDK,開發者除了要更新JAR包之外,也要注意一下SO有無更新,如果SO名稱不一樣了,也要及時替換老的SO版本,不然會導緻定位失敗!
設定AndroidManifest.xml
在application标簽中聲明service元件,每個app擁有自己單獨的定位service

<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote">
</service>

【重要提醒】

定位SDKv3版本之後,以下權限已不需要,請取消聲明,否則将由于Android 多帳戶系統加強權限管理而導緻應用安裝失敗。 <uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE"></uses-permission>
聲明使用權限

<!-- 這個權限用于進行網絡定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!-- 這個權限用于通路GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<!-- 用于通路wifi網絡資訊,wifi資訊會用于進行網絡定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<!-- 擷取營運商資訊,用于支援提供營運商資訊相關的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<!-- 這個權限用于擷取wifi的擷取權限,wifi資訊會用來進行網絡定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<!-- 用于讀取手機目前的狀态-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<!-- 寫入擴充存儲,向擴充卡寫入資料,用于寫入離線定位資料-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!-- 通路網絡,網絡定位需要上網-->
<uses-permission android:name="android.permission.INTERNET" />
<!-- SD卡讀取權限,使用者寫入離線定位資料-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>

設定AcessKey

SDK4及之後版本需要在Mainfest.xml設定Accesskey,設定有誤會引起定位和地理圍欄服務不能正常使用,必須進行Accesskey的正确設定。

設定AccessKey,在application标簽中加入

<meta-data
            android:name="com.baidu.lbsapi.API_KEY"
            android:value="key" />       //key:開發者申請的key

import相關類

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.BDNotifyListener;//假如用到位置提醒功能,需要import該類
import com.baidu.location.Poi;
           
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Point;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
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.BaiduMap.OnMapClickListener;
import com.baidu.mapapi.map.BaiduMap.OnMarkerClickListener;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.InfoWindow.OnInfoWindowClickListener;
import com.baidu.mapapi.map.MapPoi;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationConfiguration.LocationMode;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.model.LatLng;
import com.imooc.baidumap.MyOrientationListener.OnOrientationListener;

public class MainActivity extends Activity {

    /**
     * @Field @mMapView : TODO(XML中用于顯示地圖的控件)
     */
    private MapView mMapView;
    /**
     * @Field @mBaiduMap : TODO(定義 BaiduMap 地圖對象的操作方法與接口)
     */
    private BaiduMap mBaiduMap;

    private Context context;

    // 定位相關
    private LocationClient mLocationClient;
    private MyLocationListener mLocationListener;
    private boolean isFirstIn = true;
    private double mLatitude;
    private double mLongtitude;
    // 自定義定位圖示
    private BitmapDescriptor mIconLocation;// bitmap 描述資訊
    private MyOrientationListener myOrientationListener;
    private float mCurrentX;
    private LocationMode mLocationMode;

    // 覆寫物相關
    private BitmapDescriptor mMarker;
    private RelativeLayout mMarkerLy;

    /*
     * (非 Javadoc) Description:
     * @see android.app.Activity#onCreate(android.os.Bundle)
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // requestWindowFeature(Window.FEATURE_NO_TITLE);
        // 在使用SDK各元件之前初始化context資訊,傳入ApplicationContext
        // 注意該方法要再setContentView方法之前實作
        // getWindow().setFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY,WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
        try {
            getWindow().addFlags(WindowManager.LayoutParams.class.getField("FLAG_NEEDS_MENU_KEY").getInt(null));
        } catch (NoSuchFieldException e) {
            // Ignore since this field won't exist in most versions of Android
        } catch (IllegalAccessException e) {
            Log.w("feelyou.info", "Could not access FLAG_NEEDS_MENU_KEY in addLegacyOverflowButton()", e);
        }
        SDKInitializer.initialize(getApplicationContext());
        setContentView(R.layout.activity_main);

        this.context = this;

        initView();
        // 初始化定位
        initLocation();
        initMarker();

        mBaiduMap.setOnMarkerClickListener(new OnMarkerClickListener() {

            // 設定地圖 Marker 覆寫物點選事件監聽者,自3.4.0版本起可設定多個監聽對象,停止監聽時調用removeMarkerClickListener移除監聽對象
            @Override
            public boolean onMarkerClick(Marker marker) {
                Bundle extraInfo = marker.getExtraInfo();
                Info info = (Info) extraInfo.getSerializable("info");
                ImageView iv = (ImageView) mMarkerLy.findViewById(R.id.id_info_img);
                TextView distance = (TextView) mMarkerLy.findViewById(R.id.id_info_distance);
                TextView name = (TextView) mMarkerLy.findViewById(R.id.id_info_name);
                TextView zan = (TextView) mMarkerLy.findViewById(R.id.id_info_zan);
                iv.setImageResource(info.getImgId());
                distance.setText(info.getDistance());
                name.setText(info.getName());
                zan.setText(info.getZan() + "");

                InfoWindow infoWindow;
                TextView tv = new TextView(context);
                tv.setBackgroundResource(R.drawable.location_tips);
                tv.setPadding(, , , );
                tv.setText(info.getName());
                tv.setTextColor(Color.parseColor("#ffffff"));

                final LatLng latLng = marker.getPosition();
                Point p = mBaiduMap.getProjection().toScreenLocation(latLng);// 将地理坐标轉換成螢幕坐标
                p.y -= ;
                LatLng ll = mBaiduMap.getProjection().fromScreenLocation(p);// 将螢幕坐标轉換成地理坐标

                infoWindow = new InfoWindow(tv, ll, new OnInfoWindowClickListener() {

                    @Override
                    public void onInfoWindowClick() {
                        mBaiduMap.hideInfoWindow();// 隐藏目前 InfoWindow
                    }
                });
                mBaiduMap.showInfoWindow(infoWindow);// 顯示 InfoWindow
                mMarkerLy.setVisibility(View.VISIBLE);
                return true;
            }
        });
        mBaiduMap.setOnMapClickListener(new OnMapClickListener() {// 設定地圖單擊事件監聽者

                    @Override
                    public boolean onMapPoiClick(MapPoi arg0) {
                        return false;
                    }

                    @Override
                    public void onMapClick(LatLng arg0) {
                        mMarkerLy.setVisibility(View.GONE);
                        mBaiduMap.hideInfoWindow();// 隐藏目前 InfoWindow
                    }
                });
    }

    private void initMarker() {
        mMarker = BitmapDescriptorFactory.fromResource(R.drawable.maker);
        mMarkerLy = (RelativeLayout) findViewById(R.id.id_maker_ly);
    }

    private void initLocation() {

        mLocationMode = LocationMode.NORMAL;
        mLocationClient = new LocationClient(this);
        mLocationListener = new MyLocationListener();
        mLocationClient.registerLocationListener(mLocationListener);

        LocationClientOption option = new LocationClientOption();
        option.setCoorType("bd09ll");
        option.setIsNeedAddress(true);
        option.setOpenGps(true);
        option.setScanSpan();
        mLocationClient.setLocOption(option);
        // 初始化圖示
        mIconLocation = BitmapDescriptorFactory.fromResource(R.drawable.navi_map_gps_locked);
        myOrientationListener = new MyOrientationListener(context);

        myOrientationListener.setOnOrientationListener(new OnOrientationListener() {

            @Override
            public void onOrientationChanged(float x) {
                mCurrentX = x;
            }
        });

    }

    private void initView() {
        mMapView = (MapView) findViewById(R.id.id_bmapView);
        mBaiduMap = mMapView.getMap();
        MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(f);
        mBaiduMap.setMapStatus(msu);// 改變地圖狀态
    }

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

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

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

    @Override
    protected void onStop() {
        super.onStop();

        // 停止定位
        mBaiduMap.setMyLocationEnabled(false);
        mLocationClient.stop();
        // 停止方向傳感器
        myOrientationListener.stop();

    }

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.id_map_common:
            mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);// 設定地圖類型 MAP_TYPE_NORMAL 普通圖; MAP_TYPE_SATELLITE
                                                           // 衛星圖;MAP_TYPE_NONE 衛星圖
            break;

        case R.id.id_map_site:
            mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
            break;

        case R.id.id_map_traffic:
            if (mBaiduMap.isTrafficEnabled()) {// 擷取是否打開交通圖層
                mBaiduMap.setTrafficEnabled(false);// 設定是否打開交通圖層
                item.setTitle("實時交通(off)");
            } else {
                mBaiduMap.setTrafficEnabled(true);
                item.setTitle("實時交通(on)");
            }
            break;
        case R.id.id_map_location:
            centerToMyLocation();
            break;
        case R.id.id_map_mode_common:
            mLocationMode = LocationMode.NORMAL;
            break;
        case R.id.id_map_mode_following:
            mLocationMode = LocationMode.FOLLOWING;
            break;
        case R.id.id_map_mode_compass:
            mLocationMode = LocationMode.COMPASS;
            break;
        case R.id.id_add_overlay:
            addOverlays(Info.infos);
            break;
        default:
            break;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * 添加覆寫物
     * 
     * @param infos
     */
    private void addOverlays(List<Info> infos) {
        mBaiduMap.clear();// 清空地圖所有的 Overlay 覆寫物以及 InfoWindow
        LatLng latLng = null;
        Marker marker = null;
        OverlayOptions options;
        for (Info info : infos) {
            // 經緯度
            latLng = new LatLng(info.getLatitude(), info.getLongitude());
            // 圖示
            options = new MarkerOptions().position(latLng).icon(mMarker).zIndex();
            marker = (Marker) mBaiduMap.addOverlay(options);// 向地圖添加一個 Overlay
            Bundle arg0 = new Bundle();
            arg0.putSerializable("info", info);
            marker.setExtraInfo(arg0);
        }

        MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
        mBaiduMap.setMapStatus(msu);// 改變地圖狀态

    }

    /**
     * 定位到我的位置
     */
    private void centerToMyLocation() {
        LatLng latLng = new LatLng(mLatitude, mLongtitude);
        MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
        mBaiduMap.animateMapStatus(msu);// 以動畫方式更新地圖狀态,動畫耗時 300 ms
    }

    private class MyLocationListener implements BDLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {

            MyLocationData data = new MyLocationData.Builder()//
                    .direction(mCurrentX)//
                    .accuracy(location.getRadius())//
                    .latitude(location.getLatitude())//
                    .longitude(location.getLongitude())//
                    .build();
            mBaiduMap.setMyLocationData(data);// 設定定位資料, 隻有先允許定位圖層後設定資料才會生效,參見 setMyLocationEnabled(boolean)
            // 設定自定義圖示
            MyLocationConfiguration config = new MyLocationConfiguration(mLocationMode, true, mIconLocation);
            mBaiduMap.setMyLocationConfigeration(config);// 設定定位圖層配置資訊,隻有先允許定位圖層後設定定位圖層配置資訊才會生效

            // 更新經緯度
            mLatitude = location.getLatitude();
            mLongtitude = location.getLongitude();

            if (isFirstIn) {
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
                MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
                mBaiduMap.animateMapStatus(msu);// 以動畫方式更新地圖狀态,動畫耗時 300 ms
                isFirstIn = false;

                Toast.makeText(context, location.getAddrStr(), Toast.LENGTH_SHORT).show();
            }

        }
    }

}
           

繼續閱讀