我的Android进阶之旅------>Android百度地图定位SDK功能学习
因为项目需求,需要使用百度地图的定位功能,因此去百度地图开发平台下载了百度地图的Android定位SDK最新版本的开发包和示例代码学习。
Android 定位SDK地址:http://developer.baidu.com/map/index.php?title=android-locsdk
下载地址为:http://developer.baidu.com/map/index.php?title=android-locsdk/geosdk-android-download
下载示例代码后,导入到相应的IDE工具。代码有android_studio和eclipse两个版本。我使用的Eclipse,因此导入Eclipse的版本代码。
先申请秘钥,然后修改AndroidManifest.xml中的代码,具体要修改的代码如下:
<!-- meta-data需要写在application中 -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="请输入AK" />
具体的秘钥申请步骤,请参考链接:http://developer.baidu.com/map/index.php?title=android-locsdk/guide/key
如果上面的key值不对或者是没有的话,运行项目会出现下面的结果,其中的error code:505代表key不存在或者非法。
完成上述步骤后,就可以运行该项目了。正常运行项目后,如下所示:
====================================================================================
下面来具体看看项目代码,项目的结构如下图所示,开发所需要的SDK是最新版本的locSDK_6.11.jar,还有liblocSDK6a.so库文件
主要的类有三个,LocationActivity、NotifyActivity和LocationApplication。
LocationActivity.java主要功能是展示定位的信息,代码如下:
package com.baidu.baidulocationdemo;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.LocationClientOption.LocationMode;
import android.app.Activity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;
public class LocationActivity extends Activity{
private LocationClient mLocationClient;
private TextView LocationResult,ModeInfor;
private Button startLocation;
private RadioGroup selectMode,selectCoordinates;
private EditText frequence;
private LocationMode tempMode = LocationMode.Hight_Accuracy;
private String tempcoor="gcj02";
private CheckBox checkGeoLocation;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.location);
mLocationClient = ((LocationApplication)getApplication()).mLocationClient;
LocationResult = (TextView)findViewById(R.id.textView1);
LocationResult.setMovementMethod(ScrollingMovementMethod.getInstance());
ModeInfor= (TextView)findViewById(R.id.modeinfor);
ModeInfor.setText(getString(R.string.hight_accuracy_desc));
((LocationApplication)getApplication()).mLocationResult = LocationResult;
frequence = (EditText)findViewById(R.id.frequence);
checkGeoLocation = (CheckBox)findViewById(R.id.geolocation);
startLocation = (Button)findViewById(R.id.addfence);
startLocation.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//初始化定位SDK的配置参数
initLocation();
if(startLocation.getText().equals(getString(R.string.startlocation))){
//启动定位sdk
mLocationClient.start();//定位SDK start之后会默认发起一次定位请求,开发者无须判断isstart并主动调用request
startLocation.setText(getString(R.string.stoplocation));
}else{
//停止定位sdk
mLocationClient.stop();
startLocation.setText(getString(R.string.startlocation));
}
}
});
selectMode = (RadioGroup)findViewById(R.id.selectMode);
selectCoordinates= (RadioGroup)findViewById(R.id.selectCoordinates);
selectMode.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
String ModeInformation = null;
switch (checkedId) {
case R.id.radio_hight:
//高精度定位模式:这种定位模式下,会同时使用网络定位和GPS定位,优先返回最高精度的定位结果;
tempMode = LocationMode.Hight_Accuracy;//高精度模式
ModeInformation = getString(R.string.hight_accuracy_desc);
break;
case R.id.radio_low:
//低功耗定位模式:这种定位模式下,不会使用GPS,只会使用网络定位(Wi-Fi和基站定位)
tempMode = LocationMode.Battery_Saving;//低功耗模式
ModeInformation = getString(R.string.saving_battery_desc);
break;
case R.id.radio_device:
//仅用设备定位模式:这种定位模式下,不需要连接网络,只使用GPS进行定位,这种模式下不支持室内环境的定位
tempMode = LocationMode.Device_Sensors;//仅设备(Gps)模式
ModeInformation = getString(R.string.device_sensor_desc);
break;
default:
break;
}
ModeInfor.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;
}
}
});
}
@Override
protected void onStop() {
//停止定位sdk
mLocationClient.stop();
super.onStop();
}
/**
* 初始化定位SDK的配置参数
*/
private void initLocation(){
//配置定位SDK各配置参数,比如定位模式、定位时间间隔、坐标系类型等
LocationClientOption option = new LocationClientOption();
//设置定位模式:高精度,低功耗,仅设备
option.setLocationMode(tempMode);
/*
* 设置坐标类型
* coorType - 取值有3个:
* 返回国测局经纬度坐标系:gcj02
* 返回百度墨卡托坐标系 :bd09
* 返回百度经纬度坐标系 :bd09ll
*/
option.setCoorType(tempcoor);
int span=1000;
try {
span = Integer.valueOf(frequence.getText().toString());
} catch (Exception e) {
// TODO: handle exception
}
/*
* 设置扫描间隔,单位是毫秒 当<1000(1s)时,定时定位无效
* 默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的
*/
option.setScanSpan(span);
//设置是否需要地址信息,默认为无地址
option.setIsNeedAddress(checkGeoLocation.isChecked());
//设置是否打开gps进行定位
option.setOpenGps(true);
//可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果
option.setLocationNotify(true);
/*
* 可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,
* 设置是否在stop的时候杀死这个进程,默认不杀死
*/
option.setIgnoreKillProcess(true);
//可选,默认false,设置是否需要过滤gps仿真结果,默认需要
option.setEnableSimulateGps(false);
/*
* 可选,默认false,设置是否需要位置语义化结果,
* 可以在BDLocation.getLocationDescribe里得到,
* 结果类似于“在北京天安门附近”
*/
option.setIsNeedLocationDescribe(true);
/*
* 设置是否需要返回位置POI信息,可以在BDLocation.getPoiList()中得到数据
*/
option.setIsNeedLocationPoiList(true);
mLocationClient.setLocOption(option);
}
}
该acvtivity的布局文件为location.xml,代码如下:
<?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:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_weight="2.89"
android:maxLines="12"
android:scrollbars="vertical"
android:text=" "
android:textColor="#ffffffff" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" 定位模式"
android:textAppearance="?android:attr/textAppearanceLarge" />
<RadioGroup
android:id="@+id/selectMode"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
<RadioButton
android:id="@+id/radio_hight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="高精度" />
<RadioButton
android:id="@+id/radio_low"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="低功耗" />
<RadioButton
android:id="@+id/radio_device"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="仅设备" />
</RadioGroup>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="@+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="坐标系"
android:textAppearance="?android:attr/textAppearanceLarge" />
<RadioGroup
android:id="@+id/selectCoordinates"
android:layout_width="wrap_content"
android:layout_height="match_parent" >
<RadioButton
android:id="@+id/radio_gcj02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="gcj02(国测局加密经纬度坐标)" />
<RadioButton
android:id="@+id/radio_bd09ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bd09ll(百度加密经纬度坐标)" />
<RadioButton
android:id="@+id/radio_bd09"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="bd09(百度加密墨卡托坐标)" />
</RadioGroup>
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/modeinfor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2.88"
android:text=" " />
<LinearLayout
android:layout_width="278dp"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="定位时间间隔(ms):"
android:textAppearance="?android:attr/textAppearanceLarge" />
<EditText
android:id="@+id/frequence"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="1000"
android:inputType="number" >
<requestFocus />
</EditText>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2.89"
android:orientation="horizontal" >
<TextView
android:id="@+id/geofencelog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="反地理编码"
android:textAppearance="?android:attr/textAppearanceLarge" />
<CheckBox
android:id="@+id/geolocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" " />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2.89"
android:gravity="center|top"
android:orientation="vertical" >
<Button
android:id="@+id/addfence"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开启定位" />
</LinearLayout>
</LinearLayout>
在LocationActivity中引用的LocationApplication,主要功能是定位功能的主要逻辑都在这里,代码如下:
package com.baidu.baidulocationdemo;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.Poi;
import android.app.Application;
import android.app.Service;
import android.os.Vibrator;
import android.util.Log;
import android.widget.TextView;
import java.util.List;
/**
* 主Application,所有百度定位SDK的接口说明请参考线上文档:http://developer.baidu.com/map/loc_refer/index.html
* 百度定位SDK官方网站:http://developer.baidu.com/map/index.php?title=android-locsdk
*/
public class LocationApplication extends Application {
public LocationClient mLocationClient;
public MyLocationListener mMyLocationListener;
public TextView mLocationResult,logMsg;
public TextView trigger,exit;
public Vibrator mVibrator;
@Override
public void onCreate() {
super.onCreate();
mLocationClient = new LocationClient(this.getApplicationContext());
mMyLocationListener = new MyLocationListener();
mLocationClient.registerLocationListener(mMyLocationListener);
mVibrator =(Vibrator)getApplicationContext().getSystemService(Service.VIBRATOR_SERVICE);
}
/**
* 实现实时位置回调监听
*/
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//Receive Location
StringBuffer sb = new StringBuffer(256);
sb.append("time : ");
//server返回的当前定位时间
sb.append(location.getTime());
sb.append("\nerror code : ");
/*
* 获取定位类型
* 常量字段 值 描述
* TypeCacheLocation 65 定位结果描述:缓存定位结果
TypeCriteriaException 62 定位结果描述:无法定位结果
TypeGpsLocation 61 定位结果描述:GPS定位结果
TypeNetWorkException 63 定位结果描述:网络连接失败
TypeNetWorkLocation 161 定位结果描述:网络定位结果
TypeNone 0 定位结果描述:无效定位结果
TypeOffLineLocation 66 定位结果描述:离线定位成功结果
TypeOffLineLocationFail 67 定位结果描述:离线定位失败结果
TypeOffLineLocationNetworkFail 68 定位结果描述:网络连接失败时,查找本地离线定位时对应的返回结果
TypeServerError 167 定位结果描述:server定位失败
*/
sb.append(location.getLocType());
sb.append("\nlatitude : ");
//获取纬度坐标
sb.append(location.getLatitude());
sb.append("\nlontitude : ");
//获取经度坐标
sb.append(location.getLongitude());
sb.append("\nradius : ");
//获取定位精度,默认值0.0f
sb.append(location.getRadius());
if (location.getLocType() == BDLocation.TypeGpsLocation){// GPS定位结果
sb.append("\nspeed : ");
//获取速度,仅gps定位结果时有速度信息,单位公里/小时,默认值0.0f
sb.append(location.getSpeed());// 单位:公里每小时
sb.append("\nsatellite : ");
//gps定位结果时,获取gps锁定用的卫星数
sb.append(location.getSatelliteNumber());
sb.append("\nheight : ");
//获取高度信息,目前只有是GPS定位结果时才有效,单位米
sb.append(location.getAltitude());// 单位:米
sb.append("\ndirection : ");
//gps定位结果时,行进的方向,单位度
sb.append(location.getDirection());
sb.append("\naddr : ");
//获取详细地址信息
sb.append(location.getAddrStr());
sb.append("\ndescribe : ");
sb.append("gps定位成功");
} else if (location.getLocType() == BDLocation.TypeNetWorkLocation){// 网络定位结果
sb.append("\naddr : ");
//获取详细地址信息
sb.append(location.getAddrStr());
//运营商信息
sb.append("\noperationers : ");
/*
* 获取运营商信息
* 常量字段 描述 值
* OPERATORS_TYPE_UNKONW 未知运营商 0
* OPERATORS_TYPE_MOBILE 中国移动 1
* OPERATORS_TYPE_UNICOM 中国联通 2
* OPERATORS_TYPE_TELECOMU 中国电信 3
*/
sb.append(location.getOperators());
sb.append("\ndescribe : ");
sb.append("网络定位成功");
} else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 离线定位结果
sb.append("\ndescribe : ");
sb.append("离线定位成功,离线定位结果也是有效的");
} else if (location.getLocType() == BDLocation.TypeServerError) {
sb.append("\ndescribe : ");
sb.append("服务端网络定位失败,可以反馈IMEI号和大体定位时间到[email protected],会有人追查原因");
} else if (location.getLocType() == BDLocation.TypeNetWorkException) {
sb.append("\ndescribe : ");
sb.append("网络不同导致定位失败,请检查网络是否通畅");
} else if (location.getLocType() == BDLocation.TypeCriteriaException) {
sb.append("\ndescribe : ");
sb.append("无法获取有效定位依据导致定位失败,一般是由于手机的原因,处于飞行模式下一般会造成这种结果,可以试着重启手机");
}
sb.append("\nlocationdescribe : ");// 位置语义化信息
//获取位置语义化信息,没有的话返回NULL
sb.append(location.getLocationDescribe());
//仅在开发者设置需要POI信息时才会返回,在网络不通或无法获取时有可能返回null
List<Poi> list = location.getPoiList();// POI信息
if (list != null) {
sb.append("\npoilist size = : ");
sb.append(list.size());
/**
* POI: POI封装类,可以得到POI的ID、NAME、RANK(概率)值
* poi字串JSON格式的字符串。
* getId(): 获取POI的ID字符串
* getName(): 获取POI的名字字符串
* getRank(): 获取POI概率值,表示该POI在当前位置周边的概率
*/
for (Poi p : list) {
sb.append("\npoi= : ");
sb.append(p.getId() + " " + p.getName() + " " + p.getRank());
}
}
logMsg(sb.toString());
Log.i("BaiduLocationApiDem", sb.toString());
}
}
/**
* 显示请求字符串
* @param str
*/
public void logMsg(String str) {
try {
if (mLocationResult != null)
mLocationResult.setText(str);
} catch (Exception e) {
e.printStackTrace();
}
}
}
NotifyActivity.java的主要功能是位置提醒功能,代码如下
package com.baidu.baidulocationdemo;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.BDNotifyListener;
import com.baidu.location.LocationClient;
import android.app.Activity;
import android.app.Service;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class NotifyActivity extends Activity{
private Button startNotify;
private Vibrator mVibrator;
private LocationClient mLocationClient;
private NotiftLocationListener listener;
private double longtitude,latitude;
private NotifyLister mNotifyLister;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.notify);
listener = new NotiftLocationListener();
mVibrator =(Vibrator)getApplicationContext().getSystemService(Service.VIBRATOR_SERVICE);
startNotify = (Button)findViewById(R.id.notifystart);
mLocationClient = new LocationClient(this);
mLocationClient.registerLocationListener(listener);
startNotify.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(startNotify.getText().toString().equals("开启位置提醒")){
mLocationClient.start();
startNotify.setText("关闭位置提醒");
}else{
if(mNotifyLister!=null){
//取消注册的位置提醒监听
mLocationClient.removeNotifyEvent(mNotifyLister);
startNotify.setText("开启位置提醒");
}
}
}
});
}
@Override
protected void onStop() {
super.onStop();
//取消注册的位置提醒监听
mLocationClient.removeNotifyEvent(mNotifyLister);
mLocationClient = null;
mNotifyLister= null;
listener = null;
}
private Handler notifyHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
mNotifyLister = new NotifyLister();
/*
* 设置位置提醒的点的相关参数,4个参数代表要位置提醒的点的坐标,具体含义依次为:
* latitude - 纬度
longitude - 经度
radius - 距离范围
coorType - 坐标系类型(gcj02,gps,bd09,bd09ll)
*/
mNotifyLister.SetNotifyLocation(latitude,longtitude, 3000,"gcj02");
//注册位置提醒监听
mLocationClient.registerNotify(mNotifyLister);
}
};
public class NotiftLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//Receive Location
longtitude = location.getLongitude();//获取经度坐标
latitude = location.getLatitude(); //获取纬度坐标
notifyHandler.sendEmptyMessage(0);
}
}
public class NotifyLister extends BDNotifyListener{
/*
* 位置提醒回调函数
* mlocation: 位置坐标
* distance: 当前位置跟设定提醒点的距离
*/
@Override
public void onNotify(BDLocation mlocation, float distance){
mVibrator.vibrate(1000);//振动提醒已到设定位置附近
Toast.makeText(NotifyActivity.this, "震动提醒", Toast.LENGTH_SHORT).show();
}
}
}
描述文件AndroidManifest.xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.baidu.baidulocationdemo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<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.READ_LOGS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
android:name="com.baidu.baidulocationdemo.LocationApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.Black" >
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" >
<intent-filter>
<action android:name="com.baidu.location.service_v2.2" >
</action>
</intent-filter>
</service>
<!-- meta-data需要写在application中 -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="这里填写你申请的百度 key" />
<activity
android:name="com.baidu.baidulocationdemo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.baidu.baidulocationdemo.LocationActivity" >
</activity>
<activity android:name="com.baidu.baidulocationdemo.NotifyActivity" >
</activity>
<activity android:name="com.baidu.baidulocationdemo.QuestActivity" >
</activity>
</application>
</manifest>
====================================================================================
作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:http://blog.****.net/ouyang_peng
====================================================================================