前天試着用google的三種定位方式,GPS,Network,和基站定位。效果不是很理想。
所以昨天又開始試着用百度定位,最終效果確實比較好(個人感覺,可能是我目前的知識還是太淺薄)
大概整理了一下百度定位的一些知識:
1.這兩者的區別:可能是我沒有用過一些谷歌其它的SDK,但是就目前而言,百度定位還是很好用的,它直接將三種定位都封裝在了一起,開發人員可以通過setLocOption來設置一些他想要選擇的模式。有以下三種定位模式:
1.1:高精度定位模式下(Hight_Accuracy):會同時使用GPS、Wifi和基站定位,返回的是當前條件下精度最好的定位結果
1.2:低功耗定位模式下(Battery_Saving):僅使用網絡定位即Wifi和基站定位,返回的是當前條件下精度最好的網絡定位結果
1.3:僅用設備定位模式下(Device_Sensors):只使用用戶的GPS進行定位。這個模式下,由於GPS芯片鎖定需要時間,首次定位速度會需要一定的時間,而且GPS不適合室內
而且,如果開發一些手機地圖之類的軟件,百度SDK還是很方便的!
2.百度定位的準備工作:
2.1:申請key,需要在百度註冊成爲一個百度開發者,然後申請密鑰。地址:http://developer.baidu.com/map/android-mobile-apply-key.htm
2.2:Android開發申請密鑰時選擇移動端,申請密鑰時需要Android的簽名證書。Android的簽名證書在eclipse-window-preferences-Android-Build裏面可以找到SHA1,就是它了.
3.一個百度定位應用Manifest裏面應該必須部署的東西:
1.,<application>節點下面的meta-data節點:注意,name必須是"com.baidu.lbsapi.API_Key"(我有用過其它的name,結果都會報錯)
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="自己的value" />
2.<application>節點下面必須聲明對應的service,原因是,百度定位裏面有一個service,必須註冊才能調用它,要不然無法啓動LocationClient.start()函數
<service android:name="com.baidu.location.f" android:enabled="true"
android:process=":remote">
</service>
4.只需要創建一次LocationClient對象,在創建時註冊監聽函數,銷燬時註銷監聽函數,然後用按鈕來控制start()和stop()
4.1:如果設置參數時沒有 option.setScanSpan(),那麼只會在start()時得到一次位置,之後如果需要得到位置需要手動調用函數mLocationClient.requestLocation()。
5.可以參考百度給的那個定位的Demo,裏面實現了很多基礎功能。
6.在監聽函數給主線程傳遞消息時,使用了異步傳輸數據,即Handler-Thread,給主線程綁定一個Handler,然後重寫ReceiveMessage函數,子線程裏面可以通過Handler將消息傳給主線程。
7.其實可以直接自定義一個自己的Application,然後在裏面生成LocationClient,並且註冊監聽,其它Activity只要通過引用其對象就可以實現start()和stop()功能了。
(每個程序運行時創建一個Application類的對象而且只創建一個,Application是單例模式的一個類。)
以下是主要的代碼以及配置文件,最後是完整工程:
public class BaiduLbsDemoActivity extends Activity implements OnClickListener{
private static final String TAG="BaiduLbsDemoActivity";
//控件
private Button btn_StartLocation;
private Button btn_CheckNetwork;
//顯示文本
private TextView txt_LocationView,ModeInfo;
//定位有關
private LocationClient mLocationClient = null;
private BDLocationListener myListener;
//一些定位的參數
private RadioGroup selectMode,selectCoordinates;
private EditText frequence;
private LocationMode tempMode = LocationMode.Hight_Accuracy;//默認的精度
private String tempcoor="gcj02";//默認的座標系
//是否顯示詳細地理位置
private CheckBox checkGeoLocation;
//一個handler對象,用來線程傳輸
private MyHandler myHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG,"創建"+TAG);
super.onCreate(savedInstanceState);
init();
}
@Override
protected void onDestroy() {
Log.i(TAG,"Destroy!");
//Activity暫停時,停止定位功能
super.onPause();
if(mLocationClient.isStarted())
{
Log.i(TAG,"停止定位功能!");
mLocationClient.stop(); //停止定位
}
mLocationClient.unRegisterLocationListener(myListener);//註銷監聽
}
/**函數*/
private void init()
{
setContentView(R.layout.baidu_lbs_demo);
//實現創建handler並與主線程自帶的looper綁定。這裏沒有涉及looper與
//線程的關聯是因爲主線程在創建之初就已有looper
myHandler=new MyHandler(BaiduLbsDemoActivity.this);
mLocationClient=new LocationClient(this.getApplicationContext());
myListener = new MyLocationListener( myHandler);
//註冊監聽
mLocationClient.registerLocationListener(myListener); // 註冊監聽函數
bindWidgets();
setListeners();
}
/**綁定控件*/
private void bindWidgets()
{
btn_StartLocation=(Button) findViewById(R.id.btn_OnLocation);
btn_CheckNetwork=(Button) findViewById(R.id.btn_checkNetWork);
txt_LocationView=(TextView) findViewById(R.id.txt_locationView);
ModeInfo= (TextView)findViewById(R.id.modeinfo);
//定位頻率
frequence = (EditText)findViewById(R.id.frequence);
//是否顯示具體地址
checkGeoLocation = (CheckBox)findViewById(R.id.geolocation);
//定位模式
selectMode = (RadioGroup)findViewById(R.id.selectMode);
//不同的定位座標
selectCoordinates= (RadioGroup)findViewById(R.id.selectCoordinates);
}
//設置監聽
private void setListeners()
{
btn_StartLocation.setOnClickListener(this);
btn_CheckNetwork.setOnClickListener(this);
selectMode.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// TODO Auto-generated method stub
String ModeInformation = null;
switch (checkedId) {
case R.id.radio_high:
tempMode = LocationMode.Hight_Accuracy;
ModeInformation = getString(R.string.txt_hight_accuracy_desc);
break;
case R.id.radio_low:
tempMode = LocationMode.Battery_Saving;
ModeInformation = getString(R.string.txt_saving_battery_desc);
break;
case R.id.radio_device:
tempMode = LocationMode.Device_Sensors;
ModeInformation = getString(R.string.txt_device_sensor_desc);
break;
default:
break;
}
ModeInfo.setText(ModeInformation);
}
});
selectCoordinates.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// TODO Auto-generated method stub
switch (checkedId) {
case R.id.radio_gcj02:
tempcoor="gcj02";
break;
case R.id.radio_bd09ll:
tempcoor="bd09ll";
break;
case R.id.radio_bd09:
tempcoor="bd09";
break;
default:
break;
}
}
});
}
/**初始化定位參數*/
private void initLocation()
{
//設置定位參數
Log.i(TAG,"設置定位參數!");
setLocationOption();
}
/**設置定位的相關參數*/
private void setLocationOption()
{
LocationClientOption option=new LocationClientOption();
option.setOpenGps(true);//是否打開GPS
option.setIsNeedAddress(checkGeoLocation.isChecked());
option.setLocationMode(tempMode);//設置定位模式
option.setCoorType(tempcoor);//返回的定位結果是百度經緯度,默認值gcj02
//設置產品線名稱,強烈建議使用自定義的產品線名稱,方便提供更高效準確的定位服務
option.setProdName("dlcBaiduLbsDemo");
int span=1000;
try {
span = Integer.valueOf(frequence.getText().toString());
} catch (Exception e) {
Log.i(TAG,"設置頻率出錯"+e.getMessage());
}
option.setScanSpan(span);//設置發起定位請求的間隔時間爲5000ms
//設置
mLocationClient.setLocOption(option);
}
/**GPS定位*/
private void onLocation()
{
Log.i(TAG,"GPS定位");
if (mLocationClient == null)
{
Log.d(TAG, "locClient is null");
}
initLocation();
//一個按鈕實現開始和停止功能
if(btn_StartLocation.getText().equals(getString(R.string.btn_StartLocation))){
Log.i(TAG,"開始定位!");
mLocationClient.start();
btn_StartLocation.setText(getString(R.string.btn_StopLocation));
//mLocationClient.requestLocation();
}else{
Log.i(TAG,"停止定位!");
mLocationClient.stop();
btn_StartLocation.setText(getString(R.string.btn_StartLocation));
txt_LocationView.setText("已經停止定位!");
}
}
/**檢查網絡狀態*/
private void onCheckNetwork()
{
Log.i(TAG,"檢查網絡狀態");
}
@Override
public void onClick(View v) {
switch(v.getId())
{
case R.id.btn_OnLocation:
onLocation();
break;
case R.id.btn_checkNetWork:
onCheckNetwork();
break;
}
}
/**myHandler類,繼承Handler,重寫了handleMessage方法*/
private class MyHandler extends Handler
{
private Activity activity;
public MyHandler(Activity activity)
{
this.activity=new WeakReference<Activity>(activity).get();//使用弱引用避免Handler內存泄露
}
//重寫handleMessage,用於處理message
@Override
public void handleMessage(Message msg) {
Log.i(TAG,"主線程接收到消息!");
//選擇不同的口令類型
//0-獲取地址失敗 1-獲取地址成功
switch(msg.arg1)
{
case 0:
//Toast.makeText(activity.getApplicationContext(), "解析地址出錯,不能將經緯度解析爲正確地址!", Toast.LENGTH_SHORT)
//.show();
Update(msg);
break;
case 1:
//Toast.makeText(activity.getApplicationContext(), "地址獲取成功!", Toast.LENGTH_SHORT)
//.show();
Update(msg);
break;
default:
//Toast.makeText(activity.getApplicationContext(), "解析地址出錯,未知錯誤!", Toast.LENGTH_SHORT)
//.show();
Update(msg);
break;
}
}
/**更新UI方法*/
private void Update(Message msg)
{
//這裏用於更新網絡信息---更新Location
Bundle b=msg.getData();
//記得設置bundle時,將Location 鍵的值設爲對應的location
String myLocation=b.getString("LocationData");
txt_LocationView.setText(myLocation);
}
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dlc.test07.baidu.location"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<!-- 權限添加 -->
<!-- 這個權限用於進行網絡定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION">
</uses-permission>
<!-- 這個權限用於訪問GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION">
</uses-permission>
<!-- 用於訪問wifi網絡信息,wifi信息會用於進行網絡定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE">
</uses-permission>
<!-- 獲取運營商信息,用於支持提供運營商信息相關的接口 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">
</uses-permission>
<!-- 這個權限用於獲取wifi的獲取權限,wifi信息會用來進行網絡定位 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE">
</uses-permission>
<!-- 用於讀取手機當前的狀態 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE">
</uses-permission>
<!-- 寫入擴展存儲,向擴展卡寫入數據,用於寫入離線定位數據 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">
</uses-permission>
<!-- 訪問網絡,網絡定位需要上網 -->
<uses-permission android:name="android.permission.INTERNET">
</uses-permission>
<!-- SD卡讀取權限,用戶寫入離線定位數據 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS">
</uses-permission>
<!-- 允許應用讀取低級別的系統日誌文件 -->
<uses-permission android:name="android.permission.READ_LOGS">
</uses-permission>
<application
android:allowBackup="true"
android:icon="@drawable/ic_baidu_lbs"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<!-- meta-data必須放在application裏面 -->
<!-- value是申請的AK,name是申請的包名 -->
<meta-data android:name="com.baidu.lbsapi.API_KEY"
android:value="Fuk70GOYrzVDKqzyZrRpjNtW"/>
<!-- 聲明開始百度定位的服務 -->
<service android:name="com.baidu.location.f" android:enabled="true"
android:process=":remote">
</service>
<!-- Activity配置 -->
<activity android:name=".activity.SplashActivity"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation|keyboardHidden|screenSize"
>
<intent-filter >
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="dlc.test07.baidu.lbs.start" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity android:name=".activity.MainActivity"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation|keyboardHidden|screenSize"
></activity>
<activity android:name=".activity.BaiduLbsDemoActivity"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation|keyboardHidden|screenSize"
></activity>
</application>
</manifest>
完整工程:http://download.csdn.net/detail/u010979495/8113041