基于高德地图实现融云位置共享功能(Android篇)


效果预览:

室内导航位置共享Java实现代码 导航共享位置怎样操作_高德地图


室内导航位置共享Java实现代码 导航共享位置怎样操作_android_02


室内导航位置共享Java实现代码 导航共享位置怎样操作_融云_03

开发准备:

1: 登录 融云开发者账号,提交 server 平台工单申请开通 实时位置共享功能。工单回复开通成功后、 2 小时生效。

2: 注册高德地图账号、申请成为开发者。获取高德地图相关 key 和 jar 包

室内导航位置共享Java实现代码 导航共享位置怎样操作_android_04

3: Android 工程当中配置自己获取的 高德地图的 key.

室内导航位置共享Java实现代码 导航共享位置怎样操作_室内导航位置共享Java实现代码_05


注: 此处需要配置自己的 高德地图 key


code:

核心类: RealTimeLocationInputProvider
RealTimeLocationMessageProvider
LocationMapActivity
RealTimeLocationActivity
BasicMapActivity 抽象类

RealTimeLocationActivity 继承自 LocationMapActivity 继承自
BasicMapActivity

此类代码可以在 demo 的 message provider 包下 copy 到
需要注意的是 RealTimeLocationInputProvider, 继承自 LocationInputProvider(此类功用是发送当前位置的静态图给对方)。
如果你没有开通 位置共享功能 的服务 他就通不过第一个 if 判断

RealTimeLocationConstant.RealTimeLocationErrorCode errorCode = RongIMClient.getInstance().getRealTimeLocation(getCurrentConversation().getConversationType(), getCurrentConversation().getTargetId());

        if (errorCode != null && errorCode != RealTimeLocationConstant.RealTimeLocationErrorCode.RC_REAL_TIME_LOCATION_CONVERSATION_NOT_SUPPORT) {//服务端未开通

然后他就会去调用父类的发送位置的方法 ,也就是 LocationInputProvider 。需要注意会话类型,位置共享目前只支持单聊 和 讨论组的会话类型

核心接口:
RongIMClient.RealTimeLocationListener
目前 demo 是在 ConversationActivity 类中实现这个接口

public interface RealTimeLocationListener {
        void onStatusChange(RealTimeLocationStatus status);

        void onReceiveLocation(double latitude, double longitude, String userId);

        void onParticipantsJoin(String userId);

        void onParticipantsQuit(String userId);

        void onError(RealTimeLocationErrorCode errorCode);
    }

RealTimeLocationActivity 中的

private void addUserInfoToScrollView(final String userId) {


        DemoContext.getInstance().getDemoApi().getUserInfo(userId, new DemoApi.GetUserInfoListener() {

            @Override
            public void onSuccess(final UserInfo userInfo) {

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        horizontalScrollView.addUserToView(userInfo);
                        setParticipantTextView(-1);
                    }
                });

            }

            @Override
            public void onError(String userId, BaseException e) {

            }
        });
    }

   public void onEventMainThread(final RongEvent.RealTimeLocationReceiveEvent event) {
        String userId = event.getUserId();

        DemoContext.getInstance().getDemoApi().getUserInfo(userId, new DemoApi.GetUserInfoListener() {

            @Override
            public void onSuccess(final UserInfo userInfo) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        moveMarker(new LatLng(event.getLatitude(), event.getLongitude()), userInfo);
                    }
                });
            }

            @Override
            public void onError(String userId, BaseException e) {

            }
        });
    }

请求获取用户信息部分 需要换成自己的 网络请求 或者 缓存信息

经纬度的获取:

LocationMapActivity 中

@Override
    public void onLocationChanged(AMapLocation amapLocation) {
        if (amapLocation != null && amapLocation.getAMapException().getErrorCode() == 0) {
            //获取位置信息
            Double geoLat = amapLocation.getLatitude();
            Double geoLng = amapLocation.getLongitude();

            RongIMClient.getInstance().updateRealTimeLocationStatus(conversationType, targetId, geoLat, geoLng);
        }
    }

如果进入界面 一直定位在北京中心 你当在此处监听你的经纬度有没有成功获取到,如果经纬度没有获取到可能是因为高德地图的 appkey 或者 keystore 没有配置 (keystore 很重要 与 高德 appkey 必须是对应的 否则无法获取到 经纬度)


key 的配置: key 的值 从高德地图获取 此处只是 demo 的示例

室内导航位置共享Java实现代码 导航共享位置怎样操作_android_06


Use:

使用在会话界面 + 号扩展功能中使用:

InputProvider.ExtendProvider[] singleProvider = {
                new ImageInputProvider(RongContext.getInstance()),
                new CameraInputProvider(RongContext.getInstance()),//相机
                new RealTimeLocationInputProvider(RongContext.getInstance()),//带位置共享的地理位置
//                new VoIPInputProvider(RongContext.getInstance()),// 语音通话
        };

        InputProvider.ExtendProvider[] muiltiProvider = {
                new ImageInputProvider(RongContext.getInstance()),
                new CameraInputProvider(RongContext.getInstance()),//相机
                new LocationInputProvider(RongContext.getInstance()),//地理位置
        };

        RongIM.getInstance().resetInputExtensionProvider(Conversation.ConversationType.PRIVATE, singleProvider);
        RongIM.getInstance().resetInputExtensionProvider(Conversation.ConversationType.DISCUSSION, muiltiProvider);
        RongIM.getInstance().resetInputExtensionProvider(Conversation.ConversationType.CUSTOMER_SERVICE, muiltiProvider);
        RongIM.getInstance().resetInputExtensionProvider(Conversation.ConversationType.GROUP, muiltiProvider);

室内导航位置共享Java实现代码 导航共享位置怎样操作_IM_07


至此 Android Kit 位置共享集成实现完毕

Lib 使用:

kit 开发者无需参考下面文章

如果 lib sdk 开发者也需要使用位置共享,需要自己来实现所有的 UI 界面。lib 提供了 相关的位置共享的实现接口如下

/**
     * 获取 RealTimeLocation 实例,每发起一次位置共享业务,就要获取一个实例。
     * 如果获取实例失败,返回 error code,对应具体的失败信息。
     * 使用时,每次进入会话,获取该会话对应的实例,以此判断位置共享业务是否可用或者正在进行中。
     * 如果返回成功,使用者可以设置监听,发起位置共享。
     * 如果返回正在进行中,则是对方已发起位置共享,使用者可以设置监听,加入。
     * 如果返回其他失败信息,使用者可以据此做出相应的提示。
     *
     * @param conversationType 发起位置共享的所在会话的会话类型。
     * @param targetId         发起位置共享的 target id。
     * @return 是否获取实例成功。
     */
    public RealTimeLocationErrorCode getRealTimeLocation(Conversation.ConversationType conversationType, String targetId) {
        if (sS == null)
            throw new RuntimeException("RongIMClient 尚未初始化!");

        if (mLibHandler == null) {
            return RealTimeLocationErrorCode.RC_REAL_TIME_LOCATION_NOT_INIT;
        }

        if (conversationType == null || targetId == null) {
            RLog.e(this, "getRealTimeLocation", "Type or id is null!");
            return null;
        }

        int code = -1;
        try {
            code = mLibHandler.setupRealTimeLocation(conversationType.getValue(), targetId);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return RealTimeLocationErrorCode.valueOf(code);
    }

    /**
     * 发起位置共享。
     *
     * @param conversationType 发起位置共享的会话类型。
     * @param targetId         发起位置共享的 targetId。
     */
    public RealTimeLocationErrorCode startRealTimeLocation(final Conversation.ConversationType conversationType, final String targetId) {
        if (sS == null)
            throw new RuntimeException("RongIMClient 尚未初始化!");

        if (mLibHandler == null) {
            return RealTimeLocationErrorCode.RC_REAL_TIME_LOCATION_NOT_INIT;
        }

        if (conversationType == null || targetId == null) {
            RLog.e(this, "startRealTimeLocation", "Type or id is null!");
            return null;
        }

        int code = -1;
        try {
            code = mLibHandler.startRealTimeLocation(conversationType.getValue(), targetId);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return RealTimeLocationErrorCode.valueOf(code);
    }

    /**
     * 加入位置共享。
     *
     * @param conversationType 位置共享的会话类型。
     * @param targetId         位置共享的 targetId。
     */
    public RealTimeLocationErrorCode joinRealTimeLocation(final Conversation.ConversationType conversationType, final String targetId) {
        if (sS == null)
            throw new RuntimeException("RongIMClient 尚未初始化!");

        if (mLibHandler == null) {
            return RealTimeLocationErrorCode.RC_REAL_TIME_LOCATION_NOT_INIT;
        }

        if (conversationType == null || targetId == null) {
            RLog.e(this, "joinRealTimeLocation", "Type or id is null!");
            return null;
        }

        int code = -1;
        try {
            code = mLibHandler.joinRealTimeLocation(conversationType.getValue(), targetId);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return RealTimeLocationErrorCode.valueOf(code);
    }

    /**
     * 退出位置共享。
     *
     * @param conversationType 位置共享的会话类型。
     * @param targetId         位置共享的 targetId。
     */
    public void quitRealTimeLocation(final Conversation.ConversationType conversationType, final String targetId) {
        if (sS == null)
            throw new RuntimeException("RongIMClient 尚未初始化!");

        if (conversationType == null || targetId == null) {
            RLog.e(this, "quitRealTimeLocation", "Type or id is null!");
            return;
        }

        mWorkHandler.post(new Runnable() {
            @Override
            public void run() {
                if (mLibHandler == null) {
                    return;
                }
                try {
                    mLibHandler.quitRealTimeLocation(conversationType.getValue(), targetId);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 获取参与该位置共享的所有成员。
     *
     * @param conversationType 位置共享的会话类型。
     * @param targetId         位置共享的 targetId。
     * @return 参与成员 id 列表。
     */
    public List<String> getRealTimeLocationParticipants(Conversation.ConversationType conversationType, String targetId) {
        if (sS == null)
            throw new RuntimeException("RongIMClient 尚未初始化!");

        if (mLibHandler == null) {
            return null;
        }

        if (conversationType == null || targetId == null) {
            RLog.e(this, "getRealTimeLocationParticipants", "Type or id is null!");
            return null;
        }

        List<String> list = null;
        try {
            list = mLibHandler.getRealTimeLocationParticipants(conversationType.getValue(), targetId);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return list;
    }


    /**
     * 获取位置共享状态。
     *
     * @param conversationType 位置共享的会话类型。
     * @param targetId         位置共享的 targetId。
     * @return 正在进行的位置共享状态。
     */
    public RealTimeLocationStatus getRealTimeLocationCurrentState(Conversation.ConversationType conversationType, String targetId) {
        if (sS == null)
            throw new RuntimeException("RongIMClient 尚未初始化!");

        if (mLibHandler == null) {
            return null;
        }

        if (conversationType == null || targetId == null) {
            RLog.e(this, "getRealTimeLocationCurrentState", "Type or id is null!");
            return null;
        }

        int state = 0;
        try {
            state = mLibHandler.getRealTimeLocationCurrentState(conversationType.getValue(), targetId);
        } catch (RemoteException e) {
            e.printStackTrace();
        }

        return RealTimeLocationStatus.valueOf(state);
    }

    /**
     * 添加位置共享观察者。
     *
     * @param conversationType 位置共享的会话类型。
     * @param targetId         位置共享的 targetId。
     * @param listener         位置共享监听。
     */
    public void addRealTimeLocationListener(final Conversation.ConversationType conversationType, final String targetId, final RealTimeLocationListener listener) {

        if (sS == null)
            throw new RuntimeException("RongIMClient 尚未初始化!");

        if (conversationType == null || targetId == null) {
            RLog.e(this, "addRealTimeLocationListener", "Type or id is null!");
            return;
        }

        mWorkHandler.post(new Runnable() {
            @Override
            public void run() {
                if (mLibHandler == null) {
                    return;
                }
                try {
                    mLibHandler.addRealTimeLocationListener(conversationType.getValue(), targetId, new IRealTimeLocationListener.Stub() {
                        @Override
                        public void onStatusChange(final int status) {
                            if (listener != null) {
                                mHandler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        listener.onStatusChange(RealTimeLocationStatus.valueOf(status));
                                    }
                                });
                            }
                        }

                        @Override
                        public void onReceiveLocation(final double latitude, final double longitude, final String userId) {
                            if (listener != null) {
                                mHandler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        listener.onReceiveLocation(latitude, longitude, userId);
                                    }
                                });
                            }
                        }

                        @Override
                        public void onParticipantsJoin(final String userId) {
                            if (listener != null) {
                                mHandler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        listener.onParticipantsJoin(userId);
                                    }
                                });
                            }
                        }

                        @Override
                        public void onParticipantsQuit(final String userId) {
                            if (listener != null) {
                                mHandler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        listener.onParticipantsQuit(userId);
                                    }
                                });
                            }
                        }

                        @Override
                        public void onError(final int errorCode) {
                            if (listener != null) {
                                mHandler.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        listener.onError(RealTimeLocationErrorCode.valueOf(errorCode));
                                    }
                                });
                            }
                        }
                    });
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 使用者调用此方法更新坐标位置。
     *
     * @param conversationType 位置共享的会话类型。
     * @param targetId         位置共享的会话 targetId。
     * @param latitude         维度
     * @param longitude        经度
     */
    public void updateRealTimeLocationStatus(Conversation.ConversationType conversationType,
                                             String targetId,
                                             double latitude,
                                             double longitude) {

        if (sS == null)
            throw new RuntimeException("RongIMClient 尚未初始化!");

        RLog.d(this, "updateRealTimeLocationStatus", "latitude=" + latitude);
        if (conversationType == null || targetId == null) {
            RLog.e(this, "updateRealTimeLocationStatus", "Type or id is null!");
            return;
        }

        if (mLibHandler != null) {
            try {
                mLibHandler.updateRealTimeLocationStatus(conversationType.getValue(), targetId, latitude, longitude);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 实时位置共享监听。
     */
    public interface RealTimeLocationListener {
        /**
         * 位置共享状态发生改变。
         *
         * @param status 空闲、加入、退出、建立连接等状态
         */
        void onStatusChange(RealTimeLocationStatus status);

        /**
         * 接收到位置共享信息。
         *
         * @param latitude  维度
         * @param longitude 经度
         * @param userId    发送者 id
         */
        void onReceiveLocation(double latitude, double longitude, String userId);

        /**
         * 对方加入位置共享。
         *
         * @param userId 加入者 id
         */
        void onParticipantsJoin(String userId);

        /**
         * 对方退出位置共享
         *
         * @param userId 退出者 id
         */
        void onParticipantsQuit(String userId);

        /**
         * 位置共享过程出现错误。
         *
         * @param errorCode 错误码
         */
        void onError(RealTimeLocationErrorCode errorCode);
    }

接口的使用方式可以参考 上述文档注释 和 demo 中 kit 层如何调用 lib 层这几个接口