├── .gitignore ├── android ├── src │ └── main │ │ ├── aidl │ │ └── android │ │ │ └── content │ │ │ └── pm │ │ │ ├── PackageStats.aidl │ │ │ ├── IPackageStatsObserver.aidl │ │ │ └── IPackageDataObserver.aidl │ │ ├── res │ │ ├── raw │ │ │ ├── rp.wav │ │ │ └── msg.wav │ │ ├── drawable-hdpi │ │ │ ├── nim_avatar_group.png │ │ │ ├── ic_stat_notify_msg.png │ │ │ └── nim_avatar_default.png │ │ └── values │ │ │ ├── dimens.xml │ │ │ └── strings.xml │ │ ├── assets │ │ └── pinyin │ │ │ └── index.dat │ │ └── java │ │ └── com │ │ └── netease │ │ └── im │ │ ├── uikit │ │ ├── UIKit.java │ │ ├── contact │ │ │ └── core │ │ │ │ ├── model │ │ │ │ ├── AbsContact.java │ │ │ │ ├── TeamContact.java │ │ │ │ ├── TeamMemberContact.java │ │ │ │ ├── IContact.java │ │ │ │ ├── ContactGroupStrategy.java │ │ │ │ ├── ContactDataTask.java │ │ │ │ └── ContactDataList.java │ │ │ │ ├── item │ │ │ │ ├── ContactItemFilter.java │ │ │ │ ├── LabelItem.java │ │ │ │ ├── AbsContactItem.java │ │ │ │ ├── ItemTypes.java │ │ │ │ ├── TextItem.java │ │ │ │ ├── ContactIdFilter.java │ │ │ │ ├── MsgItem.java │ │ │ │ └── ContactItem.java │ │ │ │ ├── query │ │ │ │ ├── IContactDataProvider.java │ │ │ │ ├── TextQuery.java │ │ │ │ └── SimpleT9Matcher.java │ │ │ │ ├── ContactProvider.java │ │ │ │ ├── provider │ │ │ │ ├── ContactDataProvider.java │ │ │ │ ├── UserDataProvider.java │ │ │ │ ├── TeamMemberDataProvider.java │ │ │ │ ├── TeamDataProvider.java │ │ │ │ └── MsgDataProvider.java │ │ │ │ └── util │ │ │ │ └── ContactHelper.java │ │ ├── cache │ │ │ └── SimpleCallback.java │ │ ├── permission │ │ │ └── annotation │ │ │ │ ├── OnMPermissionGranted.java │ │ │ │ ├── OnMPermissionDenied.java │ │ │ │ └── OnMPermissionNeverAskAgain.java │ │ ├── common │ │ │ ├── util │ │ │ │ ├── sys │ │ │ │ │ ├── ClipboardUtil.java │ │ │ │ │ └── ReflectionUtil.java │ │ │ │ ├── string │ │ │ │ │ ├── StringTextWatcher.java │ │ │ │ │ ├── MD5.java │ │ │ │ │ └── StringUtil.java │ │ │ │ ├── storage │ │ │ │ │ └── StorageType.java │ │ │ │ ├── C.java │ │ │ │ └── log │ │ │ │ │ └── LogUtil.java │ │ │ ├── framework │ │ │ │ └── NimSingleThreadExecutor.java │ │ │ └── media │ │ │ │ └── BitmapUtil.java │ │ ├── uinfo │ │ │ ├── UserUpdateHelper.java │ │ │ ├── UserInfoObservable.java │ │ │ └── UserInfoHelper.java │ │ └── session │ │ │ └── helper │ │ │ ├── MessageListPanelHelper.java │ │ │ └── MessageHelper.java │ │ ├── session │ │ ├── ShowTimeUtil.java │ │ ├── SessionObserver.java │ │ └── extension │ │ │ ├── CustomAttachmentType.java │ │ │ ├── CustomAttachment.java │ │ │ ├── DefaultCustomAttachment.java │ │ │ ├── LinkUrlAttachment.java │ │ │ ├── BankTransferAttachment.java │ │ │ ├── RedPacketAttachement.java │ │ │ ├── CardAttachment.java │ │ │ ├── CustomAttachParser.java │ │ │ ├── AccountNoticeAttachment.java │ │ │ └── BankTransferSystemAttachment.java │ │ ├── group │ │ ├── IData.java │ │ ├── DefaultGroupStrategy.java │ │ ├── LabeItem.java │ │ ├── AbstractItem.java │ │ ├── TextItem.java │ │ ├── DefaultItem.java │ │ ├── GroupStrategy.java │ │ └── DefaultDataList.java │ │ ├── common │ │ ├── push │ │ │ ├── Extras.java │ │ │ ├── CustomPushContentProvider.java │ │ │ └── NimMixPushMessageHandler.java │ │ ├── ResourceUtil.java │ │ ├── sys │ │ │ ├── SystemUtil.java │ │ │ └── InstallUtil.java │ │ └── ToolUtil.java │ │ ├── RNNeteaseImPackage.java │ │ ├── receiver │ │ ├── CustomNotificationCache.java │ │ ├── NetworkReceiver.java │ │ └── CustomNotificationReceiver.java │ │ ├── recent │ │ └── RecentService.java │ │ ├── contact │ │ └── DefaultContactProvider.java │ │ ├── team │ │ └── TeamObserver.java │ │ ├── RNAppCacheUtilModule.java │ │ └── ImPushConfig.java ├── libs │ └── MiPush_SDK_Client_3_6_2.jar └── build.gradle ├── ios └── RNNeteaseIm │ ├── RNNeteaseIm.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcuserdata │ │ │ └── VisonMac.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── VisonMac.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist │ └── RNNeteaseIm │ ├── Util │ ├── NIMKitInfo.m │ ├── NIMKitInfoFetchOption.m │ ├── NIMKitDataProviderImpl.h │ ├── NTESSDKConfigDelegate.h │ ├── Model │ │ ├── NTESGroupedContacts.h │ │ ├── NTESContactDataMember.h │ │ ├── NSDictionary+NTESJson.h │ │ ├── NTESGroupedDataCollection.h │ │ ├── NTESGroupedContacts.m │ │ ├── NTESContactDataMember.m │ │ └── NSDictionary+NTESJson.m │ ├── NTESClientUtil.h │ ├── Spelling │ │ ├── NTESPinyinConverter.h │ │ ├── NTESSpellingCenter.h │ │ └── NTESPinyinConverter.m │ ├── NSString+NIMKit.h │ ├── NIMKitInfoFetchOption.h │ ├── NIMKitLocationPoint.h │ ├── NTESClientUtil.m │ ├── NIMKitInfo.h │ ├── NIMKitUtil.h │ ├── NIMKitDataProvider.h │ ├── NIMKitTimerHolder.h │ ├── NTESSDKConfigDelegate.m │ ├── NIMKitNotificationFirer.h │ ├── NIMKitLocationPoint.m │ ├── NIMMessageMaker.h │ ├── NIMKitTimerHolder.m │ ├── NIMKit.h │ ├── NSString+NIMKit.m │ ├── NTESBundleSetting.h │ ├── NIMKitNotificationFirer.m │ └── NIMKit.m │ ├── RNNeteaseIm.h │ ├── RNNotificationCenter.h │ ├── DWCustomAttachmentDecoder.h │ ├── DWCustomAttachment.h │ ├── NIMObject.h │ ├── BankListViewController.h │ ├── Info.plist │ ├── NIMViewController.h │ ├── NIMObject.m │ ├── NoticeViewController.h │ ├── ContactViewController.h │ ├── NIMModel.h │ ├── ImConfig.h │ ├── PrefixHeader.pch │ ├── DWCustomAttachment.m │ ├── NTESGlobalMacro.h │ ├── TeamViewController.h │ ├── BankListViewController.m │ ├── DWCustomAttachmentDecoder.m │ └── ConversationViewController.h ├── package.json ├── index.js ├── RNNeteaseIm.podspec ├── Utils.js └── im └── Friend.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | android/*.iml 3 | android/build 4 | android/.idea/ 5 | .DS_Store 6 | .idea/ 7 | react-native-android.md 8 | -------------------------------------------------------------------------------- /android/src/main/aidl/android/content/pm/PackageStats.aidl: -------------------------------------------------------------------------------- 1 | package android.content.pm; 2 | 3 | parcelable PackageStats; -------------------------------------------------------------------------------- /android/src/main/res/raw/rp.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnativecomponent/react-native-netease-im/HEAD/android/src/main/res/raw/rp.wav -------------------------------------------------------------------------------- /android/src/main/res/raw/msg.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnativecomponent/react-native-netease-im/HEAD/android/src/main/res/raw/msg.wav -------------------------------------------------------------------------------- /android/libs/MiPush_SDK_Client_3_6_2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnativecomponent/react-native-netease-im/HEAD/android/libs/MiPush_SDK_Client_3_6_2.jar -------------------------------------------------------------------------------- /android/src/main/assets/pinyin/index.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnativecomponent/react-native-netease-im/HEAD/android/src/main/assets/pinyin/index.dat -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/UIKit.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit; 2 | 3 | /** 4 | * Created by dowin on 2017/4/28. 5 | */ 6 | 7 | public class UIKit { 8 | } 9 | -------------------------------------------------------------------------------- /android/src/main/res/drawable-hdpi/nim_avatar_group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnativecomponent/react-native-netease-im/HEAD/android/src/main/res/drawable-hdpi/nim_avatar_group.png -------------------------------------------------------------------------------- /android/src/main/res/drawable-hdpi/ic_stat_notify_msg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnativecomponent/react-native-netease-im/HEAD/android/src/main/res/drawable-hdpi/ic_stat_notify_msg.png -------------------------------------------------------------------------------- /android/src/main/res/drawable-hdpi/nim_avatar_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnativecomponent/react-native-netease-im/HEAD/android/src/main/res/drawable-hdpi/nim_avatar_default.png -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/ShowTimeUtil.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session; 2 | 3 | /** 4 | * Created by dowin on 2017/5/5. 5 | */ 6 | 7 | public class ShowTimeUtil { 8 | } 9 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/SessionObserver.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session; 2 | 3 | /** 4 | * Created by dowin on 2017/5/3. 5 | */ 6 | 7 | public class SessionObserver { 8 | } 9 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/model/AbsContact.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.model; 2 | 3 | public abstract class AbsContact implements IContact { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /android/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 48dip 6 | 60dip 7 | 8 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/item/ContactItemFilter.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.item; 2 | 3 | import java.io.Serializable; 4 | 5 | public interface ContactItemFilter extends Serializable { 6 | boolean filter(AbsContactItem item); 7 | } 8 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitInfo.m 3 | // NIMKit 4 | // 5 | // Created by amao on 2016/11/17. 6 | // Copyright © 2016年 NetEase. All rights reserved. 7 | // 8 | 9 | #import "NIMKitInfo.h" 10 | 11 | @implementation NIMKitInfo 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/RNNeteaseIm.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNNeteaseIm.h 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/5/9. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | 10 | #import "RCTViewManager.h" 11 | 12 | @interface RNNeteaseIm : RCTViewManager 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm.xcodeproj/project.xcworkspace/xcuserdata/VisonMac.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reactnativecomponent/react-native-netease-im/HEAD/ios/RNNeteaseIm/RNNeteaseIm.xcodeproj/project.xcworkspace/xcuserdata/VisonMac.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitInfoFetchOption.m: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitInfoFetchOption.m 3 | // NIMKit 4 | // 5 | // Created by chris on 2016/12/26. 6 | // Copyright © 2016年 NetEase. All rights reserved. 7 | // 8 | 9 | #import "NIMKitInfoFetchOption.h" 10 | 11 | @implementation NIMKitInfoFetchOption 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/group/IData.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.group; 2 | 3 | /** 4 | * Created by dowin on 2017/8/16. 5 | */ 6 | 7 | public interface IData { 8 | 9 | /** 10 | * get contact's display name to show to user 11 | * 12 | * @return 13 | */ 14 | String getDisplayName(); 15 | } 16 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitDataProviderImpl.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitDataProviderImpl.h 3 | // NIMKit 4 | // 5 | // Created by chris on 2016/10/31. 6 | // Copyright © 2016年 NetEase. All rights reserved. 7 | // 8 | 9 | #import "NIMKitDataProvider.h" 10 | 11 | @interface NIMKitDataProviderImpl : NSObject 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NTESSDKConfigDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESSDKConfig.h 3 | // NIM 4 | // 5 | // Created by amao on 5/9/16. 6 | // Copyright © 2016 Netease. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImConfig.h" 11 | 12 | @interface NTESSDKConfigDelegate : NSObject 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/RNNotificationCenter.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNNotificationCenter.h 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/5/24. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RNNotificationCenter : NSObject 12 | + (instancetype)sharedCenter; 13 | - (void)start; 14 | @end 15 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/Model/NTESGroupedContacts.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESGroupedContacts.h 3 | // NIM 4 | // 5 | // Created by Xuhui on 15/3/2. 6 | // Copyright (c) 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #import "NTESGroupedDataCollection.h" 10 | 11 | @class NTESContactsManager; 12 | 13 | @interface NTESGroupedContacts : NTESGroupedDataCollection 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/DWCustomAttachmentDecoder.h: -------------------------------------------------------------------------------- 1 | // 2 | // DWCustomAttachmentDecoder.h 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/6/13. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImConfig.h" 11 | 12 | @interface DWCustomAttachmentDecoder : NSObject 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/common/push/Extras.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.common.push; 2 | 3 | public interface Extras { 4 | 5 | String EXTRA_JUMP_P2P = "EXTRA_JUMP_P2P"; 6 | 7 | String EXTRA_DATA = "data"; 8 | 9 | String EXTRA_FROM = "from"; 10 | 11 | String EXTRA_FROM_NOTIFICATION = "from_notification"; 12 | 13 | // 参数 14 | String EXTRA_ACCOUNT = "account"; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NTESClientUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESClientUtil.h 3 | // NIM 4 | // 5 | // Created by chris on 15/7/27. 6 | // Copyright (c) 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImConfig.h" 11 | 12 | @interface NTESClientUtil : NSObject 13 | 14 | + (NSString *)clientName:(NIMLoginClientType)clientType; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/cache/SimpleCallback.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.cache; 2 | 3 | /** 4 | * 简单的回调接口 5 | * Created by huangjun on 2015/11/19. 6 | */ 7 | public interface SimpleCallback { 8 | 9 | /** 10 | * 回调函数返回结果 11 | * 12 | * @param success 是否成功,结果是否有效 13 | * @param result 结果 14 | */ 15 | void onResult(boolean success, T result); 16 | } 17 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/Model/NTESContactDataMember.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESContactDataMember.h 3 | // NIM 4 | // 5 | // Created by chris on 15/9/21. 6 | // Copyright © 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImConfig.h" 11 | 12 | @interface NTESContactDataMember : NSObject 13 | 14 | @property (nonatomic,strong) NIMKitInfo *info; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/Spelling/NTESPinyinConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESPinyinConverter.h 3 | // NIM 4 | // 5 | // Created by amao on 10/15/13. 6 | // Copyright (c) 2013 Netease. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NTESPinyinConverter : NSObject 12 | + (NTESPinyinConverter *)sharedInstance; 13 | 14 | - (NSString *)toPinyin: (NSString *)source; 15 | @end 16 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/query/IContactDataProvider.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.query; 2 | 3 | 4 | import com.netease.im.uikit.contact.core.item.AbsContactItem; 5 | import java.util.List; 6 | 7 | /** 8 | * 通讯录数据源提供者接口 9 | * Created by huangjun on 2015/4/2. 10 | */ 11 | public interface IContactDataProvider { 12 | public List provide(TextQuery query); 13 | } 14 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/DWCustomAttachment.h: -------------------------------------------------------------------------------- 1 | // 2 | // DWCustomAttachment.h 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/6/13. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImConfig.h" 11 | 12 | @interface DWCustomAttachment : NSObject 13 | @property (assign, nonatomic) NSInteger custType; 14 | @property (strong, nonatomic) NSDictionary *dataDict; 15 | @end 16 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/group/DefaultGroupStrategy.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.group; 2 | 3 | /** 4 | * Created by dowin on 2017/8/16. 5 | */ 6 | 7 | public class DefaultGroupStrategy extends GroupStrategy { 8 | 9 | public DefaultGroupStrategy() { 10 | add(GroupStrategy.GROUP_NULL, -1, ""); 11 | addABC(0); 12 | } 13 | 14 | @Override 15 | public String belongs(AbstractItem item) { 16 | return super.belongs(item); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /android/src/main/aidl/android/content/pm/IPackageStatsObserver.aidl: -------------------------------------------------------------------------------- 1 | package android.content.pm; 2 | 3 | import android.content.pm.PackageStats; 4 | /** 5 | * API for package data change related callbacks from the Package Manager. 6 | * Some usage scenarios include deletion of cache directory, generate 7 | * statistics related to code, data, cache usage(TODO) 8 | */ 9 | oneway interface IPackageStatsObserver { 10 | 11 | void onGetStatsCompleted(in PackageStats pStats, boolean succeeded); 12 | } -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm.xcodeproj/xcuserdata/VisonMac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | RNNeteaseIm.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NSString+NIMKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+NIM.h 3 | // NIMKit 4 | // 5 | // Created by chris. 6 | // Copyright (c) 2015年 NetEase. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (NIMKit) 12 | 13 | - (CGSize)nim_stringSizeWithFont:(UIFont *)font; 14 | 15 | - (NSString *)nim_MD5String; 16 | 17 | - (NSUInteger)nim_getBytesLength; 18 | 19 | - (NSString *)nim_stringByDeletingPictureResolution; 20 | 21 | - (UIColor *)nim_hexToColor; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/permission/annotation/OnMPermissionGranted.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.permission.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * register a method invoked when permission requests are succeeded. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.METHOD) 13 | public @interface OnMPermissionGranted { 14 | int value(); 15 | } 16 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/NIMObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMObject.h 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/5/17. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImConfig.h" 11 | 12 | @interface NIMObject : NSObject 13 | +(instancetype)initNIMObject; 14 | @property(nonatomic,strong)NSString *attachment; 15 | //下载本地视频 16 | - (void)downLoadVideo:(NIMVideoObject *)videoObject Error:(void(^)(NSError *error))handler progress:(void(^)(float progress))succ; 17 | @end 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "name": "react-native-netease-im", 4 | "version": "3.0.0", 5 | "description": "网易云信ReactNative插件", 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [ 11 | "react-native" 12 | ], 13 | "repository" : 14 | { "type" : "git", 15 | "url" : "https://github.com/reactnativecomponent/react-native-netease-im.git" 16 | }, 17 | "author": "", 18 | "license": "", 19 | "peerDependencies": { 20 | "react-native": ">=0.60.0" 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/permission/annotation/OnMPermissionDenied.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.permission.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * register a method invoked when permission requests are denied without check never ask again. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.METHOD) 13 | public @interface OnMPermissionDenied { 14 | int value(); 15 | } -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/item/LabelItem.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.item; 2 | 3 | public class LabelItem extends AbsContactItem { 4 | private final String text; 5 | 6 | public LabelItem(String text) { 7 | this.text = text; 8 | } 9 | 10 | @Override 11 | public int getItemType() { 12 | return ItemTypes.LABEL; 13 | } 14 | 15 | @Override 16 | public String belongsGroup() { 17 | return null; 18 | } 19 | 20 | public final String getText() { 21 | return text; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/group/LabeItem.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.group; 2 | 3 | /** 4 | * Created by dowin on 2017/8/16. 5 | */ 6 | 7 | public class LabeItem extends AbstractItem{ 8 | private final String text; 9 | 10 | public LabeItem(String text) { 11 | this.text = text; 12 | } 13 | 14 | @Override 15 | public int getItemType() { 16 | return -1; 17 | } 18 | 19 | @Override 20 | public String belongsGroup() { 21 | return null; 22 | } 23 | 24 | public final String getText() { 25 | return text; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/permission/annotation/OnMPermissionNeverAskAgain.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.permission.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * register some methods handling the user's choice to permanently deny permissions checking never ask again. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.METHOD) 13 | public @interface OnMPermissionNeverAskAgain { 14 | int value(); 15 | } 16 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/group/AbstractItem.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.group; 2 | 3 | /** 4 | * Created by dowin on 2017/8/16. 5 | */ 6 | 7 | public abstract class AbstractItem { 8 | /** 9 | * 所属的类型 10 | * 11 | */ 12 | public abstract int getItemType(); 13 | 14 | /** 15 | * 所属的分组 16 | */ 17 | public abstract String belongsGroup(); 18 | 19 | protected final int compareType(AbstractItem item) { 20 | return compareType(getItemType(), item.getItemType()); 21 | } 22 | 23 | public static int compareType(int lhs, int rhs) { 24 | return lhs - rhs; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitInfoFetchOption.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitInfoFetchOption.h 3 | // NIMKit 4 | // 5 | // Created by chris on 2016/12/26. 6 | // Copyright © 2016年 NetEase. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class NIMSession; 12 | @class NIMMessage; 13 | 14 | @interface NIMKitInfoFetchOption : NSObject 15 | 16 | /** 17 | * 所属会话 18 | */ 19 | @property (nonatomic,strong) NIMSession *session; 20 | 21 | /** 22 | * 所属消息 23 | */ 24 | @property (nonatomic,strong) NIMMessage *message; 25 | 26 | /** 27 | * 屏蔽备注名 28 | */ 29 | @property (nonatomic,assign) BOOL forbidaAlias; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/BankListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BankListViewController.h 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/5/12. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NIMModel.h" 11 | typedef void(^Success)(id param); 12 | typedef void(^Errors)(id erro); 13 | @interface BankListViewController : UIViewController 14 | +(instancetype)initWithBankListViewController; 15 | -(void)getBlackList; 16 | -(void)addToBlackList:(NSString *)contactId success:(Success)suc Err:(Errors)err; 17 | -(void)removeFromBlackList:(NSString *)contactId success:(Success)suc Err:(Errors)err; 18 | @end 19 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/common/push/CustomPushContentProvider.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.common.push; 2 | 3 | import com.netease.nimlib.sdk.msg.model.IMMessage; 4 | 5 | import java.util.Map; 6 | 7 | /** 8 | * 用户自定义推送 content 以及 payload 的接口 9 | */ 10 | 11 | public interface CustomPushContentProvider { 12 | 13 | /** 14 | * 在消息发出去之前,回调此方法,用户需实现自定义的推送文案 15 | * 16 | * @param message 17 | */ 18 | String getPushContent(IMMessage message); 19 | 20 | /** 21 | * 在消息发出去之前,回调此方法,用户需实现自定义的推送payload,它可以被消息接受者在通知栏点击之后得到 22 | * 23 | * @param message 24 | */ 25 | Map getPushPayload(IMMessage message); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import NimUtils from './Utils'; 2 | import NimFriend from './im/Friend'; 3 | import NimSession from './im/Session'; 4 | import NimSystemMsg from './im/SystemMsg'; 5 | import NimTeam from './im/Team'; 6 | /** 7 | *监听列表 8 | *observeRecentContact 最近会话 9 | *observeOnlineStatus 在线状态 10 | *observeFriend 联系人/好友 11 | *observeTeam 群组 12 | *observeBlackList 黑名单 13 | *observeReceiveMessage 接收消息 14 | *observeReceiveSystemMsg 系统通知 15 | *observeUnreadCountChange 未读消息数 16 | *observeMsgStatus 发送消息状态变化 17 | *observeAudioRecord 录音状态 18 | *observeDeleteMessage 撤销后删除消息 19 | *observeAttachmentProgress 未读数变化 20 | *observeOnKick 被踢出下线 21 | */ 22 | export {NimUtils, NimFriend, NimSession, NimSystemMsg, NimTeam}; 23 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/common/ResourceUtil.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.common; 2 | 3 | import com.netease.im.IMApplication; 4 | 5 | import androidx.annotation.NonNull; 6 | import androidx.annotation.StringRes; 7 | 8 | /** 9 | * Created by dowin on 2017/4/28. 10 | */ 11 | 12 | public class ResourceUtil { 13 | 14 | @NonNull 15 | public final static String getString(@StringRes int resId) { 16 | 17 | return IMApplication.getContext().getResources().getString(resId); 18 | } 19 | @NonNull 20 | public final static String getString(@StringRes int resId, Object... formatArgs) { 21 | return IMApplication.getContext().getString(resId, formatArgs); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitLocationPoint.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitLocationPoint.h 3 | // NIM 4 | // 5 | // Created by chris on 15/2/28. 6 | // Copyright (c) 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | @class NIMLocationObject; 12 | 13 | @interface NIMKitLocationPoint : NSObject 14 | 15 | @property (nonatomic, readonly) CLLocationCoordinate2D coordinate; 16 | 17 | @property (nonatomic, readonly, copy) NSString *title; 18 | 19 | - (instancetype)initWithLocationObject:(NIMLocationObject *)locationObject; 20 | 21 | - (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate andTitle:(NSString*)title; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NTESClientUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // NTESClientUtil.m 3 | // NIM 4 | // 5 | // Created by chris on 15/7/27. 6 | // Copyright (c) 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #import "NTESClientUtil.h" 10 | 11 | 12 | @implementation NTESClientUtil 13 | 14 | + (NSString *)clientName:(NIMLoginClientType)clientType{ 15 | switch (clientType) { 16 | case NIMLoginClientTypeAOS: 17 | case NIMLoginClientTypeiOS: 18 | case NIMLoginClientTypeWP: 19 | return @"移动"; 20 | case NIMLoginClientTypePC: 21 | return @"电脑"; 22 | case NIMLoginClientTypeWeb: 23 | return @"网页"; 24 | default: 25 | return @""; 26 | } 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/extension/CustomAttachmentType.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session.extension; 2 | 3 | /** 4 | * Created by zhoujianghua on 2015/4/9. 5 | */ 6 | public interface CustomAttachmentType { 7 | 8 | 9 | String RedPacket = "redpacket";//红包 10 | String BankTransfer = "transfer";//转账 11 | 12 | String BankTransferSystem= "system";//系统消息 13 | String RedPacketOpen = "redpacketOpen";//拆红包提醒 14 | 15 | String ProfileCard = "ProfileCard";//个人名片 16 | String Collection = "Collection";//收藏 17 | String SystemImageText = "SystemImageText";//系统富文本消息 18 | 19 | 20 | String LinkUrl = "url";//链接 21 | String AccountNotice = "account_notice";//账户变动通知 22 | String Card = "card";//账户变动通知 23 | 24 | } 25 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/item/AbsContactItem.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.item; 2 | 3 | /** 4 | * 通讯录数据项抽象类 5 | * Created by huangjun on 2015/2/10. 6 | */ 7 | public abstract class AbsContactItem { 8 | /** 9 | * 所属的类型 10 | * 11 | * @see com.netease.im.uikit.contact.core.item.ItemTypes 12 | */ 13 | public abstract int getItemType(); 14 | 15 | /** 16 | * 所属的分组 17 | */ 18 | public abstract String belongsGroup(); 19 | 20 | protected final int compareType(AbsContactItem item) { 21 | return compareType(getItemType(), item.getItemType()); 22 | } 23 | 24 | public static int compareType(int lhs, int rhs) { 25 | return lhs - rhs; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/Model/NSDictionary+NTESJson.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+NTESJson.h 3 | // NIM 4 | // 5 | // Created by amao on 13-7-12. 6 | // Copyright (c) 2013年 Netease. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface NSDictionary (NTESJson) 13 | - (NSString *)jsonString: (NSString *)key; 14 | 15 | - (NSDictionary *)jsonDict: (NSString *)key; 16 | - (NSArray *)jsonArray: (NSString *)key; 17 | - (NSArray *)jsonStringArray: (NSString *)key; 18 | 19 | 20 | - (BOOL)jsonBool: (NSString *)key; 21 | - (NSInteger)jsonInteger: (NSString *)key; 22 | - (long long)jsonLongLong: (NSString *)key; 23 | - (unsigned long long)jsonUnsignedLongLong:(NSString *)key; 24 | 25 | - (double)jsonDouble: (NSString *)key; 26 | @end 27 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/common/util/sys/ClipboardUtil.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.common.util.sys; 2 | 3 | import android.content.Context; 4 | import android.text.ClipboardManager; 5 | 6 | public class ClipboardUtil { 7 | public static final void clipboardCopyText(Context context, CharSequence text) { 8 | ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 9 | if (cm != null) { 10 | cm.setText(text); 11 | } 12 | } 13 | 14 | public static final int clipboardTextLength(Context context) { 15 | ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); 16 | CharSequence text = cm != null ? cm.getText() : null; 17 | return text != null ? text.length() : 0; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/ContactProvider.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core; 2 | 3 | import com.netease.nimlib.sdk.uinfo.model.UserInfo; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 通讯录(联系人)数据源提供者 9 | */ 10 | public interface ContactProvider { 11 | /** 12 | * 返回本地所有好友用户信息(通讯录一般列出所有的好友) 13 | * 14 | * @return 用户信息集合 15 | */ 16 | List getUserInfoOfMyFriends(); 17 | 18 | /** 19 | * 返回我的好友数量,提供给通讯录显示所有联系人数量使用 20 | * 21 | * @return 好友个数 22 | */ 23 | int getMyFriendsCount(); 24 | 25 | /** 26 | * 返回一个用户显示名(例如:如果有昵称显示昵称,如果没有显示帐号) 27 | * 28 | * @param account 用户帐号 29 | * @return 显示名 30 | */ 31 | String getUserDisplayName(String account); 32 | } 33 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/item/ItemTypes.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.item; 2 | 3 | /** 4 | * 通讯录列表项类型 5 | * Created by huangjun on 2015/2/10. 6 | */ 7 | public interface ItemTypes { 8 | 9 | /** 10 | * 基础类型 11 | */ 12 | int TEXT = -2; 13 | 14 | int LABEL = -1; 15 | 16 | /** 17 | * 扩展类型 18 | */ 19 | int FUNC = 0; // 功能项 20 | 21 | int FRIEND = 1; // 好友项 22 | 23 | int TEAM = 2; // 群组项 24 | 25 | int TEAM_MEMBER = 3; // 群成员 26 | 27 | int MSG = 4; // 消息 28 | 29 | /** 30 | * 子类型 31 | */ 32 | interface TEAMS { 33 | int BASE = ItemTypes.TEAM << 16; 34 | 35 | int NORMAL_TEAM = BASE + 1; // 普通群 36 | 37 | int ADVANCED_TEAM = BASE + 2; // 高级群 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitInfo.h 3 | // NIMKit 4 | // 5 | // Created by amao on 2016/11/17. 6 | // Copyright © 2016年 NetEase. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NIMKitInfo : NSObject 13 | /** 14 | * id,如果是用户信息,为用户id;如果是群信息,为群id 15 | */ 16 | @property (nonatomic,copy) NSString *infoId; 17 | 18 | /** 19 | * 显示名 20 | */ 21 | @property (nonatomic,copy) NSString *showName; 22 | 23 | 24 | //如果avatarUrlString为nil,则显示头像图片 25 | //如果avatarUrlString不为nil,则将头像图片当做占位图,当下载完成后显示头像url指定的图片。 26 | 27 | /** 28 | * 头像url 29 | */ 30 | @property (nonatomic,copy) NSString *avatarUrlString; 31 | 32 | /** 33 | * 头像图片 34 | */ 35 | @property (nonatomic,strong) UIImage *avatarImage; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMUtil.h 3 | // NIMKit 4 | // 5 | // Created by chris on 15/8/10. 6 | // Copyright (c) 2015年 NetEase. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImConfig.h" 11 | 12 | 13 | @interface NIMKitUtil : NSObject 14 | 15 | + (NSString *)showNick:(NSString *)uid inMessage:(NIMMessage *)message; 16 | 17 | + (NSString *)showNick:(NSString *)uid inSession:(NIMSession *)session; 18 | 19 | + (NSString *)showTime:(NSTimeInterval)msglastTime showDetail:(BOOL)showDetail; 20 | 21 | + (NSString *)messageTipContent:(NIMMessage *)message; 22 | 23 | + (BOOL)canEditTeamInfo:(NIMTeamMember *)member; 24 | 25 | + (BOOL)canInviteMember:(NIMTeamMember *)member; 26 | 27 | + (NSString*)teamNotificationFormatedMessage:(NIMMessage *)message; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 网络连接失败,请检查你的网络设置 4 | 录音失败,请重试 5 | 未知大小 6 | 帐号或密码错误 7 | 登录失败: 8 | 无效输入 9 | 邀请失败,成员人数上限为%1$d人 10 | 创建失败,创建群数量达到限制 11 | 发送时间超过2分钟的消息,不能被撤回 12 | 需要身份验证 13 | 允许任何人加入 14 | 不允许任何人申请加入 15 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/NIMViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMViewController.h 3 | // NIM 4 | // 5 | // Created by Dowin on 2017/5/8. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NIMModel.h" 11 | #import "NTESClientUtil.h" 12 | typedef void(^SUCCESS) (id param); 13 | typedef void(^ERROR)(NSString *error); 14 | @interface NIMViewController : UIViewController 15 | 16 | @property (copy, nonatomic) NSString *strAccount; 17 | @property (copy, nonatomic) NSString *strToken; 18 | 19 | +(instancetype)initWithController; 20 | -(instancetype)initWithNIMController; 21 | -(void)deleteCurrentSession:(NSString *)recentContactId andback:(ERROR)error; 22 | //获取最近聊天列表回调 23 | -(void)getRecentContactListsuccess:(SUCCESS)suc andError:(ERROR)err; 24 | -(void)addDelegate; 25 | - (void)getResouces; 26 | @end 27 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/Spelling/NTESSpellingCenter.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESSpellingCenter.h 3 | // NIM 4 | // 用于拼音全称和简称生成查询读取的类 5 | // Created by amao on 13-1-21. 6 | // Copyright (c) 2013年 Netease. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SpellingUnit : NSObject 12 | @property (nonatomic,strong) NSString *fullSpelling; 13 | @property (nonatomic,strong) NSString *shortSpelling; 14 | @end 15 | 16 | @interface NTESSpellingCenter : NSObject 17 | { 18 | NSMutableDictionary *_spellingCache; //全拼,简称cache 19 | NSString *_filepath; 20 | } 21 | + (NTESSpellingCenter *)sharedCenter; 22 | - (void)saveSpellingCache; //写入缓存 23 | 24 | - (SpellingUnit *)spellingForString: (NSString *)source; //全拼,简拼 (全是小写) 25 | - (NSString *)firstLetter: (NSString *)input; //首字母 26 | @end 27 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/model/TeamContact.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.model; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.netease.nimlib.sdk.team.model.Team; 6 | 7 | public class TeamContact extends AbsContact { 8 | 9 | private Team team; 10 | 11 | public TeamContact(Team team) { 12 | this.team = team; 13 | } 14 | 15 | @Override 16 | public String getContactId() { 17 | return team == null ? "" : team.getId(); 18 | } 19 | 20 | @Override 21 | public int getContactType() { 22 | return IContact.Type.Team; 23 | } 24 | 25 | @Override 26 | public String getDisplayName() { 27 | String name = team.getName(); 28 | 29 | return TextUtils.isEmpty(name) ? team.getId() : name; 30 | } 31 | 32 | public Team getTeam() { 33 | return team; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitDataProvider.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitDataProvider.h 3 | // NIMKit 4 | // 5 | // Created by amao on 8/13/15. 6 | // Copyright (c) 2015 NetEase. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class NIMSession; 12 | @class NIMKitInfo; 13 | @class NIMKitInfoFetchOption; 14 | 15 | @protocol NIMKitDataProvider 16 | 17 | @optional 18 | 19 | /** 20 | * 上层提供用户信息的接口 21 | * 22 | * @param userId 用户ID 23 | * @param option 获取选项 24 | * 25 | * @return 用户信息 26 | */ 27 | - (NIMKitInfo *)infoByUser:(NSString *)userId 28 | option:(NIMKitInfoFetchOption *)option; 29 | 30 | 31 | /** 32 | * 上层提供群组信息的接口 33 | * 34 | * @param teamId 群组ID 35 | * @param option 获取选项 36 | * 37 | * @return 群组信息 38 | */ 39 | - (NIMKitInfo *)infoByTeam:(NSString *)teamId 40 | option:(NIMKitInfoFetchOption *)option; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitTimerHolder.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitTimerHolder.h 3 | // NIM 4 | // 5 | // Created by amao on 5/16/14. 6 | // Copyright (c) 2014 amao. All rights reserved. 7 | // 8 | 9 | //M80TimerHolder,管理某个Timer,功能为 10 | //1.隐藏NSTimer,使得NSTimer只能retain M80TimerHolder 11 | //2.对于非repeats的Timer,执行一次后自动释放Timer 12 | //3.对于repeats的Timer,需要持有M80TimerHolder的对象在析构时调用[M80TimerHolder stopTimer] 13 | 14 | #import 15 | 16 | @class NIMKitTimerHolder; 17 | 18 | @protocol NIMKitTimerHolderDelegate 19 | - (void)onNIMKitTimerFired:(NIMKitTimerHolder *)holder; 20 | @end 21 | 22 | @interface NIMKitTimerHolder : NSObject 23 | @property (nonatomic,weak) id timerDelegate; 24 | 25 | - (void)startTimer:(NSTimeInterval)seconds 26 | delegate:(id)delegate 27 | repeats:(BOOL)repeats; 28 | 29 | - (void)stopTimer; 30 | @end 31 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/model/TeamMemberContact.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.model; 2 | 3 | import com.netease.im.uikit.cache.TeamDataCache; 4 | import com.netease.nimlib.sdk.team.model.TeamMember; 5 | 6 | /** 7 | * Created by huangjun on 2015/5/5. 8 | */ 9 | public class TeamMemberContact extends AbsContact { 10 | 11 | private TeamMember teamMember; 12 | 13 | public TeamMemberContact(TeamMember teamMember) { 14 | this.teamMember = teamMember; 15 | } 16 | 17 | @Override 18 | public String getContactId() { 19 | return teamMember.getAccount(); 20 | } 21 | 22 | @Override 23 | public int getContactType() { 24 | return Type.TeamMember; 25 | } 26 | 27 | @Override 28 | public String getDisplayName() { 29 | return TeamDataCache.getInstance().getTeamMemberDisplayName(teamMember.getTid(), teamMember.getAccount()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/group/TextItem.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.group; 2 | 3 | import android.text.TextUtils; 4 | 5 | /** 6 | * Created by dowin on 2017/8/16. 7 | */ 8 | 9 | public class TextItem extends AbstractItem implements Comparable { 10 | private final String text; 11 | 12 | public TextItem(String text) { 13 | this.text = text != null ? text : ""; 14 | } 15 | 16 | public final String getText() { 17 | return text; 18 | } 19 | 20 | @Override 21 | public int getItemType() { 22 | return 0; 23 | } 24 | 25 | @Override 26 | public String belongsGroup() { 27 | String group = TextComparator.getLeadingUp(text); 28 | 29 | return !TextUtils.isEmpty(group) ? group : GroupStrategy.GROUP_SHARP; 30 | } 31 | 32 | @Override 33 | public int compareTo(TextItem item) { 34 | return TextComparator.compareIgnoreCase(text, item.text); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NTESSDKConfigDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // NTESSDKConfig.m 3 | // NIM 4 | // 5 | // Created by amao on 5/9/16. 6 | // Copyright © 2016 Netease. All rights reserved. 7 | // 8 | 9 | #import "NTESSDKConfigDelegate.h" 10 | 11 | 12 | @implementation NTESSDKConfigDelegate 13 | - (BOOL)shouldIgnoreNotification:(NIMNotificationObject *)notification 14 | { 15 | BOOL ignore = NO; 16 | NIMNotificationContent *content = notification.content; 17 | if ([content isKindOfClass:[NIMTeamNotificationContent class]]) //这里做个示范如何忽略部分通知 (不在聊天界面显示) 18 | { 19 | NSArray *types = @[]; 20 | NIMTeamOperationType type = [(NIMTeamNotificationContent *)content operationType]; 21 | for (NSString *item in types) 22 | { 23 | if (type == [item integerValue]) 24 | { 25 | ignore = YES; 26 | break; 27 | } 28 | } 29 | } 30 | return ignore; 31 | } 32 | @end 33 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitNotificationFirer.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitNotificationFirer.h 3 | // NIMKit 4 | // 5 | // Created by chris on 16/6/13. 6 | // Copyright © 2016年 NetEase. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "NIMKitTimerHolder.h" 12 | 13 | 14 | @class NIMKitFirerInfo; 15 | 16 | @interface NIMKitNotificationFirer : NSObject 17 | 18 | @property (nonatomic,strong) NSMutableDictionary *cachedInfo; 19 | 20 | @property (nonatomic,strong) NIMKitTimerHolder *timer; 21 | 22 | @property (nonatomic,assign) NSTimeInterval timeInterval; 23 | 24 | - (void)addFireInfo:(NIMKitFirerInfo *)info; 25 | 26 | @end 27 | 28 | 29 | @interface NIMKitFirerInfo : NSObject 30 | 31 | @property (nonatomic,strong) NIMSession *session; 32 | 33 | @property (nonatomic,copy) NSString *notificationName; 34 | 35 | - (NSObject *)fireObject; 36 | 37 | - (NSString *)saveIdentity; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/model/IContact.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.model; 2 | 3 | public interface IContact { 4 | 5 | interface Type { 6 | 7 | /** 8 | * TYPE USER 9 | */ 10 | int Friend = 0x1; 11 | 12 | /** 13 | * TYPE TEAM 14 | */ 15 | int Team = 0x2; 16 | 17 | /** 18 | * TYPE TEAM MEMBER 19 | */ 20 | int TeamMember = 0x03; 21 | 22 | /** 23 | * TYPE_MSG 24 | */ 25 | int Msg = 0x04; 26 | } 27 | 28 | /** 29 | * get contact id 30 | * 31 | * @return 32 | */ 33 | String getContactId(); 34 | 35 | /** 36 | * get contact type {@link Type} 37 | * 38 | * @return 39 | */ 40 | int getContactType(); 41 | 42 | /** 43 | * get contact's display name to show to user 44 | * 45 | * @return 46 | */ 47 | String getDisplayName(); 48 | } 49 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/NIMObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // NIMObject.m 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/5/17. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import "NIMObject.h" 10 | 11 | @implementation NIMObject 12 | +(instancetype)initNIMObject{ 13 | static NIMObject *nimObj = nil; 14 | static dispatch_once_t onceToken; 15 | dispatch_once(&onceToken, ^{ 16 | nimObj = [[NIMObject alloc]init]; 17 | }); 18 | return nimObj; 19 | } 20 | - (void)downLoadVideo:(NIMVideoObject *)videoObject Error:(void(^)(NSError *error))handler progress:(void(^)(float progress))succ { 21 | __weak typeof(self) wself = self; 22 | [[NIMSDK sharedSDK].resourceManager download:videoObject.url filepath:videoObject.path progress:^(float progress) { 23 | succ(progress); 24 | } completion:^(NSError *error) { 25 | if (wself) { 26 | if (handler) { 27 | handler(error); 28 | } 29 | } 30 | }]; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/item/TextItem.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.item; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.netease.im.uikit.contact.core.model.ContactGroupStrategy; 6 | import com.netease.im.uikit.contact.core.query.TextComparator; 7 | 8 | public class TextItem extends AbsContactItem implements Comparable { 9 | private final String text; 10 | 11 | public TextItem(String text) { 12 | this.text = text != null ? text : ""; 13 | } 14 | 15 | public final String getText() { 16 | return text; 17 | } 18 | 19 | @Override 20 | public int getItemType() { 21 | return ItemTypes.TEXT; 22 | } 23 | 24 | @Override 25 | public String belongsGroup() { 26 | String group = TextComparator.getLeadingUp(text); 27 | 28 | return !TextUtils.isEmpty(group) ? group : ContactGroupStrategy.GROUP_SHARP; 29 | } 30 | 31 | @Override 32 | public int compareTo(TextItem item) { 33 | return TextComparator.compareIgnoreCase(text, item.text); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/item/ContactIdFilter.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.item; 2 | 3 | 4 | import com.netease.im.uikit.contact.core.model.IContact; 5 | 6 | import java.util.Collection; 7 | 8 | public class ContactIdFilter implements ContactItemFilter { 9 | private static final long serialVersionUID = -6813849507791265300L; 10 | 11 | private final Collection ids; 12 | 13 | private boolean exclude = true; // false means include 14 | 15 | public ContactIdFilter(Collection ids) { 16 | this.ids = ids; 17 | } 18 | 19 | public ContactIdFilter(Collection ids, boolean exclude) { 20 | this.ids = ids; 21 | this.exclude = exclude; 22 | } 23 | 24 | @Override 25 | public boolean filter(AbsContactItem item) { 26 | if (item instanceof ContactItem) { 27 | IContact contact = ((ContactItem) item).getContact(); 28 | boolean contains = ids.contains(contact.getContactId()); 29 | return exclude ? contains : !contains; 30 | } 31 | 32 | return false; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitLocationPoint.m: -------------------------------------------------------------------------------- 1 | // 2 | // NIMLocationPoint.m 3 | // NIM 4 | // 5 | // Created by chris on 15/2/28. 6 | // Copyright (c) 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #import "NIMKitLocationPoint.h" 10 | #import 11 | 12 | @implementation NIMKitLocationPoint 13 | 14 | - (instancetype)initWithLocationObject:(NIMLocationObject *)locationObject{ 15 | self = [super init]; 16 | if (self) { 17 | CLLocationCoordinate2D coordinate; 18 | coordinate.longitude = locationObject.longitude; 19 | coordinate.latitude = locationObject.latitude; 20 | _coordinate = coordinate; 21 | _title = locationObject.title; 22 | } 23 | return self; 24 | } 25 | 26 | - (instancetype)initWithCoordinate:(CLLocationCoordinate2D)coordinate andTitle:(NSString *)title{ 27 | self = [super init]; 28 | if (self) { 29 | _coordinate = coordinate; 30 | _title = title; 31 | } 32 | return self; 33 | } 34 | 35 | 36 | 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /RNNeteaseIm.podspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | 3 | 4 | require "json" 5 | 6 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 7 | version = package['version'] 8 | 9 | source = { :git => 'https://github.com/reactnativecomponent/react-native-netease-im.git' } 10 | if version == '1000.0.0' 11 | # This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in. 12 | source[:commit] = `git rev-parse HEAD`.strip 13 | else 14 | source[:tag] = "v#{version}" 15 | end 16 | 17 | Pod::Spec.new do |s| 18 | s.name = "RNNeteaseIm" 19 | s.version = version 20 | s.summary = "A React component for netease-im." 21 | s.homepage = "https://github.com/reactnativecomponent" 22 | s.requires_arc = true 23 | s.license = "None" 24 | s.author = {"Y_Kinooo" => "75438777@qq.com"} 25 | s.platform = :ios , "8.0" 26 | s.source = source 27 | s.source_files = "**/*.{h,m}" 28 | 29 | s.dependency 'React-Core' 30 | s.dependency "NIMSDK", "6.2.0" 31 | 32 | end 33 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/item/MsgItem.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.item; 2 | 3 | import com.netease.im.uikit.contact.core.model.IContact; 4 | import com.netease.nimlib.sdk.search.model.MsgIndexRecord; 5 | 6 | public class MsgItem extends AbsContactItem { 7 | private final IContact contact; 8 | 9 | private final MsgIndexRecord record; 10 | 11 | private final boolean querySession; 12 | 13 | public MsgItem(IContact contact, MsgIndexRecord record, boolean querySession) { 14 | this.contact = contact; 15 | this.record = record; 16 | this.querySession = querySession; 17 | } 18 | 19 | public IContact getContact() { 20 | return contact; 21 | } 22 | 23 | public MsgIndexRecord getRecord() { 24 | return record; 25 | } 26 | 27 | public boolean isQuerySession() { 28 | return querySession; 29 | } 30 | 31 | @Override 32 | public int getItemType() { 33 | return ItemTypes.MSG; 34 | } 35 | 36 | @Override 37 | public String belongsGroup() { 38 | return null; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/NoticeViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // NoticeViewController.h 3 | // NIM 4 | // 5 | // Created by Dowin on 2017/5/4. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NIMModel.h" 11 | typedef void(^Success)(id param); 12 | typedef void(^Errors)(id erro); 13 | typedef NS_ENUM(NSInteger, NotificationHandleType) { 14 | NotificationHandleTypePending = 0, 15 | NotificationHandleTypeOk, 16 | NotificationHandleTypeNo, 17 | NotificationHandleTypeOutOfDate 18 | }; 19 | 20 | static const NSInteger MaxNotificationCount = 20; 21 | @interface NoticeViewController : UIViewController 22 | +(instancetype)initWithNoticeViewController; 23 | -(void)initWithDelegate; 24 | - (void)stopSystemMsg; 25 | -(void)deleteNotice:(NSString *)targetID timestamp:(NSString *)timestamp; 26 | -(void)deleAllNotic; 27 | -(void)setAllread; 28 | -(void)onAccept:(NSString *)targetID timestamp:(NSString *)timestamp sucess:(Success)success error:(Errors)err; 29 | -(void)onRefuse:(NSString *)targetID timestamp:(NSString *)timestamp sucess:(Success)success error:(Errors)err; 30 | @end 31 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/uinfo/UserUpdateHelper.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.uinfo; 2 | 3 | import com.netease.nimlib.sdk.NIMClient; 4 | import com.netease.nimlib.sdk.RequestCallbackWrapper; 5 | import com.netease.nimlib.sdk.uinfo.UserService; 6 | import com.netease.nimlib.sdk.uinfo.constant.UserInfoFieldEnum; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * Created by hzxuwen on 2015/9/17. 13 | */ 14 | public class UserUpdateHelper { 15 | private static final String TAG = UserUpdateHelper.class.getSimpleName(); 16 | 17 | /** 18 | * 更新用户资料 19 | */ 20 | public static void update(final UserInfoFieldEnum field, final Object value, RequestCallbackWrapper callback) { 21 | Map fields = new HashMap<>(1); 22 | fields.put(field, value); 23 | update(fields, callback); 24 | } 25 | 26 | public static void update(final Map fields, final RequestCallbackWrapper callback) { 27 | NIMClient.getService(UserService.class).updateUserInfo(fields).setCallback(callback); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /android/src/main/aidl/android/content/pm/IPackageDataObserver.aidl: -------------------------------------------------------------------------------- 1 | /* 2 | ** 3 | ** Copyright 2007, The Android Open Source Project 4 | ** 5 | ** Licensed under the Apache License, Version 2.0 (the "License"); 6 | ** you may not use this file except in compliance with the License. 7 | ** You may obtain a copy of the License at 8 | ** 9 | ** http://www.apache.org/licenses/LICENSE-2.0 10 | ** 11 | ** Unless required by applicable law or agreed to in writing, software 12 | ** distributed under the License is distributed on an "AS IS" BASIS, 13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | ** See the License for the specific language governing permissions and 15 | ** limitations under the License. 16 | */ 17 | 18 | package android.content.pm; 19 | 20 | /** 21 | * API for package data change related callbacks from the Package Manager. 22 | * Some usage scenarios include deletion of cache directory, generate 23 | * statistics related to code, data, cache usage(TODO) 24 | */ 25 | oneway interface IPackageDataObserver { 26 | void onRemoveCompleted(in String packageName, boolean succeeded); 27 | } -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/RNNeteaseImPackage.java: -------------------------------------------------------------------------------- 1 | 2 | package com.netease.im; 3 | 4 | import com.facebook.react.ReactPackage; 5 | import com.facebook.react.bridge.JavaScriptModule; 6 | import com.facebook.react.bridge.NativeModule; 7 | import com.facebook.react.bridge.ReactApplicationContext; 8 | import com.facebook.react.uimanager.ViewManager; 9 | 10 | import java.util.Arrays; 11 | import java.util.Collections; 12 | import java.util.List; 13 | public class RNNeteaseImPackage implements ReactPackage { 14 | @Override 15 | public List createNativeModules(ReactApplicationContext reactContext) { 16 | return Arrays.asList( 17 | // new RNAppCacheUtilModule(reactContext), 18 | new RNPinYinModule(reactContext), 19 | new RNNeteaseImModule(reactContext)); 20 | } 21 | 22 | public List> createJSModules() { 23 | return Collections.emptyList(); 24 | } 25 | 26 | @Override 27 | public List createViewManagers(ReactApplicationContext reactContext) { 28 | return Collections.emptyList(); 29 | } 30 | } -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/Spelling/NTESPinyinConverter.m: -------------------------------------------------------------------------------- 1 | // 2 | // NTESPinyinConverter.m 3 | // NIM 4 | // 5 | // Created by amao on 10/15/13. 6 | // Copyright (c) 2013 Netease. All rights reserved. 7 | // 8 | 9 | #import "NTESPinyinConverter.h" 10 | 11 | 12 | @implementation NTESPinyinConverter 13 | + (NTESPinyinConverter *)sharedInstance 14 | { 15 | static NTESPinyinConverter *instance = nil; 16 | static dispatch_once_t onceToken; 17 | dispatch_once(&onceToken, ^{ 18 | instance = [[NTESPinyinConverter alloc] init]; 19 | }); 20 | return instance; 21 | } 22 | 23 | 24 | - (NSString *)toPinyin: (NSString *)source 25 | { 26 | if ([source length] == 0) 27 | { 28 | return nil; 29 | } 30 | NSMutableString *piyin = [NSMutableString stringWithString:source]; 31 | CFStringTransform((__bridge CFMutableStringRef)piyin, NULL, kCFStringTransformToLatin, false); 32 | 33 | NSString *py = [piyin stringByFoldingWithOptions:NSDiacriticInsensitiveSearch locale:[NSLocale currentLocale]]; 34 | return [py stringByReplacingOccurrencesOfString:@"'" withString:@""]; 35 | } 36 | 37 | 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/receiver/CustomNotificationCache.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.receiver; 2 | 3 | import com.netease.nimlib.sdk.msg.model.CustomNotification; 4 | 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * 自定义通知缓存 10 | *

11 | * Created by huangjun on 2015/5/29. 12 | */ 13 | public class CustomNotificationCache { 14 | 15 | public static CustomNotificationCache getInstance() { 16 | return InstanceHolder.instance; 17 | } 18 | 19 | private List notifications = new LinkedList<>(); 20 | 21 | public void addCustomNotification(CustomNotification notification) { 22 | if (notification == null) { 23 | return; 24 | } 25 | 26 | if (!notifications.contains(notification)) { 27 | notifications.add(0, notification); 28 | } 29 | } 30 | 31 | public List getCustomNotification() { 32 | return notifications; 33 | } 34 | 35 | public static class InstanceHolder { 36 | public final static CustomNotificationCache instance = new CustomNotificationCache(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMMessageMaker.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMMessageMaker.h 3 | // NIMKit 4 | // 5 | // Created by chris. 6 | // Copyright (c) 2015年 NetEase. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImConfig.h" 11 | 12 | @class NIMKitLocationPoint; 13 | 14 | @interface NIMMessageMaker : NSObject 15 | 16 | + (NIMMessage*)msgWithText:(NSString*)text andApnsMembers:(NSArray *)members andeSession:(NIMSession *)session; 17 | 18 | + (NIMMessage *)msgWithAudio:(NSString *)filePath andeSession:(NIMSession *)session; 19 | 20 | + (NIMMessage *)msgWithImage:(UIImage *)image andeSession:(NIMSession *)session; 21 | 22 | + (NIMMessage *)msgWithImagePath:(NSString *)path andeSession:(NIMSession *)session; 23 | 24 | + (NIMMessage *)msgWithVideo:(NSString *)filePath andeSession:(NIMSession *)session; 25 | 26 | + (NIMMessage *)msgWithLocation:(NIMKitLocationPoint*)locationPoint andeSession:(NIMSession *)session; 27 | 28 | + (NIMMessage*)msgWithCustom:(NIMObject *)attachment andeSession:(NIMSession *)session; 29 | 30 | + (NIMMessage*)msgWithCustomAttachment:(DWCustomAttachment *)attachment andeSession:(NIMSession *)session; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/ContactViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ContactViewController.h 3 | // NIM 4 | // 5 | // Created by Dowin on 2017/5/2. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NIMModel.h" 11 | 12 | typedef void(^Error)(NSString *error); 13 | typedef void(^Success)(id param); 14 | @interface ContactViewController : UIViewController 15 | +(instancetype)initWithContactViewController; 16 | -(void)initWithDelegate; 17 | -(void)getAllContactFriends; 18 | -(void)adduserId:(NSString *)userId andVerifyType:(NSString *)strType andMag:(NSString *)msg Friends:(Error)err Success:(Error )success; 19 | -(void)getUserInFo:(NSString *)userId Success:(Success )success; 20 | -(void)fetchUserInfos:(NSString *)userId Success:(Success )success error:(Error )error; 21 | -(void)deleteFriends:(NSString *)userId Success:(Success )success error:(Error )err; 22 | //获取好友列表,回调 23 | -(void)getFriendList:(Success )success error:(Error )error; 24 | - (void)disealloc; 25 | -(void)upDateUserInfo:(NSString *)contactId alias:(NSString *)alias Success:(Success )success error:(Error )err; 26 | -(void)updateMyUserInfo:(NSString *)strName; 27 | @end 28 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/extension/CustomAttachment.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session.extension; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.facebook.react.bridge.WritableMap; 5 | import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; 6 | 7 | /** 8 | * Created by zhoujianghua on 2015/4/9. 9 | */ 10 | public abstract class CustomAttachment implements MsgAttachment { 11 | 12 | protected String type; 13 | 14 | CustomAttachment(String type) { 15 | this.type = type; 16 | } 17 | 18 | public void fromJson(JSONObject data) { 19 | if (data != null) { 20 | parseData(data); 21 | } 22 | } 23 | 24 | @Override 25 | public String toJson(boolean send) { 26 | return CustomAttachParser.packData(type, packData()); 27 | } 28 | 29 | public String getType() { 30 | return type; 31 | } 32 | 33 | protected abstract void parseData(JSONObject data); 34 | protected abstract JSONObject packData(); 35 | protected abstract WritableMap toReactNative(); 36 | 37 | // protected abstract WritableMap packReactNative(); 38 | // protected abstract void packReactNative(ReadableMap map); 39 | 40 | } 41 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/recent/RecentService.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.recent; 2 | 3 | import com.netease.nimlib.sdk.Observer; 4 | import com.netease.nimlib.sdk.StatusCode; 5 | 6 | /** 7 | * Created by dowin on 2017/4/28. 8 | */ 9 | 10 | public class RecentService { 11 | 12 | private RecentService() { 13 | 14 | } 15 | 16 | static class InstanceHolder { 17 | final static RecentService instance = new RecentService(); 18 | } 19 | 20 | public static RecentService getInstance() { 21 | return InstanceHolder.instance; 22 | } 23 | Observer userStatusObserver = new Observer() { 24 | 25 | @Override 26 | public void onEvent(StatusCode code) { 27 | } 28 | }; 29 | private void registerObservers(boolean register) { 30 | // MsgServiceObserve service = NIMClient.getService(MsgServiceObserve.class); 31 | // service.observeReceiveMessage(messageReceiverObserver, register); 32 | // service.observeRecentContact(messageObserver, register); 33 | // service.observeMsgStatus(statusObserver, register); 34 | // service.observeRecentContactDeleted(deleteObserver, register); 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/common/util/string/StringTextWatcher.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.common.util.string; 2 | 3 | import android.text.Editable; 4 | import android.text.TextWatcher; 5 | import android.widget.EditText; 6 | 7 | /** 8 | * EditText字符数限制 9 | * Created by hzxuwen on 2015/5/22. 10 | */ 11 | public class StringTextWatcher implements TextWatcher{ 12 | private int length; 13 | private EditText editText; 14 | 15 | public StringTextWatcher(int length, EditText editText) { 16 | this.length = length; 17 | this.editText = editText; 18 | } 19 | @Override 20 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 21 | 22 | } 23 | 24 | @Override 25 | public void onTextChanged(CharSequence s, int start, int before, int count) { 26 | 27 | } 28 | 29 | @Override 30 | public void afterTextChanged(Editable s) { 31 | int editEnd = editText.getSelectionEnd(); 32 | editText.removeTextChangedListener(this); 33 | while (StringUtil.counterChars(s.toString()) > length && editEnd > 0) { 34 | s.delete(editEnd - 1, editEnd); 35 | editEnd--; 36 | } 37 | editText.setSelection(editEnd); 38 | editText.addTextChangedListener(this); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/contact/DefaultContactProvider.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.contact; 2 | 3 | import com.netease.im.uikit.cache.FriendDataCache; 4 | import com.netease.im.uikit.cache.NimUserInfoCache; 5 | import com.netease.im.uikit.contact.core.ContactProvider; 6 | import com.netease.nimlib.sdk.uinfo.model.NimUserInfo; 7 | import com.netease.nimlib.sdk.uinfo.model.UserInfo; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * UIKit默认的通讯录(联系人)数据源提供者, 14 | * Created by hzchenkang on 2016/12/19. 15 | */ 16 | 17 | public class DefaultContactProvider implements ContactProvider { 18 | 19 | @Override 20 | public List getUserInfoOfMyFriends() { 21 | List nimUsers = NimUserInfoCache.getInstance().getAllUsersOfMyFriend(); 22 | List users = new ArrayList<>(nimUsers.size()); 23 | if (!nimUsers.isEmpty()) { 24 | users.addAll(nimUsers); 25 | } 26 | 27 | return users; 28 | } 29 | 30 | @Override 31 | public int getMyFriendsCount() { 32 | return FriendDataCache.getInstance().getMyFriendCounts(); 33 | } 34 | 35 | @Override 36 | public String getUserDisplayName(String account) { 37 | return NimUserInfoCache.getInstance().getUserDisplayName(account); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/query/TextQuery.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.query; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.text.TextUtils; 5 | 6 | @SuppressLint("DefaultLocale") 7 | public final class TextQuery { 8 | public final String text; 9 | 10 | public final boolean t9; 11 | 12 | public boolean digit; 13 | 14 | public boolean letter; 15 | 16 | public boolean pinyin; 17 | 18 | public Object[] extra; 19 | 20 | public TextQuery(String text) { 21 | this(text, false); 22 | } 23 | 24 | public TextQuery(String text, boolean t9) { 25 | this.text = !TextUtils.isEmpty(text) ? text.toLowerCase() : text; 26 | this.t9 = t9; 27 | 28 | init(); 29 | } 30 | 31 | private void init() { 32 | if (TextUtils.isEmpty(text)) { 33 | return; 34 | } 35 | 36 | int digits = 0; 37 | int letters = 0; 38 | int pinyins = 0; 39 | 40 | for (int i = 0; i < text.length(); i++) { 41 | char chr = text.charAt(i); 42 | 43 | if ('0' <= chr && chr <= '9') { 44 | digits++; 45 | } else if ('a' <= chr && chr <= 'z') { 46 | letters++; 47 | } else if (PinYin.getIndex(chr) != -1) { 48 | pinyins++; 49 | } 50 | } 51 | 52 | digit = digits == text.length(); 53 | letter = letters == text.length(); 54 | pinyin = pinyins == text.length(); 55 | } 56 | } -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/Model/NTESGroupedDataCollection.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESGroupedDataCollection.h 3 | // NIM 4 | // 5 | // Created by Xuhui on 15/3/2. 6 | // Copyright (c) 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol NTESGroupMemberProtocol 12 | 13 | - (NSString *)groupTitle; 14 | - (NSString *)memberId; 15 | - (id)sortKey; 16 | 17 | @end 18 | 19 | @interface NTESGroupedDataCollection : NSObject 20 | 21 | @property (nonatomic, strong) NSArray *members; 22 | @property (nonatomic, copy) NSComparator groupTitleComparator; 23 | @property (nonatomic, copy) NSComparator groupMemberComparator; 24 | @property (nonatomic, readonly) NSArray *sortedGroupTitles; 25 | 26 | - (void)addGroupMember:(id)member; 27 | 28 | - (void)removeGroupMember:(id)member; 29 | 30 | - (void)addGroupAboveWithTitle:(NSString *)title members:(NSArray *)members; 31 | 32 | - (NSString *)titleOfGroup:(NSInteger)groupIndex; 33 | 34 | - (NSArray *)membersOfGroup:(NSInteger)groupIndex; 35 | 36 | - (id)memberOfIndex:(NSIndexPath *)indexPath; 37 | 38 | - (id)memberOfId:(NSString *)uid; 39 | 40 | - (NSInteger)groupCount; 41 | 42 | - (NSInteger)memberCountOfGroup:(NSInteger)groupIndex; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/common/sys/SystemUtil.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.common.sys; 2 | 3 | import android.app.ActivityManager; 4 | import android.content.Context; 5 | import android.text.TextUtils; 6 | 7 | /** 8 | * 系统工具箱 9 | */ 10 | public class SystemUtil { 11 | 12 | /** 13 | * 获取当前进程名 14 | * @param context 15 | * @return 进程名 16 | */ 17 | public static final String getProcessName(Context context) { 18 | String processName = null; 19 | 20 | // ActivityManager 21 | ActivityManager am = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)); 22 | 23 | while (true) { 24 | for (ActivityManager.RunningAppProcessInfo info : am.getRunningAppProcesses()) { 25 | if (info.pid == android.os.Process.myPid()) { 26 | processName = info.processName; 27 | 28 | break; 29 | } 30 | } 31 | 32 | // go home 33 | if (!TextUtils.isEmpty(processName)) { 34 | return processName; 35 | } 36 | 37 | // take a rest and again 38 | try { 39 | Thread.sleep(100L); 40 | } catch (InterruptedException ex) { 41 | ex.printStackTrace(); 42 | } 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/uinfo/UserInfoObservable.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.uinfo; 2 | 3 | import android.content.Context; 4 | import android.os.Handler; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * 用户资料变动观察者。 11 | */ 12 | public class UserInfoObservable { 13 | 14 | private List observers = new ArrayList<>(); 15 | private Handler uiHandler; 16 | 17 | public UserInfoObservable(Context context) { 18 | uiHandler = new Handler(context.getMainLooper()); 19 | } 20 | 21 | synchronized public void registerObserver(UserInfoObserver observer) { 22 | if (observer != null) { 23 | observers.add(observer); 24 | } 25 | } 26 | 27 | synchronized public void unregisterObserver(UserInfoObserver observer) { 28 | if (observer != null) { 29 | observers.remove(observer); 30 | } 31 | } 32 | 33 | synchronized public void notifyObservers(final List accounts) { 34 | uiHandler.post(new Runnable() { 35 | @Override 36 | public void run() { 37 | for (UserInfoObserver observer : observers) { 38 | observer.onUserInfoChanged(accounts); 39 | } 40 | } 41 | }); 42 | } 43 | 44 | public interface UserInfoObserver { 45 | void onUserInfoChanged(List accounts); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Descripttion: 工具类 3 | * @Author: huangjun 4 | * @Date: 2020-09-16 11:31:07 5 | * @LastEditors: huangjun 6 | * @LastEditTime: 2020-09-16 11:33:56 7 | */ 8 | 'use strict'; 9 | import {NativeModules, Platform, NetInfo} from 'react-native'; 10 | const {RNNeteaseIm, PinYin} = NativeModules; 11 | 12 | class Utils { 13 | /** 14 | * 清除数据缓存 15 | */ 16 | cleanCache() { 17 | return RNNeteaseIm.cleanCache(); 18 | } 19 | 20 | /** 21 | * 获取缓存大小 22 | */ 23 | getCacheSize() { 24 | return RNNeteaseIm.getCacheSize(); 25 | } 26 | 27 | 28 | /** 29 | * 播放录音 30 | * @returns {*} 31 | */ 32 | play(filepath) { 33 | return RNNeteaseIm.play(filepath); 34 | } 35 | 36 | /** 37 | * 播放本地资源音乐 38 | * name:iOS:文件名字,Android:文件路径 39 | * type:音乐类型,如:'mp3' 40 | * @returns {*} 41 | */ 42 | playLocacl(name, type) { 43 | if (Platform.OS === 'ios') { 44 | return RNNeteaseIm.playLocal(name, type); 45 | } 46 | return RNNeteaseIm.playLocal('assets:///' + name + '.' + type, type); 47 | } 48 | 49 | /** 50 | * 停止播放录音 51 | * @returns {*} 52 | */ 53 | stopPlay() { 54 | return RNNeteaseIm.stopPlay(); 55 | } 56 | 57 | sortPinYin(o, key) { 58 | return PinYin.sortPinYin(o, key); 59 | } 60 | 61 | /** 62 | * 仅限Android 63 | * @returns {*} 64 | */ 65 | fetchNetInfo() { 66 | return RNNeteaseIm.fetchNetInfo(); 67 | } 68 | } 69 | 70 | export default new Utils(); 71 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/common/ToolUtil.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.common; 2 | 3 | import android.content.Context; 4 | import android.media.MediaPlayer; 5 | import android.net.Uri; 6 | import android.text.TextUtils; 7 | import android.widget.Toast; 8 | 9 | import com.netease.im.R; 10 | import com.netease.im.login.LoginService; 11 | import com.netease.im.uikit.common.util.sys.NetworkUtil; 12 | 13 | import java.io.File; 14 | 15 | /** 16 | * Created by dowin on 2017/5/8. 17 | */ 18 | 19 | public class ToolUtil { 20 | 21 | public static boolean checkNetwork(Context context) { 22 | if (!NetworkUtil.isNetAvailable(context)) { 23 | Toast.makeText(context, R.string.network_is_not_available, Toast.LENGTH_SHORT).show(); 24 | return false; 25 | } else { 26 | return true; 27 | } 28 | } 29 | 30 | public static boolean checkAddFriend(Context context,String account) { 31 | if (!TextUtils.isEmpty(account) && account.equals(LoginService.getInstance().getAccount())) { 32 | Toast.makeText(context, "不能加自己为好友", Toast.LENGTH_SHORT).show(); 33 | return false; 34 | } 35 | return true; 36 | } 37 | private MediaPlayer getVideoMediaPlayer(Context context,File file) { 38 | try { 39 | return MediaPlayer.create(context, Uri.fromFile(file)); 40 | } catch (Exception e) { 41 | e.printStackTrace(); 42 | } 43 | return null; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/session/helper/MessageListPanelHelper.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.session.helper; 2 | 3 | import com.netease.nimlib.sdk.msg.model.IMMessage; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * 聊天消息列表辅助类 10 | * 主要用于某些需求场景下需要往聊天消息列表中手动添加消息、删除消息、或者清空消息列表。 11 | * Created by huangjun on 2015/7/8. 12 | */ 13 | public class MessageListPanelHelper { 14 | 15 | private static MessageListPanelHelper instance; 16 | 17 | private List observers = new ArrayList<>(); 18 | 19 | public static MessageListPanelHelper getInstance() { 20 | if (instance == null) { 21 | instance = new MessageListPanelHelper(); 22 | } 23 | 24 | return instance; 25 | } 26 | 27 | public interface LocalMessageObserver { 28 | void onAddMessage(IMMessage message); 29 | void onClearMessages(String account); 30 | } 31 | 32 | public void registerObserver(LocalMessageObserver o, boolean register) { 33 | if (register) { 34 | observers.add(o); 35 | } else { 36 | observers.remove(o); 37 | } 38 | } 39 | 40 | public void notifyAddMessage(IMMessage msg) { 41 | for (LocalMessageObserver o : observers) { 42 | o.onAddMessage(msg); 43 | } 44 | } 45 | 46 | public void notifyClearMessages(String account) { 47 | for (LocalMessageObserver o : observers) { 48 | o.onClearMessages(account); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/NIMModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMModel.h 3 | // NIM 4 | // 5 | // Created by Dowin on 2017/4/28. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef void(^onSuccess)(NSInteger index,id param); 12 | @interface NIMModel : NSObject 13 | +(instancetype)initShareMD; 14 | @property(nonatomic,strong)onSuccess myBlock; 15 | //@property(nonatomic,strong)NSMutableArray *recentListArr; 16 | @property (strong, nonatomic) NSDictionary *recentDict;//最近会话对象 17 | @property(nonatomic,strong)NSString *NetStatus; 18 | @property(nonatomic,strong)NSString *NIMKick; 19 | @property(nonatomic,strong)NSMutableDictionary *contactList; 20 | @property(nonatomic,strong)NSMutableArray *notiArr; 21 | @property(nonatomic,assign)NSInteger unreadCount; 22 | @property(nonatomic,strong)NSMutableArray *teamArr; 23 | @property(nonatomic,assign)NSMutableArray *ResorcesArr; 24 | @property(nonatomic,strong)NSMutableArray *sendState; 25 | @property(nonatomic,strong)NSDictionary *startSend; 26 | @property(nonatomic,strong)NSDictionary *endSend; 27 | @property(nonatomic,strong)NSDictionary *processSend; 28 | @property(nonatomic,strong)NSString *receipt; 29 | @property(nonatomic,strong)NSMutableArray *bankList; 30 | @property(nonatomic,strong)NSDictionary *audioDic; 31 | @property (strong, nonatomic) NSDictionary *deleteMessDict;//撤销时删除的消息ID 32 | @property (strong, nonatomic) NSDictionary *accountNoticeDict;//接收到资金变动的消息 33 | @property(nonatomic,strong)NSMutableArray *videoProgress; 34 | //- (void)insertMessages:(NSArray *)messages; 35 | @end 36 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitTimerHolder.m: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitTimerHolder.m 3 | // NIM 4 | // 5 | // Created by amao on 5/16/14. 6 | // Copyright (c) 2014 amao. All rights reserved. 7 | // 8 | 9 | #import "NIMKitTimerHolder.h" 10 | 11 | @interface NIMKitTimerHolder () 12 | { 13 | NSTimer *_timer; 14 | BOOL _repeats; 15 | } 16 | - (void)onTimer: (NSTimer *)timer; 17 | @end 18 | 19 | @implementation NIMKitTimerHolder 20 | 21 | - (void)dealloc 22 | { 23 | [self stopTimer]; 24 | } 25 | 26 | - (void)startTimer: (NSTimeInterval)seconds 27 | delegate: (id)delegate 28 | repeats: (BOOL)repeats 29 | { 30 | _timerDelegate = delegate; 31 | _repeats = repeats; 32 | if (_timer) 33 | { 34 | [_timer invalidate]; 35 | _timer = nil; 36 | } 37 | _timer = [NSTimer scheduledTimerWithTimeInterval:seconds 38 | target:self 39 | selector:@selector(onTimer:) 40 | userInfo:nil 41 | repeats:repeats]; 42 | } 43 | 44 | - (void)stopTimer 45 | { 46 | [_timer invalidate]; 47 | _timer = nil; 48 | _timerDelegate = nil; 49 | } 50 | 51 | - (void)onTimer: (NSTimer *)timer 52 | { 53 | if (!_repeats) 54 | { 55 | _timer = nil; 56 | } 57 | if (_timerDelegate && [_timerDelegate respondsToSelector:@selector(onNIMKitTimerFired:)]) 58 | { 59 | [_timerDelegate onNIMKitTimerFired:self]; 60 | } 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/item/ContactItem.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.item; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.netease.im.uikit.contact.core.model.ContactGroupStrategy; 6 | import com.netease.im.uikit.contact.core.model.IContact; 7 | import com.netease.im.uikit.contact.core.query.TextComparator; 8 | 9 | public class ContactItem extends AbsContactItem implements Comparable { 10 | private final IContact contact; 11 | 12 | private final int dataItemType; 13 | 14 | public ContactItem(IContact contact, int type) { 15 | this.contact = contact; 16 | this.dataItemType = type; 17 | } 18 | 19 | public IContact getContact() { 20 | return contact; 21 | } 22 | 23 | @Override 24 | public int getItemType() { 25 | return dataItemType; 26 | } 27 | 28 | @Override 29 | public int compareTo(ContactItem item) { 30 | // TYPE 31 | int compare = compareType(item); 32 | if (compare != 0) { 33 | return compare; 34 | } else { 35 | return TextComparator.compareIgnoreCase(getCompare(), item.getCompare()); 36 | } 37 | } 38 | 39 | @Override 40 | public String belongsGroup() { 41 | IContact contact = getContact(); 42 | if (contact == null) { 43 | return ContactGroupStrategy.GROUP_NULL; 44 | } 45 | 46 | String group = TextComparator.getLeadingUp(getCompare()); 47 | return !TextUtils.isEmpty(group) ? group : ContactGroupStrategy.GROUP_SHARP; 48 | } 49 | 50 | private String getCompare() { 51 | IContact contact = getContact(); 52 | return contact != null ? contact.getDisplayName() : null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/Model/NTESGroupedContacts.m: -------------------------------------------------------------------------------- 1 | // 2 | // NTESGroupedContacts.m 3 | // NIM 4 | // 5 | // Created by Xuhui on 15/3/2. 6 | // Copyright (c) 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #import "NTESGroupedContacts.h" 10 | #import "NTESContactDataMember.h" 11 | 12 | @interface NTESGroupedContacts () 13 | 14 | @end 15 | 16 | @implementation NTESGroupedContacts 17 | 18 | - (instancetype)init 19 | { 20 | self = [super init]; 21 | if(self) { 22 | self.groupTitleComparator = ^NSComparisonResult(NSString *title1, NSString *title2) { 23 | if ([title1 isEqualToString:@"#"]) { 24 | return NSOrderedDescending; 25 | } 26 | if ([title2 isEqualToString:@"#"]) { 27 | return NSOrderedAscending; 28 | } 29 | return [title1 compare:title2]; 30 | }; 31 | self.groupMemberComparator = ^NSComparisonResult(NSString *key1, NSString *key2) { 32 | return [key1 compare:key2]; 33 | }; 34 | [self update]; 35 | } 36 | return self; 37 | } 38 | 39 | - (void)update{ 40 | // NSMutableArray *contacts = [NSMutableArray array]; 41 | // for (NIMUser *user in [NIMSDK sharedSDK].userManager.myFriends) { 42 | // NIMKitInfo *info = [[NIMKit sharedKit] infoByUser:user.userId option:nil]; 43 | // NTESContactDataMember *contact = [[NTESContactDataMember alloc] init]; 44 | // contact.info = info; 45 | // [contacts addObject:contact]; 46 | // } 47 | // [self setMembers:contacts]; 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/receiver/NetworkReceiver.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.receiver; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.net.ConnectivityManager; 7 | import android.net.NetworkInfo; 8 | 9 | import com.facebook.react.bridge.Arguments; 10 | import com.facebook.react.bridge.WritableMap; 11 | import com.netease.im.ReactCache; 12 | import com.netease.im.login.LoginService; 13 | import com.netease.nimlib.sdk.NIMClient; 14 | import com.netease.nimlib.sdk.StatusCode; 15 | 16 | /** 17 | * Created by dowin on 2017/9/28. 18 | */ 19 | 20 | public class NetworkReceiver extends BroadcastReceiver { 21 | @Override 22 | public void onReceive(Context context, Intent intent) { 23 | 24 | ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 25 | // NetworkInfo mobileInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 26 | // NetworkInfo wifiInfo = manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 27 | NetworkInfo activeInfo = manager.getActiveNetworkInfo(); 28 | if (activeInfo != null && activeInfo.isAvailable()) { 29 | if (NIMClient.getStatus().shouldReLogin()) { 30 | LoginService.getInstance().autoLogin(); 31 | } 32 | } else { 33 | WritableMap r = Arguments.createMap(); 34 | r.putString("status", Integer.toString(StatusCode.NET_BROKEN.getValue())); 35 | ReactCache.emit(ReactCache.observeOnlineStatus, r); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/provider/ContactDataProvider.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.provider; 2 | 3 | 4 | import com.netease.im.uikit.contact.core.item.AbsContactItem; 5 | import com.netease.im.uikit.contact.core.item.ItemTypes; 6 | import com.netease.im.uikit.contact.core.query.IContactDataProvider; 7 | import com.netease.im.uikit.contact.core.query.TextQuery; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | public class ContactDataProvider implements IContactDataProvider { 13 | 14 | private int[] itemTypes; 15 | 16 | public ContactDataProvider(int... itemTypes) { 17 | this.itemTypes = itemTypes; 18 | } 19 | 20 | @Override 21 | public List provide(TextQuery query) { 22 | List data = new ArrayList<>(); 23 | 24 | for (int itemType : itemTypes) { 25 | data.addAll(provide(itemType, query)); 26 | } 27 | 28 | return data; 29 | } 30 | 31 | private final List provide(int itemType, TextQuery query) { 32 | switch (itemType) { 33 | case ItemTypes.FRIEND: 34 | return UserDataProvider.provide(query); 35 | case ItemTypes.TEAM: 36 | case ItemTypes.TEAMS.ADVANCED_TEAM: 37 | case ItemTypes.TEAMS.NORMAL_TEAM: 38 | return TeamDataProvider.provide(query, itemType); 39 | case ItemTypes.MSG: 40 | return MsgDataProvider.provide(query); 41 | default: 42 | return new ArrayList<>(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/ImConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImConfig.h 3 | // Test 4 | // 5 | // Created by Kinooo on 2019/12/26. 6 | // Copyright © 2019年 Kinooo. All rights reserved. 7 | // 8 | 9 | #ifndef ImConfig_h 10 | #define ImConfig_h 11 | 12 | #import 13 | #import "NTESGlobalMacro.h" 14 | #import "NIMKitInfo.h" 15 | #import "NIMKitUtil.h" 16 | #import "NIMKitInfoFetchOption.h" 17 | //#import 18 | #import 19 | 20 | #import "NIMKit.h" 21 | #import "NIMObject.h" 22 | #import "DWCustomAttachment.h" 23 | #define NTESNotifyID @"id" 24 | #define NTESCustomContent @"content" 25 | 26 | #define NTESCommandTyping (1) 27 | #define NTESCustom (2) 28 | 29 | //#ifdef DEBUG 30 | //static DDLogLevel ddLogLevel = DDLogLevelVerbose; 31 | //#else 32 | //static DDLogLevel ddLogLevel = DDLogLevelInfo; 33 | //#endif 34 | 35 | #define NTES_USE_CLEAR_BAR - (BOOL)useClearBar{return YES;} 36 | 37 | #define NTES_FORBID_INTERACTIVE_POP - (BOOL)forbidInteractivePop{return YES;} 38 | // Include any system framework and library headers here that should be included in all compilation units. 39 | // You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. 40 | #define CustomMessgeTypeUnknown 101 //未知消息类型 41 | #define CustomMessgeTypeRedpacket 5 //红包类型 redpacket 42 | #define CustomMessgeTypeBankTransfer 6 //转账类型 transfer 43 | #define CustomMessgeTypeUrl 7 // 连接类型 url 44 | #define CustomMessgeTypeAccountNotice 8 //账户通知,与账户金额相关变动 account_notice 45 | #define CustomMessgeTypeRedPacketOpenMessage 9 //发送拆红包 46 | #define CustomMessgeTypeBusinessCard 10 //名片 47 | #define CustomMessgeTypeCustom 102 //名片 48 | 49 | 50 | #endif /* ImConfig_h */ 51 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/PrefixHeader.pch: -------------------------------------------------------------------------------- 1 | // 2 | // PrefixHeader.pch 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/5/9. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | #ifndef PrefixHeader_pch 9 | #define PrefixHeader_pch 10 | #import 11 | #import "NTESGlobalMacro.h" 12 | #import "NIMKitInfo.h" 13 | #import "NIMKitUtil.h" 14 | #import "NIMKitInfoFetchOption.h" 15 | #import 16 | #import 17 | 18 | #import "NIMKit.h" 19 | #import "NIMObject.h" 20 | #import "DWCustomAttachment.h" 21 | #define NTESNotifyID @"id" 22 | #define NTESCustomContent @"content" 23 | 24 | #define NTESCommandTyping (1) 25 | #define NTESCustom (2) 26 | 27 | #ifdef DEBUG 28 | static DDLogLevel ddLogLevel = DDLogLevelVerbose; 29 | #else 30 | static DDLogLevel ddLogLevel = DDLogLevelInfo; 31 | #endif 32 | #define NTES_USE_CLEAR_BAR - (BOOL)useClearBar{return YES;} 33 | 34 | #define NTES_FORBID_INTERACTIVE_POP - (BOOL)forbidInteractivePop{return YES;} 35 | // Include any system framework and library headers here that should be included in all compilation units. 36 | // You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. 37 | #define CustomMessgeTypeUnknown 101 //未知消息类型 38 | #define CustomMessgeTypeRedpacket 5 //红包类型 redpacket 39 | #define CustomMessgeTypeBankTransfer 6 //转账类型 transfer 40 | #define CustomMessgeTypeUrl 7 // 连接类型 url 41 | #define CustomMessgeTypeAccountNotice 8 //账户通知,与账户金额相关变动 account_notice 42 | #define CustomMessgeTypeRedPacketOpenMessage 9 //发送拆红包 43 | #define CustomMessgeTypeBusinessCard 10 //名片 44 | #define CustomMessgeTypeCustom 102 //名片 45 | 46 | #endif /* PrefixHeader_pch */ 47 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/DWCustomAttachment.m: -------------------------------------------------------------------------------- 1 | // 2 | // DWCustomAttachment.m 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/6/13. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import "DWCustomAttachment.h" 10 | 11 | @implementation DWCustomAttachment 12 | 13 | - (NSString *)encodeAttachment{ 14 | NSString *strType = @""; 15 | switch (self.custType) { 16 | case CustomMessgeTypeRedpacket: 17 | strType = @"redpacket"; 18 | break; 19 | case CustomMessgeTypeBankTransfer: 20 | strType = @"transfer"; 21 | break; 22 | case CustomMessgeTypeUrl: 23 | strType = @"url"; 24 | break; 25 | case CustomMessgeTypeAccountNotice: 26 | strType = @"account_notice"; 27 | break; 28 | case CustomMessgeTypeRedPacketOpenMessage: 29 | strType = @"redpacketOpen"; 30 | break; 31 | case CustomMessgeTypeBusinessCard: 32 | strType = @"card"; 33 | break; 34 | case CustomMessgeTypeCustom: 35 | strType = @"custom"; 36 | break; 37 | default: 38 | strType = @"unknown"; 39 | break; 40 | } 41 | 42 | NSDictionary *dict = @{@"msgtype" : strType,@"data":self.dataDict}; 43 | NSData *data = [NSJSONSerialization dataWithJSONObject:dict 44 | options:0 45 | error:nil]; 46 | NSString *content = nil; 47 | if (data) { 48 | content = [[NSString alloc] initWithData:data 49 | encoding:NSUTF8StringEncoding]; 50 | } 51 | return content; 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/extension/DefaultCustomAttachment.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session.extension; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.facebook.react.bridge.Arguments; 5 | import com.facebook.react.bridge.WritableMap; 6 | 7 | /** 8 | * Created by zhoujianghua on 2015/4/10. 9 | */ 10 | public class DefaultCustomAttachment extends CustomAttachment { 11 | 12 | final static String KEY_DIGST = "digst"; 13 | private String content; 14 | private String digst; 15 | 16 | public DefaultCustomAttachment(String type) { 17 | super(type); 18 | } 19 | 20 | @Override 21 | protected void parseData(JSONObject data) { 22 | digst = data.getString(KEY_DIGST); 23 | content = data.toJSONString(); 24 | } 25 | 26 | @Override 27 | protected JSONObject packData() { 28 | JSONObject data = null; 29 | try { 30 | data = JSONObject.parseObject(content); 31 | if(data == null){ 32 | data = new JSONObject(); 33 | } 34 | data.put(KEY_DIGST, digst); 35 | } catch (Exception e) { 36 | e.printStackTrace(); 37 | } 38 | return data; 39 | } 40 | 41 | public void setContent(String content) { 42 | this.content = content; 43 | } 44 | 45 | public void setDigst(String digst) { 46 | this.digst = digst; 47 | } 48 | 49 | public String getDigst() { 50 | return digst; 51 | } 52 | 53 | @Override 54 | public WritableMap toReactNative() { 55 | WritableMap writableMap = Arguments.createMap(); 56 | writableMap.putString("digst", digst); 57 | writableMap.putString("content", content); 58 | return writableMap; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/query/SimpleT9Matcher.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.query; 2 | 3 | public class SimpleT9Matcher { 4 | 5 | private static final char[] LATIN_LETTERS_TO_DIGITS = { 6 | '2', '2', '2', // A,B,C -> 2 7 | '3', '3', '3', // D,E,F -> 3 8 | '4', '4', '4', // G,H,I -> 4 9 | '5', '5', '5', // J,K,L -> 5 10 | '6', '6', '6', // M,N,O -> 6 11 | '7', '7', '7', '7', // P,Q,R,S -> 7 12 | '8', '8', '8', // T,U,V -> 8 13 | '9', '9', '9', '9' // W,X,Y,Z -> 9 14 | }; 15 | 16 | private static boolean isAlphaNumberString(String name) { 17 | return name.matches("[0-9a-zA-Z]+"); 18 | } 19 | 20 | private static char getDialpadNumericCharacter(char ch) { 21 | if(ch >= 'A' && ch <= 'Z'){ 22 | ch = (char) (ch + ('a' - 'A')); 23 | } 24 | if (ch >= 'a' && ch <= 'z') { 25 | return LATIN_LETTERS_TO_DIGITS[ch - 'a']; 26 | } 27 | return ch; 28 | } 29 | 30 | /** 31 | * 将仅包含数字和字母的字符串转化为数字串(对应T9) 32 | * @param name 33 | * @return 34 | */ 35 | private static String alphaNumberStringToNumbericString(String name){ 36 | if(isAlphaNumberString(name)){ 37 | final int length = name.length(); 38 | StringBuilder builder = new StringBuilder(); 39 | for (int index = 0; index < length ; index++){ 40 | builder.append(getDialpadNumericCharacter(name.charAt(index))); 41 | } 42 | return builder.toString(); 43 | } 44 | return ""; 45 | } 46 | 47 | public static boolean hit(String text,String query){ 48 | return alphaNumberStringToNumbericString(text).contains(query); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/group/DefaultItem.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.group; 2 | 3 | import android.text.TextUtils; 4 | 5 | /** 6 | * Created by dowin on 2017/8/16. 7 | */ 8 | 9 | public class DefaultItem extends AbstractItem implements Comparable ,IData{ 10 | 11 | private final int dataItemType; 12 | private final String displayName; 13 | private T data; 14 | public DefaultItem(String displayName) { 15 | this.displayName = displayName; 16 | this.dataItemType = 1; 17 | } 18 | public DefaultItem(String displayName, int type) { 19 | this.displayName = displayName; 20 | this.dataItemType = type; 21 | } 22 | 23 | public void setData(T data) { 24 | this.data = data; 25 | } 26 | 27 | public T getData() { 28 | return data; 29 | } 30 | 31 | @Override 32 | public int getItemType() { 33 | return dataItemType; 34 | } 35 | 36 | @Override 37 | public int compareTo(DefaultItem item) { 38 | // TYPE 39 | int compare = compareType(item); 40 | if (compare != 0) { 41 | return compare; 42 | } else { 43 | return TextComparator.compareIgnoreCase(getCompare(), item.getCompare()); 44 | } 45 | } 46 | 47 | @Override 48 | public String belongsGroup() { 49 | if (displayName == null) { 50 | return GroupStrategy.GROUP_NULL; 51 | } 52 | 53 | String group = TextComparator.getLeadingUp(getCompare()); 54 | return !TextUtils.isEmpty(group) ? group : GroupStrategy.GROUP_SHARP; 55 | } 56 | 57 | private String getCompare() { 58 | return displayName; 59 | } 60 | 61 | @Override 62 | public String getDisplayName() { 63 | return displayName; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/common/util/storage/StorageType.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.common.util.storage; 2 | 3 | public enum StorageType { 4 | TYPE_LOG(DirectoryName.LOG_DIRECTORY_NAME), 5 | TYPE_TEMP(DirectoryName.TEMP_DIRECTORY_NAME), 6 | TYPE_FILE(DirectoryName.FILE_DIRECTORY_NAME), 7 | TYPE_AUDIO(DirectoryName.AUDIO_DIRECTORY_NAME), 8 | TYPE_IMAGE(DirectoryName.IMAGE_DIRECTORY_NAME), 9 | TYPE_VIDEO(DirectoryName.VIDEO_DIRECTORY_NAME), 10 | TYPE_THUMB_IMAGE(DirectoryName.THUMB_DIRECTORY_NAME), 11 | TYPE_THUMB_VIDEO(DirectoryName.THUMB_DIRECTORY_NAME), 12 | ; 13 | private DirectoryName storageDirectoryName; 14 | private long storageMinSize; 15 | 16 | public String getStoragePath() { 17 | return storageDirectoryName.getPath(); 18 | } 19 | 20 | public long getStorageMinSize() { 21 | return storageMinSize; 22 | } 23 | 24 | StorageType(DirectoryName dirName) { 25 | this(dirName, StorageUtil.THRESHOLD_MIN_SPCAE); 26 | } 27 | 28 | StorageType(DirectoryName dirName, long storageMinSize) { 29 | this.storageDirectoryName = dirName; 30 | this.storageMinSize = storageMinSize; 31 | } 32 | 33 | enum DirectoryName { 34 | AUDIO_DIRECTORY_NAME("audio/"), 35 | DATA_DIRECTORY_NAME("data/"), 36 | FILE_DIRECTORY_NAME("file/"), 37 | LOG_DIRECTORY_NAME("log/"), 38 | TEMP_DIRECTORY_NAME("temp/"), 39 | IMAGE_DIRECTORY_NAME("image/"), 40 | THUMB_DIRECTORY_NAME("thumb/"), 41 | VIDEO_DIRECTORY_NAME("video/"), 42 | ; 43 | 44 | private String path; 45 | 46 | public String getPath() { 47 | return path; 48 | } 49 | 50 | private DirectoryName(String path) { 51 | this.path = path; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/NTESGlobalMacro.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESGlobalMacro.h 3 | // NIMDemo 4 | // 5 | // Created by chris on 15/2/12. 6 | // Copyright (c) 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #ifndef NIMDemo_GlobalMacro_h 10 | #define NIMDemo_GlobalMacro_h 11 | 12 | #define IOS8 ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 8.0) 13 | #define UIScreenWidth [UIScreen mainScreen].bounds.size.width 14 | #define UIScreenHeight [UIScreen mainScreen].bounds.size.height 15 | #define UISreenWidthScale UIScreenWidth / 320 16 | 17 | 18 | #define UICommonTableBkgColor UIColorFromRGB(0xe4e7ec) 19 | #define Message_Font_Size 14 // 普通聊天文字大小 20 | #define Notification_Font_Size 10 // 通知文字大小 21 | #define Chatroom_Message_Font_Size 16 // 聊天室聊天文字大小 22 | 23 | 24 | #define SuppressPerformSelectorLeakWarning(Stuff) \ 25 | do { \ 26 | _Pragma("clang diagnostic push") \ 27 | _Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \ 28 | Stuff; \ 29 | _Pragma("clang diagnostic pop") \ 30 | } while (0) 31 | 32 | 33 | #pragma mark - UIColor宏定义 34 | #define UIColorFromRGBA(rgbValue, alphaValue) [UIColor \ 35 | colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ 36 | green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ 37 | blue:((float)(rgbValue & 0x0000FF))/255.0 \ 38 | alpha:alphaValue] 39 | 40 | #define UIColorFromRGB(rgbValue) UIColorFromRGBA(rgbValue, 1.0) 41 | 42 | #define dispatch_sync_main_safe(block)\ 43 | if ([NSThread isMainThread]) {\ 44 | block();\ 45 | } else {\ 46 | dispatch_sync(dispatch_get_main_queue(), block);\ 47 | } 48 | 49 | #define dispatch_async_main_safe(block)\ 50 | if ([NSThread isMainThread]) {\ 51 | block();\ 52 | } else {\ 53 | dispatch_async(dispatch_get_main_queue(), block);\ 54 | } 55 | 56 | 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | def DEFAULT_COMPILE_SDK_VERSION = 27 4 | def DEFAULT_BUILD_TOOLS_VERSION = "27.0.3" 5 | def DEFAULT_TARGET_SDK_VERSION = 27 6 | def DEFAULT_MIN_SDK_VERSION = 16 7 | def DEFAULT_SUPPOR_LIBVERSION = "27.0.3" 8 | 9 | android { 10 | // useLibrary 'org.apache.http.legacy' 11 | 12 | compileSdkVersion rootProject.hasProperty('compileSdkVersion') ? rootProject.compileSdkVersion : DEFAULT_COMPILE_SDK_VERSION 13 | 14 | 15 | defaultConfig { 16 | minSdkVersion rootProject.hasProperty('minSdkVersion') ? rootProject.minSdkVersion : DEFAULT_MIN_SDK_VERSION 17 | targetSdkVersion rootProject.hasProperty('targetSdkVersion') ? rootProject.targetSdkVersion : DEFAULT_TARGET_SDK_VERSION 18 | versionCode 1 19 | versionName "1.0" 20 | ndk { 21 | //设置支持的SO库架构 22 | abiFilters "armeabi-v7a", "x86","arm64-v8a","x86_64" 23 | } 24 | } 25 | buildTypes { 26 | release { 27 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 28 | } 29 | } 30 | sourceSets{ 31 | main{ 32 | jniLibs.srcDir(['libs']) 33 | } 34 | } 35 | lintOptions { 36 | abortOnError false 37 | } 38 | } 39 | 40 | repositories { 41 | mavenCentral() 42 | } 43 | 44 | dependencies { 45 | implementation fileTree(include: '*.jar', dir: 'libs') 46 | implementation 'com.facebook.react:react-native:+' 47 | // 基础功能 (必需) 48 | implementation 'com.netease.nimlib:basesdk:6.3.0' 49 | implementation 'com.netease.nimlib:push:6.3.0' 50 | implementation 'com.alibaba:fastjson:1.2.57' 51 | // implementation 'com.huawei.hms:push:3.0.3.301' 52 | implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' 53 | 54 | } 55 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/Model/NTESContactDataMember.m: -------------------------------------------------------------------------------- 1 | // 2 | // NTESContactDataMember.m 3 | // NIM 4 | // 5 | // Created by chris on 15/9/21. 6 | // Copyright © 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #import "NTESContactDataMember.h" 10 | #import "NTESSpellingCenter.h" 11 | 12 | @implementation NTESContactDataMember 13 | 14 | - (CGFloat)uiHeight{ 15 | return 50; 16 | } 17 | 18 | //userId和Vcname必有一个有值,根据有值的状态push进不同的页面 19 | 20 | - (NSString *)vcName{ 21 | return nil; 22 | } 23 | 24 | - (NSString *)reuseId{ 25 | return @"NTESContactDataItem"; 26 | } 27 | 28 | - (NSString *)cellName{ 29 | return @"NIMContactDataCell"; 30 | } 31 | 32 | - (NSString *)badge{ 33 | return @""; 34 | } 35 | 36 | - (NSString *)groupTitle { 37 | NSString *title = [[NTESSpellingCenter sharedCenter] firstLetter:self.info.showName].capitalizedString; 38 | unichar character = [title characterAtIndex:0]; 39 | if (character >= 'A' && character <= 'Z') { 40 | return title; 41 | }else{ 42 | return @"#"; 43 | } 44 | } 45 | 46 | - (NSString *)userId{ 47 | return self.info.infoId; 48 | } 49 | 50 | - (UIImage *)icon{ 51 | return self.info.avatarImage; 52 | } 53 | 54 | - (NSString *)avatarUrl{ 55 | return self.info.avatarUrlString; 56 | } 57 | 58 | - (NSString *)memberId{ 59 | return self.info.infoId; 60 | } 61 | 62 | - (NSString *)showName{ 63 | return self.info.showName; 64 | } 65 | 66 | - (BOOL)showAccessoryView{ 67 | return NO; 68 | } 69 | 70 | - (id)sortKey { 71 | return [[NTESSpellingCenter sharedCenter] spellingForString:self.info.showName].shortSpelling; 72 | } 73 | 74 | - (BOOL)isEqual:(id)object{ 75 | if (![object isKindOfClass:[self class]]) { 76 | return NO; 77 | } 78 | return [self.info.infoId isEqualToString:[[object info] infoId]]; 79 | } 80 | 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/common/util/string/MD5.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.common.util.string; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.FileInputStream; 5 | import java.io.UnsupportedEncodingException; 6 | import java.security.MessageDigest; 7 | 8 | public class MD5 { 9 | 10 | public static String getStringMD5(String value) { 11 | if (value == null || value.trim().length() < 1) { 12 | return null; 13 | } 14 | try { 15 | return getMD5(value.getBytes("UTF-8")); 16 | } catch (UnsupportedEncodingException e) { 17 | throw new RuntimeException(e.getMessage(), e); 18 | } 19 | } 20 | 21 | public static String getMD5(byte[] source) { 22 | try { 23 | MessageDigest md5 = MessageDigest.getInstance("MD5"); 24 | return HexDump.toHex(md5.digest(source)); 25 | } catch (Exception e) { 26 | throw new RuntimeException(e.getMessage(), e); 27 | } 28 | } 29 | 30 | public static String getStreamMD5(String filePath) { 31 | String hash=null; 32 | byte[] buffer = new byte[4096]; 33 | BufferedInputStream in=null; 34 | try 35 | { 36 | MessageDigest md5 = MessageDigest.getInstance("MD5"); 37 | in = new BufferedInputStream(new FileInputStream(filePath)); 38 | int numRead = 0; 39 | while ((numRead = in.read(buffer)) > 0) { 40 | md5.update(buffer, 0, numRead); 41 | } 42 | in.close(); 43 | hash = HexDump.toHex(md5.digest()); 44 | } catch (Exception e) { 45 | e.printStackTrace(); 46 | } finally { 47 | if (in != null) { 48 | try { 49 | in.close(); 50 | } catch (Exception ex) { 51 | ex.printStackTrace(); 52 | } 53 | } 54 | } 55 | return hash; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/team/TeamObserver.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.team; 2 | 3 | import com.netease.im.ReactCache; 4 | import com.netease.im.uikit.cache.TeamDataCache; 5 | import com.netease.im.uikit.contact.core.model.ContactDataList; 6 | import com.netease.nimlib.sdk.team.model.Team; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by dowin on 2017/5/9. 12 | */ 13 | 14 | public class TeamObserver { 15 | 16 | 17 | TeamListService teamListService = TeamListService.getInstance(); 18 | TeamDataCache.TeamDataChangedObserver teamDataChangedObserver=new TeamDataCache.TeamDataChangedObserver() { 19 | @Override 20 | public void onUpdateTeams(List teams) { 21 | teamListService.load(true); 22 | } 23 | 24 | @Override 25 | public void onRemoveTeam(Team team) { 26 | teamListService.load(true); 27 | } 28 | }; 29 | public void startTeamList(){ 30 | queryTeamList(); 31 | registerObserver(true); 32 | } 33 | public void stopTeamList(){ 34 | registerObserver(false); 35 | } 36 | void queryTeamList(){ 37 | teamListService.setOnLoadListener(new TeamListService.OnLoadListener() { 38 | @Override 39 | public void updateData(ContactDataList datas) { 40 | ReactCache.emit(ReactCache.observeTeam,ReactCache.createTeamList(datas)); 41 | } 42 | }); 43 | teamListService.load(true); 44 | } 45 | boolean hasRegister; 46 | void registerObserver(boolean register){ 47 | if(hasRegister&®ister){ 48 | return; 49 | } 50 | hasRegister = register; 51 | if(register) { 52 | TeamDataCache.getInstance().registerTeamDataChangedObserver(teamDataChangedObserver); 53 | }else { 54 | TeamDataCache.getInstance().unregisterTeamDataChangedObserver(teamDataChangedObserver); 55 | } 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/extension/LinkUrlAttachment.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session.extension; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.facebook.react.bridge.Arguments; 5 | import com.facebook.react.bridge.WritableMap; 6 | import com.netease.im.MessageConstant; 7 | 8 | /** 9 | * Created by dowin on 2017/6/14. 10 | */ 11 | 12 | public class LinkUrlAttachment extends CustomAttachment{ 13 | 14 | 15 | final String KEY_TITLE = "title"; 16 | final String KEY_DESCRIBE = "describe"; 17 | final String KEY_IMAGE = "image"; 18 | final String KEY_LINK_URL = "linkUrl"; 19 | private String title; 20 | private String describe; 21 | private String image; 22 | private String linkUrl; 23 | public LinkUrlAttachment() { 24 | super(CustomAttachmentType.LinkUrl); 25 | } 26 | 27 | @Override 28 | protected void parseData(JSONObject data) { 29 | title = data.getString(KEY_TITLE); 30 | describe = data.getString(KEY_DESCRIBE); 31 | image = data.getString(KEY_IMAGE); 32 | linkUrl = data.getString(KEY_LINK_URL); 33 | } 34 | 35 | @Override 36 | protected JSONObject packData() { 37 | JSONObject object = new JSONObject(); 38 | object.put(KEY_TITLE,title); 39 | object.put(KEY_DESCRIBE,describe); 40 | object.put(KEY_IMAGE,image); 41 | object.put(KEY_LINK_URL,linkUrl); 42 | return object; 43 | } 44 | 45 | public String getTitle() { 46 | return title; 47 | } 48 | 49 | @Override 50 | public WritableMap toReactNative() { 51 | WritableMap writableMap = Arguments.createMap(); 52 | writableMap.putString(MessageConstant.Link.TITLE,title); 53 | writableMap.putString(MessageConstant.Link.DESCRIBE,describe); 54 | writableMap.putString(MessageConstant.Link.IMAGE,image); 55 | writableMap.putString(MessageConstant.Link.LINK_URL,linkUrl); 56 | return writableMap; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/common/util/C.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.common.util; 2 | 3 | public class C { 4 | // 视频允许大小 5 | public static final long MAX_LOCAL_VIDEO_FILE_SIZE = 20 * 1024 * 1024; 6 | 7 | 8 | // 关于文件后缀的常量 9 | public static final class FileSuffix { 10 | public static final String JPG = ".jpg"; 11 | 12 | public static final String PNG = ".png"; 13 | 14 | public static final String M4A = ".m4a"; 15 | 16 | public static final String THREE_3GPP = ".3gp"; 17 | 18 | public static final String BMP = ".bmp"; 19 | 20 | public static final String MP4 = ".mp4"; 21 | 22 | public static final String AMR_NB = ".amr"; 23 | 24 | public static final String APK = ".apk"; 25 | 26 | public static final String AAC = ".aac"; 27 | } 28 | 29 | // 关于mimetype的常量 30 | public static final class MimeType { 31 | public static final String MIME_JPEG = "image/jpeg"; 32 | 33 | public static final String MIME_PNG = "image/png"; 34 | 35 | public static final String MIME_BMP = "image/x-MS-bmp"; 36 | 37 | public static final String MIME_GIF = "image/gif"; 38 | 39 | public static final String MIME_AUDIO_3GPP = "audio/3gpp"; 40 | 41 | public static final String MIME_AUDIO_MP4 = "audio/mp4"; 42 | 43 | public static final String MIME_AUDIO_M4A = "audio/m4a"; 44 | 45 | public static final String MIME_AUDIO_AMR_NB = "audio/amr"; 46 | 47 | public static final String MIME_AUDIO_AAC = "audio/aac"; 48 | 49 | public static final String MIME_TXT = "txt/txt";// 用 于PC长消息 50 | 51 | public static final String MIME_WAPPUSH_SMS = "message/sms"; 52 | 53 | public static final String MIME_WAPPUSH_TEXT = "txt/wappush"; // 文字wappush 54 | 55 | public static final String MIME_MUSIC_LOVE = "music/love"; // 爱音乐 56 | 57 | public static final String MIME_MUSIC_XIA = "music/xia"; // 虾米音乐 58 | 59 | public static final String MIME_VIDEO_3GPP = "video/3gpp"; 60 | 61 | public static final String MIME_VIDEO_ALL = "video/*"; 62 | 63 | public static final String MIME_LOCATION_GOOGLE = "location/google"; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/extension/BankTransferAttachment.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session.extension; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.facebook.react.bridge.Arguments; 5 | import com.facebook.react.bridge.WritableMap; 6 | import com.netease.im.MessageConstant; 7 | 8 | /** 9 | * Created by dowin on 2017/5/2. 10 | */ 11 | 12 | public class BankTransferAttachment extends CustomAttachment { 13 | 14 | final static String KEY_AMOUNT= "amount"; 15 | final static String KEY_COMMENTS= "comments"; 16 | final static String KEY_SERIAL_NO = "serialNo"; 17 | 18 | private String amount; 19 | private String comments; 20 | private String serialNo; 21 | 22 | public BankTransferAttachment() { 23 | super(CustomAttachmentType.BankTransfer); 24 | } 25 | 26 | @Override 27 | protected void parseData(JSONObject data) { 28 | amount = data.getString(KEY_AMOUNT); 29 | comments = data.getString(KEY_COMMENTS); 30 | serialNo = data.getString(KEY_SERIAL_NO); 31 | } 32 | 33 | @Override 34 | protected JSONObject packData() { 35 | JSONObject object = new JSONObject(); 36 | object.put(KEY_AMOUNT, amount); 37 | object.put(KEY_COMMENTS, comments); 38 | object.put(KEY_SERIAL_NO, serialNo); 39 | return object; 40 | } 41 | 42 | public void setParams(String amount, String comments, String serialNo) { 43 | this.amount = amount; 44 | this.comments = comments; 45 | this.serialNo = serialNo; 46 | } 47 | 48 | public String getComments() { 49 | return comments; 50 | } 51 | 52 | @Override 53 | public WritableMap toReactNative() { 54 | WritableMap writableMap = Arguments.createMap(); 55 | writableMap.putString(MessageConstant.BankTransfer.AMOUNT,amount); 56 | writableMap.putString(MessageConstant.BankTransfer.COMMENTS,comments); 57 | writableMap.putString(MessageConstant.BankTransfer.SERIA_NO,serialNo); 58 | return writableMap; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/extension/RedPacketAttachement.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session.extension; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.facebook.react.bridge.Arguments; 5 | import com.facebook.react.bridge.WritableMap; 6 | import com.netease.im.MessageConstant; 7 | 8 | /** 9 | * Created by dowin on 2017/5/2. 10 | */ 11 | 12 | public class RedPacketAttachement extends CustomAttachment { 13 | 14 | final static String KEY_TYPE = "type"; 15 | final static String KEY_COMMENTS= "comments"; 16 | final static String KEY_SERIAL_NO = "serialNo"; 17 | 18 | private String redPacketType; 19 | private String comments; 20 | private String serialNo; 21 | 22 | public RedPacketAttachement() { 23 | super(CustomAttachmentType.RedPacket); 24 | 25 | } 26 | 27 | public void setParams(String redPacketType, String comments, String serialNo) { 28 | this.redPacketType = redPacketType; 29 | this.comments = comments; 30 | this.serialNo = serialNo; 31 | } 32 | 33 | @Override 34 | protected void parseData(JSONObject data) { 35 | redPacketType = data.getString(KEY_TYPE); 36 | comments = data.getString(KEY_COMMENTS); 37 | serialNo = data.getString(KEY_SERIAL_NO); 38 | } 39 | 40 | public String getComments() { 41 | return comments; 42 | } 43 | 44 | @Override 45 | protected JSONObject packData() { 46 | JSONObject object = new JSONObject(); 47 | object.put(KEY_TYPE, redPacketType); 48 | object.put(KEY_COMMENTS, comments); 49 | object.put(KEY_SERIAL_NO, serialNo); 50 | return object; 51 | } 52 | @Override 53 | public WritableMap toReactNative(){ 54 | WritableMap writableMap = Arguments.createMap(); 55 | writableMap.putString(MessageConstant.RedPacket.TYPE,redPacketType); 56 | writableMap.putString(MessageConstant.RedPacket.COMMENTS,comments); 57 | writableMap.putString(MessageConstant.RedPacket.SERIAL_NO,serialNo); 58 | return writableMap; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/uinfo/UserInfoHelper.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.uinfo; 2 | 3 | import com.netease.im.IMApplication; 4 | import com.netease.im.login.LoginService; 5 | import com.netease.im.uikit.cache.NimUserInfoCache; 6 | import com.netease.im.uikit.cache.TeamDataCache; 7 | import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; 8 | 9 | import java.util.List; 10 | 11 | public class UserInfoHelper { 12 | 13 | private static UserInfoObservable userInfoObservable; 14 | 15 | // 获取用户显示在标题栏和最近联系人中的名字 16 | public static String getUserTitleName(String id, SessionTypeEnum sessionType) { 17 | if (sessionType == SessionTypeEnum.P2P) { 18 | if (LoginService.getInstance().getAccount().equals(id)) { 19 | return "我的电脑"; 20 | } else { 21 | return NimUserInfoCache.getInstance().getUserDisplayName(id); 22 | } 23 | } else if (sessionType == SessionTypeEnum.Team) { 24 | return TeamDataCache.getInstance().getTeamName(id); 25 | } 26 | return id; 27 | } 28 | 29 | /** 30 | * 注册用户资料变化观察者。
31 | * 注意:不再观察时(如Activity destroy后),要unregister,否则会造成资源泄露 32 | * @param observer 观察者 33 | */ 34 | public static void registerObserver(UserInfoObservable.UserInfoObserver observer) { 35 | if (userInfoObservable == null) { 36 | userInfoObservable = new UserInfoObservable(IMApplication.getContext()); 37 | } 38 | userInfoObservable.registerObserver(observer); 39 | } 40 | 41 | /** 42 | * 注销用户资料变化观察者。 43 | * @param observer 观察者 44 | */ 45 | public static void unregisterObserver(UserInfoObservable.UserInfoObserver observer) { 46 | if (userInfoObservable != null) { 47 | userInfoObservable.unregisterObserver(observer); 48 | } 49 | } 50 | 51 | /** 52 | * 当用户资料发生改动时,请调用此接口,通知更新UI 53 | * @param accounts 有用户信息改动的帐号列表 54 | */ 55 | public static void notifyChanged(List accounts) { 56 | if (userInfoObservable != null) { 57 | userInfoObservable.notifyObservers(accounts); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/common/framework/NimSingleThreadExecutor.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.common.framework; 2 | 3 | import android.os.Handler; 4 | 5 | import com.netease.im.IMApplication; 6 | 7 | import java.util.concurrent.Executor; 8 | import java.util.concurrent.Executors; 9 | 10 | /** 11 | * Created by huangjun on 2015/3/12. 12 | */ 13 | public class NimSingleThreadExecutor { 14 | 15 | private static NimSingleThreadExecutor instance; 16 | 17 | private Handler uiHander; 18 | private Executor executor; 19 | 20 | private NimSingleThreadExecutor() { 21 | uiHander = new Handler(IMApplication.getContext().getMainLooper()); 22 | executor = Executors.newSingleThreadExecutor(); 23 | } 24 | 25 | public synchronized static NimSingleThreadExecutor getInstance() { 26 | if (instance == null) { 27 | instance = new NimSingleThreadExecutor(); 28 | } 29 | 30 | return instance; 31 | } 32 | 33 | public void execute(NimTask task) { 34 | if (executor != null) { 35 | executor.execute(new NimRunnable<>(task)); 36 | } 37 | } 38 | 39 | public void execute(Runnable runnable) { 40 | if (executor != null) { 41 | executor.execute(runnable); 42 | } 43 | } 44 | 45 | /** 46 | * ****************** model ************************* 47 | */ 48 | 49 | public interface NimTask { 50 | T runInBackground(); 51 | 52 | void onCompleted(T result); 53 | } 54 | 55 | private class NimRunnable implements Runnable { 56 | 57 | public NimRunnable(NimTask task) { 58 | this.task = task; 59 | } 60 | 61 | private NimTask task; 62 | 63 | @Override 64 | public void run() { 65 | final T res = task.runInBackground(); 66 | if (uiHander != null) { 67 | uiHander.post(new Runnable() { 68 | @Override 69 | public void run() { 70 | task.onCompleted(res); 71 | } 72 | }); 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKit.h 3 | // NIMKit 4 | // 5 | // Created by amao on 8/14/15. 6 | // Copyright (c) 2015 NetEase. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | //! Project version number for NIMKit. 13 | FOUNDATION_EXPORT double NIMKitVersionNumber; 14 | 15 | //! Project version string for NIMKit. 16 | FOUNDATION_EXPORT const unsigned char NIMKitVersionString[]; 17 | 18 | // In this header, you should import all the public headers of your framework using statements like #import 19 | 20 | #import 21 | 22 | /** 23 | * 基础Model 24 | */ 25 | #import "NIMKitInfo.h" 26 | #import "NIMKitDataProvider.h" 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | @interface NIMKit : NSObject 38 | 39 | + (instancetype)sharedKit; 40 | 41 | 42 | /** 43 | * 内容提供者,由上层开发者注入。如果没有则使用默认 provider 44 | */ 45 | @property (nonatomic,strong) id provider; 46 | 47 | /** 48 | * NIMKit图片资源所在的 bundle 名称。 49 | */ 50 | @property (nonatomic,copy) NSString *resourceBundleName; 51 | 52 | /** 53 | * NIMKit表情资源所在的 bundle 名称。 54 | */ 55 | @property (nonatomic,copy) NSString *emoticonBundleName; 56 | 57 | /** 58 | * NIMKit设置资源所在的 bundle 名称。 59 | */ 60 | @property (nonatomic,copy) NSString *settingBundleName; 61 | 62 | 63 | /** 64 | * 用户信息变更通知接口 65 | * 66 | * @param userIds 用户id 67 | */ 68 | - (void)notfiyUserInfoChanged:(NSArray *)userIds; 69 | 70 | /** 71 | * 群信息变更通知接口 72 | * 73 | * @param teamIds 群id 74 | */ 75 | - (void)notifyTeamInfoChanged:(NSArray *)teamIds; 76 | 77 | 78 | /** 79 | * 群成员变更通知接口 80 | * 81 | * @param teamIds 群id 82 | */ 83 | - (void)notifyTeamMemebersChanged:(NSArray *)teamIds; 84 | 85 | /** 86 | * 返回用户信息 87 | */ 88 | - (NIMKitInfo *)infoByUser:(NSString *)userId 89 | option:(NIMKitInfoFetchOption *)option; 90 | 91 | /** 92 | * 返回群信息 93 | */ 94 | - (NIMKitInfo *)infoByTeam:(NSString *)teamId 95 | option:(NIMKitInfoFetchOption *)option; 96 | 97 | @end 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NSString+NIMKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+NIM.m 3 | // NIMKit 4 | // 5 | // Created by chris. 6 | // Copyright (c) 2015年 NetEase. All rights reserved. 7 | // 8 | 9 | #import "NSString+NIMKit.h" 10 | #import 11 | 12 | @implementation NSString (NIMKit) 13 | 14 | - (CGSize)nim_stringSizeWithFont:(UIFont *)font{ 15 | return [self sizeWithAttributes:@{NSFontAttributeName:font}]; 16 | } 17 | 18 | - (NSString *)nim_MD5String { 19 | const char *cstr = [self UTF8String]; 20 | unsigned char result[16]; 21 | CC_MD5(cstr, (CC_LONG)strlen(cstr), result); 22 | return [NSString stringWithFormat: 23 | @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 24 | result[0], result[1], result[2], result[3], 25 | result[4], result[5], result[6], result[7], 26 | result[8], result[9], result[10], result[11], 27 | result[12], result[13], result[14], result[15] 28 | ]; 29 | } 30 | 31 | 32 | - (NSUInteger)nim_getBytesLength 33 | { 34 | NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000); 35 | return [self lengthOfBytesUsingEncoding:enc]; 36 | } 37 | 38 | 39 | - (NSString *)nim_stringByDeletingPictureResolution{ 40 | NSString *doubleResolution = @"@2x"; 41 | NSString *tribleResolution = @"@3x"; 42 | NSString *fileName = self.stringByDeletingPathExtension; 43 | NSString *res = [self copy]; 44 | if ([fileName hasSuffix:doubleResolution] || [fileName hasSuffix:tribleResolution]) { 45 | res = [fileName substringToIndex:fileName.length - 3]; 46 | if (self.pathExtension.length) { 47 | res = [res stringByAppendingPathExtension:self.pathExtension]; 48 | } 49 | } 50 | return res; 51 | } 52 | 53 | 54 | - (UIColor *)nim_hexToColor 55 | { 56 | unsigned rgbValue = 0; 57 | NSScanner *scanner = [NSScanner scannerWithString:self]; 58 | //去掉# 59 | [scanner setScanLocation:1]; 60 | [scanner scanHexInt:&rgbValue]; 61 | return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0 green:((rgbValue & 0xFF00) >> 8)/255.0 blue:(rgbValue & 0xFF)/255.0 alpha:1.0]; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/common/util/log/LogUtil.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.common.util.log; 2 | 3 | public class LogUtil { 4 | 5 | public static void setDebugAble(boolean debugAble){ 6 | LogImpl.setDebugAble(debugAble); 7 | } 8 | public static final void init(String logFile, int level) { 9 | LogImpl.init(logFile, level); 10 | } 11 | 12 | public static final void v(String tag, String msg) { 13 | LogImpl.v(tag, buildMessage(msg)); 14 | } 15 | 16 | public static final void v(String tag, String msg, Throwable thr) { 17 | LogImpl.v(tag, buildMessage(msg), thr); 18 | } 19 | 20 | public static final void d(String tag, String msg) { 21 | LogImpl.d(tag, buildMessage(msg)); 22 | } 23 | 24 | public static final void d(String tag, String msg, Throwable thr) { 25 | LogImpl.d(tag, buildMessage(msg), thr); 26 | } 27 | 28 | public static final void i(String tag, String msg) { 29 | LogImpl.i(tag, buildMessage(msg)); 30 | } 31 | 32 | public static final void i(String tag, String msg, Throwable thr) { 33 | LogImpl.i(tag, buildMessage(msg), thr); 34 | } 35 | 36 | public static final void w(String tag, String msg) { 37 | LogImpl.w(tag, buildMessage(msg)); 38 | } 39 | 40 | public static final void w(String tag, String msg, Throwable thr) { 41 | LogImpl.w(tag, buildMessage(msg), thr); 42 | } 43 | 44 | public static final void w(String tag, Throwable thr) { 45 | LogImpl.w(tag, buildMessage(""), thr); 46 | } 47 | 48 | public static final void e(String tag, String msg) { 49 | LogImpl.e(tag, buildMessage(msg)); 50 | } 51 | 52 | public static final void e(String tag, String msg, Throwable thr) { 53 | LogImpl.e(tag, buildMessage(msg), thr); 54 | } 55 | 56 | public static final void ui(String msg) { 57 | LogImpl.i("ui", buildMessage(msg)); 58 | } 59 | 60 | public static final void res(String msg) { 61 | LogImpl.i("RES", buildMessage(msg)); 62 | } 63 | 64 | public static final void audio(String msg) { 65 | LogImpl.i("AudioRecorder", buildMessage(msg)); 66 | } 67 | 68 | public static String getLogFileName(String cat) { 69 | return LogImpl.getLogFileName(cat); 70 | } 71 | 72 | private static String buildMessage(String msg) { 73 | return "IM:"+msg; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/receiver/CustomNotificationReceiver.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.receiver; 2 | 3 | import android.app.NotificationManager; 4 | import android.content.BroadcastReceiver; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.os.Bundle; 8 | 9 | import com.netease.im.IMApplication; 10 | import com.netease.im.uikit.common.util.log.LogUtil; 11 | import com.netease.nimlib.sdk.NimIntent; 12 | 13 | /** 14 | * 自定义通知消息广播接收器 15 | */ 16 | public class CustomNotificationReceiver extends BroadcastReceiver { 17 | 18 | private NotificationManager notificationManager; 19 | 20 | @Override 21 | public void onReceive(Context context, Intent intent) { 22 | 23 | String action = context.getPackageName() + NimIntent.ACTION_RECEIVE_CUSTOM_NOTIFICATION; 24 | // printIntent(action, intent); 25 | if (action.equals(intent.getAction())) { 26 | 27 | // 从intent中取出自定义通知 28 | // try { 29 | // CustomNotification notification = (CustomNotification) intent.getSerializableExtra(NimIntent.EXTRA_BROADCAST_MSG); 30 | // SessionUtil.receiver(getNotificationManager(), notification); 31 | // } catch (Exception e) { 32 | // LogUtil.e("CustomNotificationReceiver", e.getMessage()); 33 | // } 34 | } 35 | } 36 | 37 | public NotificationManager getNotificationManager() { 38 | if (notificationManager == null) { 39 | notificationManager = (NotificationManager) IMApplication.getContext().getSystemService(Context.NOTIFICATION_SERVICE); 40 | } 41 | return notificationManager; 42 | } 43 | 44 | void printIntent(String action, Intent intent) { 45 | LogUtil.d("NimNetease", "--------------------------------------------"); 46 | LogUtil.d("NimNetease", "action" + action); 47 | LogUtil.d("NimNetease", intent.getAction()); 48 | Bundle bundle = intent.getExtras(); 49 | if (bundle != null) { 50 | LogUtil.d("NimNetease", "+" + intent); 51 | } else { 52 | LogUtil.d("NimNetease", "+null"); 53 | } 54 | LogUtil.d("NimNetease", "--------------------------------------------"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/common/media/BitmapUtil.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.common.media; 2 | 3 | import android.graphics.Bitmap; 4 | import android.graphics.Matrix; 5 | import android.media.ExifInterface; 6 | 7 | import java.io.IOException; 8 | 9 | 10 | public class BitmapUtil { 11 | 12 | public static Bitmap reviewPicRotate(Bitmap bitmap,String path){ 13 | int degree = getPicRotate(path); 14 | if(degree!=0){ 15 | try{ 16 | Matrix m = new Matrix(); 17 | int width = bitmap.getWidth(); 18 | int height = bitmap.getHeight(); 19 | m.setRotate(degree); 20 | bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height,m, true); 21 | }catch(Exception e){ 22 | e.printStackTrace(); 23 | }catch(Error err){ 24 | err.printStackTrace(); 25 | } 26 | } 27 | return bitmap; 28 | } 29 | 30 | 31 | /** 32 | * 读取图片属性:旋转的角度 33 | * 34 | * @param path 35 | * 图片绝对路径 36 | * @return degree旋转的角度 37 | */ 38 | public static int getPicRotate(String path) { 39 | int degree = 0; 40 | try { 41 | ExifInterface exifInterface = new ExifInterface(path); 42 | int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); 43 | switch (orientation) { 44 | case ExifInterface.ORIENTATION_ROTATE_90: 45 | degree = 90; 46 | break; 47 | case ExifInterface.ORIENTATION_ROTATE_180: 48 | degree = 180; 49 | break; 50 | case ExifInterface.ORIENTATION_ROTATE_270: 51 | degree = 270; 52 | break; 53 | } 54 | } catch (IOException e) { 55 | e.printStackTrace(); 56 | } 57 | return degree; 58 | } 59 | 60 | public static Bitmap resizeBitmap(Bitmap bitmap, int w, int h) 61 | { 62 | if(bitmap == null) { 63 | return null; 64 | } 65 | 66 | Bitmap BitmapOrg = bitmap; 67 | int width = BitmapOrg.getWidth(); 68 | int height = BitmapOrg.getHeight(); 69 | int newWidth = w; 70 | int newHeight = h; 71 | 72 | float scaleWidth = ((float) newWidth) / width; 73 | float scaleHeight = ((float) newHeight) / height; 74 | 75 | Matrix matrix = new Matrix(); 76 | matrix.postScale(scaleWidth, scaleHeight); 77 | 78 | return Bitmap.createBitmap(BitmapOrg, 0, 0, width, height, matrix, true); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/provider/UserDataProvider.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.provider; 2 | 3 | import com.netease.im.IMApplication; 4 | import com.netease.im.uikit.cache.FriendDataCache; 5 | import com.netease.im.uikit.common.util.log.LogUtil; 6 | import com.netease.im.uikit.contact.core.item.AbsContactItem; 7 | import com.netease.im.uikit.contact.core.item.ContactItem; 8 | import com.netease.im.uikit.contact.core.item.ItemTypes; 9 | import com.netease.im.uikit.contact.core.query.TextQuery; 10 | import com.netease.im.uikit.contact.core.util.ContactHelper; 11 | import com.netease.nimlib.sdk.friend.model.Friend; 12 | import com.netease.nimlib.sdk.uinfo.model.UserInfo; 13 | 14 | import java.util.ArrayList; 15 | import java.util.Iterator; 16 | import java.util.List; 17 | 18 | public final class UserDataProvider { 19 | 20 | final static String TAG = "UserDataProvider"; 21 | public static final List provide(TextQuery query) { 22 | List sources = query(query); 23 | List items = new ArrayList<>(sources.size()); 24 | for (UserInfo u : sources) { 25 | items.add(new ContactItem(ContactHelper.makeContactFromUserInfo(u), ItemTypes.FRIEND)); 26 | } 27 | 28 | LogUtil.w(TAG, "contact provide data size =" + items.size()); 29 | return items; 30 | } 31 | 32 | private static final List query(TextQuery query) { 33 | if (query != null) { 34 | List users = IMApplication.getContactProvider().getUserInfoOfMyFriends(); 35 | UserInfo user; 36 | for (Iterator iter = users.iterator(); iter.hasNext(); ) { 37 | user = iter.next(); 38 | Friend friend = FriendDataCache.getInstance().getFriendByAccount(user.getAccount()); 39 | boolean hit = ContactSearch.hitUser(user, query) || (friend != null && ContactSearch.hitFriend(friend, query)); 40 | if (!hit) { 41 | iter.remove(); 42 | } 43 | } 44 | return users; 45 | } else { 46 | return IMApplication.getContactProvider().getUserInfoOfMyFriends(); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/util/ContactHelper.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.util; 2 | 3 | import com.netease.im.IMApplication; 4 | import com.netease.im.uikit.cache.NimUserInfoCache; 5 | import com.netease.im.uikit.cache.TeamDataCache; 6 | import com.netease.im.uikit.contact.core.model.IContact; 7 | import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; 8 | import com.netease.nimlib.sdk.search.model.MsgIndexRecord; 9 | import com.netease.nimlib.sdk.uinfo.model.UserInfo; 10 | 11 | /** 12 | * Created by huangjun on 2015/9/8. 13 | */ 14 | public class ContactHelper { 15 | public static IContact makeContactFromUserInfo(final UserInfo userInfo) { 16 | return new IContact() { 17 | @Override 18 | public String getContactId() { 19 | return userInfo.getAccount(); 20 | } 21 | 22 | @Override 23 | public int getContactType() { 24 | return Type.Friend; 25 | } 26 | 27 | @Override 28 | public String getDisplayName() { 29 | return IMApplication.getContactProvider().getUserDisplayName(userInfo.getAccount()); 30 | } 31 | }; 32 | } 33 | 34 | public static IContact makeContactFromMsgIndexRecord(final MsgIndexRecord record) { 35 | return new IContact() { 36 | @Override 37 | public String getContactId() { 38 | return record.getSessionId(); 39 | } 40 | 41 | @Override 42 | public int getContactType() { 43 | return Type.Msg; 44 | } 45 | 46 | @Override 47 | public String getDisplayName() { 48 | String sessionId = record.getSessionId(); 49 | SessionTypeEnum sessionType = record.getSessionType(); 50 | 51 | if (sessionType == SessionTypeEnum.P2P) { 52 | return NimUserInfoCache.getInstance().getUserDisplayName(sessionId); 53 | } else if (sessionType == SessionTypeEnum.Team) { 54 | return TeamDataCache.getInstance().getTeamName(sessionId); 55 | } 56 | 57 | return ""; 58 | } 59 | }; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/extension/CardAttachment.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session.extension; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.facebook.react.bridge.Arguments; 5 | import com.facebook.react.bridge.WritableMap; 6 | import com.netease.im.MessageConstant; 7 | 8 | /** 9 | * Created by dowin on 2017/10/23. 10 | */ 11 | 12 | public class CardAttachment extends CustomAttachment { 13 | 14 | private String cardType; 15 | private String name; 16 | private String imgPath; 17 | private String sessionId; 18 | 19 | public CardAttachment() { 20 | super(CustomAttachmentType.Card); 21 | } 22 | 23 | @Override 24 | protected void parseData(JSONObject data) { 25 | cardType = data.getString(MessageConstant.Card.type); 26 | name = data.getString(MessageConstant.Card.name); 27 | imgPath = data.getString(MessageConstant.Card.imgPath); 28 | sessionId = data.getString(MessageConstant.Card.sessionId); 29 | } 30 | 31 | public void setParams(String type, String name, String imgPath, String sessionId) { 32 | this.cardType = type; 33 | this.name = name; 34 | this.imgPath = imgPath; 35 | this.sessionId = sessionId; 36 | } 37 | 38 | public String getCardType() { 39 | return cardType; 40 | } 41 | 42 | public String getName() { 43 | return name; 44 | } 45 | 46 | public String getImgPath() { 47 | return imgPath; 48 | } 49 | 50 | @Override 51 | protected JSONObject packData() { 52 | JSONObject object = new JSONObject(); 53 | object.put(MessageConstant.Card.type, cardType); 54 | object.put(MessageConstant.Card.name, name); 55 | object.put(MessageConstant.Card.imgPath, imgPath); 56 | object.put(MessageConstant.Card.sessionId, sessionId); 57 | return object; 58 | } 59 | 60 | @Override 61 | public WritableMap toReactNative() { 62 | WritableMap writableMap = Arguments.createMap(); 63 | writableMap.putString(MessageConstant.Card.type, cardType); 64 | writableMap.putString(MessageConstant.Card.name, name); 65 | writableMap.putString(MessageConstant.Card.imgPath, imgPath); 66 | writableMap.putString(MessageConstant.Card.sessionId, sessionId); 67 | return writableMap; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/group/GroupStrategy.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.group; 2 | 3 | import java.util.Comparator; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * Created by dowin on 2017/8/16. 9 | */ 10 | 11 | public class GroupStrategy implements Comparator { 12 | 13 | public static final String GROUP_SHARP = "#"; 14 | 15 | public static final String GROUP_TEAM = "@"; 16 | 17 | public static final String GROUP_NULL = "?"; 18 | private static final class Group { 19 | private final int order; 20 | 21 | private final String name; 22 | 23 | public Group(int order, String name) { 24 | this.order = order; 25 | this.name = name; 26 | } 27 | } 28 | 29 | private final Map groups = new HashMap(); 30 | 31 | public String belongs(AbstractItem item) { 32 | return item.belongsGroup(); 33 | } 34 | 35 | protected final void add(String id, int order, String name) { 36 | groups.put(id, new Group(order, name)); 37 | } 38 | 39 | protected final int addABC(int order) { 40 | String id = GroupStrategy.GROUP_SHARP; 41 | 42 | add(id, order++, id); 43 | 44 | for (char i = 0; i < 26; i++) { 45 | id = Character.toString((char) ('A' + i)); 46 | 47 | add(id, order++, id); 48 | } 49 | 50 | return order; 51 | } 52 | 53 | public final String getName(String id) { 54 | Group group = groups.get(id); 55 | String name = group != null ? group.name : null; 56 | return name != null ? name : ""; 57 | } 58 | 59 | private Integer toOrder(String id) { 60 | Group group = groups.get(id); 61 | return group != null ? group.order : null; 62 | } 63 | 64 | @Override 65 | public int compare(String lhs, String rhs) { 66 | if (lhs == null) { 67 | lhs = GroupStrategy.GROUP_NULL; 68 | } 69 | 70 | if (rhs == null) { 71 | rhs = GroupStrategy.GROUP_NULL; 72 | } 73 | 74 | Integer lhsO = toOrder(lhs); 75 | Integer rhsO = toOrder(rhs); 76 | 77 | if (lhsO == rhsO) { 78 | return 0; 79 | } 80 | 81 | if (lhsO == null) { 82 | return -1; 83 | } 84 | 85 | if (rhsO == null) { 86 | return 1; 87 | } 88 | 89 | return lhsO - rhsO; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NTESBundleSetting.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESBundleSetting.h 3 | // NIM 4 | // 5 | // Created by chris on 15/7/1. 6 | // Copyright (c) 2015年 Netease. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | 13 | //部分API提供了额外的选项,如删除消息会有是否删除会话的选项,为了测试方便提供配置参数 14 | //上层开发只需要按照策划需求选择一种适合自己项目的选项即可,这个设置只是为了方便测试不同的case下API的正确性 15 | 16 | @interface NTESBundleSetting : NSObject 17 | 18 | + (instancetype)sharedConfig; 19 | 20 | - (BOOL)removeSessionWheDeleteMessages; //删除消息时是否同时删除会话项 21 | 22 | - (BOOL)localSearchOrderByTimeDesc; //本地搜索消息顺序 YES表示按时间戳逆序搜索,NO表示按照时间戳顺序搜索 23 | 24 | - (BOOL)autoRemoveRemoteSession; //删除会话时是不是也同时删除服务器会话 (防止漫游) 25 | 26 | - (BOOL)autoRemoveSnapMessage; //阅后即焚消息在看完后是否删除 27 | 28 | - (BOOL)needVerifyForFriend; //添加好友是否需要验证 29 | 30 | - (BOOL)showFps; //是否显示Fps 31 | 32 | - (BOOL)disableProximityMonitor; //贴耳的时候是否需要自动切换成听筒模式 33 | 34 | - (BOOL)enableRotate; //支持旋转(仅组件部分,其他部分可能会显示不正常,谨慎开启) 35 | 36 | - (BOOL)usingAmr; //使用amr作为录音 37 | 38 | - (NSArray *)ignoreTeamNotificationTypes; //需要忽略的群通知类型 39 | 40 | #pragma mark - 网络通话和白板 41 | - (BOOL)serverRecordAudio; //服务器录制语音 42 | 43 | - (BOOL)serverRecordVideo; //服务器录制视频 44 | 45 | - (BOOL)serverRecordWhiteboardData; //服务器录制白板数据 46 | 47 | 48 | - (BOOL)videochatDisableAutoCropping; //禁用自动裁剪画面 49 | 50 | - (BOOL)videochatAutoRotateRemoteVideo; //自动旋转视频聊天远端画面 51 | 52 | - (NIMNetCallVideoQuality)preferredVideoQuality; //期望的视频发送清晰度 53 | 54 | - (BOOL)startWithBackCamera; //使用后置摄像头开始视频通话 55 | 56 | - (NIMNetCallVideoCodec)perferredVideoEncoder; //期望的视频编码器 57 | 58 | - (NIMNetCallVideoCodec)perferredVideoDecoder; //期望的视频解码器 59 | 60 | - (NSUInteger)videoMaxEncodeKbps; //最大发送视频编码码率 61 | 62 | - (NSUInteger)localRecordVideoKbps; //本地录制视频码率 63 | 64 | - (BOOL)autoDeactivateAudioSession; //自动结束AudioSession 65 | 66 | - (BOOL)audioDenoise; //降噪开关 67 | 68 | - (BOOL)voiceDetect; //语音检测开关 69 | 70 | - (BOOL)preferHDAudio; //期望高清语音 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/TeamViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TeamViewController.h 3 | // NIM 4 | // 5 | // Created by Dowin on 2017/5/4. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NIMModel.h" 11 | typedef void(^Success)(id param); 12 | typedef void(^Errors)(id erro); 13 | @interface TeamViewController : UIViewController 14 | +(instancetype)initWithTeamViewController; 15 | -(void)initWithDelegate; 16 | //获取群组列表 17 | -(void)getTeamList:(Success)succ Err:(Errors)err; 18 | //创建群组 19 | -(void)createTeam:(NSDictionary *)fields type:(NSString *)type accounts:(NSArray *)accounts Succ:(Success)succ Err:(Errors)err; 20 | //更新群成员名片 21 | - (void)updateMemberNick:(nonnull NSString *)teamId contactId:(nonnull NSString *)contactId nick:(nonnull NSString*)nick Succ:(Success)succ Err:(Errors)err; 22 | //获取群资料 23 | -(void)getTeamInfo:(NSString *)teamId Succ:(Success)succ Err:(Errors)err; 24 | ////群成员禁言 25 | -(void)setTeamMemberMute:(NSString *)teamId contactId:(NSString *)contactId mute:(NSString *)mute Succ:(Success)succ Err:(Errors)err; 26 | //获取远程群资料 27 | -(void)fetchTeamInfo:(NSString *)teamId Succ:(Success)succ Err:(Errors)err; 28 | //获取群成员 29 | -(void)getTeamMemberList:(NSString *)teamId Succ:(Success)succ Err:(Errors)err; 30 | //申请加入群组 31 | -(void)applyJoinTeam:(NSString *)teamId message:(NSString *)message Succ:(Success)succ Err:(Errors)err; 32 | //获取群成员资料及设置 33 | - (void)fetchTeamMemberInfo:(NSString *)teamId contactId:(NSString *)contactId Succ:(Success)succ Err:(Errors)err; 34 | //开启/关闭消息提醒 35 | -(void)muteTeam:(NSString *)teamId mute:(NSString *)mute Succ:(Success)succ Err:(Errors)err; 36 | //解散群组 37 | -(void)dismissTeam:(NSString *)teamId Succ:(Success)succ Err:(Errors)err; 38 | //拉人入群 39 | -(void)addMembers:(NSString *)teamId accounts:(NSArray *)count Succ:(Success)succ Err:(Errors)err; 40 | //踢人出群 41 | -(void)removeMember:(NSString *)teamId accounts:(NSArray *)count Succ:(Success)succ Err:(Errors)err; 42 | //主动退群 43 | -(void)quitTeam:(NSString *)teamId Succ:(Success)succ Err:(Errors)err; 44 | //转让群组 45 | -(void)transferManagerWithTeam:(NSString *)teamId 46 | newOwnerId:(NSString *)newOwnerId quit:(NSString *)quit Succ:(Success)succ Err:(Errors)err; 47 | //修改自己的群昵称 48 | -(void)updateTeamName:(NSString *)teamId nick:(NSString *)nick Succ:(Success)succ Err:(Errors)err; 49 | -(void)stopTeamList; 50 | //更新群资料 51 | - (void)updateTeam:(NSString *)teamId fieldType:(NSString *)fieldType value:(NSString *)value Succ:(Success)succ Err:(Errors)err; 52 | @end 53 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/model/ContactGroupStrategy.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.model; 2 | 3 | 4 | import com.netease.im.uikit.contact.core.item.AbsContactItem; 5 | 6 | import java.util.Comparator; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * 通讯录分组策略 12 | * Created by huangjun on 2015/2/10. 13 | */ 14 | 15 | public class ContactGroupStrategy implements Comparator { 16 | public static final String GROUP_SHARP = "#"; 17 | 18 | public static final String GROUP_TEAM = "@"; 19 | 20 | public static final String GROUP_NULL = "?"; 21 | 22 | private static final class Group { 23 | private final int order; 24 | 25 | private final String name; 26 | 27 | public Group(int order, String name) { 28 | this.order = order; 29 | this.name = name; 30 | } 31 | } 32 | 33 | private final Map groups = new HashMap(); 34 | 35 | public String belongs(AbsContactItem item) { 36 | return item.belongsGroup(); 37 | } 38 | 39 | protected final void add(String id, int order, String name) { 40 | groups.put(id, new Group(order, name)); 41 | } 42 | 43 | protected final int addABC(int order) { 44 | String id = ContactGroupStrategy.GROUP_SHARP; 45 | 46 | add(id, order++, id); 47 | 48 | for (char i = 0; i < 26; i++) { 49 | id = Character.toString((char) ('A' + i)); 50 | 51 | add(id, order++, id); 52 | } 53 | 54 | return order; 55 | } 56 | 57 | public final String getName(String id) { 58 | Group group = groups.get(id); 59 | String name = group != null ? group.name : null; 60 | return name != null ? name : ""; 61 | } 62 | 63 | private Integer toOrder(String id) { 64 | Group group = groups.get(id); 65 | return group != null ? group.order : null; 66 | } 67 | 68 | @Override 69 | public int compare(String lhs, String rhs) { 70 | if (lhs == null) { 71 | lhs = ContactGroupStrategy.GROUP_NULL; 72 | } 73 | 74 | if (rhs == null) { 75 | rhs = ContactGroupStrategy.GROUP_NULL; 76 | } 77 | 78 | Integer lhsO = toOrder(lhs); 79 | Integer rhsO = toOrder(rhs); 80 | 81 | if (lhsO == rhsO) { 82 | return 0; 83 | } 84 | 85 | if (lhsO == null) { 86 | return -1; 87 | } 88 | 89 | if (rhsO == null) { 90 | return 1; 91 | } 92 | 93 | return lhsO - rhsO; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/provider/TeamMemberDataProvider.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.provider; 2 | 3 | import com.netease.im.uikit.cache.TeamDataCache; 4 | import com.netease.im.uikit.contact.core.item.AbsContactItem; 5 | import com.netease.im.uikit.contact.core.item.ContactItem; 6 | import com.netease.im.uikit.contact.core.item.ItemTypes; 7 | import com.netease.im.uikit.contact.core.model.ContactGroupStrategy; 8 | import com.netease.im.uikit.contact.core.model.TeamMemberContact; 9 | import com.netease.im.uikit.contact.core.query.TextComparator; 10 | import com.netease.im.uikit.contact.core.query.TextQuery; 11 | import com.netease.nimlib.sdk.team.model.TeamMember; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * 群成员数据源提供者 18 | *

19 | * Created by huangjun on 2015/5/4. 20 | */ 21 | public class TeamMemberDataProvider { 22 | public static final List provide(TextQuery query, String tid) { 23 | List sources = query(query, tid); 24 | List items = new ArrayList<>(sources.size()); 25 | for (TeamMemberContact t : sources) { 26 | items.add(createTeamMemberItem(t)); 27 | } 28 | 29 | return items; 30 | } 31 | 32 | private static AbsContactItem createTeamMemberItem(TeamMemberContact teamMember) { 33 | return new ContactItem(teamMember, ItemTypes.TEAM_MEMBER) { 34 | @Override 35 | public int compareTo(ContactItem item) { 36 | return compareTeamMember((TeamMemberContact) getContact(), (TeamMemberContact) (item.getContact())); 37 | } 38 | 39 | @Override 40 | public String belongsGroup() { 41 | return ContactGroupStrategy.GROUP_TEAM; 42 | } 43 | }; 44 | } 45 | 46 | private static int compareTeamMember(TeamMemberContact lhs, TeamMemberContact rhs) { 47 | return TextComparator.compareIgnoreCase(lhs.getDisplayName(), rhs.getDisplayName()); 48 | } 49 | 50 | /** 51 | * * 数据查询 52 | */ 53 | private static final List query(TextQuery query, String tid) { 54 | List teamMembers = TeamDataCache.getInstance().getTeamMemberList(tid); 55 | 56 | List contacts = new ArrayList<>(); 57 | for (TeamMember t : teamMembers) { 58 | if (t != null && (query == null || ContactSearch.hitTeamMember(t, query))) { 59 | contacts.add(new TeamMemberContact(t)); 60 | } 61 | } 62 | 63 | return contacts; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/BankListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BankListViewController.m 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/5/12. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import "BankListViewController.h" 10 | #import "ImConfig.h" 11 | 12 | @interface BankListViewController () 13 | 14 | @end 15 | 16 | @implementation BankListViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | // Do any additional setup after loading the view. 21 | } 22 | 23 | +(instancetype)initWithBankListViewController{ 24 | static BankListViewController *BackVC = nil; 25 | static dispatch_once_t onceToken; 26 | dispatch_once(&onceToken, ^{ 27 | BackVC = [[BankListViewController alloc]init]; 28 | 29 | }); 30 | return BackVC; 31 | } 32 | -(void)initWithDelegate{ 33 | } 34 | -(void)getBlackList{ 35 | NSMutableArray *list = [[NSMutableArray alloc] init]; 36 | NSArray *blackList = [NIMSDK sharedSDK].userManager.myBlackList; 37 | for (NIMUser *user in blackList) { 38 | NIMKitInfo *info = [[NIMKit sharedKit] infoByUser:user.userId option:nil]; 39 | NSMutableDictionary *dic = [NSMutableDictionary dictionary]; 40 | [dic setObject:[NSString stringWithFormat:@"%@", info.showName] forKey:@"name"]; 41 | [dic setObject:[NSString stringWithFormat:@"%@", info.infoId] forKey:@"contactId"]; 42 | [dic setObject:[NSString stringWithFormat:@"%@", info.avatarUrlString ] forKey:@"avatar"]; 43 | NSArray *keys = [dic allKeys]; 44 | for (NSString *tem in keys) { 45 | if ([[dic objectForKey:tem] isEqualToString:@"(null)"]) { 46 | [dic setObject:@"" forKey:tem]; 47 | } 48 | } 49 | [list addObject:dic]; 50 | } 51 | NIMModel *model = [NIMModel initShareMD]; 52 | model.bankList = list; 53 | } 54 | -(void)addToBlackList:(NSString *)contactId success:(Success)suc Err:(Errors)err{ 55 | [[NIMSDK sharedSDK].userManager addToBlackList:contactId completion:^(NSError * _Nullable error) { 56 | if (!error) { 57 | [self getBlackList]; 58 | suc(@"拉黑成功!"); 59 | }else{ 60 | err(@"拉黑失败!"); 61 | } 62 | }]; 63 | } 64 | -(void)removeFromBlackList:(NSString *)contactId success:(Success)suc Err:(Errors)err{ 65 | [[NIMSDK sharedSDK].userManager removeFromBlackBlackList:contactId completion:^(NSError * _Nullable error) { 66 | if (!error) { 67 | [self getBlackList]; 68 | suc(@"移除成功!"); 69 | }else{ 70 | err(@"移除失败!"); 71 | } 72 | }]; 73 | } 74 | 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/extension/CustomAttachParser.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session.extension; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.JSONObject; 5 | import com.netease.nimlib.sdk.msg.attachment.MsgAttachment; 6 | import com.netease.nimlib.sdk.msg.attachment.MsgAttachmentParser; 7 | 8 | /** 9 | * Created by zhoujianghua on 2015/4/9. 10 | */ 11 | public class CustomAttachParser implements MsgAttachmentParser { 12 | 13 | private static final String KEY_TYPE = "msgtype"; 14 | private static final String KEY_DATA = "data"; 15 | 16 | @Override 17 | public MsgAttachment parse(String json) { 18 | CustomAttachment attachment = null; 19 | try { 20 | JSONObject object = JSON.parseObject(json); 21 | String type = object.getString(KEY_TYPE); 22 | JSONObject data = object.getJSONObject(KEY_DATA); 23 | switch (type) { 24 | case CustomAttachmentType.RedPacket: 25 | attachment = new RedPacketAttachement(); 26 | break; 27 | case CustomAttachmentType.BankTransfer: 28 | attachment = new BankTransferAttachment(); 29 | break; 30 | case CustomAttachmentType.BankTransferSystem: 31 | attachment = new BankTransferSystemAttachment(); 32 | break; 33 | case CustomAttachmentType.RedPacketOpen: 34 | attachment = new RedPacketOpenAttachement(); 35 | break; 36 | case CustomAttachmentType.LinkUrl: 37 | attachment = new LinkUrlAttachment(); 38 | break; 39 | case CustomAttachmentType.AccountNotice: 40 | attachment = new AccountNoticeAttachment(); 41 | break; 42 | case CustomAttachmentType.Card: 43 | attachment = new CardAttachment(); 44 | break; 45 | default: 46 | attachment = new DefaultCustomAttachment(type); 47 | break; 48 | } 49 | 50 | if (attachment != null) { 51 | attachment.fromJson(data); 52 | } 53 | } catch (Exception e) { 54 | 55 | } 56 | 57 | return attachment; 58 | } 59 | 60 | public static String packData(String type, JSONObject data) { 61 | JSONObject object = new JSONObject(); 62 | object.put(KEY_TYPE, type); 63 | if (data != null) { 64 | object.put(KEY_DATA, data); 65 | } 66 | 67 | return object.toJSONString(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/model/ContactDataTask.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.model; 2 | 3 | 4 | import com.netease.im.uikit.contact.core.item.AbsContactItem; 5 | import com.netease.im.uikit.contact.core.item.ContactItemFilter; 6 | import com.netease.im.uikit.contact.core.query.IContactDataProvider; 7 | import com.netease.im.uikit.contact.core.query.TextQuery; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * 通讯录获取数据任务 13 | * Created by huangjun on 2015/2/10. 14 | */ 15 | public class ContactDataTask { 16 | 17 | public interface Host { 18 | public void onData(ContactDataTask task, AbsContactDataList datas, boolean all); // 搜索完成,返回数据给调用方 19 | 20 | public boolean isCancelled(ContactDataTask task); // 判断调用放是否已经取消 21 | } 22 | 23 | private final IContactDataProvider dataProvider; // 数据源提供者 24 | 25 | private final ContactItemFilter filter; // 项过滤器 26 | 27 | private final TextQuery query; // 要搜索的信息,null为查询所有 28 | 29 | private Host host; 30 | 31 | public ContactDataTask(TextQuery query, IContactDataProvider dataProvider, ContactItemFilter filter) { 32 | this.query = query; 33 | this.dataProvider = dataProvider; 34 | this.filter = filter; 35 | } 36 | 37 | public final void setHost(Host host) { 38 | this.host = host; 39 | } 40 | 41 | protected void onPreProvide(AbsContactDataList datas) { 42 | 43 | } 44 | 45 | public final void run(AbsContactDataList datas) { 46 | // CANCELLED 47 | if (isCancelled()) { 48 | return; 49 | } 50 | 51 | // PRE PROVIDE 52 | onPreProvide(datas); 53 | 54 | // CANCELLED 55 | if (isCancelled()) { 56 | return; 57 | } 58 | 59 | // PROVIDE 60 | List items = dataProvider.provide(query); 61 | 62 | // ADD 63 | add(datas, items, filter); 64 | 65 | // BUILD 66 | datas.build(); 67 | 68 | // PUBLISH ALL 69 | publish(datas, true); 70 | } 71 | 72 | private void publish(AbsContactDataList datas, boolean all) { 73 | if (host != null) { 74 | datas.setQuery(query); 75 | 76 | host.onData(this, datas, all); 77 | } 78 | } 79 | 80 | private boolean isCancelled() { 81 | return host != null && host.isCancelled(this); 82 | } 83 | 84 | private static void add(AbsContactDataList datas, List items, ContactItemFilter filter) { 85 | for (AbsContactItem item : items) { 86 | if (filter == null || !filter.filter(item)) { 87 | datas.add(item); 88 | } 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/RNAppCacheUtilModule.java: -------------------------------------------------------------------------------- 1 | package com.netease.im; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.provider.MediaStore; 6 | 7 | import com.facebook.react.bridge.Promise; 8 | import com.facebook.react.bridge.ReactApplicationContext; 9 | import com.facebook.react.bridge.ReactContext; 10 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 11 | import com.facebook.react.bridge.ReactMethod; 12 | 13 | import java.io.File; 14 | import java.io.FileNotFoundException; 15 | 16 | /** 17 | * Created by dowin on 2017/7/13. 18 | */ 19 | 20 | public class RNAppCacheUtilModule extends ReactContextBaseJavaModule { 21 | 22 | private final static String TAG = "AppCacheUtil";//AppCacheUtil.getCacheSize clearCache 23 | private final static String NAME = "AppCacheUtil"; 24 | 25 | private ReactContext reactContext; 26 | 27 | public RNAppCacheUtilModule(ReactApplicationContext reactContext) { 28 | super(reactContext); 29 | this.reactContext = reactContext; 30 | } 31 | 32 | @Override 33 | public String getName() { 34 | return NAME; 35 | } 36 | 37 | @ReactMethod 38 | public void getCacheSize(final Promise promise) { 39 | FileCacheUtil.getCacheSie(new FileCacheUtil.OnObserverGet() { 40 | @Override 41 | public void onGetCacheSize(String size) { 42 | promise.resolve(size); 43 | } 44 | }); 45 | } 46 | 47 | @ReactMethod 48 | public void cleanCache(final Promise promise) { 49 | FileCacheUtil.cleanCache(new FileCacheUtil.OnObserverClean() { 50 | 51 | @Override 52 | public void onCleanCache(boolean succeeded) { 53 | promise.resolve("" + succeeded); 54 | } 55 | }); 56 | } 57 | 58 | @ReactMethod 59 | public void saveImageToAlbum(String filePath, final Promise promise) { 60 | 61 | File imageFile = new File(filePath); 62 | if (imageFile.exists()) { 63 | try { 64 | String path = MediaStore.Images.Media.insertImage(reactContext.getContentResolver(), imageFile.getAbsolutePath(), "title", "description"); 65 | reactContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + imageFile.getAbsolutePath()))); 66 | if (new File(path).exists()) { 67 | promise.resolve("200"); 68 | } else { 69 | promise.reject("-1", ""); 70 | } 71 | } catch (FileNotFoundException e) { 72 | e.printStackTrace(); 73 | } 74 | } else { 75 | promise.reject("-1", ""); 76 | } 77 | 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/provider/TeamDataProvider.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.provider; 2 | 3 | import com.netease.im.uikit.cache.TeamDataCache; 4 | import com.netease.im.uikit.contact.core.item.AbsContactItem; 5 | import com.netease.im.uikit.contact.core.item.ContactItem; 6 | import com.netease.im.uikit.contact.core.item.ItemTypes; 7 | import com.netease.im.uikit.contact.core.model.ContactGroupStrategy; 8 | import com.netease.im.uikit.contact.core.model.TeamContact; 9 | import com.netease.im.uikit.contact.core.query.TextComparator; 10 | import com.netease.im.uikit.contact.core.query.TextQuery; 11 | import com.netease.nimlib.sdk.team.model.Team; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | /** 17 | * 群数据源提供者 18 | *

19 | * Created by huangjun on 2015/3/1. 20 | */ 21 | public class TeamDataProvider { 22 | public static final List provide(TextQuery query, int itemType) { 23 | List sources = query(query, itemType); 24 | List items = new ArrayList<>(sources.size()); 25 | for (TeamContact t : sources) { 26 | items.add(createTeamItem(t)); 27 | } 28 | 29 | return items; 30 | } 31 | 32 | private static AbsContactItem createTeamItem(TeamContact team) { 33 | return new ContactItem(team, ItemTypes.TEAM) { 34 | @Override 35 | public int compareTo(ContactItem item) { 36 | return compareTeam((TeamContact) getContact(), (TeamContact) (item.getContact())); 37 | } 38 | 39 | @Override 40 | public String belongsGroup() { 41 | return ContactGroupStrategy.GROUP_TEAM; 42 | } 43 | }; 44 | } 45 | 46 | private static int compareTeam(TeamContact lhs, TeamContact rhs) { 47 | return TextComparator.compareIgnoreCase(lhs.getDisplayName(), rhs.getDisplayName()); 48 | } 49 | 50 | /** 51 | * * 数据查询 52 | */ 53 | private static final List query(TextQuery query, int itemType) { 54 | List teams; 55 | if (itemType == ItemTypes.TEAMS.ADVANCED_TEAM) { 56 | teams = TeamDataCache.getInstance().getAllAdvancedTeams(); 57 | } else if (itemType == ItemTypes.TEAMS.NORMAL_TEAM) { 58 | teams = TeamDataCache.getInstance().getAllNormalTeams(); 59 | } else { 60 | teams = TeamDataCache.getInstance().getAllTeams(); 61 | } 62 | 63 | List contacts = new ArrayList<>(); 64 | for (Team t : teams) { 65 | if (query == null || ContactSearch.hitTeam(t, query)) { 66 | contacts.add(new TeamContact(t)); 67 | } 68 | } 69 | 70 | return contacts; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/common/util/string/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.common.util.string; 2 | 3 | import android.text.TextUtils; 4 | 5 | import java.util.Locale; 6 | import java.util.UUID; 7 | 8 | public class StringUtil { 9 | 10 | public static String getPercentString(float percent) { 11 | return String.format(Locale.US, "%d%%", (int) (percent * 100)); 12 | } 13 | /** 14 | * 删除字符串中的空白符 15 | * 16 | * @param content 17 | * @return String 18 | */ 19 | public static String removeBlanks(String content) { 20 | if (content == null) { 21 | return null; 22 | } 23 | StringBuilder buff = new StringBuilder(); 24 | buff.append(content); 25 | for (int i = buff.length() - 1; i >= 0; i--) { 26 | if (' ' == buff.charAt(i) || ('\n' == buff.charAt(i)) || ('\t' == buff.charAt(i)) 27 | || ('\r' == buff.charAt(i))) { 28 | buff.deleteCharAt(i); 29 | } 30 | } 31 | return buff.toString(); 32 | } 33 | /** 34 | * 获取32位uuid 35 | * 36 | * @return 37 | */ 38 | public static String get32UUID() { 39 | return UUID.randomUUID().toString().replaceAll("-", ""); 40 | } 41 | 42 | public static boolean isEmpty(String input) { 43 | return TextUtils.isEmpty(input); 44 | } 45 | 46 | /** 47 | * 生成唯一号 48 | * 49 | * @return 50 | */ 51 | public static String get36UUID() { 52 | UUID uuid = UUID.randomUUID(); 53 | String uniqueId = uuid.toString(); 54 | return uniqueId; 55 | } 56 | 57 | public static String makeMd5(String source) { 58 | return MD5.getStringMD5(source); 59 | } 60 | 61 | public static final String filterUCS4(String str) { 62 | if (TextUtils.isEmpty(str)) { 63 | return str; 64 | } 65 | 66 | if (str.codePointCount(0, str.length()) == str.length()) { 67 | return str; 68 | } 69 | 70 | StringBuilder sb = new StringBuilder(); 71 | 72 | int index = 0; 73 | while (index < str.length()) { 74 | int codePoint = str.codePointAt(index); 75 | index += Character.charCount(codePoint); 76 | if (Character.isSupplementaryCodePoint(codePoint)) { 77 | continue; 78 | } 79 | 80 | sb.appendCodePoint(codePoint); 81 | } 82 | 83 | return sb.toString(); 84 | } 85 | 86 | /** 87 | * counter ASCII character as one, otherwise two 88 | * 89 | * @param str 90 | * @return count 91 | */ 92 | public static int counterChars(String str) { 93 | // return 94 | if (TextUtils.isEmpty(str)) { 95 | return 0; 96 | } 97 | int count = 0; 98 | for (int i = 0; i < str.length(); i++) { 99 | int tmp = (int) str.charAt(i); 100 | if (tmp > 0 && tmp < 127) { 101 | count += 1; 102 | } else { 103 | count += 2; 104 | } 105 | } 106 | return count; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/DWCustomAttachmentDecoder.m: -------------------------------------------------------------------------------- 1 | // 2 | // DWCustomAttachmentDecoder.m 3 | // RNNeteaseIm 4 | // 5 | // Created by Dowin on 2017/6/13. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import "DWCustomAttachmentDecoder.h" 10 | 11 | @implementation DWCustomAttachmentDecoder 12 | 13 | - (id)decodeAttachment:(NSString *)content 14 | { 15 | id attachment = nil; 16 | 17 | NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding]; 18 | if (data) { 19 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data 20 | options:0 21 | error:nil]; 22 | if ([dict isKindOfClass:[NSDictionary class]]) 23 | { 24 | NSString *strType = [self jsonString:@"msgtype" andDict:dict]; 25 | NSInteger custType = 0; 26 | if ([strType isEqualToString:@"redpacket"]) {//红包 27 | custType = CustomMessgeTypeRedpacket; 28 | }else if([strType isEqualToString:@"transfer"]){//转账 29 | custType = CustomMessgeTypeBankTransfer; 30 | }else if([strType isEqualToString:@"url"]){//链接 31 | custType = CustomMessgeTypeUrl; 32 | }else if([strType isEqualToString:@"account_notice"]){//账户资金变动 33 | custType = CustomMessgeTypeAccountNotice; 34 | }else if ([strType isEqualToString:@"redpacketOpen"]){//拆红包消息 35 | custType = CustomMessgeTypeRedPacketOpenMessage; 36 | }else if([strType isEqualToString:@"card"]){//名片 37 | custType = CustomMessgeTypeBusinessCard; 38 | }else if([strType isEqualToString:@"custom"]){//自定义 39 | custType = CustomMessgeTypeCustom; 40 | }else{//未知消息类型 41 | custType = CustomMessgeTypeUnknown; 42 | } 43 | NSDictionary *dataDict = [self jsonDict:@"data" andDict:dict]; 44 | DWCustomAttachment *obj = [[DWCustomAttachment alloc]init]; 45 | obj.custType = custType; 46 | obj.dataDict = dataDict; 47 | attachment = obj; 48 | } 49 | } 50 | return attachment; 51 | } 52 | 53 | 54 | - (NSString *)jsonString: (NSString *)key andDict:(NSDictionary *)dict 55 | { 56 | id object = [dict objectForKey:key]; 57 | if ([object isKindOfClass:[NSString class]]) 58 | { 59 | return object; 60 | } 61 | else if([object isKindOfClass:[NSNumber class]]) 62 | { 63 | return [object stringValue]; 64 | } 65 | return nil; 66 | } 67 | 68 | - (NSDictionary *)jsonDict: (NSString *)key andDict:(NSDictionary *)dict 69 | { 70 | id object = [dict objectForKey:key]; 71 | return [object isKindOfClass:[NSDictionary class]] ? object : nil; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/common/push/NimMixPushMessageHandler.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.common.push; 2 | 3 | import android.app.Activity; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | 8 | import com.netease.im.IMApplication; 9 | import com.netease.im.uikit.common.util.log.LogUtil; 10 | import com.netease.nimlib.sdk.NimIntent; 11 | import com.netease.nimlib.sdk.StatusBarNotificationConfig; 12 | import com.netease.nimlib.sdk.mixpush.MixPushMessageHandler; 13 | import com.netease.nimlib.sdk.msg.MessageBuilder; 14 | import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; 15 | import com.netease.nimlib.sdk.msg.model.IMMessage; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Map; 19 | 20 | /** 21 | * Created by hzchenkang on 2016/11/10. 22 | */ 23 | 24 | public class NimMixPushMessageHandler implements MixPushMessageHandler { 25 | 26 | @Override 27 | public boolean onNotificationClicked(Context context, Map payload) { 28 | 29 | LogUtil.w(NimMixPushMessageHandler.class.getSimpleName(), "rev miPushMessage payload " + payload); 30 | 31 | String sessionId = payload.get("sessionID"); 32 | String type = payload.get("sessionType"); 33 | // 34 | if (sessionId != null && type != null) { 35 | int typeValue = Integer.valueOf(type); 36 | ArrayList imMessages = new ArrayList<>(); 37 | IMMessage imMessage = MessageBuilder.createEmptyMessage(sessionId, SessionTypeEnum.typeOfValue(typeValue), 0); 38 | imMessages.add(imMessage); 39 | Intent notifyIntent = new Intent(); 40 | notifyIntent.setComponent(initLaunchComponent(context)); 41 | notifyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); 42 | notifyIntent.setAction(Intent.ACTION_VIEW); 43 | notifyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 必须 44 | notifyIntent.putExtra(NimIntent.EXTRA_NOTIFY_CONTENT, imMessages); 45 | 46 | context.startActivity(notifyIntent); 47 | return true; 48 | } else { 49 | return false; 50 | } 51 | } 52 | 53 | @Override 54 | public boolean cleanMixPushNotifications(int pushType) { 55 | return true; 56 | } 57 | 58 | private ComponentName initLaunchComponent(Context context) { 59 | ComponentName launchComponent; 60 | StatusBarNotificationConfig config = IMApplication.getNotificationConfig(); 61 | Class entrance = config.notificationEntrance; 62 | if (entrance == null) { 63 | launchComponent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()).getComponent(); 64 | } else { 65 | launchComponent = new ComponentName(context, entrance); 66 | } 67 | return launchComponent; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKitNotificationFirer.m: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKitNotificationFirer.m 3 | // NIMKit 4 | // 5 | // Created by chris on 16/6/13. 6 | // Copyright © 2016年 NetEase. All rights reserved. 7 | // 8 | 9 | #import "NIMKitNotificationFirer.h" 10 | 11 | NSString *const NIMKitUserInfoHasUpdatedNotification = @"NIMKitUserInfoHasUpdatedNotification"; 12 | NSString *const NIMKitTeamInfoHasUpdatedNotification = @"NIMKitTeamInfoHasUpdatedNotification"; 13 | 14 | NSString *const NIMKitUserBlackListHasUpdatedNotification = @"NIMKitUserBlackListHasUpdatedNotification"; 15 | NSString *const NIMKitUserMuteListHasUpdatedNotification = @"NIMKitUserMuteListHasUpdatedNotification"; 16 | 17 | NSString *const NIMKitTeamMembersHasUpdatedNotification = @"NIMKitTeamMembersHasUpdatedNotification"; 18 | 19 | NSString *const NIMKitInfoKey = @"InfoId"; 20 | 21 | @implementation NIMKitNotificationFirer 22 | 23 | - (instancetype)init{ 24 | self = [super init]; 25 | if (self) { 26 | _timer = [[NIMKitTimerHolder alloc] init]; 27 | _timeInterval = 1.0f; 28 | _cachedInfo = [[NSMutableDictionary alloc] init]; 29 | } 30 | return self; 31 | } 32 | 33 | - (void)addFireInfo:(NIMKitFirerInfo *)info{ 34 | NSAssert([NSThread currentThread].isMainThread, @"info must be fired in main thread"); 35 | if (!self.cachedInfo.count) { 36 | [self.timer startTimer:self.timeInterval delegate:self repeats:NO]; 37 | } 38 | [self.cachedInfo setObject:info forKey:info.saveIdentity]; 39 | } 40 | 41 | #pragma mark - NIMKitTimerHolderDelegate 42 | 43 | - (void)onNIMKitTimerFired:(NIMKitTimerHolder *)holder{ 44 | NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 45 | for (NIMKitFirerInfo *info in self.cachedInfo.allValues) { 46 | NSMutableArray *fireInfos = dict[info.notificationName]; 47 | if (!fireInfos) { 48 | fireInfos = [[NSMutableArray alloc] init]; 49 | dict[info.notificationName] = fireInfos; 50 | } 51 | if (info.fireObject) { 52 | [fireInfos addObject:info.fireObject]; 53 | } 54 | } 55 | 56 | for (NSString *notificationName in dict) { 57 | NSDictionary *userInfo = dict[notificationName]? @{ NIMKitInfoKey:dict[notificationName] } : nil; 58 | [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:nil userInfo:userInfo]; 59 | } 60 | 61 | [self.cachedInfo removeAllObjects]; 62 | } 63 | 64 | 65 | @end 66 | 67 | 68 | @implementation NIMKitFirerInfo 69 | 70 | - (NSObject *)fireObject 71 | { 72 | if (self.session) { 73 | return self.session.sessionId; 74 | } 75 | return [NSNull null]; 76 | } 77 | 78 | - (NSString *)saveIdentity 79 | { 80 | if (self.session) { 81 | return [NSString stringWithFormat:@"%@-%zd",self.session.sessionId,self.session.sessionType];; 82 | } 83 | return self.notificationName; 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/Model/NSDictionary+NTESJson.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+NTESJson.m 3 | // NIM 4 | // 5 | // Created by amao on 13-7-12. 6 | // Copyright (c) 2013年 Netease. All rights reserved. 7 | // 8 | 9 | #import "ImConfig.h" 10 | 11 | @implementation NSDictionary (NTESJson) 12 | 13 | - (NSString *)jsonString: (NSString *)key 14 | { 15 | id object = [self objectForKey:key]; 16 | if ([object isKindOfClass:[NSString class]]) 17 | { 18 | return object; 19 | } 20 | else if([object isKindOfClass:[NSNumber class]]) 21 | { 22 | return [object stringValue]; 23 | } 24 | return nil; 25 | } 26 | 27 | - (NSDictionary *)jsonDict: (NSString *)key 28 | { 29 | id object = [self objectForKey:key]; 30 | return [object isKindOfClass:[NSDictionary class]] ? object : nil; 31 | } 32 | 33 | 34 | - (NSArray *)jsonArray: (NSString *)key 35 | { 36 | id object = [self objectForKey:key]; 37 | return [object isKindOfClass:[NSArray class]] ? object : nil; 38 | 39 | } 40 | 41 | - (NSArray *)jsonStringArray: (NSString *)key 42 | { 43 | NSArray *array = [self jsonArray:key]; 44 | BOOL invalid = NO; 45 | for (id item in array) 46 | { 47 | if (![item isKindOfClass:[NSString class]]) 48 | { 49 | invalid = YES; 50 | } 51 | } 52 | return invalid ? nil : array; 53 | } 54 | 55 | - (BOOL)jsonBool: (NSString *)key 56 | { 57 | id object = [self objectForKey:key]; 58 | if ([object isKindOfClass:[NSString class]] || 59 | [object isKindOfClass:[NSNumber class]]) 60 | { 61 | return [object boolValue]; 62 | } 63 | return NO; 64 | } 65 | 66 | - (NSInteger)jsonInteger: (NSString *)key 67 | { 68 | id object = [self objectForKey:key]; 69 | if ([object isKindOfClass:[NSString class]] || 70 | [object isKindOfClass:[NSNumber class]]) 71 | { 72 | return [object integerValue]; 73 | } 74 | return 0; 75 | } 76 | 77 | - (long long)jsonLongLong: (NSString *)key 78 | { 79 | id object = [self objectForKey:key]; 80 | if ([object isKindOfClass:[NSString class]] || 81 | [object isKindOfClass:[NSNumber class]]) 82 | { 83 | return [object longLongValue]; 84 | } 85 | return 0; 86 | } 87 | 88 | - (unsigned long long)jsonUnsignedLongLong:(NSString *)key 89 | { 90 | id object = [self objectForKey:key]; 91 | if ([object isKindOfClass:[NSString class]] || 92 | [object isKindOfClass:[NSNumber class]]) 93 | { 94 | return [object unsignedLongLongValue]; 95 | } 96 | return 0; 97 | } 98 | 99 | 100 | - (double)jsonDouble: (NSString *)key{ 101 | id object = [self objectForKey:key]; 102 | if ([object isKindOfClass:[NSString class]] || 103 | [object isKindOfClass:[NSNumber class]]) 104 | { 105 | return [object doubleValue]; 106 | } 107 | return 0; 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/common/util/sys/ReflectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.common.util.sys; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.netease.im.uikit.common.util.log.LogUtil; 6 | 7 | import java.lang.reflect.Field; 8 | import java.lang.reflect.Method; 9 | 10 | /** 11 | * 反射工具类 12 | * 通过反射获得对应函数功能 13 | */ 14 | public class ReflectionUtil { 15 | 16 | /** 17 | * 通过类对象,运行指定方法 18 | * @param obj 类对象 19 | * @param methodName 方法名 20 | * @param params 参数值 21 | * @return 失败返回null 22 | */ 23 | public static Object invokeMethod(Object obj, String methodName, Object[] params) { 24 | if (obj == null || TextUtils.isEmpty(methodName)) { 25 | return null; 26 | } 27 | 28 | Class clazz = obj.getClass(); 29 | try { 30 | Class[] paramTypes = null; 31 | if (params != null) { 32 | paramTypes = new Class[params.length]; 33 | for (int i = 0; i < params.length; ++i) { 34 | paramTypes[i] = params[i].getClass(); 35 | } 36 | } 37 | Method method = clazz.getMethod(methodName, paramTypes); 38 | method.setAccessible(true); 39 | return method.invoke(obj, params); 40 | } catch (NoSuchMethodException e) { 41 | LogUtil.w("reflect", "method " + methodName + " not found in " + obj.getClass().getName()); 42 | } catch (Exception e) { 43 | e.printStackTrace(); 44 | } 45 | return null; 46 | } 47 | 48 | public static Object getFieldValue(Object obj, String fieldName) { 49 | if (obj == null || TextUtils.isEmpty(fieldName)) { 50 | return null; 51 | } 52 | 53 | Class clazz = obj.getClass(); 54 | while (clazz != Object.class) { 55 | try { 56 | Field field = clazz.getDeclaredField(fieldName); 57 | field.setAccessible(true); 58 | return field.get(obj); 59 | } catch (Exception e) { 60 | } 61 | clazz = clazz.getSuperclass(); 62 | } 63 | LogUtil.e("reflect", "get field " + fieldName + " not found in " + obj.getClass().getName()); 64 | return null; 65 | } 66 | 67 | public static void setFieldValue(Object obj, String fieldName, Object value) { 68 | if (obj == null || TextUtils.isEmpty(fieldName)) { 69 | return; 70 | } 71 | 72 | Class clazz = obj.getClass(); 73 | while (clazz != Object.class) { 74 | try { 75 | Field field = clazz.getDeclaredField(fieldName); 76 | field.setAccessible(true); 77 | field.set(obj, value); 78 | return; 79 | } catch (Exception e) { 80 | } 81 | clazz = clazz.getSuperclass(); 82 | } 83 | LogUtil.e("reflect", "set field " + fieldName + " not found in " + obj.getClass().getName()); 84 | } 85 | } -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/group/DefaultDataList.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.group; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by dowin on 2017/8/16. 10 | */ 11 | 12 | public class DefaultDataList extends AbstractDataList{ 13 | private List groups; 14 | 15 | private Map indexes; 16 | 17 | public DefaultDataList(GroupStrategy groupStrategy) { 18 | super(groupStrategy); 19 | } 20 | 21 | @Override 22 | public int getCount() { 23 | int count = 0; 24 | for (AbstractDataList.Group group : groups) { 25 | count += group.getCount(); 26 | } 27 | return count; 28 | } 29 | 30 | @Override 31 | public AbstractItem getItem(int index) { 32 | int count = 0; 33 | for (AbstractDataList.Group group : groups) { 34 | int gIndex = index - count; 35 | int gCount = group.getCount(); 36 | 37 | if (gIndex >= 0 && gIndex < gCount) { 38 | return group.getItem(gIndex); 39 | } 40 | 41 | count += gCount; 42 | } 43 | 44 | return null; 45 | } 46 | 47 | @Override 48 | public boolean isEmpty() { 49 | return groups.isEmpty() || indexes.isEmpty(); 50 | } 51 | 52 | @Override 53 | public List getItems() { 54 | List items = new ArrayList<>(); 55 | for (AbstractDataList.Group group : groups) { 56 | AbstractItem head = group.getHead(); 57 | if (head != null) { 58 | items.add(head); 59 | } 60 | items.addAll(group.getItems()); 61 | } 62 | 63 | return items; 64 | } 65 | 66 | @Override 67 | public Map getIndexes() { 68 | return indexes; 69 | } 70 | 71 | @Override 72 | public void build() { 73 | // 74 | // GROUPS 75 | // 76 | 77 | List groups = new ArrayList<>(); 78 | groups.add(groupNull); 79 | groups.addAll(groupMap.values()); 80 | sortGroups(groups); 81 | 82 | // 83 | // INDEXES 84 | // 85 | 86 | Map indexes = new HashMap<>(); 87 | int count = 0; 88 | for (AbstractDataList.Group group : groups) { 89 | if (group.id != null) { 90 | indexes.put(group.id, count); 91 | } 92 | 93 | count += group.getCount(); 94 | } 95 | 96 | // 97 | // RESULT 98 | // 99 | 100 | this.groups = groups; 101 | this.indexes = indexes; 102 | } 103 | 104 | public void clear(){ 105 | super.clear(); 106 | if(groups!=null){ 107 | groups.clear(); 108 | } 109 | if(indexes!=null){ 110 | indexes.clear(); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /im/Friend.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: huangjun 3 | * @Date: 2019-03-06 16:28:25 4 | * @Last Modified by: huangjun 5 | * @Last Modified time: 2020-04-19 17:26:46 6 | */ 7 | import {NativeModules} from 'react-native'; 8 | const {RNNeteaseIm} = NativeModules; 9 | class Friend { 10 | /** 11 | * 进入好友 12 | * @returns {*} @see observeFriend 13 | */ 14 | startFriendList() { 15 | return RNNeteaseIm.startFriendList(); 16 | } 17 | /** 18 | * 退出好友 19 | * @returns {*} 20 | */ 21 | stopFriendList() { 22 | return RNNeteaseIm.stopFriendList(); 23 | } 24 | /** 25 | * 获取本地用户资料 26 | * @param contactId 27 | * @returns {*} 28 | */ 29 | getUserInfo(contactId) { 30 | return RNNeteaseIm.getUserInfo(contactId); 31 | } 32 | /** 33 | * 获取服务器用户资料 34 | * @param contactId 35 | * @returns {*} 36 | */ 37 | fetchUserInfo(contactId) { 38 | return RNNeteaseIm.fetchUserInfo(contactId); 39 | } 40 | /** 41 | * 保存用户资料 42 | * @param contactId {'NIMUserInfoUpdateTagNick':'昵称'} 43 | * @returns {*} 44 | */ 45 | updateMyUserInfo(userInFo) { 46 | return RNNeteaseIm.updateMyUserInfo(userInFo); 47 | } 48 | /** 49 | * 保存好友备注 50 | * @param contactId 51 | * @returns {*} 52 | */ 53 | updateUserInfo(contactId, alias) { 54 | return RNNeteaseIm.updateUserInfo(contactId, alias); 55 | } 56 | /** 57 | * 好友列表 58 | * @param keyword 59 | * @returns {*} 60 | */ 61 | getFriendList(keyword) { 62 | return RNNeteaseIm.getFriendList(keyword); 63 | } 64 | /** 65 | * 添加好友 66 | * @param contactId 67 | * @param msg 备注 68 | * @returns {*} 69 | */ 70 | addFriend(contactId, msg) { 71 | return RNNeteaseIm.addFriend(contactId, msg); 72 | } 73 | 74 | /** 75 | * 添加好友 76 | * @param contactId 77 | * @param verifyType "1" 直接添加 其他 验证添加 78 | * @param msg 备注 79 | * @returns {*} 80 | */ 81 | addFriendWithType(contactId, verifyType, msg) { 82 | return RNNeteaseIm.addFriendWithType(contactId, verifyType, msg); 83 | } 84 | /** 85 | * 删除好友 86 | * @param contactId 87 | * @returns {*} 88 | */ 89 | deleteFriend(contactId) { 90 | return RNNeteaseIm.deleteFriend(contactId); 91 | } 92 | /** 93 | * 进入黑名单列表 94 | * @returns {*} @see observeBlackList 95 | */ 96 | startBlackList() { 97 | return RNNeteaseIm.startBlackList(); 98 | } 99 | /** 100 | * 退出黑名单列表 101 | * @returns {*} 102 | */ 103 | stopBlackList() { 104 | return RNNeteaseIm.stopBlackList(); 105 | } 106 | /** 107 | * 获取黑名单列表 108 | * @returns {*} 109 | */ 110 | getBlackList() { 111 | return RNNeteaseIm.getBlackList(); 112 | } 113 | /** 114 | * 加入黑名单 115 | * @returns {*} 116 | */ 117 | addToBlackList(contactId) { 118 | return RNNeteaseIm.addToBlackList(contactId); 119 | } 120 | /** 121 | * 移出黑名单 122 | * @returns {*} 123 | */ 124 | removeFromBlackList(contactId) { 125 | return RNNeteaseIm.removeFromBlackList(contactId); 126 | } 127 | } 128 | export default new Friend(); 129 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/ImPushConfig.java: -------------------------------------------------------------------------------- 1 | package com.netease.im; 2 | 3 | public class ImPushConfig { 4 | 5 | /** 6 | * 小米推送 appId 7 | */ 8 | public String xmAppId; 9 | 10 | /** 11 | * 小米推送 appKey 12 | */ 13 | public String xmAppKey; 14 | 15 | /** 16 | * 小米推送证书,请在云信管理后台申请 17 | */ 18 | public String xmCertificateName; 19 | 20 | /** 21 | * 华为推送 appId 请在 AndroidManifest.xml 文件中配置 22 | * 华为推送证书,请在云信管理后台申请 23 | */ 24 | public String hwCertificateName; 25 | 26 | /** 27 | * 魅族推送 appId 28 | */ 29 | public String mzAppId; 30 | 31 | /** 32 | * 魅族推送 appKey 33 | */ 34 | public String mzAppKey; 35 | 36 | /** 37 | * 魅族推送证书,请在云信管理后台申请 38 | */ 39 | public String mzCertificateName; 40 | 41 | /** 42 | * FCM 推送证书,请在云信管理后台申请 43 | * 海外客户使用 44 | */ 45 | public String fcmCertificateName; 46 | 47 | public String getXmAppKey() { 48 | return xmAppKey; 49 | } 50 | 51 | public void setXmAppKey(String xmAppKey) { 52 | this.xmAppKey = xmAppKey; 53 | } 54 | 55 | public String getVivoCertificateName() { 56 | return vivoCertificateName; 57 | } 58 | 59 | public void setVivoCertificateName(String vivoCertificateName) { 60 | this.vivoCertificateName = vivoCertificateName; 61 | } 62 | 63 | public String getMzCertificateName() { 64 | return mzCertificateName; 65 | } 66 | 67 | public void setMzCertificateName(String mzCertificateName) { 68 | this.mzCertificateName = mzCertificateName; 69 | } 70 | 71 | public String getFcmCertificateName() { 72 | return fcmCertificateName; 73 | } 74 | 75 | public void setFcmCertificateName(String fcmCertificateName) { 76 | this.fcmCertificateName = fcmCertificateName; 77 | } 78 | 79 | public String getMzAppKey() { 80 | return mzAppKey; 81 | } 82 | 83 | public void setMzAppKey(String mzAppKey) { 84 | this.mzAppKey = mzAppKey; 85 | } 86 | 87 | public String getMzAppId() { 88 | return mzAppId; 89 | } 90 | 91 | public void setMzAppId(String mzAppId) { 92 | this.mzAppId = mzAppId; 93 | } 94 | 95 | public String getHwCertificateName() { 96 | return hwCertificateName; 97 | } 98 | 99 | public void setHwCertificateName(String hwCertificateName) { 100 | this.hwCertificateName = hwCertificateName; 101 | } 102 | 103 | public String getXmCertificateName() { 104 | return xmCertificateName; 105 | } 106 | 107 | public void setXmCertificateName(String xmCertificateName) { 108 | this.xmCertificateName = xmCertificateName; 109 | } 110 | 111 | /** 112 | * VIVO推送 appId apiKey请在 AndroidManifest.xml 文件中配置 113 | * VIVO推送证书,请在云信管理后台申请 114 | */ 115 | public String vivoCertificateName; 116 | 117 | public String getXmAppId() { 118 | return xmAppId; 119 | } 120 | 121 | public void setXmAppId(String xmAppId) { 122 | this.xmAppId = xmAppId; 123 | } 124 | 125 | } 126 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/model/ContactDataList.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.model; 2 | 3 | 4 | import com.netease.im.uikit.contact.core.item.AbsContactItem; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | 12 | /** 13 | * 通讯录列表数据(分组、索引) 14 | * Created by huangjun on 2015/2/10. 15 | */ 16 | public class ContactDataList extends AbsContactDataList { 17 | // 18 | // RESULT DATA 19 | // 20 | 21 | private List groups; 22 | 23 | private Map indexes; 24 | 25 | public ContactDataList(ContactGroupStrategy groupStrategy) { 26 | super(groupStrategy); 27 | } 28 | 29 | @Override 30 | public int getCount() { 31 | int count = 0; 32 | for (Group group : groups) { 33 | count += group.getCount(); 34 | } 35 | return count; 36 | } 37 | 38 | @Override 39 | public AbsContactItem getItem(int index) { 40 | int count = 0; 41 | for (Group group : groups) { 42 | int gIndex = index - count; 43 | int gCount = group.getCount(); 44 | 45 | if (gIndex >= 0 && gIndex < gCount) { 46 | return group.getItem(gIndex); 47 | } 48 | 49 | count += gCount; 50 | } 51 | 52 | return null; 53 | } 54 | 55 | @Override 56 | public boolean isEmpty() { 57 | return groups.isEmpty() || indexes.isEmpty(); 58 | } 59 | 60 | @Override 61 | public List getItems() { 62 | List items = new ArrayList(); 63 | for (Group group : groups) { 64 | AbsContactItem head = group.getHead(); 65 | if (head != null) { 66 | items.add(head); 67 | } 68 | items.addAll(group.getItems()); 69 | } 70 | 71 | return items; 72 | } 73 | 74 | @Override 75 | public Map getIndexes() { 76 | return indexes; 77 | } 78 | 79 | @Override 80 | public void build() { 81 | // 82 | // GROUPS 83 | // 84 | 85 | List groups = new ArrayList(); 86 | groups.add(groupNull); 87 | groups.addAll(groupMap.values()); 88 | sortGroups(groups); 89 | 90 | // 91 | // INDEXES 92 | // 93 | 94 | Map indexes = new HashMap(); 95 | int count = 0; 96 | for (Group group : groups) { 97 | if (group.id != null) { 98 | indexes.put(group.id, count); 99 | } 100 | 101 | count += group.getCount(); 102 | } 103 | 104 | // 105 | // RESULT 106 | // 107 | 108 | this.groups = groups; 109 | this.indexes = indexes; 110 | } 111 | 112 | public void clear(){ 113 | super.clear(); 114 | if(groups!=null){ 115 | groups.clear(); 116 | } 117 | if(indexes!=null){ 118 | indexes.clear(); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/session/helper/MessageHelper.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.session.helper; 2 | 3 | import com.netease.im.login.LoginService; 4 | import com.netease.im.uikit.cache.TeamDataCache; 5 | import com.netease.nimlib.sdk.NIMClient; 6 | import com.netease.nimlib.sdk.msg.MessageBuilder; 7 | import com.netease.nimlib.sdk.msg.MsgService; 8 | import com.netease.nimlib.sdk.msg.constant.MsgStatusEnum; 9 | import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; 10 | import com.netease.nimlib.sdk.msg.model.CustomMessageConfig; 11 | import com.netease.nimlib.sdk.msg.model.IMMessage; 12 | import com.netease.nimlib.sdk.team.constant.TeamTypeEnum; 13 | import com.netease.nimlib.sdk.team.model.Team; 14 | 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | /** 19 | * Created by hzxuwen on 2016/8/19. 20 | */ 21 | public class MessageHelper { 22 | 23 | public static MessageHelper getInstance() { 24 | return InstanceHolder.instance; 25 | } 26 | 27 | static class InstanceHolder { 28 | final static MessageHelper instance = new MessageHelper(); 29 | } 30 | 31 | // 消息撤回 32 | public void onRevokeMessage(IMMessage item) { 33 | if (item == null) { 34 | return; 35 | } 36 | if (item.getSessionType() == SessionTypeEnum.Team) { 37 | Team t = TeamDataCache.getInstance().getTeamById(item.getSessionId()); 38 | if (t == null || !t.isMyTeam()) { 39 | return; 40 | } 41 | } 42 | 43 | IMMessage message = MessageBuilder.createTipMessage(item.getSessionId(), item.getSessionType()); 44 | String nick = ""; 45 | if (item.getSessionType() == SessionTypeEnum.Team) { 46 | nick = TeamDataCache.getInstance().getTeamMemberDisplayNameYou(item.getSessionId(), item.getFromAccount()); 47 | } else if (item.getSessionType() == SessionTypeEnum.P2P) { 48 | nick = item.getFromAccount().equals(LoginService.getInstance().getAccount()) ? "你" : "对方"; 49 | } 50 | message.setContent(nick + "撤回了一条消息"); 51 | // message.setPushContent(nick + "撤回了一条消息"); 52 | message.setStatus(MsgStatusEnum.success); 53 | CustomMessageConfig config = new CustomMessageConfig(); 54 | config.enableUnreadCount = false; 55 | config.enablePush = false; 56 | message.setConfig(config); 57 | NIMClient.getService(MsgService.class).saveMessageToLocalEx(message, true, item.getTime()); 58 | } 59 | 60 | public void onCreateTeamMessage(Team team) { 61 | if (team == null || team.getType() == TeamTypeEnum.Normal) { 62 | return; 63 | } 64 | Map content = new HashMap<>(1); 65 | content.put("content", "成功创建群"); 66 | IMMessage msg = MessageBuilder.createTipMessage(team.getId(), SessionTypeEnum.Team); 67 | msg.setRemoteExtension(content); 68 | CustomMessageConfig config = new CustomMessageConfig(); 69 | config.enableUnreadCount = false; 70 | config.enablePush = false; 71 | msg.setConfig(config); 72 | msg.setStatus(MsgStatusEnum.success); 73 | NIMClient.getService(MsgService.class).saveMessageToLocal(msg, true); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/extension/AccountNoticeAttachment.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session.extension; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.facebook.react.bridge.Arguments; 5 | import com.facebook.react.bridge.WritableMap; 6 | import com.netease.im.MessageConstant; 7 | 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | /** 12 | * Created by dowin on 2017/6/14. 13 | */ 14 | 15 | public class AccountNoticeAttachment extends CustomAttachment { 16 | 17 | final String KEY_TITLE = "title"; 18 | final String KEY_DATE = "date"; 19 | final String KEY_TIME = "time"; 20 | final String KEY_AMOUNT = "amount"; 21 | final String KEY_BODY = "body"; 22 | final String KEY_SERIAL_NO = "serialNo"; 23 | 24 | private String title; 25 | private String date; 26 | private String time; 27 | private String amount; 28 | private Map body; 29 | private String serialNo; 30 | 31 | public AccountNoticeAttachment() { 32 | super(CustomAttachmentType.AccountNotice); 33 | } 34 | 35 | @Override 36 | protected void parseData(JSONObject data) { 37 | title = data.getString(KEY_TITLE); 38 | time = data.getString(KEY_TIME); 39 | date = data.getString(KEY_DATE); 40 | amount = data.getString(KEY_AMOUNT); 41 | 42 | body = data.getJSONObject(KEY_BODY); 43 | serialNo = data.getString(KEY_SERIAL_NO); 44 | } 45 | 46 | @Override 47 | protected JSONObject packData() { 48 | 49 | JSONObject object = new JSONObject(); 50 | object.put(KEY_TITLE, title); 51 | object.put(KEY_TIME, time); 52 | object.put(KEY_DATE, date); 53 | object.put(KEY_AMOUNT, amount); 54 | object.put(KEY_SERIAL_NO, serialNo); 55 | JSONObject bodyJson = new JSONObject(); 56 | if (body != null && !body.isEmpty()) { 57 | 58 | Set> entrySet = body.entrySet(); 59 | for (Map.Entry entry : entrySet) { 60 | bodyJson.put(entry.getKey(), entry.getValue()); 61 | } 62 | 63 | } 64 | object.put(KEY_BODY, bodyJson); 65 | return object; 66 | } 67 | 68 | public String getTitle() { 69 | return title; 70 | } 71 | 72 | @Override 73 | public WritableMap toReactNative() { 74 | WritableMap writableMap = Arguments.createMap(); 75 | writableMap.putString(MessageConstant.AccountNotice.TITLE, title); 76 | writableMap.putString(MessageConstant.AccountNotice.TIME, time); 77 | writableMap.putString(MessageConstant.AccountNotice.DATE, date); 78 | writableMap.putString(MessageConstant.AccountNotice.AMOUNT, amount); 79 | writableMap.putString(MessageConstant.AccountNotice.SERIAL_NO, serialNo); 80 | WritableMap bodyMap = Arguments.createMap(); 81 | if (body != null && !body.isEmpty()) { 82 | Set> entrySet = body.entrySet(); 83 | for (Map.Entry entry : entrySet) { 84 | bodyMap.putString(entry.getKey(), String.valueOf(entry.getValue())); 85 | } 86 | } 87 | writableMap.putMap(MessageConstant.AccountNotice.BODY, bodyMap); 88 | return writableMap; 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/ConversationViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ConversationViewController.h 3 | // NIM 4 | // 5 | // Created by Dowin on 2017/5/5. 6 | // Copyright © 2017年 Dowin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ImConfig.h" 11 | 12 | typedef void(^Success)(id param); 13 | typedef void(^Errors)(id erro); 14 | @interface ConversationViewController : UIViewController 15 | 16 | +(instancetype)initWithConversationViewController; 17 | -(void)localSession:(NSInteger)index cerrentmessageId:(NSString *)currentMessageID success:(Success)succe err:(Errors)err; 18 | -(void)startSession:(NSString *)sessionID withType:(NSString *)type; 19 | -(void)stopSession; 20 | //-(void)sendAudioRecode:(NSString *)filePath; 21 | /** 22 | * 会话页详细配置 23 | */ 24 | //取消录音 25 | - (void)onCancelRecording; 26 | //结束录音 27 | - (void)onStopRecording; 28 | //开始录音 29 | - (void)onStartRecording; 30 | //发送文本,并指定@用户(@仅适用于群组) 31 | -(void)sendMessage:(NSString *)mess andApnsMembers:(NSArray *)members; 32 | //发送图片 33 | -(void)sendImageMessages:( NSString *)path displayName:( NSString *)displayName; 34 | //发送音频 35 | -(void)sendAudioMessage:( NSString *)file duration:( NSString *)duration; 36 | //发送视频 37 | -(void)sendVideoMessage:( NSString *)path duration:( NSString *)duration width:( NSString *)width height:( NSString *)height displayName:( NSString *)displayName; 38 | //发送自定义消息 39 | -(void)sendCustomMessage:(NSDictionary *)dataDict; 40 | //发送地理位置消息 41 | -(void)sendLocationMessage:( NSString *)latitude longitude:( NSString *)longitude address:( NSString *)address; 42 | //发送提醒消息 43 | -(void)sendTipMessage:( NSString *)content; 44 | //发送红包消息 45 | - (void)sendRedPacketMessage:(NSString *)type comments:(NSString *)comments serialNo:(NSString *)serialNo; 46 | //发送转账消息 47 | - (void)sendBankTransferMessage:(NSString *)amount comments:(NSString *)comments serialNo:(NSString *)serialNo; 48 | //发送拆红包消息 49 | - (void)sendRedPacketOpenMessage:(NSString *)sendId hasRedPacket:(NSString *)hasRedPacket serialNo:(NSString *)serialNo; 50 | //发送名片消息 51 | - (void)sendCardMessage:(NSString *)type sessionId:(NSString *)sessionId name:(NSString *)name imgPath:(NSString *)strImgPath; 52 | 53 | //转发消息 54 | -(void)forwardMessage:(NSString *)messageId sessionId:(NSString *)sessionId sessionType:(NSString *)sessionType content:(NSString *)content success:(Success)succe; 55 | 56 | //本地历史记录 57 | -(void)localSessionList:(NSString *)sessionId sessionType:(NSString *)sessionType timeLong:(NSString *)timeLong direction:(NSString *)direction limit:(NSString *)limit asc:(BOOL)asc success:(Success)succe; 58 | //撤回消息 59 | -(void)revokeMessage:(NSString *)messageId success:(Success)succe; 60 | //开始播放录音 61 | - (void)play:(NSString *)filepath; 62 | //停止播放 63 | - (void)stopPlay; 64 | //好友消息提醒 65 | -(void)muteMessage:(NSString *)contactId mute:(NSString *)mute Succ:(Success)succ Err:(Errors)err; 66 | //清空本地聊天记录 67 | -(void)clearMsg:(NSString *)contactId type:(NSString *)type; 68 | //删除一条信息 69 | -(void)deleteMsg:(NSString *)messageId; 70 | //麦克风权限 71 | - (void)onTouchVoiceSucc:(Success)succ Err:(Errors)err; 72 | //更新录音消息为已播放 73 | - (void)updateAudioMessagePlayStatus:(NSString *)messageID; 74 | 75 | //获得撤回内容 76 | - (NSString *)tipOnMessageRevoked:(id)message; 77 | //更具提示生成撤回消息 78 | - (NIMMessage *)msgWithTip:(NSString *)tip; 79 | //重发消息 80 | - (void)resendMessage:(NSString *)messageID; 81 | @end 82 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/common/sys/InstallUtil.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.common.sys; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.pm.PackageInfo; 6 | import android.content.pm.PackageManager; 7 | import android.content.pm.PackageManager.NameNotFoundException; 8 | import android.net.Uri; 9 | import android.text.TextUtils; 10 | 11 | 12 | import com.netease.im.IMApplication; 13 | 14 | import java.io.File; 15 | 16 | public class InstallUtil { 17 | private static final String TAG = "InstallUtil"; 18 | 19 | private static int versionCode; 20 | 21 | private static String versionName; 22 | 23 | /** 24 | * 是否已安装app 25 | * 26 | * @param context 27 | * @param packageName 28 | * @return 29 | */ 30 | public static boolean isAppInstalled(Context context, String packageName) { 31 | try { 32 | if (TextUtils.isEmpty(packageName)) 33 | return false; 34 | return context.getPackageManager().getPackageInfo(packageName, PackageManager.GET_ACTIVITIES) != null; 35 | } catch (NameNotFoundException localNameNotFoundException) { 36 | return false; 37 | } 38 | } 39 | 40 | /** 41 | * 打开app 42 | * 43 | * @param packageName 44 | * @param context 45 | */ 46 | public static void openApp(Context context, String packageName) { 47 | PackageManager packageManager = context.getPackageManager(); 48 | Intent intent = packageManager.getLaunchIntentForPackage(packageName); 49 | if (intent != null) 50 | context.startActivity(intent); 51 | } 52 | 53 | /** 54 | * 某个app的版本号,未安装时返回null 55 | */ 56 | public static final String getVersionName(Context context, String packageName) { 57 | try { 58 | PackageInfo pi = context.getPackageManager().getPackageInfo(packageName, 0); 59 | if (pi != null) { 60 | return pi.versionName; 61 | } else { 62 | return null; 63 | } 64 | } catch (NameNotFoundException e) { 65 | return null; 66 | } 67 | } 68 | 69 | public static final int getVersionCode(Context context) { 70 | if (versionCode == 0) { 71 | loadVersionInfo(context); 72 | } 73 | 74 | return versionCode; 75 | } 76 | 77 | /** 78 | * 易信版本号 79 | */ 80 | public static final String getVersionName(Context context) { 81 | if (TextUtils.isEmpty(versionName)) { 82 | loadVersionInfo(context); 83 | } 84 | 85 | return versionName; 86 | } 87 | 88 | private static final void loadVersionInfo(Context context) { 89 | try { 90 | PackageInfo pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); 91 | if (pi != null) { 92 | versionCode = pi.versionCode; 93 | versionName = pi.versionName; 94 | } 95 | } catch (NameNotFoundException e) { 96 | e.printStackTrace(); 97 | } 98 | } 99 | 100 | /** 101 | * 安装apk文件 102 | */ 103 | public static void installApk(String filepath) { 104 | IMApplication.getContext().startActivity(getInstallApkIntent(filepath)); 105 | } 106 | 107 | /** 108 | * 安装apk文件 109 | */ 110 | public static Intent getInstallApkIntent(String filepath) { 111 | Intent intent = new Intent(Intent.ACTION_VIEW); 112 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 113 | File file = new File(filepath); 114 | intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); 115 | return intent; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/session/extension/BankTransferSystemAttachment.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.session.extension; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.facebook.react.bridge.Arguments; 5 | import com.facebook.react.bridge.WritableMap; 6 | 7 | /** 8 | * Created by dowin on 2017/6/8. 9 | */ 10 | 11 | public class BankTransferSystemAttachment extends CustomAttachment { 12 | 13 | final static String KEY_FROM = "from"; 14 | final static String KEY_OPE = "ope"; 15 | final static String KEY_TO = "to"; 16 | final static String KEY_TYPE = "type"; 17 | final static String KEY_BODY = "body"; 18 | 19 | 20 | final static String KEY_BODY_MSG_TYPE = "msgtype"; 21 | final static String KEY_BODY_AMOUNT = "amount"; 22 | final static String KEY_BODY_COMMENTS = "comments"; 23 | final static String KEY_BODY_SERIAL_NO = "serialNo"; 24 | 25 | private String from; 26 | private String ope; 27 | private String to; 28 | private String attachType; 29 | 30 | private String msgtype; 31 | private String amount; 32 | private String comments; 33 | private String serialNo; 34 | 35 | public BankTransferSystemAttachment() { 36 | super(CustomAttachmentType.BankTransferSystem); 37 | } 38 | 39 | @Override 40 | protected void parseData(JSONObject data) { 41 | from = data.getString(KEY_FROM); 42 | ope = data.getString(KEY_OPE); 43 | to = data.getString(KEY_TO); 44 | attachType = data.getString(KEY_TYPE); 45 | 46 | JSONObject body = data.getJSONObject(KEY_BODY); 47 | msgtype = body.getString(KEY_BODY_MSG_TYPE); 48 | amount = body.getString(KEY_BODY_AMOUNT); 49 | comments = body.getString(KEY_BODY_COMMENTS); 50 | serialNo = body.getString(KEY_BODY_SERIAL_NO); 51 | } 52 | 53 | @Override 54 | protected JSONObject packData() { 55 | JSONObject object = new JSONObject(); 56 | object.put(KEY_FROM,from); 57 | object.put(KEY_OPE,ope); 58 | object.put(KEY_TO,to); 59 | object.put(KEY_TYPE,type); 60 | 61 | JSONObject body = new JSONObject(); 62 | body.put(KEY_BODY_MSG_TYPE,msgtype); 63 | body.put(KEY_BODY_AMOUNT,amount); 64 | body.put(KEY_BODY_COMMENTS,comments); 65 | body.put(KEY_BODY_SERIAL_NO,serialNo); 66 | object.put(KEY_BODY,body); 67 | 68 | return object; 69 | } 70 | 71 | public void setParams(String from, String ope, String to, String type, String msgtype, String amount, String comments, String serialNo) { 72 | this.from = from; 73 | this.ope = ope; 74 | this.to = to; 75 | this.attachType = type; 76 | this.msgtype = msgtype; 77 | this.amount = amount; 78 | this.comments = comments; 79 | this.serialNo = serialNo; 80 | } 81 | @Override 82 | public WritableMap toReactNative(){ 83 | WritableMap writableMap = Arguments.createMap(); 84 | writableMap.putString("from",from); 85 | writableMap.putString("ope",ope); 86 | writableMap.putString("to",to); 87 | writableMap.putString("type",attachType); 88 | 89 | writableMap.putString("msgtype",msgtype); 90 | writableMap.putString("amount",amount); 91 | writableMap.putString("comments",comments); 92 | writableMap.putString("serialNo",serialNo); 93 | return writableMap; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /android/src/main/java/com/netease/im/uikit/contact/core/provider/MsgDataProvider.java: -------------------------------------------------------------------------------- 1 | package com.netease.im.uikit.contact.core.provider; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.netease.im.uikit.common.util.log.LogUtil; 6 | import com.netease.im.uikit.contact.core.item.AbsContactItem; 7 | import com.netease.im.uikit.contact.core.item.MsgItem; 8 | import com.netease.im.uikit.contact.core.query.TextQuery; 9 | import com.netease.im.uikit.contact.core.util.ContactHelper; 10 | import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum; 11 | import com.netease.nimlib.sdk.search.model.MsgIndexRecord; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | //import com.netease.nimlib.sdk.lucene.LuceneService; 17 | 18 | /** 19 | * 消息全文检索数据提供者 20 | */ 21 | public final class MsgDataProvider { 22 | 23 | private static final String TAG = "MsgDataProvider"; 24 | 25 | public static final List provide(TextQuery query) { 26 | if (TextUtils.isEmpty(query.text) || TextUtils.isEmpty(query.text.trim())) { 27 | return new ArrayList<>(0); 28 | } 29 | 30 | // fetch result 31 | List sources; 32 | boolean querySession; 33 | if (query.extra != null) { 34 | SessionTypeEnum sessionType = (SessionTypeEnum) query.extra[0]; 35 | String sessionId = (String) query.extra[1]; 36 | MsgIndexRecord anchor = null; 37 | if (query.extra.length >= 3) { 38 | anchor = (MsgIndexRecord) query.extra[2]; 39 | } 40 | sources = searchSession(query.text, sessionType, sessionId, anchor); 41 | querySession = true; 42 | } else { 43 | sources = searchAllSession(query.text); 44 | querySession = false; 45 | } 46 | 47 | // build AbsContactItem 48 | if (sources == null) { 49 | return new ArrayList<>(0); 50 | } 51 | 52 | List items = new ArrayList<>(sources.size()); 53 | for (MsgIndexRecord r : sources) { 54 | items.add(new MsgItem(ContactHelper.makeContactFromMsgIndexRecord(r), r, querySession)); 55 | } 56 | 57 | return items; 58 | } 59 | 60 | private static List searchSession(String query, SessionTypeEnum sessionType, String sessionId, MsgIndexRecord anchor) { 61 | long startTime = System.currentTimeMillis(); 62 | 63 | List result; 64 | if (anchor != null) { 65 | result = null;// NIMClient.getService(LuceneService.class).searchSessionNextPageBlock(query, sessionType, sessionId, anchor, 50); 66 | } else { 67 | result = null;//NIMClient.getService(LuceneService.class).searchSessionBlock(query, sessionType, sessionId); 68 | } 69 | 70 | log(true, result, System.currentTimeMillis() - startTime); 71 | 72 | return result; 73 | } 74 | 75 | private static List searchAllSession(String query) { 76 | long startTime = System.currentTimeMillis(); 77 | List result = null;//NIMClient.getService(LuceneService.class).searchAllSessionBlock(query, -1); 78 | log(false, result, System.currentTimeMillis() - startTime); 79 | 80 | return result; 81 | } 82 | 83 | private static void log(boolean searchSession, List result, long cost) { 84 | LogUtil.d(TAG, (searchSession ? "search session" : "search all session") + ", result size=" + (result == null ? 0 : result.size()) + ", cost=" + cost); 85 | } 86 | } -------------------------------------------------------------------------------- /ios/RNNeteaseIm/RNNeteaseIm/Util/NIMKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NIMKit.m 3 | // NIMKit 4 | // 5 | // Created by amao on 8/14/15. 6 | // Copyright (c) 2015 NetEase. All rights reserved. 7 | // 8 | 9 | #import "NIMKit.h" 10 | #import "NIMKitInfoFetchOption.h" 11 | #import "NIMKitDataProviderImpl.h" 12 | #import "NIMKitNotificationFirer.h" 13 | extern NSString *const NIMKitUserInfoHasUpdatedNotification; 14 | extern NSString *const NIMKitTeamInfoHasUpdatedNotification; 15 | 16 | 17 | @interface NIMKit() 18 | @property (nonatomic,strong) NIMKitNotificationFirer *firer; 19 | @end 20 | 21 | 22 | @implementation NIMKit 23 | - (instancetype)init 24 | { 25 | if (self = [super init]) { 26 | _provider = [[NIMKitDataProviderImpl alloc] init]; 27 | } 28 | return self; 29 | } 30 | - (void)notifyTeamInfoChanged:(NSArray *)teamIds{ 31 | if (teamIds.count) { 32 | for (NSString *teamId in teamIds) { 33 | [self notifyTeam:teamId]; 34 | } 35 | }else{ 36 | [self notifyTeam:nil]; 37 | } 38 | } 39 | - (void)notifyTeam:(NSString *)teamId 40 | { 41 | NIMKitFirerInfo *info = [[NIMKitFirerInfo alloc] init]; 42 | if (teamId.length) { 43 | NIMSession *session = [NIMSession session:teamId type:NIMSessionTypeTeam]; 44 | info.session = session; 45 | } 46 | info.notificationName = NIMKitTeamInfoHasUpdatedNotification; 47 | [self.firer addFireInfo:info]; 48 | } 49 | - (void)notifyTeamMemebersChanged:(NSArray *)teamIds 50 | { 51 | if (teamIds.count) { 52 | for (NSString *teamId in teamIds) { 53 | [self notifyTeamMemebers:teamId]; 54 | } 55 | }else{ 56 | [self notifyTeamMemebers:nil]; 57 | } 58 | } 59 | 60 | - (void)notifyTeamMemebers:(NSString *)teamId 61 | { 62 | NIMKitFirerInfo *info = [[NIMKitFirerInfo alloc] init]; 63 | if (teamId.length) { 64 | NIMSession *session = [NIMSession session:teamId type:NIMSessionTypeTeam]; 65 | info.session = session; 66 | } 67 | extern NSString *NIMKitTeamMembersHasUpdatedNotification; 68 | info.notificationName = NIMKitTeamMembersHasUpdatedNotification; 69 | [self.firer addFireInfo:info]; 70 | } 71 | 72 | + (instancetype)sharedKit 73 | { 74 | static NIMKit *instance = nil; 75 | static dispatch_once_t onceToken; 76 | dispatch_once(&onceToken, ^{ 77 | instance = [[NIMKit alloc] init]; 78 | }); 79 | return instance; 80 | } 81 | - (void)notfiyUserInfoChanged:(NSArray *)userIds{ 82 | if (!userIds.count) { 83 | return; 84 | } 85 | for (NSString *userId in userIds) { 86 | NIMSession *session = [NIMSession session:userId type:NIMSessionTypeP2P]; 87 | NIMKitFirerInfo *info = [[NIMKitFirerInfo alloc] init]; 88 | info.session = session; 89 | info.notificationName = NIMKitUserInfoHasUpdatedNotification; 90 | [self.firer addFireInfo:info]; 91 | } 92 | } 93 | 94 | - (NIMKitInfo *)infoByUser:(NSString *)userId option:(NIMKitInfoFetchOption *)option 95 | { 96 | NIMKitInfo *info = nil; 97 | if (self.provider && [self.provider respondsToSelector:@selector(infoByUser:option:)]) { 98 | info = [self.provider infoByUser:userId option:option]; 99 | } 100 | return info; 101 | } 102 | 103 | - (NIMKitInfo *)infoByTeam:(NSString *)teamId option:(NIMKitInfoFetchOption *)option 104 | { 105 | NIMKitInfo *info = nil; 106 | if (self.provider && [self.provider respondsToSelector:@selector(infoByTeam:option:)]) { 107 | info = [self.provider infoByTeam:teamId option:option]; 108 | } 109 | return info; 110 | 111 | } 112 | 113 | @end 114 | 115 | 116 | 117 | --------------------------------------------------------------------------------