api changes. muc options

Daniel Gultsch created

Change summary

AndroidManifest.xml                                            |   5 
gen/eu/siacs/conversations/R.java                              |  95 +-
gen/org/sufficientlysecure/keychain/api/R.java                 |   1 
res/layout/fragment_conversation.xml                           |  30 
res/layout/muc_options.xml                                     |  76 ++
res/values/strings.xml                                         |   2 
src/eu/siacs/conversations/crypto/PgpEngine.java               |  78 +-
src/eu/siacs/conversations/entities/Conversation.java          |   5 
src/eu/siacs/conversations/entities/MucOptions.java            | 146 +++
src/eu/siacs/conversations/services/XmppConnectionService.java |  93 ++
src/eu/siacs/conversations/ui/ConversationActivity.java        |  17 
src/eu/siacs/conversations/ui/ConversationFragment.java        |  41 
src/eu/siacs/conversations/ui/DialogMucDetails.java            | 100 ++
src/eu/siacs/conversations/ui/XmppActivity.java                |  15 
src/eu/siacs/conversations/utils/MessageParser.java            |   2 
src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java        |   2 
src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java   |   2 
src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java  |   2 
src/eu/siacs/conversations/xmpp/PacketReceived.java            |   5 
src/eu/siacs/conversations/xmpp/XmppConnection.java            |  57 +
20 files changed, 647 insertions(+), 127 deletions(-)

Detailed changes

AndroidManifest.xml 🔗

@@ -44,6 +44,11 @@
             android:name="eu.siacs.conversations.ui.ManageAccountActivity"
             android:label="Manage Accounts"
             android:parentActivityName="eu.siacs.conversations.ui.ConversationActivity" >
+        </activity>
+         <activity
+            android:name="eu.siacs.conversations.ui.MucOptionsActivity"
+            android:label="Conference Details"
+            android:parentActivityName="eu.siacs.conversations.ui.ConversationActivity" >
         </activity>
         <activity
             android:name="eu.siacs.conversations.ui.NewConversationActivity"

gen/eu/siacs/conversations/R.java 🔗

@@ -34,43 +34,44 @@ public final class R {
         public static final int ic_action_add=0x7f020005;
         public static final int ic_action_add_person=0x7f020006;
         public static final int ic_action_cancel_launchersize=0x7f020007;
-        public static final int ic_action_delete=0x7f020008;
-        public static final int ic_action_group=0x7f020009;
-        public static final int ic_action_person=0x7f02000a;
-        public static final int ic_action_refresh=0x7f02000b;
-        public static final int ic_action_secure=0x7f02000c;
-        public static final int ic_action_send=0x7f02000d;
-        public static final int ic_action_send_now=0x7f02000e;
-        public static final int ic_action_unsecure=0x7f02000f;
-        public static final int ic_launcher=0x7f020010;
-        public static final int ic_profile=0x7f020011;
-        public static final int message_border=0x7f020012;
-        public static final int notification=0x7f020013;
-        public static final int red=0x7f020014;
-        public static final int redbackground=0x7f020015;
-        public static final int section_header=0x7f020016;
+        public static final int ic_action_cancel_launchersize_light=0x7f020008;
+        public static final int ic_action_delete=0x7f020009;
+        public static final int ic_action_group=0x7f02000a;
+        public static final int ic_action_person=0x7f02000b;
+        public static final int ic_action_refresh=0x7f02000c;
+        public static final int ic_action_secure=0x7f02000d;
+        public static final int ic_action_send=0x7f02000e;
+        public static final int ic_action_send_now=0x7f02000f;
+        public static final int ic_action_unsecure=0x7f020010;
+        public static final int ic_launcher=0x7f020011;
+        public static final int ic_profile=0x7f020012;
+        public static final int message_border=0x7f020013;
+        public static final int notification=0x7f020014;
+        public static final int red=0x7f020015;
+        public static final int redbackground=0x7f020016;
+        public static final int section_header=0x7f020017;
     }
     public static final class id {
         public static final int account_confirm_password_desc=0x7f0a001c;
-        public static final int account_delete=0x7f0a0038;
-        public static final int account_disable=0x7f0a0039;
-        public static final int account_enable=0x7f0a003a;
+        public static final int account_delete=0x7f0a0041;
+        public static final int account_disable=0x7f0a0042;
+        public static final int account_enable=0x7f0a0043;
         public static final int account_jid=0x7f0a0000;
-        public static final int account_list=0x7f0a0029;
+        public static final int account_list=0x7f0a002b;
         public static final int account_password=0x7f0a0019;
         public static final int account_password_confirm2=0x7f0a001d;
         public static final int account_status=0x7f0a0002;
         public static final int account_usetls=0x7f0a001a;
-        public static final int action_accounts=0x7f0a0032;
-        public static final int action_add=0x7f0a002d;
-        public static final int action_add_account=0x7f0a0037;
-        public static final int action_archive=0x7f0a0031;
-        public static final int action_contact_details=0x7f0a002f;
-        public static final int action_muc_details=0x7f0a0030;
-        public static final int action_refresh_contacts=0x7f0a003c;
-        public static final int action_security=0x7f0a002e;
-        public static final int action_settings=0x7f0a0033;
-        public static final int announce_pgp=0x7f0a003b;
+        public static final int action_accounts=0x7f0a003b;
+        public static final int action_add=0x7f0a0036;
+        public static final int action_add_account=0x7f0a0040;
+        public static final int action_archive=0x7f0a003a;
+        public static final int action_contact_details=0x7f0a0038;
+        public static final int action_muc_details=0x7f0a0039;
+        public static final int action_refresh_contacts=0x7f0a0045;
+        public static final int action_security=0x7f0a0037;
+        public static final int action_settings=0x7f0a003c;
+        public static final int announce_pgp=0x7f0a0044;
         public static final int contactList=0x7f0a0006;
         public static final int contact_display_name=0x7f0a0008;
         public static final int contact_jid=0x7f0a0009;
@@ -88,22 +89,31 @@ public final class R {
         public static final int details_receive_presence=0x7f0a0014;
         public static final int details_send_presence=0x7f0a0013;
         public static final int edit_account_register_new=0x7f0a001b;
-        public static final int encryption_choice_none=0x7f0a0034;
-        public static final int encryption_choice_otr=0x7f0a0035;
-        public static final int encryption_choice_pgp=0x7f0a0036;
+        public static final int encryption_choice_none=0x7f0a003d;
+        public static final int encryption_choice_otr=0x7f0a003e;
+        public static final int encryption_choice_pgp=0x7f0a003f;
         public static final int info_box=0x7f0a0022;
-        public static final int list=0x7f0a0027;
-        public static final int message_body=0x7f0a002b;
-        public static final int message_photo=0x7f0a002a;
-        public static final int message_time=0x7f0a002c;
+        public static final int list=0x7f0a0029;
+        public static final int message_body=0x7f0a002d;
+        public static final int message_photo=0x7f0a002c;
+        public static final int message_time=0x7f0a002e;
         public static final int messages_view=0x7f0a0021;
+        public static final int muc_error=0x7f0a0023;
+        public static final int muc_error_msg=0x7f0a0024;
+        public static final int muc_moderators=0x7f0a0031;
+        public static final int muc_moderators_header=0x7f0a0030;
+        public static final int muc_participants=0x7f0a0033;
+        public static final int muc_participants_header=0x7f0a0032;
+        public static final int muc_visitors=0x7f0a0035;
+        public static final int muc_visitors_header=0x7f0a0034;
+        public static final int muc_your_nick=0x7f0a002f;
         public static final int new_conversation_search=0x7f0a0004;
-        public static final int new_fingerprint=0x7f0a0023;
-        public static final int otr_fingerprint=0x7f0a0024;
-        public static final int pgp_keyentry=0x7f0a0025;
+        public static final int new_fingerprint=0x7f0a0025;
+        public static final int otr_fingerprint=0x7f0a0026;
+        public static final int pgp_keyentry=0x7f0a0027;
         public static final int progressBar1=0x7f0a0003;
-        public static final int selected_conversation=0x7f0a0028;
-        public static final int slidingpanelayout=0x7f0a0026;
+        public static final int selected_conversation=0x7f0a002a;
+        public static final int slidingpanelayout=0x7f0a0028;
         public static final int textSendButton=0x7f0a0020;
         public static final int textView1=0x7f0a0018;
         public static final int textView2=0x7f0a0001;
@@ -127,6 +137,7 @@ public final class R {
         public static final int message_error=0x7f03000a;
         public static final int message_recieved=0x7f03000b;
         public static final int message_sent=0x7f03000c;
+        public static final int muc_options=0x7f03000d;
     }
     public static final class menu {
         public static final int conversations=0x7f090000;
@@ -146,8 +157,10 @@ public final class R {
         public static final int action_settings=0x7f050003;
         public static final int announce_pgp=0x7f05000e;
         public static final int app_name=0x7f050002;
+        public static final int conference_details=0x7f050010;
         public static final int encrypted_message=0x7f05000f;
         public static final int just_now=0x7f05000c;
+        public static final int nick_in_use=0x7f050011;
         public static final int openpgp_install_openkeychain_via=0x7f050001;
         public static final int openpgp_list_preference_none=0x7f050000;
         public static final int sending=0x7f05000d;

gen/org/sufficientlysecure/keychain/api/R.java 🔗

@@ -9,6 +9,7 @@ package org.sufficientlysecure.keychain.api;
 public final class R {
 	public static final class drawable {
 		public static final int ic_action_cancel_launchersize = 0x7f020007;
+		public static final int ic_action_cancel_launchersize_light = 0x7f020008;
 	}
 	public static final class string {
 		public static final int openpgp_install_openkeychain_via = 0x7f050001;

res/layout/fragment_conversation.xml 🔗

@@ -62,6 +62,36 @@
          android:layout_width="fill_parent"
          android:orientation="vertical"
         >
+        
+        <LinearLayout
+        android:id="@+id/muc_error"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:background="@drawable/redbackground"
+        android:orientation="vertical"
+        android:visibility="gone"
+        >
+
+        <TextView
+            android:id="@+id/muc_error_msg"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textColor="#eee"
+            android:textStyle="bold"
+            android:padding="8dp"
+            android:textSize="20sp"/>
+        <TextView 
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Click to edit conference details"
+            android:textColor="#eee"
+            android:paddingLeft="8dp"
+            android:paddingBottom="8dp"
+            android:textSize="14sp"/>
+        
+    </LinearLayout>
+        
+        
     <LinearLayout
         android:id="@+id/new_fingerprint"
         android:layout_width="fill_parent"

res/layout/muc_options.xml 🔗

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:padding="8dp">
+     <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Your nickname"
+                android:textColor="#33B5E5"
+                android:textSize="20sp" />
+
+     <EditText
+         android:id="@+id/muc_your_nick"
+         android:layout_width="match_parent"
+         android:layout_height="wrap_content"
+         android:ems="10"
+         android:inputType="textEmailAddress"
+         android:padding="8dp"
+         />
+
+     <TextView
+         		android:paddingTop="16dp"
+         		android:id="@+id/muc_moderators_header"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Moderators"
+                android:textColor="#33B5E5"
+                android:textSize="20sp" />
+      <TextView
+                android:id="@+id/muc_moderators"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Romeo"
+                android:singleLine="true"
+                android:textSize="16sp"
+                android:paddingLeft="8dp"
+                android:paddingBottom="8dp"/>
+     
+     <TextView
+         		android:id="@+id/muc_participants_header"
+         		android:paddingTop="8dp"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Participants"
+                android:textColor="#33B5E5"
+                android:textSize="20sp" />
+      <TextView
+                android:id="@+id/muc_participants"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Juilett"
+                android:singleLine="true"
+                android:textSize="16sp"
+                android:paddingLeft="8dp"
+                android:paddingBottom="8dp"/>
+     <TextView
+         		android:id="@+id/muc_visitors_header"
+         		android:paddingTop="8dp"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Visitors"
+                android:textColor="#33B5E5"
+                android:textSize="20sp" />
+      <TextView
+                android:id="@+id/muc_visitors"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Benvolio"
+                android:singleLine="true"
+                android:textSize="16sp"
+                android:paddingLeft="8dp"
+                android:paddingBottom="8dp"/>
+
+   
+</LinearLayout>

res/values/strings.xml 🔗

@@ -15,4 +15,6 @@
     <string name="sending">sending&#8230;</string>
     <string name="announce_pgp">Renew PGP announcement</string>
     <string name="encrypted_message">Decrypting message. please wait&#8230;</string>
+    <string name="conference_details">Conference Details</string>
+    <string name="nick_in_use">Nickname is already in use</string>
 </resources>

src/eu/siacs/conversations/crypto/PgpEngine.java 🔗

@@ -7,11 +7,9 @@ import java.io.InputStream;
 import org.openintents.openpgp.OpenPgpError;
 import org.openintents.openpgp.OpenPgpSignatureResult;
 import org.openintents.openpgp.util.OpenPgpApi;
-import org.openintents.openpgp.util.OpenPgpConstants;
 
 import android.app.PendingIntent;
-import android.os.Bundle;
-import android.util.Log;
+import android.content.Intent;
 
 public class PgpEngine {
 	private OpenPgpApi api;
@@ -22,34 +20,34 @@ public class PgpEngine {
 
 	public String decrypt(String message) throws UserInputRequiredException,
 			OpenPgpException {
+		Intent params = new Intent();
+		params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
 		InputStream is = new ByteArrayInputStream(message.getBytes());
 		ByteArrayOutputStream os = new ByteArrayOutputStream();
-		Bundle result = api.decryptAndVerify(is, os);
-		switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
-		case OpenPgpConstants.RESULT_CODE_SUCCESS:
+		Intent result = api.executeApi(params, is, os);
+		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
+		case OpenPgpApi.RESULT_CODE_SUCCESS:
 			return os.toString();
-		case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED:
-			throw new UserInputRequiredException(
-					(PendingIntent) result
-							.getParcelable(OpenPgpConstants.RESULT_INTENT));
-		case OpenPgpConstants.RESULT_CODE_ERROR:
+		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
+			throw new UserInputRequiredException((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
+		case OpenPgpApi.RESULT_CODE_ERROR:
 			throw new OpenPgpException(
-					(OpenPgpError) result
-							.getParcelable(OpenPgpConstants.RESULT_ERRORS));
+					(OpenPgpError) result.getParcelableExtra(OpenPgpApi.RESULT_ERRORS));
 		default:
 			return null;
 		}
 	}
 
 	public String encrypt(long keyId, String message) {
-		Bundle params = new Bundle();
-		params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
-		long[] keyIds = { keyId };
-		params.putLongArray(OpenPgpConstants.PARAMS_KEY_IDS, keyIds);
-
+		Long[] keys = {keyId};
+		Intent params = new Intent();
+		params.setAction(OpenPgpApi.ACTION_ENCRYPT);
+		params.putExtra(OpenPgpApi.EXTRA_KEY_IDS,keys);
+		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
+		
 		InputStream is = new ByteArrayInputStream(message.getBytes());
 		ByteArrayOutputStream os = new ByteArrayOutputStream();
-		Bundle result = api.encrypt(params, is, os);
+		Intent result = api.executeApi(params, is, os);
 		StringBuilder encryptedMessageBody = new StringBuilder();
 		String[] lines = os.toString().split("\n");
 		for (int i = 3; i < lines.length - 1; ++i) {
@@ -74,47 +72,45 @@ public class PgpEngine {
 		pgpSig.append(signature.replace("\n", "").trim());
 		pgpSig.append('\n');
 		pgpSig.append("-----END PGP SIGNATURE-----");
-		Bundle params = new Bundle();
-		params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
+		Intent params = new Intent();
+		params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
+		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
 		InputStream is = new ByteArrayInputStream(pgpSig.toString().getBytes());
 		ByteArrayOutputStream os = new ByteArrayOutputStream();
-		Bundle result = api.decryptAndVerify(params, is, os);
-		switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
-		case OpenPgpConstants.RESULT_CODE_SUCCESS:
-			OpenPgpSignatureResult sigResult = result
-					.getParcelable(OpenPgpConstants.RESULT_SIGNATURE);
+		Intent result = api.executeApi(params, is, os);
+		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
+		case OpenPgpApi.RESULT_CODE_SUCCESS:
+			OpenPgpSignatureResult sigResult
+            = result.getParcelableExtra(OpenPgpApi.RESULT_SIGNATURE);
 			return sigResult.getKeyId();
-		case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED:
+		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
 			break;
-		case OpenPgpConstants.RESULT_CODE_ERROR:
+		case OpenPgpApi.RESULT_CODE_ERROR:
 			throw new OpenPgpException(
-					(OpenPgpError) result
-							.getParcelable(OpenPgpConstants.RESULT_ERRORS));
+					(OpenPgpError) result.getParcelableExtra(OpenPgpApi.RESULT_ERRORS));
 		}
 		return 0;
 	}
 
 	public String generateSignature(String status)
 			throws UserInputRequiredException {
-		Bundle params = new Bundle();
-		params.putBoolean(OpenPgpConstants.PARAMS_REQUEST_ASCII_ARMOR, true);
+		Intent params = new Intent();
+		params.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
+		params.setAction(OpenPgpApi.ACTION_SIGN);
 		InputStream is = new ByteArrayInputStream(status.getBytes());
 		ByteArrayOutputStream os = new ByteArrayOutputStream();
-		Bundle result = api.sign(params, is, os);
+		Intent result = api.executeApi(params, is, os);
 		StringBuilder signatureBuilder = new StringBuilder();
-		switch (result.getInt(OpenPgpConstants.RESULT_CODE)) {
-		case OpenPgpConstants.RESULT_CODE_SUCCESS:
+		switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, 0)) {
+		case OpenPgpApi.RESULT_CODE_SUCCESS:
 			String[] lines = os.toString().split("\n");
 			for (int i = 7; i < lines.length - 1; ++i) {
 				signatureBuilder.append(lines[i].trim());
 			}
 			break;
-		case OpenPgpConstants.RESULT_CODE_USER_INTERACTION_REQUIRED:
-			UserInputRequiredException exception = new UserInputRequiredException(
-					(PendingIntent) result
-							.getParcelable(OpenPgpConstants.RESULT_INTENT));
-			throw exception;
-		case OpenPgpConstants.RESULT_CODE_ERROR:
+		case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
+			throw new UserInputRequiredException((PendingIntent) result.getParcelableExtra(OpenPgpApi.RESULT_INTENT));
+		case OpenPgpApi.RESULT_CODE_ERROR:
 			break;
 		}
 		return signatureBuilder.toString();

src/eu/siacs/conversations/entities/Conversation.java 🔗

@@ -275,10 +275,15 @@ public class Conversation extends AbstractEntity {
 		if (this.mucOptions == null) {
 			this.mucOptions = new MucOptions();
 		}
+		this.mucOptions.setConversation(this);
 		return this.mucOptions ;
 	}
 	
 	public void resetMucOptions() {
 		this.mucOptions = null;
 	}
+
+	public void setContactJid(String jid) {
+		this.contactJid = jid;
+	}
 }

src/eu/siacs/conversations/entities/MucOptions.java 🔗

@@ -1,9 +1,21 @@
 package eu.siacs.conversations.entities;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xmpp.PresencePacket;
 import android.annotation.SuppressLint;
+import android.util.Log;
 
 @SuppressLint("DefaultLocale")
 public class MucOptions {
+	public static final int ERROR_NICK_IN_USE = 1;
+	
+	public interface OnRenameListener {
+		public void onRename(boolean success);
+	}
+	
 	public class User {
 		public static final int ROLE_MODERATOR = 3;
 		public static final int ROLE_NONE = 0;
@@ -17,6 +29,15 @@ public class MucOptions {
 		
 		private int role;
 		private int affiliation;
+		private String name;
+		
+		public String getName() {
+			return name;
+		}
+		public void setName(String user) {
+			this.name = user;
+		}
+		
 		public int getRole() {
 			return this.role;
 		}
@@ -35,8 +56,127 @@ public class MucOptions {
 		public int getAffiliation() {
 			return this.affiliation;
 		}
-		public void setAffiliation() {
-			
+		public void setAffiliation(String affiliation) {
+			if (affiliation.equalsIgnoreCase("admin")) {
+				this.affiliation = AFFILIATION_ADMIN;
+			} else if (affiliation.equalsIgnoreCase("owner")) {
+				this.affiliation = AFFILIATION_OWNER;
+			} else if (affiliation.equalsIgnoreCase("member")) {
+				this.affiliation = AFFILIATION_MEMBER;
+			} else if (affiliation.equalsIgnoreCase("outcast")) {
+				this.affiliation = AFFILIATION_OUTCAST;
+			} else {
+				this.affiliation = AFFILIATION_NONE;
+			}
+		}
+	}
+	private ArrayList<User> users = new ArrayList<User>();
+	private Conversation conversation;
+	private boolean isOnline = false;
+	private int error = 0;
+	private OnRenameListener renameListener = null;
+
+	
+	public void deleteUser(String name) {
+		for(int i = 0; i < users.size(); ++i) {
+			if (users.get(i).getName().equals(name)) {
+				users.remove(i);
+				return;
+			}
+		}
+	}
+	
+	public void addUser(User user) {
+		for(int i = 0; i < users.size(); ++i) {
+			if (users.get(i).getName().equals(user.getName())) {
+				users.set(i, user);
+				return;
+			}
 		}
+		users.add(user);
+		}
+	
+	public void processPacket(PresencePacket packet) {
+		Log.d("xmppService","process Packet for muc options: "+packet.toString());
+		String name = packet.getAttribute("from").split("/")[1];
+			String type = packet.getAttribute("type");
+			if (type==null) {
+				User user = new User();
+				Element item = packet.findChild("x").findChild("item");
+				user.setName(name);
+				user.setAffiliation(item.getAttribute("affiliation"));
+				user.setRole(item.getAttribute("role"));
+				user.setName(name);
+				addUser(user);
+				Log.d("xmppService","nick: "+getNick());
+				Log.d("xmppService","name: "+name);
+				if (name.equals(getNick())) {
+					this.isOnline = true;
+					this.error = 0;
+				}
+			} else if (type.equals("unavailable")) {
+				Log.d("xmppService","name: "+name);
+				if (name.equals(getNick())) {
+					Element item = packet.findChild("x").findChild("item");
+					Log.d("xmppService","nick equals name");
+					String nick = item.getAttribute("nick");
+					if (nick!=null) {
+						if (renameListener!=null) {
+							renameListener.onRename(true);
+						}
+						this.setNick(nick);
+					}
+				}
+				deleteUser(packet.getAttribute("from").split("/")[1]);
+			} else if (type.equals("error")) {
+				Element error = packet.findChild("error");
+				if (error.hasChild("conflict")) {
+					this.error  = ERROR_NICK_IN_USE;
+				}
+			}
+	}
+	
+	public List<User> getUsers() {
+		return this.users;
+	}
+	
+	public String getNick() {
+		String[] split = conversation.getContactJid().split("/");
+		if (split.length == 2) {
+			return split[1];
+		} else {
+			return conversation.getAccount().getUsername();
+		}
+	}
+	
+	public void setNick(String nick) {
+		String jid = conversation.getContactJid().split("/")[0]+"/"+nick;
+		conversation.setContactJid(jid);
+	}
+	
+	public void setConversation(Conversation conversation) {
+		this.conversation = conversation;
+	}
+	
+	public boolean online() {
+		return this.isOnline;
+	}
+	
+	public int getError() {
+		return this.error;
+	}
+
+	public void setOnRenameListener(OnRenameListener listener) {
+		this.renameListener = listener;
+	}
+	
+	public OnRenameListener getOnRenameListener() {
+		return this.renameListener;
+	}
+
+	public void setOffline() {
+		this.users.clear();
+		this.error = 0;
+		this.isOnline = false;
 	}
-}
+}

src/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -20,12 +20,15 @@ import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.Contact;
 import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.entities.MucOptions;
+import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
 import eu.siacs.conversations.entities.Presences;
 import eu.siacs.conversations.persistance.DatabaseBackend;
 import eu.siacs.conversations.persistance.OnPhoneContactsMerged;
 import eu.siacs.conversations.ui.OnAccountListChangedListener;
 import eu.siacs.conversations.ui.OnConversationListChangedListener;
 import eu.siacs.conversations.ui.OnRosterFetchedListener;
+import eu.siacs.conversations.ui.XmppActivity;
 import eu.siacs.conversations.utils.MessageParser;
 import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
 import eu.siacs.conversations.utils.PhoneHelper;
@@ -53,6 +56,7 @@ import android.os.PowerManager;
 import android.preference.PreferenceManager;
 import android.provider.ContactsContract;
 import android.util.Log;
+import android.widget.Toast;
 
 public class XmppConnectionService extends Service {
 
@@ -116,7 +120,7 @@ public class XmppConnectionService extends Service {
 			} else if (packet.getType() == MessagePacket.TYPE_ERROR) {
 				message = MessageParser.parseError(packet, account, service);
 			} else {
-				Log.d(LOGTAG, "unparsed message " + packet.toString());
+				//Log.d(LOGTAG, "unparsed message " + packet.toString());
 			}
 			if (message == null) {
 				return;
@@ -188,8 +192,15 @@ public class XmppConnectionService extends Service {
 		@Override
 		public void onPresencePacketReceived(Account account,
 				PresencePacket packet) {
+			Log.d(LOGTAG, packet.toString());
 			if (packet.hasChild("x")&&(packet.findChild("x").getAttribute("xmlns").startsWith("http://jabber.org/protocol/muc"))) {
-				Log.d(LOGTAG,"got muc presence "+packet.toString());
+				Conversation muc = findMuc(packet.getAttribute("from").split("/")[0]);
+				if (muc!=null) {
+					muc.getMucOptions().processPacket(packet);
+					if (convChangedListener!=null) {
+						convChangedListener.onConversationListChanged();
+					}
+				}
 			} else {
 				String[] fromParts = packet.getAttribute("from").split("/");
 				Contact contact = findContact(account, fromParts[0]);
@@ -290,6 +301,15 @@ public class XmppConnectionService extends Service {
 
 	}
 
+	protected Conversation findMuc(String name) {
+		for(Conversation conversation : this.conversations) {
+			if (conversation.getContactJid().split("/")[0].equals(name)) {
+				return conversation;
+			}
+		}
+		return null;
+	}
+
 	private void processRosterItems(Account account, Element elements) {
 		String version = elements.getAttribute("ver");
 		if (version != null) {
@@ -506,7 +526,7 @@ public class XmppConnectionService extends Service {
 		} else if (message.getConversation().getMode() == Conversation.MODE_MULTI) {
 			packet.setType(MessagePacket.TYPE_GROUPCHAT);
 			packet.setBody(message.getBody());
-			packet.setTo(message.getCounterpart());
+			packet.setTo(message.getCounterpart().split("/")[0]);
 			packet.setFrom(account.getJid());
 		}
 		return packet;
@@ -653,7 +673,7 @@ public class XmppConnectionService extends Service {
 			boolean muc) {
 		for (Conversation conv : this.getConversations()) {
 			if ((conv.getAccount().equals(account))
-					&& (conv.getContactJid().equals(jid))) {
+					&& (conv.getContactJid().split("/")[0].equals(jid))) {
 				return conv;
 			}
 		}
@@ -799,10 +819,19 @@ public class XmppConnectionService extends Service {
 	}
 
 	public void joinMuc(Conversation conversation) {
-		String muc = conversation.getContactJid();
+		String[] mucParts = conversation.getContactJid().split("/");
+		String muc;
+		String nick;
+		if (mucParts.length == 2) {
+			muc = mucParts[0];
+			nick = mucParts[1];
+		} else {
+			muc = mucParts[0];
+			nick = conversation.getAccount().getUsername();
+		}
 		PresencePacket packet = new PresencePacket();
 		packet.setAttribute("to", muc + "/"
-				+ conversation.getAccount().getUsername());
+				+ nick);
 		Element x = new Element("x");
 		x.setAttribute("xmlns", "http://jabber.org/protocol/muc");
 		if (conversation.getMessages().size() != 0) {
@@ -816,9 +845,55 @@ public class XmppConnectionService extends Service {
 		conversation.getAccount().getXmppConnection()
 				.sendPresencePacket(packet);
 	}
+	
+	public void renameInMuc(final Conversation conversation, final String nick, final XmppActivity activity) {
+		final MucOptions options = conversation.getMucOptions();
+		if (options.online()) {
+			options.setOnRenameListener(new OnRenameListener() {
+				
+				@Override
+				public void onRename(final boolean success) {
+					activity.runOnUiThread(new Runnable() {
+						
+						@Override
+						public void run() {
+							if (success) {
+								databaseBackend.updateConversation(conversation);
+								Toast.makeText(activity, "Your nickname has been changed", Toast.LENGTH_SHORT).show();
+							} else {
+								Toast.makeText(activity, "Nickname already in use",Toast.LENGTH_SHORT).show();
+							}
+						}
+					});
+				}
+			});
+			PresencePacket packet = new PresencePacket();
+			packet.setAttribute("to", conversation.getContactJid().split("/")[0]+"/"+nick);
+			conversation.getAccount().getXmppConnection().sendPresencePacket(packet, new OnPresencePacketReceived() {
+				
+				@Override
+				public void onPresencePacketReceived(Account account, PresencePacket packet) {
+					final boolean changed;
+					String type = packet.getAttribute("type");
+					changed = (!"error".equals(type));
+					if (!changed) {
+						options.getOnRenameListener().onRename(changed);
+					}
+					options.processPacket(packet);
+				}
+			});
+		} else {
+			String jid = conversation.getContactJid().split("/")[0]+"/"+nick;
+			conversation.setContactJid(jid);
+			databaseBackend.updateConversation(conversation);
+			if (conversation.getAccount().getStatus() == Account.STATUS_ONLINE) {
+				joinMuc(conversation);
+			}
+		}
+	}
 
 	public void leaveMuc(Conversation conversation) {
-
+		conversation.getMucOptions().setOffline();
 	}
 
 	public void disconnect(Account account) {
@@ -943,4 +1018,8 @@ public class XmppConnectionService extends Service {
 			sendPgpPresence(account, signature);
 		}
 	}
+
+	public void updateConversation(Conversation conversation) {
+		this.databaseBackend.updateConversation(conversation);
+	}
 }

src/eu/siacs/conversations/ui/ConversationActivity.java 🔗

@@ -208,17 +208,7 @@ public class ConversationActivity extends XmppActivity {
 				getActionBar().setDisplayHomeAsUpEnabled(false);
 				getActionBar().setTitle(R.string.app_name);
 				invalidateOptionsMenu();
-
-				InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
-
-				View focus = getCurrentFocus();
-
-				if (focus != null) {
-
-					inputManager.hideSoftInputFromWindow(
-							focus.getWindowToken(),
-							InputMethodManager.HIDE_NOT_ALWAYS);
-				}
+				hideKeyboard();
 			}
 
 			@Override
@@ -316,6 +306,11 @@ public class ConversationActivity extends XmppActivity {
 				builder.create().show();
 			}
 			break;
+		case R.id.action_muc_details:
+			DialogMucDetails mucDetails = new DialogMucDetails();
+			mucDetails.setConversation(getSelectedConversation());
+			mucDetails.show(getFragmentManager(), "details");
+			break;
 		case R.id.action_security:
 			final Conversation selConv = getSelectedConversation();
 			View menuItemView = findViewById(R.id.action_security);

src/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -13,9 +13,11 @@ import net.java.otr4j.session.SessionStatus;
 import eu.siacs.conversations.R;
 import eu.siacs.conversations.crypto.PgpEngine.OpenPgpException;
 import eu.siacs.conversations.crypto.PgpEngine.UserInputRequiredException;
+import eu.siacs.conversations.entities.Account;
 import eu.siacs.conversations.entities.Contact;
 import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.entities.Message;
+import eu.siacs.conversations.entities.MucOptions;
 import eu.siacs.conversations.services.XmppConnectionService;
 import eu.siacs.conversations.utils.PhoneHelper;
 import eu.siacs.conversations.utils.UIHelper;
@@ -95,6 +97,17 @@ public class ConversationFragment extends Fragment {
 		}
 	};
 	private LinearLayout pgpInfo;
+	private LinearLayout mucError;
+	private TextView mucErrorText;
+	private OnClickListener clickToMuc = new OnClickListener() {
+		
+		@Override
+		public void onClick(View v) {
+			DialogMucDetails mucDetails = new DialogMucDetails();
+			mucDetails.setConversation(conversation);
+			mucDetails.show(getFragmentManager(), "details");
+		}
+	};
 	
 	public void hidePgpPassphraseBox() {
 		pgpInfo.setVisibility(View.GONE);
@@ -138,6 +151,9 @@ public class ConversationFragment extends Fragment {
 		
 		pgpInfo = (LinearLayout) view.findViewById(R.id.pgp_keyentry);
 		pgpInfo.setOnClickListener(clickToDecryptListener);
+		mucError = (LinearLayout) view.findViewById(R.id.muc_error);
+		mucError.setOnClickListener(clickToMuc );
+		mucErrorText = (TextView) view.findViewById(R.id.muc_error_msg);
 		
 		messagesView = (ListView) view.findViewById(R.id.messages_view);
 
@@ -348,15 +364,26 @@ public class ConversationFragment extends Fragment {
 		this.messageList.clear();
 		this.messageList.addAll(this.conversation.getMessages());
 		this.messageListAdapter.notifyDataSetChanged();
-		if (messageList.size() >= 1) {
-			int latestEncryption = this.conversation.getLatestMessage()
-					.getEncryption();
-			if (latestEncryption== Message.ENCRYPTION_DECRYPTED) {
-				conversation.nextMessageEncryption = Message.ENCRYPTION_PGP;
+		if (conversation.getMode() == Conversation.MODE_SINGLE) {
+			if (messageList.size() >= 1) {
+				int latestEncryption = this.conversation.getLatestMessage()
+						.getEncryption();
+				if (latestEncryption== Message.ENCRYPTION_DECRYPTED) {
+					conversation.nextMessageEncryption = Message.ENCRYPTION_PGP;
+				} else {
+					conversation.nextMessageEncryption = latestEncryption;
+				}
+				makeFingerprintWarning(latestEncryption);
+			}
+		} else {
+			if (conversation.getMucOptions().getError() != 0) {
+				mucError.setVisibility(View.VISIBLE);
+				if (conversation.getMucOptions().getError() == MucOptions.ERROR_NICK_IN_USE) {
+					mucErrorText.setText(getString(R.string.nick_in_use));
+				}
 			} else {
-				conversation.nextMessageEncryption = latestEncryption;
+				mucError.setVisibility(View.GONE);
 			}
-			makeFingerprintWarning(latestEncryption);
 		}
 		getActivity().invalidateOptionsMenu();
 		updateChatMsgHint();

src/eu/siacs/conversations/ui/DialogMucDetails.java 🔗

@@ -0,0 +1,100 @@
+package eu.siacs.conversations.ui;
+
+
+import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.MucOptions;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.TextView;
+
+public class DialogMucDetails extends DialogFragment {
+	private XmppActivity activity;
+	private Conversation conversation;
+	private EditText mYourNick;
+	private OnClickListener changeNickListener = new OnClickListener() {
+		
+		@Override
+		public void onClick(DialogInterface dialog, int which) {
+			MucOptions options = conversation.getMucOptions();
+			String nick = mYourNick.getText().toString();
+			if (!options.getNick().equals(nick)) {
+				activity.xmppConnectionService.renameInMuc(conversation,nick,activity);
+			}
+		}
+	};
+
+	@Override
+	public Dialog onCreateDialog(Bundle savedInstanceState) {
+		this.activity = (XmppActivity) getActivity();
+		AlertDialog.Builder builder = new AlertDialog.Builder(this.activity);
+		LayoutInflater inflater = getActivity().getLayoutInflater();
+		View view = inflater.inflate(R.layout.muc_options, null);
+		builder.setView(view);
+		builder.setTitle(getString(R.string.conference_details));
+		mYourNick = (EditText) view.findViewById(R.id.muc_your_nick);
+		TextView mTextModerators = (TextView) view.findViewById(R.id.muc_moderators);
+		TextView mTextParticipants = (TextView) view.findViewById(R.id.muc_participants);
+		TextView mTextVisiotors = (TextView) view.findViewById(R.id.muc_visitors);
+		TextView mTextModeratorsHead = (TextView) view.findViewById(R.id.muc_moderators_header);
+		TextView mTextParticipantsHead = (TextView) view.findViewById(R.id.muc_participants_header);
+		TextView mTextVisiotorsHead = (TextView) view.findViewById(R.id.muc_visitors_header);
+		StringBuilder mods = new StringBuilder();
+		StringBuilder participants = new StringBuilder();
+		StringBuilder visitors = new StringBuilder();
+		for(MucOptions.User user : conversation.getMucOptions().getUsers()) {
+			if (user.getRole() == MucOptions.User.ROLE_MODERATOR) {
+				if (mods.length()>=1) {
+					mods.append("\n, "+user.getName());
+				} else {
+					mods.append(user.getName());
+				}
+			} else if (user.getRole() == MucOptions.User.ROLE_PARTICIPANT) {
+				if (participants.length()>=1) {
+					participants.append("\n, "+user.getName());
+				} else {
+					participants.append(user.getName());
+				}
+			} else {
+				if (visitors.length()>=1) {
+					visitors.append("\n, "+user.getName());
+				} else {
+					visitors.append(user.getName());
+				}
+			}
+		}
+		if (mods.length()>0) {
+			mTextModerators.setText(mods.toString());
+		} else {
+			mTextModerators.setVisibility(View.GONE);
+			mTextModeratorsHead.setVisibility(View.GONE);
+		}
+		if (participants.length()>0) {
+			mTextParticipants.setText(participants.toString());
+		} else {
+			mTextParticipants.setVisibility(View.GONE);
+			mTextParticipantsHead.setVisibility(View.GONE);
+		}
+		if (visitors.length()>0) {
+			mTextVisiotors.setText(visitors.toString());
+		} else {
+			mTextVisiotors.setVisibility(View.GONE);
+			mTextVisiotorsHead.setVisibility(View.GONE);
+		}
+		mYourNick.setText(conversation.getMucOptions().getNick());
+		builder.setPositiveButton("Done", this.changeNickListener );
+		builder.setNegativeButton("Cancel", null);
+		return builder.create();
+	}
+	
+	public void setConversation(Conversation conversation) {
+		this.conversation = conversation;
+	}
+}

src/eu/siacs/conversations/ui/XmppActivity.java 🔗

@@ -8,6 +8,8 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
 import android.os.IBinder;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
 
 public abstract class XmppActivity extends Activity {
 	public XmppConnectionService xmppConnectionService;
@@ -48,5 +50,18 @@ public abstract class XmppActivity extends Activity {
 		}
 	}
 	
+	protected void hideKeyboard() {
+		InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+
+		View focus = getCurrentFocus();
+
+		if (focus != null) {
+
+			inputManager.hideSoftInputFromWindow(
+					focus.getWindowToken(),
+					InputMethodManager.HIDE_NOT_ALWAYS);
+		}
+	}
+	
 	abstract void onBackendConnected();
 }

src/eu/siacs/conversations/utils/MessageParser.java 🔗

@@ -85,7 +85,7 @@ public class MessageParser {
 			return null;
 		}
 		String counterPart = fromParts[1];
-		if (counterPart.equals(account.getUsername())) {
+		if (counterPart.equals(conversation.getMucOptions().getNick())) {
 			status = Message.STATUS_SEND;
 		} else {
 			status = Message.STATUS_RECIEVED;

src/eu/siacs/conversations/xmpp/OnIqPacketReceived.java 🔗

@@ -2,6 +2,6 @@ package eu.siacs.conversations.xmpp;
 
 import eu.siacs.conversations.entities.Account;
 
-public interface OnIqPacketReceived {
+public interface OnIqPacketReceived extends PacketReceived {
 	public void onIqPacketReceived(Account account, IqPacket packet);
 }

src/eu/siacs/conversations/xmpp/OnMessagePacketReceived.java 🔗

@@ -2,6 +2,6 @@ package eu.siacs.conversations.xmpp;
 
 import eu.siacs.conversations.entities.Account;
 
-public interface OnMessagePacketReceived {
+public interface OnMessagePacketReceived extends PacketReceived {
 	public void onMessagePacketReceived(Account account, MessagePacket packet);
 }

src/eu/siacs/conversations/xmpp/OnPresencePacketReceived.java 🔗

@@ -2,6 +2,6 @@ package eu.siacs.conversations.xmpp;
 
 import eu.siacs.conversations.entities.Account;
 
-public interface OnPresencePacketReceived {
+public interface OnPresencePacketReceived extends PacketReceived {
 	public void onPresencePacketReceived(Account account, PresencePacket packet);
 }

src/eu/siacs/conversations/xmpp/XmppConnection.java 🔗

@@ -53,7 +53,7 @@ public class XmppConnection implements Runnable {
 	private static final int PACKET_MESSAGE = 1;
 	private static final int PACKET_PRESENCE = 2;
 
-	private Hashtable<String, OnIqPacketReceived> iqPacketCallbacks = new Hashtable<String, OnIqPacketReceived>();
+	private Hashtable<String, PacketReceived> packetCallbacks = new Hashtable<String, PacketReceived>();
 	private OnPresencePacketReceived presenceListener = null;
 	private OnIqPacketReceived unregisteredIqListener = null;
 	private OnMessagePacketReceived messageListener = null;
@@ -212,24 +212,33 @@ public class XmppConnection implements Runnable {
 		return element;
 	}
 
-	private IqPacket processIq(Tag currentTag) throws XmlPullParserException,
+	private void processIq(Tag currentTag) throws XmlPullParserException,
 			IOException {
 		IqPacket packet = (IqPacket) processPacket(currentTag, PACKET_IQ);
-		if (iqPacketCallbacks.containsKey(packet.getId())) {
-			iqPacketCallbacks.get(packet.getId()).onIqPacketReceived(account,
-					packet);
-			iqPacketCallbacks.remove(packet.getId());
+		if (packetCallbacks.containsKey(packet.getId())) {
+			if (packetCallbacks.get(packet.getId()) instanceof OnIqPacketReceived) {
+				((OnIqPacketReceived) packetCallbacks.get(packet.getId())).onIqPacketReceived(account,
+						packet);
+			}
+			
+			packetCallbacks.remove(packet.getId());
 		} else if (this.unregisteredIqListener != null) {
 			this.unregisteredIqListener.onIqPacketReceived(account, packet);
 		}
-		return packet;
 	}
 
 	private void processMessage(Tag currentTag) throws XmlPullParserException,
 			IOException {
 		MessagePacket packet = (MessagePacket) processPacket(currentTag,
 				PACKET_MESSAGE);
-		if (this.messageListener != null) {
+		String id = packet.getAttribute("id");
+		if ((id!=null)&&(packetCallbacks.containsKey(id))) {
+			if (packetCallbacks.get(id) instanceof OnMessagePacketReceived) {
+				((OnMessagePacketReceived) packetCallbacks.get(id)).onMessagePacketReceived(account,
+						packet);
+			}
+			packetCallbacks.remove(id);
+		} else if (this.messageListener != null) {
 			this.messageListener.onMessagePacketReceived(account, packet);
 		}
 	}
@@ -238,7 +247,14 @@ public class XmppConnection implements Runnable {
 			IOException {
 		PresencePacket packet = (PresencePacket) processPacket(currentTag,
 				PACKET_PRESENCE);
-		if (this.presenceListener != null) {
+		String id = packet.getAttribute("id");
+		if ((id!=null)&&(packetCallbacks.containsKey(id))) {
+			if (packetCallbacks.get(id) instanceof OnPresencePacketReceived) {
+				((OnPresencePacketReceived) packetCallbacks.get(id)).onPresencePacketReceived(account,
+						packet);
+			}
+			packetCallbacks.remove(id);
+		} else if (this.presenceListener != null) {
 			this.presenceListener.onPresencePacketReceived(account, packet);
 		}
 	}
@@ -405,19 +421,34 @@ public class XmppConnection implements Runnable {
 		packet.setAttribute("id", id);
 		tagWriter.writeElement(packet);
 		if (callback != null) {
-			iqPacketCallbacks.put(id, callback);
+			packetCallbacks.put(id, callback);
 		}
-		//Log.d(LOGTAG, account.getJid() + ": sending: " + packet.toString());
 	}
 
 	public void sendMessagePacket(MessagePacket packet) {
-		Log.d(LOGTAG,"sending message packet "+packet.toString());
+		this.sendMessagePacket(packet, null);
+	}
+	
+	public void sendMessagePacket(MessagePacket packet, OnMessagePacketReceived callback) {
+		String id = nextRandomId();
+		packet.setAttribute("id", id);
 		tagWriter.writeElement(packet);
+		if (callback != null) {
+			packetCallbacks.put(id, callback);
+		}
 	}
 
 	public void sendPresencePacket(PresencePacket packet) {
+		this.sendPresencePacket(packet, null);
+	}
+	
+	public void sendPresencePacket(PresencePacket packet, OnPresencePacketReceived callback) {
+		String id = nextRandomId();
+		packet.setAttribute("id", id);
 		tagWriter.writeElement(packet);
-		Log.d(LOGTAG, account.getJid() + ": sending: " + packet.toString());
+		if (callback != null) {
+			packetCallbacks.put(id, callback);
+		}
 	}
 
 	public void setOnMessagePacketReceivedListener(