注册百度开发者账户、获取密钥
2.点击“创建应用”开始申请开发密钥,如下图:
3.填写应用名称,注意应用类型选择“Android SDK”、正确填写SHA1 和 程序包名
应用名称:
自己随便写
包名:
就是你应用程序的包名,打开应用程序的AndroidManifest.xml文件,package后面就是包名
开发版SHA1:
打开Android Studio任意一个项目,点击右侧工具栏Gradle->项目名->app->Tasks->android,双击signingReport
在下方就会出现SHA1,把它复制到开发版SHA1。
发布版SHA1:
如果你的应用只是用于平时的程序练习,简单起见,可以直接在这里填写上面的开发版SHA1,之后提交,就可以得到对应的AK了
下载百度地图SDK
点击开发文档->Android地图SDk->产品下载->自定义下载
要实现什么功能就选择下载什么,我这里只是用于获取经纬度,所以只用选择基础定位下载即可。
下载后解析点开他有两个文件,第一个文件是我们一会要用的。
Android Stdio的配置
- 点开刚才的libs文件,里面有如下文件
- 把他们全放在libs目录下
- 配置build.gradle文件
在build.gradle配置我们的libs路径(sourceSets和defaultConfig同级)
sourceSets{
main{
jniLibs.srcDir 'libs'
}
}
注意这边的libs是和src同级,才会生效,不同目录结构按以下修改
jniLibs.srcDirs =['src/main/libs']
- 添加依赖
api files('libs/BaiduLBS_Android.jar')
添加后完整的build.gradle如下
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.example.gps"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
sourceSets{
main{
jniLibs.srcDir 'libs'
jni.srcDirs = [] //disable automatic ndk-build
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
api files('libs/BaiduLBS_Android.jar')
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
- AndoirdMainifest.xml中的配置
在AndoirdMainifest.xml的application底下添加
<!-- 声明service组件 -->
<application
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote">
</service>
<!-- AK鉴权 -->
<!-- meta-data需要写在application中 -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="申请的密钥AK" />
</application>
加入所需的权限
<!-- 这个权限用于进行网络定位-->
<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.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!-- 访问网络,网络定位需要上网-->
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
使用
获取经纬度信息
- 初始化LocationClient类
主线程中声明LocationClient类对象,该对象初始化需传入Context类型参数。
private LocationClient locationClient;
//这个类的具体实现在下面
private MyLocationListener myLocationListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建LocationClient对象
locationClient = new LocationClient(getApplicationContext());
//注册监听函数
locationClient.registerLocationListener(myLocationListener);
}
- 配置定位SDK参数
通过参数配置,可选择定位模式、可设定返回经纬度坐标类型、可设定是单次定位还是连续定位
LocationClientOption option = new LocationClientOption();
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
//可选,设置定位模式,默认高精度
//LocationMode.Hight_Accuracy:高精度;
//LocationMode. Battery_Saving:低功耗;
//LocationMode. Device_Sensors:仅使用设备;
option.setCoorType("bd09ll");
//可选,设置返回经纬度坐标类型,默认GCJ02
//GCJ02:国测局坐标;
//BD09ll:百度经纬度坐标;
//BD09:百度墨卡托坐标;
//海外地区定位,无需设置坐标类型,统一返回WGS84类型坐标
option.setScanSpan(1000);
//可选,设置发起定位请求的间隔,int类型,单位ms
//如果设置为0,则代表单次定位,即仅定位一次,默认为0
//如果设置非0,需设置1000ms以上才有效
option.setOpenGps(true);
//可选,设置是否使用gps,默认false
//使用高精度和仅用设备两种定位模式的,参数必须设置为true
option.setLocationNotify(true);
//可选,设置是否当GPS有效时按照1S/1次频率输出GPS结果,默认false
option.setIgnoreKillProcess(false);
//可选,定位SDK内部是一个service,并放到了独立进程。
//设置是否在stop的时候杀死这个进程,默认(建议)不杀死,即setIgnoreKillProcess(true)
option.SetIgnoreCacheException(false);
//可选,设置是否收集Crash信息,默认收集,即参数为false
option.setWifiCacheTimeOut(5*60*1000);
//可选,V7.2版本新增能力
//如果设置了该接口,首次启动定位时,会先判断当前Wi-Fi是否超出有效期,若超出有效期,会先重新扫描Wi-Fi,然后定位
option.setEnableSimulateGps(false);
//可选,设置是否需要过滤GPS仿真结果,默认需要,即参数为false
option.setNeedNewVersionRgc(true);
//可选,设置是否需要最新版本的地址信息。默认需要,即参数为true
locationClient.setLocOption(option);
- 实现BDAbstractLocationListener接口
class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
double latitude = location.getLatitude(); //获取纬度信息
double longitude = location.getLongitude(); //获取经度信
Log.d("MainActivity",latitude+" "+longitude);
float radius = location.getRadius(); //获取定位精度,默认值为0.0f
String coorType = location.getCoorType();
//获取经纬度坐标类型,以LocationClientOption中设置过的坐标类型为准
int errorCode = location.getLocType();
//获取定位类型、定位错误返回码,具体信息可参照类参考中BDLocation类中的说明
}
}
- 获取定位经纬度
只需发起定位,便能够从BDAbstractLocationListener监听接口中获取定位结果信息
locationClient.start();
使用baiduSDK解析城市名
直接可在 BDAbstractLocationListener接口的实现类中获取到,在 onReceiveLocation()方法中添加如下方法遍可获取到对应的地区
public class MyLocationListener extends BDAbstractLocationListener{
@Override
public void onReceiveLocation(BDLocation location){
//此处的BDLocation为定位结果信息类,通过它的各种get方法可获取定位相关的全部结果
//以下只列举部分获取地址相关的结果信息
//更多结果信息获取说明,请参照类参考中BDLocation类中的说明
String addr = location.getAddrStr(); //获取详细地址信息
String country = location.getCountry(); //获取国家
String province = location.getProvince(); //获取省份
String city = location.getCity(); //获取城市
String district = location.getDistrict(); //获取区县
String street = location.getStreet(); //获取街道信息
String adcode = location.getAdCode(); //获取adcode
String town = location.getTown(); //获取乡镇信息
}
}
把上述代码进行封装
- 定义回调接口,用于把获取到的经纬度返回
public interface ReturnLocation {
public void return_LatIng(String Lat,String Ing);
}
- BDAbstractLocationListener接口的实现类
class MyLocationListener extends BDAbstractLocationListener {
private ReturnLocation returnLocation;
public MyLocationListener() {
}
public MyLocationListener(ReturnLocation returnLocation) {
this.returnLocation = returnLocation;
}
@Override
public void onReceiveLocation(BDLocation location){
//此处的BDLocation为定位结果信息类,通过它的各种get方法可获取定位相关的全部结果
//以下只列举部分获取经纬度相关(常用)的结果信息
//更多结果信息获取说明,请参照类参考中BDLocation类中的说明
double latitude = location.getLatitude(); //获取纬度信息
double longitude = location.getLongitude(); //获取经度信息
returnLocation.return_LatIng(String.valueOf(latitude),String.valueOf(longitude));
float radius = location.getRadius(); //获取定位精度,默认值为0.0f
String coorType = location.getCoorType();
//获取经纬度坐标类型,以LocationClientOption中设置过的坐标类型为准
int errorCode = location.getLocType();
//获取定位类型、定位错误返回码,具体信息可参照类参考中BDLocation类中的说明
}
}
- 主要的定位服务类
public class LocationService {
private LocationClient client = null;
private LocationClientOption mOption,DIYoption;
private Object objLock = new Object();
public LocationService(Context locationContext){
synchronized (objLock) {
if(client == null){
client = new LocationClient(locationContext);
client.setLocOption(getDefaultLocationClientOption());
}
}
}
// 注册
public boolean registerListener(BDAbstractLocationListener listener){
boolean isSuccess = false;
if(listener != null){
client.registerLocationListener(listener);
isSuccess = true;
}
return isSuccess;
}
// 注销
public void unregisterListener(BDAbstractLocationListener listener){
if(listener != null){
client.unRegisterLocationListener(listener);
}
}
//设置配置
public boolean setLocationOption(LocationClientOption option){
boolean isSuccess = false;
if(option != null){
if(client.isStarted())
client.stop();
DIYoption = option;
client.setLocOption(option);
}
return isSuccess;
}
//默认Option设置
public LocationClientOption getDefaultLocationClientOption(){
if(mOption == null){
mOption = new LocationClientOption();
mOption.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备
mOption.setCoorType("bd09ll");//可选,默认gcj02,设置返回的定位结果坐标系,如果配合百度地图使用,建议设置为bd09ll;
mOption.setScanSpan(1000);//可选,默认0,即仅定位一次,设置发起连续定位请求的间隔需要大于等于1000ms才是有效的
mOption.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要
mOption.setIsNeedLocationDescribe(true);//可选,设置是否需要地址描述
mOption.setNeedDeviceDirect(false);//可选,设置是否需要设备方向结果
mOption.setLocationNotify(false);//可选,默认false,设置是否当gps有效时按照1S1次频率输出GPS结果
mOption.setIgnoreKillProcess(true);//可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死
mOption.setIsNeedLocationDescribe(true);//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation.getLocationDescribe里得到,结果类似于“在北京天安门附近”
mOption.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到
mOption.SetIgnoreCacheException(false);//可选,默认false,设置是否收集CRASH信息,默认收集
mOption.setOpenGps(true);//可选,默认false,设置是否开启Gps定位
mOption.setIsNeedAltitude(false);//可选,默认false,设置定位时是否需要海拔信息,默认不需要,除基础定位版本都可用
}
return mOption;
}
//自定义Option设置
public LocationClientOption getOption(){
if(DIYoption == null) {
DIYoption = new LocationClientOption();
}
return DIYoption;
}
public void start(){
synchronized (objLock) {
if(client != null && !client.isStarted()){
client.start();
}
}
}
public void stop(){
synchronized (objLock) {
if(client != null && client.isStarted()){
client.stop();
}
}
}
public boolean isStart() {
return client.isStarted();
}
public boolean requestHotSpotState(){
return client.requestHotSpotState();
}
}
使用示例;
private LocationService locationService;
private MyLocationListener myListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}
else{
get();
}
}
private void get() {
locationService = new LocationService(this);
myListener = new MyLocationListener(new ReturnLocation() {
@Override
public void return_LatIng(String Lat, String Ing) {
Log.d("MainActivity","纬度 "+Lat);
Log.d("MainActivity","经度 "+Ing);
}
});
locationService.registerListener(myListener);
locationService.setLocationOption(locationService.getDefaultLocationClientOption());
locationService.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
locationService.stop();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode){
case 1:
if(grantResults.length > 0 && grantResults[0]==PackageManager.PERMISSION_GRANTED)
get();
}
}
真机运行结果
使用经纬度反编译获取地区名
如果你已经知道了经纬度,可以无需进行Android Stdio配置baidu SDK,直接使用它提供的api可直接访问到经纬度对应的位置
官网地址链接
http://api.map.baidu.com/geocoder?output=json&location=31.225696563611,121.49884033194&key=你的AK
返回的数据如下,之后进行解析就可获取到相应的地区
{
"status":"OK",
"result":{
"location":{
"lng":121.49884,
"lat":31.225696
},
"formatted_address":"上海市黄浦区净土街31弄-4号",
"business":"老西门,城隍庙,豫园",
"addressComponent":{
"city":"上海市",
"direction":"north",
"distance":"58",
"district":"黄浦区",
"province":"上海市",
"street":"净土街",
"street_number":"31弄-4号"
},
"cityCode":289
}
}
使用示范如下:
发送okHttp的帮助类,具体的使用方法链接
public class HTTpUtil {
public static void sendOkHttpRequest(String address,okhttp3.Callback callback){
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(address)
.build();
//OkHtt在enqueue()方法的内部已经帮我们开好子线程了,它会在子线程中去执行HTTP请求,并将结果回调到okhttp3.Callback中
client.newCall(request).enqueue(callback);
}
}
使用GSON解析的解析类
GSON的具体使用
public class GetLocationPlace {
@SerializedName("status")
public String status;
@SerializedName("result")
public Result result;
public class Result{
@SerializedName("formatted_address")
public String formatted_address;
@SerializedName("addressComponent")
public AddressComponent addressComponent;
}
public class AddressComponent{
@SerializedName("city")
public String city;
@SerializedName("district")
public String district;
@SerializedName("province")
public String province;
}
}
GSON解析的工具类
public class Utility {
public static GetLocationPlace handlePlaceResponse(String response){
Gson gson = new Gson();
try{
GetLocationPlace getLocationPlace = gson.fromJson(response,GetLocationPlace.class);
return getLocationPlace;
}catch (Exception e){
return null;
}
}
}
活动中的使用代码,传入经纬度打印地区
public void getAddress(final String Lat, final String Ing) {
//CoolWeatherApplication.getBaiduApptoken()中放的是baiduSDK申请到的AK值
String address = "http://api.map.baidu.com/geocoder?output=json&location="
+ Lat + "," + Ing + "&key=" + CoolWeatherApplication.getBaiduApptoken();
HTTpUtil.sendOkHttpRequest(address, new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(CoolWeatherApplication.getContext(), "获取地区失败", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
String re = response.body().string();
final GetLocationPlace locationPlace = Utility.handlePlaceResponse(re);
runOnUiThread(new Runnable() {
@Override
public void run() {
if(locationPlace==null){
Toast.makeText(CoolWeatherApplication.getContext(), "获取地区失败", Toast.LENGTH_SHORT).show();
return;
}
String placeName = locationPlace.result.formatted_address;
Log.d("MainActivity",placeName);
}
});
}
});
}