Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 高德地圖的定位,周邊搜索

Android 高德地圖的定位,周邊搜索

編輯:關於Android編程

剛弄完這兩個功能,當然是結合官網例子實現的。效果還行,稍作優化便可整合到app使用。在這裡做一下總結,及說明下我的思路。

剛開始上手感覺比較亂學起來也比較累,方法,類太多,直接復制各種錯,還不知道為什麼這麼做。現在我們一起交流下實現的思路:

1:定位:這是所有地圖功能實現的基礎,所以不管要實現諸如周邊搜索啊,導航啊什麼的都需要基於定位。
如何定位:官網上例子也很詳細,主要是實現幾個監聽,並實現方法:

    aMap.setLocationSource(this);// 設置定位監聽
            //綁定監聽
            mapLocationClient.setLocationListener(this);
            //開啟定位
            mapLocationClient.startLocation();

監聽的實現方法:

public void onLocationChanged(AMapLocation aMapLocation)

定位實現:

//激活定位的重寫
public void activate(OnLocationChangedListener onLocationChangedListener)
//取消定位的重寫
public void deactivate()

定位成功與否會有返回碼,返回碼對照如下(來自官網):

0 定位成功。
1 一些重要參數為空,如context;請對定位傳遞的參數進行非空判斷。
2 定位失敗,由於僅掃描到單個wifi,且沒有基站信息。
3 獲取到的請求參數為空,可能獲取過程中出現異常。
4 請求服務器過程中的異常,多為網絡情況差,鏈路不通導致,請檢查設備網絡是否通暢。
5 返回的XML格式錯誤,解析失敗。
6 定位服務返回定位失敗,如果出現該異常,請將errorDetail信息通過[email protected]反饋給我們。
7 KEY建權失敗,請仔細檢查key綁定的sha1值與apk簽名sha1值是否對應。
8 Android exception通用錯誤,請將errordetail信息通過[email protected]反饋給我們。
9 定位初始化時出現異常,請重新啟動定位。
10 定位客戶端啟動失敗,請檢查AndroidManifest.xml文件是否配置了APSService定位服務
11 定位時的基站信息錯誤,請檢查是否安裝SIM卡,設備很有可能連入了偽基站網絡。
12 缺少定位權限,請在設備的設置中開啟app的定位權限。

2:搜索,周邊搜索 :有了定位,便有了搜索裡面的要求的條件(經緯度等),然後就可以慢慢實現功能了。
搜索功能靠一下方法和監聽:

PoiSearch.Query query=PoiSearch.Query(keyWord,type,city);
PoiSearch poiSearch = new PoiSearch(this,query);
poiSearch.setOnPoiSearchListener(this);//設置回調數據的監聽器
poiSearch.searchPOIAsyn();//開始搜索

監聽的回調方法:

public void onPoiSearched(PoiResult poiResult, int i) 
public void onPoiItemSearched(PoiItem poiItem, int i)

搜索返回碼對照(來自官網)本文最後:

實例:
功能介紹:定位,周邊搜索(可選擇搜索范圍:1000-5000米(spinner下拉實現))

代碼:
清單文件:


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    


        

布局:


    
    

    

activity:

package com.inext.test.gaodemap;

import android.app.ProgressDialog;
import android.content.res.Configuration;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.inputmethod.EditorInfo;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapException;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.NaviPara;
import com.amap.api.maps.overlay.PoiOverlay;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.core.SuggestionCity;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;

import java.util.List;

public class MainActivity extends AppCompatActivity implements LocationSource,AMapLocationListener , View.OnClickListener,PoiSearch.OnPoiSearchListener, AMap.OnMarkerClickListener, AMap.InfoWindowAdapter {

    private Button button1;
    private AMap aMap;
    private OnLocationChangedListener  mListener;
    private MapView mMapView;
    //聲明AMapLocationClient類對象
    public AMapLocationClient mapLocationClient;
    //聲明AMapLocationClientOption對象
    public AMapLocationClientOption mapLocationClientOption;
    ////////
    private ProgressDialog progDialog = null;// 搜索時進度條
    private String keyWord;
    private PoiSearch.Query query;// Poi查詢條件類
    private PoiSearch poiSearch;//搜索
    private PoiSearch.SearchBound searchBound;
    private int currentPage;// 當前頁面,從0開始計數
    private PoiResult poiResults; // poi返回的結果
    private String city = "";//搜索城市
    private EditText editText1;
    private LatLonPoint latLonPoint;
    private Spinner spinner;
    private int juli = 1000;
    ////////
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportActionBar().hide();
        setContentView(R.layout.activity_main);
        mMapView = (MapView)findViewById(R.id.map);
        //在activity執行onCreate時執行mMapView.onCreate(savedInstanceState),實現地圖生命周期管理
        mMapView.onCreate(savedInstanceState);
        init();
    }

    private void init(){

        if (aMap==null){
            aMap = mMapView.getMap();
        }
        setUp();
    }

    private void setUp() {

        aMap.setLocationSource(this);// 設置定位監聽
        aMap.getUiSettings().setMyLocationButtonEnabled(true);// 設置默認定位按鈕是否顯示
        // 設置為true表示顯示定位層並可觸發定位,false表示隱藏定位層並不可觸發定位,默認是false
        aMap.setMyLocationEnabled(true);
        // 設置定位的類型為定位模式 ,可以由定位、跟隨或地圖根據面向方向旋轉幾種
        aMap.setMyLocationType(AMap.LOCATION_TYPE_LOCATE);

        button1 = (Button) findViewById(R.id.search_button);
        button1.setOnClickListener(this);
        spinner = (Spinner)findViewById(R.id.juli);
        String[] ints = {"1000","2000","3000","4000","5000"};
        ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_dropdown_item_1line,ints);
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView parent, View view, int position, long id) {
                juli = Integer.valueOf(String.valueOf(spinner.getSelectedItem()));
                Log.i("---",juli-10+"");
            }

            @Override
            public void onNothingSelected(AdapterView parent) {

            }
        });
        editText1 = (EditText) findViewById(R.id.search_edit);

        //editText1.addTextChangedListener(this);
        aMap.setOnMarkerClickListener(this);
        aMap.setInfoWindowAdapter(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //在activity執行onDestroy時執行mMapView.onDestroy(),實現地圖生命周期管理
        mMapView.onDestroy();
        mapLocationClient.onDestroy();
    }
    @Override
    protected void onResume() {
        super.onResume();
        //在activity執行onResume時執行mMapView.onResume (),實現地圖生命周期管理
        mMapView.onResume();
    }
    @Override
    protected void onPause() {
        super.onPause();
        //在activity執行onPause時執行mMapView.onPause (),實現地圖生命周期管理
        mMapView.onPause();
    }
    @Override
    protected void onStop() {
        super.onStop();
        mapLocationClient.stopLocation();
    }
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        //在activity執行onSaveInstanceState時執行mMapView.onSaveInstanceState (outState),實現地圖生命周期管理
        mMapView.onSaveInstanceState(outState);
    }
    @Override
    public void onLocationChanged(AMapLocation aMapLocation) {
        if (aMapLocation!=null){
            if (aMapLocation.getErrorCode()==0){

                mListener.onLocationChanged(aMapLocation);// 顯示系統小藍點

                StringBuilder stringBuilder = new StringBuilder();
                //定位成功回調信息,設置相關消息
                int type = aMapLocation.getLocationType();
                String address = aMapLocation.getAddress();
                stringBuilder.append(type+address);
                city = aMapLocation.getCity();
                //獲得小點
                if (latLonPoint==null){
                    latLonPoint = new LatLonPoint(aMapLocation.getLatitude(),aMapLocation.getLongitude());
                }else {
                    latLonPoint.setLatitude(aMapLocation.getLatitude());
                    latLonPoint.setLongitude(aMapLocation.getLongitude());
                }
                //Toast.makeText(this,stringBuilder.toString(),Toast.LENGTH_SHORT).show();
            }else {
                //顯示錯誤信息ErrCode是錯誤碼,errInfo是錯誤信息,詳見下方錯誤碼表。
                Log.i("erro info:",aMapLocation.getErrorCode()+"---"+aMapLocation.getErrorInfo());
            }
        }
    }
    //激活定位
    @Override
    public void activate(OnLocationChangedListener onLocationChangedListener) {
        mListener = onLocationChangedListener;
        if (mapLocationClient==null){
            //初始化AMapLocationClient,並綁定監聽
            mapLocationClient = new AMapLocationClient(getApplicationContext());

            //初始化定位參數
            mapLocationClientOption = new AMapLocationClientOption();
            //設置定位精度
            mapLocationClientOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
            //是否返回地址信息
            mapLocationClientOption.setNeedAddress(true);
            //是否只定位一次
            mapLocationClientOption.setOnceLocation(false);
            //設置是否強制刷新WIFI,默認為強制刷新
            mapLocationClientOption.setWifiActiveScan(true);
            //是否允許模擬位置
            mapLocationClientOption.setMockEnable(false);
            //定位時間間隔
            mapLocationClientOption.setInterval(2000);
            //給定位客戶端對象設置定位參數
            mapLocationClient.setLocationOption(mapLocationClientOption);
            //綁定監聽
            mapLocationClient.setLocationListener(this);
            //開啟定位
            mapLocationClient.startLocation();
        }

    }
    //停止定位
    @Override
    public void deactivate() {
        mListener = null;
        if (mapLocationClient!=null){
            mapLocationClient.stopLocation();
            mapLocationClient.onDestroy();
        }
        mapLocationClient = null;
    }
    long firstTime = 0;
    //雙擊退出
    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode==KeyEvent.KEYCODE_BACK){
            long secondTime = System.currentTimeMillis();
            if (secondTime-firstTime>2000){
                Toast.makeText(this,"再按一次退出",Toast.LENGTH_SHORT).show();
                firstTime = System.currentTimeMillis();
                return true;
            }else {
                finish();
            }
        }
        return super.onKeyUp(keyCode, event);
    }
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){
            Log.d("=========", "橫屏");
        }else {
            Log.d("=========", "豎屏");
        }
    }
    /**
     * 點擊搜索按鈕
     */
    private void search(){
        keyWord = editText1.getText().toString();
        Log.i("---", keyWord);
        if ("".equals(keyWord)){
            Toast.makeText(MainActivity.this, "請輸入搜索關鍵字",Toast.LENGTH_SHORT).show();
            return;
        }else {
            doSearchQuery();
        }
    }
    /**
     * 搜索操作
     */
    private void doSearchQuery() {
        showProgressDialog();
        currentPage = 0;
        //第一個參數表示搜索字符串,第二個參數表示poi搜索類型,第三個參數表示poi搜索區域(空字符串代表全國)
        query = new PoiSearch.Query(keyWord,"",city);
        query.setPageSize(10);// 設置每頁最多返回多少條poiitem
        query.setPageNum(currentPage);// 設置查第一頁
        poiSearch = new PoiSearch(this,query);
        poiSearch.setOnPoiSearchListener(this);//設置回調數據的監聽器
        //點附近2000米內的搜索結果
        if (latLonPoint!=null){
            searchBound = new PoiSearch.SearchBound(latLonPoint,juli);
            poiSearch.setBound(searchBound);
        }
        poiSearch.searchPOIAsyn();//開始搜索
    }
    /**
     * 顯示進度框
     */
    private void showProgressDialog() {
        if (progDialog == null)
            progDialog = new ProgressDialog(this);
        progDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progDialog.setIndeterminate(false);
        progDialog.setCancelable(false);
        progDialog.setMessage("正在搜索:\n" + keyWord);
        progDialog.show();
    }

    /**
     * 隱藏進度框
     */
    private void dissmissProgressDialog() {
        if (progDialog != null) {
            progDialog.dismiss();
        }
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.search_button:
                Log.i("---","搜索操作");
                search();
                break;
        }
    }
    /**
     * poi沒有搜索到數據,返回一些推薦城市的信息
     */
    private void showSuggestCity(List cities) {
        String infomation = "推薦城市\n";
        for (int i = 0; i < cities.size(); i++) {
            infomation += "城市名稱:" + cities.get(i).getCityName() + "城市區號:"
                    + cities.get(i).getCityCode() + "城市編碼:"
                    + cities.get(i).getAdCode() + "\n";
        }
        Toast.makeText(MainActivity.this, infomation,Toast.LENGTH_SHORT).show();

    }


    /**
     * POI信息查詢回調方法
     */
    @Override
    public void onPoiSearched(PoiResult poiResult, int i) {
        dissmissProgressDialog();// 隱藏對話框
        if (i == 1000) {
            Log.i("---","查詢結果:"+i);
            if (poiResult != null && poiResult.getQuery() != null) {// 搜索poi的結果
                if (poiResult.getQuery().equals(query)) {// 是否是同一條
                    poiResults = poiResult;
                    // 取得搜索到的poiitems有多少頁
                    List poiItems = poiResult.getPois();// 取得第一頁的poiitem數據,頁數從數字0開始
                    List suggestionCities = poiResult
                            .getSearchSuggestionCitys();// 當搜索不到poiitem數據時,會返回含有搜索關鍵字的城市信息

                    if (poiItems != null && poiItems.size() > 0) {
                        aMap.clear();// 清理之前的圖標
                        PoiOverlay poiOverlay = new PoiOverlay(aMap, poiItems);
                        poiOverlay.removeFromMap();
                        poiOverlay.addToMap();
                        poiOverlay.zoomToSpan();
                    } else if (suggestionCities != null
                            && suggestionCities.size() > 0) {
                        showSuggestCity(suggestionCities);
                    } else {
                        Toast.makeText(MainActivity.this, "未找到結果",Toast.LENGTH_SHORT).show();
                    }
                }
            } else {
                Toast.makeText(MainActivity.this, "該距離內沒有找到結果",Toast.LENGTH_SHORT).show();
            }
        } else {
            Log.i("---","查詢結果:"+i);
            Toast.makeText(MainActivity.this, "異常代碼---"+i,Toast.LENGTH_SHORT).show();
        }

    }

    @Override
    public void onPoiItemSearched(PoiItem poiItem, int i) {

    }

    @Override
    public boolean onMarkerClick(Marker marker) {
        marker.showInfoWindow();
        return false;
    }
    /**
     * 調起高德地圖導航功能,如果沒安裝高德地圖,會進入異常,可以在異常中處理,調起高德地圖app的下載頁面
     */
    public void startAMapNavi(Marker marker) {
        // 構造導航參數
        NaviPara naviPara = new NaviPara();
        // 設置終點位置
        naviPara.setTargetPoint(marker.getPosition());
        // 設置導航策略,這裡是避免擁堵
        naviPara.setNaviStyle(NaviPara.DRIVING_AVOID_CONGESTION);

        // 調起高德地圖導航
        try {
            AMapUtils.openAMapNavi(naviPara, getApplicationContext());
        } catch (AMapException e) {

            // 如果沒安裝會進入異常,調起下載頁面
            AMapUtils.getLatestAMapApp(getApplicationContext());

        }

    }
    @Override
    public View getInfoWindow(final Marker marker) {
        View view = getLayoutInflater().inflate(R.layout.poikeywordsearch_uri,
                null);
        TextView title = (TextView) view.findViewById(R.id.title);
        title.setText(marker.getTitle());

        TextView snippet = (TextView) view.findViewById(R.id.snippet);
        snippet.setText(marker.getSnippet());
        ImageButton button = (ImageButton) view
                .findViewById(R.id.start_amap_app);
        // 調起高德地圖app
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startAMapNavi(marker);
            }
        });
        return view;
    }

    @Override
    public View getInfoContents(Marker marker) {
        return null;
    }
}

注意: 為了更好的對問題進行排查, 自 Android 搜索 SDK V3.2.1 版本,搜索回調接口返回響應
碼已經變更,詳細見下面表格。
響應碼 說明及排查方法 錯誤碼來源
1000 請求正常 公用錯誤碼,來源於
高德服務
1001 開發者簽名未通過。
開發者在 key 控制台中,開啟了“ 數字簽名” 功能,但沒有按照指
定算法生成“ 數字簽名” 。 現階段發生在 web 服務 API 和智能硬
件定位的 key。
1002 用戶 key 不正確或過期。
a、 目前網站現有產品,僅支持 2014 年 9 月 23 日之後申請的 key。
b、對照開發指南配置功能,檢查 key 添加是否正確。
1003 沒有權限使用相應的接口。
請檢查使用的 key、與使用的接口是否匹配。
1008 綁定的 SHA1 與包名不一致。
請檢查 SHA1、包名是否正確,論壇鏈接
http://lbsbbs.amap.com/forum.php?mod=viewthread&tid=
10894&extra=&page=1
1009 請求 key 與綁定平台不符。
請確認申請的 key,適用於 Android 平台 SDK。
1012 權限不足,服務請求被拒絕。
如果申請的 Android 平台 SDK,請確認 key 調用是否正常。如有
問題,可通過郵件 [email protected]、論壇反饋給高德開放平台。
1013 開發者刪除了 key,key 被刪除後無法正常使用。
1100 引擎服務響應錯誤。
1101 引擎返回數據異常。
1102 高德服務端請求鏈接超時
1103 讀取服務結果返回超時。
1200 請求參數非法
請求參數的值沒有按照規范要求填寫。例如,某參數值域范圍為
[1,3],開發者傳了’4’
1201 請求條件中,缺少必填參數。
1202 服務請求協議非法
1203 服務端未知錯誤
1800 服務端新增錯誤,如有問題,可通過郵件 [email protected]、 論
壇反饋給高德開放平台。
公用錯誤碼,來源於
SDK 本地錯誤
1801 協議解析錯誤
1802 socket 連接超時 - SocketTimeoutException
1803 url 異常 - MalformedURLException
1804 未知主機 - UnKnowHostException
1806 http 或 socket 連接失敗 - ConnectionException
1900 未知錯誤
1901 參數無效
1902 IO 操作異常 - IOException
1903 空指針異常 - NullPointException
2000 Tableid 格式不正確。 雲檢索返回錯誤碼,
來源於高德服務
2001 ID 不存在,請檢查。
2002 雲檢索服務器維護中
2003 key 對應的 tableID 不存在,請檢查。
2100 找不到對應的 userid 信息,請檢查您提供的 userid 是否存在。 附近功能返回錯誤
2101 App key 未開通“ 附近” 功能,請登錄 碼,來源於高德服務
http://lbs.amap.com/console/bind 進行開通。
2200 已開啟自動上傳 附近功能返回錯誤
碼,來源於 SDK 本
地錯誤
2201 USERID 非法(UserID 為空、包含非法字符、長度超過 32 位或與
前次上傳的 UserID 不同)
2202 NearbyInfo 對象為空
2203 兩次單次上傳的間隔低於 7 秒
2204 Point 為空,或與前次上傳的相同
3000 規劃點(包括起點、終點、途經點)不在中國陸地范圍內 路徑規劃功能返回
錯誤碼,來源於高德
服務端
3001 規劃點(包括起點、終點、途經點)附近搜不到路
3002 路線計算失敗,通常是由於道路連通關系導致
3003 步行算路起點、終點距離過長導致算路失敗。
4000 短串分享認證失敗,請通過郵件 [email protected]、 論壇等方式
反饋給高德開放平台。
短串分享功能返回,
來源於高德服務端
4001 短串請求失敗。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved