先看看demo效果
效果
简介
前段时间写即时聊天,其中有一个功能是发送定位功能,所以就在网上看了一些视频和博客,实现发送定位的功能,第三方的东西都比较简单,直接拿来用就可以了,你不用知道他内部实现的原理,具体步骤如下
开发前准备
和所有的第三方集成SDK一样,首先当然是去官网去注册,百度地图官网:http://lbsyun.baidu.com/
拿到密钥:AppKey:http://lbsyun.baidu.com/apiconsole/key
申请密钥的步骤具体在:http://lbsyun.baidu.com/index.php?title=android-locsdk/guide/key
下载第三方Jar包和一些SO文件:http://lbsyun.baidu.com/index.php?title=android-locsdk/geosdk-android-download
这些在我前面的讲第三方集成SharedSDK的时候的步骤差不多,这里就不在详细讲解了
集成到项目中
将下载的jar包复制到libs文件夹下,在main文件夹下创建一个jniLibs文件夹,把解压出来的so文件都复制进去:
配置环境
使用eclipse开发的开发者,只需要将SO的文件夹放到libs下即可;使用AndroidStutio的开发者除了上述操作,还需要在build.gradle中配置SO的使用,如下所示:
开发者如果开发的是系统应用,则只在工程中配置SO还是不够的,还需要手动把对应架构的SO拷贝到/system/lib下,如果是64位系统的话需要将64位的SO拷贝到/sytem/lib64下。
注意:每次新版本的定位SDK,开发者除了要更新JAR包之外,也要注意一下SO有无更新,如果SO名称不一样了,也要及时替换老的SO版本,不然会导致定位失败!
设置AndroidManifest.xml
在application标签中声明service组件,每个app拥有自己单独的定位service
【重要提醒】
定位SDKv3.1版本之后,以下权限已不需要,请取消声明,否则将由于Android 5.0多帐户系统加强权限管理而导致应用安装失败。 <uses-permission android:name="android.permission.BAIDU_LOCATION_SERVICE"></uses-permission>
声明使用权限
设置AcessKey
SDK4.2及之后版本需要在Mainfest.xml设置Accesskey,设置有误会引起定位和地理围栏服务不能正常使用,必须进行Accesskey的正确设置。
设置AccessKey,在application标签中加入
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.duanlian.baidumapdemo">
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<!-- 这个权限用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 这个权限用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_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" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="DRVOPN5q7eKZhsYmwnBNa0gLkGqahdeo" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MapActivity"/>
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" >
</service>
</application>
</manifest>
代码中的具体实现
初始化SDK
初始化SDK一般都是在Application中,因为程序运行开始首先运行的就是Applicaition,所以我们创建一个MyApplication继承Application,在里面重写OnCreate方法,在OnCreate方法里面初始化SDK,具体如下:
package com.duanlian.baidumapdemo;
import android.app.Application;
import com.baidu.mapapi.SDKInitializer;
/**
* 初始化sdk
*/
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
SDKInitializer.initialize(this);
}
}
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
MainActivity.java
MainActivity布局文件
MainActivity的布局文件里面只有一个Button和一个TextView,Button用来点击跳转到定位的页面,TextView用来显示定位得到的精度纬度和具体地址,布局文件具体如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.duanlian.baidumapdemo.MainActivity">
<TextView
android:id="@+id/address"
android:layout_width="match_parent"
android:layout_height="100dp"/>
<Button
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="location"
android:textSize="30sp"
android:text="开始定位" />
</RelativeLayout>
MainActivity中代码
MainActivity中就只有一个跳转,和一个跳转回调得到的地址等数据,(跳转回调具体请看本人的博客:android数据传递(二)之activity带返回值的跳转,模拟登陆注册)具体如下:
package com.duanlian.baidumapdemo;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private TextView myAddress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myAddress = (TextView) findViewById(R.id.address);
}
public void location(View view){
//跳转到定位的activity
Intent intent = new Intent(MainActivity.this, MapActivity.class);
startActivityForResult(intent,1);
}
/**
* 回调方法拿到数据
* @param requestCode 请求码
* @param resultCode 结果码
* @param data 数据
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==1&&resultCode==RESULT_OK) {
myAddress.setText("维度:"+data.getStringExtra("getLatitude")+"\n"+"精度:"+data.getStringExtra("getLongitude")+"\n"+"地址:"+data.getStringExtra("getAddress"));
}
}
}
定位逻辑
布局文件
首先布局文件只有一个自定义的地图控件和一个发送定位的按钮:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.baidu.mapapi.map.MapView
android:id="@+id/bmapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
<Button
android:id="@+id/map_sendmap_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginTop="20dp"
android:onClick="sendMessage"
android:layout_marginRight="10dp"
android:text="发送定位"/>
</RelativeLayout>
定位具体代码
注释比较清楚了,就不一一解释了
package com.duanlian.baidumapdemo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
/**
* 地图定位
*/
public class MapActivity extends Activity {
// 定位相关
LocationClient mLocClient;
//定位监听
public MyLocationListenner myListener = new MyLocationListenner();
MapView mMapView = null;
BaiduMap mBaiduMap;
boolean isFirstLoc = true; // 是否首次定位
BDLocation mlocation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
//获取地图控件引用
mMapView = (MapView) findViewById(R.id.bmapView);
mBaiduMap = mMapView.getMap();
// 开启定位图层
mBaiduMap.setMyLocationEnabled(true);
// 定位初始化
mLocClient = new LocationClient(this);
mLocClient.registerLocationListener(myListener);
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打开gps
option.setCoorType("bd09ll"); // 设置坐标类型
option.setScanSpan(1000);
option.setAddrType("all");
mLocClient.setLocOption(option);
mLocClient.start();
}
/**
* 定位SDK监听函数
*/
public class MyLocationListenner implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
// map view 销毁后不在处理新接收的位置
if (location == null || mMapView == null) {
return;
}
mlocation = location;
MyLocationData locData = new MyLocationData.Builder()
.accuracy(mlocation.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(100).latitude(mlocation.getLatitude())
.longitude(mlocation.getLongitude()).build();
mBaiduMap.setMyLocationData(locData);
if (isFirstLoc) {
isFirstLoc = false;
LatLng ll = new LatLng(location.getLatitude(),
location.getLongitude());
MapStatus.Builder builder = new MapStatus.Builder();
builder.target(ll).zoom(18.0f);
mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
}
}
public void onReceivePoi(BDLocation poiLocation) {
}
}
@Override
protected void onPause() {
//在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
mMapView.onPause();
super.onPause();
}
@Override
protected void onResume() {
//在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
mMapView.onResume();
super.onResume();
}
@Override
protected void onDestroy() {
// 退出时销毁定位
mLocClient.stop();
// 关闭定位图层
mBaiduMap.setMyLocationEnabled(false);
mMapView.onDestroy();
mMapView = null;
super.onDestroy();
}
/**
* 发送按钮的点击事件
*/
public void sendMessage(View v) {
if (mlocation == null || mMapView == null) {
Toast.makeText(MapActivity.this, "点击了发送按钮", Toast.LENGTH_SHORT).show();
return;
}
Intent intent = new Intent();
//纬度
intent.putExtra("getLatitude", mlocation.getLatitude()+"");
//经度
intent.putExtra("getLongitude", mlocation.getLongitude()+"");
//地址
intent.putExtra("getAddress", mlocation.getAddrStr());
setResult(RESULT_OK, intent);
finish();
}
}
这样定位功能就实现了,有不足之处,请指正,虚心听取
demo下载地址:https://github.com/dl10210950/BaiduMapDemo