├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── android ├── .gitignore ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── libs │ └── open_sdk_r6019_lite.jar ├── settings.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── github │ └── marekchen │ └── flutterqq │ └── FlutterQqPlugin.java ├── example ├── .gitignore ├── .metadata ├── README.md ├── android │ ├── .gitignore │ ├── app │ │ ├── build.gradle │ │ ├── debug.keystore │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── github │ │ │ │ └── marekchen │ │ │ │ └── flutterqqexample │ │ │ │ └── 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 │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── flutter_qq_example.iml ├── flutter_qq_example_android.iml ├── ios │ ├── .gitignore │ ├── Flutter │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ └── Release.xcconfig │ ├── Podfile │ ├── Podfile.lock │ ├── Runner.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── 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 │ │ └── main.m ├── lib │ └── main.dart ├── pubspec.yaml └── test │ └── widget_test.dart ├── flutter_qq.iml ├── flutter_qq_android.iml ├── ios ├── .gitignore ├── Assets │ └── .gitkeep ├── Classes │ ├── FlutterQqPlugin.h │ └── FlutterQqPlugin.m └── flutter_qq.podspec ├── lib └── flutter_qq.dart └── pubspec.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | pubspec.lock 7 | .idea 8 | 9 | build/ 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.0.5] - 2019.7.11. 2 | 3 | * **Breaking change**. Migrate from the deprecated original Android Support 4 | Library to AndroidX. This shouldn't result in any functional changes, but it 5 | requires any Android apps using this plugin to [also 6 | migrate](https://developer.android.com/jetpack/androidx/migrate) if they're 7 | using the original support library. 8 | * update qq android sdk 9 | 10 | ## [0.0.4] - 2018.8.6. 11 | 12 | * fix bug 13 | 14 | ## [0.0.3] - 2018.8.6. 15 | 16 | * fix bug 17 | 18 | ## [0.0.2] - 2018.8.6. 19 | 20 | * support ios 21 | * complete doc 22 | 23 | ## [0.0.1] - 2018.5.28. 24 | 25 | * support android 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flutter_qq 2 | # [DEPRECATED] 3 | 4 | Flutter plugin for QQ. 5 | 6 | ## Getting Started 7 | ### android 8 | 1. Add the following to your project's AndroidManifest.xml and replace [QQ APPId] with your own QQ AppId 9 | ``` xml 10 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | ``` 27 | 28 | ### iOS 29 | 1. Add the followings to your project's Info.plist 30 | ``` xml 31 | CFBundleURLTypes 32 | 33 | 34 | CFBundleTypeRole 35 | Editor 36 | CFBundleURLName 37 | tencent 38 | CFBundleURLSchemes 39 | 40 | tencent1107493622 41 | 42 | 43 | 44 | LSApplicationQueriesSchemes 45 | 46 | mqq 47 | mqqapi 48 | mqqwpa 49 | mqqbrowser 50 | mttbrowser 51 | mqqOpensdkSSoLogin 52 | mqqopensdkapiV2 53 | mqqopensdkapiV3 54 | mqqopensdkapiV4 55 | wtloginmqq2 56 | mqzone 57 | mqzoneopensdk 58 | mqzoneopensdkapi 59 | mqzoneopensdkapi19 60 | mqzoneopensdkapiV2 61 | mqqapiwallet 62 | mqqopensdkfriend 63 | mqqopensdkdataline 64 | mqqgamebindinggroup 65 | mqqopensdkgrouptribeshare 66 | tencentapi.qq.reqContent 67 | tencentapi.qzone.reqContent 68 | 69 | NSMicrophoneUsageDescription 70 | microphoneUsageDescription 71 | NSPhotoLibraryUsageDescription 72 | photoLibraryDesciption 73 | NSCameraUsageDescription 74 | cameraUsageDesciption 75 | LSRequiresIPhoneOS 76 | 77 | UIBackgroundModes 78 | 79 | fetch 80 | remote-notification 81 | 82 | ``` 83 | 84 | 2. Add the followings to your project's AppDelegate.m 85 | ``` objective-c 86 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url 87 | options:(NSDictionary *)options 88 | { 89 | NSString * urlStr = [url absoluteString]; 90 | [[NSNotificationCenter defaultCenter] 91 | postNotificationName:@"QQ" object:nil userInfo:@{@"url":urlStr}]; 92 | return YES; 93 | } 94 | ``` 95 | 96 | ## Not Complete 97 | 1. SHARE_TO_QQ_TYPE.AUDIO 98 | 2. SHARE_TO_QZONE_TYPE.PUBLISH_VIDEO 99 | 3. SHARE_TO_QQ_TYPE.APP & SHARE_TO_QZONE_TYPE.APP 100 | 4. SHARE_TO_QZONE_TYPE.IMAGE_TEXT,android & ios don't have same action 101 | 102 | ## Api Documentation 103 | ### Data struct 104 | 1. QQResult 105 | 106 | |field|type|description| 107 | |-----|----|-----------| 108 | |code|int|错误码 0:成功 1:发生错误 2:用户取消| 109 | |message|String|错误详情| 110 | |response|Map|只在login时返回| 111 | 112 | response格式为: 113 | ``` json 114 | { 115 | "openid":"xxxxx", 116 | "accessToken":"XXXXXXXXX", 117 | "expiresAt":"xxxxxxxxx", 118 | } 119 | ``` 120 | 121 | 2. QZONE_FLAG(enum) 122 | 123 | |field|description| 124 | |-----|-----------| 125 | |DEFAULT|默认| 126 | |AUTO_OPEN|在好友选择列表会自动打开分享到qzone的弹窗| 127 | |ITEM_HIDE|在好友选择列表隐藏了qzone分享选项| 128 | 129 | 3. SHARE_TO_QQ_TYPE(enum) 130 | 131 | |field|description| 132 | |-----|-----------| 133 | |DEFAULT|默认| 134 | |AUDIO|音频| 135 | |IMAGE|图片| 136 | |APP|应用| 137 | 138 | 4. SHARE_TO_QZONE_TYPE(enum) 139 | 140 | |field|description| 141 | |-----|-----------| 142 | |IMAGE_TEXT|默认| 143 | |PUBLISH_MOOD|说说| 144 | |PUBLISH_VIDEO|视频| 145 | |IMAGE|图片 **貌似QQ已不再支持,不建议使用,可以通过`shareToQQ`中设置`qzoneFlag`为`QZONE_FLAG.AUTO_OPEN`实现**| 146 | |APP|应用| 147 | 148 | 5. ShareQQContent 149 | 150 | |field|type|description| 151 | |-----|----|-----------| 152 | |shareType|SHARE_TO_QQ_TYPE|分享类型| 153 | |title|String|title| 154 | |targetUrl|String|targetUrl| 155 | |summary|String|summary| 156 | |imageUrl|String|imageUrl(shareType为IMAGE时,只支持imageLocalUrl)| 157 | |imageLocalUrl|String|imageLocalUrl| 158 | |appName|String|appName| 159 | |audioUrl|String|audioUrl(只有shareType为AUDIO时支持)| 160 | |qzoneFlag|QZONE_FLAG|qzone flag| 161 | 162 | 6. ShareQzoneContent 163 | 164 | |field|type|description| 165 | |-----|----|-----------| 166 | |shareType|SHARE_TO_QZONE_TYPE|分享类型| 167 | |title|String|title| 168 | |targetUrl|String|targetUrl| 169 | |summary|String|summary| 170 | |imageUrls|List|imageUrl| 171 | |scene|String|scene| 172 | |callback|String|callback| 173 | 174 | ### Method 175 | 1. registerQQ 176 | ``` dart 177 | FlutterQq.registerQQ('YOUR_QQ_APPId'); 178 | ``` 179 | 180 | 2. isQQInstalled 181 | ``` dart 182 | Future _handleisQQInstalled() async { 183 | var result = await FlutterQq.isQQInstalled(); 184 | var output; 185 | if (result) { 186 | output = "QQ已安装"; 187 | } else { 188 | output = "QQ未安装"; 189 | } 190 | setState(() { 191 | _output = output; 192 | }); 193 | } 194 | ``` 195 | 196 | 3. login 197 | ``` dart 198 | Future _handleLogin() async { 199 | try { 200 | var qqResult = await FlutterQq.login(); 201 | var output; 202 | if (qqResult.code == 0) { 203 | output = "登录成功" + qqResult.response.toString(); 204 | } else if (qqResult.code == 1) { 205 | output = "登录失败" + qqResult.message; 206 | } else { 207 | output = "用户取消"; 208 | } 209 | setState(() { 210 | _output = output; 211 | }); 212 | } catch (error) { 213 | print("flutter_plugin_qq_example:" + error.toString()); 214 | } 215 | } 216 | ``` 217 | 218 | 4. shareToQQ 219 | ``` dart 220 | Future _handleShareToQQ() async { 221 | ShareQQContent shareContent = new ShareQQContent( 222 | title: "测试title", 223 | targetUrl: "https://www.baidu.com", 224 | summary: "测试summary", 225 | imageUrl: "http://inews.gtimg.com/newsapp_bt/0/876781763/1000", 226 | ); 227 | try { 228 | var qqResult = await FlutterQq.shareToQQ(shareContent); 229 | var output; 230 | if (qqResult.code == 0) { 231 | output = "分享成功"; 232 | } else if (qqResult.code == 1) { 233 | output = "分享失败" + qqResult.message; 234 | } else { 235 | output = "用户取消"; 236 | } 237 | setState(() { 238 | _output = output; 239 | }); 240 | } catch (error) { 241 | print("flutter_plugin_qq_example:" + error.toString()); 242 | } 243 | } 244 | ``` 245 | 246 | 5. shareToQzone 247 | `shareToQzone`可以通过`shareToQQ`中设置`qzoneFlag`为`QZONE_FLAG.AUTO_OPEN`实现 248 | ``` dart 249 | Future _handleShareToQZone() async { 250 | ShareQzoneContent shareContent = new ShareQzoneContent( 251 | title: "测试title", 252 | targetUrl: "https://www.baidu.com", 253 | summary: "测试summary", 254 | imageUrl: "http://inews.gtimg.com/newsapp_bt/0/876781763/1000", // 或者本地图片地址 255 | ); 256 | try { 257 | var qqResult = await FlutterQq.shareToQzone(shareContent); 258 | var output; 259 | if (qqResult.code == 0) { 260 | output = "分享成功"; 261 | } else if (qqResult.code == 1) { 262 | output = "分享失败" + qqResult.message; 263 | } else { 264 | output = "用户取消"; 265 | } 266 | setState(() { 267 | _output = output; 268 | }); 269 | } catch (error) { 270 | print("flutter_plugin_qq_example:" + error.toString()); 271 | } 272 | } 273 | ``` 274 | 275 | ## How To Contribute 276 | ### android 277 | 1. add your own flutter.sdk path to local.properties 278 | ``` 279 | flutter.sdk=YOUR_OWN_FLUTTER_SDK_PATH 280 | ``` 281 | 282 | 2. PR 283 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .idea 5 | .DS_Store 6 | /build 7 | /captures 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | def PLUGIN = "flutter_qq" 2 | def ANDROIDX_WARNING = "flutterPluginsAndroidXWarning" 3 | gradle.buildFinished { buildResult -> 4 | if (buildResult.failure && !rootProject.ext.has(ANDROIDX_WARNING)) { 5 | println ' *********************************************************' 6 | println 'WARNING: This version of ' + PLUGIN + ' will break your Android build if it or its dependencies aren\'t compatible with AndroidX.' 7 | println ' See https://goo.gl/CP92wY for more information on the problem and how to fix it.' 8 | println ' This warning prints for all Android build failures. The real root cause of the error may be unrelated.' 9 | println ' *********************************************************' 10 | rootProject.ext.set(ANDROIDX_WARNING, true); 11 | } 12 | } 13 | 14 | group 'com.github.marekchen.flutterqq' 15 | version '1.0-SNAPSHOT' 16 | 17 | buildscript { 18 | repositories { 19 | google() 20 | jcenter() 21 | } 22 | 23 | dependencies { 24 | classpath 'com.android.tools.build:gradle:3.3.0' 25 | } 26 | } 27 | 28 | rootProject.allprojects { 29 | repositories { 30 | google() 31 | jcenter() 32 | } 33 | } 34 | 35 | apply plugin: 'com.android.library' 36 | 37 | android { 38 | compileSdkVersion 28 39 | 40 | defaultConfig { 41 | minSdkVersion 16 42 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 43 | } 44 | lintOptions { 45 | disable 'InvalidPackage' 46 | } 47 | } 48 | 49 | dependencies { 50 | implementation files('libs/open_sdk_r6019_lite.jar') 51 | api 'androidx.legacy:legacy-support-v4:1.0.0' 52 | } -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableJetifier=true 3 | android.useAndroidX=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat May 26 11:28:32 CST 2018 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 -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /android/libs/open_sdk_r6019_lite.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/android/libs/open_sdk_r6019_lite.jar -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'flutter_qq' 2 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /android/src/main/java/com/github/marekchen/flutterqq/FlutterQqPlugin.java: -------------------------------------------------------------------------------- 1 | package com.github.marekchen.flutterqq; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.Looper; 7 | import android.util.Log; 8 | 9 | import com.tencent.connect.common.Constants; 10 | import com.tencent.connect.share.QQShare; 11 | import com.tencent.connect.share.QzonePublish; 12 | import com.tencent.connect.share.QzoneShare; 13 | import com.tencent.tauth.IUiListener; 14 | import com.tencent.tauth.Tencent; 15 | import com.tencent.tauth.UiError; 16 | 17 | import org.json.JSONObject; 18 | 19 | import java.util.ArrayList; 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | 23 | import io.flutter.plugin.common.MethodCall; 24 | import io.flutter.plugin.common.MethodChannel; 25 | import io.flutter.plugin.common.MethodChannel.MethodCallHandler; 26 | import io.flutter.plugin.common.MethodChannel.Result; 27 | import io.flutter.plugin.common.PluginRegistry; 28 | import io.flutter.plugin.common.PluginRegistry.Registrar; 29 | 30 | /** 31 | * FlutterQqPlugin 32 | */ 33 | public class FlutterQqPlugin implements MethodCallHandler { 34 | 35 | private static Tencent mTencent; 36 | private Registrar registrar; 37 | private boolean isLogin; 38 | 39 | private FlutterQqPlugin(Registrar registrar) { 40 | this.registrar = registrar; 41 | } 42 | 43 | /** 44 | * Plugin registration. 45 | */ 46 | public static void registerWith(Registrar registrar) { 47 | final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_qq"); 48 | final FlutterQqPlugin instance = new FlutterQqPlugin(registrar); 49 | channel.setMethodCallHandler(instance); 50 | } 51 | 52 | @Override 53 | public void onMethodCall(MethodCall call, Result result) { 54 | registrar.addActivityResultListener(mListener); 55 | switch (call.method) { 56 | case "registerQQ": 57 | registerQQ(call, result); 58 | break; 59 | case "isQQInstalled": 60 | isQQInstalled(call, result); 61 | break; 62 | case "login": 63 | isLogin = true; 64 | mListener.setResult(result); 65 | login(call, mListener); 66 | break; 67 | case "shareToQQ": 68 | isLogin = false; 69 | mListener.setResult(result); 70 | doShareToQQ(call, mListener); 71 | break; 72 | case "shareToQzone": 73 | isLogin = false; 74 | mListener.setResult(result); 75 | doShareToQzone(call, mListener); 76 | break; 77 | } 78 | } 79 | 80 | private void registerQQ(MethodCall call, Result result) { 81 | String mAppid = call.argument("appId"); 82 | mTencent = Tencent.createInstance(mAppid, registrar.context()); 83 | result.success(true); 84 | } 85 | 86 | private void isQQInstalled(MethodCall call, Result result) { 87 | result.success(mTencent.isQQInstalled(registrar.activeContext())); 88 | } 89 | 90 | private void login(MethodCall call, final OneListener listener) { 91 | String scopes = (String) call.argument("scopes"); 92 | mTencent.login(registrar.activity(), scopes == null ? "get_simple_userinfo" : scopes, listener); 93 | } 94 | 95 | private void doShareToQQ(MethodCall call, final OneListener listener) { 96 | final Bundle params = new Bundle(); 97 | int shareType = call.argument("shareType"); 98 | Log.i("FlutterQqPlugin", "arguments:" + call.arguments); 99 | if (shareType != QQShare.SHARE_TO_QQ_TYPE_IMAGE) { 100 | params.putString(QQShare.SHARE_TO_QQ_TITLE, (String) call.argument("title")); 101 | params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, (String) call.argument("targetUrl")); 102 | params.putString(QQShare.SHARE_TO_QQ_SUMMARY, (String) call.argument("summary")); 103 | } 104 | if (shareType == QQShare.SHARE_TO_QQ_TYPE_IMAGE) { 105 | params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, (String) call.argument("imageLocalUrl")); 106 | } else { 107 | params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, (String) call.argument("imageUrl")); 108 | } 109 | params.putString(QQShare.SHARE_TO_QQ_APP_NAME, (String) call.argument("appName")); 110 | params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, shareType); 111 | params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, (Integer) call.argument("qzoneFlag")); 112 | if (shareType == QQShare.SHARE_TO_QQ_TYPE_AUDIO) { 113 | params.putString(QQShare.SHARE_TO_QQ_AUDIO_URL, (String) call.argument("audioUrl")); 114 | } 115 | params.putString(QQShare.SHARE_TO_QQ_ARK_INFO, (String) call.argument("ark")); 116 | Log.i("FlutterQqPlugin", "params:" + params); 117 | new Handler(Looper.getMainLooper()).post(new Runnable() { 118 | @Override 119 | public void run() { 120 | mTencent.shareToQQ(registrar.activity(), params, listener); 121 | } 122 | }); 123 | } 124 | 125 | private void doShareToQzone(MethodCall call, final OneListener listener) { 126 | final Bundle params = new Bundle(); 127 | int shareType = call.argument("shareType"); 128 | Log.i("FlutterQqPlugin", "arguments:" + call.arguments); 129 | params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE, shareType); 130 | params.putString(QzoneShare.SHARE_TO_QQ_TITLE, (String) call.argument("title")); 131 | params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, (String) call.argument("summary")); 132 | params.putString(QzoneShare.SHARE_TO_QQ_TARGET_URL, (String) call.argument("targetUrl")); 133 | ArrayList list = new ArrayList<>(); 134 | list.add((String) call.argument("imageUrl")); 135 | params.putStringArrayList(QQShare.SHARE_TO_QQ_IMAGE_URL, list); 136 | //params.putStringArrayList(QQShare.SHARE_TO_QQ_IMAGE_URL, (ArrayList) call.argument("imageUrls")); 137 | params.putString(QzonePublish.PUBLISH_TO_QZONE_VIDEO_PATH, (String) call.argument("videoPath")); 138 | Bundle bundle2 = new Bundle(); 139 | bundle2.putString(QzonePublish.HULIAN_EXTRA_SCENE, (String) call.argument("scene")); 140 | bundle2.putString(QzonePublish.HULIAN_CALL_BACK, (String) call.argument("hulian_call_back")); 141 | params.putBundle(QzonePublish.PUBLISH_TO_QZONE_EXTMAP, bundle2); 142 | Log.i("FlutterQqPlugin", "params:" + params); 143 | if (shareType == QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT) { 144 | new Handler(Looper.getMainLooper()).post(new Runnable() { 145 | @Override 146 | public void run() { 147 | mTencent.shareToQzone(registrar.activity(), params, listener); 148 | } 149 | }); 150 | } else { 151 | new Handler(Looper.getMainLooper()).post(new Runnable() { 152 | @Override 153 | public void run() { 154 | mTencent.publishToQzone(registrar.activity(), params, listener); 155 | } 156 | }); 157 | } 158 | } 159 | 160 | private final OneListener mListener = new OneListener(); 161 | 162 | private class OneListener implements IUiListener, PluginRegistry.ActivityResultListener { 163 | 164 | private Result result; 165 | 166 | void setResult(Result result) { 167 | this.result = result; 168 | } 169 | 170 | @Override 171 | public void onComplete(Object response) { 172 | Log.i("FlutterQqPlugin", response.toString()); 173 | Map re = new HashMap<>(); 174 | if (isLogin) { 175 | if (null == response) { 176 | re.put("Code", 1); 177 | re.put("Message", "response is empty"); 178 | result.success(re); 179 | return; 180 | } 181 | JSONObject jsonResponse = (JSONObject) response; 182 | if (null != jsonResponse && jsonResponse.length() == 0) { 183 | re.put("Code", 1); 184 | re.put("Message", "response is empty"); 185 | result.success(re); 186 | return; 187 | } 188 | Map resp = new HashMap<>(); 189 | try { 190 | Log.i("FlutterQqPlugin", resp.toString()); 191 | resp.put("openid", jsonResponse.getString(Constants.PARAM_OPEN_ID)); 192 | resp.put("accessToken", jsonResponse.getString(Constants.PARAM_ACCESS_TOKEN)); 193 | resp.put("expiresAt", jsonResponse.getLong(Constants.PARAM_EXPIRES_TIME)); 194 | // resp.put("appId", jsonResponse.getString(Constants.PARAM_APP_ID)); 195 | re.put("Code", 0); 196 | re.put("Message", "ok"); 197 | re.put("Response", resp); 198 | result.success(re); 199 | return; 200 | } catch (Exception e) { 201 | re.put("Code", 1); 202 | re.put("Message", e.getLocalizedMessage()); 203 | result.success(re); 204 | return; 205 | } 206 | } 207 | re.put("Code", 0); 208 | re.put("Message", response.toString()); 209 | result.success(re); 210 | } 211 | 212 | @Override 213 | public void onError(UiError uiError) { 214 | Log.w("FlutterQqPlugin", "errorCode:" + uiError.errorCode + ";errorMessage:" + uiError.errorMessage); 215 | Map re = new HashMap<>(); 216 | re.put("Code", 1); 217 | re.put("Message", "errorCode:" + uiError.errorCode + ";errorMessage:" + uiError.errorMessage); 218 | result.success(re); 219 | } 220 | 221 | @Override 222 | public void onCancel() { 223 | Log.w("FlutterQqPlugin", "error:cancel"); 224 | Map re = new HashMap<>(); 225 | re.put("Code", 2); 226 | re.put("Message", "cancel"); 227 | result.success(re); 228 | } 229 | 230 | @Override 231 | public boolean onActivityResult(int requestCode, int resultCode, Intent data) { 232 | if (requestCode == Constants.REQUEST_LOGIN || 233 | requestCode == Constants.REQUEST_QQ_SHARE || 234 | requestCode == Constants.REQUEST_QZONE_SHARE || 235 | requestCode == Constants.REQUEST_APPBAR) { 236 | Tencent.onActivityResultData(requestCode, resultCode, data, this); 237 | return true; 238 | } 239 | return false; 240 | } 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | 4 | .packages 5 | .pub/ 6 | 7 | build/ 8 | .idea 9 | 10 | .flutter-plugins 11 | -------------------------------------------------------------------------------- /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: f9bb4289e9fd861d70ae78bcc3a042ef1b35cc9d 8 | channel: beta 9 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # flutter_qq_example 2 | 3 | Demonstrates how to use the flutter_qq plugin. 4 | 5 | ## Getting Started 6 | 7 | For help getting started with Flutter, view our online 8 | [documentation](https://flutter.io/). 9 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | *.class 3 | .gradle 4 | /local.properties 5 | .idea 6 | .DS_Store 7 | /build 8 | /captures 9 | GeneratedPluginRegistrant.java 10 | -------------------------------------------------------------------------------- /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 | apply plugin: 'com.android.application' 15 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 16 | 17 | android { 18 | compileSdkVersion 28 19 | 20 | lintOptions { 21 | disable 'InvalidPackage' 22 | } 23 | 24 | defaultConfig { 25 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 26 | applicationId "com.droi.sdk.socialdemo" 27 | minSdkVersion 16 28 | targetSdkVersion 28 29 | versionCode 1 30 | versionName "1.0" 31 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 32 | } 33 | 34 | signingConfigs { 35 | debug { 36 | storeFile file('debug.keystore') 37 | storePassword "android" 38 | keyAlias "androiddebugkey" 39 | keyPassword "android" 40 | } 41 | release { 42 | storeFile file('debug.keystore') 43 | storePassword "android" 44 | keyAlias "androiddebugkey" 45 | keyPassword "android" 46 | } 47 | } 48 | 49 | buildTypes { 50 | release { 51 | // TODO: Add your own signing config for the release build. 52 | // Signing with the debug keys for now, so `flutter run --release` works. 53 | signingConfig signingConfigs.release 54 | } 55 | debug { 56 | // TODO: Add your own signing config for the release build. 57 | // Signing with the debug keys for now, so `flutter run --release` works. 58 | signingConfig signingConfigs.debug 59 | } 60 | } 61 | } 62 | 63 | flutter { 64 | source '../..' 65 | } 66 | 67 | dependencies { 68 | testImplementation 'junit:junit:4.12' 69 | androidTestImplementation 'androidx.test:runner:1.1.1' 70 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 71 | 72 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 73 | //implementation fileTree(include: '*.jar', dir: 'libs') 74 | } 75 | -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 31 | 32 | 35 | 36 | 37 | 40 | 41 | 48 | 52 | 55 | 56 | 57 | 58 | 59 | 60 | 65 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/github/marekchen/flutterqqexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.marekchen.flutterqqexample; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import io.flutter.embedding.android.FlutterActivity; 6 | import io.flutter.embedding.engine.FlutterEngine; 7 | import io.flutter.plugins.GeneratedPluginRegistrant; 8 | 9 | public class MainActivity extends FlutterActivity { 10 | @Override 11 | public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) { 12 | GeneratedPluginRegistrant.registerWith(flutterEngine); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.3.0' 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.enableJetifier=true 3 | android.useAndroidX=true 4 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 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 7 | -------------------------------------------------------------------------------- /example/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 | -------------------------------------------------------------------------------- /example/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 | -------------------------------------------------------------------------------- /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/flutter_qq_example.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /example/flutter_qq_example_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /example/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/app.flx 37 | /Flutter/app.zip 38 | /Flutter/flutter_assets/ 39 | /Flutter/App.framework 40 | /Flutter/Flutter.framework 41 | /Flutter/Generated.xcconfig 42 | /ServiceDefinitions.json 43 | 44 | Pods/ 45 | .symlinks/ 46 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | com.github.marekchen.flutterqqexample 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/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /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/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Flutter (1.0.0) 3 | - flutter_qq (0.0.5): 4 | - Flutter 5 | - QQSDK 6 | - image_picker (0.0.1): 7 | - Flutter 8 | - QQSDK (3.3.3) 9 | 10 | DEPENDENCIES: 11 | - Flutter (from `.symlinks/flutter/ios-release`) 12 | - flutter_qq (from `.symlinks/plugins/flutter_qq/ios`) 13 | - image_picker (from `.symlinks/plugins/image_picker/ios`) 14 | 15 | SPEC REPOS: 16 | https://github.com/cocoapods/specs.git: 17 | - QQSDK 18 | 19 | EXTERNAL SOURCES: 20 | Flutter: 21 | :path: ".symlinks/flutter/ios-release" 22 | flutter_qq: 23 | :path: ".symlinks/plugins/flutter_qq/ios" 24 | image_picker: 25 | :path: ".symlinks/plugins/image_picker/ios" 26 | 27 | SPEC CHECKSUMS: 28 | Flutter: 58dd7d1b27887414a370fcccb9e645c08ffd7a6a 29 | flutter_qq: fd560988a312c5c7c077f1f93980badf1de09eed 30 | image_picker: 16e5fec1fbc87fd3b297c53e4048521eaf17cd06 31 | QQSDK: 97a38fdbd3217626f0ef16321b67c4eb67e7bf9d 32 | 33 | PODFILE CHECKSUM: 1e5af4103afd21ca5ead147d7b81d06f494f51a2 34 | 35 | COCOAPODS: 1.7.3 36 | -------------------------------------------------------------------------------- /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 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 11 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 12 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 13 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 15 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 16 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 17 | 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; }; 18 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 19 | 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 20 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 21 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 22 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 23 | CC371D9BEF1A454ED72744D9 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A0E758DC7FE5DE1D25AD96B2 /* libPods-Runner.a */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXCopyFilesBuildPhase section */ 27 | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { 28 | isa = PBXCopyFilesBuildPhase; 29 | buildActionMask = 2147483647; 30 | dstPath = ""; 31 | dstSubfolderSpec = 10; 32 | files = ( 33 | 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 34 | 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, 35 | ); 36 | name = "Embed Frameworks"; 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXCopyFilesBuildPhase section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | 0EC5E6A320C9051EC6D300C2 /* 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 = ""; }; 43 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 44 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 45 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 46 | 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 47 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 48 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 51 | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 52 | 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 53 | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 55 | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 56 | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 57 | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 58 | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | A0E758DC7FE5DE1D25AD96B2 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | A7C5F3344501C0415CDC56EF /* 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 = ""; }; 61 | /* End PBXFileReference section */ 62 | 63 | /* Begin PBXFrameworksBuildPhase section */ 64 | 97C146EB1CF9000F007C117D /* Frameworks */ = { 65 | isa = PBXFrameworksBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 69 | 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, 70 | CC371D9BEF1A454ED72744D9 /* libPods-Runner.a in Frameworks */, 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | /* End PBXFrameworksBuildPhase section */ 75 | 76 | /* Begin PBXGroup section */ 77 | 0CCAE7C5C72907ADD1278AEE /* Pods */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | A7C5F3344501C0415CDC56EF /* Pods-Runner.debug.xcconfig */, 81 | 0EC5E6A320C9051EC6D300C2 /* Pods-Runner.release.xcconfig */, 82 | ); 83 | name = Pods; 84 | sourceTree = ""; 85 | }; 86 | 94655D31F6562D203B101719 /* Frameworks */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | A0E758DC7FE5DE1D25AD96B2 /* libPods-Runner.a */, 90 | ); 91 | name = Frameworks; 92 | sourceTree = ""; 93 | }; 94 | 9740EEB11CF90186004384FC /* Flutter */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 3B80C3931E831B6300D905FE /* App.framework */, 98 | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 99 | 9740EEBA1CF902C7004384FC /* Flutter.framework */, 100 | 9740EEB21CF90195004384FC /* Debug.xcconfig */, 101 | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 102 | 9740EEB31CF90195004384FC /* Generated.xcconfig */, 103 | ); 104 | name = Flutter; 105 | sourceTree = ""; 106 | }; 107 | 97C146E51CF9000F007C117D = { 108 | isa = PBXGroup; 109 | children = ( 110 | 9740EEB11CF90186004384FC /* Flutter */, 111 | 97C146F01CF9000F007C117D /* Runner */, 112 | 97C146EF1CF9000F007C117D /* Products */, 113 | 0CCAE7C5C72907ADD1278AEE /* Pods */, 114 | 94655D31F6562D203B101719 /* Frameworks */, 115 | ); 116 | sourceTree = ""; 117 | }; 118 | 97C146EF1CF9000F007C117D /* Products */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 97C146EE1CF9000F007C117D /* Runner.app */, 122 | ); 123 | name = Products; 124 | sourceTree = ""; 125 | }; 126 | 97C146F01CF9000F007C117D /* Runner */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 130 | 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 131 | 97C146FA1CF9000F007C117D /* Main.storyboard */, 132 | 97C146FD1CF9000F007C117D /* Assets.xcassets */, 133 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 134 | 97C147021CF9000F007C117D /* Info.plist */, 135 | 97C146F11CF9000F007C117D /* Supporting Files */, 136 | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 137 | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, 138 | ); 139 | path = Runner; 140 | sourceTree = ""; 141 | }; 142 | 97C146F11CF9000F007C117D /* Supporting Files */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | 97C146F21CF9000F007C117D /* main.m */, 146 | ); 147 | name = "Supporting Files"; 148 | sourceTree = ""; 149 | }; 150 | /* End PBXGroup section */ 151 | 152 | /* Begin PBXNativeTarget section */ 153 | 97C146ED1CF9000F007C117D /* Runner */ = { 154 | isa = PBXNativeTarget; 155 | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; 156 | buildPhases = ( 157 | 64F1E4791E29623DE60DBD7B /* [CP] Check Pods Manifest.lock */, 158 | 9740EEB61CF901F6004384FC /* Run Script */, 159 | 97C146EA1CF9000F007C117D /* Sources */, 160 | 97C146EB1CF9000F007C117D /* Frameworks */, 161 | 97C146EC1CF9000F007C117D /* Resources */, 162 | 9705A1C41CF9048500538489 /* Embed Frameworks */, 163 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 164 | 3D613EDE37FD2BDA1FAD0917 /* [CP] Embed Pods Frameworks */, 165 | ); 166 | buildRules = ( 167 | ); 168 | dependencies = ( 169 | ); 170 | name = Runner; 171 | productName = Runner; 172 | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; 173 | productType = "com.apple.product-type.application"; 174 | }; 175 | /* End PBXNativeTarget section */ 176 | 177 | /* Begin PBXProject section */ 178 | 97C146E61CF9000F007C117D /* Project object */ = { 179 | isa = PBXProject; 180 | attributes = { 181 | LastUpgradeCheck = 0910; 182 | ORGANIZATIONNAME = "The Chromium Authors"; 183 | TargetAttributes = { 184 | 97C146ED1CF9000F007C117D = { 185 | CreatedOnToolsVersion = 7.3.1; 186 | SystemCapabilities = { 187 | com.apple.BackgroundModes = { 188 | enabled = 1; 189 | }; 190 | }; 191 | }; 192 | }; 193 | }; 194 | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; 195 | compatibilityVersion = "Xcode 3.2"; 196 | developmentRegion = English; 197 | hasScannedForEncodings = 0; 198 | knownRegions = ( 199 | English, 200 | en, 201 | Base, 202 | ); 203 | mainGroup = 97C146E51CF9000F007C117D; 204 | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; 205 | projectDirPath = ""; 206 | projectRoot = ""; 207 | targets = ( 208 | 97C146ED1CF9000F007C117D /* Runner */, 209 | ); 210 | }; 211 | /* End PBXProject section */ 212 | 213 | /* Begin PBXResourcesBuildPhase section */ 214 | 97C146EC1CF9000F007C117D /* Resources */ = { 215 | isa = PBXResourcesBuildPhase; 216 | buildActionMask = 2147483647; 217 | files = ( 218 | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 219 | 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */, 220 | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 221 | 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 222 | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 223 | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXResourcesBuildPhase section */ 228 | 229 | /* Begin PBXShellScriptBuildPhase section */ 230 | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 231 | isa = PBXShellScriptBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | ); 235 | inputPaths = ( 236 | ); 237 | name = "Thin Binary"; 238 | outputPaths = ( 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | shellPath = /bin/sh; 242 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin\n"; 243 | }; 244 | 3D613EDE37FD2BDA1FAD0917 /* [CP] Embed Pods Frameworks */ = { 245 | isa = PBXShellScriptBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | ); 249 | inputPaths = ( 250 | "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", 251 | "${PODS_ROOT}/../.symlinks/flutter/ios-release/Flutter.framework", 252 | ); 253 | name = "[CP] Embed Pods Frameworks"; 254 | outputPaths = ( 255 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | shellPath = /bin/sh; 259 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; 260 | showEnvVarsInLog = 0; 261 | }; 262 | 64F1E4791E29623DE60DBD7B /* [CP] Check Pods Manifest.lock */ = { 263 | isa = PBXShellScriptBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | ); 267 | inputPaths = ( 268 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 269 | "${PODS_ROOT}/Manifest.lock", 270 | ); 271 | name = "[CP] Check Pods Manifest.lock"; 272 | outputPaths = ( 273 | "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | shellPath = /bin/sh; 277 | 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"; 278 | showEnvVarsInLog = 0; 279 | }; 280 | 9740EEB61CF901F6004384FC /* Run Script */ = { 281 | isa = PBXShellScriptBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | ); 285 | inputPaths = ( 286 | ); 287 | name = "Run Script"; 288 | outputPaths = ( 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | shellPath = /bin/sh; 292 | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; 293 | }; 294 | /* End PBXShellScriptBuildPhase section */ 295 | 296 | /* Begin PBXSourcesBuildPhase section */ 297 | 97C146EA1CF9000F007C117D /* Sources */ = { 298 | isa = PBXSourcesBuildPhase; 299 | buildActionMask = 2147483647; 300 | files = ( 301 | 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 302 | 97C146F31CF9000F007C117D /* main.m in Sources */, 303 | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, 304 | ); 305 | runOnlyForDeploymentPostprocessing = 0; 306 | }; 307 | /* End PBXSourcesBuildPhase section */ 308 | 309 | /* Begin PBXVariantGroup section */ 310 | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { 311 | isa = PBXVariantGroup; 312 | children = ( 313 | 97C146FB1CF9000F007C117D /* Base */, 314 | ); 315 | name = Main.storyboard; 316 | sourceTree = ""; 317 | }; 318 | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { 319 | isa = PBXVariantGroup; 320 | children = ( 321 | 97C147001CF9000F007C117D /* Base */, 322 | ); 323 | name = LaunchScreen.storyboard; 324 | sourceTree = ""; 325 | }; 326 | /* End PBXVariantGroup section */ 327 | 328 | /* Begin XCBuildConfiguration section */ 329 | 97C147031CF9000F007C117D /* Debug */ = { 330 | isa = XCBuildConfiguration; 331 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 332 | buildSettings = { 333 | ALWAYS_SEARCH_USER_PATHS = NO; 334 | CLANG_ANALYZER_NONNULL = YES; 335 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 336 | CLANG_CXX_LIBRARY = "libc++"; 337 | CLANG_ENABLE_MODULES = YES; 338 | CLANG_ENABLE_OBJC_ARC = YES; 339 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 340 | CLANG_WARN_BOOL_CONVERSION = YES; 341 | CLANG_WARN_COMMA = YES; 342 | CLANG_WARN_CONSTANT_CONVERSION = YES; 343 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 344 | CLANG_WARN_EMPTY_BODY = YES; 345 | CLANG_WARN_ENUM_CONVERSION = YES; 346 | CLANG_WARN_INFINITE_RECURSION = YES; 347 | CLANG_WARN_INT_CONVERSION = YES; 348 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 349 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 350 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 351 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 352 | CLANG_WARN_STRICT_PROTOTYPES = YES; 353 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 354 | CLANG_WARN_UNREACHABLE_CODE = YES; 355 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 356 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 357 | COPY_PHASE_STRIP = NO; 358 | DEBUG_INFORMATION_FORMAT = dwarf; 359 | ENABLE_STRICT_OBJC_MSGSEND = YES; 360 | ENABLE_TESTABILITY = YES; 361 | GCC_C_LANGUAGE_STANDARD = gnu99; 362 | GCC_DYNAMIC_NO_PIC = NO; 363 | GCC_NO_COMMON_BLOCKS = YES; 364 | GCC_OPTIMIZATION_LEVEL = 0; 365 | GCC_PREPROCESSOR_DEFINITIONS = ( 366 | "DEBUG=1", 367 | "$(inherited)", 368 | ); 369 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 370 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 371 | GCC_WARN_UNDECLARED_SELECTOR = YES; 372 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 373 | GCC_WARN_UNUSED_FUNCTION = YES; 374 | GCC_WARN_UNUSED_VARIABLE = YES; 375 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 376 | MTL_ENABLE_DEBUG_INFO = YES; 377 | ONLY_ACTIVE_ARCH = YES; 378 | SDKROOT = iphoneos; 379 | TARGETED_DEVICE_FAMILY = "1,2"; 380 | }; 381 | name = Debug; 382 | }; 383 | 97C147041CF9000F007C117D /* Release */ = { 384 | isa = XCBuildConfiguration; 385 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 386 | buildSettings = { 387 | ALWAYS_SEARCH_USER_PATHS = NO; 388 | CLANG_ANALYZER_NONNULL = YES; 389 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 390 | CLANG_CXX_LIBRARY = "libc++"; 391 | CLANG_ENABLE_MODULES = YES; 392 | CLANG_ENABLE_OBJC_ARC = YES; 393 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 394 | CLANG_WARN_BOOL_CONVERSION = YES; 395 | CLANG_WARN_COMMA = YES; 396 | CLANG_WARN_CONSTANT_CONVERSION = YES; 397 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 398 | CLANG_WARN_EMPTY_BODY = YES; 399 | CLANG_WARN_ENUM_CONVERSION = YES; 400 | CLANG_WARN_INFINITE_RECURSION = YES; 401 | CLANG_WARN_INT_CONVERSION = YES; 402 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 403 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 404 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 405 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 406 | CLANG_WARN_STRICT_PROTOTYPES = YES; 407 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 408 | CLANG_WARN_UNREACHABLE_CODE = YES; 409 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 410 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 411 | COPY_PHASE_STRIP = NO; 412 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 413 | ENABLE_NS_ASSERTIONS = NO; 414 | ENABLE_STRICT_OBJC_MSGSEND = YES; 415 | GCC_C_LANGUAGE_STANDARD = gnu99; 416 | GCC_NO_COMMON_BLOCKS = YES; 417 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 418 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 419 | GCC_WARN_UNDECLARED_SELECTOR = YES; 420 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 421 | GCC_WARN_UNUSED_FUNCTION = YES; 422 | GCC_WARN_UNUSED_VARIABLE = YES; 423 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 424 | MTL_ENABLE_DEBUG_INFO = NO; 425 | SDKROOT = iphoneos; 426 | TARGETED_DEVICE_FAMILY = "1,2"; 427 | VALIDATE_PRODUCT = YES; 428 | }; 429 | name = Release; 430 | }; 431 | 97C147061CF9000F007C117D /* Debug */ = { 432 | isa = XCBuildConfiguration; 433 | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; 434 | buildSettings = { 435 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 436 | CURRENT_PROJECT_VERSION = 1; 437 | DEVELOPMENT_TEAM = ""; 438 | ENABLE_BITCODE = NO; 439 | FRAMEWORK_SEARCH_PATHS = ( 440 | "$(inherited)", 441 | "$(PROJECT_DIR)/Flutter", 442 | ); 443 | INFOPLIST_FILE = Runner/Info.plist; 444 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 445 | LIBRARY_SEARCH_PATHS = ( 446 | "$(inherited)", 447 | "$(PROJECT_DIR)/Flutter", 448 | ); 449 | PRODUCT_BUNDLE_IDENTIFIER = com.github.marekchen.flutterQqExample; 450 | PRODUCT_NAME = "$(TARGET_NAME)"; 451 | VERSIONING_SYSTEM = "apple-generic"; 452 | }; 453 | name = Debug; 454 | }; 455 | 97C147071CF9000F007C117D /* Release */ = { 456 | isa = XCBuildConfiguration; 457 | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; 458 | buildSettings = { 459 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 460 | CURRENT_PROJECT_VERSION = 1; 461 | DEVELOPMENT_TEAM = ""; 462 | ENABLE_BITCODE = NO; 463 | FRAMEWORK_SEARCH_PATHS = ( 464 | "$(inherited)", 465 | "$(PROJECT_DIR)/Flutter", 466 | ); 467 | INFOPLIST_FILE = Runner/Info.plist; 468 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 469 | LIBRARY_SEARCH_PATHS = ( 470 | "$(inherited)", 471 | "$(PROJECT_DIR)/Flutter", 472 | ); 473 | PRODUCT_BUNDLE_IDENTIFIER = com.github.marekchen.flutterQqExample; 474 | PRODUCT_NAME = "$(TARGET_NAME)"; 475 | VERSIONING_SYSTEM = "apple-generic"; 476 | }; 477 | name = Release; 478 | }; 479 | /* End XCBuildConfiguration section */ 480 | 481 | /* Begin XCConfigurationList section */ 482 | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { 483 | isa = XCConfigurationList; 484 | buildConfigurations = ( 485 | 97C147031CF9000F007C117D /* Debug */, 486 | 97C147041CF9000F007C117D /* Release */, 487 | ); 488 | defaultConfigurationIsVisible = 0; 489 | defaultConfigurationName = Release; 490 | }; 491 | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { 492 | isa = XCConfigurationList; 493 | buildConfigurations = ( 494 | 97C147061CF9000F007C117D /* Debug */, 495 | 97C147071CF9000F007C117D /* Release */, 496 | ); 497 | defaultConfigurationIsVisible = 0; 498 | defaultConfigurationName = Release; 499 | }; 500 | /* End XCConfigurationList section */ 501 | }; 502 | rootObject = 97C146E61CF9000F007C117D /* Project object */; 503 | } 504 | -------------------------------------------------------------------------------- /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.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 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 didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 7 | [GeneratedPluginRegistrant registerWithRegistry:self]; 8 | // Override point for customization after application launch. 9 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 10 | } 11 | 12 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url 13 | sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 14 | { 15 | NSString * urlStr = [url absoluteString]; 16 | [[NSNotificationCenter defaultCenter] 17 | postNotificationName:@"QQ" object:nil userInfo:@{@"url":urlStr}]; 18 | return YES; 19 | } 20 | 21 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url 22 | options:(NSDictionary *)options 23 | { 24 | NSString * urlStr = [url absoluteString]; 25 | [[NSNotificationCenter defaultCenter] 26 | postNotificationName:@"QQ" object:nil userInfo:@{@"url":urlStr}]; 27 | return YES; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/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 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_qq_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | CFBundleURLTypes 24 | 25 | 26 | CFBundleTypeRole 27 | Editor 28 | CFBundleURLName 29 | tencent 30 | CFBundleURLSchemes 31 | 32 | tencent1107493622 33 | 34 | 35 | 36 | LSApplicationQueriesSchemes 37 | 38 | mqq 39 | mqqapi 40 | mqqwpa 41 | mqqbrowser 42 | mttbrowser 43 | mqqOpensdkSSoLogin 44 | mqqopensdkapiV2 45 | mqqopensdkapiV3 46 | mqqopensdkapiV4 47 | wtloginmqq2 48 | mqzone 49 | mqzoneopensdk 50 | mqzoneopensdkapi 51 | mqzoneopensdkapi19 52 | mqzoneopensdkapiV2 53 | mqqapiwallet 54 | mqqopensdkfriend 55 | mqqopensdkdataline 56 | mqqgamebindinggroup 57 | mqqopensdkgrouptribeshare 58 | tencentapi.qq.reqContent 59 | tencentapi.qzone.reqContent 60 | 61 | NSMicrophoneUsageDescription 62 | microphoneUsageDescription 63 | NSPhotoLibraryUsageDescription 64 | photoLibraryDesciption 65 | NSCameraUsageDescription 66 | cameraUsageDesciption 67 | LSRequiresIPhoneOS 68 | 69 | UIBackgroundModes 70 | 71 | fetch 72 | remote-notification 73 | 74 | UILaunchStoryboardName 75 | LaunchScreen 76 | UIMainStoryboardFile 77 | Main 78 | UISupportedInterfaceOrientations 79 | 80 | UIInterfaceOrientationPortrait 81 | UIInterfaceOrientationLandscapeLeft 82 | UIInterfaceOrientationLandscapeRight 83 | 84 | UISupportedInterfaceOrientations~ipad 85 | 86 | UIInterfaceOrientationPortrait 87 | UIInterfaceOrientationPortraitUpsideDown 88 | UIInterfaceOrientationLandscapeLeft 89 | UIInterfaceOrientationLandscapeRight 90 | 91 | UIViewControllerBasedStatusBarAppearance 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /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/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'dart:io'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_qq/flutter_qq.dart'; 6 | import 'package:image_picker/image_picker.dart'; 7 | 8 | void main() => runApp(new MyApp()); 9 | 10 | class MyApp extends StatefulWidget { 11 | @override 12 | _MyAppState createState() => new _MyAppState(); 13 | } 14 | 15 | class _MyAppState extends State { 16 | List _images = new List(); 17 | String _output = '---'; 18 | 19 | @override 20 | initState() { 21 | super.initState(); 22 | } 23 | 24 | Future _chooseImage() async { 25 | var image = await ImagePicker.pickImage(source: ImageSource.gallery); 26 | _images.add(image); 27 | } 28 | 29 | Future _handleisQQInstalled() async { 30 | var result = await FlutterQq.isQQInstalled(); 31 | var output; 32 | if (result) { 33 | output = "QQ已安装"; 34 | } else { 35 | output = "QQ未安装"; 36 | } 37 | setState(() { 38 | _output = output; 39 | }); 40 | } 41 | 42 | Future _handleLogin() async { 43 | try { 44 | var qqResult = await FlutterQq.login(); 45 | var output; 46 | if (qqResult.code == 0) { 47 | if(qqResult.response==null){ 48 | output = "登录成功qqResult.response==null"; 49 | return; 50 | } 51 | output = "登录成功" + qqResult.response.toString(); 52 | } else { 53 | output = "登录失败" + qqResult.message; 54 | } 55 | setState(() { 56 | _output = output; 57 | }); 58 | } catch (error) { 59 | print("flutter_plugin_qq_example:" + error.toString()); 60 | } 61 | } 62 | 63 | Future _handleShareToQQ() async { 64 | ShareQQContent shareContent = new ShareQQContent( 65 | shareType: SHARE_TO_QQ_TYPE.DEFAULT, 66 | title: "测试title", 67 | targetUrl: "https://www.baidu.com", 68 | summary: "测试summary", 69 | imageUrl: "http://inews.gtimg.com/newsapp_bt/0/876781763/1000", 70 | ); 71 | try { 72 | var qqResult = await FlutterQq.shareToQQ(shareContent); 73 | var output; 74 | if (qqResult.code == 0) { 75 | output = "分享成功"; 76 | } else if (qqResult.code == 1) { 77 | output = "分享失败" + qqResult.message; 78 | } else { 79 | output = "用户取消"; 80 | } 81 | setState(() { 82 | _output = output; 83 | }); 84 | } catch (error) { 85 | print("flutter_plugin_qq_example:" + error.toString()); 86 | 87 | } 88 | } 89 | 90 | Future _handleShareToQQWithLocalImage() async { 91 | ShareQQContent shareContent = new ShareQQContent( 92 | shareType: SHARE_TO_QQ_TYPE.IMAGE, 93 | title: "测试title", 94 | targetUrl: "https://www.baidu.com", 95 | summary: "测试summary", 96 | imageLocalUrl: _images[0].path 97 | ); 98 | try { 99 | var qqResult = await FlutterQq.shareToQQ(shareContent); 100 | var output; 101 | if (qqResult.code == 0) { 102 | output = "分享成功"; 103 | } else if (qqResult.code == 1) { 104 | output = "分享失败" + qqResult.message; 105 | } else { 106 | output = "用户取消"; 107 | } 108 | setState(() { 109 | _output = output; 110 | }); 111 | } catch (error) { 112 | print("flutter_plugin_qq_example:" + error.toString()); 113 | 114 | } 115 | } 116 | 117 | Future _handleShareToQZone() async { 118 | ShareQzoneContent shareContent = new ShareQzoneContent( 119 | shareType: SHARE_TO_QZONE_TYPE.IMAGE_TEXT, 120 | title: "测试title", 121 | targetUrl: "https://www.baidu.com", 122 | summary: "测试summary", 123 | imageUrl: "http://inews.gtimg.com/newsapp_bt/0/876781763/1000", 124 | ); 125 | try { 126 | var qqResult = await FlutterQq.shareToQzone(shareContent); 127 | var output; 128 | if (qqResult.code == 0) { 129 | output = "分享成功"; 130 | } else if (qqResult.code == 1) { 131 | output = "分享失败" + qqResult.message; 132 | } else { 133 | output = "用户取消"; 134 | } 135 | setState(() { 136 | _output = output; 137 | }); 138 | } catch (error) { 139 | print("flutter_plugin_qq_example:" + error.toString()); 140 | } 141 | } 142 | 143 | @override 144 | Widget build(BuildContext context) { 145 | FlutterQq.registerQQ('1107493622'); 146 | return new MaterialApp( 147 | home: new Scaffold( 148 | appBar: new AppBar( 149 | title: new Text('Plugin QQ example app'), 150 | ), 151 | body: new Column( 152 | children: [ 153 | new Text(_output), 154 | new RaisedButton( 155 | onPressed: _chooseImage, 156 | child: new Text('chooseImage'), 157 | ), 158 | new RaisedButton( 159 | onPressed: _handleisQQInstalled, 160 | child: new Text('isQQInstalled'), 161 | ), 162 | new RaisedButton( 163 | onPressed: _handleLogin, 164 | child: new Text('login'), 165 | ), 166 | new RaisedButton( 167 | onPressed: _handleShareToQQ, 168 | child: new Text('ShareToQQ'), 169 | ), 170 | new RaisedButton( 171 | onPressed: _handleShareToQQWithLocalImage, 172 | child: new Text('ShareToQQ-WithLocalImage'), 173 | ), 174 | new RaisedButton( 175 | onPressed: _handleShareToQZone, 176 | child: new Text('ShareToQZone'), 177 | ), 178 | ], 179 | ), 180 | ), 181 | ); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_qq_example 2 | description: Demonstrates how to use the flutter_qq plugin. 3 | 4 | dependencies: 5 | flutter: 6 | sdk: flutter 7 | 8 | # The following adds the Cupertino Icons font to your application. 9 | # Use with the CupertinoIcons class for iOS style icons. 10 | cupertino_icons: ^0.1.2 11 | 12 | dev_dependencies: 13 | flutter_test: 14 | sdk: flutter 15 | 16 | flutter_qq: 17 | path: ../ 18 | 19 | image_picker: ^0.6.0+15 20 | 21 | # For information on the generic Dart part of this file, see the 22 | # following page: https://www.dartlang.org/tools/pub/pubspec 23 | 24 | # The following section is specific to Flutter. 25 | flutter: 26 | 27 | # The following line ensures that the Material Icons font is 28 | # included with your application, so that you can use the icons in 29 | # the material Icons class. 30 | uses-material-design: true 31 | 32 | # To add assets to your application, add an assets section, like this: 33 | # assets: 34 | # - images/a_dot_burr.jpeg 35 | # - images/a_dot_ham.jpeg 36 | 37 | # An image asset can refer to one or more resolution-specific "variants", see 38 | # https://flutter.io/assets-and-images/#resolution-aware. 39 | 40 | # For details regarding adding assets from package dependencies, see 41 | # https://flutter.io/assets-and-images/#from-packages 42 | 43 | # To add custom fonts to your application, add a fonts section here, 44 | # in this "flutter" section. Each entry in this list should have a 45 | # "family" key with the font family name, and a "fonts" key with a 46 | # list giving the asset and other descriptors for the font. For 47 | # example: 48 | # fonts: 49 | # - family: Schyler 50 | # fonts: 51 | # - asset: fonts/Schyler-Regular.ttf 52 | # - asset: fonts/Schyler-Italic.ttf 53 | # style: italic 54 | # - family: Trajan Pro 55 | # fonts: 56 | # - asset: fonts/TrajanPro.ttf 57 | # - asset: fonts/TrajanPro_Bold.ttf 58 | # weight: 700 59 | # 60 | # For details regarding fonts from package dependencies, 61 | # see https://flutter.io/custom-fonts/#from-packages 62 | -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // To perform an interaction with a widget in your test, use the WidgetTester utility that Flutter 3 | // provides. For example, you can send tap and scroll gestures. You can also use WidgetTester to 4 | // find child widgets in the widget tree, read text, and verify that the values of widget properties 5 | // are correct. 6 | 7 | //import 'package:flutter/material.dart'; 8 | //import 'package:flutter_test/flutter_test.dart'; 9 | // 10 | //import 'package:flutter_qq_example/main.dart'; 11 | // 12 | //void main() { 13 | // testWidgets('Verify Platform version', (WidgetTester tester) async { 14 | // // Build our app and trigger a frame. 15 | // await tester.pumpWidget(new MyApp()); 16 | // 17 | // // Verify that platform version is retrieved. 18 | // expect( 19 | // find.byWidgetPredicate( 20 | // (Widget widget) => 21 | // widget is Text && widget.data.startsWith('Running on:'), 22 | // ), 23 | // findsOneWidget); 24 | // }); 25 | //} 26 | -------------------------------------------------------------------------------- /flutter_qq.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /flutter_qq_android.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /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/marekchen/flutter_qq/a12f563c1462f7ce8ebaac7034f845d510836b33/ios/Assets/.gitkeep -------------------------------------------------------------------------------- /ios/Classes/FlutterQqPlugin.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #define SHARE_TO_QQ_TYPE_DEFAULT 1 // 默认(图片文字) news 4 | #define SHARE_TO_QZONE_TYPE_IMAGE_TEXT 1 // 图片文字 news 5 | 6 | #define SHARE_TO_QQ_TYPE_AUDIO 2 // 音频 7 | 8 | #define PUBLISH_TO_QZONE_TYPE_PUBLISHMOOD 3 // 说说 9 | #define PUBLISH_TO_QZONE_TYPE_PUBLISHVIDEO 4 // 视频 10 | 11 | #define SHARE_TO_QQ_TYPE_IMAGE 5 // 图片(本地图片) 12 | #define SHARE_TO_QZONE_TYPE_IMAGE 5 13 | 14 | #define SHARE_TO_QQ_TYPE_APP 6 // App 15 | #define SHARE_TO_QZONE_TYPE_APP 6 16 | 17 | @interface FlutterQqPlugin : NSObject 18 | @end 19 | -------------------------------------------------------------------------------- /ios/Classes/FlutterQqPlugin.m: -------------------------------------------------------------------------------- 1 | #import "FlutterQqPlugin.h" 2 | #import 3 | #import 4 | #import 5 | 6 | @interface FlutterQqPlugin() { 7 | TencentOAuth* _oauth; 8 | FlutterResult result; 9 | } 10 | @end 11 | 12 | @implementation FlutterQqPlugin 13 | - (instancetype)init 14 | { 15 | self = [super init]; 16 | [[NSNotificationCenter defaultCenter] addObserver:self 17 | selector:@selector(handleOpenURL:) 18 | name:@"QQ" 19 | object:nil]; 20 | return self; 21 | } 22 | - (void)dealloc 23 | { 24 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 25 | } 26 | + (void)registerWithRegistrar:(NSObject*)registrar { 27 | FlutterMethodChannel* channel = [FlutterMethodChannel 28 | methodChannelWithName:@"flutter_qq" 29 | binaryMessenger:[registrar messenger]]; 30 | FlutterQqPlugin* instance = [[FlutterQqPlugin alloc] init]; 31 | [registrar addMethodCallDelegate:instance channel:channel]; 32 | } 33 | 34 | - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)flutterResult { 35 | result=flutterResult; 36 | if ([@"registerQQ" isEqualToString:call.method]) { 37 | NSString *appId = call.arguments[@"appId"]; 38 | _oauth = [[TencentOAuth alloc] initWithAppId:appId andDelegate:self]; 39 | } else if([@"isQQInstalled" isEqualToString:call.method]){ 40 | if([QQApiInterface isQQInstalled]){ 41 | result(@(YES)); 42 | }else{ 43 | result(@(NO)); 44 | } 45 | } else if([@"login" isEqualToString:call.method]) { 46 | NSArray *scopeArray = nil; 47 | NSString *scopes = call.arguments[@"scopes"]; 48 | if(scopes && scopes.length){ 49 | scopeArray = [scopes componentsSeparatedByString:@","]; 50 | } 51 | if (scopeArray == nil) { 52 | scopeArray = @[@"get_user_info", @"get_simple_userinfo"]; 53 | } 54 | if(![_oauth authorize:scopeArray]) { 55 | NSMutableDictionary *body = @{@"type":@"QQAuthorizeResponse"}.mutableCopy; 56 | body[@"Code"] = @(1); 57 | body[@"Message"] = @"login failed"; 58 | result(body); 59 | } 60 | } else if([@"shareToQQ" isEqualToString:call.method]) { 61 | [self shareToQQ:call result:result]; 62 | } else if([@"shareToQzone" isEqualToString:call.method]) { 63 | [self shareToQzone:call result:result]; 64 | } 65 | } 66 | 67 | - (void)shareToQQ:(FlutterMethodCall*)call result:(FlutterResult)flutterResult{ 68 | int shareType = [call.arguments[@"shareType"] intValue]; 69 | NSString *title = call.arguments[@"title"]; 70 | NSString *description = call.arguments[@"summary"]; 71 | NSString *imageUrl = call.arguments[@"imageUrl"]; 72 | NSString *imageLocalUrl = call.arguments[@"imageLocalUrl"]; 73 | NSString *webpageUrl = call.arguments[@"targetUrl"]; 74 | NSString *audioUrl = call.arguments[@"audioUrl"]; 75 | QQApiObject *message = nil; 76 | 77 | if(shareType == SHARE_TO_QQ_TYPE_DEFAULT){ 78 | // news|Image 79 | message = [QQApiNewsObject objectWithURL:[NSURL URLWithString:webpageUrl] title:title description:description previewImageURL:[NSURL URLWithString:imageUrl]]; 80 | } 81 | else if(shareType == SHARE_TO_QQ_TYPE_IMAGE){ 82 | // localImage 83 | UIImage *image = nil; 84 | if(imageLocalUrl.length) { 85 | if ([[NSFileManager defaultManager] fileExistsAtPath:imageLocalUrl]){ 86 | image = [UIImage imageWithContentsOfFile:imageLocalUrl]; 87 | } 88 | } 89 | NSData *imageData = UIImageJPEGRepresentation(image, 0.80); 90 | NSData *previewImageData = UIImageJPEGRepresentation(image, 0.20); 91 | message = [QQApiImageObject objectWithData:imageData previewImageData:previewImageData title:title description:description]; 92 | 93 | } 94 | else if (shareType == SHARE_TO_QQ_TYPE_AUDIO){ 95 | // audio 96 | QQApiAudioObject *audioObj = [QQApiAudioObject objectWithURL:[NSURL URLWithString:webpageUrl] title:title description:description previewImageURL:[NSURL URLWithString:imageUrl]]; 97 | if(audioUrl) { 98 | [audioObj setFlashURL:[NSURL URLWithString:audioUrl]]; 99 | } 100 | } 101 | SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:message]; 102 | QQApiSendResultCode code = [QQApiInterface sendReq:req]; 103 | if(code != EQQAPISENDSUCESS && code != EQQAPIAPPSHAREASYNC){ 104 | NSMutableDictionary *body = @{@"type":@"QQShareResponse"}.mutableCopy; 105 | body[@"Code"] = @(1); 106 | body[@"Message"] = [NSString stringWithFormat:@"errorCode:%d", code]; 107 | result(body); 108 | } 109 | } 110 | 111 | - (void)shareToQzone:(FlutterMethodCall*)call result:(FlutterResult)flutterResult{ 112 | int shareType = [call.arguments[@"shareType"] intValue]; 113 | NSString *title = call.arguments[@"title"]; 114 | NSString *description = call.arguments[@"summary"]; 115 | NSString *imageUrl = call.arguments[@"imageUrl"]; 116 | NSArray *imageUrls = call.arguments[@"imageUrls"]; 117 | NSString *webpageUrl = call.arguments[@"targetUrl"]; 118 | NSString *sceneStr = call.arguments[@"scene"]; 119 | NSString *callBackStr = call.arguments[@"hulian_call_back"]; 120 | 121 | NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 122 | if(![sceneStr isKindOfClass:[NSNull class]]){ 123 | NSString *checkSceneStr = [sceneStr stringByReplacingOccurrencesOfString:@" " withString:@""]; 124 | if (checkSceneStr.length > 0) { 125 | [dict setObject:sceneStr forKey:@"hulian_extra_scene"]; 126 | } 127 | } 128 | if(![callBackStr isKindOfClass:[NSNull class]]){ 129 | NSString *checkCallBackStr = [callBackStr stringByReplacingOccurrencesOfString:@" " withString:@""]; 130 | if (checkCallBackStr.length > 0) { 131 | [dict setObject:callBackStr forKey:@"hulian_call_back"]; 132 | } 133 | } 134 | if (dict.count == 0) { 135 | dict = nil; 136 | } 137 | 138 | QQApiObject *message = nil; 139 | 140 | if(shareType == SHARE_TO_QZONE_TYPE_IMAGE_TEXT) { 141 | // text 142 | // message = [QQApiImageArrayForQZoneObject objectWithimageDataArray:nil title:title extMap:dict]; 143 | message = [QQApiNewsObject objectWithURL:[NSURL URLWithString:webpageUrl] title:title description:description previewImageURL:[NSURL URLWithString:imageUrl]]; 144 | } 145 | else if(shareType == SHARE_TO_QZONE_TYPE_IMAGE) { 146 | // localImages 147 | NSMutableArray *photoArray = [NSMutableArray array]; 148 | for(NSString *imageUrl in imageUrls){ 149 | if(imageUrl.length) { 150 | if ([[NSFileManager defaultManager] fileExistsAtPath:imageUrl]){ 151 | UIImage *image = [UIImage imageWithContentsOfFile:imageUrl]; 152 | NSData *imageData = UIImageJPEGRepresentation(image, 0.80); 153 | [photoArray addObject:imageData]; 154 | } 155 | } 156 | } 157 | message = [QQApiImageArrayForQZoneObject objectWithimageDataArray:photoArray title:title extMap:dict]; 158 | } 159 | SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:message]; 160 | QQApiSendResultCode code = [QQApiInterface SendReqToQZone:req]; 161 | if(code != EQQAPISENDSUCESS && code != EQQAPIAPPSHAREASYNC){ 162 | NSMutableDictionary *body = @{@"type":@"QQShareResponse"}.mutableCopy; 163 | body[@"Code"] = @(1); 164 | body[@"Message"] = [NSString stringWithFormat:@"errorCode:%d", code]; 165 | result(body); 166 | } 167 | } 168 | 169 | - (BOOL)handleOpenURL:(NSNotification *)aNotification 170 | { 171 | NSString * aURLString = [aNotification userInfo][@"url"]; 172 | NSURL * url = [NSURL URLWithString:aURLString]; 173 | [QQApiInterface handleOpenURL:url delegate:self]; 174 | if (YES == [TencentOAuth CanHandleOpenURL:url]) 175 | { 176 | return [TencentOAuth HandleOpenURL:url]; 177 | } 178 | return YES; 179 | } 180 | 181 | #pragma mark - QQApiInterfaceDelegate 182 | - (void)onReq:(QQBaseReq *)req 183 | { 184 | 185 | } 186 | 187 | - (void) onResp:(QQBaseResp *)resp 188 | { 189 | if([resp isKindOfClass:[SendMessageToQQResp class]]) 190 | { 191 | NSMutableDictionary *body = @{@"type":@"QQShareResponse"}.mutableCopy; 192 | SendMessageToQQResp* sendReq = (SendMessageToQQResp*)resp; 193 | if(sendReq.errorDescription) { 194 | body[@"Code"] = @(1); 195 | } else { 196 | body[@"Code"] = @(0); 197 | } 198 | body[@"Message"] = sendReq.result; 199 | result(body); 200 | } 201 | } 202 | - (void) isOnlineResponse:(NSDictionary *)response 203 | { 204 | 205 | } 206 | 207 | #pragma mark - oauth delegate 208 | - (void)tencentDidLogin 209 | { 210 | NSMutableDictionary *body = @{@"type":@"QQAuthorizeResponse"}.mutableCopy; 211 | body[@"Code"] = @(0); 212 | body[@"Message"] = @"Ok"; 213 | NSMutableDictionary *response = @{@"openid":_oauth.openId}.mutableCopy; 214 | response[@"openid"] = _oauth.openId; 215 | response[@"accessToken"] = _oauth.accessToken; 216 | 217 | response[@"expiresAt"] = @([_oauth.expirationDate timeIntervalSince1970] * 1000); 218 | response[@"appId"] =_oauth.appId; 219 | body[@"Response"] = response; 220 | result(body); 221 | } 222 | 223 | - (void)tencentDidNotLogin:(BOOL)cancelled 224 | { 225 | NSMutableDictionary *body = @{@"type":@"QQAuthorizeResponse"}.mutableCopy; 226 | if (cancelled) { 227 | body[@"Code"] = @(2); 228 | body[@"Message"] = @"login canceled"; 229 | } 230 | else { 231 | body[@"Code"] = @(1); 232 | body[@"Message"] = @"login failed"; 233 | } 234 | } 235 | 236 | - (void)tencentDidNotNetWork 237 | { 238 | } 239 | 240 | @end 241 | -------------------------------------------------------------------------------- /ios/flutter_qq.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 = 'flutter_qq' 6 | s.version = '0.0.5' 7 | s.summary = 'Flutter plugin for QQ.' 8 | s.static_framework = true 9 | s.description = <<-DESC 10 | Flutter plugin for QQ. 11 | DESC 12 | s.homepage = 'https://github.com/marekchen/flutter_qq' 13 | s.license = { :file => '../LICENSE' } 14 | s.author = { 'marekchen' => 'c491843272@gmail.com' } 15 | s.source = { :path => '.' } 16 | s.source_files = 'Classes/**/*' 17 | s.public_header_files = 'Classes/**/*.h' 18 | s.dependency 'Flutter' 19 | s.dependency 'QQSDK' 20 | 21 | s.ios.deployment_target = '8.0' 22 | end 23 | 24 | -------------------------------------------------------------------------------- /lib/flutter_qq.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/services.dart'; 4 | 5 | enum SHARE_TO_QQ_TYPE { 6 | DEFAULT, //1 7 | AUDIO, //2 8 | IMAGE, //5 9 | APP //6 10 | } 11 | 12 | enum SHARE_TO_QZONE_TYPE { 13 | IMAGE_TEXT, //1 14 | PUBLISH_MOOD, //3 说说 15 | PUBLISH_VIDEO, //4 视频 16 | IMAGE, //5, 貌似QQ不再支持 17 | APP //6 18 | } 19 | 20 | enum QZONE_FLAG { 21 | DEFAULT, //0 22 | AUTO_OPEN, //1 23 | ITEM_HIDE //2 24 | } 25 | 26 | class ShareQQContent { 27 | SHARE_TO_QQ_TYPE shareType; 28 | String title; 29 | String targetUrl; 30 | String summary; 31 | 32 | String imageUrl; 33 | String imageLocalUrl; 34 | 35 | String appName; 36 | String audioUrl; 37 | 38 | QZONE_FLAG qzoneFlag; 39 | 40 | String ark; 41 | 42 | ShareQQContent({ 43 | this.shareType = SHARE_TO_QQ_TYPE.DEFAULT, 44 | this.title, 45 | this.targetUrl, 46 | this.summary, 47 | this.imageUrl, 48 | this.imageLocalUrl, 49 | this.appName, 50 | this.audioUrl, 51 | this.qzoneFlag = QZONE_FLAG.DEFAULT, 52 | this.ark, 53 | }); 54 | } 55 | 56 | class ShareQzoneContent { 57 | SHARE_TO_QZONE_TYPE shareType; 58 | String title; 59 | String targetUrl; 60 | String summary; 61 | String imageUrl; 62 | List imageUrls; 63 | 64 | String scene; 65 | String callback; 66 | 67 | ShareQzoneContent({ 68 | this.shareType = SHARE_TO_QZONE_TYPE.IMAGE_TEXT, 69 | this.title, 70 | this.targetUrl, 71 | this.summary, 72 | this.imageUrl, 73 | this.imageUrls, 74 | this.scene, 75 | this.callback, 76 | }); 77 | } 78 | 79 | class QQResult { 80 | int code; 81 | String message; 82 | Map response; 83 | } 84 | 85 | class FlutterQq { 86 | static const MethodChannel _channel = const MethodChannel('flutter_qq'); 87 | 88 | static void registerQQ(String appId) async { 89 | await _channel.invokeMethod('registerQQ', {'appId': appId}); 90 | } 91 | 92 | static Future isQQInstalled() async { 93 | return await _channel.invokeMethod('isQQInstalled'); 94 | } 95 | 96 | static Future login() async { 97 | final Map result = await _channel.invokeMethod('login'); 98 | QQResult qqResult = new QQResult(); 99 | qqResult.code = result["Code"]; 100 | qqResult.message = result["Message"]; 101 | qqResult.response = result["Response"]; 102 | return qqResult; 103 | } 104 | 105 | static Future shareToQQ(ShareQQContent shareContent) async { 106 | Map params; 107 | int shareType = 1; 108 | switch (shareContent.shareType) { 109 | case SHARE_TO_QQ_TYPE.AUDIO: 110 | shareType = 2; 111 | break; 112 | case SHARE_TO_QQ_TYPE.IMAGE: 113 | shareType = 5; 114 | break; 115 | case SHARE_TO_QQ_TYPE.APP: 116 | shareType = 6; 117 | break; 118 | default: 119 | shareType = 1; 120 | } 121 | params = { 122 | "shareType": shareType, 123 | "title": shareContent.title, 124 | "targetUrl": shareContent.targetUrl, 125 | "summary": shareContent.summary, 126 | "imageUrl": shareContent.imageUrl, 127 | // shareType == IMAGE,support imageLocalUrl only 128 | "imageLocalUrl": shareContent.imageLocalUrl, 129 | "appName": shareContent.appName, 130 | "audioUrl": shareContent.audioUrl, 131 | "qzoneFlag": shareContent.qzoneFlag.index, 132 | // app 信息? 133 | "ark": shareContent.ark 134 | }; 135 | final Map result = 136 | await _channel.invokeMethod('shareToQQ', params); 137 | QQResult qqResult = new QQResult(); 138 | qqResult.code = result["Code"]; 139 | qqResult.message = result["Message"]; 140 | return qqResult; 141 | } 142 | 143 | static Future shareToQzone(ShareQzoneContent shareContent) async { 144 | Map params; 145 | int shareType = 1; 146 | switch (shareContent.shareType) { 147 | case SHARE_TO_QZONE_TYPE.PUBLISH_MOOD: 148 | shareType = 3; 149 | break; 150 | case SHARE_TO_QZONE_TYPE.PUBLISH_VIDEO: 151 | shareType = 4; 152 | break; 153 | case SHARE_TO_QZONE_TYPE.IMAGE: 154 | shareType = 5; 155 | break; 156 | case SHARE_TO_QZONE_TYPE.APP: 157 | shareType = 6; 158 | break; 159 | default: 160 | shareType = 1; 161 | } 162 | params = { 163 | "shareType": shareType, 164 | "title": shareContent.title, 165 | "targetUrl": shareContent.targetUrl, 166 | "summary": shareContent.summary, 167 | "imageUrl": shareContent.imageUrl, 168 | "imageUrls": shareContent.imageUrls, 169 | // app 信息? 170 | "scene": shareContent.scene, 171 | "callback": shareContent.callback, 172 | }; 173 | final Map result = 174 | await _channel.invokeMethod('shareToQzone', params); 175 | QQResult qqResult = new QQResult(); 176 | qqResult.code = result["Code"]; 177 | qqResult.message = result["Message"]; 178 | return qqResult; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_qq 2 | description: Flutter plugin for QQ. 3 | version: 0.0.5 4 | author: marekchen 5 | homepage: https://github.com/marekchen/flutter_qq 6 | 7 | dependencies: 8 | flutter: 9 | sdk: flutter 10 | 11 | dev_dependencies: 12 | image_picker: ^0.6.0+15 13 | 14 | # For information on the generic Dart part of this file, see the 15 | # following page: https://www.dartlang.org/tools/pub/pubspec 16 | 17 | # The following section is specific to Flutter. 18 | flutter: 19 | plugin: 20 | androidPackage: com.github.marekchen.flutterqq 21 | pluginClass: FlutterQqPlugin 22 | 23 | environment: 24 | sdk: ">=2.0.0-dev.28.0 <3.0.0" 25 | flutter: ">=1.5.0 <2.0.0" 26 | --------------------------------------------------------------------------------