百度地图API基础操作--导航篇

接着上一篇的定位写,之前的那篇文章仅仅介绍了简单的当前位置的定位,其实官方文档写的很详细了,出贴意义不大,不过导航篇还是有必要叨叨一下的,在我最初研究百度地图API的时候,差点被官方文档绕迷糊了,还是踩过许多坑的,也许是我悟性不够吧,哈哈,下面出教程(其实更偏向于我的私人笔记)

还是熟悉的–准备工作

由于这个是接着上一篇写的,代码也是在原来工程的基础上加的功能,所以,之前强调的准备工作依然需要的,在这里就不多说了。提醒一下,如果在之前定位实现的时候下载的SDK没有包含导航模块,一定要重新去百度地图API下载区去下载完整的SDK包,把之前的替换掉。
相对于定位,导航新加了一些权限,如下:

<!-- 百度地图导航所需权限 start -->
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  
<uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE" />  
<uses-permission android:name="android.permission.ACCES_MOCK_LOCATION" />  
<uses-permission android:name="android.permission.ACCESS_GPS" />   
<uses-permission android:name="android.permission.BROADCAST_STICKY" />  
<!-- 来电消音 -->  
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />  
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />  
<uses-permission android:name="android.permission.RECORD_AUDIO" />     
 <!-- 摄影机 -->     
<uses-permission android:name="android.permission.CAMERA" />
 <!-- 百度地图导航所需权限 end -->

还要加上百度地图的服务声明(其实这些在官方文档介绍的都很详细的)

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

在之前的SDK版本中,语音TTS需要设置鉴权白名单的,因为要写这篇帖子,昨天就重新看了下官方文档,发现方法变了,不需要设置白名单了,新版本需要两个步骤,一、在http://yuyin.baidu.com/app创建自己的应用,注册语音合成功能;二、在初始化导航前,调用APPID的设置接口,这样就可以进行语音导航了,所谓APPID就是在注册语音合成功能的时候生成的,在步骤一的新建完的应用中可以查到

Bundle bundle = new Bundle();
        // 必须设置APPID,否则会静音
        bundle.putString(BNCommonSettingParam.TTS_APP_ID, "你自己的APPID");
        BNaviSettingManager.setNaviSdkParam(bundle);

BaiduNaviOperation类

先新建一个百度地图导航的操作类,当然啦,你大可不必一定要新建类,个人习惯而已,这个类里主要包含两个内容,首先是导航引擎的初始化,然后就是发起算路及算路成功后跳转到诱导View

导航引擎初始化

初始化之前要检查是否有完备的权限

// 申请权限
        if (android.os.Build.VERSION.SDK_INT >= 23) {
             // 保证导航功能完备
            if (!hasBasePhoneAuth()) {
                if (!hasRequestComAuth) {
                    hasRequestComAuth = true;
                    mActivity.requestPermissions(authComArr, authComRequestCode);
                    return;
                } else {
                    Toast.makeText(mActivity, "没有完备的权限!", Toast.LENGTH_SHORT).show();
                }

            }
        }

权限完备之后,要设置一个用来缓存导航数据的文件夹,在这里我设置为根文件夹下名为“导航demo”的文件夹,不存在则新建

private boolean initDirs() {
        mSDCardPath = getSdcardDir();
        if (mSDCardPath == null) {
            return false;
        }
        File f = new File(mSDCardPath, APP_FOLDER_NAME);//APP_FOLDER_NAME是文件夹的名字,自定义的
        if (!f.exists()) {
            try {
                f.mkdir();
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }

    private String getSdcardDir() {
        if (Environment.getExternalStorageState().equalsIgnoreCase(
                Environment.MEDIA_MOUNTED)) {
            return Environment.getExternalStorageDirectory().toString();
        }
        return null;
    }

在之前提到初始化之前要调用APPID的设置接口,不然导航会没声音,那么下一步就是把刚才APPID的设置的那块代码拿过来用咯。
最后才是真正的初始化操作,先上代码再解释:

/***
 *mActivity - 传过来的Activity
 *mSDCardPath  - 系统根文件夹
 *APP_FOLDER_NAME - 应用在SD卡中的目录名
 *NaviInitListener- 百度导航初始化监听器
 *ttsCallback - 外部TTS能力回调接口,若使用百度内置TTS能力,传入null即可
 *ttsHandler - 异步获取百度内部TTS播报状态
 *ttsPlayStateListener- 同步获取百度内部TTS播报状态
 ***/
        BaiduNaviManager.getInstance().init(mActivity, mSDCardPath,
                APP_FOLDER_NAME, new NaviInitListener() {

                    @Override
                    public void initFailed() {
                        // TODO Auto-generated method stub
                        System.out.println("失败");
                    }

                    @Override
                    public void initStart() {
                        // TODO Auto-generated method stub
                        System.out.println("开始");
                    }

                    @Override
                    public void initSuccess() {
                        // TODO Auto-generated method stub
                        Toast.makeText(mActivity, "百度导航引擎初始化成功",
                                Toast.LENGTH_SHORT).show();
                        initSetting();

                    }

                    @Override
                    public void onAuthResult(int status, String msg) {
                        if (0 == status) {
                            authinfo = "key校验成功!";
                        } else {
                            authinfo = "key校验失败, " + msg;
                        }
                        mActivity.runOnUiThread(new Runnable() {

                            @Override
                            public void run() {
                                Toast.makeText(mActivity, authinfo,
                                        Toast.LENGTH_LONG).show();
                            }
                        });
                    }
                }, null, ttsHandler, ttsPlayStateListener);

导航的初始化监听器能够捕获到四种事件,先校验key,然后开始初始化,再就是初始化的两种结果,失败、成功,这个代码都很易懂,没什么可说的;ttsCallback 这个参数,由于使用的内置TTS,所以我传进了null,ttsHandler以及ttsPlayStateListener,在功能实现上没什么太重要的影响,为了节省时间我给省略了,仅仅做个初步的创建,代码如下:

private Handler ttsHandler = new Handler() {
        public void handleMessage(Message msg) {
            int type = msg.what;
            switch (type) {
            case BaiduNaviManager.TTSPlayMsgType.PLAY_START_MSG: {
                // showToastMsg("Handler : TTS play start");
                break;
            }
            case BaiduNaviManager.TTSPlayMsgType.PLAY_END_MSG: {
                // showToastMsg("Handler : TTS play end");
                break;
            }
            default:
                break;
            }
        }
    };

    private BaiduNaviManager.TTSPlayStateListener ttsPlayStateListener = new BaiduNaviManager.TTSPlayStateListener() {

        @Override
        public void playEnd() {
            // showToastMsg("TTSPlayStateListener : TTS play end");
        }

        @Override
        public void playStart() {
            // showToastMsg("TTSPlayStateListener : TTS play start");
        }
    };

初始化的操作到此就结束了,初始化成功之后,调一下initSetting(),用来设置导航的部分初始化设置项

private void initSetting() {

        BNaviSettingManager.setShowTotalRoadConditionBar(BNaviSettingManager.PreViewRoadCondition.ROAD_CONDITION_BAR_SHOW_ON);
        BNaviSettingManager.setVoiceMode(BNaviSettingManager.VoiceMode.Veteran);
        BNaviSettingManager
                .setRealRoadCondition(BNaviSettingManager.RealRoadCondition.NAVI_ITS_ON);
    }

发起算路

通过代码解释吧

/***
 *routeplanToNavi - 发起算路
 *coType - 坐标系类型
 *f_longitude - 当前位置的longitude
 *f_latitude - 当前位置的latitude
 *fromname - 当前位置名称
 ***/
public void routeplanToNavi(CoordinateType coType, double f_longitude,
            double f_latitude, String fromname) {
//      mCoordinateType = coType;
        hasInitSuccess=BaiduNaviManager.isNaviInited();//获取是否已经初始化
        if (!hasInitSuccess) {
            Toast.makeText(mActivity, "还未初始化!", Toast.LENGTH_SHORT).show();
        }
        // 权限申请
        if (android.os.Build.VERSION.SDK_INT >= 23) {
            // 保证导航功能完备
            if (!hasCompletePhoneAuth()) {
                if (!hasRequestComAuth) {
                    hasRequestComAuth = true;
                    mActivity
                            .requestPermissions(authComArr, authComRequestCode);
                    return;
                } else {
                    Toast.makeText(mActivity, "没有完备的权限!", Toast.LENGTH_SHORT)
                            .show();
                }
            }

        }
        BNRoutePlanNode sNode = null;//起始地点
        BNRoutePlanNode eNode = null;//目的地
        switch (coType) {

        case BD09LL: {
            sNode = new BNRoutePlanNode(f_longitude, f_latitude, fromname,
                    null, coType);
            eNode = new BNRoutePlanNode(116.40386525193937, 39.915160800132085, "北京天安门", null,
                    coType);
            break;
        }
        default:
            break;
        }
        if (sNode != null && eNode != null) {
            List<BNRoutePlanNode> list = new ArrayList<BNRoutePlanNode>();
            list.add(sNode);
            list.add(eNode);
            //发起算路操作并在算路成功后通过回调监听器进入导航过程
            BaiduNaviManager.getInstance().launchNavigator(mActivity, list, 1,
                    true, new DemoRoutePlanListener(sNode));
        }
    }

由于在本次工程中没有用到BD09LL之外的其他坐标系类型,所以,在进行类型判断时我只写了BD09LL的处理方法,在设置目的地的坐标时,为了节省时间,并没有动态设置,而是直接设置了天安门广场的坐标,各位在实际项目中肯定不可能这么干的,终点的坐标直接像当前位置坐标一样通过参数传递过来就行了
BaiduNaviManager.getInstance().launchNavigator(mActivity,list,1,true,new DemoRoutePlanListener(sNode)); launchNavigator的第三个参数“1”,代表的是推荐路线

限定符和类型字段和说明
static intROUTE_PLAN_MOD_AVOID_TAFFICJAM 躲避拥堵16
static intROUTE_PLAN_MOD_MIN_DIST 少走高速4
static intROUTE_PLAN_MOD_MIN_TIME 高速优先2
static intROUTE_PLAN_MOD_MIN_TOLL 少收费8
static intROUTE_PLAN_MOD_RECOMMEND 推荐1

launchNavigator第四个参数true表示真实GPS导航,false表示模拟导航;
DemoRoutePlanListener算路结果监听器,算路成功则可以进入导航界面

public class DemoRoutePlanListener implements RoutePlanListener {

        private BNRoutePlanNode mBNRoutePlanNode = null;

        public DemoRoutePlanListener(BNRoutePlanNode node) {
            mBNRoutePlanNode = node;
        }

        @Override
        public void onJumpToNavigator() {
            /*
             * 设置途径点以及resetEndNode会回调该接口
             */

            for (Activity ac : activityList) {
              //判断当前界面是否是诱导view,如果是,就不需要跳转了
                if (ac.getClass().getName().endsWith("BNDemoGuideActivity")) {

                    return;
                }
            }
            Intent intent = new Intent(mActivity, BNDemoGuideActivity.class);
            Bundle bundle = new Bundle();
            bundle.putSerializable(ROUTE_PLAN_NODE,
                    (BNRoutePlanNode) mBNRoutePlanNode);
            intent.putExtras(bundle);
            mActivity.startActivity(intent);

        }

        @Override
        public void onRoutePlanFailed() {
            // TODO Auto-generated method stub
            Toast.makeText(mActivity, "算路失败", Toast.LENGTH_SHORT).show();
        }
    }

通过监听器代码可以看出,算路成功后,跳转到诱导view,将目的地的坐标通过可序列化对象接口的方式传递给跳转页面,那么,我们应该新建一个诱导view的Activity,自定义Activity名为“BNDemoGuideActivity”,继承于Activity,但是不要xml布局文件,这个在官方文档给的demo中有,直接拷贝过来稍微改改用就可以, 记得在AndroidManifest.xml中注册下哦

 <activity
            android:name=".BNDemoGuideActivity"
            android:configChanges="orientation|screenSize|keyboard|keyboardHidden"

            android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
        </activity>

BNDemoGuideActivity

直接上代码

import java.util.ArrayList;
import java.util.List;
import com.baidu.navisdk.adapter.BNRouteGuideManager;
import com.baidu.navisdk.adapter.BNRouteGuideManager.CustomizedLayerItem;
import com.baidu.navisdk.adapter.BNRouteGuideManager.OnNavigationListener;
import com.baidu.navisdk.adapter.BNRoutePlanNode;
import com.baidu.navisdk.adapter.BNaviBaseCallbackModel;
import com.baidu.navisdk.adapter.BaiduNaviCommonModule;
import com.baidu.navisdk.adapter.NaviModuleFactory;
import com.baidu.navisdk.adapter.NaviModuleImpl;
import com.baidu.navisdk.adapter.BNRoutePlanNode.CoordinateType;

import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Toast;


public class BNDemoGuideActivity extends Activity {

    private final String TAG = BNDemoGuideActivity.class.getName();
    private BNRoutePlanNode mBNRoutePlanNode = null;
    private BaiduNaviCommonModule mBaiduNaviCommonModule = null;

    private boolean useCommonInterface = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        BaiduNaviOperation.activityList.add(this);
        createHandler();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        }
        View view = null;
        if (useCommonInterface) {
             //使用通用接口
            mBaiduNaviCommonModule = NaviModuleFactory.getNaviModuleManager().getNaviCommonModule(
                    NaviModuleImpl.BNaviCommonModuleConstants.ROUTE_GUIDE_MODULE, this,
                    BNaviBaseCallbackModel.BNaviBaseCallbackConstants.CALLBACK_ROUTEGUIDE_TYPE, mOnNavigationListener);
            if(mBaiduNaviCommonModule != null) {
                mBaiduNaviCommonModule.onCreate();
                view = mBaiduNaviCommonModule.getView();
            }

        } else {
            //使用传统接口
            view = BNRouteGuideManager.getInstance().onCreate(this,mOnNavigationListener);
        }


        if (view != null) {
            setContentView(view);
        }

        Intent intent = getIntent();
        if (intent != null) {
            Bundle bundle = intent.getExtras();
            if (bundle != null) {
                mBNRoutePlanNode = (BNRoutePlanNode) bundle.getSerializable(BaiduNaviOperation.ROUTE_PLAN_NODE);
            }
        }

        if (hd != null) {
            hd.sendEmptyMessageAtTime(MSG_SHOW, 5000);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if(useCommonInterface) {
            if(mBaiduNaviCommonModule != null) {
                mBaiduNaviCommonModule.onResume();
            }
        } else {
            BNRouteGuideManager.getInstance().onResume();
        }



    }

    protected void onPause() {
        super.onPause();

        if(useCommonInterface) {
            if(mBaiduNaviCommonModule != null) {
                mBaiduNaviCommonModule.onPause();
            }
        } else {
            BNRouteGuideManager.getInstance().onPause();
        }

    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(useCommonInterface) {
            if(mBaiduNaviCommonModule != null) {
                mBaiduNaviCommonModule.onDestroy();
            }
        } else {
            BNRouteGuideManager.getInstance().onDestroy();
        }
        BaiduNaviOperation.activityList.remove(this);

    }

    @Override
    protected void onStop() {
        super.onStop();
        if(useCommonInterface) {
            if(mBaiduNaviCommonModule != null) {
                mBaiduNaviCommonModule.onStop();
            }
        } else {
            BNRouteGuideManager.getInstance().onStop();
        }

    }

    @Override
    public void onBackPressed() {//返回键退出导航页
        if(useCommonInterface) {
            if(mBaiduNaviCommonModule != null) {
                mBaiduNaviCommonModule.onBackPressed(false);
            }
        } else {
            BNRouteGuideManager.getInstance().onBackPressed(false);
        }
    }

    public void onConfigurationChanged(android.content.res.Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if(useCommonInterface) {
            if(mBaiduNaviCommonModule != null) {
                mBaiduNaviCommonModule.onConfigurationChanged(newConfig);
            }
        } else {
            BNRouteGuideManager.getInstance().onConfigurationChanged(newConfig);
        }

    };


    @Override
    public boolean onKeyDown(int keyCode, android.view.KeyEvent event) {
        if(useCommonInterface) {
            if(mBaiduNaviCommonModule != null) {
                Bundle mBundle = new Bundle();
                mBundle.putInt(RouteGuideModuleConstants.KEY_TYPE_KEYCODE, keyCode);
                mBundle.putParcelable(RouteGuideModuleConstants.KEY_TYPE_EVENT, event);
                mBaiduNaviCommonModule.setModuleParams(RouteGuideModuleConstants.METHOD_TYPE_ON_KEY_DOWN, mBundle);
                try {
                    Boolean ret = (Boolean)mBundle.get(RET_COMMON_MODULE);
                    if(ret) {
                        return true;
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        } 
        return super.onKeyDown(keyCode, event);  
    }
    @Override
    protected void onStart() {
        super.onStart();
        // TODO Auto-generated method stub
        if(useCommonInterface) {
            if(mBaiduNaviCommonModule != null) {
                mBaiduNaviCommonModule.onStart();
            }
        } else {
            BNRouteGuideManager.getInstance().onStart();
        }
    }
    //设置自定义图层
    private void addCustomizedLayerItems() {
        List<CustomizedLayerItem> items = new ArrayList<CustomizedLayerItem>();
        CustomizedLayerItem item1 = null;
        if (mBNRoutePlanNode != null) {
            item1 = new CustomizedLayerItem(mBNRoutePlanNode.getLongitude(), mBNRoutePlanNode.getLatitude(),
                    mBNRoutePlanNode.getCoordinateType(), getResources().getDrawable(R.drawable.ic_launcher),
                    CustomizedLayerItem.ALIGN_CENTER);
            items.add(item1);

            BNRouteGuideManager.getInstance().setCustomizedLayerItems(items);
        }
        BNRouteGuideManager.getInstance().showCustomizedLayer(true);
    }

    private static final int MSG_SHOW = 1;
    private static final int MSG_HIDE = 2;
    private static final int MSG_RESET_NODE = 3;
    private Handler hd = null;

    private void createHandler() {
        if (hd == null) {
            hd = new Handler(getMainLooper()) {
                public void handleMessage(android.os.Message msg) {
                    if (msg.what == MSG_SHOW) {//显示自定义图层
                        addCustomizedLayerItems();
                    } else if (msg.what == MSG_HIDE) {//隐藏自定义图层
                        BNRouteGuideManager.getInstance().showCustomizedLayer(false);
                    } else if (msg.what == MSG_RESET_NODE) {//重置终点
                        BNRouteGuideManager.getInstance().resetEndNodeInNavi(
                                new BNRoutePlanNode(116.21142, 40.85087, "  ", null, CoordinateType.GCJ02));//这坐标根据自身情况设置
                    }
                };
            };
        }
    }

    private OnNavigationListener mOnNavigationListener = new OnNavigationListener() {

        @Override
        public void onNaviGuideEnd() {

            finish();
        }

        @Override
        public void notifyOtherAction(int actionType, int arg1, int arg2, Object obj) {

            if (actionType == 0) {


            }

            Log.i(TAG, "actionType:" + actionType + "arg1:" + arg1 + "arg2:" + arg2 + "obj:" + obj.toString());
        }

    };

    private final static String RET_COMMON_MODULE = "module.ret";

    private interface RouteGuideModuleConstants {
        final static int METHOD_TYPE_ON_KEY_DOWN = 0x01;
        final static String KEY_TYPE_KEYCODE = "keyCode";
        final static String KEY_TYPE_EVENT = "event";
    }
}

这一页没什么解释的,有什么疑问留言吧

源码地址:http://download.csdn.net/download/qq_23931287/9948307

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值