├── .github
└── workflows
│ └── publish.yml
├── .gitignore
├── .idea
├── libraries
│ └── Flutter_for_Android.xml
├── modules.xml
└── runConfigurations
│ └── example_lib_main_dart.xml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── android
├── .gitignore
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── jiguang
│ └── jmessageflutter
│ ├── ChatRoomHandler.java
│ ├── JMessageUtils.java
│ ├── JmessageFlutterPlugin.java
│ ├── JsonUtils.java
│ └── PushService.java
├── documents
└── APIs.md
├── example
├── .flutter-plugins-dependencies
├── .gitignore
├── .metadata
├── README.md
├── android
│ ├── app
│ │ ├── build.gradle
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── jiguang
│ │ │ │ └── jmessageflutterexample
│ │ │ │ └── MainActivity.java
│ │ │ └── res
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ └── gradle-wrapper.properties
│ ├── key.properties
│ └── settings.gradle
├── assets
│ ├── 2.0x
│ │ └── nav_close.png
│ ├── 3.0x
│ │ └── nav_close.png
│ └── nav_close.png
├── ios
│ ├── Flutter
│ │ ├── .last_build_id
│ │ ├── AppFrameworkInfo.plist
│ │ ├── Debug.xcconfig
│ │ ├── Flutter.podspec
│ │ ├── Release.xcconfig
│ │ └── flutter_export_environment.sh
│ ├── Podfile
│ ├── Runner.xcodeproj
│ │ ├── project.pbxproj
│ │ ├── project.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── Runner.xcscheme
│ ├── Runner.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── Runner
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ └── LaunchImage.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ └── README.md
│ │ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ │ ├── Info.plist
│ │ ├── Runner.entitlements
│ │ └── main.m
├── lib
│ ├── conversation_manage_view.dart
│ ├── group_manage_view.dart
│ └── main.dart
└── pubspec.yaml
├── ios
├── .gitignore
├── Assets
│ └── .gitkeep
├── Classes
│ ├── JMessageHelper.h
│ ├── JMessageHelper.m
│ ├── JmessageFlutterPlugin.h
│ └── JmessageFlutterPlugin.m
└── jmessage_flutter.podspec
├── jmessage_flutter.iml
├── jmessage_flutter_android.iml
├── lib
└── jmessage_flutter.dart
└── pubspec.yaml
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: publish
2 |
3 | on:
4 | push:
5 | tags:
6 | - v*
7 |
8 | jobs:
9 | build:
10 |
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v2
15 |
16 | - name: Publish Dart/Flutter package
17 | uses: sakebook/actions-flutter-pub-publisher@v1.3.1
18 | with:
19 | credential: ${{ secrets.JMESSAGE_CREDENTIAL_JSON }}
20 | flutter_package: false
21 | skip_test: true
22 | dry_run: false
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .dart_tool/
3 |
4 | .packages
5 | .pub/
6 | pubspec.lock
7 |
8 | build/
9 | .idea/
10 | flutter.jar
11 | example/.flutter-plugins-dependencies
12 | jmessage_flutter_android.iml
13 | example/ios/Flutter/flutter_export_environment.sh
--------------------------------------------------------------------------------
/.idea/libraries/Flutter_for_Android.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/example_lib_main_dart.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 2.2.1
2 | +修复 addSyncRoamingMessageListener 没回调问题
3 | ## 2.2.0
4 | +修复 enterChatRoom getChatRoomConversation 方法
5 | ## 2.1.9
6 | +补充 nicknames 字段
7 | ## 2.1.8
8 | +新增 nicknames 字段
9 | ## 2.1.7
10 | +修复:修复未实现方法getMessageHaveReadStatus
11 | ## 2.1.6
12 | +修复:修复判空异常
13 | ## 2.1.4
14 | +新增:新增发送视频接口 sendVideoMessage
15 | ## 2.1.2
16 | +升级:升级 android jcore 2.8.2
17 | ## 2.1.0
18 | +适配:适配 null safety
19 | ## 2.0.5
20 | + 升级:Android jcore sdk 升级到 2.7.8
21 | ## 2.0.3
22 | + 升级:Android msg sdk 升级到 2.1.4
23 | ## 2.0.1
24 | + 适配Flutter 2.0
25 | ## 0.6.5
26 | + 修复Android端下载消息原图失败问题
27 | ## 0.6.4
28 | + 聊天室消息添加监听、移除监听方法修改
29 | + 修复聊天室消息移除监听失败问题
30 | ## 0.6.3
31 | + 新增:消息已读回执监听方法
32 | ## 0.6.2
33 | + 内部安全策略优化
34 | ## 0.6.1
35 | + 修复:获取用户信息时黑名单字段错误问题
36 | ## 0.6.0
37 | + 修复:获取消息失败问题
38 | + 注意:接口参数请严格按照接口说明传值
39 | ## 0.5.0
40 | + 修复:黑名单接口异常
41 | ## 0.4.0
42 | + 1、新增:消息已读未读回执功能
43 | + 2、修复:删除会话 Android 报错问题
44 | + 3、下载消息多媒体文件时,统一传入本地消息 id
45 | + 4、统一iOS、Android 的用户登录状态变更事件枚举
46 | ## 0.3.0
47 | ### fix:
48 | + 1、新增:发送消息透传接口,支持会话间、设备间透传命令;
49 | + 2、修复经纬度数据错误问题;
50 | ## 0.2.0
51 | fix:
52 | 1、新增:消息撤回类型消息;
53 | 2、修复:Group 和 GroupInfo 属性 maxMemberCount 改为 int 类型;
54 | 3、修复:获取我的群组 crash
55 |
56 | ## 0.1.0
57 | fix:
58 | 1、修复:createMessage 方法中经纬度为 int 的错误;
59 | 2、修复:在 Android 下 GroupInfo 的属性 maxMemberCount 为 int 的错误;
60 | 3、修复:消息撤回事件回调中 message 为 null 的错误;
61 | 4、修复:监听不到入群申请通知事件的 bug ;
62 | ## 0.0.20
63 | fix:
64 | 1、修改: sendLocationMessage 方法经纬度参数改为 double 类型
65 | ## 0.0.19
66 | fix:
67 | 1、修复:Android 接收消息时 flutter 没回调问题
68 | 2、适配 Android 最新 SDK
69 | 3、修改代码书写错误
70 | ## 0.0.18
71 | fix:
72 | 1、添加 iOS 端 apns 注册方法
73 | 2、修复:Android 端 serverMessageId 超过 int 存储范围问题;
74 | 3、更新到最新版本 JMessage SDK
75 | ## 0.0.17
76 | fix:
77 | 1、修复IOS发送文件消息获取不到文件问题
78 | ## 0.0.16
79 | fix:
80 | 1、修复发送自定义消息解析失败的bug
81 | 2、修复安卓端exitConversation没有回调的问题。
82 | 3、升级安卓端JMessage sdk版本2.8.2
83 |
84 | ## 0.0.15
85 | fix:
86 | 1.修复getHistoryMessages 安卓和ios的消息排序不一致
87 | 2.修复updateMyInfo 的参数缺失问题。
88 | ## 0.0.14
89 | fix: contact event username is null bug
90 |
91 | ## 0.0.13
92 | feature: getHistoryMessages parameters add isDescend-option.
93 |
94 | ## 0.0.12
95 | feature: onLoginStateChanged add user_kicked event.
96 |
97 | ## 0.0.11
98 | fix: jmessage login api remove without avatar path error.
99 |
100 | ## 0.0.10
101 | fix: updateGroupInfo update desc error.
102 | new feature: add extras field in JMConversationInfo.
103 |
104 | ## 0.0.9
105 |
106 | fix: JMConversationInfo getHistoryMessages helper function
107 |
108 | ## 0.0.8
109 |
110 | fix: group.maxMemberCount type
111 |
112 | ## 0.0.7
113 |
114 | new feature: add message.state property
115 |
116 | ## 0.0.6
117 |
118 | fix: voice message error
119 | new feature: add createMessage and sendMessage api
120 |
121 | ## 0.0.5
122 |
123 | fix: login state changed not fire in android
124 |
125 | ## 0.0.4
126 |
127 | fix:isSend 返回 null 的情况。
128 |
129 | ## 0.0.3
130 |
131 | fix:android isSend 返回错误。
132 |
133 | ## 0.0.2
134 |
135 | fix:swift 工程集成报错。
136 |
137 | ## 0.0.1
138 |
139 | 第一个版本。
140 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 极光开发者
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | []()
2 | [](https://pub.flutter-io.cn/packages/jmessage_flutter)
3 |
4 | # jmessage_flutter
5 |
6 | ### 安装
7 |
8 | 在工程 pubspec.yaml 中加入 dependencies
9 |
10 | ```
11 | //github 集成
12 | dependencies:
13 | jmessage_flutter:
14 | git:
15 | url: git://github.com/jpush/jmessage-flutter-plugin.git
16 | ref: master
17 |
18 | //pub.dev 集成
19 | dependencies:
20 | jmessage_flutter: 2.2.1
21 | ```
22 |
23 |
24 | ### 配置
25 |
26 | 在 `/android/app/build.gradle` 中添加下列代码:
27 |
28 | ```gradle
29 | android {
30 | ......
31 | defaultConfig {
32 | applicationId "com.xxx.xxx" //JPush上注册的包名.
33 | ......
34 |
35 | ndk {
36 | //选择要添加的对应cpu类型的.so库。
37 | abiFilters 'armeabi', 'armeabi-v7a', 'armeabi-v8a'
38 | // 还可以添加 'x86', 'x86_64', 'mips', 'mips64'
39 | }
40 |
41 | manifestPlaceholders = [
42 | JPUSH_PKGNAME : applicationId,
43 | JPUSH_APPKEY : "你的appkey", //JPush上注册的包名对应的appkey.
44 | JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可.
45 | ]
46 | ......
47 | }
48 | ......
49 | }
50 | ```
51 |
52 |
53 |
54 | ### 使用
55 |
56 | ```dart
57 | import 'package:jmessage_flutter/jmessage_flutter.dart';
58 | ```
59 |
60 |
61 |
62 | ### APIs
63 |
64 | **注意** : 需要先调用 `JmessageFlutter().init` 来初始化插件,才能保证其它功能正常工作。
65 |
66 | [参考](/documents/APIs.md)
67 |
68 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | group 'com.jiguang.jmessageflutter'
2 | version '1.0-SNAPSHOT'
3 |
4 | buildscript {
5 | repositories {
6 | mavenCentral()
7 | google()
8 | jcenter()
9 | }
10 |
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:3.2.1'
13 | }
14 | }
15 |
16 | rootProject.allprojects {
17 | repositories {
18 | mavenCentral()
19 | google()
20 | jcenter()
21 | }
22 | }
23 |
24 | apply plugin: 'com.android.library'
25 |
26 | android {
27 | compileSdkVersion 28
28 |
29 | defaultConfig {
30 | minSdkVersion 17
31 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
32 |
33 | }
34 | lintOptions {
35 | disable 'InvalidPackage'
36 | }
37 | }
38 |
39 | dependencies {
40 | implementation 'cn.jiguang.sdk:jmessage:2.9.2'
41 | implementation 'cn.jiguang.sdk:jcore:2.8.2'
42 | }
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Apr 02 18:21:36 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'jmessage_flutter'
2 |
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/android/src/main/java/com/jiguang/jmessageflutter/ChatRoomHandler.java:
--------------------------------------------------------------------------------
1 | package com.jiguang.jmessageflutter;
2 |
3 | //import org.apache.cordova.CallbackContext;
4 | import org.json.JSONArray;
5 | import org.json.JSONException;
6 | import org.json.JSONObject;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.HashSet;
11 | import java.util.List;
12 | import java.util.Set;
13 |
14 | import cn.jpush.im.android.api.ChatRoomManager;
15 | import cn.jpush.im.android.api.JMessageClient;
16 | import cn.jpush.im.android.api.callback.RequestCallback;
17 | import cn.jpush.im.android.api.model.ChatRoomInfo;
18 | import cn.jpush.im.android.api.model.Conversation;
19 | import cn.jpush.im.api.BasicCallback;
20 |
21 | import static com.jiguang.jmessageflutter.JmessageFlutterPlugin.ERR_CODE_PARAMETER;
22 | import static com.jiguang.jmessageflutter.JmessageFlutterPlugin.ERR_MSG_PARAMETER;
23 | import static com.jiguang.jmessageflutter.JMessageUtils.handleResult;
24 | import static com.jiguang.jmessageflutter.JsonUtils.toJson;
25 |
26 | import io.flutter.plugin.common.MethodChannel.Result;
27 |
28 |
29 | /**
30 | * 处理聊天室相关 API。
31 | */
32 |
33 | class ChatRoomHandler {
34 |
35 | static void getChatRoomInfoListOfApp(JSONObject data, final Result callback) {
36 | int start, count;
37 | try {
38 |
39 | start = data.getInt("start");
40 | count = data.getInt("count");
41 | } catch (JSONException e) {
42 | e.printStackTrace();
43 | handleResult(ERR_CODE_PARAMETER, ERR_MSG_PARAMETER, callback);
44 | return;
45 | }
46 |
47 | ChatRoomManager.getChatRoomListByApp(start, count, new RequestCallback>() {
48 | @Override
49 | public void gotResult(int status, String desc, List chatRoomInfos) {
50 | if (status != 0) {
51 | handleResult(status, desc, callback);
52 | return;
53 | }
54 |
55 | ArrayList jsonArr = new ArrayList();
56 | for (ChatRoomInfo chatroomInfo : chatRoomInfos) {
57 | jsonArr.add(toJson(chatroomInfo));
58 | }
59 | callback.success(jsonArr);
60 | }
61 | });
62 | }
63 |
64 | static void getChatRoomInfoListOfUser(JSONObject data, final Result callback) {
65 | ChatRoomManager.getChatRoomListByUser(new RequestCallback>() {
66 | @Override
67 | public void gotResult(int status, String desc, List chatRoomInfoList) {
68 | if (status != 0) {
69 | handleResult(status, desc, callback);
70 | return;
71 | }
72 |
73 | ArrayList jsonArr = new ArrayList();
74 | for (ChatRoomInfo chatroomInfo : chatRoomInfoList) {
75 | jsonArr.add(toJson(chatroomInfo));
76 | }
77 | callback.success(jsonArr);
78 | }
79 | });
80 | }
81 |
82 | static void getChatRoomInfoListById(JSONObject data, final Result callback) {
83 | Set roomIds = new HashSet(); // JS 层为了和 iOS 统一,因此 roomId 类型为 String,在原生做转换。
84 |
85 | try {
86 |
87 | JSONArray roomIdArr = data.getJSONArray("roomIds");
88 |
89 | for (int i = 0; i < roomIdArr.length(); i++) {
90 | roomIds.add(Long.valueOf(roomIdArr.getString(i)));
91 | }
92 | } catch (JSONException e) {
93 | e.printStackTrace();
94 | handleResult(ERR_CODE_PARAMETER, ERR_MSG_PARAMETER, callback);
95 | return;
96 | }
97 |
98 | ChatRoomManager.getChatRoomInfos(roomIds, new RequestCallback>() {
99 | @Override
100 | public void gotResult(int status, String desc, List chatRoomInfos) {
101 | if (status != 0) {
102 | handleResult(status, desc, callback);
103 | return;
104 | }
105 |
106 | ArrayList jsonArr = new ArrayList();
107 | for (ChatRoomInfo chatroomInfo : chatRoomInfos) {
108 | jsonArr.add(toJson(chatroomInfo));
109 | }
110 | callback.success(jsonArr);
111 | }
112 | });
113 | }
114 |
115 | static void getChatRoomOwner(JSONObject data, final Result callback) {
116 | final long roomId;
117 |
118 | try {
119 | roomId = Long.parseLong(data.getString("roomId"));
120 | } catch (JSONException e) {
121 | e.printStackTrace();
122 | handleResult(ERR_CODE_PARAMETER, ERR_MSG_PARAMETER, callback);
123 | return;
124 | }
125 |
126 | Set roomIds = new HashSet();
127 | roomIds.add(roomId);
128 |
129 | ChatRoomManager.getChatRoomInfos(roomIds, new RequestCallback>() {
130 | @Override
131 | public void gotResult(int status, String desc, List chatRoomInfoList) {
132 | if (status != 0) {
133 | handleResult(status, desc, callback);
134 | return;
135 | }
136 |
137 | HashMap chatroomInfoJson = toJson(chatRoomInfoList.get(0));
138 | callback.success(chatroomInfoJson);
139 | }
140 | });
141 | }
142 |
143 | static void enterChatRoom(JSONObject data, final Result callback) {
144 | final long roomId;
145 |
146 | try {
147 | roomId = Long.parseLong(data.getString("roomId"));
148 | } catch (JSONException e) {
149 | e.printStackTrace();
150 | handleResult(ERR_CODE_PARAMETER, ERR_MSG_PARAMETER, callback);
151 | return;
152 | }
153 |
154 | ChatRoomManager.enterChatRoom(roomId, new RequestCallback() {
155 | @Override
156 | public void gotResult(int status, String desc, Conversation conversation) {
157 | if (status != 0) {
158 | handleResult(status, desc, callback);
159 | return;
160 | }
161 |
162 | // HashMap result = new HashMap();
163 | // result.put("roomId", roomId);
164 | // result.put("conversation", toJson(conversation));
165 | callback.success(toJson(conversation));
166 | }
167 | });
168 | }
169 |
170 | static void exitChatRoom(JSONObject data, final Result callback) {
171 | final long roomId;
172 |
173 | try {
174 | roomId = Long.parseLong(data.getString("roomId"));
175 | } catch (JSONException e) {
176 | e.printStackTrace();
177 | handleResult(ERR_CODE_PARAMETER, ERR_MSG_PARAMETER, callback);
178 | return;
179 | }
180 |
181 | ChatRoomManager.leaveChatRoom(roomId, new BasicCallback() {
182 | @Override
183 | public void gotResult(int status, String desc) {
184 | if (status == 0) { // success
185 | callback.success(null);
186 | } else {
187 | handleResult(status, desc, callback);
188 | }
189 | }
190 | });
191 | }
192 |
193 | static void getChatRoomConversationList(JSONObject data, final Result callback) {
194 | List conversations = JMessageClient.getChatRoomConversationList();
195 |
196 | ArrayList result = new ArrayList();
197 |
198 | if (conversations == null) {
199 | callback.success(result);
200 | return;
201 | }
202 |
203 | for (Conversation con : conversations) {
204 | result.add(toJson(con));
205 | }
206 | callback.success(result);
207 | }
208 |
209 | }
210 |
--------------------------------------------------------------------------------
/android/src/main/java/com/jiguang/jmessageflutter/JMessageUtils.java:
--------------------------------------------------------------------------------
1 | package com.jiguang.jmessageflutter;
2 |
3 | import android.graphics.Bitmap;
4 | import android.os.Environment;
5 | import android.util.Log;
6 |
7 | //import org.apache.cordova.CallbackContext;
8 | import org.json.JSONArray;
9 | import org.json.JSONException;
10 | import org.json.JSONObject;
11 |
12 |
13 | import java.io.BufferedOutputStream;
14 | import java.io.File;
15 | import java.io.FileNotFoundException;
16 | import java.io.FileOutputStream;
17 | import java.io.IOException;
18 | import java.net.URI;
19 | import java.util.HashMap;
20 | import java.util.List;
21 |
22 | import cn.jpush.im.android.api.JMessageClient;
23 | import cn.jpush.im.android.api.callback.GetUserInfoCallback;
24 | import cn.jpush.im.android.api.content.MessageContent;
25 | import cn.jpush.im.android.api.model.Conversation;
26 | import cn.jpush.im.android.api.model.Message;
27 | import cn.jpush.im.android.api.options.MessageSendingOptions;
28 | import cn.jpush.im.api.BasicCallback;
29 |
30 | import static com.jiguang.jmessageflutter.JsonUtils.JsonToMessage;
31 | import io.flutter.plugin.common.MethodChannel.Result;
32 |
33 | class JMessageUtils {
34 |
35 | private static JSONObject getErrorObject(int code, String description) throws JSONException {
36 | JSONObject error = new JSONObject();
37 | error.put("code", code);
38 | error.put("description", description);
39 | return error;
40 | }
41 |
42 | static void handleResult(int status, String desc, Result callback) {
43 | if (status == 0) {
44 | callback.success(null);
45 | } else {
46 | callback.error(Integer.toString(status), desc, "");
47 | }
48 | }
49 |
50 | static void handleResult(HashMap returnObject, int status, String desc, Result callback) {
51 | if (status == 0) {
52 | callback.success(returnObject);
53 | } else {
54 | callback.error(Integer.toString(status), desc, "");
55 | }
56 | }
57 |
58 | static void handleResult(List returnObject, int status, String desc, Result callback) {
59 | if (status == 0) {
60 | callback.success(returnObject);
61 | } else {
62 | callback.error(Integer.toString(status), desc, "");
63 | }
64 | }
65 |
66 | static MessageSendingOptions toMessageSendingOptions(JSONObject json) throws JSONException {
67 | MessageSendingOptions messageSendingOptions = new MessageSendingOptions();
68 |
69 | if (json.has("isShowNotification") && !json.isNull("isShowNotification")) {
70 | messageSendingOptions.setShowNotification(json.getBoolean("isShowNotification"));
71 | }
72 |
73 | if (json.has("isRetainOffline") && !json.isNull("isRetainOffline")) {
74 | messageSendingOptions.setRetainOffline(json.getBoolean("isRetainOffline"));
75 | }
76 |
77 | if (json.has("isCustomNotificationEnabled") && !json.isNull("isCustomNotificationEnabled")) {
78 | messageSendingOptions.setCustomNotificationEnabled(json.getBoolean("isCustomNotificationEnabled"));
79 | }
80 |
81 | if (json.has("notificationTitle") && !json.isNull("notificationTitle")) {
82 | messageSendingOptions.setNotificationTitle(json.getString("notificationTitle"));
83 | }
84 |
85 | if (json.has("notificationText") && !json.isNull("notificationText")) {
86 | messageSendingOptions.setNotificationText(json.getString("notificationText"));
87 | }
88 | if (json.has("needReadReceipt") && !json.isNull("needReadReceipt")) {
89 | messageSendingOptions.setNeedReadReceipt(json.getBoolean("needReadReceipt"));
90 | }
91 |
92 | return messageSendingOptions;
93 | }
94 |
95 | static void getUserInfo(JSONObject params, GetUserInfoCallback callback) throws JSONException {
96 | String username, appKey;
97 |
98 | username = params.getString("username");
99 | appKey = params.has("appKey") ? params.getString("appKey") : "";
100 |
101 | JMessageClient.getUserInfo(username, appKey, callback);
102 | }
103 |
104 | /**
105 | * 创建会话对象,如果本地以及存在,则直接返回而不会重新创建。
106 | */
107 | static Conversation createConversation(JSONObject params) throws JSONException {
108 | String type = params.getString("type");
109 | Conversation conversation = null;
110 |
111 | if (type.equals("single")) {
112 | String username = params.getString("username");
113 | String appKey = params.has("appKey") ? params.getString("appKey") : "";
114 | conversation = Conversation.createSingleConversation(username, appKey);
115 |
116 | } else if (type.equals("group")) {
117 | String groupId = params.getString("groupId");
118 | conversation = Conversation.createGroupConversation(Long.parseLong(groupId));
119 |
120 | } else if (type.equals("chatRoom")) {
121 | long roomId = Long.parseLong(params.getString("roomId"));
122 | conversation = Conversation.createChatRoomConversation(roomId);
123 | }
124 |
125 | return conversation;
126 | }
127 |
128 | static Conversation getConversation(JSONObject params) throws JSONException {
129 | String type = params.getString("type");
130 | Conversation conversation = null;
131 |
132 | if (type.equals("group")) {
133 | String groupId = params.getString("groupId");
134 | conversation = JMessageClient.getGroupConversation(Long.parseLong(groupId));
135 |
136 | } else if (type.equals("chatRoom")) {
137 | long roomId = Long.parseLong(params.getString("roomId"));
138 | conversation = JMessageClient.getChatRoomConversation(roomId);
139 | } else {//if (type.equals("single")) || "user"
140 | String username = params.getString("username");
141 | String appKey = params.has("appKey") ? params.getString("appKey") : "";
142 | conversation = JMessageClient.getSingleConversation(username, appKey);
143 | }
144 |
145 | return conversation;
146 | }
147 |
148 | static Message getMessage(JSONObject params) throws JSONException {
149 | if (params.has("messageId")) { // 代表 JS 层为显式传入所需的参数。
150 | Conversation conversation = getConversation(params);
151 | if (conversation == null) {
152 | return null;
153 | }
154 |
155 | Message msg;
156 | String messageId = params.getString("messageId");
157 |
158 | Long b = Long.parseLong(messageId);
159 | if (b > Integer.MAX_VALUE) {
160 | msg = conversation.getMessage(Long.parseLong(messageId));
161 | }else {
162 | msg = conversation.getMessage(Integer.parseInt(messageId));
163 | }
164 |
165 | return msg;
166 | } else if (params.has("id")) { // 代表 JS 层传入的是 Message 对象。
167 | return JsonToMessage(params);
168 | }
169 |
170 | return null;
171 | }
172 |
173 | static void sendMessage(Conversation conversation, MessageContent content, MessageSendingOptions options,
174 | final Result callback) {
175 | final Message msg = conversation.createSendMessage(content);
176 | msg.setOnSendCompleteCallback(new BasicCallback() {
177 | @Override
178 | public void gotResult(int status, String desc) {
179 | if (status == 0) {
180 | HashMap json = JsonUtils.toJson(msg);
181 | handleResult(json, status, desc, callback);
182 | } else {
183 | handleResult(status, desc, callback);
184 | }
185 | }
186 | });
187 |
188 | if (options == null) {
189 | JMessageClient.sendMessage(msg);
190 | } else {
191 | JMessageClient.sendMessage(msg, options);
192 | }
193 | }
194 |
195 | static String storeImage(Bitmap bitmap, String filename, String pkgName) {
196 | File avatarFile = new File(getAvatarPath(pkgName));
197 | if (!avatarFile.exists()) {
198 | avatarFile.mkdirs();
199 | }
200 |
201 | String filePath = getAvatarPath(pkgName) + filename + ".png";
202 | try {
203 | FileOutputStream fos = new FileOutputStream(filePath);
204 | BufferedOutputStream bos = new BufferedOutputStream(fos);
205 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);
206 | bos.flush();
207 | bos.close();
208 | return filePath;
209 | } catch (FileNotFoundException e) {
210 | e.printStackTrace();
211 | return "";
212 | } catch (IOException e) {
213 | e.printStackTrace();
214 | return "";
215 | }
216 | }
217 |
218 | static String getFilePath(String pkgName) {
219 | return Environment.getExternalStorageDirectory() + "/" + pkgName;
220 | }
221 |
222 | static String getAvatarPath(String pkgName) {
223 | return getFilePath(pkgName) + "/images/avatar/";
224 | }
225 |
226 | static String getFileExtension(String path) {
227 | return path.substring(path.lastIndexOf("."));
228 | }
229 |
230 | /**
231 | * 根据绝对路径或 URI 获得本地图片。
232 | *
233 | * @param path 文件路径或者 URI。
234 | * @return 文件对象。
235 | */
236 | static File getFile(String path) throws FileNotFoundException {
237 | File file = new File(path); // if it is a absolute path
238 |
239 | if (!file.isFile()) {
240 | URI uri = URI.create(path); // if it is a uri.
241 | file = new File(uri);
242 | }
243 |
244 | if (!file.exists() || !file.isFile()) {
245 | throw new FileNotFoundException();
246 | }
247 |
248 | return file;
249 | }
250 |
251 | }
252 |
--------------------------------------------------------------------------------
/android/src/main/java/com/jiguang/jmessageflutter/JsonUtils.java:
--------------------------------------------------------------------------------
1 | package com.jiguang.jmessageflutter;
2 |
3 | import android.text.TextUtils;
4 | import android.util.Log;
5 |
6 | import org.json.JSONArray;
7 | import org.json.JSONException;
8 | import org.json.JSONObject;
9 |
10 | import java.text.DateFormat;
11 | import java.text.SimpleDateFormat;
12 | import java.util.ArrayList;
13 | import java.util.Date;
14 | import java.util.HashMap;
15 | import java.util.Iterator;
16 | import java.util.List;
17 | import java.util.Map;
18 |
19 | import cn.jmessage.support.google.gson.JsonElement;
20 | import cn.jmessage.support.google.gson.JsonObject;
21 | import cn.jmessage.support.google.gson.JsonParser;
22 | import cn.jpush.im.android.api.JMessageClient;
23 | import cn.jpush.im.android.api.content.CustomContent;
24 | import cn.jpush.im.android.api.content.EventNotificationContent;
25 | import cn.jpush.im.android.api.content.FileContent;
26 | import cn.jpush.im.android.api.content.ImageContent;
27 | import cn.jpush.im.android.api.content.LocationContent;
28 | import cn.jpush.im.android.api.content.MessageContent;
29 | import cn.jpush.im.android.api.content.TextContent;
30 | import cn.jpush.im.android.api.content.VideoContent;
31 | import cn.jpush.im.android.api.content.VoiceContent;
32 | import cn.jpush.im.android.api.enums.ConversationType;
33 | import cn.jpush.im.android.api.enums.MessageDirect;
34 | import cn.jpush.im.android.api.model.ChatRoomInfo;
35 | import cn.jpush.im.android.api.model.Conversation;
36 | import cn.jpush.im.android.api.model.GroupBasicInfo;
37 | import cn.jpush.im.android.api.model.GroupInfo;
38 | import cn.jpush.im.android.api.model.GroupMemberInfo;
39 | import cn.jpush.im.android.api.model.Message;
40 | import cn.jpush.im.android.api.model.UserInfo;
41 |
42 | class JsonUtils {
43 |
44 | static Map fromJson(JSONObject jsonObject) {
45 | Map map = new HashMap();
46 | try {
47 | Iterator keysItr = jsonObject.keys();
48 | while (keysItr.hasNext()) {
49 | String key = keysItr.next();
50 | String value = jsonObject.getString(key);
51 | map.put(key, value);
52 | }
53 | } catch (JSONException e) {
54 |
55 | }
56 |
57 | return map;
58 | }
59 |
60 | static HashMap toJson(Map map) {
61 | HashMap result = new HashMap();
62 | Iterator iterator = map.keySet().iterator();
63 |
64 | // JSONObject jsonObject = new JSONObject();
65 | while (iterator.hasNext()) {
66 | String key = iterator.next();
67 |
68 | result.put(key, map.get(key));
69 | }
70 | return result;
71 | }
72 |
73 | static HashMap toJson(final UserInfo userInfo) {
74 | if (userInfo == null) {
75 | return null;
76 | }
77 |
78 | final HashMap result = new HashMap();
79 |
80 | result.put("type", "user");
81 |
82 | if (null != userInfo.getGender()) {
83 | switch (userInfo.getGender()) {
84 | case male:
85 | result.put("gender", "male");
86 | break;
87 | case female:
88 | result.put("gender", "female");
89 | break;
90 | case unknown:
91 | result.put("gender", "unknown");
92 |
93 | }
94 | } else {
95 | result.put("gender", "unknown");
96 | }
97 |
98 | result.put("username", userInfo.getUserName() != null ? userInfo.getUserName() : "");
99 | result.put("appKey", userInfo.getAppKey());
100 | result.put("nickname", userInfo.getNickname() != null ? userInfo.getNickname() : "");
101 | if (userInfo.getAvatarFile() != null) {
102 | result.put("avatarThumbPath", userInfo.getAvatarFile().getAbsolutePath());
103 | } else {
104 | result.put("avatarThumbPath", "");
105 | }
106 |
107 | if (userInfo.getBirthday() != 0) {
108 | DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
109 | try {
110 | String tsStr = sdf.format(userInfo.getBirthday());
111 | result.put("birthday", tsStr);
112 | } catch (Exception e) {
113 | e.printStackTrace();
114 | }
115 | } else {
116 | long time = userInfo.getBirthday();
117 | result.put("birthday", "");
118 | }
119 |
120 | result.put("region", userInfo.getRegion() != null ? userInfo.getRegion() : "");
121 | result.put("signature", userInfo.getSignature() != null ? userInfo.getSignature() : "");
122 | result.put("address", userInfo.getAddress() != null ? userInfo.getAddress() : "");
123 | result.put("noteName", userInfo.getNotename() != null ? userInfo.getNotename() : "");
124 | result.put("noteText", userInfo.getNoteText() != null ? userInfo.getNoteText() : "");
125 | result.put("isNoDisturb", userInfo.getNoDisturb() == 1);
126 | result.put("isInBlackList", userInfo.getBlacklist() == 1);
127 | result.put("isFriend", userInfo.isFriend());
128 | Map extras = userInfo.getExtras();
129 | result.put("extras", extras != null ? extras : new HashMap());
130 | return result;
131 | }
132 |
133 | static HashMap toJson(GroupInfo groupInfo) {
134 |
135 | final HashMap result = new HashMap();
136 |
137 | result.put("type", "group");
138 | result.put("id", String.valueOf(groupInfo.getGroupID()));
139 |
140 | switch (groupInfo.getGroupType()) {
141 | case public_group: {
142 | }
143 | result.put("groupType", "public");
144 | break;
145 | default:
146 | result.put("groupType", "private");
147 | break;
148 | }
149 |
150 | result.put("name", groupInfo.getGroupName());
151 | result.put("desc", groupInfo.getGroupDescription());
152 | result.put("level", groupInfo.getGroupLevel());
153 | result.put("owner", groupInfo.getGroupOwner() != null ? groupInfo.getGroupOwner() : "");
154 | GroupMemberInfo memberInfo = groupInfo.getOwnerMemberInfo();
155 | //
156 | // if (memberInfo != null) {
157 | //
158 | // result.put("owner", memberInfo.getUserInfo().getUserName());
159 | // }
160 |
161 | // result.put("ownerAppKey", groupInfo.getOwnerMemberInfo().getUserInfo().getAppKey());
162 | result.put("ownerAppKey", groupInfo.getOwnerAppkey() != null ? groupInfo.getOwnerAppkey() : "");
163 | result.put("maxMemberCount", groupInfo.getMaxMemberCount());
164 | result.put("isNoDisturb", groupInfo.getNoDisturb() == 1);
165 | result.put("isBlocked", groupInfo.isGroupBlocked() == 1);
166 |
167 | return result;
168 | }
169 |
170 | static HashMap toJson(GroupMemberInfo groupMemberInfo) {
171 |
172 | final HashMap result = new HashMap();
173 | result.put("user", toJson(groupMemberInfo.getUserInfo()));
174 | result.put("groupNickname", groupMemberInfo.getNickName());
175 |
176 | if (groupMemberInfo.getType() == GroupMemberInfo.Type.group_owner) {
177 | result.put("memberType", "owner");
178 | } else if (groupMemberInfo.getType() == GroupMemberInfo.Type.group_keeper) {
179 | result.put("memberType", "admin");
180 | } else {
181 | result.put("memberType", "ordinary");
182 | }
183 | result.put("joinGroupTime", groupMemberInfo.getJoinGroupTime());
184 |
185 | return result;
186 | }
187 |
188 | static HashMap toJson(GroupBasicInfo groupInfo) {
189 | final HashMap result = new HashMap();
190 | result.put("type", "group");
191 | result.put("id", String.valueOf(groupInfo.getGroupID()));
192 | result.put("name", groupInfo.getGroupName());
193 | result.put("desc", groupInfo.getGroupDescription());
194 | result.put("level", groupInfo.getGroupLevel());
195 | result.put("avatarThumbPath", groupInfo.getAvatar());
196 | result.put("maxMemberCount", groupInfo.getMaxMemberCount());//String.valueOf(groupInfo.getMaxMemberCount())
197 | switch (groupInfo.getGroupType()) {
198 | case public_group: {
199 | }
200 | result.put("groupType", "public");
201 | break;
202 | default:
203 | result.put("groupType", "private");
204 | break;
205 | }
206 |
207 | return result;
208 | }
209 |
210 | static HashMap toJson(Message msg) {
211 |
212 | final HashMap result = new HashMap();
213 |
214 | result.put("id", String.valueOf(msg.getId())); // 本地数据库 id
215 | result.put("serverMessageId", String.valueOf(msg.getServerMessageId())); // 服务器端 id
216 | result.put("from", toJson(msg.getFromUser())); // 消息发送者
217 |
218 | boolean isSend = msg.getDirect().equals(MessageDirect.send);
219 | result.put("isSend", isSend); // 消息是否是由当前用户发出
220 |
221 | HashMap targetJson = null;
222 | switch (msg.getTargetType()) {
223 | case single:
224 | if (isSend) { // 消息发送
225 | targetJson = toJson((UserInfo) msg.getTargetInfo());
226 | } else { // 消息接收
227 | targetJson = toJson(JMessageClient.getMyInfo());
228 | }
229 | break;
230 | case group:
231 | targetJson = toJson((GroupInfo) msg.getTargetInfo());
232 | break;
233 | case chatroom:
234 | targetJson = toJson((ChatRoomInfo) msg.getTargetInfo());
235 | break;
236 | default:
237 | }
238 | result.put("target", targetJson);
239 | switch (msg.getStatus()) {
240 | case created:
241 | result.put("state", "draft");
242 | break;
243 | case send_going:
244 | result.put("state", "sending");
245 | break;
246 | case send_fail:
247 | result.put("state", "send_failed");
248 | break;
249 | case send_draft:
250 | result.put("state", "draft");
251 | break;
252 | case receive_fail:
253 | result.put("state", "download_failed");
254 | break;
255 | case send_success:
256 | result.put("state", "send_succeed");
257 | break;
258 | case receive_going:
259 | result.put("state", "receiving");
260 | break;
261 | case receive_success:
262 | result.put("state", "received");
263 | break;
264 | }
265 | MessageContent content = msg.getContent();
266 | if (content.getStringExtras() != null) {
267 | result.put("extras", content.getStringExtras());
268 | } else {
269 | result.put("extras", new HashMap());
270 | }
271 |
272 | result.put("createTime", msg.getCreateTime());
273 |
274 | switch (msg.getContentType()) {
275 | case text:
276 | result.put("type", "text");
277 | result.put("text", ((TextContent) content).getText());
278 | break;
279 | case image:
280 | result.put("type", "image");
281 | result.put("thumbPath", ((ImageContent) content).getLocalThumbnailPath());
282 | break;
283 | case voice:
284 | result.put("type", "voice");
285 | result.put("path", ((VoiceContent) content).getLocalPath());
286 | result.put("duration", ((VoiceContent) content).getDuration() + 0.0);
287 | break;
288 | case file:
289 | result.put("type", "file");
290 | result.put("fileName", ((FileContent) content).getFileName());
291 | break;
292 | case custom:
293 | result.put("type", "custom");
294 | Map customObject = ((CustomContent) content).getAllStringValues();
295 | result.put("customObject", toJson(customObject));
296 | break;
297 | case location:
298 | result.put("type", "location");
299 | result.put("latitude", ((LocationContent) content).getLatitude().doubleValue());
300 | result.put("longitude", ((LocationContent) content).getLongitude().doubleValue());
301 | result.put("address", ((LocationContent) content).getAddress());
302 | result.put("scale", ((LocationContent) content).getScale().intValue());
303 | break;
304 | case video:
305 | result.put("type", "video");
306 | result.put("duration", ((VideoContent) content).getDuration());
307 | result.put("videoPath", ((VideoContent) content).getVideoLocalPath());
308 | result.put("thumbImagePath", ((VideoContent) content).getThumbLocalPath());
309 | result.put("videoFileName", ((VideoContent) content).getFileName());
310 | result.put("thumbFormat", ((VideoContent) content).getThumbFormat());
311 | break;
312 | case eventNotification:
313 | result.put("type", "event");
314 | List usernameList = ((EventNotificationContent) content).getUserNames();
315 | if (usernameList != null) {
316 | result.put("usernames", toJson(usernameList));
317 | }
318 | Log.d("flutter plugin", "usernameList:" + usernameList);
319 |
320 | List displayNameList = ((EventNotificationContent) content).getUserDisplayNames();
321 | if (displayNameList != null) {
322 | result.put("nicknames", toJson(displayNameList));
323 | }
324 | Log.d("flutter plugin", "displayNameList:" + displayNameList);
325 |
326 | switch (((EventNotificationContent) content).getEventNotificationType()) {
327 | case group_member_added:
328 | // 群成员加群事件
329 | result.put("eventType", "group_member_added");
330 | break;
331 | case group_member_removed:
332 | // 群成员被踢事件
333 | result.put("eventType", "group_member_removed");
334 | break;
335 | case group_member_exit:
336 | // 群成员退群事件
337 | result.put("eventType", "group_member_exit");
338 | break;
339 | case group_info_updated:
340 | result.put("eventType", "group_info_updated");
341 | break;
342 | case group_member_keep_silence:
343 | result.put("eventType", "group_member_keep_silence");
344 | break;
345 | case group_member_keep_silence_cancel:
346 | result.put("eventType", "group_member_keep_silence_cancel");
347 | break;
348 | case group_keeper_added:
349 | result.put("eventType", "group_keeper_added");
350 | break;
351 | case group_keeper_removed:
352 | result.put("eventType", "group_keeper_removed");
353 | break;
354 | case group_dissolved:
355 | // 解散群组事件
356 | result.put("eventType", "group_dissolved");
357 | break;
358 | case group_owner_changed:
359 | // 移交群组事件
360 | result.put("eventType", "group_owner_changed");
361 | break;
362 | case group_type_changed:
363 | // 移交群组事件
364 | result.put("eventType", "group_type_changed");
365 | break;
366 | default:
367 | }
368 | default:
369 | }
370 | return result;
371 | }
372 |
373 | static Message JsonToMessage(JSONObject json) {
374 | Conversation conversation = null;
375 | int msgId = 0;
376 |
377 | try {
378 | msgId = Integer.parseInt(json.getString("id"));
379 | boolean isSend = json.getBoolean("isSend");
380 |
381 | JSONObject target = json.getJSONObject("target");
382 |
383 | if (target.getString("type").equals("user")) {
384 | String username;
385 | String appKey;
386 |
387 | if (isSend) { // 消息由当前用户发送,则聊天对象为消息接收方。
388 | username = target.getString("username");
389 | appKey = target.has("appKey") ? target.getString("appKey") : null;
390 |
391 | } else { // 当前用户为消息接收方,则聊天对象为消息发送方。
392 | JSONObject opposite = json.getJSONObject("from");
393 | username = opposite.getString("username");
394 | appKey = opposite.has("appKey") ? opposite.getString("appKey") : null;
395 | }
396 |
397 | conversation = JMessageClient.getSingleConversation(username, appKey);
398 |
399 | } else if (target.getString("type").equals("group")) {
400 | long groupId = Long.parseLong(target.getString("id"));
401 | conversation = JMessageClient.getGroupConversation(groupId);
402 |
403 | } else if (target.getString("type").equals("chatRoom")) {
404 | long roomId = Long.parseLong(target.getString("roomId"));
405 | conversation = JMessageClient.getChatRoomConversation(roomId);
406 | }
407 | } catch (JSONException e) {
408 | e.printStackTrace();
409 | }
410 |
411 | return conversation != null ? conversation.getMessage(msgId) : null;
412 | }
413 |
414 | static HashMap toJson(Conversation conversation) {
415 |
416 | final HashMap json = new HashMap();
417 | json.put("title", conversation.getTitle() != null ? conversation.getTitle() : "");
418 | json.put("unreadCount", conversation.getUnReadMsgCnt());
419 |
420 | if (conversation.getLatestMessage() != null) {
421 | json.put("latestMessage", toJson(conversation.getLatestMessage()));
422 | }
423 |
424 | if (conversation.getType() == ConversationType.single) {
425 | UserInfo targetInfo = (UserInfo) conversation.getTargetInfo();
426 | json.put("conversationType", "single");
427 | json.put("target", toJson(targetInfo));
428 |
429 | } else if (conversation.getType() == ConversationType.group) {
430 | GroupInfo targetInfo = (GroupInfo) conversation.getTargetInfo();
431 | json.put("conversationType", "group");
432 | json.put("target", toJson(targetInfo));
433 | } else if (conversation.getType() == ConversationType.chatroom) {
434 | ChatRoomInfo chatRoom = (ChatRoomInfo) conversation.getTargetInfo();
435 | json.put("target", toJson(chatRoom));
436 | json.put("conversationType", "chatRoom");
437 | }
438 |
439 | if (!TextUtils.isEmpty(conversation.getExtra())) {
440 | HashMap extrasMap = new HashMap();
441 | String extras = conversation.getExtra();
442 | JsonParser parser = new JsonParser();
443 | JsonObject jsonObject = parser.parse(extras).getAsJsonObject();
444 | for (Map.Entry entry : jsonObject.entrySet()) {
445 | extrasMap.put(entry.getKey(), entry.getValue().toString());
446 | }
447 | json.put("extras", extrasMap);
448 | } else {
449 | json.put("extras", new HashMap());
450 | }
451 |
452 | Log.d("flutter plugin", "native the conversation:" + json.toString());
453 |
454 | return json;
455 | }
456 |
457 | static List toJson(List list) {
458 |
459 | List jsonArray = new ArrayList();
460 |
461 | if (list == null) {
462 | return jsonArray;
463 | }
464 |
465 | for (Object object : list) {
466 |
467 | if (object instanceof UserInfo) {
468 | jsonArray.add(toJson((UserInfo) object));
469 | } else if (object instanceof GroupInfo) {
470 | jsonArray.add(toJson((GroupInfo) object));
471 | } else if (object instanceof GroupBasicInfo) {
472 | jsonArray.add(toJson((GroupBasicInfo) object));
473 | } else if (object instanceof Message) {
474 | jsonArray.add(toJson((Message) object));
475 | } else if (object instanceof GroupMemberInfo) {
476 | jsonArray.add(toJson((GroupMemberInfo) object));
477 | } else {
478 | jsonArray.add(object);
479 | }
480 | }
481 |
482 | return jsonArray;
483 | }
484 |
485 | static HashMap toJson(String eventName, JSONObject value) {
486 | final HashMap result = new HashMap();
487 | result.put("eventName", eventName);
488 | result.put("value", value);
489 | return result;
490 | }
491 |
492 | static HashMap toJson(String eventName, JSONArray value) {
493 | final HashMap result = new HashMap();
494 | result.put("eventName", eventName);
495 | result.put("value", value);
496 | return result;
497 | }
498 |
499 | static HashMap toJson(ChatRoomInfo chatRoomInfo) {
500 |
501 | final HashMap json = new HashMap();
502 | json.put("type", "chatRoom");
503 | json.put("roomId", String.valueOf(chatRoomInfo.getRoomID())); // 配合 iOS,将 long 转成 String。
504 | json.put("name", chatRoomInfo.getName() != null ? chatRoomInfo.getName() : "");
505 | json.put("appKey", chatRoomInfo.getAppkey());
506 | json.put("description", chatRoomInfo.getDescription() != null ? chatRoomInfo.getDescription() : "");
507 | json.put("createTime", chatRoomInfo.getCreateTime()); // 创建日期,单位秒。
508 | json.put("maxMemberCount", chatRoomInfo.getMaxMemberCount()); // 最大成员数。
509 | json.put("memberCount", chatRoomInfo.getTotalMemberCount()); // 当前成员数。
510 | return json;
511 | }
512 | }
513 |
--------------------------------------------------------------------------------
/android/src/main/java/com/jiguang/jmessageflutter/PushService.java:
--------------------------------------------------------------------------------
1 | package com.jiguang.jmessageflutter;
2 |
3 | import cn.jpush.android.service.JCommonService;
4 |
5 | public class PushService extends JCommonService {
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/documents/APIs.md:
--------------------------------------------------------------------------------
1 | # API
2 |
3 | #### Usage
4 | ```dart
5 | import 'package:jmessage_flutter/jmessage_flutter.dart';
6 |
7 | JmessageFlutter JMessage = JmessageFlutter();
8 | ```
9 |
10 | - [初始化](#初始化)
11 | - [init](#init)
12 | - [setDebugMode](#setdebugmode)
13 | - [setBadge](#setbadge)
14 | - [applyPushAuthority](#applyPushAuthority)
15 | - [用户登录、注册及属性维护](#用户登录注册及属性维护)
16 | - [userRegister](#userregister)
17 | - [login](#login)
18 | - [logout](#logout)
19 | - [getMyInfo](#getmyinfo)
20 | - [getUserInfo](#getuserinfo)
21 | - [updateMyPassword](#updatemypassword)
22 | - [updateMyAvatar](#updatemyavatar)
23 | - [updateMyInfo](#updatemyinfo)
24 | - [downloadThumbUserAvatar](#downloadthumbuseravatar)
25 | - [downloadOriginalUserAvatar](#downloadoriginaluseravatar)
26 | - [群组](#群组)
27 | - [createGroup](#creategroup)
28 | - [addGroupAdmins](#addgroupadmins)
29 | - [removeGroupAdmins](#removegroupadmins)
30 | - [changeGroupType](#changegrouptype)
31 | - [getPublicGroupInfos](#getpublicgroupinfos)
32 | - [applyJoinGroup](#applyjoingroup)
33 | - [processApplyJoinGroup](#processapplyjoingroup)
34 | - [dissolveGroup](#dissolvegroup)
35 | - [getGroupIds](#getgroupids)
36 | - [getGroupInfo](#getgroupinfo)
37 | - [getGroupMembers](#getgroupmembers)
38 | - [updateGroupInfo](#updategroupinfo)
39 | - [addGroupMembers](#addgroupmembers)
40 | - [removeGroupMembers](#removegroupmembers)
41 | - [聊天](#聊天)
42 | - [createMessage](#createmessage)
43 | - [sendMessage](#sendmessage)
44 | - [sendTextMessage](#sendtextmessage)
45 | - [sendImageMessage](#sendimagemessage)
46 | - [sendVoiceMessage](#sendvoicemessage)
47 | - [sendCustomMessage](#sendcustommessage)
48 | - [sendLocationMessage](#sendlocationmessage)
49 | - [sendFileMessage](#sendfilemessage)
50 | - [retractMessage](#retractmessage)
51 | - [getHistoryMessages](#gethistorymessages)
52 | - [downloadOriginalImage](#downloadoriginalimage)
53 | - [downloadThumbImage](#downloadthumbimage)
54 | - [downloadVoiceFile](#downloadvoicefile)
55 | - [downloadFile](#downloadfile)
56 | - [会话](#会话)
57 | - [createConversation](#createconversation)
58 | - [deleteConversation](#deleteconversation)
59 | - [enterConversation](#enterconversation)
60 | - [exitConversation](#exitconversation)
61 | - [getConversation](#getconversation)
62 | - [getConversations](#getconversations)
63 | - [getAllUnreadCount](#getallunreadcount)
64 | - [resetUnreadMessageCount](#resetunreadmessagecount)
65 | - [聊天室](#聊天室)
66 | - [getChatRoomListByApp](#getchatroomlistbyapp)
67 | - [getChatRoomListByUser](#getchatroomlistbyuser)
68 | - [getChatRoomInfos](#getchatroominfos)
69 | - [getChatRoomOwner](#getchatroomowner)
70 | - [enterChatRoom](#enterchatroom)
71 | - [leaveChatRoom](#leavechatroom)
72 | - [getChatRoomConversationList](#getchatroomconversationlist)
73 | - [好友](#好友)
74 | - [sendInvitationRequest](#sendinvitationrequest)
75 | - [acceptInvitation](#acceptInvitation)
76 | - [declineInvitation](#declineinvitation)
77 | - [getFriends](#getfriends)
78 | - [removeFromFriendList](#removefromfriendlist)
79 | - [updateFriendNoteName](#updatefriendnotename)
80 | - [updateFriendNoteText](#updatefriendnotetext)
81 | - [事件监听]()
82 | - [消息事件](#addreceivemessagelistener)
83 | - [addReceiveMessageListener](#addreceivemessagelistener)
84 | - [removeReceiveMessageListener](#addreceivemessagelistener)
85 | - [addReceiveChatRoomMsgListener](#addreceivechatroommsglistener)
86 | - [removeReceiveChatRoomMsgListener](#removereceivechatroommsglistener)
87 | - [离线消息](#addsyncofflinemessagelistener)
88 | - [addSyncOfflineMessageListener](#addsyncofflinemessagelistener)
89 | - [removeSyncOfflineMessageListener](#addsyncofflinemessagelistener)
90 | - [消息漫游](#addsyncroamingmessagelistener)
91 | - [addSyncRoamingMessageListener](#addsyncroamingmessagelistener)
92 | - [removeSyncRoamingMessageListener](#addsyncroamingmessagelistener)
93 | - [好友请求事件](#addcontactnotifylistener)
94 | - [addContactNotifyListener](#addcontactnotifylistener)
95 | - [removeContactNotifyListener](#addcontactnotifylistener)
96 | - [接收到消息撤回事件](#addmessageretractlistener)
97 | - [addMessageRetractListener](#addmessageretractlistener)
98 | - [removeMessageRetractListener](#addmessageretractlistener)
99 | - [登录状态变更](#addloginstatechangedlistener)
100 | - [addLoginStateChangedListener](#addloginstatechangedlistener)
101 | - [removeLoginStateChangedListener](#addloginstatechangedlistener)
102 | - [监听接收入群申请事件](#addreceiveapplyjoingroupapprovallistener)
103 | - [addReceiveApplyJoinGroupApprovalListener](#addreceiveapplyjoingroupapprovallistener)
104 | - [removeReceiveApplyJoinGroupApprovalListener](#removereceiveapplyjoingroupapprovallistener)
105 | - [监听管理员拒绝入群申请事件](#addreceivegroupadminrejectlistener)
106 | - [addReceiveGroupAdminRejectListener](#addreceivegroupadminrejectlistener)
107 | - [removeReceiveGroupAdminRejectListener](#removereceivegroupadminrejectlistener)
108 | - [监听管理员同意入群申请事件](#addreceivegroupadminapprovallistener)
109 | - [addReceiveGroupAdminApprovalListener](#addreceivegroupadminapprovallistener)
110 | - [removeReceiveGroupAdminApprovalListener](#removereceivegroupadminapprovallistener)
111 |
112 |
113 | - [点击消息通知事件(Android Only)](#addclickmessagenotificationlistener)
114 | - [addClickMessageNotificationListener](#addclickmessagenotificationlistener)
115 | - [removeClickMessageNotificationListener](#addclickmessagenotificationlistener)
116 |
117 | ## 初始化
118 |
119 | ### init
120 |
121 | **注意 Android 仍需在 build.gradle 中配置 appKey,具体可以[参考这个文件](https://github.com/jpush/jmessage-react-plugin/blob/dev/example/android/app/build.gradle)**
122 | 初始化插件。建议在应用起始页的构造函数中调用。
123 |
124 | #### 示例
125 |
126 | ```dart
127 | JMessage.init(isOpenMessageRoaming: true, appkey: kMockAppkey);
128 | ```
129 |
130 | #### 参数说明
131 |
132 | - appkey:极光官网注册的应用 AppKey。**Android 仍需配置 app 下 build.gradle 中的 AppKey。**
133 | - isOpenMessageRoaming:是否开启消息漫游,不传默认关闭。
134 | - isProduction:是否为生产模式。
135 | - channel:(选填)应用的渠道名称。
136 |
137 | ### setDebugMode
138 |
139 | 设置是否开启 debug 模式,开启后 SDK 将会输出更多日志信息,推荐在应用对外发布时关闭。
140 |
141 | #### 示例
142 |
143 | ```dart
144 | JMessage.setDebugMode( enable: true );
145 | ```
146 |
147 | #### 参数说明
148 |
149 | - enable:为 true 打开 Debug 模式,false 关闭 Debug 模式。
150 |
151 | ### setBadge
152 |
153 | 设置 badge 值,该操作会设置本地应用的 badge 值,同时设置极光服务器的 badge 值,收到消息 badge +1 会在极光服务器 badge 的基础上累加。
154 |
155 | #### 示例
156 |
157 | ```dart
158 | await JMessage.setBadge(badge: 5);
159 | ```
160 |
161 | ### applyPushAuthority
162 |
163 | iOS 端注册 apns 通知
164 |
165 | #### 示例
166 |
167 | ```dart
168 | jmessage.applyPushAuthority(
169 | new JMNotificationSettingsIOS(
170 | sound: true,
171 | alert: true,
172 | badge: true)
173 | );
174 | ```
175 |
176 | ## 用户登录、注册及属性维护
177 |
178 | ### userRegister
179 |
180 | 用户注册。
181 |
182 | #### 示例
183 |
184 | ```dart
185 | // 注册
186 | await JMessage.userRegister(
187 | username: "登录用户名",
188 | password: "登录密码"
189 | );
190 | ```
191 |
192 | #### 参数说明
193 |
194 | - username: 用户名。在应用中用于唯一标识用户,必须唯一。支持以字母或者数字开头,支持字母、数字、下划线、英文点(.)、减号、@。长度限制:Byte(4~128)。
195 | - password: 用户密码。不限制字符。长度限制:Byte(4~128)。
196 | - nickname: 昵称
197 |
198 | ### login
199 |
200 | ```dart
201 | // 登录
202 | await JMessage.login({
203 | username: "登录用户名",
204 | password: "登录密码"
205 | });
206 | ```
207 |
208 | #### 参数说明
209 |
210 | - username: 用户名。
211 | - password: 用户密码。
212 |
213 | ### logout
214 |
215 | 用户登出。
216 |
217 | #### 示例
218 |
219 | ```dart
220 | JMessage.logout();
221 | ```
222 |
223 | ### getMyInfo
224 |
225 | 获取当前登录用户信息。如果未登录返回的 user 对象里面的数据为空,例如 user.username 为空。可以用于判断用户登录状态
226 |
227 | #### 示例
228 |
229 | ```dart
230 | JMUserInfo user = await JMessage.getMyInfo();
231 | ```
232 |
233 | ### getUserInfo
234 |
235 | 获取用户信息。该接口可以获取不同 AppKey 下(即不同应用)的用户信息,如果 AppKey 为空,则默认为当前应用下。
236 |
237 | #### 示例
238 |
239 | ```dart
240 | JMUserInfo user = await JMessage.getUserInfo( username: 'username', appKey: 'your_app_key' );
241 | ```
242 |
243 | ### updateMyPassword
244 |
245 | 更新当前登录用户的密码。
246 |
247 | #### 示例
248 |
249 | ```dart
250 | await JMessage.updateMyPassword( oldPwd: 'old_password', newPwd: 'new_password' );
251 | ```
252 |
253 | ### updateMyAvatar
254 |
255 | 更新当前登录用户的头像。
256 |
257 | #### 示例
258 |
259 | ```dart
260 | await JMessage.updateMyAvatar( imgPath: 'img_local_path' );
261 | ```
262 |
263 | #### 参数说明
264 |
265 | - imgPath: 本地图片文件的绝对路径地址。注意在 Android 6.0 及以上版本系统中,需要动态请求 `WRITE_EXTERNAL_STORAGE` 权限。
266 | 两个系统中的图片路径分别类似于:
267 | - Android:`/storage/emulated/0/DCIM/Camera/IMG_20160526_130223.jpg`
268 | - iOS:`/var/mobile/Containers/Data/Application/7DC5CDFF-6581-4AD3-B165-B604EBAB1250/tmp/photo.jpg`
269 |
270 | ### updateMyInfo
271 |
272 | 更新当前登录用户信息。包括了:昵称(nickname)、生日(birthday)、个性签名(signature)、性别(gender)、地区(region)和具体地址(address)。
273 |
274 | #### 示例
275 |
276 | ```dart
277 | await JMessage.updateMyInfo( nickname: 'nickname' );
278 | ```
279 |
280 | #### 参数说明
281 |
282 | - nickname: 昵称。不支持字符 "\n" 和 "\r";长度限制:Byte (0~64)。
283 | - birthday: (Number)生日日期的毫秒数。
284 |
285 | ### downloadThumbUserAvatar
286 |
287 | 下载用户头像缩略图。
288 |
289 | #### 示例
290 |
291 | ```dart
292 | Map resJson = await JMessage.downloadThumbUserAvatar(
293 | username: 'theUserName',
294 | appKey: 'you appKey');
295 | resJson = {
296 | 'username': 'user name ',
297 | 'appKey': 'appKey',
298 | 'filePath': 'filePath'
299 | };
300 | ```
301 |
302 | #### 参数说明:
303 |
304 | - username (string): 用户名
305 | - appKey (string): 不传默认是本应用 appkey。
306 |
307 |
308 | - resJson (Map):
309 | - username (string): 用户名
310 | - appKey (string):
311 | - filePath (string): 下载后的图片路径(本地路径)
312 |
313 | ### downloadOriginalUserAvatar
314 |
315 | 下载用户头像原图。
316 |
317 | #### 示例
318 |
319 | ```dart
320 | const param = {
321 | username: 'theUserName',
322 | appKey: 'you appKey'
323 | }
324 | Map resJson = await JMessage.downloadOriginalUserAvatar(
325 | username: 'theUserName',
326 | appKey: 'you appKey'
327 | );
328 |
329 | resJson = {
330 | 'username': 'user name ',
331 | 'appKey': 'appKey',
332 | 'filePath': 'filePath'
333 | };
334 | ```
335 |
336 | #### 参数说明:
337 |
338 | - username (string): 用户名
339 | - appKey (string): 不传默认是本应用 appkey。
340 | - result (object):
341 | - username (string): 用户名
342 | - appKey (string):
343 | - filePath (string): 下载后的图片路径
344 |
345 | ## 群组
346 |
347 | ### createGroup
348 |
349 | 创建群组。
350 |
351 | #### 示例
352 |
353 | ```dart
354 | JMessage.createGroup( name: 'group_name', desc: 'group_desc' );
355 | ```
356 |
357 | #### 参数说明
358 |
359 | - name (string): 群组名。不支持 "\n" 和 "\r" 字符,长度限制为 0 ~ 64 Byte。
360 | - groupType (string): 指定创建群的类型,可以为 'private' 和 'public', 默认为 private。
361 | - desc (string): 群组描述。长度限制为 0 ~ 250 Byte。
362 |
363 | ### dissolveGroup
364 |
365 | 解散群
366 |
367 | #### 示例
368 |
369 | ```dart
370 | await JMessage.dissolveGroup( groupId: 'group_id' );
371 | ```
372 |
373 | #### 参数说明
374 |
375 | - groupId (string): 要解散的群组 id。
376 |
377 | ### getGroupIds
378 |
379 | 获取当前用户群组
380 |
381 | #### 示例
382 |
383 | ```dart
384 | List gids = await JMessage.getGroupIds();
385 | ```
386 |
387 | #### 参数说明
388 |
389 | 无
390 |
391 | ### getGroupInfo
392 |
393 | 根据群组id获取群组信息
394 |
395 | #### 示例
396 |
397 | ```dart
398 | JMessage.getGroupInfo( id: "1234567" )
399 | ```
400 |
401 | #### 参数说明
402 |
403 | - id(string): 指定群组
404 |
405 | ### getGroupMembers
406 |
407 | 获取群成员。
408 |
409 | #### 示例
410 |
411 | ```dart
412 | Listmembers = await JMessage.getGroupMembers( id: 'groupId');
413 | ```
414 |
415 | ### updateGroupInfo
416 |
417 | 更新群组信息。
418 |
419 | #### 示例
420 |
421 | ```dart
422 | await JMessage.updateGroupInfo( id: 'groupId' ,newName: 'group_name', newDesc: 'group_desc' );
423 | ```
424 |
425 | #### 参数说明
426 |
427 | - id (string): 指定操作的群 groupId
428 | - newName (string): 群组名。不支持 "\n" 和 "\r" 字符,长度限制为 0 ~ 64 Byte。
429 | - newDesc (string): 群组描述。长度限制为 0 ~ 250 Byte。
430 |
431 | ### addGroupMembers
432 |
433 | 批量添加群成员
434 |
435 | #### 示例
436 |
437 | ```dart
438 | await JMessage.addGroupAdmins(
439 | id: 'group_id',
440 | usernames: ['ex_username1', 'ex_username2'],
441 | appKey: 'appkey'
442 | );
443 | ```
444 |
445 | #### 参数说明
446 |
447 | - id: 指定操作的群 groupId
448 | - usernames: 被添加的的用户名数组。
449 | - appKey: 被添加用户所属应用的 AppKey。如果不填,默认为当前应用。
450 |
451 | ### removeGroupMembers
452 |
453 | 批量删除群成员
454 |
455 | #### 示例
456 |
457 | ```dart
458 | await JMessage.removeGroupMembers(
459 | id: 'group_id',
460 | usernames: ['ex_username1', 'ex_username2'],
461 | appKey: 'appkey' );
462 | ```
463 |
464 | #### 参数说明
465 |
466 | - id : 指定操作的群 groupId
467 | - username : 被添加的的用户名数组。
468 | - appKey: 被添加用户所属应用的 AppKey。如果不填,默认为当前应用。
469 |
470 | ### addGroupAdmins
471 |
472 | 批量添加管理员
473 |
474 | #### 示例
475 |
476 | ```dart
477 | await JMessage.addGroupAdmins(
478 | groupId: 'group_id',
479 | usernames: ['ex_username1', 'ex_username2']
480 | );
481 | ```
482 |
483 | #### 参数说明
484 |
485 | - groupId (string): 指定操作的群 groupId。
486 | - usernames : 被添加的的用户名数组。
487 |
488 | ### removeGroupAdmins
489 |
490 | 批量删除管理员
491 |
492 | #### 示例
493 |
494 | ```dart
495 | await JMessage.removeGroupAdmins(
496 | groupId: 'group_id',
497 | usernames: ['ex_username1', 'ex_username2']
498 | );
499 | ```
500 |
501 | #### 参数说明
502 |
503 | - groupId (string): 指定操作的群 groupId。
504 | - usernames : 被移除的的用户名数组。
505 |
506 | ### changeGroupType
507 |
508 | 修改群类型
509 |
510 | #### 示例
511 |
512 | ```dart
513 | await JMessage.changeGroupType(
514 | groupId: 'group_id',
515 | type: 'public'
516 | );
517 | ```
518 |
519 | #### 参数说明
520 |
521 | - groupId (string): 指定操作的群 groupId。
522 | - type : 公有群(类似 QQ 群进群需要管理员以上人员审批),私有群(类似微信群直接邀请就能进)。
523 |
524 | ### getPublicGroupInfos
525 |
526 | 分页获取指定 appKey 下的共有群
527 |
528 | #### 示例
529 |
530 | ```dart
531 | List groups = await JMessage.getPublicGroupInfos(
532 | appKey: 'my_appkey',
533 | start: 0,
534 | count: 20
535 | );
536 | ```
537 |
538 | #### 参数说明
539 |
540 | - appKey (string): 获取指定 appkey
541 | - start (int): 开始的位置
542 | - count (int): 获取的数量
543 |
544 | ### applyJoinGroup
545 |
546 | 申请入群(公开群)
547 |
548 | #### 示例
549 |
550 | ```dart
551 | await JMessage.applyJoinGroup(
552 | groupId: 'group_id',
553 | reason: 'Hello I from ...'
554 | );
555 | ```
556 |
557 | ####
558 |
559 | ### processApplyJoinGroup
560 |
561 | 批量处理入群(公开群)申请
562 |
563 | #### 示例
564 |
565 | ```dart
566 | await JMessage.processApplyJoinGroup(
567 | events: ['ex_event_id_1', 'ex_event_id_2'],
568 | reason: 'Hello I from ...'
569 | }
570 | );
571 | ```
572 |
573 | #### 参数说明
574 |
575 | - events (array): eventId 数组,当有用户申请入群的时候(或者被要求)会回调一个 event(通过 addReceiveApplyJoinGroupApprovalListener 监听),每个 event 会有个 id,用于审核入群操作。
576 | - reason (string): 入群理由。
577 |
578 | ## 聊天
579 |
580 | ### createMessage
581 |
582 | 创建消息,创建好消息后需要调用 [sendMessage](#sendMessage) 来发送消息。如果需要状态更新(发送中 -> 发送完成)可以使用这种方式,聊天室不支持该接口。
583 |
584 | ```dart
585 | var message = await jmessage.createMessage(
586 | type: JMMessageType.image,
587 | targetType: msg.from.targetType,
588 | path: msg.thumbPath,
589 | extras: {"key1": "value1"}
590 | );
591 | ```
592 |
593 | - type: 不同的消息类型需要不同的参数。
594 | - type = text 时 `text` 为必填。
595 | - type = image 时 `path` 为必填。
596 | - type = voice 时 `path` 为必填。
597 | - type = file 时 `path` 为必填。
598 | - type = location 时 `latitude` `longitude` 和 `scale` 为必填,`address` 选填。
599 | - type = custom 时 `customObject` 为必填。
600 |
601 | ### sendMessage
602 |
603 | 与 [createMessage](#createMessage) 配合使用,用于发送创建好的消息。
604 |
605 | ```dart
606 | var message = await jmessage.createMessage(
607 | type: JMMessageType.image,
608 | targetType: msg.from.targetType,
609 | path: msg.thumbPath,
610 | extras: {"key1": "value1"}
611 | );
612 |
613 | var sendedMessage = await jmessage.sendMessage(
614 | message: message,
615 | sendOption: JMMessageSendOptions.fromJson({
616 | 'isShowNotification': true,
617 | 'isRetainOffline': true,
618 | })
619 | );
620 | ```
621 |
622 |
623 |
624 | ### sendTextMessage
625 |
626 | 发送文本消息。
627 |
628 | #### 示例
629 |
630 | ```dart
631 | JMTextMessage msg = await JMessage.sendTextMessage(
632 | type: kMockUser,
633 | text: 'Text Message Test!',
634 | );
635 | ```
636 |
637 | #### 参数说明
638 |
639 | - type: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
640 | - text: 消息内容。
641 | - extras (Map): 自定义键值对,value 必须为字符串类型。
642 | - messageSendingOptions: 消息发送配置参数。支持的属性:
643 | - isShowNotification: 接收方是否针对此次消息发送展示通知栏通知。默认为 `true`。
644 | - isRetainOffline: 是否让后台在对方不在线时保存这条离线消息,等到对方上线后再推送给对方。默认为 `true`。
645 | - isCustomNotificationEnabled: 是否开启自定义接收方通知栏功能,设置为 `true` 后可设置下面的 `notificationTitle` 和 `notificationText`。默认未设置。
646 | - notificationTitle: 设置此条消息在接收方通知栏所展示通知的标题。
647 | - notificationText: 设置此条消息在接收方通知栏所展示通知的内容。
648 |
649 | ### sendImageMessage
650 |
651 | 发送图片消息,在收到消息时 SDK 默认会自动下载缩略图,如果要下载原图,需调用 `downloadOriginalImage` 方法。
652 |
653 | #### 示例
654 |
655 | ```dart
656 | JMessage.sendImageMessage(
657 | type: msg.from.targetType,
658 | path: msg.thumbPath,
659 | )
660 | ```
661 |
662 | #### 参数说明
663 |
664 | - type: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
665 | - path: 本地图片的绝对路径。格式分别类似为:
666 | - Android:`/storage/emulated/0/DCIM/Camera/IMG_20160526_130223.jpg`
667 | - iOS:`/var/mobile/Containers/Data/Application/7DC5CDFF-6581-4AD3-B165-B604EBAB1250/tmp/photo.jpg`
668 | - extras: 自定义键值对,value 必须为字符串类型。
669 | - sendingOptions: 消息发送配置参数。支持的属性:
670 | - isShowNotification: 接收方是否针对此次消息发送展示通知栏通知。默认为 `true`。
671 | - isRetainOffline: 是否让后台在对方不在线时保存这条离线消息,等到对方上线后再推送给对方。默认为 `true`。
672 | - isCustomNotificationEnabled: 是否开启自定义接收方通知栏功能,设置为 `true` 后可设置下面的 `notificationTitle` 和 `notificationText`。默认未设置。
673 | - notificationTitle: 设置此条消息在接收方通知栏所展示通知的标题。
674 | - notificationText: 设置此条消息在接收方通知栏所展示通知的内容。
675 |
676 | ### sendVoiceMessage
677 |
678 | 发送语音消息,在收到消息时 SDK 默认会自动下载语音文件,如果下载失败(即语音消息文件路径为空),可调用 `downloadVoiceFile` 手动下载。
679 |
680 | #### 示例
681 |
682 | ```dart
683 | jmessage.sendVoiceMessage(
684 | type: msg.from.targetType,
685 | path: msg.path,
686 | )
687 | ```
688 |
689 | #### 参数说明
690 |
691 | - type: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
692 | - path: 本地音频文件的绝对路径。
693 | - extras (Map): 自定义键值对,key 、value 必须为字符串类型。
694 | - sendingOptions: 消息发送配置参数。支持的属性:
695 | - isShowNotification: 接收方是否针对此次消息发送展示通知栏通知。默认为 `true`。
696 | - isRetainOffline: 是否让后台在对方不在线时保存这条离线消息,等到对方上线后再推送给对方。默认为 `true`。
697 | - isCustomNotificationEnabled: 是否开启自定义接收方通知栏功能,设置为 `true` 后可设置下面的 `notificationTitle` 和 `notificationText`。默认未设置。
698 | - notificationTitle: 设置此条消息在接收方通知栏所展示通知的标题。
699 | - notificationText: 设置此条消息在接收方通知栏所展示通知的内容。
700 |
701 | ### sendCustomMessage
702 |
703 | 发送自定义消息。
704 |
705 | #### 示例
706 |
707 | ```dart
708 | JMCustomMessage msg = await JMessage.sendCustomMessage(
709 | type: kMockGroup,
710 | customObject: {'customKey1': 'customValue1'}
711 | );
712 | ```
713 |
714 | #### 参数说明
715 |
716 | - type: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
717 | - customObject: 自定义键值对,`value` 必须为字符串类型。
718 | - sendingOptions: 消息发送配置参数。支持的属性:
719 | - isShowNotification: 接收方是否针对此次消息发送展示通知栏通知。默认为 `true`。
720 | - isRetainOffline: 是否让后台在对方不在线时保存这条离线消息,等到对方上线后再推送给对方。默认为 `true`。
721 | - isCustomNotificationEnabled: 是否开启自定义接收方通知栏功能,设置为 `true` 后可设置下面的 `notificationTitle` 和 `notificationText`。默认未设置。
722 | - notificationTitle: 设置此条消息在接收方通知栏所展示通知的标题。
723 | - notificationText: 设置此条消息在接收方通知栏所展示通知的内容。
724 |
725 | ### sendLocationMessage
726 |
727 | 发送地理位置消息,通常需要配合地图插件使用。
728 |
729 | #### 示例
730 |
731 | ```dart
732 | JMLocationMessage msg = await jmessage.sendVoiceMessage(
733 | type: kMockUser,
734 | longitude: kmockgitude,
735 | latitude: kmocklatitude
736 | )
737 | ```
738 |
739 | #### 参数说明
740 |
741 | - type: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
742 | - latitude: 纬度。
743 | - longitude: 经度。
744 | - scale: 地图缩放比例。
745 | - address: 详细地址。
746 | - extras: 自定义键值对,value 必须为字符串类型。
747 | - sendingOptions: 消息发送配置参数。支持的属性:
748 | - isShowNotification: 接收方是否针对此次消息发送展示通知栏通知。默认为 `true`。
749 | - isRetainOffline: 是否让后台在对方不在线时保存这条离线消息,等到对方上线后再推送给对方。默认为 `true`。
750 | - isCustomNotificationEnabled: 是否开启自定义接收方通知栏功能,设置为 `true` 后可设置下面的 `notificationTitle` 和 `notificationText`。默认未设置。
751 | - notificationTitle: 设置此条消息在接收方通知栏所展示通知的标题。
752 | - notificationText: 设置此条消息在接收方通知栏所展示通知的内容。
753 |
754 | ### sendFileMessage
755 |
756 | 发送文件消息。对方在收到文件消息时 SDK 不会自动下载,下载文件需手动调用 `downloadFile` 方法。
757 |
758 | #### 示例
759 |
760 | ```dart
761 | JMFileMessage msg = await jmessage.sendFileMessage(
762 | type: kMockUser,
763 | path: kMockFilePath,
764 | );
765 | ```
766 |
767 | #### 参数说明
768 |
769 | - type: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
770 | - path: 本地文件的绝对路径。
771 | - extras: 自定义键值对,value 必须为字符串类型。
772 | - sendingOptions: 消息发送配置参数。支持的属性:
773 | - isShowNotification: 接收方是否针对此次消息发送展示通知栏通知。默认为 `true`。
774 | - isRetainOffline: 是否让后台在对方不在线时保存这条离线消息,等到对方上线后再推送给对方。默认为 `true`。
775 | - isCustomNotificationEnabled: 是否开启自定义接收方通知栏功能,设置为 `true` 后可设置下面的 `notificationTitle` 和 `notificationText`。默认未设置。
776 | - notificationTitle: 设置此条消息在接收方通知栏所展示通知的标题。
777 | - notificationText: 设置此条消息在接收方通知栏所展示通知的内容。
778 |
779 | ### retractMessage
780 |
781 | 消息撤回。调用后被撤回方会收到一条 `retractMessage` 事件。并且双方的消息内容将变为不可见。
782 |
783 | #### 示例
784 |
785 | ```dart
786 | JMessage.retractMessage(
787 | type: kMockUser,
788 | messageId: 'target_msg_id'
789 | );
790 | ```
791 |
792 | #### 参数说明
793 |
794 | - type: 会话类型。可以为 (JMSingle | JMGroup)。
795 | - messageId: 要撤回的消息 id。
796 |
797 | ### getHistoryMessages
798 |
799 | 从最新的消息开始获取历史消息。
800 |
801 | #### 示例
802 |
803 | ```dart
804 | JMessage.getHistoryMessages(
805 | type: kMockUser,
806 | from: 0,
807 | limit: 10,
808 | isDescend: false
809 | );
810 | ```
811 |
812 | #### 参数说明
813 |
814 | - type: 会话类型。可以为 (JMSingle | JMGroup)。
815 |
816 | - from: 第一条消息对应的下标,起始为 0。
817 |
818 | - limit: 消息数。当 from = 0 并且 limit = -1 时,返回所有的历史消息。
819 |
820 | - isDescend: 是否降序(消息时间戳从大到小排序),默认为 false。
821 |
822 |
823 | ### downloadOriginalImage
824 |
825 | 下载图片消息原图。如果已经下载,会直接返回本地文件路径,不会重复下载。
826 |
827 | #### 示例
828 |
829 | ```dart
830 | JMessage.downloadOriginalImage(
831 | target: kMockUser,
832 | messageId: 'target_msg_id'
833 | });
834 | ```
835 |
836 | #### 参数说明
837 |
838 | - type: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
839 | - messageId: 图片消息 id。
840 |
841 | ### downloadThumbImage
842 |
843 | 下载图片消息缩略图。如果已经下载,会直接返回本地文件路径,不会重复下载。
844 |
845 | #### 示例
846 |
847 | ```dart
848 | Map resJson = await JMessage.downloadThumbImage(
849 | target: kMockUser,
850 | messageId: 'target_msg_id'
851 | });
852 |
853 | resJson == {
854 | 'messageId': resJson['messageId'],
855 | 'filePath': resJson['filePath']
856 | }
857 | ```
858 |
859 | #### 参数说明
860 |
861 | - type: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
862 | - username: 对方用户的用户名。当 `type` 为 'single' 时,`username` 为必填。
863 | - appKey: 对方用户所属应用的 AppKey。如果不填,默认为当前应用。
864 | - groupId: 对象群组 id。当 `type` 为 'group' 时,`groupId` 为必填。
865 | - messageId: 图片消息 id。
866 |
867 | ### downloadVoiceFile
868 |
869 | 下载语音文件。如果已经下载,会直接返回本地文件路径,不会重复下载。
870 |
871 | ### 示例
872 |
873 | ```dart
874 | Map resJson = await JMessage.downloadVoiceFile(
875 | type: kMockUser,
876 | messageId: 'target_msg_id'
877 | );
878 | resJson == {
879 | 'messageId': resJson['messageId'],
880 | 'filePath': resJson['filePath']
881 | }
882 | ```
883 |
884 | #### 参数说明
885 |
886 | - type: 会话类型。可以为 (JMSingle | JMGroup)。
887 | - messageId: 语音消息 id。
888 |
889 | ### downloadFile
890 |
891 | 下载文件。如果已经下载,会直接返回本地文件路径,不会重复下载。
892 |
893 | #### 示例
894 |
895 | ```dart
896 | Map resJson = await JMessage.downloadFile(
897 | type: kMockUser,
898 | messageId: 'target_msg_id'
899 | );
900 |
901 | resJson == {
902 | 'messageId': resJson['messageId'],
903 | 'filePath': resJson['filePath']
904 | }
905 | ```
906 |
907 | #### 参数说明
908 |
909 | - type: 会话类型。可以为 (JMSingle | JMGroup)。
910 | - messageId: 文件消息 id。
911 |
912 | ## 会话
913 |
914 | ### createConversation
915 |
916 | 创建会话。
917 |
918 | #### 示例
919 |
920 | ```dart
921 | JMConversationInfo conversation = await JMessage.createConversation(
922 | target:kMockUser
923 | );
924 | ```
925 |
926 | #### 参数说明
927 |
928 | - target: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
929 |
930 | ### deleteConversation
931 |
932 | 删除聊天会话,同时也会删除本地聊天记录。
933 |
934 | #### 示例
935 |
936 | ```dart
937 | await JMessage.deleteConversation(
938 | target:kMockUser
939 | );
940 | ```
941 |
942 | #### 参数说明
943 |
944 | - target: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
945 |
946 | ### enterConversation
947 |
948 | **(Android only)** 进入聊天会话。当调用后,该聊天会话的消息将不再显示通知。
949 |
950 | iOS 默认应用在前台时,就不会显示通知。
951 |
952 | #### 示例
953 |
954 | ```dart
955 | await JMessage.enterConversation(
956 | target:kMockUser
957 | );
958 | ```
959 |
960 | #### 参数说明
961 |
962 | - target: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
963 |
964 | ### exitConversation
965 |
966 | **(Android only)** 退出当前聊天会话。调用后,聊天会话之后的相关消息通知将会被触发。
967 |
968 | #### 示例
969 |
970 | ```dart
971 | await JMessage.exitConversation(
972 | target:kMockUser
973 | );
974 | ```
975 |
976 | ### getConversation
977 |
978 | 获取聊天会话对象。
979 |
980 | #### 示例
981 |
982 | ```dart
983 | JMConversationInfo conversation = await jmessage.getConversation(target: kMockUser);
984 | ```
985 |
986 | #### 参数说明
987 |
988 | - target: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
989 |
990 | ### getConversations
991 |
992 | 从本地数据库获取会话列表。默认按照会话的最后一条消息时间降序排列。
993 |
994 | #### 示例
995 |
996 | ```dart
997 | List conversations = await JMessage.getConversations();
998 | ```
999 |
1000 | ### getAllUnreadCount
1001 |
1002 | 当前用户所有会话的未读消息总数
1003 |
1004 | - ⚠️ 截止jmessage-sdk-2.6.1 返回的数量为会话列表的未读总数即包括了被移除的群组、好友的未读.
1005 |
1006 | #### 示例
1007 |
1008 | ```dart
1009 | num unreadCount = await JMessage.getAllUnreadCount();
1010 | ```
1011 |
1012 | ####
1013 |
1014 | ### resetUnreadMessageCount
1015 |
1016 | 重置会话的未读消息数。
1017 |
1018 | #### 示例
1019 |
1020 | ```dart
1021 | await JMessage.resetUnreadMessageCount(
1022 | target: kMockuser
1023 | );
1024 | ```
1025 |
1026 | #### 参数说明
1027 |
1028 | - target: 会话类型。可以为 (JMSingle | JMGroup | JMChatRoom)。
1029 |
1030 | ## 聊天室
1031 |
1032 | #### 注意: 聊天室相关 api 功能还不完整,建议先不要添加相关功能。
1033 |
1034 | ### enterChatRoom
1035 |
1036 | 进入聊天室,进入后才能收到聊天室信息及发言。
1037 |
1038 | #### 示例
1039 |
1040 | ```dart
1041 | await JMessage.enterChatRoom({ roomId: 'Example_RoomId_1'},
1042 | (conversation) => { // 进入聊天室,会自动创建并返回该聊天室会话信息。
1043 | // do something.
1044 |
1045 | }, (error) => {
1046 | var code = error.code
1047 | var desc = error.description
1048 | })
1049 | ```
1050 |
1051 | #### 参数说明
1052 |
1053 | - roomId:要进入的聊天室的 id。
1054 |
1055 | ### exitChatRoom
1056 |
1057 | 离开指定聊天室。
1058 |
1059 | #### 示例
1060 |
1061 | ```dart
1062 | await JMessage.leaveChatRoom({ roomId: 'Example_RoomId_1'},
1063 | () => {
1064 | // do something.
1065 |
1066 | }, (error) => {
1067 | var code = error.code
1068 | var desc = error.description
1069 | })
1070 | ```
1071 |
1072 | #### 参数说明
1073 |
1074 | - roomId:要离开的聊天室的 id。
1075 |
1076 | ### getChatRoomConversationList
1077 |
1078 | 从本地获取用户的聊天室会话列表,没有则返回为空的列表。
1079 |
1080 | #### 示例
1081 |
1082 | ```dart
1083 | List conversations = await JMessage.getChatRoomConversationList();
1084 | ```
1085 |
1086 |
1087 |
1088 | ## 好友
1089 |
1090 | JMessage 好友模块仅实现对用户好友关系的托管,以及相关好友请求的发送与接收。
1091 | 除此之外更多的功能,比如仅允许好友间聊天需要开发者自行实现。
1092 |
1093 | ### sendInvitationRequest
1094 |
1095 | 发送添加好友请求,调用后对方会收到 [好友事件](#addcontactnotifylistener) 事件。
1096 |
1097 | #### 示例
1098 |
1099 | ```dart
1100 | JMessage.sendInvitationRequest(
1101 | username: 'username',
1102 | appKey: 'appKey',
1103 | reason: '请求添加好友'
1104 | );
1105 | ```
1106 |
1107 | #### 参数说明
1108 |
1109 | - username: 对方用户的用户名。
1110 | - appKey: 对方用户所属应用的 AppKey,如果为空则默认为当前应用。
1111 | - reason: 申请理由。
1112 |
1113 | ### acceptInvitation
1114 |
1115 | 接受申请好友请求,调用后对方会收到 [好友事件](#addcontactnotifylistener) 事件。
1116 |
1117 | #### 示例
1118 |
1119 | ```dart
1120 | await JMessage.acceptInvitation(
1121 | username: 'username',
1122 | appKey: 'appKey'
1123 | );
1124 | ```
1125 |
1126 | #### 参数说明
1127 |
1128 | - username: 申请发送用户的用户名。
1129 | - appKey: 申请发送用户所在应用的 AppKey。
1130 |
1131 | ### declineInvitation
1132 |
1133 | 拒绝申请好友请求,调用成功后对方会收到 [好友事件](#addcontactnotifylistener) 事件。
1134 |
1135 | #### 示例
1136 |
1137 | ```dart
1138 | await JMessage.declineInvitation(
1139 | username: 'username',
1140 | appKey: 'appKey',
1141 | reason: '拒绝理由'
1142 | );
1143 | ```
1144 |
1145 | #### 参数说明
1146 |
1147 | - username: 申请发送用户的用户名。
1148 | - appKey: 申请发送用户所在应用的 AppKey。
1149 | - reason: 拒绝理由。长度要求为 0 ~ 250 Byte。
1150 |
1151 | ### getFriends
1152 |
1153 | 获取好友列表。
1154 |
1155 | #### 示例
1156 |
1157 | ```dart
1158 | List users = await JMessage.getFriends();
1159 | ```
1160 |
1161 | ### removeFromFriendList
1162 |
1163 | 删除好友,调用成功后对方会收到 [好友事件](#addcontactnotifylistener) 事件。
1164 |
1165 | #### 示例
1166 |
1167 | ```dart
1168 | await JMessage.removeFromFriendList(
1169 | username: 'username',
1170 | appKey: 'appKey'
1171 | );
1172 | ```
1173 |
1174 | ### updateFriendNoteName
1175 |
1176 | 更新好友备注名。
1177 |
1178 | #### 示例
1179 |
1180 | ```dart
1181 | await JMessage.updateFriendNoteName(
1182 | username: 'username',
1183 | appKey: 'appKey',
1184 | noteName: 'noteName'
1185 | );
1186 | ```
1187 |
1188 | #### 参数说明
1189 |
1190 | - username: 好友的用户名。
1191 | - appKey: 好友所属应用的 AppKey,如果为空默认为当前应用。
1192 | - noteName: 备注名。不支持 "\n" 和 "\r" 字符,长度要求为 0 ~ 64 Byte。
1193 |
1194 | ### updateFriendNoteText
1195 |
1196 | 更新用户备注信息。
1197 |
1198 | #### 示例
1199 |
1200 | ```dart
1201 | await JMessage.updateFriendNoteText(
1202 | username: 'username',
1203 | appKey: 'appKey',
1204 | noteText: 'noteName'
1205 | )
1206 | ```
1207 |
1208 | #### 参数说明
1209 |
1210 | - username: 好友的用户名。
1211 | - appKey: 好友所属应用的 AppKey,如果为空默认为当前应用。
1212 | - noteText: 备注名。长度要求为 0 ~ 250 Byte。
1213 |
1214 | ## 事件监听
1215 |
1216 | ### 消息事件
1217 |
1218 | #### addReceiveMessageListener
1219 |
1220 | 添加消息事件的监听。
1221 |
1222 | ##### 示例
1223 |
1224 | ```dart
1225 |
1226 | JMessage.addReceiveMessageListener(listener) // 添加监听
1227 | JMessage.removeReceiveMessageListener(listener) // 移除监听
1228 | ```
1229 |
1230 | #### addReceiveChatRoomMsgListener
1231 |
1232 | 添加聊天室消息事件的监听。
1233 |
1234 | ##### 示例
1235 |
1236 | ```dart
1237 | JMessage.addReceiveChatRoomMsgListene(listener) // 添加监听
1238 | JMessage.removeReceiveChatRoomMsgListener(listener) // 移除监听
1239 | ```
1240 |
1241 | #### addSyncOfflineMessageListener
1242 |
1243 | 同步离线消息事件监听。
1244 |
1245 | ##### 示例
1246 |
1247 | ```dart
1248 | JMessage.addSyncOfflineMessageListener(listener) // 添加监听
1249 | JMessage.removeSyncOfflineMessageListener(listener) // 移除监听
1250 | ```
1251 |
1252 | ##### 回调参数
1253 |
1254 | - callbackResult
1255 | - conversation:离线消息所在的会话
1256 | - messageArray:指定会话中的离线消息
1257 |
1258 | #### addSyncRoamingMessageListener
1259 |
1260 | 同步漫游消息事件监听。
1261 |
1262 | ##### 示例
1263 |
1264 | ```dart
1265 | JMessage.addSyncRoamingMessageListener(listener) // 添加监听
1266 | JMessage.removeSyncRoamingMessageListener(listener) // 移除监听
1267 | ```
1268 |
1269 | ##### 回调参数
1270 |
1271 | - callbackResult
1272 | - conversation:漫游消息所在的会话。
1273 |
1274 | #### addMessageRetractListener
1275 |
1276 | 消息撤回事件监听。
1277 |
1278 | ##### 示例
1279 |
1280 | ```dart
1281 | JMessage.addMessageRetractListener(listener) // 添加监听
1282 | JMessage.removeMessageRetractListener(listener) // 移除监听
1283 | ```
1284 |
1285 | ##### 回调参数
1286 |
1287 | - event
1288 | - conversation: 会话对象
1289 | - retractedMessage:被撤回的消息对象
1290 |
1291 | #### addClickMessageNotificationListener
1292 |
1293 | 点击消息通知回调(Android Only,iOS 端可以使用 jpush-react-native 插件的,监听点击推送的事件)。
1294 |
1295 | ##### 示例
1296 |
1297 | ```dart
1298 | JMessage.addClickMessageNotificationListener(listener) // 添加监听
1299 | JMessage.removeClickMessageNotificationListener(listener) // 移除监听
1300 | ```
1301 |
1302 | ##### 回调参数
1303 |
1304 | - message: 可以是 JMTextMessage | JMVoiceMessage | JMImageMessage | JMFileMessage | JMEventMessage | JMCustomMessage;
1305 |
1306 | ### 好友事件
1307 |
1308 | #### addContactNotifyListener
1309 |
1310 | 好友相关通知事件。
1311 |
1312 | ##### 示例
1313 |
1314 | ```dart
1315 | JMessage.addContactNotifyListener(listener) // 添加监听
1316 | JMessage.removeContactNotifyListener(listener) // 移除监听
1317 | ```
1318 |
1319 | ##### 回调参数
1320 |
1321 | - event
1322 | - type:'invite_received' / 'invite_accepted' / 'invite_declined' / 'contact_deleted'
1323 | - reason:事件发生的理由,该字段由对方发起请求时所填,对方如果未填则返回默认字符串。
1324 | - fromUsername: 事件发送者的 username。
1325 | - fromUserAppKey: 事件发送者的 AppKey。
1326 |
1327 | ### 登录状态事件
1328 |
1329 | #### addLoginStateChangedListener
1330 |
1331 | 登录状态变更事件,例如在其他设备登录把当前设备挤出,会触发这个事件。
1332 |
1333 | ##### 示例
1334 |
1335 | ```dart
1336 | JMessage.addLoginStateChangedListener(listener) // 添加监听
1337 | JMessage.removeMessageRetractListener(listener) // 移除监听
1338 | ```
1339 |
1340 | ##### 回调参数
1341 |
1342 | - type: JMLoginStateChangedType。
1343 |
1344 | ### 群组事件
1345 |
1346 | #### addReceiveApplyJoinGroupApprovalListener
1347 |
1348 | 监听接收入群申请事件
1349 |
1350 | ##### 示例
1351 |
1352 | ```dart
1353 |
1354 | JMessage.addReceiveApplyJoinGroupApprovalListener(listener) // 添加监听
1355 | JMessage.removeReceiveApplyJoinGroupApprovalListener(listener) // 移除监听
1356 | ```
1357 |
1358 | ##### 回调参数说明
1359 |
1360 | - event: JMReceiveApplyJoinGroupApprovalEvent
1361 | - eventId (string):消息 id。
1362 | - groupId (string):申请入群的 groudId。
1363 | - isInitiativeApply (boolean):是否是用户主动申请入群,YES:主动申请加入,NO:被邀请加入
1364 | - sendApplyUser (JMUserInfo):发送申请的用户
1365 | - reason (string):入群原因
1366 |
1367 | #### addReceiveGroupAdminRejectListener
1368 |
1369 | 监听管理员拒绝入群申请事件
1370 |
1371 | ##### 示例
1372 |
1373 | ```dart
1374 | JMessage.addReceiveGroupAdminRejectListener(listener) // 添加监听
1375 | JMessage.removeReceiveGroupAdminRejectListener(listener) // 移除监听
1376 | ```
1377 |
1378 | ##### 回调参数说明
1379 |
1380 | - event: JMReceiveGroupAdminRejectEvent
1381 | - eventId (string): 消息 id。
1382 | - rejectReason (string): 拒绝原因。
1383 | - groupManager (JMUserInfo): 操作的管理员
1384 |
1385 | #### addReceiveGroupAdminApprovalListener
1386 |
1387 | 监听管理员同意入群申请事件
1388 |
1389 | ##### 示例
1390 |
1391 | ```dart
1392 | JMessage.addReceiveGroupAdminApprovalListener(listener) // 添加监听
1393 | JMessage.removeReceiveGroupAdminApprovalListener(listener) // 移除监听
1394 | ```
1395 |
1396 | ##### 回调参数说明
1397 |
1398 | - event: JMReceiveGroupAdminApprovalEvent
1399 | - isAgreeApply (boolean): 管理员是否同意申请,YES:同意,NO:拒绝.
1400 | - applyEventID (string): 申请入群事件的事件 id.
1401 | - groupId (string): 群 gid.
1402 | - groupAdmin (JMGroupInfo): 操作的管理员.
1403 | - users [JMUserInfo]: 申请或被邀请加入群的用户,即:实际入群的用户
1404 |
--------------------------------------------------------------------------------
/example/.flutter-plugins-dependencies:
--------------------------------------------------------------------------------
1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"image_picker","path":"D:\\\\Workspace\\\\android\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.flutter-io.cn\\\\image_picker-0.7.5+2\\\\","dependencies":[]},{"name":"jmessage_flutter","path":"D:\\\\Workspace\\\\flutter\\\\jmessage-flutter-plugin\\\\","dependencies":[]},{"name":"modal_progress_hud_nsn","path":"D:\\\\Workspace\\\\android\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.flutter-io.cn\\\\modal_progress_hud_nsn-0.1.0-nullsafety-1\\\\","dependencies":[]},{"name":"video_thumbnail","path":"D:\\\\Workspace\\\\android\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.flutter-io.cn\\\\video_thumbnail-0.3.3\\\\","dependencies":[]}],"android":[{"name":"flutter_plugin_android_lifecycle","path":"D:\\\\Workspace\\\\android\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.flutter-io.cn\\\\flutter_plugin_android_lifecycle-2.0.1\\\\","dependencies":[]},{"name":"image_picker","path":"D:\\\\Workspace\\\\android\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.flutter-io.cn\\\\image_picker-0.7.5+2\\\\","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"jmessage_flutter","path":"D:\\\\Workspace\\\\flutter\\\\jmessage-flutter-plugin\\\\","dependencies":[]},{"name":"modal_progress_hud_nsn","path":"D:\\\\Workspace\\\\android\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.flutter-io.cn\\\\modal_progress_hud_nsn-0.1.0-nullsafety-1\\\\","dependencies":[]},{"name":"video_thumbnail","path":"D:\\\\Workspace\\\\android\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.flutter-io.cn\\\\video_thumbnail-0.3.3\\\\","dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[{"name":"image_picker_for_web","path":"D:\\\\Workspace\\\\android\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.flutter-io.cn\\\\image_picker_for_web-2.0.0\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"image_picker","dependencies":["flutter_plugin_android_lifecycle","image_picker_for_web"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"jmessage_flutter","dependencies":[]},{"name":"modal_progress_hud_nsn","dependencies":[]},{"name":"video_thumbnail","dependencies":[]}],"date_created":"2021-06-01 11:58:00.043626","version":"2.2.0"}
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.lock
4 | *.log
5 | *.pyc
6 | *.swp
7 | .DS_Store
8 | .atom/
9 | .buildlog/
10 | .history
11 | .svn/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # Visual Studio Code related
20 | .vscode/
21 |
22 | # Flutter/Dart/Pub related
23 | **/doc/api/
24 | .dart_tool/
25 | .flutter-plugins
26 | .packages
27 | .pub-cache/
28 | .pub/
29 | build/
30 |
31 | # Android related
32 | **/android/**/gradle-wrapper.jar
33 | **/android/.gradle
34 | **/android/captures/
35 | **/android/gradlew
36 | **/android/gradlew.bat
37 | **/android/local.properties
38 | **/android/**/GeneratedPluginRegistrant.java
39 |
40 | # iOS/XCode related
41 | **/ios/**/*.mode1v3
42 | **/ios/**/*.mode2v3
43 | **/ios/**/*.moved-aside
44 | **/ios/**/*.pbxuser
45 | **/ios/**/*.perspectivev3
46 | **/ios/**/*sync/
47 | **/ios/**/.sconsign.dblite
48 | **/ios/**/.tags*
49 | **/ios/**/.vagrant/
50 | **/ios/**/DerivedData/
51 | **/ios/**/Icon?
52 | **/ios/**/Pods/
53 | **/ios/**/.symlinks/
54 | **/ios/**/profile
55 | **/ios/**/xcuserdata
56 | **/ios/.generated/
57 | **/ios/Flutter/App.framework
58 | **/ios/Flutter/Flutter.framework
59 | **/ios/Flutter/Generated.xcconfig
60 | **/ios/Flutter/app.flx
61 | **/ios/Flutter/app.zip
62 | **/ios/Flutter/flutter_assets/
63 | **/ios/ServiceDefinitions.json
64 | **/ios/Runner/GeneratedPluginRegistrant.*
65 |
66 | # Exceptions to above rules.
67 | !**/ios/**/default.mode1v3
68 | !**/ios/**/default.mode2v3
69 | !**/ios/**/default.pbxuser
70 | !**/ios/**/default.perspectivev3
71 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
72 |
--------------------------------------------------------------------------------
/example/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: f37c235c32fc15babe6dc7b7bc2ee4387e5ecf92
8 | channel: beta
9 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # jmessage_flutter_example
2 |
3 | Demonstrates how to use the jmessage_flutter plugin.
4 |
5 | ## Getting Started
6 |
7 | For help getting started with Flutter, view our online
8 | [documentation](https://flutter.io/).
9 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
26 |
27 | android {
28 | compileSdkVersion 28
29 |
30 | lintOptions {
31 | disable 'InvalidPackage'
32 | }
33 |
34 | defaultConfig {
35 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
36 | applicationId "com.shikk.testJpush"
37 | minSdkVersion 17
38 | targetSdkVersion 28
39 | versionCode flutterVersionCode.toInteger()
40 | versionName flutterVersionName
41 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
42 |
43 | ndk {
44 | //选择要添加的对应 cpu 类型的 .so 库。
45 | abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64', 'mips', 'mips64', 'arm64-v8a'
46 | // 还可以添加
47 | }
48 |
49 | manifestPlaceholders = [
50 | JPUSH_PKGNAME : applicationId,
51 | JPUSH_APPKEY : "你自己应用的 AppKey", //极光 上注册的包名对应的 Appkey.
52 | JPUSH_CHANNEL : "developer-default", //暂时填写默认值即可.
53 | ]
54 | }
55 |
56 | buildTypes {
57 | release {
58 | // TODO: Add your own signing config for the release build.
59 | // Signing with the debug keys for now, so `flutter run --release` works.
60 | signingConfig signingConfigs.debug
61 | }
62 | }
63 | }
64 |
65 | flutter {
66 | source '../..'
67 | }
68 |
69 | dependencies {
70 | testImplementation 'junit:junit:4.12'
71 | androidTestImplementation 'com.android.support.test:runner:1.0.2'
72 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
73 | }
74 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
8 |
9 |
10 |
15 |
19 |
26 |
30 |
34 |
39 |
43 |
44 |
45 |
46 |
47 |
48 |
50 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/jiguang/jmessageflutterexample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.jiguang.jmessageflutterexample;
2 |
3 | import io.flutter.embedding.android.FlutterActivity;
4 |
5 | public class MainActivity extends FlutterActivity {
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:3.2.1'
9 | }
10 | }
11 |
12 | allprojects {
13 | repositories {
14 | google()
15 | jcenter()
16 | }
17 | }
18 |
19 | rootProject.buildDir = '../build'
20 | subprojects {
21 | project.buildDir = "${rootProject.buildDir}/${project.name}"
22 | }
23 | subprojects {
24 | project.evaluationDependsOn(':app')
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.enableR8=true
3 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Oct 30 10:15:16 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
--------------------------------------------------------------------------------
/example/android/key.properties:
--------------------------------------------------------------------------------
1 | storePassword=123456
2 | keyPassword=123456
3 | keyAlias=key
4 | storeFile=/Users/raoxudong/Develop/android/key.jks
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
4 |
5 | def plugins = new Properties()
6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
7 | if (pluginsFile.exists()) {
8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
9 | }
10 |
11 | plugins.each { name, path ->
12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
13 | include ":$name"
14 | project(":$name").projectDir = pluginDirectory
15 | }
16 |
--------------------------------------------------------------------------------
/example/assets/2.0x/nav_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/assets/2.0x/nav_close.png
--------------------------------------------------------------------------------
/example/assets/3.0x/nav_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/assets/3.0x/nav_close.png
--------------------------------------------------------------------------------
/example/assets/nav_close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/assets/nav_close.png
--------------------------------------------------------------------------------
/example/ios/Flutter/.last_build_id:
--------------------------------------------------------------------------------
1 | fb2cd0472ffa0e4848752d33e0ab0ccb
--------------------------------------------------------------------------------
/example/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Flutter.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # NOTE: This podspec is NOT to be published. It is only used as a local source!
3 | #
4 |
5 | Pod::Spec.new do |s|
6 | s.name = 'Flutter'
7 | s.version = '1.0.0'
8 | s.summary = 'High-performance, high-fidelity mobile apps.'
9 | s.description = <<-DESC
10 | Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
11 | DESC
12 | s.homepage = 'https://flutter.io'
13 | s.license = { :type => 'MIT' }
14 | s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
15 | s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
16 | s.ios.deployment_target = '8.0'
17 | s.vendored_frameworks = 'Flutter.framework'
18 | end
19 |
--------------------------------------------------------------------------------
/example/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/example/ios/Flutter/flutter_export_environment.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # This is a generated file; do not edit or check into version control.
3 | export "FLUTTER_ROOT=D:\Workspace\android\flutter"
4 | export "FLUTTER_APPLICATION_PATH=D:\Workspace\flutter\jmessage-flutter-plugin\example"
5 | export "COCOAPODS_PARALLEL_CODE_SIGN=true"
6 | export "FLUTTER_TARGET=lib\main.dart"
7 | export "FLUTTER_BUILD_DIR=build"
8 | export "SYMROOT=${SOURCE_ROOT}/../build\ios"
9 | export "FLUTTER_BUILD_NAME=1.0.0"
10 | export "FLUTTER_BUILD_NUMBER=1"
11 | export "DART_OBFUSCATION=false"
12 | export "TRACK_WIDGET_CREATION=false"
13 | export "TREE_SHAKE_ICONS=false"
14 | export "PACKAGE_CONFIG=.packages"
15 |
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '9.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | def parse_KV_file(file, separator='=')
8 | file_abs_path = File.expand_path(file)
9 | if !File.exists? file_abs_path
10 | return [];
11 | end
12 | pods_ary = []
13 | skip_line_start_symbols = ["#", "/"]
14 | File.foreach(file_abs_path) { |line|
15 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
16 | plugin = line.split(pattern=separator)
17 | if plugin.length == 2
18 | podname = plugin[0].strip()
19 | path = plugin[1].strip()
20 | podpath = File.expand_path("#{path}", file_abs_path)
21 | pods_ary.push({:name => podname, :path => podpath});
22 | else
23 | puts "Invalid plugin specification: #{line}"
24 | end
25 | }
26 | return pods_ary
27 | end
28 |
29 | target 'Runner' do
30 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
31 | # referring to absolute paths on developers' machines.
32 | system('rm -rf .symlinks')
33 | system('mkdir -p .symlinks/plugins')
34 |
35 | # Flutter Pods
36 | generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig')
37 | if generated_xcode_build_settings.empty?
38 | puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first."
39 | end
40 | generated_xcode_build_settings.map { |p|
41 | if p[:name] == 'FLUTTER_FRAMEWORK_DIR'
42 | symlink = File.join('.symlinks', 'flutter')
43 | File.symlink(File.dirname(p[:path]), symlink)
44 | pod 'Flutter', :path => File.join(symlink, File.basename(p[:path]))
45 | end
46 | }
47 |
48 | # Plugin Pods
49 | plugin_pods = parse_KV_file('../.flutter-plugins')
50 | plugin_pods.map { |p|
51 | symlink = File.join('.symlinks', 'plugins', p[:name])
52 | File.symlink(p[:path], symlink)
53 | pod p[:name], :path => File.join(symlink, 'ios')
54 | }
55 | end
56 |
57 | post_install do |installer|
58 | installer.pods_project.targets.each do |target|
59 | target.build_configurations.each do |config|
60 | config.build_settings['ENABLE_BITCODE'] = 'NO'
61 | end
62 | end
63 | end
64 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 0421D6A4AECA46E06708D921 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D8562786885B6B17E6F1E79 /* libPods-Runner.a */; };
11 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
12 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
13 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
14 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
15 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
16 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
17 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
18 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
19 | /* End PBXBuildFile section */
20 |
21 | /* Begin PBXCopyFilesBuildPhase section */
22 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
23 | isa = PBXCopyFilesBuildPhase;
24 | buildActionMask = 2147483647;
25 | dstPath = "";
26 | dstSubfolderSpec = 10;
27 | files = (
28 | );
29 | name = "Embed Frameworks";
30 | runOnlyForDeploymentPostprocessing = 0;
31 | };
32 | /* End PBXCopyFilesBuildPhase section */
33 |
34 | /* Begin PBXFileReference section */
35 | 08EFDA6E22E5A0760064D57C /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; };
36 | 0D8562786885B6B17E6F1E79 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
37 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
38 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
39 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
40 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
41 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
42 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
43 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
44 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
45 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
46 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
47 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
48 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
49 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
50 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
51 | CA73986AFFC3F39E1A9C5F66 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
52 | F4119DDD6425406B43A1B55A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
53 | /* End PBXFileReference section */
54 |
55 | /* Begin PBXFrameworksBuildPhase section */
56 | 97C146EB1CF9000F007C117D /* Frameworks */ = {
57 | isa = PBXFrameworksBuildPhase;
58 | buildActionMask = 2147483647;
59 | files = (
60 | 0421D6A4AECA46E06708D921 /* libPods-Runner.a in Frameworks */,
61 | );
62 | runOnlyForDeploymentPostprocessing = 0;
63 | };
64 | /* End PBXFrameworksBuildPhase section */
65 |
66 | /* Begin PBXGroup section */
67 | 3511FF9C175122F5F3E6EF69 /* Frameworks */ = {
68 | isa = PBXGroup;
69 | children = (
70 | 0D8562786885B6B17E6F1E79 /* libPods-Runner.a */,
71 | );
72 | name = Frameworks;
73 | sourceTree = "";
74 | };
75 | 9740EEB11CF90186004384FC /* Flutter */ = {
76 | isa = PBXGroup;
77 | children = (
78 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
79 | 9740EEB21CF90195004384FC /* Debug.xcconfig */,
80 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
81 | 9740EEB31CF90195004384FC /* Generated.xcconfig */,
82 | );
83 | name = Flutter;
84 | sourceTree = "";
85 | };
86 | 97C146E51CF9000F007C117D = {
87 | isa = PBXGroup;
88 | children = (
89 | 9740EEB11CF90186004384FC /* Flutter */,
90 | 97C146F01CF9000F007C117D /* Runner */,
91 | 97C146EF1CF9000F007C117D /* Products */,
92 | BEE789AD141E349003616266 /* Pods */,
93 | 3511FF9C175122F5F3E6EF69 /* Frameworks */,
94 | );
95 | sourceTree = "";
96 | };
97 | 97C146EF1CF9000F007C117D /* Products */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 97C146EE1CF9000F007C117D /* Runner.app */,
101 | );
102 | name = Products;
103 | sourceTree = "";
104 | };
105 | 97C146F01CF9000F007C117D /* Runner */ = {
106 | isa = PBXGroup;
107 | children = (
108 | 08EFDA6E22E5A0760064D57C /* Runner.entitlements */,
109 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
110 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
111 | 97C146FA1CF9000F007C117D /* Main.storyboard */,
112 | 97C146FD1CF9000F007C117D /* Assets.xcassets */,
113 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
114 | 97C147021CF9000F007C117D /* Info.plist */,
115 | 97C146F11CF9000F007C117D /* Supporting Files */,
116 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
117 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
118 | );
119 | path = Runner;
120 | sourceTree = "";
121 | };
122 | 97C146F11CF9000F007C117D /* Supporting Files */ = {
123 | isa = PBXGroup;
124 | children = (
125 | 97C146F21CF9000F007C117D /* main.m */,
126 | );
127 | name = "Supporting Files";
128 | sourceTree = "";
129 | };
130 | BEE789AD141E349003616266 /* Pods */ = {
131 | isa = PBXGroup;
132 | children = (
133 | F4119DDD6425406B43A1B55A /* Pods-Runner.debug.xcconfig */,
134 | CA73986AFFC3F39E1A9C5F66 /* Pods-Runner.release.xcconfig */,
135 | );
136 | name = Pods;
137 | sourceTree = "";
138 | };
139 | /* End PBXGroup section */
140 |
141 | /* Begin PBXNativeTarget section */
142 | 97C146ED1CF9000F007C117D /* Runner */ = {
143 | isa = PBXNativeTarget;
144 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
145 | buildPhases = (
146 | C6963D077F919AA39B9905A3 /* [CP] Check Pods Manifest.lock */,
147 | 9740EEB61CF901F6004384FC /* Run Script */,
148 | 97C146EA1CF9000F007C117D /* Sources */,
149 | 97C146EB1CF9000F007C117D /* Frameworks */,
150 | 97C146EC1CF9000F007C117D /* Resources */,
151 | 9705A1C41CF9048500538489 /* Embed Frameworks */,
152 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
153 | 03468A242FE0B80CF0AD9B45 /* [CP] Embed Pods Frameworks */,
154 | );
155 | buildRules = (
156 | );
157 | dependencies = (
158 | );
159 | name = Runner;
160 | productName = Runner;
161 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
162 | productType = "com.apple.product-type.application";
163 | };
164 | /* End PBXNativeTarget section */
165 |
166 | /* Begin PBXProject section */
167 | 97C146E61CF9000F007C117D /* Project object */ = {
168 | isa = PBXProject;
169 | attributes = {
170 | LastUpgradeCheck = 0910;
171 | ORGANIZATIONNAME = "The Chromium Authors";
172 | TargetAttributes = {
173 | 97C146ED1CF9000F007C117D = {
174 | CreatedOnToolsVersion = 7.3.1;
175 | DevelopmentTeam = 8X2A38Q9VD;
176 | ProvisioningStyle = Manual;
177 | SystemCapabilities = {
178 | com.apple.BackgroundModes = {
179 | enabled = 1;
180 | };
181 | com.apple.Push = {
182 | enabled = 1;
183 | };
184 | };
185 | };
186 | };
187 | };
188 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
189 | compatibilityVersion = "Xcode 3.2";
190 | developmentRegion = English;
191 | hasScannedForEncodings = 0;
192 | knownRegions = (
193 | English,
194 | en,
195 | Base,
196 | );
197 | mainGroup = 97C146E51CF9000F007C117D;
198 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
199 | projectDirPath = "";
200 | projectRoot = "";
201 | targets = (
202 | 97C146ED1CF9000F007C117D /* Runner */,
203 | );
204 | };
205 | /* End PBXProject section */
206 |
207 | /* Begin PBXResourcesBuildPhase section */
208 | 97C146EC1CF9000F007C117D /* Resources */ = {
209 | isa = PBXResourcesBuildPhase;
210 | buildActionMask = 2147483647;
211 | files = (
212 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
213 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
214 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
215 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
216 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
217 | );
218 | runOnlyForDeploymentPostprocessing = 0;
219 | };
220 | /* End PBXResourcesBuildPhase section */
221 |
222 | /* Begin PBXShellScriptBuildPhase section */
223 | 03468A242FE0B80CF0AD9B45 /* [CP] Embed Pods Frameworks */ = {
224 | isa = PBXShellScriptBuildPhase;
225 | buildActionMask = 2147483647;
226 | files = (
227 | );
228 | inputPaths = (
229 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
230 | "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework",
231 | );
232 | name = "[CP] Embed Pods Frameworks";
233 | outputPaths = (
234 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework",
235 | );
236 | runOnlyForDeploymentPostprocessing = 0;
237 | shellPath = /bin/sh;
238 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
239 | showEnvVarsInLog = 0;
240 | };
241 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
242 | isa = PBXShellScriptBuildPhase;
243 | buildActionMask = 2147483647;
244 | files = (
245 | );
246 | inputPaths = (
247 | );
248 | name = "Thin Binary";
249 | outputPaths = (
250 | );
251 | runOnlyForDeploymentPostprocessing = 0;
252 | shellPath = /bin/sh;
253 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
254 | };
255 | 9740EEB61CF901F6004384FC /* Run Script */ = {
256 | isa = PBXShellScriptBuildPhase;
257 | buildActionMask = 2147483647;
258 | files = (
259 | );
260 | inputPaths = (
261 | );
262 | name = "Run Script";
263 | outputPaths = (
264 | );
265 | runOnlyForDeploymentPostprocessing = 0;
266 | shellPath = /bin/sh;
267 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n";
268 | };
269 | C6963D077F919AA39B9905A3 /* [CP] Check Pods Manifest.lock */ = {
270 | isa = PBXShellScriptBuildPhase;
271 | buildActionMask = 2147483647;
272 | files = (
273 | );
274 | inputPaths = (
275 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
276 | "${PODS_ROOT}/Manifest.lock",
277 | );
278 | name = "[CP] Check Pods Manifest.lock";
279 | outputPaths = (
280 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
281 | );
282 | runOnlyForDeploymentPostprocessing = 0;
283 | shellPath = /bin/sh;
284 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
285 | showEnvVarsInLog = 0;
286 | };
287 | /* End PBXShellScriptBuildPhase section */
288 |
289 | /* Begin PBXSourcesBuildPhase section */
290 | 97C146EA1CF9000F007C117D /* Sources */ = {
291 | isa = PBXSourcesBuildPhase;
292 | buildActionMask = 2147483647;
293 | files = (
294 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
295 | 97C146F31CF9000F007C117D /* main.m in Sources */,
296 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
297 | );
298 | runOnlyForDeploymentPostprocessing = 0;
299 | };
300 | /* End PBXSourcesBuildPhase section */
301 |
302 | /* Begin PBXVariantGroup section */
303 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
304 | isa = PBXVariantGroup;
305 | children = (
306 | 97C146FB1CF9000F007C117D /* Base */,
307 | );
308 | name = Main.storyboard;
309 | sourceTree = "";
310 | };
311 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
312 | isa = PBXVariantGroup;
313 | children = (
314 | 97C147001CF9000F007C117D /* Base */,
315 | );
316 | name = LaunchScreen.storyboard;
317 | sourceTree = "";
318 | };
319 | /* End PBXVariantGroup section */
320 |
321 | /* Begin XCBuildConfiguration section */
322 | 97C147031CF9000F007C117D /* Debug */ = {
323 | isa = XCBuildConfiguration;
324 | buildSettings = {
325 | ALWAYS_SEARCH_USER_PATHS = NO;
326 | CLANG_ANALYZER_NONNULL = YES;
327 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
328 | CLANG_CXX_LIBRARY = "libc++";
329 | CLANG_ENABLE_MODULES = YES;
330 | CLANG_ENABLE_OBJC_ARC = YES;
331 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
332 | CLANG_WARN_BOOL_CONVERSION = YES;
333 | CLANG_WARN_COMMA = YES;
334 | CLANG_WARN_CONSTANT_CONVERSION = YES;
335 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
336 | CLANG_WARN_EMPTY_BODY = YES;
337 | CLANG_WARN_ENUM_CONVERSION = YES;
338 | CLANG_WARN_INFINITE_RECURSION = YES;
339 | CLANG_WARN_INT_CONVERSION = YES;
340 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
341 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
342 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
343 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
344 | CLANG_WARN_STRICT_PROTOTYPES = YES;
345 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
346 | CLANG_WARN_UNREACHABLE_CODE = YES;
347 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
348 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
349 | COPY_PHASE_STRIP = NO;
350 | DEBUG_INFORMATION_FORMAT = dwarf;
351 | ENABLE_STRICT_OBJC_MSGSEND = YES;
352 | ENABLE_TESTABILITY = YES;
353 | GCC_C_LANGUAGE_STANDARD = gnu99;
354 | GCC_DYNAMIC_NO_PIC = NO;
355 | GCC_NO_COMMON_BLOCKS = YES;
356 | GCC_OPTIMIZATION_LEVEL = 0;
357 | GCC_PREPROCESSOR_DEFINITIONS = (
358 | "DEBUG=1",
359 | "$(inherited)",
360 | );
361 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
362 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
363 | GCC_WARN_UNDECLARED_SELECTOR = YES;
364 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
365 | GCC_WARN_UNUSED_FUNCTION = YES;
366 | GCC_WARN_UNUSED_VARIABLE = YES;
367 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
368 | MTL_ENABLE_DEBUG_INFO = YES;
369 | ONLY_ACTIVE_ARCH = YES;
370 | SDKROOT = iphoneos;
371 | TARGETED_DEVICE_FAMILY = "1,2";
372 | };
373 | name = Debug;
374 | };
375 | 97C147041CF9000F007C117D /* Release */ = {
376 | isa = XCBuildConfiguration;
377 | buildSettings = {
378 | ALWAYS_SEARCH_USER_PATHS = NO;
379 | CLANG_ANALYZER_NONNULL = YES;
380 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
381 | CLANG_CXX_LIBRARY = "libc++";
382 | CLANG_ENABLE_MODULES = YES;
383 | CLANG_ENABLE_OBJC_ARC = YES;
384 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
385 | CLANG_WARN_BOOL_CONVERSION = YES;
386 | CLANG_WARN_COMMA = YES;
387 | CLANG_WARN_CONSTANT_CONVERSION = YES;
388 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
389 | CLANG_WARN_EMPTY_BODY = YES;
390 | CLANG_WARN_ENUM_CONVERSION = YES;
391 | CLANG_WARN_INFINITE_RECURSION = YES;
392 | CLANG_WARN_INT_CONVERSION = YES;
393 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
394 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
395 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
396 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
397 | CLANG_WARN_STRICT_PROTOTYPES = YES;
398 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
399 | CLANG_WARN_UNREACHABLE_CODE = YES;
400 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
401 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
402 | COPY_PHASE_STRIP = NO;
403 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
404 | ENABLE_NS_ASSERTIONS = NO;
405 | ENABLE_STRICT_OBJC_MSGSEND = YES;
406 | GCC_C_LANGUAGE_STANDARD = gnu99;
407 | GCC_NO_COMMON_BLOCKS = YES;
408 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
409 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
410 | GCC_WARN_UNDECLARED_SELECTOR = YES;
411 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
412 | GCC_WARN_UNUSED_FUNCTION = YES;
413 | GCC_WARN_UNUSED_VARIABLE = YES;
414 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
415 | MTL_ENABLE_DEBUG_INFO = NO;
416 | SDKROOT = iphoneos;
417 | TARGETED_DEVICE_FAMILY = "1,2";
418 | VALIDATE_PRODUCT = YES;
419 | };
420 | name = Release;
421 | };
422 | 97C147061CF9000F007C117D /* Debug */ = {
423 | isa = XCBuildConfiguration;
424 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
425 | buildSettings = {
426 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
427 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
428 | CODE_SIGN_IDENTITY = "iPhone Developer";
429 | CODE_SIGN_STYLE = Manual;
430 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
431 | DEVELOPMENT_TEAM = 8X2A38Q9VD;
432 | ENABLE_BITCODE = NO;
433 | FRAMEWORK_SEARCH_PATHS = (
434 | "$(inherited)",
435 | "$(PROJECT_DIR)/Flutter",
436 | );
437 | INFOPLIST_FILE = Runner/Info.plist;
438 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
439 | LIBRARY_SEARCH_PATHS = (
440 | "$(inherited)",
441 | "$(PROJECT_DIR)/Flutter",
442 | );
443 | PRODUCT_BUNDLE_IDENTIFIER = com.jmessage.sdk;
444 | PRODUCT_NAME = "$(TARGET_NAME)";
445 | PROVISIONING_PROFILE_SPECIFIER = "com.jmessage.sdk-dev";
446 | VERSIONING_SYSTEM = "apple-generic";
447 | };
448 | name = Debug;
449 | };
450 | 97C147071CF9000F007C117D /* Release */ = {
451 | isa = XCBuildConfiguration;
452 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
453 | buildSettings = {
454 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
455 | CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
456 | CODE_SIGN_IDENTITY = "iPhone Developer";
457 | CODE_SIGN_STYLE = Manual;
458 | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
459 | DEVELOPMENT_TEAM = 8X2A38Q9VD;
460 | ENABLE_BITCODE = NO;
461 | FRAMEWORK_SEARCH_PATHS = (
462 | "$(inherited)",
463 | "$(PROJECT_DIR)/Flutter",
464 | );
465 | INFOPLIST_FILE = Runner/Info.plist;
466 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
467 | LIBRARY_SEARCH_PATHS = (
468 | "$(inherited)",
469 | "$(PROJECT_DIR)/Flutter",
470 | );
471 | PRODUCT_BUNDLE_IDENTIFIER = com.jmessage.sdk;
472 | PRODUCT_NAME = "$(TARGET_NAME)";
473 | PROVISIONING_PROFILE_SPECIFIER = "com.jmessage.sdk-dev";
474 | VERSIONING_SYSTEM = "apple-generic";
475 | };
476 | name = Release;
477 | };
478 | /* End XCBuildConfiguration section */
479 |
480 | /* Begin XCConfigurationList section */
481 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
482 | isa = XCConfigurationList;
483 | buildConfigurations = (
484 | 97C147031CF9000F007C117D /* Debug */,
485 | 97C147041CF9000F007C117D /* Release */,
486 | );
487 | defaultConfigurationIsVisible = 0;
488 | defaultConfigurationName = Release;
489 | };
490 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
491 | isa = XCConfigurationList;
492 | buildConfigurations = (
493 | 97C147061CF9000F007C117D /* Debug */,
494 | 97C147071CF9000F007C117D /* Release */,
495 | );
496 | defaultConfigurationIsVisible = 0;
497 | defaultConfigurationName = Release;
498 | };
499 | /* End XCConfigurationList section */
500 | };
501 | rootObject = 97C146E61CF9000F007C117D /* Project object */;
502 | }
503 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
56 |
58 |
64 |
65 |
66 |
67 |
68 |
69 |
75 |
77 |
83 |
84 |
85 |
86 |
88 |
89 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : FlutterAppDelegate
5 |
6 | @end
7 |
--------------------------------------------------------------------------------
/example/ios/Runner/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #include "AppDelegate.h"
2 | #include "GeneratedPluginRegistrant.h"
3 |
4 | @implementation AppDelegate
5 |
6 | - (BOOL)application:(UIApplication *)application
7 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
8 | [GeneratedPluginRegistrant registerWithRegistry:self];
9 | // Override point for customization after application launch.
10 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
11 | }
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/example/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSCameraUsageDescription
6 | demo 想要访问你的相机
7 | NSPhotoLibraryUsageDescription
8 | demo 想要访问你的相册
9 | CFBundleDevelopmentRegion
10 | en
11 | CFBundleExecutable
12 | $(EXECUTABLE_NAME)
13 | CFBundleIdentifier
14 | $(PRODUCT_BUNDLE_IDENTIFIER)
15 | CFBundleInfoDictionaryVersion
16 | 6.0
17 | CFBundleName
18 | jmessage_flutter_example
19 | CFBundlePackageType
20 | APPL
21 | CFBundleShortVersionString
22 | $(FLUTTER_BUILD_NAME)
23 | CFBundleSignature
24 | ????
25 | CFBundleVersion
26 | $(FLUTTER_BUILD_NUMBER)
27 | LSRequiresIPhoneOS
28 |
29 | UIBackgroundModes
30 |
31 | remote-notification
32 |
33 | UILaunchStoryboardName
34 | LaunchScreen
35 | UIMainStoryboardFile
36 | Main
37 | UISupportedInterfaceOrientations
38 |
39 | UIInterfaceOrientationPortrait
40 | UIInterfaceOrientationLandscapeLeft
41 | UIInterfaceOrientationLandscapeRight
42 |
43 | UISupportedInterfaceOrientations~ipad
44 |
45 | UIInterfaceOrientationPortrait
46 | UIInterfaceOrientationPortraitUpsideDown
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 | UIViewControllerBasedStatusBarAppearance
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/example/ios/Runner/Runner.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | aps-environment
6 | development
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/ios/Runner/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char* argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/example/lib/conversation_manage_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/widgets.dart';
3 | import 'package:jmessage_flutter/jmessage_flutter.dart';
4 | import 'package:jmessage_flutter_example/main.dart';
5 | import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
6 |
7 | class ConversationManageView extends StatefulWidget {
8 | @override
9 | _ConversationManageViewState createState() => _ConversationManageViewState();
10 | }
11 |
12 | class _ConversationManageViewState extends State {
13 | List dataList = [];
14 | bool _loading = false;
15 | String _result = "请选择需要操作的会话";
16 | int selectIndex = -1;
17 | JMConversationInfo? selectConversationInfo;
18 |
19 | @override
20 | void initState() {
21 | super.initState();
22 |
23 | demoGetConversationList();
24 | }
25 |
26 | void addMessageEvent() async {
27 | jmessage.addReceiveMessageListener((msg) {
28 | //+
29 | print('listener receive event - message : ${msg.toJson()}');
30 |
31 | verifyMessage(msg);
32 |
33 | setState(() {
34 | _result = "【收到消息】${msg.toJson()}";
35 | });
36 | });
37 | }
38 |
39 | @override
40 | Widget build(BuildContext context) {
41 | return new Scaffold(
42 | appBar: AppBar(
43 | title: new Text("会话列表", style: TextStyle(fontSize: 20)),
44 | leading: IconButton(
45 | icon: new Image.asset("assets/nav_close.png"),
46 | onPressed: () {
47 | Navigator.maybePop(context);
48 | }),
49 | ),
50 | body: ModalProgressHUD(inAsyncCall: _loading, child: _buildContentView()),
51 | );
52 | }
53 |
54 | Widget _buildContentView() {
55 | return new Column(
56 | children: [
57 | new Container(
58 | margin: EdgeInsets.fromLTRB(5, 5, 5, 0),
59 | color: Colors.brown,
60 | child: Text(_result),
61 | width: double.infinity,
62 | height: 120,
63 | ),
64 | new Row(
65 | mainAxisAlignment: MainAxisAlignment.start,
66 | children: [
67 | new Text(" "),
68 | new CustomButton(title: "发送文本消息", onPressed: demoSendTextMessage),
69 | new Text(" "),
70 | new CustomButton(title: "获取历史消息", onPressed: demoGetHistorMessage),
71 | new Text(" "),
72 | new CustomButton(
73 | title: "刷新会话列表",
74 | onPressed: () {
75 | demoGetConversationList();
76 | }),
77 | ],
78 | ),
79 | Expanded(
80 | child: new Container(
81 | color: Colors.grey,
82 | margin: EdgeInsets.fromLTRB(5, 5, 5, 5),
83 | child: new ListView.builder(
84 | itemCount: dataList.length * 2,
85 | itemBuilder: (context, i) {
86 | if (i.isOdd) return new Divider();
87 |
88 | final index = i ~/ 2;
89 |
90 | return _buildRow(dataList[index], index);
91 | }),
92 | ),
93 | ),
94 | ],
95 | );
96 | }
97 |
98 | Widget _buildRow(JMConversationInfo object, int index) {
99 | String title =
100 | "【${getStringFromEnum(object.conversationType)}】${object.title}";
101 |
102 | return new Container(
103 | height: 60,
104 | child: new ListTile(
105 | //dense: true,
106 | //leading: CircleAvatar(backgroundImage: NetworkImage(url)),
107 | //trailing: Icon(Icons.keyboard_arrow_right),
108 | contentPadding: EdgeInsets.symmetric(horizontal: 10.0),
109 | //设置内容边距,默认是 16
110 | title: new Text(title),
111 | subtitle: new Text(object.latestMessage.toString()),
112 | selected: selectIndex == index,
113 | onTap: () {
114 | print("点击了第【${index + 1}】行");
115 | setState(() {
116 | selectIndex = index;
117 | _result = "【选择的会话】\n ${object.toJson()}";
118 | });
119 | selectConversationInfo = object;
120 | },
121 | ),
122 | );
123 | }
124 |
125 | /// 获取公开群列表
126 | void demoGetConversationList() async {
127 | print("demoGetConversationList");
128 | setState(() {
129 | selectIndex = -1;
130 | selectConversationInfo = null;
131 | _result = "请选择需要操作的会话";
132 | _loading = true;
133 | });
134 |
135 | List conversations = await jmessage.getConversations();
136 |
137 | setState(() {
138 | _loading = false;
139 | dataList = conversations;
140 | });
141 |
142 | for (JMConversationInfo info in conversations) {
143 | print('会话:${info.toJson()}');
144 | }
145 | }
146 |
147 | int textIndex = 0;
148 |
149 | void demoSendTextMessage() async {
150 | print("demoSendTextMessage");
151 |
152 | if (selectConversationInfo == null) {
153 | setState(() {
154 | _result = "请选着需要操作的会话";
155 | });
156 | return;
157 | }
158 | setState(() {
159 | _loading = true;
160 | });
161 |
162 | JMTextMessage msg = await selectConversationInfo!.sendTextMessage(
163 | text: "send msg queen index $textIndex");
164 | setState(() {
165 | _loading = false;
166 | _result = "【文本消息】${msg.toJson()}";
167 | });
168 | textIndex++;
169 | }
170 |
171 | // 历史消息
172 | void demoGetHistorMessage() async {
173 | print("demoGetHistorMessage");
174 |
175 | if (selectConversationInfo == null) {
176 | setState(() {
177 | _result = "请选着需要操作的会话";
178 | });
179 | return;
180 | }
181 |
182 | setState(() {
183 | _loading = true;
184 | });
185 |
186 | selectConversationInfo!
187 | .getHistoryMessages(from: 0, limit: 20)
188 | .then((msgList) {
189 | for (JMNormalMessage msg in msgList) {
190 | print("get conversation history msg : ${msg.toJson()}");
191 | }
192 |
193 | setState(() {
194 | _loading = false;
195 | _result = "【消息列表】${msgList.toString()}";
196 | });
197 | });
198 | }
199 | }
200 |
--------------------------------------------------------------------------------
/example/lib/group_manage_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/widgets.dart';
3 | import 'package:jmessage_flutter/jmessage_flutter.dart';
4 | import 'package:jmessage_flutter_example/main.dart';
5 | import 'package:modal_progress_hud_nsn/modal_progress_hud_nsn.dart';
6 |
7 | class GroupManageView extends StatefulWidget {
8 | @override
9 | _GroupManageViewState createState() => _GroupManageViewState();
10 | }
11 |
12 | class _GroupManageViewState extends State {
13 | List dataList = [];
14 | bool _loading = false;
15 | String _result = "选择需要操作的群组";
16 | int selectIndex = -1;
17 | JMGroupInfo? selectedGroupInfo;
18 |
19 | var usernameTextEC1 = new TextEditingController();
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | return new Scaffold(
24 | appBar: AppBar(
25 | title: new Text("群组列表", style: TextStyle(fontSize: 20)),
26 | leading: IconButton(
27 | icon: new Image.asset("assets/nav_close.png"),
28 | onPressed: () {
29 | Navigator.maybePop(context);
30 | }),
31 | ),
32 | body: ModalProgressHUD(inAsyncCall: _loading, child: _buildContentView()),
33 | );
34 | }
35 |
36 | Widget _buildContentView() {
37 | return new Column(
38 | children: [
39 | new Container(
40 | height: 100,
41 | child: new Row(
42 | children: [
43 | Expanded(
44 | child: new Container(
45 | margin: EdgeInsets.fromLTRB(5, 5, 5, 0),
46 | color: Colors.brown,
47 | child: Text(_result),
48 | height: double.infinity,
49 | ),
50 | flex: 2,
51 | ),
52 | Expanded(
53 | child: new Column(
54 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
55 | children: [
56 | new CustomButton(title: "私有群列表", onPressed: demoGetGidList),
57 | new CustomButton(
58 | title: "公开群列表", onPressed: demoGetPublicGroupInfos),
59 | ],
60 | ),
61 | flex: 1,
62 | ),
63 | ],
64 | ),
65 | ),
66 | new CustomTextField(
67 | hintText: "请输入username/group name", controller: usernameTextEC1),
68 | new Row(
69 | children: [
70 | new Text(" "),
71 | new CustomButton(title: "成员列表", onPressed: demoGetMemberlist),
72 | new Text(" "),
73 | new CustomButton(title: "加入成员", onPressed: demoAddMember),
74 | new Text(" "),
75 | new CustomButton(title: "移除成员", onPressed: demoRemoveMember),
76 | new Text(" "),
77 | new CustomButton(title: "申请加入", onPressed: demoApplyJoinGroup),
78 | ],
79 | ),
80 | new Row(
81 | children: [
82 | new Text(" "),
83 | new CustomButton(
84 | title: "创建公开群组",
85 | onPressed: () {
86 | demoCreateGroup(JMGroupType.public);
87 | }),
88 | new Text(" "),
89 | new CustomButton(
90 | title: "创建私有群组",
91 | onPressed: () {
92 | demoCreateGroup(JMGroupType.private);
93 | }),
94 | new Text(" "),
95 | new CustomButton(title: "创建群聊会话", onPressed: demoCreatConversation),
96 | ],
97 | ),
98 | Expanded(
99 | child: new Container(
100 | color: Colors.grey,
101 | margin: EdgeInsets.fromLTRB(5, 5, 5, 5),
102 | child: new ListView.builder(
103 | itemCount: dataList.length * 2,
104 | itemBuilder: (context, i) {
105 | if (i.isOdd) return new Divider();
106 | final index = i ~/ 2;
107 | return _buildRow(dataList[index], index);
108 | }),
109 | ),
110 | ),
111 | ],
112 | );
113 | }
114 |
115 | Widget _buildRow(dynamic object, int index) {
116 | String title = "";
117 | String subTitle = "";
118 | if (object is String) {
119 | title = "【私有群】gid: " + object;
120 | } else if (object is JMGroupInfo) {
121 | title = "【公开群】name: " + object.name;
122 | subTitle = " gid: " + object.id;
123 | }
124 |
125 | return new Container(
126 | height: 60,
127 | child: new ListTile(
128 | //dense: true,
129 | //leading: CircleAvatar(backgroundImage: NetworkImage(url)),
130 | //trailing: Icon(Icons.keyboard_arrow_right),
131 | contentPadding: EdgeInsets.symmetric(horizontal: 10.0),
132 | //设置内容边距,默认是 16
133 | title: new Text(title),
134 | subtitle: new Text(subTitle, style: TextStyle(fontSize: 14)),
135 | selected: selectIndex == index,
136 | onTap: () {
137 | print("点击了第【${index + 1}】行");
138 | String? gid;
139 | if (object is String) {
140 | gid = object;
141 | } else if (object is JMGroupInfo) {
142 | gid = object.id;
143 | }
144 | demoGetGroupInfo(gid);
145 | setState(() {
146 | selectIndex = index;
147 | });
148 | },
149 | ),
150 | );
151 | }
152 |
153 | void demoGetGroupInfo(String? gid) async {
154 | print("demoGetGroupInfo gid = $gid");
155 |
156 | setState(() {
157 | _loading = true;
158 | });
159 |
160 | JMGroupInfo groupInfo = await jmessage.getGroupInfo(id: gid);
161 | print("群信息:${groupInfo.toJson()}");
162 |
163 | selectedGroupInfo = groupInfo;
164 |
165 | setState(() {
166 | _loading = false;
167 | _result = "【选择的群组信息】\n ${groupInfo.toJson()}";
168 | });
169 | }
170 |
171 | void demoGetMemberlist() async {
172 | print("demoGetMemberlist ");
173 |
174 | if (selectedGroupInfo == null) {
175 | setState(() {
176 | _result = "请选着需要操作的群组";
177 | });
178 | return;
179 | }
180 |
181 | setState(() {
182 | _loading = true;
183 | });
184 |
185 | String gid = selectedGroupInfo!.id;
186 | List res = await jmessage.getGroupMembers(id: gid);
187 | print("群组【gid:$gid】的群成员列表:");
188 | for (JMGroupMemberInfo member in res) {
189 | print("group member info : ${member.toJson()}");
190 | }
191 | setState(() {
192 | _loading = false;
193 | _result = "【群成员信息】请查看控制台 log 输出";
194 | });
195 | }
196 |
197 | void demoAddMember() async {
198 | print("demoAddMember ");
199 |
200 | if (usernameTextEC1.text.isEmpty) {
201 | setState(() {
202 | _loading = false;
203 | _result = "【添加群成员】username 不能为空";
204 | });
205 | return;
206 | }
207 | if (selectedGroupInfo == null) {
208 | setState(() {
209 | _loading = false;
210 | _result = "【添加群成员】请选着需要操作的群组";
211 | });
212 | return;
213 | }
214 | String gid = selectedGroupInfo!.id;
215 | String username = usernameTextEC1.text;
216 | await jmessage.addGroupMembers(id: gid, usernameArray: [username]);
217 | setState(() {
218 | _loading = false;
219 | _result = "【添加群成员】操作完成";
220 | });
221 | }
222 |
223 | void demoRemoveMember() async {
224 | print("demoRemoveMember ");
225 |
226 | if (usernameTextEC1.text.isEmpty) {
227 | setState(() {
228 | _loading = false;
229 | _result = "【移除群成员】username 不能为空";
230 | });
231 | return;
232 | }
233 | if (selectedGroupInfo == null) {
234 | setState(() {
235 | _loading = false;
236 | _result = "【移除群成员】请选着需要操作的群组";
237 | });
238 | return;
239 | }
240 | String gid = selectedGroupInfo!.id;
241 | String username = usernameTextEC1.text;
242 | await jmessage.removeGroupMembers(id: gid, usernames: [username]);
243 |
244 | setState(() {
245 | _loading = false;
246 | _result = "【移除群成员】操作完成";
247 | });
248 | }
249 |
250 | void demoApplyJoinGroup() async {
251 | print("demoApplyJoinGroup");
252 |
253 | setState(() {
254 | _loading = true;
255 | });
256 |
257 | if (selectedGroupInfo == null) {
258 | setState(() {
259 | _loading = false;
260 | _result = "【申请加入群组】请选着需要操作的群组";
261 | });
262 | return;
263 | }
264 |
265 | if (selectedGroupInfo!.groupType == JMGroupType.private) {
266 | setState(() {
267 | _loading = false;
268 | _result = "【申请加入群组】该群为私有群,可直接加入";
269 | });
270 | return;
271 | }
272 |
273 | String gid = selectedGroupInfo!.id;
274 | await jmessage.applyJoinGroup(groupId: gid);
275 |
276 | setState(() {
277 | _loading = false;
278 | _result = "【申请加入群组】操作完成";
279 | });
280 | }
281 |
282 | /// 获取 我的群列表
283 | void demoGetGidList() async {
284 | print("demoGetGroupList");
285 |
286 | reset();
287 |
288 | setState(() {
289 | _loading = true;
290 | });
291 | List list = await jmessage.getGroupIds();
292 | setState(() {
293 | _loading = false;
294 | dataList = list;
295 | });
296 | }
297 |
298 | /// 获取公开群列表
299 | void demoGetPublicGroupInfos() async {
300 | print("demoGetPublicGroupInfos");
301 |
302 | reset();
303 | setState(() {
304 | _loading = true;
305 | });
306 |
307 | JMUserInfo? userInfo = await jmessage.getMyInfo();
308 | String? appkey = userInfo!.appKey;
309 |
310 | List groupList =
311 | await jmessage.getPublicGroupInfos(appKey: appkey, start: 0, count: 20);
312 | setState(() {
313 | _loading = false;
314 | dataList = groupList;
315 | });
316 | }
317 |
318 | void demoCreateGroup(JMGroupType type) async {
319 | print("demoCreateGroup" + usernameTextEC1.text);
320 |
321 | setState(() {
322 | _loading = true;
323 | });
324 |
325 | if (usernameTextEC1.text.isEmpty) {
326 | setState(() {
327 | _loading = false;
328 | _result = "【创建公开群】group name 不能为空";
329 | });
330 | return;
331 | }
332 | String name = usernameTextEC1.text;
333 | String groupIdString = await jmessage.createGroup(
334 | groupType: type, name: name, desc: "$name-的群描述信息");
335 | setState(() {
336 | _loading = false;
337 | _result = "【创建群组】创建成功,gid = $groupIdString";
338 | });
339 | }
340 |
341 | void demoCreatConversation() async {
342 | print("demoCreatConversation");
343 |
344 | setState(() {
345 | _loading = true;
346 | });
347 |
348 | if (selectedGroupInfo == null) {
349 | setState(() {
350 | _loading = false;
351 | _result = "【创建群聊会话】请选着需要操作的群组";
352 | });
353 | return;
354 | }
355 |
356 | String gid = selectedGroupInfo!.id;
357 | JMGroup group = JMGroup.fromJson({"groupId": gid});
358 | JMConversationInfo conversationInfo =
359 | await jmessage.createConversation(target: group);
360 |
361 | setState(() {
362 | _loading = false;
363 | _result = "【创建群聊会话】 $conversationInfo";
364 | });
365 | }
366 |
367 | void reset() {
368 | setState(() {
369 | _result = "选择需要操作的群组";
370 | selectIndex = -1;
371 | selectedGroupInfo = null;
372 | });
373 | }
374 | }
375 |
--------------------------------------------------------------------------------
/example/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: jmessage_flutter_example
2 | description: Demonstrates how to use the jmessage_flutter plugin.
3 |
4 | # The following defines the version and build number for your application.
5 | # A version number is three numbers separated by dots, like 1.2.43
6 | # followed by an optional build number separated by a +.
7 | # Both the version and the builder number may be overridden in flutter
8 | # build by specifying --build-name and --build-number, respectively.
9 | # Read more about versioning at semver.org.
10 | version: 1.0.0+1
11 |
12 | environment:
13 | sdk: ">=2.12.0 <3.0.0"
14 | flutter: ">=1.20.0"
15 |
16 | dependencies:
17 | flutter:
18 | sdk: flutter
19 | modal_progress_hud_nsn: ^0.1.0-nullsafety-1
20 |
21 | # The following adds the Cupertino Icons font to your application.
22 | # Use with the CupertinoIcons class for iOS style icons.
23 | cupertino_icons: ^1.0.3
24 | image_picker: ^0.7.5+2
25 | video_thumbnail: ^0.3.3
26 |
27 | dev_dependencies:
28 | flutter_test:
29 | sdk: flutter
30 |
31 | jmessage_flutter:
32 | path: ../
33 |
34 | # For information on the generic Dart part of this file, see the
35 | # following page: https://www.dartlang.org/tools/pub/pubspec
36 |
37 | # The following section is specific to Flutter.
38 | flutter:
39 |
40 | # The following line ensures that the Material Icons font is
41 | # included with your application, so that you can use the icons in
42 | # the material Icons class.
43 | uses-material-design: true
44 |
45 | # To add assets to your application, add an assets section, like this:
46 | assets:
47 | - assets/nav_close.png
48 | # - images/a_dot_burr.jpeg
49 | # - images/a_dot_ham.jpeg
50 |
51 | # An image asset can refer to one or more resolution-specific "variants", see
52 | # https://flutter.io/assets-and-images/#resolution-aware.
53 |
54 | # For details regarding adding assets from package dependencies, see
55 | # https://flutter.io/assets-and-images/#from-packages
56 |
57 | # To add custom fonts to your application, add a fonts section here,
58 | # in this "flutter" section. Each entry in this list should have a
59 | # "family" key with the font family name, and a "fonts" key with a
60 | # list giving the asset and other descriptors for the font. For
61 | # example:
62 | # fonts:
63 | # - family: Schyler
64 | # fonts:
65 | # - asset: fonts/Schyler-Regular.ttf
66 | # - asset: fonts/Schyler-Italic.ttf
67 | # style: italic
68 | # - family: Trajan Pro
69 | # fonts:
70 | # - asset: fonts/TrajanPro.ttf
71 | # - asset: fonts/TrajanPro_Bold.ttf
72 | # weight: 700
73 | #
74 | # For details regarding fonts from package dependencies,
75 | # see https://flutter.io/custom-fonts/#from-packages
76 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .vagrant/
3 | .sconsign.dblite
4 | .svn/
5 |
6 | .DS_Store
7 | *.swp
8 | profile
9 |
10 | DerivedData/
11 | build/
12 | GeneratedPluginRegistrant.h
13 | GeneratedPluginRegistrant.m
14 |
15 | .generated/
16 |
17 | *.pbxuser
18 | *.mode1v3
19 | *.mode2v3
20 | *.perspectivev3
21 |
22 | !default.pbxuser
23 | !default.mode1v3
24 | !default.mode2v3
25 | !default.perspectivev3
26 |
27 | xcuserdata
28 |
29 | *.moved-aside
30 |
31 | *.pyc
32 | *sync/
33 | Icon?
34 | .tags*
35 |
36 | /Flutter/Generated.xcconfig
37 |
--------------------------------------------------------------------------------
/ios/Assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jpush/jmessage-flutter-plugin/f19f8a0f7f1068362a0098314b22a1d6883ff2a5/ios/Assets/.gitkeep
--------------------------------------------------------------------------------
/ios/Classes/JMessageHelper.h:
--------------------------------------------------------------------------------
1 | // __ __ ________
2 | // | | | | \ \ / / | | | | / _______|
3 | // | |____| | \ \/ / | |____| | / /
4 | // | |____| | \ / | |____| | | | _____
5 | // | | | | / \ | | | | | | |____ |
6 | // | | | | / /\ \ | | | | \ \______| |
7 | // | | | | /_/ \_\ | | | | \_________|
8 | //
9 | // Copyright (c) 2012年 HXHG. All rights reserved.
10 | // http://www.jpush.cn
11 | // Created by liangjianguo
12 | //
13 |
14 |
15 | #import
16 | #import
17 |
18 | //static NSString *JMessageAppKey;
19 |
20 | @interface JMessageHelper : NSObject
21 | @property(nonatomic, strong)NSString *JMessageAppKey;
22 | @property(strong,nonatomic)NSDictionary *launchOptions;
23 | + (JMessageHelper *)shareInstance;
24 |
25 | @end
26 |
27 |
28 | @interface NSArray (JMessage)
29 | - (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block;
30 | @end
31 |
32 | @interface NSDictionary (JMessage)
33 | -(NSString*)toJsonString;
34 | @end
35 |
36 | @interface NSString (JMessage)
37 | -(NSDictionary*)toDictionary;
38 | @end
39 |
40 | @interface JMSGConversation (JMessage)
41 | -(NSMutableDictionary*)conversationToDictionary;
42 | @end
43 |
44 | @interface JMSGUser (JMessage)
45 | -(NSMutableDictionary*)userToDictionary;
46 | @end
47 |
48 | @interface JMSGGroup (JMessage)
49 | -(NSMutableDictionary*)groupToDictionary;
50 | @end
51 |
52 | @interface JMSGGroupMemberInfo (JMessage)
53 | - (NSMutableDictionary *)memberToDictionary;
54 | @end
55 |
56 | @interface JMSGGroupInfo (JMessage)
57 | -(NSMutableDictionary*)groupToDictionary;
58 | @end
59 |
60 | @interface JMSGMessage (JMessage)
61 | - (NSMutableDictionary *)messageToDictionary;
62 | @end
63 |
64 | @interface JMSGChatRoom (JMessage)
65 | - (NSMutableDictionary *)chatRoomToDictionary;
66 | @end
67 |
68 | @interface JMSGApplyJoinGroupEvent (JMessage)
69 | - (NSMutableDictionary *)eventToDictionary;
70 | @end
71 |
72 | @interface JMSGGroupAdminRejectApplicationEvent (JMessage)
73 | - (NSMutableDictionary *)eventToDictionary;
74 | @end
75 |
76 | @interface JMSGGroupAdminApprovalEvent (JMessage)
77 | - (NSMutableDictionary *)eventToDictionary;
78 | @end
79 |
80 | @interface JMSGGroupNicknameChangeEvent (JMessage)
81 | - (NSMutableDictionary *)eventToDictionary;
82 | @end
83 |
84 |
--------------------------------------------------------------------------------
/ios/Classes/JMessageHelper.m:
--------------------------------------------------------------------------------
1 | // __ __ ________
2 | // | | | | \ \ / / | | | | / _______|
3 | // | |____| | \ \/ / | |____| | / /
4 | // | |____| | \ / | |____| | | | _____
5 | // | | | | / \ | | | | | | |____ |
6 | // | | | | / /\ \ | | | | \ \______| |
7 | // | | | | /_/ \_\ | | | | \_________|
8 | //
9 | // Copyright (c) 2012年 HXHG. All rights reserved.
10 | // http://www.jpush.cn
11 | // Created by liangjianguo
12 | //
13 |
14 |
15 | #import "JMessageHelper.h"
16 | #ifdef NSFoundationVersionNumber_iOS_9_x_Max
17 | #import
18 | #endif
19 | @interface JMessageHelper ()
20 | @end
21 |
22 | @implementation JMessageHelper
23 |
24 | + (JMessageHelper *)shareInstance {
25 | static JMessageHelper *instance = nil;
26 | static dispatch_once_t onceToken;
27 | dispatch_once(&onceToken, ^{
28 | instance = [[JMessageHelper alloc] init];
29 | });
30 | return instance;
31 | }
32 | @end
33 |
34 |
35 | #pragma mark - category
36 |
37 | @implementation NSDictionary (JPush)
38 | -(NSString*)toJsonString{
39 | NSError *error;
40 | NSData *data = [NSJSONSerialization dataWithJSONObject:self options:0 error:&error];
41 | NSString *jsonString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
42 | return jsonString;
43 | }
44 | @end
45 |
46 | @implementation NSString (JPush)
47 | -(NSMutableDictionary*)toDictionary{
48 | NSError *error;
49 | NSData *jsonData = [self dataUsingEncoding:NSUTF8StringEncoding];
50 | NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
51 | return dict;
52 | }
53 | @end
54 |
55 | @implementation JMSGConversation (JMessage)
56 | -(NSMutableDictionary*)conversationToDictionary{
57 | NSMutableDictionary *dict = [NSMutableDictionary dictionary];
58 |
59 | switch (self.conversationType) {
60 | case kJMSGConversationTypeSingle:{
61 | JMSGUser *user = self.target;
62 | dict[@"target"] = [user userToDictionary];
63 | dict[@"conversationType"] = @"single";
64 | break;
65 | }
66 |
67 | case kJMSGConversationTypeGroup:{
68 | JMSGGroup *group = self.target;
69 | dict[@"target"] = [group groupToDictionary];
70 | dict[@"conversationType"] = @"group";
71 | break;
72 | }
73 | case kJMSGConversationTypeChatRoom:{
74 | JMSGChatRoom *chatroom = self.target;
75 | dict[@"target"] = [chatroom chatRoomToDictionary];
76 | dict[@"conversationType"] = @"chatRoom";
77 | break;
78 | }
79 | }
80 |
81 | if (self.latestMessage) {
82 | dict[@"latestMessage"] = [self.latestMessage messageToDictionary];
83 | }
84 |
85 | dict[@"unreadCount"] = self.unreadCount ?: @(0);
86 | dict[@"title"] = [self title] ?: @"";
87 | dict[@"extras"] = [self getConversationExtras] ?: @{};
88 | return dict;
89 | }
90 |
91 |
92 | @end
93 |
94 | @implementation JMSGUser (JMessage)
95 | -(NSMutableDictionary*)userToDictionary{
96 | NSMutableDictionary *dict = [NSMutableDictionary dictionary];
97 | dict[@"type"] = @"user";
98 | dict[@"username"] = self.username ?: @"";
99 | dict[@"nickname"] = self.nickname ?: @"";
100 | dict[@"birthday"] = self.birthday ?: @"";
101 | dict[@"region"] = self.region ?: @"";
102 | dict[@"signature"] = self.signature ?: @"";
103 | dict[@"address"] = [self address] ?: @"";
104 | dict[@"noteName"] = self.noteName ?: @"";
105 | dict[@"noteText"] = self.noteText ?: @"";
106 | dict[@"appKey"] = self.appKey ?: @"";
107 | dict[@"isNoDisturb"] = @(self.isNoDisturb);
108 | dict[@"isInBlackList"] = @(self.isInBlacklist);
109 | dict[@"isFriend"] = @(self.isFriend);
110 | dict[@"extras"] = self.extras ?: @{};
111 |
112 | if([[NSFileManager defaultManager] fileExistsAtPath: [self thumbAvatarLocalPath] ?: @""]){
113 | dict[@"avatarThumbPath"] = [self thumbAvatarLocalPath];
114 | } else {
115 | dict[@"avatarThumbPath"] = @"";
116 | }
117 |
118 | switch (self.gender) {
119 | case kJMSGUserGenderUnknown:
120 | dict[@"gender"] = @"unknown";
121 | break;
122 | case kJMSGUserGenderFemale:
123 | dict[@"gender"] = @"female";
124 | break;
125 | case kJMSGUserGenderMale:
126 | dict[@"gender"] = @"male";
127 | break;
128 | default:
129 | break;
130 | }
131 | return dict;
132 | }
133 |
134 | - (NSString *)getLargeAvatarFilePath {
135 | NSString *avatarPath = [self largeAvatarLocalPath];
136 | if([[NSFileManager defaultManager] fileExistsAtPath: avatarPath]){
137 | return avatarPath;
138 | } else {
139 | return @"";
140 | }
141 | }
142 | @end
143 |
144 | @implementation JMSGGroup (JMessage)
145 | -(NSMutableDictionary*)groupToDictionary {
146 | NSMutableDictionary *dict = [NSMutableDictionary dictionary];
147 | dict[@"type"] = @"group";
148 | dict[@"id"] = self.gid;
149 | dict[@"name"] = self.name ?: @"";
150 | dict[@"desc"] = self.desc ?: @"";
151 | dict[@"level"] = self.level;
152 | dict[@"flag"] = self.flag;
153 | dict[@"owner"] = self.owner;
154 | dict[@"ownerAppKey"] = self.ownerAppKey;
155 | dict[@"maxMemberCount"] = @([self.maxMemberCount integerValue]);
156 | dict[@"isNoDisturb"] = @(self.isNoDisturb);
157 | dict[@"isBlocked"] = @(self.isShieldMessage);
158 | dict[@"displayName"] = self.displayName;
159 |
160 | switch (self.groupType) {
161 | case kJMSGGroupTypePublic:
162 | dict[@"groupType"] = @"public";
163 | break;
164 |
165 | default:
166 | dict[@"groupType"] = @"private";
167 | break;
168 | }
169 | return dict;
170 | }
171 | @end
172 |
173 |
174 | @implementation JMSGGroupMemberInfo (JMessage)
175 | - (NSMutableDictionary *)memberToDictionary {
176 | NSMutableDictionary *dict = [NSMutableDictionary dictionary];
177 | dict[@"user"] = [self.user userToDictionary];
178 | dict[@"groupNickname"] = [self displayName] ? : @"";
179 |
180 | switch (self.memberType) {
181 | case kJMSGGroupMemberTypeOrdinary:
182 | dict[@"memberType"] = @"ordinary";
183 | break;
184 | case kJMSGGroupMemberTypeOwner:
185 |
186 | break;
187 | case kJMSGGroupMemberTypeAdmin:
188 | dict[@"memberType"] = @"admin";
189 | break;
190 | }
191 | dict[@"joinGroupTime"] = @(self.ctime);
192 | return dict;
193 | }
194 | @end
195 |
196 | @implementation JMSGGroupInfo (JMessage)
197 | -(NSMutableDictionary*)groupToDictionary {
198 | NSMutableDictionary *dict = [NSMutableDictionary dictionary];
199 | dict[@"id"] = self.gid;
200 | dict[@"name"] = self.name;
201 | dict[@"desc"] = self.desc;
202 | dict[@"maxMemberCount"] = @([self.maxMemberCount integerValue]);
203 | switch (self.groupType) {
204 | case kJMSGGroupTypePublic:
205 | dict[@"groupType"] = @"public";
206 | break;
207 |
208 | default:
209 | dict[@"groupType"] = @"private";
210 | break;
211 | }
212 | return dict;
213 | }
214 | @end
215 |
216 | @implementation JMSGMessage (JMessage)
217 |
218 | - (NSMutableDictionary *)messageToDictionary {
219 | NSMutableDictionary *dict = [NSMutableDictionary new];
220 |
221 | dict[@"id"] = self.msgId; // 本地数据库中的消息 Id。
222 | dict[@"serverMessageId"] = self.serverMessageId; // 服务器端对应的消息 Id。
223 | dict[@"from"] = [self.fromUser userToDictionary];
224 |
225 | switch (self.status) {
226 | case kJMSGMessageStatusSendDraft:
227 | dict[@"state"] = @"draft";
228 | break;
229 | case kJMSGMessageStatusSending:
230 | dict[@"state"] = @"sending";
231 | break;
232 | case kJMSGMessageStatusSendSucceed:
233 | dict[@"state"] = @"send_succeed";
234 | break;
235 | case kJMSGMessageStatusReceiving:
236 | dict[@"state"] = @"receiving";
237 | break;
238 | case kJMSGMessageStatusSendFailed:
239 | dict[@"state"] = @"send_failed";
240 | break;
241 | case kJMSGMessageStatusReceiveDownloadFailed:
242 | dict[@"state"] = @"download_failed";
243 | break;
244 | case kJMSGMessageStatusSendUploadSucceed:
245 | dict[@"state"] = @"upload_succeed";
246 | break;
247 | case kJMSGMessageStatusReceiveSucceed:
248 | dict[@"state"] = @"received";
249 | break;
250 | case kJMSGMessageStatusSendUploadFailed:
251 | dict[@"state"] = @"upload_failed";
252 | break;
253 | default:
254 | dict[@"state"] = @"send_succeed";
255 | break;
256 | }
257 |
258 | if (self.content.extras != nil) {
259 | dict[@"extras"] = self.content.extras;
260 | }
261 |
262 | dict[@"isSend"] = [NSNumber numberWithBool: !self.isReceived];
263 | switch (self.targetType) {
264 | case kJMSGConversationTypeSingle:{
265 | JMSGUser *user = self.target;
266 | dict[@"target"] = [user userToDictionary];
267 | break;
268 | }
269 | case kJMSGConversationTypeGroup:{
270 | JMSGGroup *group = self.target;
271 | dict[@"target"] = [group groupToDictionary];
272 | break;
273 | }
274 | case kJMSGConversationTypeChatRoom:{
275 | JMSGChatRoom *chatroom = self.target;
276 | dict[@"target"] = [chatroom chatRoomToDictionary];
277 | break;
278 | }
279 | }
280 |
281 | dict[@"createTime"] = self.timestamp;
282 |
283 | switch (self.contentType) {
284 | case kJMSGContentTypeUnknown: {
285 | dict[@"type"] = @"unknown";
286 | break;
287 | }
288 | case kJMSGContentTypeText: {
289 | dict[@"type"] = @"text";
290 | JMSGTextContent *textContent = (JMSGTextContent *) self.content;
291 | dict[@"text"] = textContent.text;
292 | break;
293 | }
294 | case kJMSGContentTypeImage: {
295 | dict[@"type"] = @"image";
296 | JMSGImageContent *imageContent = (JMSGImageContent *) self.content;
297 | dict[@"thumbPath"] = [imageContent thumbImageLocalPath];
298 | break;
299 | }
300 | case kJMSGContentTypeVoice: {
301 | dict[@"type"] = @"voice";
302 | dict[@"path"] = [self getOriginMediaFilePath];
303 | JMSGVoiceContent *voiceContent = (JMSGVoiceContent *) self.content;
304 | dict[@"duration"] = [voiceContent duration];
305 | break;
306 | }
307 | case kJMSGContentTypeCustom: {
308 | dict[@"type"] = @"custom";
309 | JMSGCustomContent *customContent = (JMSGCustomContent *) self.content;
310 | dict[@"customObject"] = customContent.customDictionary;
311 | break;
312 | }
313 | case kJMSGContentTypeEventNotification: {
314 | dict[@"type"] = @"event";
315 | JMSGEventContent *eventContent = (JMSGEventContent *) self.content;
316 |
317 | NSArray *userArr = [eventContent getEventToUsernameList];
318 | dict[@"usernames"] = userArr;
319 | dict[@"nicknames"] = userArr;
320 |
321 | switch (eventContent.eventType) {
322 | case kJMSGEventNotificationAcceptedFriendInvitation: {
323 | dict[@"eventType"] = @"acceptedFriendInvitation";
324 | break;
325 | }
326 | case kJMSGEventNotificationAddGroupMembers: {
327 | dict[@"eventType"] = @"group_member_added";
328 | break;
329 | }
330 | case kJMSGEventNotificationCreateGroup: {
331 | dict[@"eventType"] = @"createGroup";
332 | break;
333 | }
334 | case kJMSGEventNotificationCurrentUserInfoChange: {
335 | dict[@"eventType"] = @"currentUserInfoChange";
336 | break;
337 | }
338 | case kJMSGEventNotificationDeclinedFriendInvitation: {
339 | dict[@"eventType"] = @"declinedFriendInvitation";
340 | break;
341 | }
342 | case kJMSGEventNotificationDeletedFriend: {
343 | dict[@"eventType"] = @"deletedFriend";
344 | break;
345 | }
346 | case kJMSGEventNotificationExitGroup: {
347 | dict[@"eventType"] = @"group_member_exit";
348 | break;
349 | }
350 | case kJMSGEventNotificationLoginKicked: {
351 | dict[@"eventType"] = @"loginKicked";
352 | break;
353 | }
354 | case kJMSGEventNotificationMessageRetract: {
355 | dict[@"eventType"] = @"messageRetract";
356 | break;
357 | }
358 | case kJMSGEventNotificationReceiveFriendInvitation: {
359 | dict[@"eventType"] = @"receiveFriendInvitation";
360 | break;
361 | }
362 | case kJMSGEventNotificationReceiveServerFriendUpdate: {
363 | dict[@"eventType"] = @"receiveServerFriendUpdate";
364 | break;
365 | }
366 | case kJMSGEventNotificationRemoveGroupMembers: {
367 | dict[@"eventType"] = @"group_member_removed";
368 | break;
369 | }
370 | case kJMSGEventNotificationServerAlterPassword: {
371 | dict[@"eventType"] = @"serverAlterPassword";
372 | break;
373 | }
374 | case kJMSGEventNotificationUpdateGroupInfo: {
375 | dict[@"eventType"] = @"group_info_updated";
376 | break;
377 | }
378 | case kJMSGEventNotificationUserLoginStatusUnexpected: {
379 | dict[@"eventType"] = @"userLoginStatusUnexpected";
380 | break;
381 | }
382 | case kJMSGEventNotificationGroupTypeChange: {
383 | dict[@"eventType"] = @"group_type_changed";
384 | break;
385 | }
386 | case kJMSGEventNotificationDissolveGroup: {
387 | dict[@"eventType"] = @"group_dissolved";
388 | break;
389 | }
390 | default:
391 | break;
392 | }
393 | break;
394 | }
395 | case kJMSGContentTypeFile: {
396 | dict[@"type"] = @"file";
397 | JMSGFileContent *fileContent = (JMSGFileContent *) self.content;
398 | dict[@"fileName"] = [fileContent fileName];
399 | break;
400 | }
401 | case kJMSGContentTypeLocation: {
402 | dict[@"type"] = @"location";
403 | JMSGLocationContent *locationContent = (JMSGLocationContent *) self.content;
404 | dict[@"latitude"] = @([locationContent.latitude doubleValue]);
405 | dict[@"longitude"] = @([locationContent.longitude doubleValue]);
406 | dict[@"scale"] = @([locationContent.scale intValue]);
407 | dict[@"address"] = locationContent.address;
408 | break;
409 | }
410 | case kJMSGContentTypePrompt: {
411 | dict[@"type"] = @"prompt";
412 | JMSGPromptContent *promptContent = (JMSGPromptContent *) self.content;
413 | dict[@"promptText"] = promptContent.promptText;
414 | break;
415 | }
416 | default:
417 | break;
418 | }
419 | return dict;
420 | }
421 |
422 | - (NSString *)getOriginMediaFilePath {
423 | JMSGMediaAbstractContent *content = (JMSGMediaAbstractContent *) self.content;
424 | NSString *mediaPath = [content originMediaLocalPath];
425 | if([[NSFileManager defaultManager] fileExistsAtPath:mediaPath]){
426 | return mediaPath;
427 | } else {
428 | return @"";
429 | }
430 | }
431 |
432 | - (NSString *)getFullPathWith:(NSString *) path {
433 | NSString * homeDir = NSHomeDirectory();
434 | return [NSString stringWithFormat:@"%@/Documents/%@", homeDir,path];
435 | }
436 | @end
437 |
438 | @implementation JMSGChatRoom (JMessage)
439 | - (NSMutableDictionary *)chatRoomToDictionary {
440 | NSMutableDictionary *dict = @{}.mutableCopy;
441 | dict[@"type"] = @"chatRoom";
442 | dict[@"roomId"] = self.roomID;
443 | dict[@"name"] = self.name;
444 | dict[@"appKey"] = self.appkey;
445 | dict[@"description"] = self.description;
446 | dict[@"createTime"] = self.ctime;
447 | dict[@"maxMemberCount"] = @([self.maxMemberCount integerValue]);
448 | dict[@"memberCount"] = @(self.totalMemberCount);
449 |
450 | return dict;
451 | }
452 | @end
453 |
454 |
455 |
456 | @implementation NSArray (JMessage)
457 |
458 | - (NSArray *)mapObjectsUsingBlock:(id (^)(id obj, NSUInteger idx))block {
459 | NSMutableArray *result = [NSMutableArray arrayWithCapacity:[self count]];
460 | [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
461 | [result addObject:block(obj, idx)];
462 | }];
463 | return result;
464 | }
465 |
466 | @end
467 |
468 | @implementation JMSGApplyJoinGroupEvent (JMessage)
469 | - (NSMutableDictionary *)eventToDictionary {
470 | NSMutableDictionary *dict = @{}.mutableCopy;
471 |
472 | dict[@"eventId"] = self.eventID;
473 | dict[@"groupId"] = self.groupID;
474 | dict[@"isInitiativeApply"] = @(self.isInitiativeApply);
475 | dict[@"sendApplyUser"] = self.sendApplyUser != nil ? @{} : [self.sendApplyUser userToDictionary];
476 | if (self.joinGroupUsers != nil) {
477 | NSArray *userDicArr = [self.joinGroupUsers mapObjectsUsingBlock:^id(id obj, NSUInteger idx) {
478 | JMSGUser *user = obj;
479 | return [user userToDictionary];
480 | }];
481 | dict[@"joinGroupUsers"] = userDicArr;
482 | }
483 | dict[@"reason"] = self.reason;
484 | return dict;
485 | }
486 | @end
487 |
488 |
489 | @implementation JMSGGroupAdminRejectApplicationEvent (JMessage)
490 | - (NSMutableDictionary *)eventToDictionary {
491 | NSMutableDictionary *dict = @{}.mutableCopy;
492 | dict[@"groupId"] = self.groupID;
493 | dict[@"reason"] = self.rejectReason;
494 | dict[@"groupManager"] = [self.groupManager userToDictionary];
495 | return dict;
496 | }
497 | @end
498 |
499 | @implementation JMSGGroupAdminApprovalEvent (JMessage)
500 | - (NSMutableDictionary *)eventToDictionary {
501 | NSMutableDictionary *dict = @{}.mutableCopy;
502 | dict[@"isAgree"] = @(self.isAgreeApply);
503 | dict[@"applyEventId"] = self.applyEventID;
504 | dict[@"groupId"] = self.groupID;
505 | dict[@"groupAdmin"] = [self.groupAdmin userToDictionary];
506 |
507 | if (self.users != nil) {
508 | NSArray *userDicArr = [self.users mapObjectsUsingBlock:^id(id obj, NSUInteger idx) {
509 | JMSGUser *user = obj;
510 | return [user userToDictionary];
511 | }];
512 | dict[@"users"] = userDicArr;
513 | }
514 | return dict;
515 | }
516 | @end
517 |
518 | @implementation JMSGGroupNicknameChangeEvent (JMessage)
519 | - (NSMutableDictionary *)eventToDictionary {
520 | NSMutableDictionary *dict = @{}.mutableCopy;
521 | dict[@"group"] = [self.group groupToDictionary];
522 | dict[@"fromMemberInfo"] = [self.fromMemberInfo memberToDictionary];
523 | dict[@"toMemberInfo"] = [self.toMemberInfo memberToDictionary];
524 | dict[@"ctime"] = @(self.ctime);
525 | return dict;
526 | }
527 | @end
528 |
--------------------------------------------------------------------------------
/ios/Classes/JmessageFlutterPlugin.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface JmessageFlutterPlugin : NSObject
5 | @property NSString *JMessageAppKey;
6 | @property NSDictionary *launchOptions;
7 | @property FlutterMethodChannel *channel;
8 | @end
9 |
--------------------------------------------------------------------------------
/ios/jmessage_flutter.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
3 | #
4 | Pod::Spec.new do |s|
5 | s.name = 'jmessage_flutter'
6 | s.version = '0.0.1'
7 | s.summary = 'A new flutter plugin project.'
8 | s.description = <<-DESC
9 | A new flutter plugin project.
10 | DESC
11 | s.homepage = 'http://example.com'
12 | s.license = { :file => '../LICENSE' }
13 | s.author = { 'Your Company' => 'email@example.com' }
14 | s.source = { :path => '.' }
15 | s.source_files = 'Classes/**/*'
16 | s.public_header_files = 'Classes/**/*.h'
17 | s.dependency 'Flutter'
18 | s.dependency 'JMessage'
19 | s.ios.deployment_target = '8.0'
20 | s.static_framework = true
21 | end
22 |
23 |
--------------------------------------------------------------------------------
/jmessage_flutter.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/jmessage_flutter_android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: jmessage_flutter
2 | description: JIGUANG officially supported JMessage Flutter plugin (Android & iOS). 极光推送官方支持的 Flutter 插件(Android & iOS)(https://www.jiguang.cn).
3 | version: 2.2.1
4 | homepage: https://www.jiguang.cn
5 |
6 | environment:
7 | sdk: ">=2.12.0 <3.0.0"
8 | flutter: ">=1.20.0"
9 |
10 | dependencies:
11 | platform: ^3.0.0
12 | flutter:
13 | sdk: flutter
14 |
15 | # For information on the generic Dart part of this file, see the
16 | # following page: https://www.dartlang.org/tools/pub/pubspec
17 |
18 | # The following section is specific to Flutter.
19 | flutter:
20 | plugin:
21 | platforms:
22 | android:
23 | package: com.jiguang.jmessageflutter
24 | pluginClass: JmessageFlutterPlugin
25 | ios:
26 | pluginClass: JmessageFlutterPlugin
27 |
28 | # To add assets to your plugin package, add an assets section, like this:
29 | # assets:
30 | # - images/a_dot_burr.jpeg
31 | # - images/a_dot_ham.jpeg
32 | #
33 | # For details regarding assets in packages, see
34 | # https://flutter.io/assets-and-images/#from-packages
35 | #
36 | # An image asset can refer to one or more resolution-specific "variants", see
37 | # https://flutter.io/assets-and-images/#resolution-aware.
38 |
39 | # To add custom fonts to your plugin package, add a fonts section here,
40 | # in this "flutter" section. Each entry in this list should have a
41 | # "family" key with the font family name, and a "fonts" key with a
42 | # list giving the asset and other descriptors for the font. For
43 | # example:
44 | # fonts:
45 | # - family: Schyler
46 | # fonts:
47 | # - asset: fonts/Schyler-Regular.ttf
48 | # - asset: fonts/Schyler-Italic.ttf
49 | # style: italic
50 | # - family: Trajan Pro
51 | # fonts:
52 | # - asset: fonts/TrajanPro.ttf
53 | # - asset: fonts/TrajanPro_Bold.ttf
54 | # weight: 700
55 | #
56 | # For details regarding fonts in packages, see
57 | # https://flutter.io/custom-fonts/#from-packages
58 |
--------------------------------------------------------------------------------