Openfire添加好友申请通过发送Presence包实现,其中Presence包的Type含有七个状态:subscribe订阅、subscribed同意订阅、unsubscribe取消订阅、unsubscribed拒绝订阅、unavailable下线、probe探测、error错误;
PacketFiler过滤器,主要用于过滤出Presence包;
PacketListener监听器,监听服务器发来的消息;
Roster对象,可以理解为保存好友的花名册,接收好友请求的三种模式:Roster.SubscriptionMode.accept_all接受所有、Roster.SubscriptionMode.reject_all拒绝所有、Roster.SubscriptionMode.manual手动处理所有;
Openfire的ofroster表的字段包括sub订阅、ask是否有发送订阅请求、rec是否有接受订阅请求;
sub订阅:
-1 remove 发送删除用户请求
0 none 用户没有建立好友关系
1 to 发送订阅请求且请求被接受
2 from 接受好友订阅请求
3 both 双方互为好友关系
ask是否有发送订阅请求:
-1 null 没有发送好友请求
0 subscribe 发送好友订阅请求但没回复
1 unsubscribe 发送取消订阅好友请求
rec是否有接受订阅请求:
-1 null 没有收到好友订阅请求
1 sub 收到好友订阅请求但没回复
2 unsub 收到好友取消订阅请求
下面可以对照ofroster表看两个例子,好友状态就容易理解了:
openfireuser和ericfantastic这两个用户,ID32:openfireuser对于ericfantastic而言其状态为to,发送订阅请求并且已经被接受,此时ericfantastic可以接收到openfireuser的所有信息包括上线、下线、发送的消息等;ID33:ericfantastic对于openfireuser而且其状态为from,接受好友的订阅请求,对方可以收到你的状态消息,但是你无法收到对方的,必须主动添加才可以。
aaa和hhh这两个用户,sub为3,则已经互为好友,双方都能收到对方的订阅消息。
其他的状态就不一一列举了,对照着字段状态,也是很容易理解的。
贴一个自己做的添加好友及处理请求的Demo,全都在一个AddFriendActivity中实现。
布局文件addfriend.xml
<?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" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:background="@drawable/linearlayout_boder" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:layout_marginBottom="5dp" android:orientation="horizontal" android:background="#FFF" > <ImageView android:layout_width="40dp" android:layout_height="40dp" android:layout_marginLeft="5dp" android:layout_gravity="center_vertical" android:background="@drawable/action_search" /> <EditText android:id="@+id/edit_addfriend" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:gravity="center_vertical" android:layout_marginLeft="5dp" android:hint="猫友号/手机号/邮箱" /> <Button android:id="@+id/btn_searchfriend" android:layout_width="wrap_content" android:layout_height="40dp" android:layout_marginLeft="5dp" android:layout_gravity="center_vertical" android:background="@drawable/buttonbg" android:textColor="#FFF" android:text="搜索"/> </LinearLayout> </LinearLayout> <LinearLayout android:id="@+id/tab41" android:layout_width="fill_parent" android:layout_height="80dp" android:layout_marginTop="50dp" android:background="@drawable/linearlayout_boder" android:orientation="horizontal" > <ImageView android:id="@+id/img_seachFriend" android:layout_width="70dp" android:layout_height="70dp" android:layout_gravity="center_vertical" android:layout_marginLeft="10dp" /> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="0.95" android:layout_marginLeft="5dp" android:orientation="vertical" android:layout_gravity="center_vertical" android:gravity="center_vertical" > <TextView android:id="@+id/text_searchFriend" android:layout_width="wrap_content" android:layout_height="30dp" android:layout_gravity="center_vertical" android:gravity="center_vertical" android:textStyle="bold" android:textSize="17sp"/> <TextView android:id="@+id/text_response" android:layout_width="wrap_content" android:textSize="10sp" android:layout_height="30dp" android:layout_gravity="center_vertical" android:gravity="center_vertical" /> </LinearLayout> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|right" android:background="@drawable/erwei" android:paddingTop="10dp" /> <ImageView android:id="@+id/img_addFriend" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:background="@drawable/action_add" android:paddingTop="10dp" /> </LinearLayout> </LinearLayout>
package com.example.eric_jqm_chat; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.Roster; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.filter.AndFilter; import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.filter.PacketTypeFilter; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.Presence; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; /* *@author Eric *@2015-9-7上午9:28:52 */ public class AddFriendActivity extends Activity { private EditText edit_addfriend; private Button btn_searchfriend; private String name,password,response,acceptAdd,alertName,alertSubName; private ImageView img_searchFriend,img_addFriend; private TextView text_searchFriend,text_response; private Roster roster; private XMPPConnection con = ConnectServer.ConnectServer(); private static ProgressDialog dialog; private AddFriendHandler handler; private MyReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.addfriend); edit_addfriend = (EditText) findViewById(R.id.edit_addfriend); btn_searchfriend = (Button) findViewById(R.id.btn_searchfriend); img_searchFriend = (ImageView) findViewById(R.id.img_seachFriend); img_addFriend = (ImageView) findViewById(R.id.img_addFriend); text_searchFriend = (TextView) findViewById(R.id.text_searchFriend); text_response = (TextView) findViewById(R.id.text_response); name = getIntent().getStringExtra("name"); password = getIntent().getStringExtra("password"); roster = con.getRoster(); roster.setSubscriptionMode(Roster.SubscriptionMode.manual); try { con.login(name, password); } catch (XMPPException e) { e.printStackTrace(); } //注册广播 receiver = new MyReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("com.example.eric_jqm_chat.AddFriendActivity"); registerReceiver(receiver, intentFilter); if(con!=null&&con.isConnected()&&con.isAuthenticated()){ //条件过滤器 PacketFilter filter = new AndFilter(new PacketTypeFilter(Presence.class)); //packet监听器 PacketListener listener = new PacketListener() { @Override public void processPacket(Packet packet) { System.out.println("PresenceService-"+packet.toXML()); if(packet instanceof Presence){ Presence presence = (Presence)packet; String from = presence.getFrom();//发送方 String to = presence.getTo();//接收方 if (presence.getType().equals(Presence.Type.subscribe)) { System.out.println("收到添加请求!"); //发送广播传递发送方的JIDfrom及字符串 acceptAdd = "收到添加请求!"; Intent intent = new Intent(); intent.putExtra("fromName", from); intent.putExtra("acceptAdd", acceptAdd); intent.setAction("com.example.eric_jqm_chat.AddFriendActivity"); sendBroadcast(intent); } else if (presence.getType().equals( Presence.Type.subscribed)) { //发送广播传递response字符串 response = "恭喜,对方同意添加好友!"; Intent intent = new Intent(); intent.putExtra("response", response); intent.setAction("com.example.eric_jqm_chat.AddFriendActivity"); sendBroadcast(intent); } else if (presence.getType().equals( Presence.Type.unsubscribe)) { //发送广播传递response字符串 response = "抱歉,对方拒绝添加好友,将你从好友列表移除!"; Intent intent = new Intent(); intent.putExtra("response", response); intent.setAction("com.example.eric_jqm_chat.AddFriendActivity"); sendBroadcast(intent); } else if (presence.getType().equals( Presence.Type.unsubscribed)){ } else if (presence.getType().equals( Presence.Type.unavailable)) { System.out.println("好友下线!"); } else { System.out.println("好友上线!"); } } } }; //添加监听 con.addPacketListener(listener, filter); } btn_searchfriend.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { //从服务器查询用户头像,并没有进行搜索,自行修改 Drawable drawable = new Login() .getUserImage(con, edit_addfriend.getText().toString()); if(drawable != null){ img_searchFriend.setImageDrawable(drawable); text_searchFriend.setText(edit_addfriend.getText().toString()); }else{ text_searchFriend.setText("抱歉,未找到该用户"); } } }); img_addFriend.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { if(dialog == null){ dialog = new ProgressDialog(AddFriendActivity.this); } dialog.setTitle("请等待"); dialog.setMessage("正在发送好友申请..."); dialog.setCancelable(true); dialog.show(); //添加好友的副线程 Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1000); String friendName = edit_addfriend.getText().toString(); boolean result = addFriend(roster, friendName, friendName); Message msg = new Message(); Bundle b = new Bundle(); b.putBoolean("result", result); msg.setData(b); handler.sendMessage(msg); } catch (Exception e) { System.out.println("申请发生异常!!"); e.printStackTrace(); } } }); //启动线程和实例化handler thread.start(); handler = new AddFriendHandler(); } }); } //handler更新UI线程 public class AddFriendHandler extends Handler{ @Override public void handleMessage(Message msg) { if(dialog != null){ dialog.setMessage("发送成功!"); dialog.dismiss(); } Bundle b = msg.getData(); Boolean res = b.getBoolean("result"); if (res == true){ System.out.println("button发送添加好友请求成功!!"); } } } //添加好友 public boolean addFriend(Roster roster,String friendName,String name){ try { roster.createEntry(friendName.trim()+"@eric-pc", name, new String[]{"Friends"}); System.out.println("添加好友成功!!"); return true; } catch (XMPPException e) { e.printStackTrace(); System.out.println("失败!!"+e); return false; } } //广播接收器 public class MyReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { //接收传递的字符串response Bundle bundle = intent.getExtras(); response = bundle.getString("response"); System.out.println("广播收到"+response); text_response.setText(response); if(response==null){ //获取传递的字符串及发送方JID acceptAdd = bundle.getString("acceptAdd"); alertName = bundle.getString("fromName"); if(alertName!=null){ //裁剪JID得到对方用户名 alertSubName = alertName.substring(0,alertName.indexOf("@")); } if(acceptAdd.equals("收到添加请求!")){ //弹出一个对话框,包含同意和拒绝按钮 AlertDialog.Builder builder = new Builder(AddFriendActivity.this); builder.setTitle("添加好友请求" ) ; builder.setMessage("用户"+alertSubName+"请求添加你为好友" ) ; builder.setPositiveButton("同意",new DialogInterface.OnClickListener() { //同意按钮监听事件,发送同意Presence包及添加对方为好友的申请 @Override public void onClick(DialogInterface dialog, int arg1) { Presence presenceRes = new Presence(Presence.Type.subscribed); presenceRes.setTo(alertName); con.sendPacket(presenceRes); addFriend(roster, alertSubName, alertSubName); } }); builder.setNegativeButton("拒绝", new DialogInterface.OnClickListener() { //拒绝按钮监听事件,发送拒绝Presence包 @Override public void onClick(DialogInterface dialog, int arg1) { Presence presenceRes = new Presence(Presence.Type.unsubscribe); presenceRes.setTo(alertName); con.sendPacket(presenceRes); } }); builder.show(); } } } } }