Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發基於百度地圖的乘車助手

Android開發基於百度地圖的乘車助手

編輯:關於Android編程

寫在前面:出去玩免不了擠公交、等地鐵,不知道乘車方案當然不行,用官方APP吧,缺點一大堆,手機浏覽器在線查的話既慢又麻煩...為了解決這些問題,我們來做一個簡版的出行助手,嘛嘛再也不用擔心我會迷路了_\^o^/_   (一)功能需求分析   [基礎功能]   1.能夠根據起點站和終點站查詢乘車方案,並顯示多種乘車方案   2.能夠根據公交路線號查詢沿途站點(防止坐過站...)   [擴展功能]   3.GPS定位獲取起點站(距離當前位置最近的站點名)[後來放棄了,費電,費流量...]   4.顯示地圖[後來也放棄了,地圖對用戶來說好像沒什麼太大用處(當然喜歡走路的另當別論),至少對本人來說地圖沒什麼用]   (二)可實現性分析   1.百度地圖開放平台提供的API可以實現乘車方案查詢   2.3.4.同上,結論:完全可以實現需要的所有功能   (三)開發前提   1.需要BaiDuMap的開發者賬號   2.需要key(現在新版的地圖key與App唯一綁定)   3.需要官方提供的jar包   搜索一下“百度地圖開發”,上面的三件事情分分鐘搞定   [說到這裡不得不贊一下這極低的門檻了,騰訊、新浪微博...的開發者賬號就很難認證,有的甚至需要上傳身份證復印件...]   (四)研究API文檔以及Demo   API文檔說實話做得不怎麼樣,函數詳解都只有一句話,建議直接看Demo,附有大量注釋,簡單易懂   (五)開始編碼(下面給出的源碼都親測可用,並附有最詳細的注釋)     package com.ayqy.app_gowithme;   import java.util.ArrayList;   import android.app.Activity; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.text.InputType; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast;   import com.baidu.mapapi.BMapManager; import com.baidu.mapapi.search.MKAddrInfo; import com.baidu.mapapi.search.MKBusLineResult; import com.baidu.mapapi.search.MKDrivingRouteResult; import com.baidu.mapapi.search.MKLine; import com.baidu.mapapi.search.MKPlanNode; import com.baidu.mapapi.search.MKPoiInfo; import com.baidu.mapapi.search.MKPoiResult; import com.baidu.mapapi.search.MKRoute; import com.baidu.mapapi.search.MKSearch; import com.baidu.mapapi.search.MKSearchListener; import com.baidu.mapapi.search.MKShareUrlResult; import com.baidu.mapapi.search.MKSuggestionResult; import com.baidu.mapapi.search.MKTransitRoutePlan; import com.baidu.mapapi.search.MKTransitRouteResult; import com.baidu.mapapi.search.MKWalkingRouteResult;   public class SearchPlan extends Activity{       BMapManager mBMapMan = null;       ListView list;     private MKSearch mSearch = null; // 搜索模塊,也可去掉地圖模塊獨立使用     private String city;//城市     private String start;//起點     private String end;//終點     EditText txtCity;     EditText txtStart;     EditText txtEnd;     Button btnSearch;       ArrayList<String> plans;//方案列表     ArrayList<String> details;//詳細方案       @Override     protected void onCreate(Bundle savedInstanceState) {         // TODO Auto-generated method stub         super.onCreate(savedInstanceState);         //獲取SDK使用權限         mBMapMan=new BMapManager(getApplication());         mBMapMan.init("MzKbxcvX7gBEqpeW2kdmOqhx", null);         //注意:上面方法的第一個參數必須要填自己申請的key         //因為App的PackageName--Shell值--key都唯一對應         //用別人的key肯定會出現授權失敗的錯誤,結果就是什麼API都別想用           this.setContentView(R.layout.query);           //關聯控件         list = (ListView) findViewById(R.id.List);         txtCity = (EditText) findViewById(R.id.txtCity);         txtStart = (EditText) findViewById(R.id.txtStart);         txtEnd = (EditText) findViewById(R.id.txtEnd);         btnSearch = (Button) findViewById(R.id.btnSearch);         //設置按鈕半透明         btnSearch.getBackground().setAlpha(204);         //         txtStart.setText("小居安");         //           btnSearch.setOnClickListener(new OnClickListener() {               @Override             public void onClick(View v) {                 //搜索乘車方案                 //判空                 start = txtStart.getText().toString().trim();                 end = txtEnd.getText().toString().trim();                 city = txtCity.getText().toString().trim();                 if("".equals(start) || "".equals(end) || "".equals(city))                 {                     Toast.makeText(SearchPlan.this, "...到底想去哪裡", Toast.LENGTH_SHORT).show();                     return;                 }                 else                 {                     //搜索方案                     searchPlans();                 }             }         });           // 初始化搜索模塊,注冊事件監聽           mSearch = new MKSearch();         mSearch.init(mBMapMan, new MKSearchListener() {               @Override              public void onGetPoiDetailSearchResult(int type, int error) {               }                 public void onGetDrivingRouteResult(MKDrivingRouteResult res,                       int error) {               }                 public void onGetTransitRouteResult(MKTransitRouteResult res,                       int error) {                   if (error != 0 || res == null) {                     showError(error);                     return;                 }                                   // 得到解決方案                  int maxPlanNum = res.getNumPlan();//方案數                 //顯示方案列表                 plans = new ArrayList<String>();                 details = new ArrayList<String>();                 for(int i = 0;i < maxPlanNum;i++)                 {                     //得到詳細方案                     MKTransitRoutePlan routePlan = res.getPlan(i);                     //獲取時耗                     int time = routePlan.getTime() / 60;                     int hour = time / 60;                     int min = time % 60;                     // 公交線路                     MKLine mkLine = routePlan.getLine(0);                     //記錄方案詳細信息                     StringBuilder sb = new StringBuilder();                     sb.append("[預計耗時:");                     if(hour > 0)sb.append(hour + " 小時 ");                     sb.append(min);                     sb.append("分鐘]\n\n乘坐:");                     sb.append(mkLine.getTitle());                       MKPoiInfo mkOnPoiInfo = mkLine.getGetOnStop();                       MKPoiInfo mkOffPoiInfo = mkLine.getGetOffStop();                       sb.append("\n從");                     sb.append(mkOnPoiInfo.name);                     sb.append("上車,在");                       sb.append(mkOffPoiInfo.name);                     sb.append("下車\n[途經 ");                     sb.append(mkLine.getNumViaStops());                     sb.append(" 站]");                     if (routePlan.getNumLines() > 0) {                         // 循環當前方案公交路線                         for (int j = 1; j < routePlan.getNumLines(); j++) {                               // 公交線路                             mkLine = routePlan.getLine(j);                               sb.append("\n換乘:");                             sb.append(mkLine.getTitle());                             mkOnPoiInfo = mkLine.getGetOnStop();                               mkOffPoiInfo = mkLine.getGetOffStop();                               sb.append("\n從");                             sb.append(mkOnPoiInfo.name);                             sb.append("上車,在");                               sb.append(mkOffPoiInfo.name);                             sb.append("下車\n[途經 ");                             sb.append(mkLine.getNumViaStops());                             sb.append(" 站]");                         }                       }                     //填充詳細方案列表                     details.add(sb.toString());                       //填充方案列表                     plans.add("方案 " + (i + 1));                 }                 //顯示方案列表                 showPlans();             }                 public void onGetWalkingRouteResult(MKWalkingRouteResult res,                       int error) {               }                 public void onGetAddrResult(MKAddrInfo res, int error) {               }                 //線路查詢相關             public void onGetPoiResult(MKPoiResult res, int type, int error) {                   // 錯誤號可參考MKEvent中的定義                 if (error != 0 || res == null) {                     showError(error);                     return;                 }                 // 找到公交路線poi node                 MKPoiInfo curPoi = null;                 int totalPoiNum = res.getNumPois();                 for (int idx = 0; idx < totalPoiNum; idx++) {                     curPoi = res.getPoi(idx);                     // ePoiType-->poi類型,0:普通點,1:公交站,2:公交線路,3:地鐵站,4:地鐵線路                     if (2 == curPoi.ePoiType) {                         break;                     }                 }                 mSearch.busLineSearch(curPoi.name, curPoi.uid);             }                 //線路查詢相關             public void onGetBusDetailResult(MKBusLineResult result, int error) {                   if (error != 0 || result == null) {                     showError(error);                     return;                 }                 //獲取詳細路線                 MKRoute route = result.getBusRoute();                 int num = route.getNumSteps();//關鍵點數量                 //循環獲取關鍵點描述                 String[] arrInfo = new String[num + 1];                 for(int i = 0;i < num;i++)                     arrInfo[i + 1] = route.getStep(i).getContent();                 //獲取運營時間信息                 String busName = result.getBusName();                 String startTime = result.getStartTime();                 String endTime = result.getEndTime();                 arrInfo[0] = busName + "\n首班:" + startTime + "\n末班:" + endTime;                   //將數據裝入Bundle                 Bundle data = new Bundle();                 data.putStringArray("routeInfo", arrInfo);                 //新建Intent                 Intent intent = new Intent(SearchPlan.this,ShowRoute.class);                 intent.putExtras(data);                 //啟動對應Activity                 startActivity(intent);             }                 @Override              public void onGetSuggestionResult(MKSuggestionResult res, int arg1) {                   // TODO Auto-generated method stub               }               @Override             public void onGetShareUrlResult(MKShareUrlResult arg0, int arg1,                     int arg2) {                 // TODO Auto-generated method stub             }         });     }       @Override     public boolean onCreateOptionsMenu(Menu menu) {         // Inflate the menu; this adds items to the action bar if it is present.         getMenuInflater().inflate(R.menu.main, menu);         return true;     }       @Override     public boolean onOptionsItemSelected(android.view.MenuItem item){         if(item.getItemId() == R.id.searchRoute)         {//顯示線路查詢對話框             //創建Builder對象             Builder builder = new Builder(SearchPlan.this);             builder.setTitle("查詢線路詳情");             builder.setIcon(R.drawable.search);             //設置對話框內容             LinearLayout view = new LinearLayout(SearchPlan.this);             view.setOrientation(LinearLayout.HORIZONTAL);             TextView lbl1 = new TextView(SearchPlan.this);             lbl1.setText("查詢");             lbl1.setTextSize(18);             final EditText txtCity = new EditText(SearchPlan.this);             txtCity.setHint("城市名");             txtCity.setText("西安");             TextView lbl2 = new TextView(SearchPlan.this);             lbl2.setText("公交");             lbl2.setTextSize(18);             final EditText txtBus = new EditText(SearchPlan.this);             txtBus.setInputType(InputType.TYPE_CLASS_NUMBER);//限輸入數字             txtBus.setSingleLine();//單行             txtBus.setHint("線路名");             TextView lbl3 = new TextView(SearchPlan.this);             lbl3.setText("路");             lbl3.setTextSize(18);             view.addView(lbl1);             view.addView(txtCity);             view.addView(lbl2);             view.addView(txtBus);             view.addView(lbl3);             builder.setView(view);             //添加按鈕             builder.setPositiveButton("查詢", new DialogInterface.OnClickListener() {                   @Override                 public void onClick(DialogInterface dialog, int which) {                     //查詢路線信息                     //判空                     String city = txtCity.getText().toString().trim();                     String bus = txtBus.getText().toString().trim();                     if("".equals(city) || "".equals(bus))                     {                         Toast.makeText(SearchPlan.this, "...到底想查詢什麼", Toast.LENGTH_SHORT).show();                         return;                     }                                           //顯示提示信息                     showTip();                     //POI搜索                     mSearch.poiSearchInCity(city, bus);                 }             });             builder.setNegativeButton("取消", null);             //顯示對話框             builder.create().show();         }           if(item.getItemId() == R.id.exit)             finish();//退出程序           return true;     };       //自定義方法     private void searchPlans()     {//搜索乘車方案           //對起點終點的name進行賦值,也可以直接對坐標賦值,賦值坐標則將根據坐標進行搜索           MKPlanNode stNode = new MKPlanNode();         stNode.name = start;         MKPlanNode enNode = new MKPlanNode();         enNode.name = end;           //顯示提示信息         showTip();         //搜索         mSearch.transitSearch(city, stNode, enNode);     }       private void showPlans()     {         //為ListView綁定Adapter         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this                 , android.R.layout.simple_list_item_multiple_choice                 , plans);         list.setAdapter(adapter);         list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);           //為ListView添加ItemClick事件監聽         list.setOnItemClickListener(new OnItemClickListener() {               @Override             public void onItemClick(AdapterView<?> arg0, View arg1, int index,                     long arg3) {                 //跳轉到ListActivity,同時傳遞索引參數                   //創建Intent                 Intent intent = new Intent(SearchPlan.this                         ,ShowDetail.class);                 //創建Bundle攜帶數據                 Bundle bundle = new Bundle();                 bundle.putInt("index", index);                 bundle.putString("detail", details.get(index));                 //數據綁定                 intent.putExtras(bundle);                 //啟動Intent對應的Activity                 startActivity(intent);             }         });     }       private void showError(int error)     {         String msg = null;         switch(error)         {         case 2:msg="T_T網絡連接錯誤...";break;         case 3:msg="T_T網絡數據錯誤...";break;         case 4:msg="T_T路線搜索起點或終點有歧義...";break;         case 100:msg="T_T未找到搜索結果...";break;         case 300:msg="T_T授權驗證失敗...";break;         default:msg="T_T未知錯誤...";         }         Toast.makeText(SearchPlan.this, msg,                 Toast.LENGTH_LONG).show();     }       private void showTip()     {//顯示提示信息         Toast.makeText(SearchPlan.this                 , "(*>.<*)正在拼命搜索..."                 , Toast.LENGTH_LONG).show();     }       //重寫baiduMap中的方法     @Override     protected void onDestroy() {         mSearch.destory();           if(mBMapMan!=null){             mBMapMan.destroy();             mBMapMan=null;         }           super.onDestroy();     }       @Override      protected void onPause(){         if(mBMapMan!=null){               mBMapMan.stop();           }           super.onPause();     }       @Override      protected void onResume(){           if(mBMapMan!=null){             mBMapMan.start();           }           super.onResume();       }   } [  package com.ayqy.app_gowithme;   import android.app.ListActivity; import android.content.Intent; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.ListView;   public class ShowDetail extends ListActivity{           ListView root;           @Override     protected void onCreate(Bundle savedInstanceState) {         // TODO Auto-generated method stub         super.onCreate(savedInstanceState);                   //設置背景         root = getListView();         root.setBackgroundResource(R.drawable.blue_bg);                   //獲取數據         Intent intent= getIntent();         Bundle bundle = intent.getExtras();         int index = bundle.getInt("index") + 1;         String detail = bundle.getString("detail");                   //設置Adapter         String[] arr = new String[]{"方案 " + index + " 詳情:", detail};         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this                 , android.R.layout.simple_list_item_1                 , arr);         this.setListAdapter(adapter);     } }   package com.ayqy.app_gowithme;   import android.app.ListActivity; import android.content.Intent; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.ListView;   public class ShowRoute extends ListActivity{       ListView root;       @Override     protected void onCreate(Bundle savedInstanceState) {         // TODO Auto-generated method stub         super.onCreate(savedInstanceState);           //設置背景         root = getListView();         root.setBackgroundResource(R.drawable.blue_bg);           //獲取數據         Intent intent= getIntent();         Bundle bundle = intent.getExtras();         String[] arrInfo = bundle.getStringArray("routeInfo");           //設置Adapter         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this                 , android.R.layout.simple_list_item_1                 , arrInfo);         this.setListAdapter(adapter);     } }   <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:gravity="bottom"     android:background="@drawable/blue_bg"     android:orientation="vertical" >           <LinearLayout          android:layout_width="match_parent"         android:layout_height="wrap_content"         android:orientation="horizontal"         >                   <TextView             android:text="@string/city"             android:textSize="24sp"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             />                   <EditText              android:id="@+id/txtCity"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:hint="@string/cityHint"             android:text="@string/XiAn"             android:singleLine="true"             />                   </LinearLayout>                   <LinearLayout          android:layout_width="match_parent"         android:layout_height="wrap_content"         android:orientation="horizontal"         >                   <TextView             android:text="@string/start"             android:textSize="24sp"             android:layout_width="wrap_content"             android:layout_height="wrap_content"             />                   <EditText              android:id="@+id/txtStart"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:hint="@string/stationHint"             android:singleLine="true"             />               </LinearLayout>           <LinearLayout          android:layout_width="match_parent"         android:layout_height="wrap_content"         android:orientation="horizontal"         >                   <TextView             android:text="@string/end"             android:textSize="24sp"             android:layout_width="wrap_content"             android:layout_height="wrap_content"              />                   <EditText              android:id="@+id/txtEnd"             android:layout_width="match_parent"             android:layout_height="wrap_content"             android:hint="@string/stationHint"             android:singleLine="true"             />               </LinearLayout>           <Button          android:id="@+id/btnSearch"         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:textSize="18sp"         android:text="@string/searchPlan"         />           <ListView android:id="@+id/List"         android:layout_width="match_parent"         android:layout_height="wrap_content"         >               </ListView>   </LinearLayout> P.S.源碼都在上面,如有疑問請在下方留言   (六)顯示地圖   [最先實現的就是這個(第一次開發地圖有點激動,想看看地圖長什麼樣子...),在需求中本沒打算設計,雖然後來放棄了,但下面的源碼仍然親測無誤]     package com.ayqy.app_gowithme;   import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import android.view.Menu; import android.widget.TextView; import android.widget.Toast;   import com.baidu.mapapi.BMapManager; import com.baidu.mapapi.map.MKMapViewListener; import com.baidu.mapapi.map.MapController; import com.baidu.mapapi.map.MapPoi; import com.baidu.mapapi.map.MapView; import com.baidu.platform.comapi.basestruct.GeoPoint;   public class ShowMap extends Activity {       BMapManager mBMapMan = null;     MapView mMapView = null;     MapController mMapController = null;       TextView txt;     boolean pressAgain = false;     long pressTime = 0;       @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);           mBMapMan=new BMapManager(getApplication());         mBMapMan.init("MzKbxcvX7gBEqpeW2kdmOqhx", null);         //注意:請在試用setContentView前初始化BMapManager對象,否則會報錯           setContentView(R.layout.activity_main);         mMapView=(MapView)findViewById(R.id.bmapsView);         mMapController=mMapView.getController();           //txt = (TextView) findViewById(R.id.txt);           // 得到mMapView的控制權,可以用它控制和驅動平移和縮放         GeoPoint point =new GeoPoint((int)(34.151884* 1E6),(int)(108.882024* 1E6));         //34.151884,108.882024西北大學16級別         //用給定的經緯度構造一個GeoPoint,單位是微度 (度 * 1E6)         mMapController.enableClick(true);//設置地圖響應點擊事件         mMapController.setCenter(point);//設置地圖中心點         mMapController.setZoom(16);//設置地圖zoom級別          mMapView.setBuiltInZoomControls(false);//不顯示內置縮放控件           //創建MKMapViewListener         MKMapViewListener listener = new MKMapViewListener() {               @Override             public void onMapMoveFinish() {                 // TODO Auto-generated method stub               }               @Override             public void onMapLoadFinish() {             }               @Override             public void onMapAnimationFinish() {                 // TODO Auto-generated method stub               }               @Override             public void onGetCurrentMap(Bitmap arg0) {                 // TODO Auto-generated method stub               }               @Override             public void onClickMapPoi(MapPoi arg0) {                 //點到地圖標注時顯示詳細                 if(arg0 != null)                 {                     GeoPoint point = arg0.geoPt;//獲取GEO坐標                     mMapController.setCenter(point);//設置地圖中心點                     mMapController.zoomIn();//放大一個級別                 }             }         };         //為map注冊監聽器         mMapView.regMapViewListener(mBMapMan, listener);     }       @Override public void onBackPressed() {         //按下返回鍵,縮小地圖         float min = 12f;//設置最小縮放級別         if(mMapView.getZoomLevel() > min)             mMapController.zoomOut();//縮小一個級別         else         {             if(pressAgain && (System.currentTimeMillis() - pressTime < 1000))                 super.finish();//一秒內再按結束程序             else                 pressAgain = false;             if(!pressAgain)             {                 Toast.makeText(ShowMap.this, "再按一次退出...", Toast.LENGTH_SHORT).show();                 pressTime = System.currentTimeMillis();//獲取第一次按下的時間                 pressAgain = true;             }         }     };       @Override     public boolean onCreateOptionsMenu(Menu menu) {         // Inflate the menu; this adds items to the action bar if it is present.         getMenuInflater().inflate(R.menu.main, menu);         return true;     }       @Override     public boolean onOptionsItemSelected(android.view.MenuItem item){         if(item.getItemId() == R.id.exit)             finish();//退出程序           return true;     };           //重寫baiduMap中的方法     @Override     protected void onDestroy() {         mMapView.destroy();         if(mBMapMan!=null){             mBMapMan.destroy();             mBMapMan=null;         }           super.onDestroy();     }       @Override      protected void onPause(){         mMapView.onPause();           if(mBMapMan!=null){               mBMapMan.stop();           }           super.onPause();       }       @Override      protected void onResume(){           mMapView.onResume();           if(mBMapMan!=null){             mBMapMan.start();           }           super.onResume();       }   }       <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     android:orientation="vertical"     android:scrollbars="none" >       <com.baidu.mapapi.map.MapView         android:id="@+id/bmapsView"         android:layout_width="match_parent"         android:layout_height="match_parent"         android:clickable="true" />   </LinearLayout>     (七)離線地圖   離線地圖好處多多,但若是要開發需要推廣給眾多用戶的App的話,建議要麼做下載離線地圖包功能(Demo中有例程,很容易),要麼考慮在App第一次運行的時候把APK資源文件中的離線地圖復制到用戶SD卡中(理論上可以實現),當然這樣的話地圖適用范圍會受到限制,開發有明確地域限制的App可以選用(例如:西安出行助手)。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved