Fix reference model of LinphoneChatMessage and its listener.

This commit is contained in:
Simon Morlat 2017-10-06 13:39:47 +02:00
parent 1dfa27a009
commit 145b05ee8d
3 changed files with 41 additions and 106 deletions

View file

@ -4474,7 +4474,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) {
@ -4482,29 +4482,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) {
@ -4539,7 +4520,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;
@ -4560,7 +4541,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) {
@ -4738,6 +4719,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) msg->message_state_changed_user_data;
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");
msg->message_state_changed_user_data = NULL;
return NULL;
}
return listener;
}
static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageState state) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
@ -4746,30 +4743,20 @@ static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageS
return;
}
jobject listener = (jobject) msg->message_state_changed_user_data;
if (listener == NULL) {
ms_error("message_state_changed() notification without listener");
return ;
}
jobject listener = getMessageListener(env, msg);
if (!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));
env->DeleteLocalRef(listener);
if (state == LinphoneChatMessageStateDisplayed) {
env->DeleteGlobalRef(listener);
msg->message_state_changed_user_data = NULL;
//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);
}
}
static void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total) {
@ -4780,7 +4767,8 @@ static void file_transfer_progress_indication(LinphoneChatMessage *msg, const Li
return;
}
jobject listener = (jobject) msg->message_state_changed_user_data;
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);
@ -4803,7 +4791,8 @@ static void file_transfer_recv(LinphoneChatMessage *msg, const LinphoneContent*
return;
}
jobject listener = (jobject) msg->message_state_changed_user_data;
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);
@ -4832,7 +4821,8 @@ static LinphoneBuffer* file_transfer_send(LinphoneChatMessage *msg, const Linph
return buffer;
}
jobject listener = (jobject) msg->message_state_changed_user_data;
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);
@ -4858,13 +4848,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);
message->message_state_changed_user_data = listener;
message->message_state_changed_user_data = 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);
@ -4876,10 +4863,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) ((LinphoneChatMessage*)ptr)->message_state_changed_user_data;
linphone_chat_message_set_user_data((LinphoneChatMessage*)ptr, NULL);
if (wref){
env->DeleteWeakGlobalRef(wref);
}
if (listener_wref){
((LinphoneChatMessage*)ptr)->message_state_changed_user_data = NULL;
env->DeleteWeakGlobalRef(listener_wref);
}
linphone_chat_message_unref((LinphoneChatMessage*)ptr);
}
@ -4914,34 +4906,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
@ -4952,18 +4916,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);
message = env->NewGlobalRef(message);
linphone_chat_message_ref((LinphoneChatMessage*)messagePtr);
linphone_chat_message_set_user_data((LinphoneChatMessage*)messagePtr, message);
linphone_chat_room_send_message2((LinphoneChatRoom*)chatroom_ptr, (LinphoneChatMessage*)messagePtr, chat_room_impl_callback, (void*)listener);
}
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