編輯:關於Android編程
Android studio 百度地圖開發(3)地圖導航
email:[email protected]
開發環境:win7 64位,Android Studio,請注意是Android Studio,使用的導航SDK版本:3.1.0。
因為在寫定位功能時自己想從頭到尾地寫,但最後完全是參考了百度官網上的Demo才弄出來,後來發現用Android Studio做導航的資料太少了,於是這次寫導航功能的時候就直接參考了百度Demo。但是問題依舊,開始使用了百度的RoutePlanDemo.java這個Demo,發現有幾個包找不到,搗騰了很久沒有成功,最後甚至准備用Myclipse試試,結果配置環境的時候還把MyEclipse玩壞了,重裝!實在懷疑自己解決問題的能力,百般無奈之下,還是回到了Android Studio,靜下心來分析問題出在了哪裡:是不是本身SDK3.1.0裡就沒有這幾個包了呢?果然,我打開jar包一看,沒有。欣喜,換了導航SDK3.1.0中的Demo+SDK3.1.0,於是,導航就真正開始了。下面的代碼都來自百度Demo,我只是自己理解了一番,後面將結合第二部分的地圖定位和這部分的導航功能,自己再寫一個可以實現手動選擇起點和終點的Demo出來,喜歡吐槽的朋友請鍵盤留情,然後悄悄飄過吧。
一直以來都是喜歡百度的,盡管百度的的確確不能和Google比。但是,在中國的科技氛圍裡,我覺得百度已經夠好了,所以也貼一點百度地圖導航SDK的功能介紹。
最後,我想問問那些嘴裡罵著百度心裡又離不開百度的朋友:你為中國的科技、IT、社會做了什麼?
二.導航SDK的應用
請注意:代碼來自百度官方Demo。
導航SDK版本:BaiDuNaviSDK_3.1.0.jar和httpmime-4.1.2.jar
IDE:Android Studio
第一步:工程配置
這部分看似簡單,沒有關於Android Studio版的官方教程,真的很麻煩。
(1)將BaiDuNaviSDK_3.1.0.jar和httpmime-4.1.2.jar復制到/libs文件夾下;
(2)方法一:右鍵這兩個jar包:add as library->確定;
方法二:打開build.gradle,在dependencies中增加:
compile files('libs/httpmime-4.1.2.jar') compile files('libs/BaiduNaviSDK_3.1.0.jar')
(4)在src/main/JNIlibs/armeabi-v7a中【不是armeabi】都添加:libapp_BaiduNaviApplib.so、libapp_BaiduVIlib.so、libcurl.so、libgnustl_shared.so、 libbds.so、 libbd_etts.so 、libBDSpeechDecoder_V1.so
第二步:AndroidManifest.xml:增加權限、注冊activity、API_KEY和定位服務
package intvehapp.intvehapp; import java.io.File; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import com.baidu.navisdk.adapter.BNOuterLogUtil; import com.baidu.navisdk.adapter.BNOuterTTSPlayerCallback; import com.baidu.navisdk.adapter.BNRoutePlanNode; import com.baidu.navisdk.adapter.BNRoutePlanNode.CoordinateType; import com.baidu.navisdk.adapter.BNaviSettingManager; import com.baidu.navisdk.adapter.BaiduNaviManager; import com.baidu.navisdk.adapter.BaiduNaviManager.NaviInitListener; import com.baidu.navisdk.adapter.BaiduNaviManager.RoutePlanListener; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class BNDemoMainActivity extends Activity { public static List activityList = new LinkedList(); /** * App在SD卡中的目錄名 */ private static final String APP_FOLDER_NAME = "intvehapp"; /** * 4個按鈕控件 */ private Button mWgsNaviBtn = null; private Button mGcjNaviBtn = null; private Button mBdmcNaviBtn = null; private Button mDb06ll = null; /** * SD卡的路徑 */ private String mSDCardPath = null; public static final String ROUTE_PLAN_NODE = "routePlanNode"; public static final String SHOW_CUSTOM_ITEM = "showCustomItem"; public static final String RESET_END_NODE = "resetEndNode"; public static final String VOID_MODE = "voidMode"; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); activityList.add(this); setContentView(R.layout.activity_main_guide); /** * 獲取按鈕控件 */ mWgsNaviBtn = (Button) findViewById(R.id.wgsNaviBtn); mGcjNaviBtn = (Button) findViewById(R.id.gcjNaviBtn); mBdmcNaviBtn = (Button) findViewById(R.id.bdmcNaviBtn); mDb06ll = (Button) findViewById(R.id.mDb06llNaviBtn); BNOuterLogUtil.setLogSwitcher(true); /** * 初始化按鈕監聽函數 */ initListener(); if (initDirs()) { /** * 使用SDK前,先進行百度服務授權和引擎初始化。 */ initNavi(); } // BNOuterLogUtil.setLogSwitcher(true); } @Override protected void onResume() { super.onResume(); } /** * 為每一個按鈕控件增加點擊監聽事件,增加算路節點 */ private void initListener() { if (mWgsNaviBtn != null) { mWgsNaviBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { /** * 判斷百度導航是否初始化 */ if (BaiduNaviManager.isNaviInited()) { /** * 添加起點、終點 */ routeplanToNavi(CoordinateType.WGS84); } } }); } if (mGcjNaviBtn != null) { mGcjNaviBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if (BaiduNaviManager.isNaviInited()) { routeplanToNavi(CoordinateType.GCJ02); } } }); } if (mBdmcNaviBtn != null) { mBdmcNaviBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if (BaiduNaviManager.isNaviInited()) { routeplanToNavi(CoordinateType.BD09_MC); } } }); } if (mDb06ll != null) { mDb06ll.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if (BaiduNaviManager.isNaviInited()) { routeplanToNavi(CoordinateType.BD09LL); } } }); } } /** * 初始化SD卡,在SD卡路徑下新建文件夾:App目錄名,文件中包含了很多東西,比如log、cache等等 * @return */ private boolean initDirs() { mSDCardPath = getSdcardDir(); if (mSDCardPath == null) { return false; } File f = new File(mSDCardPath, APP_FOLDER_NAME); if (!f.exists()) { try { f.mkdir(); } catch (Exception e) { e.printStackTrace(); return false; } } return true; } String authinfo = null; /** * 內部TTS播報狀態回傳handler */ 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; } } }; /** * 內部TTS播報狀態回調接口 */ 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"); } }; public void showToastMsg(final String msg) { BNDemoMainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(BNDemoMainActivity.this, msg, Toast.LENGTH_SHORT).show(); } }); } /** * 使用SDK前,先進行百度服務授權和引擎初始化 */ private void initNavi() { BNOuterTTSPlayerCallback ttsCallback = null; BaiduNaviManager.getInstance().init(this, mSDCardPath, APP_FOLDER_NAME, new NaviInitListener() { @Override public void onAuthResult(int status, String msg) { if (0 == status) { authinfo = "key校驗成功!"; } else { authinfo = "key校驗失敗, " + msg; } BNDemoMainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(BNDemoMainActivity.this, authinfo, Toast.LENGTH_LONG).show(); } }); } public void initSuccess() { Toast.makeText(BNDemoMainActivity.this, "百度導航引擎初始化成功", Toast.LENGTH_SHORT).show(); initSetting(); } public void initStart() { Toast.makeText(BNDemoMainActivity.this, "百度導航引擎初始化開始", Toast.LENGTH_SHORT).show(); } public void initFailed() { Toast.makeText(BNDemoMainActivity.this, "百度導航引擎初始化失敗", Toast.LENGTH_SHORT).show(); } }, null, ttsHandler, null); } private String getSdcardDir() { if (Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED)) { return Environment.getExternalStorageDirectory().toString(); } return null; } /** * 算路設置起、終點,算路偏好,是否模擬導航等參數,然後在回調函數中設置跳轉至誘導。 * @param coType */ private void routeplanToNavi(CoordinateType coType) { BNRoutePlanNode sNode = null; BNRoutePlanNode eNode = null; switch (coType) { case GCJ02: { sNode = new BNRoutePlanNode(116.30142, 40.05087, "百度大廈", null, coType); eNode = new BNRoutePlanNode(116.39750, 39.90882, "北京天安門", null, coType); break; } case WGS84: { sNode = new BNRoutePlanNode(116.300821, 40.050969, "百度大廈", null, coType); eNode = new BNRoutePlanNode(116.397491, 39.908749, "北京天安門", null, coType); break; } case BD09_MC: { sNode = new BNRoutePlanNode(12947471, 4846474, "百度大廈", null, coType); eNode = new BNRoutePlanNode(12958160, 4825947, "北京天安門", null, coType); break; } case BD09LL: { sNode = new BNRoutePlanNode(116.30784537597782, 40.057009624099436, "百度大廈", null, coType); eNode = new BNRoutePlanNode(116.40386525193937, 39.915160800132085, "北京天安門", null, coType); break; } default: ; } if (sNode != null && eNode != null) { Listlist = new ArrayList (); list.add(sNode); list.add(eNode); /** * 發起算路操作並在算路成功後通過回調監聽器進入導航過程,返回是否執行成功 */ BaiduNaviManager .getInstance() .launchNavigator( this, //建議是應用的主Activity list, //傳入的算路節點,順序是起點、途經點、終點,其中途經點最多三個 1, //算路偏好 1:推薦 8:少收費 2:高速優先 4:少走高速 16:躲避擁堵 true, //true表示真實GPS導航,false表示模擬導航 new DemoRoutePlanListener(sNode)//開始導航回調監聽器,在該監聽器裡一般是進入導航過程頁面 ); } } /** * 導航回調監聽器 */ public class DemoRoutePlanListener implements RoutePlanListener { private BNRoutePlanNode mBNRoutePlanNode = null; public DemoRoutePlanListener(BNRoutePlanNode node) { mBNRoutePlanNode = node; } @Override public void onJumpToNavigator() { /* * 設置途徑點以及resetEndNode會回調該接口 */ for (Activity ac : activityList) { if (ac.getClass().getName().endsWith("BNDemoGuideActivity")) { return; } } /** * 導航activity */ Intent intent = new Intent(BNDemoMainActivity.this, BNDemoGuideActivity.class); Bundle bundle = new Bundle(); bundle.putSerializable(ROUTE_PLAN_NODE, (BNRoutePlanNode) mBNRoutePlanNode); intent.putExtras(bundle); startActivity(intent); } @Override public void onRoutePlanFailed() { // TODO Auto-generated method stub Toast.makeText(BNDemoMainActivity.this, "算路失敗", Toast.LENGTH_SHORT).show(); } } /** * 導航設置管理器 */ private void initSetting(){ /** * 日夜模式 1:自動模式 2:白天模式 3:夜間模式 */ BNaviSettingManager.setDayNightMode(BNaviSettingManager.DayNightMode.DAY_NIGHT_MODE_DAY); /** * 設置全程路況顯示 */ BNaviSettingManager.setShowTotalRoadConditionBar(BNaviSettingManager.PreViewRoadCondition.ROAD_CONDITION_BAR_SHOW_ON); /** * 設置語音播報模式 */ BNaviSettingManager.setVoiceMode(BNaviSettingManager.VoiceMode.Veteran); /** * 設置省電模式 */ BNaviSettingManager.setPowerSaveMode(BNaviSettingManager.PowerSaveMode.DISABLE_MODE); /** * 設置實時路況條 */ BNaviSettingManager.setRealRoadCondition(BNaviSettingManager.RealRoadCondition.NAVI_ITS_ON); } private BNOuterTTSPlayerCallback mTTSCallback = new BNOuterTTSPlayerCallback() { @Override public void stopTTS() { // TODO Auto-generated method stub Log.e("test_TTS", "stopTTS"); } @Override public void resumeTTS() { // TODO Auto-generated method stub Log.e("test_TTS", "resumeTTS"); } @Override public void releaseTTSPlayer() { // TODO Auto-generated method stub Log.e("test_TTS", "releaseTTSPlayer"); } @Override public int playTTSText(String speech, int bPreempt) { // TODO Auto-generated method stub Log.e("test_TTS", "playTTSText" + "_" + speech + "_" + bPreempt); return 1; } @Override public void phoneHangUp() { // TODO Auto-generated method stub Log.e("test_TTS", "phoneHangUp"); } @Override public void phoneCalling() { // TODO Auto-generated method stub Log.e("test_TTS", "phoneCalling"); } @Override public void pauseTTS() { // TODO Auto-generated method stub Log.e("test_TTS", "pauseTTS"); } @Override public void initTTSPlayer() { // TODO Auto-generated method stub Log.e("test_TTS", "initTTSPlayer"); } @Override public int getTTSState() { // TODO Auto-generated method stub Log.e("test_TTS", "getTTSState"); return 1; } }; }
package intvehapp.intvehapp; 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; /** * 誘導界面 * * @author sunhao04 * */ public class BNDemoGuideActivity extends Activity { private final String TAG = BNDemoGuideActivity.class.getName(); private BNRoutePlanNode mBNRoutePlanNode = null; private BaiduNaviCommonModule mBaiduNaviCommonModule = null; /* * 對於導航模塊有兩種方式來實現發起導航。 1:使用通用接口來實現 2:使用傳統接口來實現 */ // 是否使用通用接口 private boolean useCommonInterface = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); BNDemoMainActivity.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(BNDemoMainActivity.ROUTE_PLAN_NODE); } } } @Override protected void onResume() { super.onResume(); if(useCommonInterface) { if(mBaiduNaviCommonModule != null) { mBaiduNaviCommonModule.onResume(); } } else { BNRouteGuideManager.getInstance().onResume(); } if (hd != null) { hd.sendEmptyMessageAtTime(MSG_SHOW, 2000); } } 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(); } BNDemoMainActivity.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); } }; private void addCustomizedLayerItems() { Listitems = new ArrayList (); 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, "百度大廈11", 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, "notifyOtherAction actionType = " + actionType + ",導航到達目的地!"); } Log.i(TAG, "actionType:" + actionType + "arg1:" + arg1 + "arg2:" + arg2 + "obj:" + obj.toString()); } }; }
三.個人理解
目前Run起來後還有點問題,比如還沒發現語音播報這個可不可以。
單從這個Demo來看,導航功能實現起來並不會復雜,百度服務授權和引擎初始化成功後,主要是傳入起點、終點、途經點等需要計算的節點,然後在回調函數中進入導航回調監聽器,然後進入誘導界面。後面還有很多地方可以個性化修改或者按照自己的需要進行功能完善,這便是後面我需要做的工作了。
可能第一次用Android Studio做百度地圖真的會遇到不少問題,比如SDK版本和.so文件(需要添加到armeabi-v7a文件夾中而不是armeabi中)總之,不管多難,不要輕易放棄,問題始終是可以解決的。
秒拍視頻因為有很多明星的自拍視頻,以及其他各種視頻還是非常火爆的,眾多明星、美女都在玩的最新潮短視頻分享應用,全新的炫酷MV主題、清新文藝范的濾
本文實例為大家分享了Android實現畫板的具體代碼,采用的技術是雙緩沖技術,供大家參考,具體內容如下1.雙緩沖技術的概念所謂的雙緩沖技術其實很簡單,當程序需要在指定的V
一.通知(Notification)的相關概念Notification是一種具有全局效果的通知,它展示在屏幕的頂端,首先會表現為一個圖標的形式,當用戶向下滑動的時候,展示
在上一篇《Android仿微信滑動彈出編輯、刪除菜單效果、增加下拉刷新功能》裡,已經帶著大家學習如何使用SwipeMenuListView這一開源庫實現滑動列表彈出菜單,