使用Android自带的LocationManager和Location获取位置的时候,经常会有获取的location为null的情况,并且操作起来也不是很方便,在这个Demo里我使用了百度地图API中的定位SDK,可以一次性获取当前位置经纬度以及详细地址信息,还可以获取周边POI信息,同时可以设定位置通知点,当到达某一位置时,发出通知信息等方式来告知用户。jar包下载以及官方文档请参照:百度定位SDK,前提是需要注册百度开发者账号。
下面来看看定位的基本原理,目前,定位SDK可以通过GPS、基站、Wifi信号进行定位。基本定位流程如下图所示,当应用程序向定位SDK发起定位请求时,定位SDK会根据当前的GPS、基站、Wifi信息生成相对应的定位依据。然后定位SDK会根据定位依据来进行定位。如果需要,定位SDK会向定位服务器发送网络请求。定位服务器会根据请求的定位依据推算出对应的坐标位置,然后根据用户的定制信息,生成定位结果返回给定位SDK。
注意要把locSDK_2.4.jar添加到当天工程,右键jar文件-Build path-Add to。。。
上代码
布局文件:
<?
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"
>
<
Button
android:id
=
"@+id/btn_start"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:layout_marginTop
=
"20dp"
android:text
=
"Start"
/>
<
TextView
android:id
=
"@+id/tv_loc_info"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:textSize
=
"18sp"
/>
</
LinearLayout
>
配置文件:
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.ericssonlabs"
android:versionCode
=
"1"
android:versionName
=
"1.0"
>
<
uses-sdk
android:minSdkVersion
=
"8"
/>
<
permission
android:name
=
"android.permission.BAIDU_LOCATION_SERVICE"
>
</
permission
>
<
uses-permission
android:name
=
"android.permission.BAIDU_LOCATION_SERVICE"
>
</
uses-permission
>
<
uses-permission
android:name
=
"android.permission.ACCESS_COARSE_LOCATION"
>
</
uses-permission
>
<
uses-permission
android:name
=
"android.permission.ACCESS_FINE_LOCATION"
>
</
uses-permission
>
<
uses-permission
android:name
=
"android.permission.ACCESS_WIFI_STATE"
>
</
uses-permission
>
<
uses-permission
android:name
=
"android.permission.ACCESS_NETWORK_STATE"
>
</
uses-permission
>
<
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
android:name
=
"android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
>
</
uses-permission
>
<
uses-permission
android:name
=
"android.permission.READ_LOGS"
>
</
uses-permission
>
<
application
android:icon
=
"@drawable/ic_launcher"
android:label
=
"@string/app_name"
>
<
activity
android:name
=
".LocationDemoActivity"
android:label
=
"@string/app_name"
>
<
intent-filter
>
<
action
android:name
=
"android.intent.action.MAIN"
/>
<
category
android:name
=
"android.intent.category.LAUNCHER"
/>
</
intent-filter
>
</
activity
>
<
service
android:name
=
"com.baidu.location.f"
android:enabled
=
"true"
android:permission
=
"android.permission.BAIDU_LOCATION_SERVICE"
android:process
=
":remote"
>
<
intent-filter
>
<
action
android:name
=
"com.baidu.location.service_v2.4"
/>
</
intent-filter
>
</
service
>
</
application
>
</
manifest
>
实现代码:
public
class
LocationDemoActivity
extends
Activity {
private
TextView locationInfoTextView =
null
;
private
Button startButton =
null
;
private
LocationClient locationClient =
null
;
private
static
final
int
UPDATE_TIME =
5000
;
private
static
int
LOCATION_COUTNS =
0
;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
locationInfoTextView = (TextView)
this
.findViewById(R.id.tv_loc_info);
startButton = (Button)
this
.findViewById(R.id.btn_start);
locationClient =
new
LocationClient(
this
);
//设置定位条件
LocationClientOption option =
new
LocationClientOption();
option.setOpenGps(
true
);
//是否打开GPS
option.setCoorType(
"bd09ll"
);
//设置返回值的坐标类型。
option.setPriority(LocationClientOption.NetWorkFirst);
//设置定位优先级
option.setProdName(
"LocationDemo"
);
//设置产品线名称。强烈建议您使用自定义的产品线名称,方便我们以后为您提供更高效准确的定位服务。
option.setScanSpan(UPDATE_TIME);
//设置定时定位的时间间隔。单位毫秒
locationClient.setLocOption(option);
//注册位置监听器
locationClient.registerLocationListener(
new
BDLocationListener() {
@Override
public
void
onReceiveLocation(BDLocation location) {
// TODO Auto-generated method stub
if
(location ==
null
) {
return
;
}
StringBuffer sb =
new
StringBuffer(
256
);
sb.append(
"Time : "
);
sb.append(location.getTime());
sb.append(
"\nError code : "
);
sb.append(location.getLocType());
sb.append(
"\nLatitude : "
);
sb.append(location.getLatitude());
sb.append(
"\nLontitude : "
);
sb.append(location.getLongitude());
sb.append(
"\nRadius : "
);
sb.append(location.getRadius());
if
(location.getLocType() == BDLocation.TypeGpsLocation){
sb.append(
"\nSpeed : "
);
sb.append(location.getSpeed());
sb.append(
"\nSatellite : "
);
sb.append(location.getSatelliteNumber());
}
else
if
(location.getLocType() == BDLocation.TypeNetWorkLocation){
sb.append(
"\nAddress : "
);
sb.append(location.getAddrStr());
}
LOCATION_COUTNS ++;
sb.append(
"\n检查位置更新次数:"
);
sb.append(String.valueOf(LOCATION_COUTNS));
locationInfoTextView.setText(sb.toString());
}
@Override
public
void
onReceivePoi(BDLocation location) {
}
});
startButton.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
if
(locationClient ==
null
) {
return
;
}
if
(locationClient.isStarted()) {
startButton.setText(
"Start"
);
locationClient.stop();
}
else
{
startButton.setText(
"Stop"
);
locationClient.start();
/*
*当所设的整数值大于等于1000(ms)时,定位SDK内部使用定时定位模式。
*调用requestLocation( )后,每隔设定的时间,定位SDK就会进行一次定位。
*如果定位SDK根据定位依据发现位置没有发生变化,就不会发起网络请求,
*返回上一次定位的结果;如果发现位置改变,就进行网络请求进行定位,得到新的定位结果。
*定时定位时,调用一次requestLocation,会定时监听到定位结果。
*/
locationClient.requestLocation();
}
}
});
}
@Override
protected
void
onDestroy() {
super
.onDestroy();
if
(locationClient !=
null
&& locationClient.isStarted()) {
locationClient.stop();
locationClient =
null
;
}
}
}
来看看最后实现效果,点击Start后进入位置监听状态,根据设置的监听时间间隔进行定位,如果位置有变化则进行位置更新,同时显示了检测位置更新的次数,如果开启了GPS,则获取到卫星后,进行GPS定位: