Fix reference model of LinphoneChatMessage and its listener.

This commit is contained in:
Simon Morlat 2017-10-06 13:39:47 +02:00
parent 04fffe5c90
commit 4dd2b64c0b
3 changed files with 40 additions and 119 deletions

View file

@ -4462,7 +4462,7 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_getPeerAddress(JNIE
,jlong ptr) {
return (jlong) linphone_chat_room_get_peer_address((LinphoneChatRoom*)ptr);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatMessage(JNIEnv* env
extern "C" jobject Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatMessage(JNIEnv* env
,jobject thiz
,jlong ptr
,jstring jmessage) {
@ -4470,29 +4470,10 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatM
LinphoneChatMessage *chatMessage = linphone_chat_room_create_message((LinphoneChatRoom *)ptr, message);
ReleaseStringUTFChars(env, jmessage, message);
return (jlong) chatMessage;
return getChatMessage(env, chatMessage);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatMessage2(JNIEnv* env
,jobject thiz
,jlong ptr
,jstring jmessage
,jstring jurl
,jint state
,jlong time
,jboolean read
,jboolean incoming) {
const char* message = GetStringUTFChars(env, jmessage);
const char* url = GetStringUTFChars(env, jurl);
LinphoneChatMessage *chatMessage = linphone_chat_room_create_message_2(
(LinphoneChatRoom *)ptr, message, url, (LinphoneChatMessageState)state,
(time_t)time, read, incoming);
ReleaseStringUTFChars(env, jmessage, message);
ReleaseStringUTFChars(env, jurl, url);
return (jlong) chatMessage;
}
extern "C" jint Java_org_linphone_core_LinphoneChatRoomImpl_getHistorySize (JNIEnv* env
,jobject thiz
,jlong ptr) {
@ -4527,7 +4508,7 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_markAsRead(JNIEnv*
}
extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferMessage(JNIEnv* env, jobject thiz, jlong ptr, jstring jname, jstring jtype, jstring jsubtype, jint data_size) {
extern "C" jobject Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferMessage(JNIEnv* env, jobject thiz, jlong ptr, jstring jname, jstring jtype, jstring jsubtype, jint data_size) {
LinphoneCore *lc = linphone_chat_room_get_core((LinphoneChatRoom*) ptr);
LinphoneContent * content = linphone_core_create_content(lc);
LinphoneChatMessage *message = NULL;
@ -4548,7 +4529,7 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferM
linphone_content_unref(content);
return (jlong) message;
return getChatMessage(env, message);
}
extern "C" jboolean Java_org_linphone_core_LinphoneChatRoomImpl_islimeAvailable(JNIEnv *env, jobject thiz, jlong ptr) {
@ -4726,6 +4707,22 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_reSend(JNIEnv* e
linphone_chat_message_resend_2((LinphoneChatMessage*)ptr);
}
static jobject getMessageListener(JNIEnv *env, LinphoneChatMessage *msg){
jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg);
if (listener == NULL) {
ms_error("message_state_changed() notification without listener");
return NULL;
}
listener = env->NewLocalRef(listener); //promote the weak ref into a local ref*/
if (listener == NULL){
ms_error("message_state_changed() listener is no longer valid");
linphone_chat_message_set_message_state_changed_cb_user_data(msg, NULL);
return NULL;
}
return listener;
}
static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageState state) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
@ -4734,33 +4731,19 @@ static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageS
return;
}
jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg);
jobject listener = getMessageListener(env, msg);
if (!listener) return;
if (listener == NULL) {
ms_error("message_state_changed() notification without listener");
return ;
}
jclass clazz = (jclass) env->GetObjectClass(listener);
jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageStateChanged","(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneChatMessage$State;)V");
jobject jmessage = (jobject)linphone_chat_message_get_user_data(msg); /*this returns a global ref that was taken in setListener*/
jobject jmessage = getChatMessage(env, msg);
env->DeleteLocalRef(clazz);
LinphoneChatRoom *room = linphone_chat_message_get_chat_room(msg);
LinphoneCore *lc = linphone_chat_room_get_core(room);
LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
env->CallVoidMethod(listener, method, jmessage, env->CallStaticObjectMethod(ljb->chatMessageStateClass, ljb->chatMessageStateFromIntId, (jint)state));
if (state == LinphoneChatMessageStateDisplayed) {
env->DeleteGlobalRef(listener);
linphone_chat_message_set_message_state_changed_cb_user_data(msg, NULL);
}
if (jmessage) {
env->DeleteLocalRef(jmessage);
//We are going to drop our global ref, as the listener is no longer needed.
//Before, replace it by a weak ref, as other messages.
linphone_chat_message_set_user_data(msg, env->NewWeakGlobalRef(jmessage));
env->DeleteGlobalRef(jmessage);
}
env->DeleteLocalRef(listener);
}
static void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total) {
@ -4771,7 +4754,8 @@ static void file_transfer_progress_indication(LinphoneChatMessage *msg, const Li
return;
}
jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg);
jobject listener = getMessageListener(env, msg);
if (!listener) return;
jclass clazz = (jclass) env->GetObjectClass(listener);
jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageFileTransferProgressChanged", "(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;II)V");
env->DeleteLocalRef(clazz);
@ -4794,7 +4778,8 @@ static void file_transfer_recv(LinphoneChatMessage *msg, const LinphoneContent*
return;
}
jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg);
jobject listener = getMessageListener(env, msg);
if (!listener) return;
jclass clazz = (jclass) env->GetObjectClass(listener);
jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageFileTransferReceived", "(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;Lorg/linphone/core/LinphoneBuffer;)V");
env->DeleteLocalRef(clazz);
@ -4823,7 +4808,8 @@ static LinphoneBuffer* file_transfer_send(LinphoneChatMessage *msg, const Linph
return buffer;
}
jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg);
jobject listener = getMessageListener(env, msg);
if (!listener) return NULL;
jclass clazz = (jclass) env->GetObjectClass(listener);
jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageFileTransferSent","(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;IILorg/linphone/core/LinphoneBuffer;)V");
env->DeleteLocalRef(clazz);
@ -4849,13 +4835,10 @@ static LinphoneBuffer* file_transfer_send(LinphoneChatMessage *msg, const Linph
* we are able to notify the state changes of the message, until it reaches its final state
*/
extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) {
jobject listener = env->NewGlobalRef(jlistener);
LinphoneChatMessage *message = (LinphoneChatMessage *)ptr;
LinphoneChatMessageCbs *cbs;
jobject jmessage = env->NewGlobalRef(thiz);
linphone_chat_message_set_user_data(message, jmessage);
linphone_chat_message_set_message_state_changed_cb_user_data(message, listener);
linphone_chat_message_set_message_state_changed_cb_user_data(message, env->NewWeakGlobalRef(jlistener));
cbs = linphone_chat_message_get_callbacks(message);
linphone_chat_message_cbs_set_msg_state_changed(cbs, message_state_changed);
linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
@ -4867,10 +4850,15 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_unref(JNIEnv* en
,jobject thiz
,jlong ptr) {
jobject wref = (jobject)linphone_chat_message_get_user_data((LinphoneChatMessage*)ptr);
jobject listener_wref = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data((LinphoneChatMessage*)ptr);
linphone_chat_message_set_user_data((LinphoneChatMessage*)ptr, NULL);
if (wref){
env->DeleteWeakGlobalRef(wref);
}
if (listener_wref){
linphone_chat_message_set_message_state_changed_cb_user_data((LinphoneChatMessage*)ptr, NULL);
env->DeleteWeakGlobalRef(listener_wref);
}
linphone_chat_message_unref((LinphoneChatMessage*)ptr);
}
@ -4905,34 +4893,6 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage(JNIEnv*
ReleaseStringUTFChars(env, jmessage, message);
}
static void chat_room_impl_callback(LinphoneChatMessage* msg, LinphoneChatMessageState state, void* ud) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
ms_error("cannot attach VM\n");
return;
}
jobject listener = (jobject) ud;
jclass clazz = (jclass) env->GetObjectClass(listener);
jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageStateChanged","(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneChatMessage$State;)V");
jobject jmessage=(jobject)linphone_chat_message_get_user_data(msg);
LinphoneChatRoom *room = linphone_chat_message_get_chat_room(msg);
LinphoneCore *lc = linphone_chat_room_get_core(room);
LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc);
env->CallVoidMethod(
listener,
method,
jmessage,
env->CallStaticObjectMethod(ljb->chatMessageStateClass,ljb->chatMessageStateFromIntId,(jint)state));
if (state == LinphoneChatMessageStateDisplayed ) {
env->DeleteGlobalRef(listener);
env->DeleteGlobalRef(jmessage);
linphone_chat_message_set_user_data(msg,NULL);
}
}
extern "C" jobject Java_org_linphone_core_LinphoneChatRoomImpl_getCore(JNIEnv* env
,jobject thiz
@ -4943,28 +4903,6 @@ extern "C" jobject Java_org_linphone_core_LinphoneChatRoomImpl_getCore(JNIEnv*
return core;
}
extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage2(JNIEnv* env
,jobject thiz
,jlong chatroom_ptr
,jobject message
,jlong messagePtr
,jobject jlistener) {
jobject listener = env->NewGlobalRef(jlistener);
LinphoneChatMessage *msg = (LinphoneChatMessage *)messagePtr;
message = env->NewGlobalRef(message);
linphone_chat_message_ref(msg);
linphone_chat_message_set_user_data(msg, message);
LinphoneChatMessageCbs *cbs;
cbs = linphone_chat_message_get_callbacks(msg);
linphone_chat_message_cbs_set_user_data(cbs, (void *)listener);
linphone_chat_message_cbs_set_msg_state_changed(cbs, message_state_changed);
linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication);
linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_recv);
linphone_chat_message_cbs_set_file_transfer_send(cbs, file_transfer_send);
linphone_chat_room_send_chat_message_2((LinphoneChatRoom*)chatroom_ptr, msg);
}
extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendChatMessage(JNIEnv* env
,jobject thiz

View file

@ -115,11 +115,6 @@ public interface LinphoneChatRoom {
*/
void deleteMessage(LinphoneChatMessage message);
/**
* Create a LinphoneChatMessage
* @return LinphoneChatMessage object
*/
LinphoneChatMessage createLinphoneChatMessage(String message, String url, State state, long timestamp, boolean isRead, boolean isIncoming);
/**
* Returns a back pointer to the core managing the chat room.

View file

@ -25,7 +25,7 @@ import org.linphone.core.LinphoneCall;
@SuppressWarnings("deprecation")
class LinphoneChatRoomImpl implements LinphoneChatRoom {
protected final long nativePtr;
private native long createLinphoneChatMessage(long ptr, String message);
private native Object createLinphoneChatMessage(long ptr, String message);
private native long getPeerAddress(long ptr);
private native void sendMessage(long ptr, String message);
private native void sendMessage2(long ptr, Object msg, long messagePtr, StateListener listener);
@ -39,9 +39,6 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
private native boolean isRemoteComposing(long ptr);
private native void markAsRead(long ptr);
private native void deleteMessage(long room, long message);
private native long createLinphoneChatMessage2(long ptr, String message,
String url, int state, long timestamp, boolean isRead,
boolean isIncoming);
private native void sendChatMessage(long ptr, Object message, long messagePtr);
private native void finalize(long nativePtr);
private native boolean islimeAvailable(long nativePtr);
@ -77,7 +74,7 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
@Override
public LinphoneChatMessage createLinphoneChatMessage(String message) {
synchronized(getCore()){
return new LinphoneChatMessageImpl(createLinphoneChatMessage(nativePtr, message));
return (LinphoneChatMessage)createLinphoneChatMessage(nativePtr, message);
}
}
@ -144,15 +141,6 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
}
}
@Override
public LinphoneChatMessage createLinphoneChatMessage(String message,
String url, State state, long timestamp, boolean isRead,
boolean isIncoming) {
synchronized(getCore()){
return new LinphoneChatMessageImpl(createLinphoneChatMessage2(
nativePtr, message, url, state.value(), timestamp / 1000, isRead, isIncoming));
}
}
private native Object getCore(long nativePtr);
@Override
public synchronized LinphoneCore getCore() {
@ -162,11 +150,11 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom {
return (LinphoneChatMessage[]) typesPtr;
}
private native long createFileTransferMessage(long ptr, String name, String type, String subtype, int size);
private native Object createFileTransferMessage(long ptr, String name, String type, String subtype, int size);
@Override
public LinphoneChatMessage createFileTransferMessage(LinphoneContent content) {
synchronized(getCore()) {
return new LinphoneChatMessageImpl(createFileTransferMessage(nativePtr, content.getName(), content.getType(), content.getSubtype(), content.getRealSize()));
return (LinphoneChatMessage)createFileTransferMessage(nativePtr, content.getName(), content.getType(), content.getSubtype(), content.getRealSize());
}
}
@Override