package com.netease.nim.demo.main.activity; import android.content.Context; import android.content.Intent; import android.os.Build; import android.os.Bundle; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.Toast; import com.netease.nim.demo.R; import com.netease.nim.demo.main.adapter.SystemMessageAdapter; import com.netease.nim.demo.main.viewholder.SystemMessageViewHolder; import com.netease.nim.uikit.cache.NimUserInfoCache; import com.netease.nim.uikit.common.activity.UI; import com.netease.nim.uikit.common.adapter.TAdapterDelegate; import com.netease.nim.uikit.common.adapter.TViewHolder; import com.netease.nim.uikit.common.ui.dialog.CustomAlertDialog; import com.netease.nim.uikit.common.ui.listview.AutoRefreshListView; import com.netease.nim.uikit.common.ui.listview.ListViewUtil; import com.netease.nim.uikit.common.ui.listview.MessageListView; import com.netease.nim.uikit.model.ToolBarOptions; import com.netease.nimlib.sdk.NIMClient; import com.netease.nimlib.sdk.Observer; import com.netease.nimlib.sdk.RequestCallback; import com.netease.nimlib.sdk.RequestCallbackWrapper; import com.netease.nimlib.sdk.ResponseCode; import com.netease.nimlib.sdk.friend.FriendService; import com.netease.nimlib.sdk.friend.model.AddFriendNotify; import com.netease.nimlib.sdk.msg.SystemMessageObserver; import com.netease.nimlib.sdk.msg.SystemMessageService; import com.netease.nimlib.sdk.msg.constant.SystemMessageStatus; import com.netease.nimlib.sdk.msg.constant.SystemMessageType; import com.netease.nimlib.sdk.msg.model.SystemMessage; import com.netease.nimlib.sdk.team.TeamService; import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; /** * 系统消息中心界面 * <p/> * Created by huangjun on 2015/3/18. */ public class SystemMessageActivity extends UI implements TAdapterDelegate, AutoRefreshListView.OnRefreshListener, SystemMessageViewHolder.SystemMessageListener { private static final boolean MERGE_ADD_FRIEND_VERIFY = false; // 是否要合并好友申请,同一个用户仅保留最近一条申请内容(默认不合并) private static final int LOAD_MESSAGE_COUNT = 10; // view private MessageListView listView; // adapter private SystemMessageAdapter adapter; private List<SystemMessage> items = new ArrayList<>(); private Set<Long> itemIds = new HashSet<>(); // db private boolean firstLoad = true; public static void start(Context context) { start(context, null, true); } public static void start(Context context, Intent extras, boolean clearTop) { Intent intent = new Intent(); intent.setClass(context, SystemMessageActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); if (clearTop) { intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); } if (extras != null) { intent.putExtras(extras); } context.startActivity(intent); } @Override public int getViewTypeCount() { return 1; } @Override public Class<? extends TViewHolder> viewHolderAtPosition(int position) { return SystemMessageViewHolder.class; } @Override public boolean enabled(int position) { return false; } @Override public void onRefreshFromStart() { } @Override public void onRefreshFromEnd() { loadMessages(); // load old data } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.system_notification_message_activity); ToolBarOptions options = new ToolBarOptions(); options.titleId = R.string.verify_reminder; setToolBar(R.id.toolbar, options); initAdapter(); initListView(); loadMessages(); // load old data registerSystemObserver(true); } @Override protected void onResume() { super.onResume(); NIMClient.getService(SystemMessageService.class).resetSystemMessageUnreadCount(); } @Override protected void onStop() { super.onStop(); NIMClient.getService(SystemMessageService.class).resetSystemMessageUnreadCount(); } @Override protected void onDestroy() { super.onDestroy(); registerSystemObserver(false); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.notification_menu, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.notification_menu_btn: deleteAllMessages(); break; default: break; } return super.onOptionsItemSelected(item); } private void initAdapter() { adapter = new SystemMessageAdapter(this, items, this, this); } private void initListView() { listView = (MessageListView) findViewById(R.id.messageListView); listView.setMode(AutoRefreshListView.Mode.END); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { listView.setOverScrollMode(View.OVER_SCROLL_NEVER); } // adapter listView.setAdapter(adapter); // listener listView.setOnRefreshListener(this); } private int loadOffset = 0; private Set<String> addFriendVerifyRequestAccounts = new HashSet<>(); // 发送过好友申请的账号(好友申请合并用) /** * 加载历史消息 */ public void loadMessages() { listView.onRefreshStart(AutoRefreshListView.Mode.END); boolean loadCompleted; // 是否已经加载完成,后续没有数据了or已经满足本次请求数量 int validMessageCount = 0; // 实际加载的数量(排除被过滤被合并的条目) List<String> messageFromAccounts = new ArrayList<>(LOAD_MESSAGE_COUNT); while (true) { List<SystemMessage> temps = NIMClient.getService(SystemMessageService.class) .querySystemMessagesBlock(loadOffset, LOAD_MESSAGE_COUNT); loadOffset += temps.size(); loadCompleted = temps.size() < LOAD_MESSAGE_COUNT; int tempValidCount = 0; for (SystemMessage m : temps) { // 去重 if (duplicateFilter(m)) { continue; } // 同一个账号的好友申请仅保留最近一条 if (addFriendVerifyFilter(m)) { continue; } // 保存有效消息 items.add(m); tempValidCount++; if (!messageFromAccounts.contains(m.getFromAccount())) { messageFromAccounts.add(m.getFromAccount()); } // 判断是否达到请求数 if (++validMessageCount >= LOAD_MESSAGE_COUNT) { loadCompleted = true; // 已经满足要求,此时需要修正loadOffset loadOffset -= temps.size(); loadOffset += tempValidCount; break; } } if (loadCompleted) { break; } } // 更新数据源,刷新界面 refresh(); boolean first = firstLoad; firstLoad = false; if (first) { ListViewUtil.scrollToPosition(listView, 0, 0); // 第一次加载后显示顶部 } listView.onRefreshComplete(validMessageCount, LOAD_MESSAGE_COUNT, true); // 收集未知用户资料的账号集合并从远程获取 collectAndRequestUnknownUserInfo(messageFromAccounts); } /** * 新消息到来 */ private void onIncomingMessage(final SystemMessage message) { // 同一个账号的好友申请仅保留最近一条 if (addFriendVerifyFilter(message)) { SystemMessage del = null; for (SystemMessage m : items) { if (m.getFromAccount().equals(message.getFromAccount()) && m.getType() == SystemMessageType.AddFriend) { AddFriendNotify attachData = (AddFriendNotify) m.getAttachObject(); if (attachData != null && attachData.getEvent() == AddFriendNotify.Event.RECV_ADD_FRIEND_VERIFY_REQUEST) { del = m; break; } } } if (del != null) { items.remove(del); } } loadOffset++; items.add(0, message); refresh(); // 收集未知用户资料的账号集合并从远程获取 List<String> messageFromAccounts = new ArrayList<>(1); messageFromAccounts.add(message.getFromAccount()); collectAndRequestUnknownUserInfo(messageFromAccounts); } // 去重 private boolean duplicateFilter(final SystemMessage msg) { if (itemIds.contains(msg.getMessageId())) { return true; } itemIds.add(msg.getMessageId()); return false; } // 同一个账号的好友申请仅保留最近一条 private boolean addFriendVerifyFilter(final SystemMessage msg) { if (!MERGE_ADD_FRIEND_VERIFY) { return false; // 不需要MERGE,不过滤 } if (msg.getType() != SystemMessageType.AddFriend) { return false; // 不过滤 } AddFriendNotify attachData = (AddFriendNotify) msg.getAttachObject(); if (attachData == null) { return true; // 过滤 } if (attachData.getEvent() != AddFriendNotify.Event.RECV_ADD_FRIEND_VERIFY_REQUEST) { return false; // 不过滤 } if (addFriendVerifyRequestAccounts.contains(msg.getFromAccount())) { return true; // 过滤 } addFriendVerifyRequestAccounts.add(msg.getFromAccount()); return false; // 不过滤 } // 请求未知的用户资料 private void collectAndRequestUnknownUserInfo(List<String> messageFromAccounts) { List<String> unknownAccounts = new ArrayList<>(); for (String account : messageFromAccounts) { if (!NimUserInfoCache.getInstance().hasUser(account)) { unknownAccounts.add(account); } } if (!unknownAccounts.isEmpty()) { requestUnknownUser(unknownAccounts); } } @Override public void onAgree(SystemMessage message) { onSystemNotificationDeal(message, true); } @Override public void onReject(SystemMessage message) { onSystemNotificationDeal(message, false); } @Override public void onLongPressed(SystemMessage message) { showLongClickMenu(message); } private void onSystemNotificationDeal(final SystemMessage message, final boolean pass) { RequestCallback callback = new RequestCallback<Void>() { @Override public void onSuccess(Void param) { onProcessSuccess(pass, message); } @Override public void onFailed(int code) { onProcessFailed(code, message); } @Override public void onException(Throwable exception) { } }; if (message.getType() == SystemMessageType.TeamInvite) { if (pass) { NIMClient.getService(TeamService.class).acceptInvite(message.getTargetId(), message.getFromAccount()).setCallback(callback); } else { NIMClient.getService(TeamService.class).declineInvite(message.getTargetId(), message.getFromAccount(), "").setCallback(callback); } } else if (message.getType() == SystemMessageType.ApplyJoinTeam) { if (pass) { NIMClient.getService(TeamService.class).passApply(message.getTargetId(), message.getFromAccount()).setCallback(callback); } else { NIMClient.getService(TeamService.class).rejectApply(message.getTargetId(), message.getFromAccount(), "").setCallback(callback); } } else if (message.getType() == SystemMessageType.AddFriend) { NIMClient.getService(FriendService.class).ackAddFriendRequest(message.getFromAccount(), pass).setCallback(callback); } } private void onProcessSuccess(final boolean pass, SystemMessage message) { SystemMessageStatus status = pass ? SystemMessageStatus.passed : SystemMessageStatus.declined; NIMClient.getService(SystemMessageService.class).setSystemMessageStatus(message.getMessageId(), status); message.setStatus(status); refreshViewHolder(message); } private void onProcessFailed(final int code, SystemMessage message) { Toast.makeText(SystemMessageActivity.this, "failed, error code=" + code, Toast.LENGTH_LONG).show(); if (code == 408) { return; } SystemMessageStatus status = SystemMessageStatus.expired; NIMClient.getService(SystemMessageService.class).setSystemMessageStatus(message.getMessageId(), status); message.setStatus(status); refreshViewHolder(message); } private void refresh() { runOnUiThread(new Runnable() { @Override public void run() { adapter.notifyDataSetChanged(); } }); } private void refreshViewHolder(final SystemMessage message) { final long messageId = message.getMessageId(); int index = -1; for (int i = 0; i < items.size(); i++) { SystemMessage item = items.get(i); if (messageId == item.getMessageId()) { index = i; break; } } if (index < 0) { return; } final int m = index; runOnUiThread(new Runnable() { @Override public void run() { if (m < 0) { return; } Object tag = ListViewUtil.getViewHolderByIndex(listView, m); if (tag instanceof SystemMessageViewHolder) { ((SystemMessageViewHolder) tag).refreshDirectly(message); } } }); } private void registerSystemObserver(boolean register) { NIMClient.getService(SystemMessageObserver.class).observeReceiveSystemMsg(systemMessageObserver, register); } Observer<SystemMessage> systemMessageObserver = new Observer<SystemMessage>() { @Override public void onEvent(SystemMessage systemMessage) { onIncomingMessage(systemMessage); } }; private void requestUnknownUser(List<String> accounts) { NimUserInfoCache.getInstance().getUserInfoFromRemote(accounts, new RequestCallbackWrapper<List<NimUserInfo>>() { @Override public void onResult(int code, List<NimUserInfo> users, Throwable exception) { if (code == ResponseCode.RES_SUCCESS) { if (users != null && !users.isEmpty()) { refresh(); } } } }); } private void deleteAllMessages() { NIMClient.getService(SystemMessageService.class).clearSystemMessages(); NIMClient.getService(SystemMessageService.class).resetSystemMessageUnreadCount(); items.clear(); refresh(); Toast.makeText(SystemMessageActivity.this, R.string.clear_all_success, Toast.LENGTH_SHORT).show(); } private void showLongClickMenu(final SystemMessage message) { CustomAlertDialog alertDialog = new CustomAlertDialog(this); alertDialog.setTitle(R.string.delete_tip); String title = getString(R.string.delete_system_message); alertDialog.addItem(title, new CustomAlertDialog.onSeparateItemClickListener() { @Override public void onClick() { deleteSystemMessage(message); } }); alertDialog.show(); } private void deleteSystemMessage(final SystemMessage message) { NIMClient.getService(SystemMessageService.class).deleteSystemMessage(message.getMessageId()); items.remove(message); refresh(); Toast.makeText(SystemMessageActivity.this, R.string.delete_success, Toast.LENGTH_SHORT).show(); } }