在 xmpp 中处理数据包侦听器

Posted

技术标签:

【中文标题】在 xmpp 中处理数据包侦听器【英文标题】:handling packet listeners in xmpp 【发布时间】:2014-10-06 04:43:30 【问题描述】:

我正在尝试使用 asmack api 开发一个 android 聊天应用程序,服务器是 openfire。 我正处于处理来自用户的传入消息并代表他们相应的用户聊天屏幕(即活动)的阶段。

为此,我开发了 2 个活动,即

public class ResultActivity extends Activity 
public class UserActivity extends Activity

resultactivity 是维护名册存在信息的活动,例如在线、离开等,因此这只是一个实例。

useractivity 是维护与相应用户的聊天列表的活动。此活动从 ResultActivity 列表中的 onclick 事件开始。因此,根据 Result 活动中没有用户,这可能不止一个。

为了监听传入的数据包(即传入的消息),我在 ResultActivity 中添加了一个监听器,它将消息添加到全局数组列表中。

在结果活动中:

PacketFilter filter = new MessageTypeFilter(Message.Type.chat);
MainActivity.connection.addPacketListener(receive_message, filter);

PacketListener receive_message = new PacketListener() 
    public void processPacket(Packet packet) 
        message = (Message) packet;
        String sender=null,body=null,sender_final=null;
        if (message.getBody() !=null) 
            Log.d("UA", "message from "+StringUtils.parseBareAddress(message.getFrom()));
            Log.d("UA", "message is "+message.getBody());
            sender = StringUtils.parseBareAddress(message.getFrom());
            sender_final=sender.substring(0, sender.indexOf('@'));
            body = message.getBody();

            Log.d("UA", "Sender : "+sender_final+" body : "+body);
            userMessage = new UserMessage("In", sender_final, body);
            userMessage_list.add(userMessage);

            userMessage_list.add(userMessage);

        
    
;

在全局消息列表(即 userMessage_list)中添加消息后,我需要使用传入消息更新用户活动。 userMessage_list 是基本适配器扩展类的getview方法中用作数组的数组列表。

所以现在我需要使用 notifydatasetchanged 方法更新 userActivity 列表。

在用户活动中:

private class UserActivityThread extends Thread 
    @Override
    public void run()  
    UserActivity.this.runOnUiThread(new Runnable() 

            @Override
            public void run() 
                 userAdapter.notifyDataSetChanged();
            
        );
    

那么如何在另一个activity中调用notifydatasetchanged方法。

我很想知道在 whatsapp 或任何聊天应用程序中如何处理这种情况。

【问题讨论】:

【参考方案1】:

我已经在我的聊天应用程序中使用ContentProvider 类和CursorLoader 解决了这个问题,每当某些URI 有新记录时,都会自动通知。

在您的情况下,我建议您启动广播消息。你的班级有一个ListView 和消息将注册一个BroadcastReceiver 并且它将监听可能的更新。每次在您的活动中触发您的BroadcastReceiver.onReceive,请刷新您的适配器。

希望对你有帮助:)

编辑

如何实现:

    在您的活动中创建一个BroadcastReceiver 对象。

    BroadcastReceiver mReceiver;

    编码您的广播接收器(例如在您的 onCreate 上)

        mReceiver = new BroadcastReceiver() 
    
        @Override
        public void onReceive(Context context, Intent intent) 
            //extract our message from intent
            String extra= intent.getStringExtra("extra");
    
            Log.i("msg received: ", extra);
    
        
    ;
    

    添加IntentFilter(在您的 onResume 中可能有效)

    IntentFilter intentFilter = new IntentFilter("com.myproject.myintentfilter");

4.1 注册你的接收器

@Override
protected void onResume() 
    // TODO Auto-generated method stub
    super.onResume();
    registerReceiver(mReceiver,intentFilter);

4.2 注销您的接收器

@Override
protected void onPause() 
    // TODO Auto-generated method stub
    super.onPause();
    this.unregisterReceiver(mReceiver);

    确保您的接收者会收到消息,检查您的sendBroadcast 是否与IntentFilter 匹配。

最后:

Intent i = new Intent("com.myproject.myintentfilter").putExtra("extra", "This is a new value");
this.sendBroadcast(i);

编辑 2

如果在您的活动轮换期间收到消息(接收者未注册),我发现了 2 个我不太满意的解决方案,但它们确实有效。

    方向改变后重新加载您的列表视图,因为活动会自行销毁,您只需重新加载列表视图的信息,您的新消息应该会出现。

    在活动中放置一个静态字段,每次收到消息时,将此类变量设置为 TRUE。如果您的 broadcastReceiver 触发,将该变量设置为 false,并且在更改方向后调用您的 onResume / onCreate 方法时,检查您的静态变量并在变量为 true 时重新加载(重新加载 ListView 后将其设置为 false)。

【讨论】:

我试过了。但是具有消息列表视图的活动已经用 Activity 扩展,相应的适配器类也用 baseadapter 扩展。我尝试使用扩展广播接收器的内部类,但它在清单中未被识别。我的意思是在运行时它正在抛出未识别扩展广播接收器的类.. @kavuru 现在看看这是否对你有帮助 我实现成功了。写的时候有一个查询..通知在注销和注册接收者的间隙中怎么样。重新注册后会收到通知吗?

以上是关于在 xmpp 中处理数据包侦听器的主要内容,如果未能解决你的问题,请参考以下文章

aSmack - 使用数据包侦听器输出可空元素的数据包到 XML

smack 数据包侦听器和消息侦听器之间的区别

Smack MUC 邀请

XMPP Smack 4.1.1 UnsupportedIQ 错误

Smack 数据包侦听器未运行

GCM,我怎么知道 XMPP 数据包的结束?