如何基于百度地图实现融云 SDK 2.8.0+ 发送地理位置


            
2016-11-30 10:06 | Android

回答:

集成前准备

- 注册百度地图开放平台,可能需要审核开发者身份

- 创建 Android 应用, 生成 sha1 码获取百度地图 appkey

- 下载百度地图 SDK、 Demo、 Doc


集成代码

集成前需要将百度相关的 jar so 文件 以及 manifest 中需要配置的服务 和 appkey 都配置好,还需要在 application 中调用百度地图的初始化方法。

SDKInitializer.initialize(getApplicationContext());

android_initialize.png

集成前建议把融云 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&center="+ 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 {
    @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;
    }
}
 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

您认为此回答对您有帮助?

共有 4 位开发者认为此问题有帮助

我对此仍有疑问!继续追问