首页 > 其他分享 >Linphone callState 电话状态的监听状态(一)

Linphone callState 电话状态的监听状态(一)

时间:2023-05-29 14:37:13浏览次数:31  
标签:状态 lc state callState State call param LinphoneCore Linphone


0. 阅读指南

因为粘贴的代码比较多, 阅读之前请先看目录.

如果对这篇文章有什么建议的话, 请在评论中指出. 尽量把文章写好点.

1. 说明

LinphoneService有个重要的机制, 就是通过注册LinphoneCoreListener的实例, 当Linphone的状态发声变化的时候, 会回调相应的方法. 然后linphone上层会做相应的处理.]

为了更好的分析整个linphone, 现在这个LinphoneCoreListener注册回调机制是怎么也躲不过去了.

用到的地方

Linphone callState 电话状态的监听状态(一)_监听状态

图2.1是通过Android studio进行查找addListener调用的地方, 说明了, 这些方法一旦实例化, 便注册了addListener(), 一旦linphone有变化, 这些类就做做出相应的处理.

2. 回调都需要什么

2.1 LinphoneCoreListener.java

代码

直接看注释, 我中文稍微翻译一下

package org.linphone.core;

import java.nio.ByteBuffer;


/**
 *
 *This interface holds all callbacks that the application should implement. None is mandatory.
 * 这个接口是接收回调, 但不是强制的.
 */
public interface LinphoneCoreListener {

    /**
     * @deprecated
     * Ask the application some authentication information
     **/
    @Deprecated
    void authInfoRequested(LinphoneCore lc, String realm, String username, String domain);

    /**
     * Ask the application some authentication information
     * 询问一下有什么验证信息
     * @param lc the LinphoneCore
     * @param authInfo a LinphoneAuthInfo pre-filled with username, realm and domain values as much as possible
     * @param method the type of authentication requested (HttpDigest, Tls, ...)
     **/
    void authenticationRequested(LinphoneCore lc, LinphoneAuthInfo authInfo, LinphoneCore.AuthMethod method);

    /**
     * Call stats notification
     */
    void callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats);

    /**
     * Reports that a new subscription request has been received and wait for a decision.
     *Status on this subscription request is notified by changing policy for this friend
     * 有新的注册请求
     *@param lc LinphoneCore
     *@param lf LinphoneFriend corresponding to the subscriber
     *@param url of the subscriber
     *
     */
    void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url);

    /**
     * Report status change for a friend previously added to LinphoneCore.
     * @param lc LinphoneCore
     * @param lf updated LinphoneFriend
     */
    void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf);

    /**
     * invoked when a new dtmf is received
     * @param lc    LinphoneCore
     * @param call  LinphoneCall involved in the dtmf sending
     * @param dtmf  value of the dtmf sent
     */
    void dtmfReceived(LinphoneCore lc, LinphoneCall call, int dtmf);

    /**
     *  Report Notified message received for this identity.
     *  @param lc LinphoneCore
     *  @param call LinphoneCall in case the notify is part of a dialog, may be null
     *  @param from LinphoneAddress the message comes from
     *  @param event String the raw body of the notify event.
     *
     */
    void notifyReceived(LinphoneCore lc, LinphoneCall call, LinphoneAddress from, byte[] event);

    /**
     * Notifies progress of a call transfer.
     * @param lc the LinphoneCore
     * @param call the call through which the transfer was sent.
     * @param new_call_state the state of the call resulting of the transfer, at the other party.
     **/
    void transferState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State new_call_state);

    /**
     * Notifies an incoming INFO message.
     * @param lc the LinphoneCore.
     * @param info the info message
     */
    void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info);

    /**
     * Notifies of subscription requests state changes, including new incoming subscriptions.
     * @param lc the LinphoneCore
     * @param ev LinphoneEvent object representing the subscription context.
     * @param state actual state of the subscription.
     */
    void subscriptionStateChanged(LinphoneCore lc, LinphoneEvent ev, SubscriptionState state);

    /**
     * Notifies about outgoing generic publish states.
     * @param lc the LinphoneCore
     * @param ev a LinphoneEvent representing the publish, typically created by {@link LinphoneCore#publish}
     * @param state the publish state
     */
    void publishStateChanged(LinphoneCore lc, LinphoneEvent ev, PublishState state);

    /**
     * Notifies the application that it should show up
     * @deprecated
     */
    @Deprecated
    void show(LinphoneCore lc);

    /**
     * Callback that notifies various events with human readable text.
     * @deprecated
     */
    @Deprecated
    void displayStatus(LinphoneCore lc,String message);

    /**
     * Callback to display a message to the user
     * @deprecated
     */
    @Deprecated
    void displayMessage(LinphoneCore lc,String message);

    /**
     * Callback to display a warning to the user
     * @deprecated
     */
    @Deprecated
    void displayWarning(LinphoneCore lc,String message);

    /**
     * Callback to be notified about the transfer progress.
     * @param lc the LinphoneCore
     * @param message the LinphoneChatMessage
     * @param content the LinphoneContent
     * @param progress percentage of the transfer done
     */
    void fileTransferProgressIndication(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, int progress);

    /**
     * Callback to be notified when new data has been received
     * @param lc the LinphoneCore
     * @param message the LinphoneChatMessage
     * @param content the LinphoneContent
     * @param buffer
     * @param size
     */
    void fileTransferRecv(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, byte[] buffer, int size);

    /**
     * Callback to be notified when new data needs to be sent
     * @param lc the LinphoneCore
     * @param message the LinphoneChatMessage
     * @param content the LinphoneContent
     * @param buffer
     * @param size
     * @return the number of bytes written into buffer
     */
    int fileTransferSend(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, ByteBuffer buffer, int size);

    /**
     * General State notification
     * @param state LinphoneCore.State
     */
    void globalState(LinphoneCore lc,LinphoneCore.GlobalState state, String message);

    /**
     * Registration state notification
     * */
    void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg, LinphoneCore.RegistrationState state, String smessage);

    /**
     * Notifies the changes about the remote provisioning step
     * @param lc the LinphoneCore
     * @param state the RemoteProvisioningState
     * @param message the error message if state == Failed
     */
    void configuringStatus(LinphoneCore lc, LinphoneCore.RemoteProvisioningState state, String message);

    /**
     * invoked when a new linphone chat message is received
     * 接收聊天信息
     * @param lc LinphoneCore
     * @param cr LinphoneChatRoom involved in this conversation. Can be be created by the framework in case the from is not present in any chat room.
     * @param message incoming linphone chat message message
     */
    void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message);

    /**
     * invoked when a new linphone chat message is received and we cannot decrypt this
     * @param lc LinphoneCore
     * @param cr LinphoneChatRoom involved in this conversation. Can be be created by the framework in case the from is not present in any chat room.
     * @param message incoming linphone chat message message
     */
    void messageReceivedUnableToDecrypted(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message);

    /** Call  State notification
     * @param state LinphoneCall.State
     */
    void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State state, String message);

    /**
     * Callback to display change in encryption state.
     * @param encrypted true if all streams of the call are encrypted
     * @param authenticationToken token like ZRTP SAS that may be displayed to user
     */
    void callEncryptionChanged(LinphoneCore lc, LinphoneCall call, boolean encrypted, String authenticationToken);

    /**
     * Notifies of an incoming NOTIFY received.
     * @param lc the linphoneCore
     * @param ev a LinphoneEvent representing the subscription context for which this notify belongs, or null if it is a NOTIFY out of of any subscription.
     * @param eventName the event name
     * @param content content of the NOTIFY request.
     */
    void notifyReceived(LinphoneCore lc, LinphoneEvent ev, String eventName, LinphoneContent content);

    /**
     * invoked when a composing notification is received
     * @param lc LinphoneCore
     * @param cr LinphoneChatRoom involved in the conversation.
     */
    void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr);

    /**
     * Invoked when echo cancalation calibration is completed
     * @param lc LinphoneCore
     * @param status
     * @param delay_ms echo delay
     * @param data
     */
    void ecCalibrationStatus(LinphoneCore lc, LinphoneCore.EcCalibratorStatus status, int delay_ms, Object data);

    /**
     * Callback prototype for reporting log collection upload progress indication.
     */
    void uploadProgressIndication(LinphoneCore lc, int offset, int total);

    /**
     * Callback prototype for reporting log collection upload state change.
     * @param lc LinphoneCore object
     * @param state The state of the log collection upload
     * @param info Additional information: error message in case of error state, URL of uploaded file in case of success.
     */
    void uploadStateChanged(LinphoneCore lc, LinphoneCore.LogCollectionUploadState state, String info);

    /**
     * Callback prototype for reporting LinphoneFriendList creation.
     * @param lc LinphoneCore object
     * @param list LinphoneFriendList object
     */
    void friendListCreated(LinphoneCore lc, LinphoneFriendList list);

    /**
     * Callback prototype for reporting LinphoneFriendList removal.
     * @param lc LinphoneCore object
     * @param list LinphoneFriendList object
     */
    void friendListRemoved(LinphoneCore lc, LinphoneFriendList list);
}

其中, 有个地方implements这个方法

LinphoneCoreListenerBase implements LinphoneCoreListener

目的是为了, 可以随意的继承想要的方法, 而不用全部实现.

说明

这个是回调的核心方法. 提供所有需要回调的方法.

2.2 LinphoneCall.java 电话的回调状态

代码

/**
     * Linphone call states
     *
     */
    static class State {

        static private Vector<State> values = new Vector<State>();
        private final int mValue;
        public final int value() {return mValue;}

        private final String mStringValue;
        /**
         * Idle
         */
        public final static State Idle = new State(0,"Idle");
        /**
         * Incoming call received.
         */
        public final static State IncomingReceived = new State(1,"IncomingReceived");
        /**
         * Outgoing call initialiazed.
         */
        public final static State OutgoingInit = new State(2,"OutgoingInit");
        /**
         * Outgoing call in progress. 
         */
        public final static State OutgoingProgress = new State(3,"OutgoingProgress");
        /**
         * Outgoing call ringing.
         */
        public final static State OutgoingRinging = new State(4,"OutgoingRinging");
        /**
         * Outgoing call early media
         */
        public final static State OutgoingEarlyMedia = new State(5,"OutgoingEarlyMedia");
        /**
         * Connected
         */
        public final static State Connected = new State(6,"Connected");
        /**
         * Streams running
         */
        public final static State StreamsRunning = new State(7,"StreamsRunning");
        /**
         * Pausing
         */
        public final static State Pausing = new State(8,"Pausing");
        /**
         * Paused
         */
        public final static State Paused = new State(9,"Paused");
        /**
         * Resuming
         */
        public final static State Resuming = new State(10,"Resuming");
        /**
         * Refered
         */
        public final static State Refered = new State(11,"Refered");
        /**
         * Error
         */
        public final static State Error = new State(12,"Error");
        /**
         * Call end
         */
        public final static State CallEnd = new State(13,"CallEnd");

        /**
         * Paused by remote
         */
        public final static State PausedByRemote = new State(14,"PausedByRemote");

        /**
         * The call's parameters are updated, used for example when video is asked by remote
         */
        public static final State CallUpdatedByRemote = new State(15, "UpdatedByRemote");

        /**
         * We are proposing early media to an incoming call
         */
        public static final State CallIncomingEarlyMedia = new State(16,"IncomingEarlyMedia");

        /**
         * We have initiated a call update. When the remote accepts the call update, state will move to StreamsRunning.
         */
        public static final State CallUpdating = new State(17, "Updating");

        /**
         * The call object is now released.
         */
        public static final State CallReleased = new State(18,"Released");

        /**
         * The call is updated by remote while not yet answered (SIP UPDATE in early dialog received)
         */
        public static final State CallEarlyUpdatedByRemote = new State(19,"EarlyUpdatedByRemote");

        /**
         * We are updating the call while not yet answered (SIP UPDATE in early dialog sent)
        **/
        public static final State CallEarlyUpdating = new State(20,"EarlyUpdating");

        private State(int value,String stringValue) {
            mValue = value;
            values.addElement(this);
            mStringValue=stringValue;
        }

        public static State fromInt(int value) {

            for (int i=0; i<values.size();i++) {
                State state = (State) values.elementAt(i);
                if (state.mValue == value) return state;
            }
            throw new RuntimeException("state not found ["+value+"]");
        }
        public String toString() {
            return mStringValue;
        }
    }

说明

这个方法中包含了所有电话的状态, 比如

  • IncomingReceived 接收来电
  • OutgoingInit 拨出电话
  • OutongingProgress 电话拨出中
  • OutgoingRinging 拨出响铃中
  • OutgoingEarlyMedia
  • Connected
  • StreamsRunning 接通中
  • Paused 暂停
  • Resuming
  • Refered
  • Error
  • CallEnd
  • PausedByRemote 被远方暂停
  • UpdatedByRemote
  • InconingEarlyMedia
  • Updating
  • Released
  • EarlyUpdatedByRemote
  • EarlyUpdating

等我看完了, 怎么有这么多方法.

2.3 LinphoneCore.GlobalState Global状态

代码

/**
     * linphone core states
     */
    static public class GlobalState {

        static private Vector<GlobalState> values = new Vector<GlobalState>();
        /**
         * Off
         */
        static public GlobalState GlobalOff = new GlobalState(0, "GlobalOff");
        /**
         * Startup
         */
        static public GlobalState GlobalStartup = new GlobalState(1, "GlobalStartup");
        /**
         * On
         */
        static public GlobalState GlobalOn = new GlobalState(2, "GlobalOn");
        /**
         * Shutdown
         */
        static public GlobalState GlobalShutdown = new GlobalState(3, "GlobalShutdown");
        /**
         * Configuring
         */
        static public GlobalState GlobalConfiguring = new GlobalState(4, "GlobalConfiguring");

说明

表示全局的状态

  • GlobalOff
  • GlobalStartup
  • GlobalOn
  • GlobalStudown
  • GlobalConfiguring

全局的一个状态

2.4 LinphoneCoreListenerBase.java

这个是实现所有LinphoneCoreListener方法, 目的是不用实现所有的方法, 而是有目的的实现其中的某个或某几个方法.

2.5 LinphoneChatMessage.State

代码

public static class State {
        static private Vector<State> values = new Vector<State>();
        private final int mValue;
        public final int value() {return mValue;}

        private final String mStringValue;
        /**
         * Initial state
         */
        public final static State Idle = new State(0,"Idle");
        /**
         * Delivery in progress
         */
        public final static State InProgress = new State(1,"InProgress");
        /**
         * Message succesffully delivered an acknoleged by remote end point
         */
        public final static State Delivered = new State(2,"Delivered");
        /**
         * Message was not delivered
         */
        public final static State NotDelivered = new State(3,"NotDelivered");
        /**
         * Message was received(and acknowledged) but cannot get file from server
         */
        public final static State FileTransferError = new State(4,"FileTransferError");
        /**
         * File transfer has been completed successfully.
         */
        public final static State FileTransferDone = new State(5,"FileTransferDone");
        /**
         * Message successfully delivered and acknowledged to destination
         */
        public final static State DeliveredToUser = new State(6,"DeliveredToUser");
        /**
         * Message displayed to the remote user
         */
        public final static State Displayed = new State(7,"Displayed");

        private State(int value,String stringValue) {
            mValue = value;
            values.addElement(this);
            mStringValue=stringValue;
        }

        public static State fromInt(int value) {

            for (int i=0; i<values.size();i++) {
                State state = (State) values.elementAt(i);
                if (state.mValue == value) return state;
            }
            throw new RuntimeException("state not found ["+value+"]");
        }
        public String toString() {
            return mStringValue;
        }
        public int toInt() {
            return mValue;
        }
    }

说明

主要是聊天中的一些状态

  • Idle
  • InProgress
  • Delivered
  • NotDelivered
  • FileTransferError
  • FileTransferDone
  • DeliveredToUser
  • Displayed

3. 逐一介绍

3.1 CallActivity.java

代码

mListener = new LinphoneCoreListenerBase() {
            @Override
            public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
                displayMissedChats(); // 从jni获取数据, 显示在界面上
            }

            @Override
            public void callState(LinphoneCore lc, final LinphoneCall call, LinphoneCall.State state, String message) {
                LinphoneUtils._log("CallActivity#Turn", "callState(" +
                        "LinphoneCore lc  " + lc +
                        ", final LinphoneCall call" + call +
                        ", LinphoneCall.State state" + state +
                        ", String message" + message +
                        ")");

                if (LinphoneManager.getLc().getCallsNb() == 0) {
                    finish();
                    return;
                }

                if (state == State.IncomingReceived) {
                    startIncomingCallActivity();
                    return;
                } else if (state == State.Paused || state == State.PausedByRemote || state == State.Pausing) {
                    LinphoneUtils._log("CallActivity", "} else if (state == State.Paused || state == State.PausedByRemote || state == State.Pausing) {");

                    if (LinphoneManager.getLc().getCurrentCall() != null) {
                        LinphoneUtils._log("CallActivity", "if (LinphoneManager.getLc().getCurrentCall() != null)   enabledVideoButton(false);");
                        enabledVideoButton(false);
                    }
                    if (isVideoEnabled(call)) {
                        LinphoneUtils._log("CallActivity", "if (isVideoEnabled(call))   showAudioView()");
                        showAudioView();
                    }
                } else if (state == State.Resuming) {
                    if (LinphonePreferences.instance().isVideoEnabled()) {
                        status.refreshStatusItems(call, isVideoEnabled(call));
                        if (call.getCurrentParamsCopy().getVideoEnabled()) {
                            showVideoView();
                        }
                    }
                    if (LinphoneManager.getLc().getCurrentCall() != null) {
                        enabledVideoButton(true);
                    }
                } else if (state == State.StreamsRunning) {
                    LinphoneUtils._log("CallActivity", "} else if (state == State.StreamsRunning) {");
                    switchVideo(isVideoEnabled(call));
                    enableAndRefreshInCallActions();

                    if (status != null) {
                        LinphoneUtils._log("CallActivity", "if (status != null) {");
                        videoProgress.setVisibility(View.GONE);
                        status.refreshStatusItems(call, isVideoEnabled(call));
                    } else {
                        LinphoneUtils._log("CallActivity", "if (status ===== null) {");
                    }
                } else if (state == State.CallUpdatedByRemote) {
                    LinphoneUtils._log("CallActivity", "} else if (state == State.CallUpdatedByRemote) {");
                    // If the correspondent proposes video while audio call
                    boolean videoEnabled = LinphonePreferences.instance().isVideoEnabled();
                    if (!videoEnabled) {
                        LinphoneUtils._log("CallActivity#Turn", "if (!videoEnabled)      acceptCallUpdate(false);");
                        acceptCallUpdate(false);
                    }

                    boolean remoteVideo = call.getRemoteParams().getVideoEnabled();
                    boolean localVideo = call.getCurrentParamsCopy().getVideoEnabled();
                    boolean autoAcceptCameraPolicy = LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests();
                    if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !LinphoneManager.getLc().isInConference()) {
                        showAcceptCallUpdateDialog();


                        createTimerForDialog(SECONDS_BEFORE_DENYING_CALL_UPDATE);
                    }
//                  else if (remoteVideo && !LinphoneManager.getLc().isInConference() && autoAcceptCameraPolicy) {
//                      mHandler.post(new Runnable() {
//                          @Override
//                          public void run() {
//                              acceptCallUpdate(true);
//                          }
//                      });
//                  }
                }

说明

在这个界面实际上就是管理接听话, 还有是否接受视频通话等.

何处调用

在LinphoneActivity开启的时候, 会对状态有个判断. 而LinphoneActivity是被LinphoneService调用的.

3.2 CallIncomingActivity.java

代码

mListener = new LinphoneCoreListenerBase() {
            @Override
            public void callState(LinphoneCore lc, LinphoneCall call, State state, String message) {
                LinphoneUtils._log("CallIncomingActivity", "callState(LinphoneCore lc    " + lc +
                        ", LinphoneCall call    " + call +
                        ", State state    " + state +
                        ", String message)    " + message +
                        "");
                if (call == mCall && State.CallEnd == state) {
                    finish();
                }
                if (state == State.StreamsRunning) {
                    // The following should not be needed except some devices need it (e.g. Galaxy S).
                    LinphoneManager.getLc().enableSpeaker(LinphoneManager.getLc().isSpeakerEnabled());
                }
            }
        };

说明

当有来电电话时, 调用此界面

何处调用

在CallActivity中, 有一个事件监听, 当收到IncomingReceived这个状态的时候调用.

3.3 CallOutgoingActivity.java

代码

mListener = new LinphoneCoreListenerBase() {
            @Override
            public void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State state, String message) {
                if (call == mCall && State.Connected == state) {
                    if (!LinphoneActivity.isInstanciated()) {
                        return;
                    }
                    LinphoneActivity.instance().startIncallActivity(mCall);
                    finish();
                    return;
                } else if (state == State.Error) {
                    // Convert LinphoneCore message for internalization
                    if (message != null && call.getErrorInfo().getReason() == Reason.Declined) {
                        displayCustomToast(getString(R.string.error_call_declined), Toast.LENGTH_SHORT);
                    } else if (message != null && call.getErrorInfo().getReason() == Reason.NotFound) {
                        displayCustomToast(getString(R.string.error_user_not_found), Toast.LENGTH_SHORT);
                    } else if (message != null && call.getErrorInfo().getReason() == Reason.Media) {
                        displayCustomToast(getString(R.string.error_incompatible_media), Toast.LENGTH_SHORT);
                    } else if (message != null && call.getErrorInfo().getReason() == Reason.Busy) {
                        displayCustomToast(getString(R.string.error_user_busy), Toast.LENGTH_SHORT);
                    } else if (message != null) {
                        displayCustomToast(getString(R.string.error_unknown) + " - " + message, Toast.LENGTH_SHORT);
                    }
                }

                if (LinphoneManager.getLc().getCallsNb() == 0) {
                    finish();
                    return;
                }
            }
        };

说明

类似CallIncomingActivity的调用方式, 只是逻辑流程相反而已.

何处调用

跟CallIncomingActivity的调用方式相同, 只是状态不同, 走的逻辑不相同.

3.4 ChatFragment.java

代码

mListener = new LinphoneCoreListenerBase(){
            @Override
            public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
                LinphoneAddress from = cr.getPeerAddress();
                if (from.asStringUriOnly().equals(sipUri)) {
                    LinphoneService.instance().removeMessageNotification();
                    cr.markAsRead();
                    LinphoneActivity.instance().updateMissedChatCount();
                    adapter.addMessage(cr.getHistory(1)[0]);

                    String externalBodyUrl = message.getExternalBodyUrl();
                    LinphoneContent fileTransferContent = message.getFileTransferInformation();
                    if (externalBodyUrl != null || fileTransferContent != null) {
                        LinphoneActivity.instance().checkAndRequestExternalStoragePermission();
                    }
                }
            }

            @Override
            public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom room) {
                if (chatRoom != null && room != null && chatRoom.getPeerAddress().asStringUriOnly().equals(room.getPeerAddress().asStringUriOnly())) {
                    remoteComposing.setVisibility(chatRoom.isRemoteComposing() ? View.VISIBLE : View.GONE);
                }
            }
        };

说明

主要是处理接收消息的逻辑.

3.5 ChatListFragment.java

代码

mListener = new LinphoneCoreListenerBase() {
            @Override
            public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
                refresh();
            }
        };

说明

更新消息列表

3.6 LinphoneActivity.java

代码

mListener = new LinphoneCoreListenerBase() {
            @Override
            public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
                displayMissedChats(getUnreadMessageCount());
            }

            @Override
            public void registrationState(LinphoneCore lc, LinphoneProxyConfig proxy, LinphoneCore.RegistrationState state, String smessage) {
                if (state.equals(RegistrationState.RegistrationCleared)) {
                    if (lc != null) {
                        LinphoneAuthInfo authInfo = lc.findAuthInfo(proxy.getIdentity(), proxy.getRealm(), proxy.getDomain());
                        if (authInfo != null)
                            lc.removeAuthInfo(authInfo);
                    }
                }

                refreshAccounts();

                if (getResources().getBoolean(R.bool.use_phone_number_validation)
                        && proxy.getDomain().equals(getString(R.string.default_domain))) {
                    if (state.equals(RegistrationState.RegistrationOk)) {
                        LinphoneManager.getInstance().isAccountWithAlias();
                    }
                }

                if (state.equals(RegistrationState.RegistrationFailed) && newProxyConfig) {
                    newProxyConfig = false;
                    if (proxy.getError() == Reason.BadCredentials) {
                        //displayCustomToast(getString(R.string.error_bad_credentials), Toast.LENGTH_LONG);
                    }
                    if (proxy.getError() == Reason.Unauthorized) {
                        displayCustomToast(getString(R.string.error_unauthorized), Toast.LENGTH_LONG);
                    }
                    if (proxy.getError() == Reason.IOError) {
                        displayCustomToast(getString(R.string.error_io_error), Toast.LENGTH_LONG);
                    }
                }
            }

            @Override
            public void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State state, String message) {
                LinphoneUtils._log("LinphoneActivity", "callState(" +
                        "LinphoneCore lc    " + lc +
                        ", LinphoneCall call    " + call +
                        ", LinphoneCall.State state    " + state +
                        ", String message    " + message +
                        ")");
                if (state == State.IncomingReceived) {
                    LinphoneUtils._log("LinphoneActivity", "startActivity(new Intent(LinphoneActivity.instance(), CallIncomingActivity.class));");
                    startActivity(new Intent(LinphoneActivity.instance(), CallIncomingActivity.class));
                } else if (state == State.OutgoingInit || state == State.OutgoingProgress) {
                    LinphoneUtils._log("LinphoneActivity", "startActivity(new Intent(LinphoneActivity.instance(), CallOutgoingActivity.class));");
                    startActivity(new Intent(LinphoneActivity.instance(), CallOutgoingActivity.class));
                } else if (state == State.CallEnd || state == State.Error || state == State.CallReleased) {
                    LinphoneUtils._log("LinphoneActivity", "resetClassicMenuLayoutAndGoBackToCallIfStillRunning();");
                    resetClassicMenuLayoutAndGoBackToCallIfStillRunning();
                }

                int missedCalls = LinphoneManager.getLc().getMissedCallsCount();
                displayMissedCalls(missedCalls);
            }
        };

说明

功能主界面, 主要是用来处理所有状态的分配, 比如跳转到图像管理界面CallActivity, 显示主界面, 拨打电话界面.

3.7 LinphoneService.java

代码

LinphoneManager.getLc().addListener(mListener = new LinphoneCoreListenerBase() {
            @Override
            public void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State state, String message) {
                LinphoneUtils._log("LinphoneService",
                        "callState(LinphoneCore lc  " + lc +
                                ", LinphoneCall call  " + call +
                                ", LinphoneCall.State state  " + state +
                                ", String message  " + message +
                                ")");

                if (instance == null) {
                    Log.i("Service not ready, discarding call state change to ", state.toString());
                    return;
                }

                if (state == LinphoneCall.State.IncomingReceived) {
                    onIncomingReceived();
                }

                if (state == State.CallEnd || state == State.CallReleased || state == State.Error) {
                    destroyOverlay();
                }

                if (state == State.CallEnd && call.getCallLog().getStatus() == CallStatus.Missed) {
                    int missedCallCount = LinphoneManager.getLcIfManagerNotDestroyedOrNull().getMissedCallsCount();
                    String body;
                    if (missedCallCount > 1) {
                        LinphoneService._log("missedCallCount > 1");
                        body = getString(R.string.missed_calls_notif_body).replace("%i", String.valueOf(missedCallCount));
                    } else {
                        LinphoneAddress address = call.getRemoteAddress();
                        LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(address);
                        LinphoneService._log("!!!!!!!(missedCallCount > 1)  , address = " + address + " , c = ");
                        if (c != null) {
                            body = c.getFullName();
                        } else {
                            body = address.getDisplayName();
                            if (body == null) {
                                body = address.asStringUriOnly();
                            }
                        }
                    }
                    Notification notif = Compatibility.createMissedCallNotification(instance, getString(R.string.missed_calls_notif_title), body, mMissedCallsNotifContentIntent);
                    notifyWrapper(MISSED_NOTIF_ID, notif);
                }

                if (state == State.StreamsRunning) {
                    // Workaround bug current call seems to be updated after state changed to streams running
                    if (getResources().getBoolean(R.bool.enable_call_notification))
                        refreshIncallIcon(call);
                } else {
                    if (getResources().getBoolean(R.bool.enable_call_notification))
                        refreshIncallIcon(LinphoneManager.getLc().getCurrentCall());
                }
            }

            @Override
            public void globalState(LinphoneCore lc, LinphoneCore.GlobalState state, String message) {
                if (state == GlobalState.GlobalOn && displayServiceNotification()) {
                    LinphoneService._log("globalState(LinphoneCore lc" +
                            ", LinphoneCore.GlobalState state  == " + state +
                            ", String message == " + message);
                    sendNotification(IC_LEVEL_ORANGE, R.string.notification_started);
                }
            }

            @Override
            public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg, LinphoneCore.RegistrationState state, String smessage) {
//              if (instance == null) {
//                  Log.i("Service not ready, discarding registration state change to ",state.toString());
//                  return;
//              }
                LinphoneService._log("LinphoneCore lc" +
                        ", LinphoneProxyConfig cfg  == " + cfg +
                        ", LinphoneCore.RegistrationState state == " + state +
                        ", String smessage == " + smessage);
                if (!mDisableRegistrationStatus) {
                    if (displayServiceNotification() && state == RegistrationState.RegistrationOk && LinphoneManager.getLc().getDefaultProxyConfig() != null && LinphoneManager.getLc().getDefaultProxyConfig().isRegistered()) {
                        sendNotification(IC_LEVEL_ORANGE, R.string.notification_registered);
                    }

                    if (displayServiceNotification() && (state == RegistrationState.RegistrationFailed || state == RegistrationState.RegistrationCleared) && (LinphoneManager.getLc().getDefaultProxyConfig() == null || !LinphoneManager.getLc().getDefaultProxyConfig().isRegistered())) {
                        sendNotification(IC_LEVEL_ORANGE, R.string.notification_register_failure);
                    }

                    if (displayServiceNotification() && state == RegistrationState.RegistrationNone) {
                        sendNotification(IC_LEVEL_ORANGE, R.string.notification_started);
                    }
                }
            }
        });

说明

这个时非常重要的逻辑了, 是主要的监听服务. 而且弹出的Notification这里也有管理.

3.8 StatusFragment.java

代码

mListener = new LinphoneCoreListenerBase(){
            @Override
            public void registrationState(final LinphoneCore lc, final LinphoneProxyConfig proxy, final LinphoneCore.RegistrationState state, String smessage) {
                if (!isAttached || !LinphoneService.isReady()) {
                    return;
                }

                if(lc.getProxyConfigList() == null){
                    statusLed.setImageResource(R.drawable.led_disconnected);
                    statusText.setText(getString(R.string.no_account));
                } else {
                    statusLed.setVisibility(View.VISIBLE);
                }

                if (lc.getDefaultProxyConfig() != null && lc.getDefaultProxyConfig().equals(proxy)) {
                    statusLed.setImageResource(getStatusIconResource(state, true));
                    statusText.setText(getStatusIconText(state));
                } else if(lc.getDefaultProxyConfig() == null) {
                    statusLed.setImageResource(getStatusIconResource(state, true));
                    statusText.setText(getStatusIconText(state));
                }

                try {
                    statusText.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            lc.refreshRegisters();
                        }
                    });
                } catch (IllegalStateException ise) {}
            }

            @Override
            public void notifyReceived(LinphoneCore lc, LinphoneEvent ev, String eventName, LinphoneContent content) {

                if(!content.getType().equals("application")) return;
                if(!content.getSubtype().equals("simple-message-summary")) return;

                if (content.getData() == null) return;

                int unreadCount = -1;
                String data = content.getDataAsString();
                String[] voiceMail = data.split("voice-message: ");
                final String[] intToParse = voiceMail[1].split("/",0);

                unreadCount = Integer.parseInt(intToParse[0]);
                if (unreadCount > 0) {
                    voicemailCount.setText(unreadCount);
                    voicemail.setVisibility(View.VISIBLE);
                    voicemailCount.setVisibility(View.VISIBLE);
                } else {
                    voicemail.setVisibility(View.GONE);
                    voicemailCount.setVisibility(View.GONE);
                }
            }

        };

说明

显示音频视频的速率

**Audio**
Codec:opus / 48kHz
Encoder:An opus encoder.
Decoder:An opus decoder.
Upload bandwidth:31 kbits/s
Download bandwidth:32 kbits/s
ICE connectivity: Not activated
IP Familiy:ipV4
Sender loss rate: 0%
Receiver loss rate: 0%
Jitter buffer:32.79ms

**Video**
Encoder:A VP8 video encoder using libvpx library.
Decoder:A VP8 video decoder using libvpx library.
Upload bandwidth:194 kbits/s
Download bandwidth:0 kbits/s
ICE connectivity: not activated
IP Family:Ipv4
Sender losdd rate:0%
Recevier loss rate: 0%
Sent video resolution: 480x640
Received video resolution: 352*288

3.9 AssistantActivity.java

代码

mListener = new LinphoneCoreListenerBase() {

            @Override
            public void configuringStatus(LinphoneCore lc, final LinphoneCore.RemoteProvisioningState state, String message) {
                if (progress != null) progress.dismiss();
                if (state == LinphoneCore.RemoteProvisioningState.ConfiguringSuccessful) {
                    LOG("AssistantActivity goToLinphoneActivity();");
                    goToLinphoneActivity();
                } else if (state == LinphoneCore.RemoteProvisioningState.ConfiguringFailed) {
                    Toast.makeText(AssistantActivity.instance(), getString(R.string.remote_provisioning_failure), Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg, RegistrationState state, String smessage) {
                if (remoteProvisioningInProgress) {
                    if (progress != null) progress.dismiss();
                    if (state == RegistrationState.RegistrationOk) {
                        remoteProvisioningInProgress = false;
                        success();
                    }
                } else if (accountCreated && !newAccount) {
                    if (address != null && address.asString().equals(cfg.getAddress().asString())) {
                        if (state == RegistrationState.RegistrationOk) {
                            if (progress != null) progress.dismiss();
                            if (LinphoneManager.getLc().getDefaultProxyConfig() != null) {
                                accountCreator.isAccountUsed();
                            }
                        } else if (state == RegistrationState.RegistrationFailed) {
                            if (progress != null) progress.dismiss();
                            if (dialog == null || !dialog.isShowing()) {
                                dialog = createErrorDialog(cfg, smessage);
                                dialog.show();
                            }
                        } else if (!(state == RegistrationState.RegistrationProgress)) {
                            if (progress != null) progress.dismiss();
                        }
                    }
                }
            }
        };

说明

3.10 RemoteProvisioningActivity.java

代码

mListener = new LinphoneCoreListenerBase(){
            @Override
            public void configuringStatus(LinphoneCore lc, final RemoteProvisioningState state, String message) {
                if (spinner != null) spinner.setVisibility(View.GONE);
                if (state == RemoteProvisioningState.ConfiguringSuccessful) {
                    goToLinphoneActivity();
                } else if (state == RemoteProvisioningState.ConfiguringFailed) {
                    Toast.makeText(RemoteProvisioningActivity.this, R.string.remote_provisioning_failure, Toast.LENGTH_LONG).show();
                }
            }
        };

说明

3.11 RemoteProvisioningLoginActivity.java

代码

mListener = new LinphoneCoreListenerBase(){
            @Override
            public void configuringStatus(LinphoneCore lc, final LinphoneCore.RemoteProvisioningState state, String message) {
                if (state == LinphoneCore.RemoteProvisioningState.ConfiguringSuccessful) {
                    //TODO
                } else if (state == LinphoneCore.RemoteProvisioningState.ConfiguringFailed) {
                    Toast.makeText(RemoteProvisioningLoginActivity.this, R.string.remote_provisioning_failure, Toast.LENGTH_LONG).show();
                }
            }
        };

说明

4. LinphoneCoreListener中callState()和transferState的区别

代码

/**
     * Notifies progress of a call transfer.
     * @param lc the LinphoneCore
     * @param call the call through which the transfer was sent.
     * @param new_call_state the state of the call resulting of the transfer, at the other party.
     **/
    void transferState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State new_call_state);
/** Call  State notification
     * @param state LinphoneCall.State
     */
    void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State state, String message);

说明

transferState时一个新到的电话的状态, callstate是第一个通信的状态.

5. 监听状态是一个观察者模式

调用此方法注册Listener

linphonecore_jni.cc中

extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addListener(JNIEnv* env, jobject thiz, jlong lc, jobject jlistener) {
    LinphoneJavaBindings *ljb = (LinphoneJavaBindings *) linphone_core_get_user_data((LinphoneCore *)lc);
    LinphoneCoreVTable *vTable = linphone_core_v_table_new();
    LinphoneCoreData* ldata = new LinphoneCoreData(env, thiz, vTable, jlistener, ljb);
    linphone_core_v_table_set_user_data(vTable, ldata);
    linphone_core_add_listener((LinphoneCore*)lc, vTable);
}
在vtabls.c中

void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable){
    LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get());
    _linphone_core_cbs_set_v_table(cbs, vtable, FALSE);
    _linphone_core_add_callbacks(lc, cbs, FALSE);
    linphone_core_cbs_unref(cbs);
}

因为要涉及到很多结构体的使用, 如果不分析结构体, 就没办法彻底的弄明白这个观察者模式时怎么来的. 这会又要涉及到很多的内容, 所以下一篇详细追踪.


标签:状态,lc,state,callState,State,call,param,LinphoneCore,Linphone
From: https://blog.51cto.com/u_11797608/6370699

相关文章

  • linphone 自动接听电话
    自动接听电话strings.xml:<stringname="pref_auto_answer">Autoanswerincomingcalls</string>non_localizable_strings.xml:<stringname="pref_auto_answer_key">pref_auto_answer_key</string>在xml文件中有这个线索,在界面设置如下将A......
  • linphone-PresenceNoteImpl文件对应的JNI层文件分析
    说明这个很短,自己看。native函数privatenativelongnewPresenceNoteImpl(Stringcontent,Stringlang);privatenativevoidunref(longnativePtr);privatenativeStringgetContent(longnativePtr);privatenativeintsetContent(longnativePtr,String......
  • linphone-TunnelConfigImpl文件对应的JNI层文件分析
    说明native函数privatenativeStringgetHost(longnativePtr);privatenativevoidsetHost(longnativePtr,Stringhost);privatenativeintgetPort(longnativePtr);privatenativevoidsetPort(longnativePtr,intport);privatenativeintgetRem......
  • linphone-LinphoneService.java文件分析
    说明主要是处理接听电话的逻辑,监听linphone拨打电话的状态逻辑。官方注释/****Linphoneservice,reactingtoIncomingcalls,...<br/>**Rolesinclude:<ul>*<li>InitializingLinphoneManager</li>*<li>StartingClibLinphonethroughLinphoneManage......
  • linphone-LinphoneCallParams.java文件分析
    说明专门作为Audio和Video的参数功能设置视频的带宽设置音频的带宽设置媒体的加密数据(encryption)设置是否允许低带宽设置RecordFile设置Sdp设置会话名称等是否允许多个rtp请求UML类图LinphoneCallParamsImpl.javapackageorg.linphone.core;importorg.linphone.core.LinphoneCor......
  • linphone-CallManager.java文件分析
    说明进行会话的管理,重新加入会话等功能创建会话重新进入Video重新设置参数更新会话UML类图CallManger.javapackageorg.linphone;importorg.linphone.core.LinphoneAddress;importorg.linphone.core.LinphoneCall;importorg.linphone.core.LinphoneCallParams;importorg.l......
  • linphone-PayloadType.java文件分析
    说明这个类主要是设置一些类型的参数,如MIME,RATE,FMTP等功能设置MIME设置RATE设置FMTUML类图PayloadType.javapackageorg.linphone.core;publicinterfacePayloadType{/***Obtaintheregisteredmime-type(actuallysubmime)ofthePayloadType.Forexample:......
  • linphone-LinphoneProxyConfig.java文件分析
    说明这个是linphone的纯配置文件,可能需要保存到文件中,是长久的数据.如何保存c/c++分析.功能设置Identity设置Address设置Proxy设置register设置Domain设置Dial设置Route设置Route设置Expires设置AVPF设置Realm设置ContactParameters设置PublichExpiresUML类图LinphoneProxyConfi......
  • linphone-LinphonePreferences.java文件分析
    说明这个文件比较长,主要是对于linphone的配置文件等设置。对于前面文章中文件的调用。其中大多数是对底层的调用设置。功能设置用户信息设置端口号设置显示名称设置密码设置代理设置编码设置编码速率设置DMTF等设置加密解密设置是否使用ipv6设置tunnel设置相机等UML类图LinphonePre......
  • linphone-NetworkManger.java文件分析
    功能InterceptnetworkstatechangesandupdatelinphonecorethroughLinphoneManger翻译拦截网络状态的变化,并通过LinphoneManger更新linphone核心内容。NetworkManager.java/**......