Linphone callState 电话状态的监听状态(二)
来源:互联网 发布:高校教学软件租赁 编辑:程序博客网 时间:2024/06/06 01:04
Linphone callState 电话状态的监听状态
callState是一个观察者模式
接着上一篇的说, 这篇主要是涉及到linphone中c层的注册监听机制. 主要是代码追踪和代码过程.
linphonecore_jni.cc中的添加监听事件的方法
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);}
LinphoneJavaBindings的代码及使用方法
说明
这个类绑定的是java类, 确定的是进行回调的监听机制.就是从c层回调至java层.
实现了LinphoneCoreListener中所有的方法.
代码
绑定了各种java的方法, 用于回调吧class LinphoneJavaBindings {public: LinphoneJavaBindings(JNIEnv *env) { listenerClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCoreListener")); authMethodClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$AuthMethod")); authMethodFromIntId = env->GetStaticMethodID(authMethodClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$AuthMethod;"); /*displayStatus(LinphoneCore lc,String message);*/ displayStatusId = env->GetMethodID(listenerClass,"displayStatus","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;)V"); /*void generalState(LinphoneCore lc,int state); */ globalStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$GlobalState")); globalStateFromIntId = env->GetStaticMethodID(globalStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$GlobalState;"); globalStateId = env->GetMethodID(listenerClass,"globalState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$GlobalState;Ljava/lang/String;)V"); /*registrationState(LinphoneCore lc, LinphoneProxyConfig cfg, LinphoneCore.RegistrationState cstate, String smessage);*/ registrationStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RegistrationState")); registrationStateFromIntId = env->GetStaticMethodID(registrationStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RegistrationState;"); registrationStateId = env->GetMethodID(listenerClass,"registrationState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneProxyConfig;Lorg/linphone/core/LinphoneCore$RegistrationState;Ljava/lang/String;)V"); /*callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State cstate,String message);*/ callStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCall$State")); callStateFromIntId = env->GetStaticMethodID(callStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCall$State;"); callStateId = env->GetMethodID(listenerClass,"callState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;Ljava/lang/String;)V"); transferStateId = env->GetMethodID(listenerClass,"transferState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;)V"); /*callStatsUpdated(LinphoneCore lc, LinphoneCall call, LinphoneCallStats stats);*/ callStatsUpdatedId = env->GetMethodID(listenerClass, "callStatsUpdated", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCallStats;)V"); /*callEncryption(LinphoneCore lc, LinphoneCall call, boolean encrypted,String auth_token);*/ callEncryptionChangedId = env->GetMethodID(listenerClass,"callEncryptionChanged","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;ZLjava/lang/String;)V"); /*void ecCalibrationStatus(LinphoneCore.EcCalibratorStatus status, int delay_ms, Object data);*/ ecCalibratorStatusClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$EcCalibratorStatus")); ecCalibratorStatusFromIntId = env->GetStaticMethodID(ecCalibratorStatusClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;"); ecCalibrationStatusId = env->GetMethodID(listenerClass,"ecCalibrationStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;ILjava/lang/Object;)V"); /*void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url)*/ newSubscriptionRequestId = env->GetMethodID(listenerClass,"newSubscriptionRequest","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;Ljava/lang/String;)V"); authInfoRequestedId = env->GetMethodID(listenerClass,"authInfoRequested","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); authenticationRequestedId = env->GetMethodID(listenerClass,"authenticationRequested","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneAuthInfo;Lorg/linphone/core/LinphoneCore$AuthMethod;)V"); /*void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf);*/ notifyPresenceReceivedId = env->GetMethodID(listenerClass,"notifyPresenceReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;)V"); messageReceivedId = env->GetMethodID(listenerClass,"messageReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V"); messageReceivedUnableToDecryptedId = env->GetMethodID(listenerClass,"messageReceivedUnableToDecrypted","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V"); isComposingReceivedId = env->GetMethodID(listenerClass,"isComposingReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;)V"); dtmfReceivedId = env->GetMethodID(listenerClass,"dtmfReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;I)V"); infoReceivedId = env->GetMethodID(listenerClass,"infoReceived", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneInfoMessage;)V"); subscriptionStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/SubscriptionState")); subscriptionStateFromIntId = env->GetStaticMethodID(subscriptionStateClass,"fromInt","(I)Lorg/linphone/core/SubscriptionState;"); subscriptionStateId = env->GetMethodID(listenerClass,"subscriptionStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Lorg/linphone/core/SubscriptionState;)V"); publishStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/PublishState")); publishStateFromIntId = env->GetStaticMethodID(publishStateClass,"fromInt","(I)Lorg/linphone/core/PublishState;"); publishStateId = env->GetMethodID(listenerClass,"publishStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Lorg/linphone/core/PublishState;)V"); notifyRecvId = env->GetMethodID(listenerClass,"notifyReceived", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneEvent;Ljava/lang/String;Lorg/linphone/core/LinphoneContent;)V"); configuringStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RemoteProvisioningState")); configuringStateFromIntId = env->GetStaticMethodID(configuringStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;"); configuringStateId = env->GetMethodID(listenerClass,"configuringStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;Ljava/lang/String;)V"); fileTransferProgressIndicationId = env->GetMethodID(listenerClass, "fileTransferProgressIndication", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;I)V"); fileTransferSendId = env->GetMethodID(listenerClass, "fileTransferSend", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;Ljava/nio/ByteBuffer;I)I"); fileTransferRecvId = env->GetMethodID(listenerClass, "fileTransferRecv", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;[BI)V"); logCollectionUploadStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$LogCollectionUploadState")); logCollectionUploadStateFromIntId = env->GetStaticMethodID(logCollectionUploadStateClass, "fromInt", "(I)Lorg/linphone/core/LinphoneCore$LogCollectionUploadState;"); logCollectionUploadProgressId = env->GetMethodID(listenerClass, "uploadProgressIndication", "(Lorg/linphone/core/LinphoneCore;II)V"); logCollectionUploadStateId = env->GetMethodID(listenerClass, "uploadStateChanged", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$LogCollectionUploadState;Ljava/lang/String;)V"); }}
创建
在linhonecore.c中void *linphone_core_get_user_data(const LinphoneCore *lc){ return lc->data;}
说明了具体的对象还是LinphoneCore中.
LinphoneCoreVTable的作用及代码
代码
/** * This structure holds all callbacks that the application should implement. * None is mandatory.**/typedef struct _LinphoneCoreVTable{ LinphoneCoreGlobalStateChangedCb global_state_changed; /**<Notifies global state changes*/ LinphoneCoreRegistrationStateChangedCb registration_state_changed;/**<Notifies registration state changes*/ LinphoneCoreCallStateChangedCb call_state_changed;/**<Notifies call state changes*/ LinphoneCoreNotifyPresenceReceivedCb notify_presence_received; /**< Notify received presence events*/ LinphoneCoreNotifyPresenceReceivedForUriOrTelCb notify_presence_received_for_uri_or_tel; /**< Notify received presence events*/ LinphoneCoreNewSubscriptionRequestedCb new_subscription_requested; /**< Notify about pending presence subscription request */ LINPHONE_DEPRECATED LinphoneCoreAuthInfoRequestedCb auth_info_requested; /**< @deprecated Use authentication_requested instead. Ask the application some authentication information */ LinphoneCoreAuthenticationRequestedCb authentication_requested; /**< Ask the application some authentication information */ LinphoneCoreCallLogUpdatedCb call_log_updated; /**< Notifies that call log list has been updated */ LinphoneCoreMessageReceivedCb message_received; /**< a message is received, can be text or external body*/ LinphoneCoreCbsMessageReceivedUnableDecryptCb message_received_unable_decrypt; /**< an encrypted message is received but we can't decrypt it*/ LinphoneCoreIsComposingReceivedCb is_composing_received; /**< An is-composing notification has been received */ LinphoneCoreDtmfReceivedCb dtmf_received; /**< A dtmf has been received received */ LinphoneCoreReferReceivedCb refer_received; /**< An out of call refer was received */ LinphoneCoreCallEncryptionChangedCb call_encryption_changed; /**<Notifies on change in the encryption of call streams */ LinphoneCoreTransferStateChangedCb transfer_state_changed; /**<Notifies when a transfer is in progress */ LinphoneCoreBuddyInfoUpdatedCb buddy_info_updated; /**< a LinphoneFriend's BuddyInfo has changed*/ LinphoneCoreCallStatsUpdatedCb call_stats_updated; /**<Notifies on refreshing of call's statistics. */ LinphoneCoreInfoReceivedCb info_received; /**<Notifies an incoming informational message received.*/ LinphoneCoreSubscriptionStateChangedCb subscription_state_changed; /**<Notifies subscription state change */ LinphoneCoreNotifyReceivedCb notify_received; /**< Notifies a an event notification, see linphone_core_subscribe() */ LinphoneCorePublishStateChangedCb publish_state_changed;/**Notifies publish state change (only from #LinphoneEvent api)*/ LinphoneCoreConfiguringStatusCb configuring_status; /** Notifies configuring status changes */ LINPHONE_DEPRECATED DisplayStatusCb display_status; /**< @deprecated Callback that notifies various events with human readable text.*/ LINPHONE_DEPRECATED DisplayMessageCb display_message;/**< @deprecated Callback to display a message to the user */ LINPHONE_DEPRECATED DisplayMessageCb display_warning;/**< @deprecated Callback to display a warning to the user */ LINPHONE_DEPRECATED DisplayUrlCb display_url; /**< @deprecated */ LINPHONE_DEPRECATED ShowInterfaceCb show; /**< vNotifies the application that it should show up*/ LINPHONE_DEPRECATED LinphoneCoreTextMessageReceivedCb text_received; /**< @deprecated, use #message_received instead <br> A text message has been received */ LINPHONE_DEPRECATED LinphoneCoreFileTransferRecvCb file_transfer_recv; /**< @deprecated Callback to store file received attached to a #LinphoneChatMessage */ LINPHONE_DEPRECATED LinphoneCoreFileTransferSendCb file_transfer_send; /**< @deprecated Callback to collect file chunk to be sent for a #LinphoneChatMessage */ LINPHONE_DEPRECATED LinphoneCoreFileTransferProgressIndicationCb file_transfer_progress_indication; /**< @deprecated Callback to indicate file transfer progress */ LinphoneCoreNetworkReachableCb network_reachable; /**< Callback to report IP network status (I.E up/down )*/ LinphoneCoreLogCollectionUploadStateChangedCb log_collection_upload_state_changed; /**< Callback to upload collected logs */ LinphoneCoreLogCollectionUploadProgressIndicationCb log_collection_upload_progress_indication; /**< Callback to indicate log collection upload progress */ LinphoneCoreFriendListCreatedCb friend_list_created; LinphoneCoreFriendListRemovedCb friend_list_removed; void *user_data; /**<User data associated with the above callbacks */} LinphoneCoreVTable;
说明
回调时应用的查询表. 创建内存空间后, 供下列函数使用.
创建
LinphoneCoreVTable *linphone_core_v_table_new() { return ms_new0(LinphoneCoreVTable,1);}
目的就是实例化一个table
class LinphoneCoreData的作用及代码
代码
LinphoneCoreData(JNIEnv *env, jobject lc, LinphoneCoreVTable *vTable, jobject alistener, LinphoneJavaBindings *ljb) { core = env->NewGlobalRef(lc); listener = env->NewGlobalRef(alistener); memset(vTable, 0, sizeof(LinphoneCoreVTable)); if (ljb->displayStatusId) { vTable->display_status = displayStatusCb; } if (ljb->globalStateId) { vTable->global_state_changed = globalStateChange; } if (ljb->registrationStateId) { vTable->registration_state_changed = registrationStateChange; } if (ljb->callStateId) { vTable->call_state_changed = callStateChange; } if (ljb->transferStateId) { vTable->transfer_state_changed = transferStateChanged; } if (ljb->callStatsUpdatedId) { vTable->call_stats_updated = callStatsUpdated; } if (ljb->callEncryptionChangedId) { vTable->call_encryption_changed = callEncryptionChange; } if (ljb->newSubscriptionRequestId) { vTable->new_subscription_requested = new_subscription_requested; } if (ljb->authInfoRequestedId) { vTable->auth_info_requested = authInfoRequested; } if (ljb->authenticationRequestedId) { vTable->authentication_requested = authenticationRequested; } if (ljb->notifyPresenceReceivedId) { vTable->notify_presence_received = notify_presence_received; } if (ljb->messageReceivedId) { vTable->message_received = message_received; } if (ljb->messageReceivedUnableToDecryptedId) { vTable->message_received_unable_decrypt = message_received_unable_decrypt; } if (ljb->isComposingReceivedId) { vTable->is_composing_received = is_composing_received; } if (ljb->dtmfReceivedId) { vTable->dtmf_received = dtmf_received; } if (ljb->infoReceivedId) { vTable->info_received = infoReceived; } if (ljb->subscriptionStateId) { vTable->subscription_state_changed = subscriptionStateChanged; } if (ljb->publishStateId) { vTable->publish_state_changed = publishStateChanged; } if (ljb->notifyRecvId) { vTable->notify_received = notifyReceived; } if (ljb->configuringStateId) { vTable->configuring_status = configuringStatus; } if (ljb->fileTransferProgressIndicationId) { vTable->file_transfer_progress_indication = fileTransferProgressIndication; } if (ljb->fileTransferSendId) { vTable->file_transfer_send = fileTransferSend; } if (ljb->fileTransferRecvId) { vTable->file_transfer_recv = fileTransferRecv; } if (ljb->logCollectionUploadProgressId) { vTable->log_collection_upload_progress_indication = logCollectionUploadProgressIndication; } if (ljb->logCollectionUploadStateId) { vTable->log_collection_upload_state_changed = logCollectionUploadStateChange; } if (ljb->friendListCreatedId) { vTable->friend_list_created = friendListCreated; } if (ljb->friendListRemovedId) { vTable->friend_list_removed = friendListRemoved; } }
说明
这是类是将VTable一一对应起来, 进行数据的操作. 通过调用相应的方法, 对上层java方法进行回调操作, 这里时ListenerCoreListener主要的操作实体类.
linphone_core_v_table_set_user_data()函数都干了什么
代码
void linphone_core_v_table_set_user_data(LinphoneCoreVTable *table, void *data) { table->user_data = data;}
说明
将数据赋值.
重点来了linphone_core_add_listener
代码
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);}
说明
这个是真刀真枪的用道德时候了.
LinphoneCoreCbs
代码
struct _LinphoneCoreCbs { belle_sip_object_t base; LinphoneCoreVTable *vtable; bool_t autorelease;};
说明
这个路径好深啊, 我只能这么说了.
创建
linphone_factory_create_core_cbs()函数创建
LinphoneCore *linphone_factory_create_core(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, const char *config_path, const char *factory_config_path) { LpConfig *config = lp_config_new_with_factory(config_path, factory_config_path); LinphoneCore *lc = _linphone_core_new_with_config(cbs, config, NULL); lp_config_unref(config); return lc;}
东西很多,最后在找到了这个bctbx_list_append_link
bctbx_list_t *bctbx_list_append_link(bctbx_list_t *elem, bctbx_list_t *new_elem) { bctbx_list_t *it = elem; if (elem == NULL) return new_elem; if (new_elem == NULL) return elem; while (it->next != NULL) it = bctbx_list_next(it); it->next = new_elem; new_elem->prev = it; return elem;}
这个就是将监听时间添到了列表中.
但是什么时候回调的呢
关于这个问题, 我觉得应该会有很多地方调用. 但是总会有一个列表的, 猜测应该vtable.c中.
没错了,就应该是这个文件中.
会不会就是这个呢
#define NOTIFY_IF_EXIST_INTERNAL(function_name, internal_val, ...) \ bctbx_list_t* iterator; \ VTableReference *ref; \ lc->vtable_notify_recursion++;\ for (iterator=lc->vtable_refs; iterator!=NULL; iterator=iterator->next){\ if ((ref=(VTableReference*)iterator->data)->valid && (lc->current_cbs=ref->cbs)->vtable->function_name && (ref->internal == internal_val)) {\ lc->current_cbs->vtable->function_name(__VA_ARGS__);\ }\ }\ lc->vtable_notify_recursion--;
然后处理的方法应该在这里面
void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) { NOTIFY_IF_EXIST_INTERNAL(notify_received, linphone_event_is_internal(lev), lc, lev, notified_event, body); cleanup_dead_vtable_refs(lc);}void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { NOTIFY_IF_EXIST_INTERNAL(subscription_state_changed,linphone_event_is_internal(lev), lc,lev,state); cleanup_dead_vtable_refs(lc);}void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state) { NOTIFY_IF_EXIST_INTERNAL(publish_state_changed, linphone_event_is_internal(lev), lc, lev, state); cleanup_dead_vtable_refs(lc);}
0 0
- Linphone callState 电话状态的监听状态(二)
- Linphone callState 电话状态的监听状态(一)
- android 电话状态的监听
- 监听电话的呼叫状态
- android电话状态的监听
- android电话状态的监听
- Android 电话状态的监听
- 监听用户电话状态
- Android监听电话状态
- android 监听电话状态
- android 监听电话状态
- android 监听电话状态
- 如何监听电话状态
- Android 电话状态监听
- 【Android】监听电话状态
- android电话状态监听
- android电话状态监听
- Android监听电话状态
- 关于 Android中的插件化开发,dex分包,热修复(Tinker)的思考(二)
- 【机房重构】——七层登陆
- java Queue接口简介
- ***POJ 3614 Sunscreen
- com.google.code.findbugs引起的错误
- Linphone callState 电话状态的监听状态(二)
- nginx配置http2无效不起作用
- 安装完成服务器进行优化
- css-position:absolute时如何居中
- 理解Jquery的first-of-type选择器
- 2017LinuxPHP+Mysql+nginx最详尽配置学习手册包括优化
- windows网络模型
- 冒泡排序和改进
- Ubuntu调教手册(软件安装sogou,chrome等)