Android studio百度地圖的使用

由於某些原因Google的網絡服務在中國不可訪問,從而導致網絡定位方式的API失效,而GPS定位雖然不用網絡,但是必須在室外才能進行有效的定位。基於以上原因可以使用第三方公司的SDK,國內在這領域做得比較好的是百度、高德

一、申請API Key

要想使用百度的LBS功能,首先必須申請一個API Key。需要百度賬號才能申請,沒有的話可以去註冊一個。登錄你的百度賬號,打開http://developer.baidu.com/user/reg鏈接,在裏面填寫一些註冊信息即可(只需填寫帶 * 的部分內容就足夠了),然後點擊提交,進行郵箱驗證,點擊郵件發來的鏈接就可完成註冊。

到此一切順利!這樣說明成爲了一名百度開發者。接着訪問http://lbsyun.baidu.com/apiconsole/key。目前新註冊的用戶列表是空的,點擊創建應用就可以去申請APIKey了。應用名稱可以隨便填(最好和Android項目名稱相同),應用類型選擇Android SDK ,啓用服務默認的就可以。

那麼發佈版和開發版SHA1是什麼東西呢? 打開你的Android Stuidio 項目,點擊Android stuidio右側工具欄的Gradle →項目名稱→:app→Tasks→android,這裏展示了項目中所有內置的Gradle Tasks,其中signingReport這個Task可以用來查看簽名文件信息。雙擊文件,結果如圖所示.查看下方的SHA1即可。注意:我們使用的是debug.keystore文件生成的指紋。這是Android自動生成的一個用於測試的簽名文件。而當應用程序發佈時還需要創建一個正式的簽名文件,如果需要得到它:可以在cmd中輸入keytool -list -v -keystore <簽名文件路徑> 然後輸入密碼...


我們得到了SHA1指紋就是開發版的SHA1,但是我們暫時還沒有發佈版的,兩個值都填一樣就可以了。最後還有一個包名,寫我們的應用程序的包名,比如com.example.hu.tourismsystem 。然後點擊提交就創建成功了。然後有了 訪問應用(AK)就可以完成後續LBS 開發工作了。


二、使用百度定位,引入包

沒有Android項目的可以現在創建,不過項目包名要和API key的包名一致。準備LBS SDK : 下載地址是http://lbsyun.baidu.com/sdk/download,我們這次會用到基礎地圖和基礎定位這兩個SDK,將他們勾上,然後點擊“開發包”下載。下載完後解壓,文件內容如圖

將BaiduLBS_Android.jar 複製到 項目app模塊下的libs 。右鍵src/main目錄創建 Directory 取名爲jniLibs的目錄,把壓縮包裏的所有文件夾複製到這裏,並且複製到app/libs下各一份。系統會在app/build.gradle默認有如下聲明:

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs') ...}
並且在buildTypes塊下添加如下代碼
sourceSets {
    main() {
        jniLibs.srcDirs = ['libs']
    }
}

找到AndroidStuidio頂部工具欄Sync按鈕(sync Project with Gradle files 一般在從右數第四個),點擊他。然後薄酒引用成功了,如圖。這樣我們就把LBS的SDK準備好了。

注意:ksoap2-android... 這個與本項目無關

三、確定自己的經緯度:

首先在Manifest添加權限

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
      在application標籤下添加:

<meta-data android:name="com.baidu.lbsapi.API_KEY"
    android:value="KLqE1SiyhO90Osu7ruCO67cbJdidDrgn"/>
<service android:name="com.baidu.location.f" android:enabled="true"
    android:process=":remote" >
其中values 爲申請到的Api Key,根據自己情況修改。


佈局文件很簡單:一個id爲positon_textview的TextView。

主程序:

public class ActivityMicroTourism extends AppCompatActivity {
   
    public LocationClient mlocationClient;
    private TextView positionText;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setContentView(R.layout.activity_micro_tourism);
       
	mlocationClient = new LocationClient(getApplicationContext());
        mlocationClient.registerLocationListener(new MyLocationListener());
 	positionText = (TextView) findViewById(R.id.position_text_view);
        List<String> permissionList = new ArrayList<>();
        if (ContextCompat.checkSelfPermission(ActivityMicroTourism.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
        }
        if (ContextCompat.checkSelfPermission(ActivityMicroTourism.this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            permissionList.add(Manifest.permission.READ_PHONE_STATE);
        }
        if(ContextCompat.checkSelfPermission(ActivityMicroTourism.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
            permissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        }
        if (!permissionList.isEmpty()){
            String [] permissions =permissionList.toArray(new String[permissionList.size()]);
            ActivityCompat.requestPermissions(ActivityMicroTourism.this,permissions,1);
        }
        else{requestLocation();}
    }
    private void requestLocation(){
        mlocationClient.start();
    }
    @Override
    public void onRequestPermissionsResult(int requestCode,  String[] permissions, int[] grantResults) {
        switch (requestCode){
            case 1:
                if(grantResults.length>0){
                    for(int result :grantResults){
                        if(result!=PackageManager.PERMISSION_GRANTED){
                            Toast.makeText(this,"必須同意所有權限才能使用本程序",Toast.LENGTH_SHORT).show();
                            finish();
                            return;
                        }
                    }
                    requestLocation();
                }else {
                    Toast.makeText(this,"發生未知錯誤",Toast.LENGTH_SHORT).show();
                    finish();
                }
                break;
            default:
        }
    }
  
      public  class MyLocationListener implements BDLocationListener{
        @Override
        public void onReceiveLocation(BDLocation bdLocation) {

            StringBuilder currentPositon =new StringBuilder();
            
            currentPositon.append("緯度: ").append(bdLocation.getLatitude()).append("  ");
            currentPositon.append("經線: ").append(bdLocation.getLongitude()).append("  ");
          /*currentPositon.append("國家: ").append(bdLocation.getCountry()).append("  ");
            currentPositon.append("省: ").append(bdLocation.getProvince()).append("  ");
            currentPositon.append("市: ").append(bdLocation.getCity()).append("  ");
            currentPositon.append("區: ").append(bdLocation.getDistrict()).append("  ");
            currentPositon.append("街道: ").append(bdLocation.getStreet()).append("  ");*/
            currentPositon.append("定位方式: ");
            if(bdLocation.getLocType()==BDLocation.TypeGpsLocation){
                currentPositon.append("GPS");
            }else if(bdLocation.getLocType()==BDLocation.TypeNetWorkLocation){
                currentPositon.append("Wifi");
            }
	positionText.setText(currentPositon);
        }
}

在手機上運行該程序查看效果,同意所有權限,如果出現數據則表示成功。(如果只出現了經線和緯線,並且值非常離譜,也許只是你的網絡太差)可以自己在搞個刷新按鈕添加單擊事件。有三個權限是需要在運行時用戶同意的,爲啥要添加那麼多權限?因爲不給添不給用。本段代碼總的來說就是權限添加和權限驗證和獲取位置信息。

如果在用戶在快速移動中,怎樣實時更新位置?添加或修改如下代碼:

private void initLocation(){
    LocationClientOption option =new LocationClientOption();
    option.setScanSpan(5000);   
    option.setIsNeedAddress(true);
    mlocationClient.setLocOption(option);
}
private void requestLocation(){
    initLocation();
    mlocationClient.start();
}
@Override
protected void onDestroy() {
    super.onDestroy();
    mlocationClient.stop();
}
每隔5秒鐘會更新一下當前位置。更新太快容易消耗手機電量讓手機發熱.setIsNeedAddress 能讓獲取豐富的位置信息,現在可以把onReceiveLocation裏的註釋取消了。

4、使用百度地圖

佈局文件:

     <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/color_2"
                android:orientation="vertical" >


                <com.baidu.mapapi.map.MapView
                    android:id="@+id/bmapView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:clickable="true"></com.baidu.mapapi.map.MapView>
		 <TextView
                    android:id="@+id/position_text_view"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
		    android:visibility="gone"
                    android:text="!"
                    />
</LinearLayout>

主程序:修改

public class ActivityMicroTourism extends AppCompatActivity  {
    ...
    private MapView mapView; // --
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SDKInitializer.initialize(getApplication());//--
        setContentView(R.layout.activity_micro_tourism);
        mapView=(MapView)findViewById(R.id.bmapView);//--
        


        mlocationClient = new LocationClient(getApplicationContext());
        mlocationClient.registerLocationListener(new MyLocationListener());
	...
	}
 
    @Override                
    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
        
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mlocationClient.stop();
       mapView.onDestroy();  //--
        
    }
   
}

用手機運行程序,看看百度地圖是否能成功顯示出來,模擬器是不支持百度地圖SDK的。這裏注意一點SDKInitializer.initialize()要放在加載頁面之前。


如果能成功在手機上顯示地圖,那麼接下來的任務就是將地圖移動到我的位置,並且能讓我的位置顯示在地圖上.

public class ActivityMicroTourism extends AppCompatActivity  {
    ...
     private BaiduMap baiduMap;          //--
     private boolean isFristLocate=true; //--
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SDKInitializer.initialize(getApplication());
        setContentView(R.layout.activity_micro_tourism);
        mapView=(MapView)findViewById(R.id.bmapView);
        baiduMap=mapView.getMap();          //--
	baiduMap.setMyLocationEnabled(true);//--
        mlocationClient = new LocationClient(getApplicationContext());
        mlocationClient.registerLocationListener(new MyLocationListener());
	...
	}
 
      private void navigateTo(BDLocation location){
        if(isFristLocate ){
            LatLng ll=new LatLng(location.getLatitude(),location.getLongitude());
            MapStatusUpdate update= MapStatusUpdateFactory.newLatLng(ll);
            baiduMap.animateMapStatus(update);
            update=MapStatusUpdateFactory.zoomTo(16f);
            baiduMap.animateMapStatus(update);
            isFristLocate=false;
            
        }

        MyLocationData.Builder locationBuilder=new MyLocationData.Builder();
        locationBuilder.latitude(location.getLatitude());
        locationBuilder.longitude(location.getLongitude());
        MyLocationData locationData=locationBuilder.build();
        baiduMap.setMyLocationData(locationData);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mlocationClient.stop();
        mapView.onDestroy();
       baiduMap.setMyLocationEnabled(false); //--
    }

 	public  class MyLocationListener implements BDLocationListener{
        @Override  //--
        public void onReceiveLocation(BDLocation bdLocation) {   
         if (bdLocation.getLocType()==BDLocation.TypeGpsLocation || bdLocation.getLocType()==BDLocation.TypeNetWorkLocation){
                navigateTo(bdLocation);
            }
		...

        }

        @Override
        public void onConnectHotSpotMessage(String s, int i) {}
    }
   
}

其中,navaigateTo()是用來用來更新位置的,第一次打開程序的時候會更新位置

手機運行程序,查看效果。需要注意的幾點:

1、在佈局文件百度地圖控件會報錯,可以無視,模擬器上運行不了可以在手機上運行

2、由於可能某些人的手機比較舊,剛開始打開程序更新位置會失敗,可以嘗試添加一個刷新按鈕,執行navaigateTo()函數

3、更新位置是一個耗時比較大的操作,放在主線程中容易造成線程阻塞,最好在子線程中運行

4、百度地圖定位座標會發生點偏移,座標校正可以參考http://blog.sina.com.cn/s/blog_80a9926b0101ktoa.html

5、更多的開發指南可以參考 http://lbsyun.baidu.com

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章