融云 sdk 2.8.0+ 内置的高德地图的发送位置。但是百度地图在地图市场占有率也是相当高的。为了满足使用百度地图的开发者,本篇文档对如何在 sdk 2.8.0 以上实现百度地图发送地理位置消息做讲解。
效果图
集成前准备
- 注册百度地图开放平台,可能需要审核开发者身份
- 创建 Android 应用, 生成 sha1 码获取百度地图 appkey
- 下载百度地图 SDK、 Demo、 Doc
Code
集成前需要将百度相关的 jar so 文件 以及 manifest 中需要配置的服务 和 appkey 都配置好,还需要在 application 中调用百度地图的初始化方法。
SDKInitializer.initialize(getApplicationContext());
集成前建议把 融云 sdk 2.8.0+ Extension 文档 通读,这样对概念理解 和 后面集成都有很大的帮助。
BaiDuLocationPlugin
public class BaiDuLocationPlugin implements IPluginModule {
private Conversation.ConversationType conversationType;
private String targetId;
@Override
public Drawable obtainDrawable(Context context) {
//设置插件 Plugin 图标
return context.getResources().getDrawable(R.drawable.rc_ext_plugin_location_selector);
}
@Override
public String obtainTitle(Context context) {
//设置插件 Plugin 展示文字
return "百度地图";
}
@Override
public void onClick(final Fragment currentFragment, RongExtension extension) {
//示例获取 会话类型、targetId、Context,此处可根据产品需求自定义逻辑,如:开启新的 Activity 等。
conversationType = extension.getConversationType();
targetId = extension.getTargetId();
//只有通过 extension 中的 startActivityForPluginResult 才会返回到本类中的 onActivityResult
extension.startActivityForPluginResult(new Intent(currentFragment.getActivity(),BaiDuLocationActivity.class),5, this);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
double latitude = data.getDoubleExtra("latitude",0.00);
double longitude = data.getDoubleExtra("longitude",0.00);
String address = data.getStringExtra("address");
String uri = data.getStringExtra("locuri");
LocationMessage locationMessage = LocationMessage.obtain(latitude,longitude,address, Uri.parse(uri));
RongIM.getInstance().sendLocationMessage(Message.obtain(targetId, conversationType, locationMessage), null, null, null);
}
}
}
此类是一个关键类,包含了唤起地图定位的 Activity ,和 onActivityResult 返回相关经纬度数据后的发送地理位置消息逻辑,请通读上面类 和 类中的注释。(参考上面 Plugin 实现可以不用理会 融云 sdk 内部接口 地理位置提供者 )
BaiDuLocationActivity
此类是地图展示的 activity 类,展示成什么逻辑由开发者自己定义。但是最少需要获取到给 BaiDuLocationPlugin 的四个参数为: 纬度,经度,地图的 uri,和位置信息的 String。
public class BaiDuLocationActivity extends BaseActivity{
public static final int RESULT_CODE = 6;
MapView mMapView;
BaiduMap baiduMap;
private double longitude;
private double latitude;
LatLng mLoactionLatLng;
private String address;
LocationClient locationClient;
LocationMessage mMsg;
boolean isFirstLoc = true;
Point mCenterPoint;
GeoCoder mGeoCoder;
List<PoiInfo> mInfoList;
PoiInfo mCurentInfo;
ListView Maplistview;
PlaceListAdapter customListAdpter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_location);
initview();
getimgxy();
}
private void initview() {
Button mRightButton = getHeadRightButton();
mRightButton.setBackground(getResources().getDrawable(R.drawable.icon1_menu));
Maplistview = (ListView) findViewById(R.id.mymapListView);
setTitle("地理位置");
mRightButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri = Uri.parse("http://api.map.baidu.com/staticimage?width=300&height=200¢er="+ longitude + "," + latitude + "&zoom=17&markers=" + longitude + "," + latitude + "&markerStyles=m,A");
Intent intent = new Intent();
intent.putExtra("latitude", latitude);
intent.putExtra("longitude", longitude);
intent.putExtra("address",address);
intent.putExtra("locuri",uri.toString());
setResult(RESULT_CODE , intent);
finish();
}
});
mMapView = (MapView) findViewById(R.id.bmapView);
mMapView.showZoomControls(false);
baiduMap = mMapView.getMap();
MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(17.0f);
baiduMap.setMapStatus(msu);
//开启定位图层
baiduMap.setMyLocationEnabled(true);
baiduMap.setOnMapTouchListener(touchListener);
try {
if (getIntent().hasExtra("location")) {
mMsg = getIntent().getParcelableExtra("location");
}
if (mMsg != null) {
Maplistview.setVisibility(View.GONE);
locationClient = new LocationClient(getApplicationContext()); // 实例化LocationClient类
MyLocationData locData = new MyLocationData.Builder()
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(100).latitude(mMsg.getLat())
.longitude(mMsg.getLng()).build();
baiduMap.setMyLocationData(locData); //设置定位数据
mLoactionLatLng = new LatLng(mMsg.getLat(),
mMsg.getLng());
MapStatusUpdate u = MapStatusUpdateFactory.newLatLngZoom(mLoactionLatLng, 16); //设置地图中心点以及缩放级别
baiduMap.animateMapStatus(u);
} else {
locationClient = new LocationClient(getApplicationContext()); // 实例化LocationClient类
locationClient.registerLocationListener(myListener); // 注册监听函数
this.setLocationOption(); //设置定位参数
locationClient.start(); // 开始定位
}
} catch (Exception e) {
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
mMapView.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
//在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
mMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
//在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
mMapView.onPause();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
locationClient.stop();
Log.d("stop", "定位关闭");
finish();
}
return false;
}
/**
* 设置定位参数
*/
private void setLocationOption() {
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打开GPS
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);// 设置定位模式
option.setCoorType("bd09ll"); // 返回的定位结果是百度经纬度,默认值gcj02
option.setScanSpan(5000); // 设置发起定位请求的间隔时间为5000ms
option.setIsNeedAddress(true); // 返回的定位结果包含地址信息
option.setNeedDeviceDirect(true); // 返回的定位结果包含手机机头的方向
locationClient.setLocOption(option);
}
public BDLocationListener myListener = new BDLocationListener() {
@Override
public void onReceiveLocation(BDLocation location) {
// map view 销毁后不在处理新接收的位置
if (location == null || mMapView == null)
return;
latitude = location.getLatitude();
longitude = location.getLongitude();
address = location.getAddrStr();
MyLocationData locData = new MyLocationData.Builder()
/*.accuracy(location.getRadius())*/
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(100).latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
baiduMap.setMyLocationData(locData); //设置定位数据
if (isFirstLoc) {
isFirstLoc = false;
mLoactionLatLng = new LatLng(location.getLatitude(),
location.getLongitude());
MapStatusUpdate u = MapStatusUpdateFactory.newLatLngZoom(mLoactionLatLng, 20);//设置地图中心点以及缩放级别
baiduMap.animateMapStatus(u);
}
// 获取当前MapView中心屏幕坐标对应的地理坐标
LatLng currentLatLng;
currentLatLng = baiduMap.getProjection().fromScreenLocation(
mCenterPoint);
System.out.println("----" + mCenterPoint.x);
System.out.println("----" + currentLatLng.latitude);
// 发起反地理编码检索
mGeoCoder.reverseGeoCode((new ReverseGeoCodeOption())
.location(currentLatLng));
}
};
/**
* 初始化地图物理坐标
*/
private void getimgxy() {
// 初始化POI信息列表
mInfoList = new ArrayList<PoiInfo>();
mCenterPoint = baiduMap.getMapStatus().targetScreen;
mLoactionLatLng = baiduMap.getMapStatus().target;
// 地理编码
mGeoCoder = GeoCoder.newInstance();
mGeoCoder.setOnGetGeoCodeResultListener(GeoListener);
customListAdpter = new PlaceListAdapter(getLayoutInflater(), mInfoList);
Maplistview.setAdapter(customListAdpter);
Maplistview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
customListAdpter.clearSelection(i);
customListAdpter.notifyDataSetChanged();
locationClient.stop();
baiduMap.clear();
PoiInfo info = (PoiInfo) customListAdpter.getItem(i);
LatLng la = info.location;
latitude = la.latitude;
longitude = la.longitude;
address = info.address;
MyLocationData locData = new MyLocationData.Builder()
/*.accuracy(location.getRadius())*/
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(100).latitude(la.latitude)
.longitude(la.longitude).build();
baiduMap.setMyLocationData(locData);
//设置定位数据
mLoactionLatLng = new LatLng(la.latitude,
la.longitude);
MapStatusUpdate u = MapStatusUpdateFactory.newLatLngZoom(mLoactionLatLng, 20); //设置地图中心点以及缩放级别
baiduMap.animateMapStatus(u);
}
});
}
// 地理编码监听器
OnGetGeoCoderResultListener GeoListener = new OnGetGeoCoderResultListener() {
public void onGetGeoCodeResult(GeoCodeResult result) {
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
// 没有检索到结果
}
// 获取地理编码结果
}
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
// 没有找到检索结果
}
// 获取反向地理编码结果
else {
// 当前位置信息
mCurentInfo = new PoiInfo();
mCurentInfo.address = result.getAddress();
mCurentInfo.location = result.getLocation();
mCurentInfo.name = "[位置]";
mInfoList.clear();
mInfoList.add(mCurentInfo);
// 将周边信息加入表
if (result.getPoiList() != null) {
mInfoList.addAll(result.getPoiList());
}
// 通知适配数据已改变
customListAdpter.notifyDataSetChanged();
/* mLoadBar.setVisibility(View.GONE);*/
}
}
};
// 地图触摸事件监听器
BaiduMap.OnMapTouchListener touchListener = new BaiduMap.OnMapTouchListener() {
@Override
public void onTouch(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (mCenterPoint == null) {
return;
}
// 获取当前MapView中心屏幕坐标对应的地理坐标
LatLng currentLatLng;
currentLatLng = baiduMap.getProjection().fromScreenLocation(
mCenterPoint);
System.out.println("----" + mCenterPoint.x);
System.out.println("----" + currentLatLng.latitude);
// 发起反地理编码检索
mGeoCoder.reverseGeoCode((new ReverseGeoCodeOption())
.location(currentLatLng));
}
}
};
}
开发者可参考上面代码,但是由于里面基本全是百度地图的 API 和 接口,如有遇到地图相关问题。本人和本篇 blog 对百度地图不做解释
调用代码
调用代码是演示如何把写好的百度地图的 Plugin 展示在 +号扩展区域中
public class SampleExtensionModule extends DefaultExtensionModule {
private EditText mEditText;
@Override
public List<IPluginModule> getPluginModules(Conversation.ConversationType conversationType) {
// super.getPluginModules(conversationType); 如果需要对红包进行排序可从父类中的 getPluginModules 集合中过滤取出 JrmfExtensionModule
List<IPluginModule> pluginModuleList = new ArrayList<>();
pluginModuleList.add(new BaiDuLocationPlugin());
pluginModuleList.add(new ImagePlugin());
// 此时扩展区域的展示顺序应该为 : 百度地图、图片、红包
return pluginModuleList;
}
@Override
public void onAttachedToExtension(RongExtension extension) {
mEditText = extension.getInputEditText();
}
@Override
public void onDetachedFromExtension() {
mEditText = null;
}
@Override
public List<IEmoticonTab> getEmoticonTabs() {
return super.getEmoticonTabs();
}
}
List<IExtensionModule> moduleList = RongExtensionManager.getInstance().getExtensionModules();
IExtensionModule defaultModule = null;
if (moduleList != null) {
for (IExtensionModule module : moduleList) {
if (module instanceof DefaultExtensionModule) {
defaultModule = module;
break;
}
}
if (defaultModule != null) {
RongExtensionManager.getInstance().unregisterExtensionModule(defaultModule);
// RongExtensionManager.getInstance().registerExtensionModule(new SealExtensionModule());
RongExtensionManager.getInstance().registerExtensionModule(new SampleExtensionModule());
}
}
参考资料
http://blog.csdn.net/qq_19986309/article/details/53302350
https://github.com/AnOneTable/CanonHouse