├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── @ionic-native └── plugins │ └── qqsdk │ └── index.ts ├── LICENSE ├── README.md ├── README_ZH.md ├── ScreenShot.png ├── example_www ├── css │ ├── bootstrap.css │ └── index.css ├── img │ └── logo.png ├── index.html └── js │ └── index.js ├── package.json ├── plugin.xml ├── src ├── android │ ├── QQSDKPlugin.java │ ├── mta-sdk-1.6.2.jar │ └── open_sdk_r5793.jar └── ios │ ├── CDVQQSDK.h │ ├── CDVQQSDK.m │ ├── TencentOpenAPI.framework │ ├── Headers │ │ ├── QQApiInterface.h │ │ ├── QQApiInterfaceObject.h │ │ ├── TencentApiInterface.h │ │ ├── TencentMessageObject.h │ │ ├── TencentOAuth.h │ │ ├── TencentOAuthObject.h │ │ └── sdkdef.h │ ├── Resources │ │ └── ios_open_sdk_3.2.3.501_iphone_release │ └── TencentOpenAPI │ └── TencentOpenApi_IOS_Bundle.bundle │ ├── Info.plist │ ├── error.png │ ├── local.html │ ├── qqicon.png │ └── success.png └── www └── qq.js /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Before submitting issues ... 2 | 3 | - 确保你的 App 在[腾讯开放平台](http://open.qq.com/)已审核通过. 4 | - 如果是 Android 平台请确保你的apk签名是正确的. 5 | - 请确认 demo 已测试通过. 6 | - 请先搜索相关的 issues,看是否同样的问题已经有解决方案了. 7 | - 发生出现错误码的情况,请前去腾讯开放平台咨询. 8 | 9 | 当你提交 issues 的时候, 请提供以下信息来帮助开发者更好的修复Bug: 10 | 11 | - 开发环境: 插件版本, Cordova 版本, Xcode 版本. 12 | - 如果出现错误,希望提供 Xcode 或 Android Studio 的错误日志. 13 | - 如果有其他额外的信息,也希望可以提供一下,帮助我们更快的定位问题. 14 | 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | 15 | # Gradle files 16 | .gradle/ 17 | build/ 18 | /*/build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | -------------------------------------------------------------------------------- /@ionic-native/plugins/qqsdk/index.ts: -------------------------------------------------------------------------------- 1 | import { Plugin, Cordova, IonicNativePlugin } from '@ionic-native/core'; 2 | import { Injectable } from '@angular/core'; 3 | 4 | export interface QQShareOptions { 5 | 6 | /** 7 | * The clinet type, QQ or TIM 8 | * Default is QQ 9 | */ 10 | client?: number; 11 | 12 | /** 13 | * The Share Sence 14 | * Default is QQ 15 | */ 16 | scene?: number; 17 | 18 | /** 19 | * The text for shareText 20 | */ 21 | text?: string; 22 | 23 | /** 24 | * The url for share news or audio 25 | */ 26 | url?: string; 27 | 28 | /** 29 | * The title for share image,news or audio 30 | */ 31 | title?: string; 32 | 33 | /** 34 | * The description for share image,news or audio 35 | */ 36 | description?: string; 37 | 38 | /** 39 | * The image for share image,news or audio 40 | * Image supports three types: 41 | * 1. Network URL 42 | * 2. Base64 43 | * 3. Absolute file path 44 | */ 45 | image?: string; 46 | 47 | /** 48 | * The URL for audio 49 | */ 50 | flashUrl?: string; 51 | } 52 | 53 | /** 54 | * @name QQSDK 55 | * @description 56 | * This Plugin is a wrapper around the Tencent QQ SDK for Android and iOS. Provides access to QQ ssoLogin, QQ Sharing, QQZone Sharing etc. 57 | * 58 | * Requires Cordova plugin: `cordova-plugin-qqsdk`. For more info, please see the [QQSDK plugin docs](https://github.com/iVanPan/Cordova_QQ). 59 | * 60 | * @usage 61 | * ```typescript 62 | * import { QQSDK, QQShareOptions } from '@ionic-native/qqsdk'; 63 | * 64 | * constructor(private qq: QQSDK) { } 65 | * 66 | * ... 67 | * 68 | * 69 | * const options: QQShareOptions = { 70 | * client: this.qq.ClientType.QQ, 71 | * scene: this.qq.Scene.QQ, 72 | * title: 'This is a title for cordova-plugin-qqsdk', 73 | * url: 'https://cordova.apache.org/', 74 | * image: 'https://cordova.apache.org/static/img/cordova_bot.png', 75 | * description: 'This is Cordova QQ share description', 76 | * flashUrl: 'http://stream20.qqmusic.qq.com/30577158.mp3', 77 | * }; 78 | * 79 | * const clientOptions: QQShareOptions = { 80 | * client: this.qq.ClientType.QQ, 81 | * }; 82 | * 83 | * const shareTextOptions: QQShareOptions = { 84 | * client: this.qq.ClientType.QQ, 85 | * text: 'This is Share Text', 86 | * scene: this.qq.Scene.QQ, 87 | * }; 88 | * 89 | * this.qq.ssoLogin(clientOptions) 90 | * .then(result => { 91 | * // Success 92 | * console.log('token is ' + result.access_token); 93 | * console.log('userid is ' + result.userid); 94 | * console.log('expires_time is ' + new Date(parseInt(result.expires_time)) + ' TimeStamp is ' + result.expires_time); 95 | * }) 96 | * .catch(error => { 97 | * console.log(error); // Failed 98 | * }); 99 | * 100 | * this.qq.logout() 101 | * .then(() => { 102 | * console.log('logout success'); 103 | * }) 104 | * .catch(error => { 105 | * console.log(error); 106 | * }); 107 | * 108 | * this.qq.checkClientInstalled(clientOptions) 109 | * .then(() => { 110 | * console.log('Installed'); 111 | * }) 112 | * .catch(() => { 113 | * console.log('Not Installed'); 114 | * }); 115 | * 116 | * this.qq.shareText(shareTextOptions) 117 | * .then(() => { 118 | * console.log('shareText success'); 119 | * }) 120 | * .catch(error => { 121 | * console.log(error); 122 | * }); 123 | * 124 | * this.qq.shareImage(options) 125 | * .then(() => { 126 | * console.log('shareImage success'); 127 | * }) 128 | * .catch(error => { 129 | * console.log(error); 130 | * }); 131 | * } 132 | * 133 | * this.qq.shareNews(options) 134 | * .then(() => { 135 | * console.log('shareNews success'); 136 | * }) 137 | * .catch(error => { 138 | * console.log(error); 139 | * }); 140 | * } 141 | * 142 | * this.qq.shareAudio(options) 143 | * .then(() => { 144 | * console.log('shareAudio success'); 145 | * }) 146 | * .catch(error => { 147 | * console.log(error); 148 | * }); 149 | * 150 | * ``` 151 | * 152 | * @interfaces 153 | * QQShareOptions 154 | */ 155 | @Plugin({ 156 | pluginName: 'QQSDK', 157 | plugin: 'cordova-plugin-qqsdk', 158 | pluginRef: 'QQSDK', 159 | repo: 'https://github.com/iVanPan/Cordova_QQ', 160 | platforms: ['Android', 'iOS'], 161 | install: 'ionic cordova plugin add cordova-plugin-qqsdk --variable QQ_APP_ID=YOUR_QQ_APPID', 162 | installVariables: ['QQ_APP_ID'], 163 | }) 164 | @Injectable() 165 | export class QQSDK extends IonicNativePlugin { 166 | 167 | /** 168 | * QQ Share Scene 169 | * @type {{QQ: number; QQZone: number; Favorite: number}} 170 | */ 171 | Scene = { 172 | QQ: 0, 173 | QQZone: 1, 174 | Favorite: 2 175 | }; 176 | /** 177 | * client type: QQ application or TIM application 178 | * @type {{QQ: number; TIM: number}} 179 | */ 180 | ClientType = { 181 | QQ: 0, 182 | TIM: 1 183 | }; 184 | 185 | /** 186 | * open QQ or TIM client perform ssoLogin 187 | * @param options 188 | * @returns {Promise} Returns a Promise that resolves with the success return, or rejects with an error. 189 | */ 190 | @Cordova({ 191 | callbackOrder: 'reverse' 192 | }) 193 | ssoLogin(options: QQShareOptions): Promise { 194 | return; 195 | } 196 | 197 | @Cordova({ 198 | callbackOrder: 'reverse' 199 | }) 200 | logout(): Promise { 201 | return; 202 | } 203 | 204 | /** 205 | * Detect if the QQ application or TIM application is installed on the device. 206 | * 207 | * @returns {Promise} Returns a Promise that resolves with the success return, or rejects with an error. 208 | */ 209 | @Cordova({ 210 | callbackOrder: 'reverse' 211 | }) 212 | checkClientInstalled(options: QQShareOptions): Promise { 213 | return; 214 | } 215 | 216 | /** 217 | * shareText 218 | * @param options 219 | * @returns {Promise} Returns a Promise that resolves with the success return, or rejects with an error. 220 | */ 221 | @Cordova({ 222 | callbackOrder: 'reverse' 223 | }) 224 | shareText(options: QQShareOptions): Promise { 225 | return; 226 | } 227 | 228 | /** 229 | * shareImage 230 | * @param options 231 | * @returns {Promise} Returns a Promise that resolves with the success return, or rejects with an error. 232 | */ 233 | @Cordova({ 234 | callbackOrder: 'reverse' 235 | }) 236 | shareImage(options: QQShareOptions): Promise { 237 | return; 238 | } 239 | 240 | /** 241 | * shareNews 242 | * @param options 243 | * @returns {Promise} Returns a Promise that resolves with the success return, or rejects with an error. 244 | */ 245 | @Cordova({ 246 | callbackOrder: 'reverse' 247 | }) 248 | shareNews(options: QQShareOptions): Promise { 249 | return; 250 | } 251 | 252 | /** 253 | * shareAudio 254 | * @param options 255 | * @returns {Promise} Returns a Promise that resolves with the success return, or rejects with an error. 256 | */ 257 | @Cordova({ 258 | callbackOrder: 'reverse' 259 | }) 260 | shareAudio(options: QQShareOptions): Promise { 261 | return; 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Van 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cordova-plugin-qqsdk 2 | [![npm](https://img.shields.io/npm/v/cordova-plugin-qqsdk.svg)](https://www.npmjs.com/package/cordova-plugin-qqsdk) 3 | [![npm](https://img.shields.io/npm/dm/cordova-plugin-qqsdk.svg)](https://www.npmjs.com/package/cordova-plugin-qqsdk) 4 | [![platform](https://img.shields.io/badge/platform-iOS%2FAndroid-lightgrey.svg?style=flat)](https://github.com/iVanPan/Cordova_QQ) 5 | [![GitHub license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat)](https://github.com/iVanPan/Cordova_QQ/blob/master/LICENSE) 6 | 7 | A Cordova wrapper around the Tencent QQ SDK for Android and iOS. Provides access to QQ ssoLogin, QQ Sharing, QQ Zone Sharing etc.. [简体中文](https://github.com/iVanPan/Cordova_QQ/blob/master/README_ZH.md). 8 | 9 | 10 | 11 | ## Table of Contents 12 | 13 | - [Feature](#feature) 14 | - [Requirements](#requirements) 15 | - [Installation](#installation) 16 | - [Documentation](#documentation) 17 | - [Error Code](#error-code) 18 | - [Support API](#support-api) 19 | - [Image](#image) 20 | - [Usage](#usage) 21 | - [checkClientInstalled](#checkclientinstalled) 22 | - [ssoLogin](#ssologin) 23 | - [logout](#logout) 24 | - [shareText](#sharetext) 25 | - [shareImage](#shareimage) 26 | - [shareNews](#sharenews) 27 | - [shareAudio](#shareaudio) 28 | - [getUserInfo](#getuserinfo) 29 | - [About SDK](#about-sdk) 30 | - [Notes](#notes) 31 | - [Demo](#demo) 32 | - [Contributing](#contributing) 33 | - [License](#license) 34 | 35 | ## Feature 36 | 1. QQ SSO Login 37 | 2. QQ Logout 38 | 3. QQ Share (Text、Image、News、Audio) 39 | 4. QQZone Share(Text、Image、News、Audio) 40 | 5. QQ Favorites(Text、Image、News、Audio) 41 | 6. checkClientInstalled 42 | 43 | ## Requirements 44 | - Cordova Version 3.5+ 45 | - Cordova-Android >= 7.0 46 | - Cordova-iOS >= 4.0 47 | 48 | ## Installation 49 | 1.```cordova plugin add cordova-plugin-qqsdk --variable QQ_APP_ID=YOUR_QQ_APPID``` 50 | 2. cordova build 51 | 52 | ## Documentation 53 | 54 | ### Support API 55 | 1. ssoLogin 56 | 2. Logout 57 | 3. checkClientInstalled 58 | 4. Share(see form below) 59 | 60 | | Platform | iOS | iOS   | iOS   | Android | Android | Android | 61 | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | 62 | | ShareScene  |  QQ   |   QQZone | QQ Favorite |  QQ   |   QQZone | QQ Favorite | 63 | | Text     |    √   |     √    | √       |    ✕    |     √    | √       | 64 | | Image     |    √   |   √  | √     |    √  |   √  | √     | 65 | |     News       |    √   |     √    |     √       |    √    |     √    |     √       | 66 | |     Audio       |    √   |     √    |     √       |    √    |     √    |     √       | 67 | 68 | 69 | ### Error Code 70 | When you use qq login,you may get an error code.If you get one, find detail error msg from [here](http://wiki.open.qq.com/wiki/mobile/API%E8%B0%83%E7%94%A8%E8%AF%B4%E6%98%8E#6._.E8.BF.94.E5.9B.9E.E7.A0.81.E8.AF.B4.E6.98.8E%E3%80%82) please. 71 | 72 | ### Image 73 | This plugin support three Image types: 74 | 1. Network URL 75 | 2. Base64 76 | 3. Absolute file path 77 | 78 | ### Usage 79 | ##### checkClientInstalled 80 | ```js 81 | var args = {}; 82 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 83 | QQSDK.checkClientInstalled(function () { 84 | alert('client is installed'); 85 | }, function () { 86 | // if installed QQ Client version is not supported sso,also will get this error 87 | alert('client is not installed'); 88 | }, args); 89 | ``` 90 | ##### ssoLogin 91 | ```js 92 | var args = {}; 93 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 94 | QQSDK.ssoLogin(function (result) { 95 | alert('token is ' + result.access_token); 96 | alert('userid is ' + result.userid); 97 | alert('expires_time is ' + new Date(parseInt(result.expires_time)) + ' TimeStamp is ' + result.expires_time); 98 | }, function (failReason) { 99 | alert(failReason); 100 | }, args); 101 | 102 | ``` 103 | ##### logout 104 | ```js 105 | QQSDK.logout(function () { 106 | alert('logout success'); 107 | }, function (failReason) { 108 | alert(failReason); 109 | }); 110 | ``` 111 | ##### shareText 112 | ```js 113 | var args = {}; 114 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 115 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 116 | args.text = '这个是 Cordova QQ 分享文字'; 117 | QQSDK.shareText(function () { 118 | alert('shareText success'); 119 | }, function (failReason) { 120 | alert(failReason); 121 | }, args); 122 | ``` 123 | ##### shareImage 124 | ```js 125 | var args = {}; 126 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 127 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 128 | args.title = '这个是 Cordova QQ 图片分享的标题'; 129 | args.description = '这个是 Cordova QQ 图片分享的描述'; 130 | args.image = 'https://cordova.apache.org/static/img/cordova_bot.png'; 131 | QQSDK.shareImage(function () { 132 | alert('shareImage success'); 133 | }, function (failReason) { 134 | alert(failReason); 135 | }, args); 136 | ``` 137 | ##### shareNews 138 | ```js 139 | var args = {}; 140 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 141 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 142 | args.url = 'https://cordova.apache.org/'; 143 | args.title = '这个是 Cordova QQ 新闻分享的标题'; 144 | args.description = '这个是 Cordova QQ 新闻分享的描述'; 145 | args.image = 'https://cordova.apache.org/static/img/cordova_bot.png'; 146 | QQSDK.shareNews(function () { 147 | alert('shareNews success'); 148 | }, function (failReason) { 149 | alert(failReason); 150 | }, args); 151 | ``` 152 | ##### shareAudio 153 | ```js 154 | var args = {}; 155 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 156 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 157 | args.url = 'https://y.qq.com/portal/song/001OyHbk2MSIi4.html'; 158 | args.title = '十年'; 159 | args.description = '陈奕迅'; 160 | args.image = 'https://y.gtimg.cn/music/photo_new/T001R300x300M000003Nz2So3XXYek.jpg'; 161 | args.flashUrl = 'http://stream20.qqmusic.qq.com/30577158.mp3'; 162 | QQSDK.shareAudio(function () { 163 | alert('shareAudio success'); 164 | }, function (failReason) { 165 | alert(failReason); 166 | }, args); 167 | ``` 168 | ##### getUserInfo 169 | ```js 170 | var url = 'https://graph.qq.com/user/get_user_info?access_token=' + accessToken + '&oauth_consumer_key=' + QQ_APP_ID + '&openid=' + userId; 171 | http.get(url) 172 | ``` 173 | 174 | ## About SDK 175 | This plugin use 3.2.1 version sdk for Android,3.2.3 version sdk for iOS. You can download lastest version sdk [here](http://wiki.open.qq.com/wiki/mobile/SDK%E4%B8%8B%E8%BD%BD) 176 | 177 | ## Notes 178 | 1. This plugin is required Cordova-Android version >=4.0,so using Cordova 5.0 or higher is recommended 179 | 2. This plugin should be used after the deviceready event has been fired!!! 180 | 3. ~~If Cordova version  <5.1.1,when two Cordova plugins are modifying “*-Info.plist” CFBundleURLTypes, only the first added plugin is getting the changes applied.so after installing plugin,please check the URLTypes in your Xcode project.You can find this issue [here](https://issues.apache.org/jira/browse/CB-8007)~~ Update:This Bug is fixed in last Cordova version(5.1.1) 181 | 4. For Android: make sure your signature is correct !!! 182 | 5. long share URL and large image shoud be avoid. 183 | 184 | ## Demo 185 | 1. install this plugin 186 | 2. backup www folder in your cordova project 187 | 3. replace www by example_www 188 | 4. install cordova-plugin-camera 189 | 5. cordova build & test 190 |
example
191 | 192 | 193 | ## Contributing 194 | Feel free to contribute 195 | 196 | ## License 197 | 198 | **cordova-plugin-qqsdk** is released under the **MIT** license. See [LICENSE](https://github.com/iVanPan/Cordova_QQ/blob/master/LICENSE) file for more information. 199 | 200 | 201 | 202 | 203 | -------------------------------------------------------------------------------- /README_ZH.md: -------------------------------------------------------------------------------- 1 | # cordova-plugin-qqsdk 2 | [![npm](https://img.shields.io/npm/v/cordova-plugin-qqsdk.svg)](https://www.npmjs.com/package/cordova-plugin-qqsdk) 3 | [![npm](https://img.shields.io/npm/dm/cordova-plugin-qqsdk.svg)](https://www.npmjs.com/package/cordova-plugin-qqsdk) 4 | [![platform](https://img.shields.io/badge/platform-iOS%2FAndroid-lightgrey.svg?style=flat)](https://github.com/iVanPan/Cordova_QQ) 5 | [![GitHub license](https://img.shields.io/github/license/mashape/apistatus.svg?style=flat)](https://github.com/iVanPan/Cordova_QQ/blob/master/LICENSE) 6 | 7 | 这个一个 QQ SDK 的 Cordova 插件。 [English](https://github.com/iVanPan/Cordova_QQ) 8 | 9 | 如果你希望使用一个微博的 Cordova 插件可以查看[这里](https://github.com/iVanPan/cordova_weibo).                     10 | 11 | 12 | ## Table of Contents 13 | 14 | - [功能](#功能) 15 | - [安装要求](#安装要求) 16 | - [安装](#安装) 17 | - [文档](#文档) 18 | - [支持的接口](#支持的接口) 19 | - [错误码](#错误码) 20 | - [关于图片](#关于图片) 21 | - [使用方式](#使用方式) 22 | - [检查客户端是否安装](#检查客户端是否安装) 23 | - [登录](#登录) 24 | - [登出](#登出) 25 | - [分享文字](#分享文字) 26 | - [分享图片](#分享图片) 27 | - [分享新闻](#分享音乐) 28 | - [分享音乐](#分享音乐) 29 | - [获取用户信息](#获取用户信息) 30 | - [关于SDK](#关于sdk) 31 | - [注意事项 ](#注意事项 ) 32 | - [Demo](#demo) 33 | - [贡献代码](#贡献代码) 34 | - [开源证书](#开源证书) 35 | 36 | ## 功能 37 | - QQ 登录 38 | - QQ 登出 39 | - QQ 分享(文字、图片、新闻网页、音乐) 40 | - QQ 空间分享(文字、图片、新闻网页、音乐) 41 | - QQ 收藏(文字、图片、新闻网页、音乐) 42 | - 检查 QQ 手机客户端端是否安装 43 | 44 | ## 安装要求 45 | - Cordova Version 3.5+ 46 | - Cordova-Android >= 7.0 47 | - Cordova-iOS >= 4.0 48 | 49 | 50 | ## 安装 51 | 1. 命令行运行 ```cordova plugin add cordova-plugin-qqsdk --variable QQ_APP_ID=YOUR_QQ_APPID``` 52 | 2. 命令行运行 cordova build 53 | 54 | 55 | ## 文档 56 | 57 | ### 支持的接口 58 | 1. ssoLogin 59 | 2. Logout 60 | 3. checkClientInstalled 61 | 4. Share(see form below) 62 | 63 | | Platform | iOS | iOS   | iOS   | Android | Android | Android | 64 | | :---: | :---: | :---: | :---: | :---: | :---: | :---: | 65 | | ShareScene  |  QQ   |   QQZone | QQ Favorite |  QQ   |   QQZone | QQ Favorite | 66 | | Text     |    √   |     √    | √       |    ✕    |     √    | √       | 67 | | Image     |    √   |   √  | √     |    √  |   √  | √     | 68 | |     News       |    √   |     √    |     √       |    √    |     √    |     √       | 69 | |      Audio       |    √   |     √    |     √       |    √    |     √    |     √       | 70 | 71 | 72 | ### 错误码 73 | 使用 SDK 时,所有结果都会通过回调返回给应用。在回调的结果中,会包含每次调用结果的返回码。 74 | 正常情况下返回码为 0,表示调用成功。 75 | 如果返回码不为 0,说明调用出错,需要根据返回码的值来定位错误原因。 76 | 110201:未登陆 77 | 110405:登录请求被限制 78 | 110404:请求参数缺少 appid 79 | 110401:请求的应用不存在 80 | 110407:应用已经下架 81 | 110406:应用没有通过审核 82 | 100044:错误的 sign 83 | 110500:获取用户授权信息失败 84 | 110501:获取应用的授权信息失败 85 | 110502:设置用户授权失败 86 | 110503:获取 token 失败 87 | 110504:系统内部错误 88 | 89 | 详情查看[这里](http://wiki.open.qq.com/wiki/mobile/API%E8%B0%83%E7%94%A8%E8%AF%B4%E6%98%8E#6._.E8.BF.94.E5.9B.9E.E7.A0.81.E8.AF.B4.E6.98.8E%E3%80%82) 90 | 91 | ### 关于图片 92 | 这个插件中的图片分享、新闻分享、音乐分享功能都要使用到图片,以下类型的图片在这些功能中都支持 93 | 1. 网络图片 94 | 2. Base64 95 | 3. 本地图片(图片的绝对路径) 96 | 97 | ### 使用方式 98 | ##### 检查客户端是否安装 99 | ```js 100 | var args = {}; 101 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 102 | QQSDK.checkClientInstalled(function () { 103 | alert('client is installed'); 104 | }, function () { 105 | // if installed QQ Client version is not supported sso,also will get this error 106 | alert('client is not installed'); 107 | }, args); 108 | ``` 109 | 110 | ##### 登录 111 | ```js 112 | var args = {}; 113 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 114 | QQSDK.ssoLogin(function (result) { 115 | alert('token is ' + result.access_token); 116 | alert('userid is ' + result.userid); 117 | alert('expires_time is ' + new Date(parseInt(result.expires_time)) + ' TimeStamp is ' + result.expires_time); 118 | }, function (failReason) { 119 | alert(failReason); 120 | }, args); 121 | 122 | ``` 123 | ##### 登出 124 | ```js 125 | QQSDK.logout(function () { 126 | alert('logout success'); 127 | }, function (failReason) { 128 | alert(failReason); 129 | }); 130 | ``` 131 | ##### 分享文字 132 | ```js 133 | var args = {}; 134 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 135 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 136 | args.text = '这个是 Cordova QQ 分享文字'; 137 | QQSDK.shareText(function () { 138 | alert('shareText success'); 139 | }, function (failReason) { 140 | alert(failReason); 141 | }, args); 142 | ``` 143 | ##### 分享图片 144 | ```js 145 | var args = {}; 146 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 147 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 148 | args.title = '这个是 Cordova QQ 图片分享的标题'; 149 | args.description = '这个是 Cordova QQ 图片分享的描述'; 150 | args.image = 'https://cordova.apache.org/static/img/cordova_bot.png'; 151 | QQSDK.shareImage(function () { 152 | alert('shareImage success'); 153 | }, function (failReason) { 154 | alert(failReason); 155 | }, args); 156 | ``` 157 | ##### 分享新闻 158 | ```js 159 | var args = {}; 160 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 161 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 162 | args.url = 'https://cordova.apache.org/'; 163 | args.title = '这个是 Cordova QQ 新闻分享的标题'; 164 | args.description = '这个是 Cordova QQ 新闻分享的描述'; 165 | args.image = 'https://cordova.apache.org/static/img/cordova_bot.png'; 166 | QQSDK.shareNews(function () { 167 | alert('shareNews success'); 168 | }, function (failReason) { 169 | alert(failReason); 170 | }, args); 171 | ``` 172 | ##### 分享音乐 173 | ```js 174 | var args = {}; 175 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 176 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 177 | args.url = 'https://y.qq.com/portal/song/001OyHbk2MSIi4.html'; 178 | args.title = '十年'; 179 | args.description = '陈奕迅'; 180 | args.image = 'https://y.gtimg.cn/music/photo_new/T001R300x300M000003Nz2So3XXYek.jpg'; 181 | args.flashUrl = 'http://stream20.qqmusic.qq.com/30577158.mp3'; 182 | QQSDK.shareAudio(function () { 183 | alert('shareAudio success'); 184 | }, function (failReason) { 185 | alert(failReason); 186 | }, args); 187 | ``` 188 | ##### 获取用户信息 189 | ```js 190 | var url = 'https://graph.qq.com/user/get_user_info?access_token=' + accessToken + '&oauth_consumer_key=' + QQ_APP_ID + '&openid=' + userId; 191 | http.get(url) 192 | ``` 193 | 194 | ## 关于SDK 195 | 本插件 Android SDK 的版本是 3.2.1,iOS SDK 的版本是 3.2.3,你可以在[这里](http://wiki.open.qq.com/wiki/mobile/SDK%E4%B8%8B%E8%BD%BD)下载最新版本的 SDK 196 | 197 | ## 注意事项 198 | **请认真阅读文档,请认真阅读文档,请认真阅读文档** 199 | 1. 这个插件要求 Cordova-Android 的版本 >= 4.0,推荐使用 Cordova 5.0 或更高的版本,因为从 Cordova 5.0 开始 Cordova-Android 4.0 是默认使用的 Android 版本 200 | 2. 请在 Cordova 的 deviceready 事件触发以后再调用本插件!!! 201 | 3. 在低于 5.1.1 的 Cordova 版本中存在一个 Bug,如果你有多个插件要修改 iOS 工程中的 “*-Info.plist” CFBundleURLTypes, 只有第一个安装的插件才会生效.所以安装完插件请务必在你的 Xcode 工程里面检查一下 URLTypes。 关于这个 bug 的详情你可以在 [这里](https://issues.apache.org/jira/browse/CB-8007)找到 建议安装使用 5.1.1 及以上的 Cordova 版本 202 | 4. Android 版本请确保你的签名是正确的 203 | 5. 分享的 URL 长度不要过长,图片不要太大,不然会分享失败,因为 SDK 做了限制 204 | 205 | 206 | 207 | ## Demo 208 | 在安装完这个插件以后,把 Cordova 工程中的代码替换为 example_www 中的代码,安装 Cordova 相机插件,在 build 以后可以进行各个功能测试,以下为运行效果图: 209 |
example
210 | 211 | ## 贡献代码 212 | 欢迎提交 PR,贡献你的代码,如果有新功能,请提供 Demo。 213 | 214 | ## 开源证书 215 | 216 | **cordova-plugin-qqsdk** 遵照了 **MIT** 证书. 详情可以查看 [证书](https://github.com/iVanPan/Cordova_QQ/blob/master/LICENSE) 文件 217 | -------------------------------------------------------------------------------- /ScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iVanPan/Cordova_QQ/8c799b5a1c055d39321db390d6f53e4e4bfe239c/ScreenShot.png -------------------------------------------------------------------------------- /example_www/css/bootstrap.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2017 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | /*! 8 | * Generated using the Bootstrap Customizer () 9 | * Config saved to config.json and 10 | */ 11 | /*! 12 | * Bootstrap v3.3.7 (http://getbootstrap.com) 13 | * Copyright 2011-2016 Twitter, Inc. 14 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 15 | */ 16 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ 17 | html { 18 | font-family: sans-serif; 19 | -ms-text-size-adjust: 100%; 20 | -webkit-text-size-adjust: 100%; 21 | } 22 | body { 23 | margin: 0; 24 | } 25 | article, 26 | aside, 27 | details, 28 | figcaption, 29 | figure, 30 | footer, 31 | header, 32 | hgroup, 33 | main, 34 | menu, 35 | nav, 36 | section, 37 | summary { 38 | display: block; 39 | } 40 | audio, 41 | canvas, 42 | progress, 43 | video { 44 | display: inline-block; 45 | vertical-align: baseline; 46 | } 47 | audio:not([controls]) { 48 | display: none; 49 | height: 0; 50 | } 51 | [hidden], 52 | template { 53 | display: none; 54 | } 55 | a { 56 | background-color: transparent; 57 | } 58 | a:active, 59 | a:hover { 60 | outline: 0; 61 | } 62 | abbr[title] { 63 | border-bottom: 1px dotted; 64 | } 65 | b, 66 | strong { 67 | font-weight: bold; 68 | } 69 | dfn { 70 | font-style: italic; 71 | } 72 | h1 { 73 | font-size: 2em; 74 | margin: 0.67em 0; 75 | } 76 | mark { 77 | background: #ff0; 78 | color: #000; 79 | } 80 | small { 81 | font-size: 80%; 82 | } 83 | sub, 84 | sup { 85 | font-size: 75%; 86 | line-height: 0; 87 | position: relative; 88 | vertical-align: baseline; 89 | } 90 | sup { 91 | top: -0.5em; 92 | } 93 | sub { 94 | bottom: -0.25em; 95 | } 96 | img { 97 | border: 0; 98 | } 99 | svg:not(:root) { 100 | overflow: hidden; 101 | } 102 | figure { 103 | margin: 1em 40px; 104 | } 105 | hr { 106 | -webkit-box-sizing: content-box; 107 | -moz-box-sizing: content-box; 108 | box-sizing: content-box; 109 | height: 0; 110 | } 111 | pre { 112 | overflow: auto; 113 | } 114 | code, 115 | kbd, 116 | pre, 117 | samp { 118 | font-family: monospace, monospace; 119 | font-size: 1em; 120 | } 121 | button, 122 | input, 123 | optgroup, 124 | select, 125 | textarea { 126 | color: inherit; 127 | font: inherit; 128 | margin: 0; 129 | } 130 | button { 131 | overflow: visible; 132 | } 133 | button, 134 | select { 135 | text-transform: none; 136 | } 137 | button, 138 | html input[type="button"], 139 | input[type="reset"], 140 | input[type="submit"] { 141 | -webkit-appearance: button; 142 | cursor: pointer; 143 | } 144 | button[disabled], 145 | html input[disabled] { 146 | cursor: default; 147 | } 148 | button::-moz-focus-inner, 149 | input::-moz-focus-inner { 150 | border: 0; 151 | padding: 0; 152 | } 153 | input { 154 | line-height: normal; 155 | } 156 | input[type="checkbox"], 157 | input[type="radio"] { 158 | -webkit-box-sizing: border-box; 159 | -moz-box-sizing: border-box; 160 | box-sizing: border-box; 161 | padding: 0; 162 | } 163 | input[type="number"]::-webkit-inner-spin-button, 164 | input[type="number"]::-webkit-outer-spin-button { 165 | height: auto; 166 | } 167 | input[type="search"] { 168 | -webkit-appearance: textfield; 169 | -webkit-box-sizing: content-box; 170 | -moz-box-sizing: content-box; 171 | box-sizing: content-box; 172 | } 173 | input[type="search"]::-webkit-search-cancel-button, 174 | input[type="search"]::-webkit-search-decoration { 175 | -webkit-appearance: none; 176 | } 177 | fieldset { 178 | border: 1px solid #c0c0c0; 179 | margin: 0 2px; 180 | padding: 0.35em 0.625em 0.75em; 181 | } 182 | legend { 183 | border: 0; 184 | padding: 0; 185 | } 186 | textarea { 187 | overflow: auto; 188 | } 189 | optgroup { 190 | font-weight: bold; 191 | } 192 | table { 193 | border-collapse: collapse; 194 | border-spacing: 0; 195 | } 196 | td, 197 | th { 198 | padding: 0; 199 | } 200 | * { 201 | -webkit-box-sizing: border-box; 202 | -moz-box-sizing: border-box; 203 | box-sizing: border-box; 204 | } 205 | *:before, 206 | *:after { 207 | -webkit-box-sizing: border-box; 208 | -moz-box-sizing: border-box; 209 | box-sizing: border-box; 210 | } 211 | html { 212 | font-size: 10px; 213 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 214 | } 215 | body { 216 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 217 | font-size: 14px; 218 | line-height: 1.42857143; 219 | color: #333333; 220 | background-color: #ffffff; 221 | } 222 | input, 223 | button, 224 | select, 225 | textarea { 226 | font-family: inherit; 227 | font-size: inherit; 228 | line-height: inherit; 229 | } 230 | a { 231 | color: #337ab7; 232 | text-decoration: none; 233 | } 234 | a:hover, 235 | a:focus { 236 | color: #23527c; 237 | text-decoration: underline; 238 | } 239 | a:focus { 240 | outline: 5px auto -webkit-focus-ring-color; 241 | outline-offset: -2px; 242 | } 243 | figure { 244 | margin: 0; 245 | } 246 | img { 247 | vertical-align: middle; 248 | } 249 | .img-responsive { 250 | display: block; 251 | max-width: 100%; 252 | height: auto; 253 | } 254 | .img-rounded { 255 | border-radius: 6px; 256 | } 257 | .img-thumbnail { 258 | padding: 4px; 259 | line-height: 1.42857143; 260 | background-color: #ffffff; 261 | border: 1px solid #dddddd; 262 | border-radius: 4px; 263 | -webkit-transition: all 0.2s ease-in-out; 264 | -o-transition: all 0.2s ease-in-out; 265 | transition: all 0.2s ease-in-out; 266 | display: inline-block; 267 | max-width: 100%; 268 | height: auto; 269 | } 270 | .img-circle { 271 | border-radius: 50%; 272 | } 273 | hr { 274 | margin-top: 20px; 275 | margin-bottom: 20px; 276 | border: 0; 277 | border-top: 1px solid #eeeeee; 278 | } 279 | .sr-only { 280 | position: absolute; 281 | width: 1px; 282 | height: 1px; 283 | margin: -1px; 284 | padding: 0; 285 | overflow: hidden; 286 | clip: rect(0, 0, 0, 0); 287 | border: 0; 288 | } 289 | .sr-only-focusable:active, 290 | .sr-only-focusable:focus { 291 | position: static; 292 | width: auto; 293 | height: auto; 294 | margin: 0; 295 | overflow: visible; 296 | clip: auto; 297 | } 298 | [role="button"] { 299 | cursor: pointer; 300 | } 301 | .btn { 302 | display: inline-block; 303 | margin-bottom: 0; 304 | font-weight: normal; 305 | text-align: center; 306 | vertical-align: middle; 307 | -ms-touch-action: manipulation; 308 | touch-action: manipulation; 309 | cursor: pointer; 310 | background-image: none; 311 | border: 1px solid transparent; 312 | white-space: nowrap; 313 | padding: 6px 12px; 314 | font-size: 14px; 315 | line-height: 1.42857143; 316 | border-radius: 4px; 317 | -webkit-user-select: none; 318 | -moz-user-select: none; 319 | -ms-user-select: none; 320 | user-select: none; 321 | } 322 | .btn:focus, 323 | .btn:active:focus, 324 | .btn.active:focus, 325 | .btn.focus, 326 | .btn:active.focus, 327 | .btn.active.focus { 328 | outline: 5px auto -webkit-focus-ring-color; 329 | outline-offset: -2px; 330 | } 331 | .btn:hover, 332 | .btn:focus, 333 | .btn.focus { 334 | color: #333333; 335 | text-decoration: none; 336 | } 337 | .btn:active, 338 | .btn.active { 339 | outline: 0; 340 | background-image: none; 341 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 342 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); 343 | } 344 | .btn.disabled, 345 | .btn[disabled], 346 | fieldset[disabled] .btn { 347 | cursor: not-allowed; 348 | opacity: 0.65; 349 | filter: alpha(opacity=65); 350 | -webkit-box-shadow: none; 351 | box-shadow: none; 352 | } 353 | a.btn.disabled, 354 | fieldset[disabled] a.btn { 355 | pointer-events: none; 356 | } 357 | .btn-default { 358 | color: #333333; 359 | background-color: #ffffff; 360 | border-color: #cccccc; 361 | } 362 | .btn-default:focus, 363 | .btn-default.focus { 364 | color: #333333; 365 | background-color: #e6e6e6; 366 | border-color: #8c8c8c; 367 | } 368 | .btn-default:hover { 369 | color: #333333; 370 | background-color: #e6e6e6; 371 | border-color: #adadad; 372 | } 373 | .btn-default:active, 374 | .btn-default.active, 375 | .open > .dropdown-toggle.btn-default { 376 | color: #333333; 377 | background-color: #e6e6e6; 378 | border-color: #adadad; 379 | } 380 | .btn-default:active:hover, 381 | .btn-default.active:hover, 382 | .open > .dropdown-toggle.btn-default:hover, 383 | .btn-default:active:focus, 384 | .btn-default.active:focus, 385 | .open > .dropdown-toggle.btn-default:focus, 386 | .btn-default:active.focus, 387 | .btn-default.active.focus, 388 | .open > .dropdown-toggle.btn-default.focus { 389 | color: #333333; 390 | background-color: #d4d4d4; 391 | border-color: #8c8c8c; 392 | } 393 | .btn-default:active, 394 | .btn-default.active, 395 | .open > .dropdown-toggle.btn-default { 396 | background-image: none; 397 | } 398 | .btn-default.disabled:hover, 399 | .btn-default[disabled]:hover, 400 | fieldset[disabled] .btn-default:hover, 401 | .btn-default.disabled:focus, 402 | .btn-default[disabled]:focus, 403 | fieldset[disabled] .btn-default:focus, 404 | .btn-default.disabled.focus, 405 | .btn-default[disabled].focus, 406 | fieldset[disabled] .btn-default.focus { 407 | background-color: #ffffff; 408 | border-color: #cccccc; 409 | } 410 | .btn-default .badge { 411 | color: #ffffff; 412 | background-color: #333333; 413 | } 414 | .btn-primary { 415 | color: #ffffff; 416 | background-color: #337ab7; 417 | border-color: #2e6da4; 418 | } 419 | .btn-primary:focus, 420 | .btn-primary.focus { 421 | color: #ffffff; 422 | background-color: #286090; 423 | border-color: #122b40; 424 | } 425 | .btn-primary:hover { 426 | color: #ffffff; 427 | background-color: #286090; 428 | border-color: #204d74; 429 | } 430 | .btn-primary:active, 431 | .btn-primary.active, 432 | .open > .dropdown-toggle.btn-primary { 433 | color: #ffffff; 434 | background-color: #286090; 435 | border-color: #204d74; 436 | } 437 | .btn-primary:active:hover, 438 | .btn-primary.active:hover, 439 | .open > .dropdown-toggle.btn-primary:hover, 440 | .btn-primary:active:focus, 441 | .btn-primary.active:focus, 442 | .open > .dropdown-toggle.btn-primary:focus, 443 | .btn-primary:active.focus, 444 | .btn-primary.active.focus, 445 | .open > .dropdown-toggle.btn-primary.focus { 446 | color: #ffffff; 447 | background-color: #204d74; 448 | border-color: #122b40; 449 | } 450 | .btn-primary:active, 451 | .btn-primary.active, 452 | .open > .dropdown-toggle.btn-primary { 453 | background-image: none; 454 | } 455 | .btn-primary.disabled:hover, 456 | .btn-primary[disabled]:hover, 457 | fieldset[disabled] .btn-primary:hover, 458 | .btn-primary.disabled:focus, 459 | .btn-primary[disabled]:focus, 460 | fieldset[disabled] .btn-primary:focus, 461 | .btn-primary.disabled.focus, 462 | .btn-primary[disabled].focus, 463 | fieldset[disabled] .btn-primary.focus { 464 | background-color: #337ab7; 465 | border-color: #2e6da4; 466 | } 467 | .btn-primary .badge { 468 | color: #337ab7; 469 | background-color: #ffffff; 470 | } 471 | .btn-success { 472 | color: #ffffff; 473 | background-color: #5cb85c; 474 | border-color: #4cae4c; 475 | } 476 | .btn-success:focus, 477 | .btn-success.focus { 478 | color: #ffffff; 479 | background-color: #449d44; 480 | border-color: #255625; 481 | } 482 | .btn-success:hover { 483 | color: #ffffff; 484 | background-color: #449d44; 485 | border-color: #398439; 486 | } 487 | .btn-success:active, 488 | .btn-success.active, 489 | .open > .dropdown-toggle.btn-success { 490 | color: #ffffff; 491 | background-color: #449d44; 492 | border-color: #398439; 493 | } 494 | .btn-success:active:hover, 495 | .btn-success.active:hover, 496 | .open > .dropdown-toggle.btn-success:hover, 497 | .btn-success:active:focus, 498 | .btn-success.active:focus, 499 | .open > .dropdown-toggle.btn-success:focus, 500 | .btn-success:active.focus, 501 | .btn-success.active.focus, 502 | .open > .dropdown-toggle.btn-success.focus { 503 | color: #ffffff; 504 | background-color: #398439; 505 | border-color: #255625; 506 | } 507 | .btn-success:active, 508 | .btn-success.active, 509 | .open > .dropdown-toggle.btn-success { 510 | background-image: none; 511 | } 512 | .btn-success.disabled:hover, 513 | .btn-success[disabled]:hover, 514 | fieldset[disabled] .btn-success:hover, 515 | .btn-success.disabled:focus, 516 | .btn-success[disabled]:focus, 517 | fieldset[disabled] .btn-success:focus, 518 | .btn-success.disabled.focus, 519 | .btn-success[disabled].focus, 520 | fieldset[disabled] .btn-success.focus { 521 | background-color: #5cb85c; 522 | border-color: #4cae4c; 523 | } 524 | .btn-success .badge { 525 | color: #5cb85c; 526 | background-color: #ffffff; 527 | } 528 | .btn-info { 529 | color: #ffffff; 530 | background-color: #5bc0de; 531 | border-color: #46b8da; 532 | } 533 | .btn-info:focus, 534 | .btn-info.focus { 535 | color: #ffffff; 536 | background-color: #31b0d5; 537 | border-color: #1b6d85; 538 | } 539 | .btn-info:hover { 540 | color: #ffffff; 541 | background-color: #31b0d5; 542 | border-color: #269abc; 543 | } 544 | .btn-info:active, 545 | .btn-info.active, 546 | .open > .dropdown-toggle.btn-info { 547 | color: #ffffff; 548 | background-color: #31b0d5; 549 | border-color: #269abc; 550 | } 551 | .btn-info:active:hover, 552 | .btn-info.active:hover, 553 | .open > .dropdown-toggle.btn-info:hover, 554 | .btn-info:active:focus, 555 | .btn-info.active:focus, 556 | .open > .dropdown-toggle.btn-info:focus, 557 | .btn-info:active.focus, 558 | .btn-info.active.focus, 559 | .open > .dropdown-toggle.btn-info.focus { 560 | color: #ffffff; 561 | background-color: #269abc; 562 | border-color: #1b6d85; 563 | } 564 | .btn-info:active, 565 | .btn-info.active, 566 | .open > .dropdown-toggle.btn-info { 567 | background-image: none; 568 | } 569 | .btn-info.disabled:hover, 570 | .btn-info[disabled]:hover, 571 | fieldset[disabled] .btn-info:hover, 572 | .btn-info.disabled:focus, 573 | .btn-info[disabled]:focus, 574 | fieldset[disabled] .btn-info:focus, 575 | .btn-info.disabled.focus, 576 | .btn-info[disabled].focus, 577 | fieldset[disabled] .btn-info.focus { 578 | background-color: #5bc0de; 579 | border-color: #46b8da; 580 | } 581 | .btn-info .badge { 582 | color: #5bc0de; 583 | background-color: #ffffff; 584 | } 585 | .btn-warning { 586 | color: #ffffff; 587 | background-color: #f0ad4e; 588 | border-color: #eea236; 589 | } 590 | .btn-warning:focus, 591 | .btn-warning.focus { 592 | color: #ffffff; 593 | background-color: #ec971f; 594 | border-color: #985f0d; 595 | } 596 | .btn-warning:hover { 597 | color: #ffffff; 598 | background-color: #ec971f; 599 | border-color: #d58512; 600 | } 601 | .btn-warning:active, 602 | .btn-warning.active, 603 | .open > .dropdown-toggle.btn-warning { 604 | color: #ffffff; 605 | background-color: #ec971f; 606 | border-color: #d58512; 607 | } 608 | .btn-warning:active:hover, 609 | .btn-warning.active:hover, 610 | .open > .dropdown-toggle.btn-warning:hover, 611 | .btn-warning:active:focus, 612 | .btn-warning.active:focus, 613 | .open > .dropdown-toggle.btn-warning:focus, 614 | .btn-warning:active.focus, 615 | .btn-warning.active.focus, 616 | .open > .dropdown-toggle.btn-warning.focus { 617 | color: #ffffff; 618 | background-color: #d58512; 619 | border-color: #985f0d; 620 | } 621 | .btn-warning:active, 622 | .btn-warning.active, 623 | .open > .dropdown-toggle.btn-warning { 624 | background-image: none; 625 | } 626 | .btn-warning.disabled:hover, 627 | .btn-warning[disabled]:hover, 628 | fieldset[disabled] .btn-warning:hover, 629 | .btn-warning.disabled:focus, 630 | .btn-warning[disabled]:focus, 631 | fieldset[disabled] .btn-warning:focus, 632 | .btn-warning.disabled.focus, 633 | .btn-warning[disabled].focus, 634 | fieldset[disabled] .btn-warning.focus { 635 | background-color: #f0ad4e; 636 | border-color: #eea236; 637 | } 638 | .btn-warning .badge { 639 | color: #f0ad4e; 640 | background-color: #ffffff; 641 | } 642 | .btn-danger { 643 | color: #ffffff; 644 | background-color: #d9534f; 645 | border-color: #d43f3a; 646 | } 647 | .btn-danger:focus, 648 | .btn-danger.focus { 649 | color: #ffffff; 650 | background-color: #c9302c; 651 | border-color: #761c19; 652 | } 653 | .btn-danger:hover { 654 | color: #ffffff; 655 | background-color: #c9302c; 656 | border-color: #ac2925; 657 | } 658 | .btn-danger:active, 659 | .btn-danger.active, 660 | .open > .dropdown-toggle.btn-danger { 661 | color: #ffffff; 662 | background-color: #c9302c; 663 | border-color: #ac2925; 664 | } 665 | .btn-danger:active:hover, 666 | .btn-danger.active:hover, 667 | .open > .dropdown-toggle.btn-danger:hover, 668 | .btn-danger:active:focus, 669 | .btn-danger.active:focus, 670 | .open > .dropdown-toggle.btn-danger:focus, 671 | .btn-danger:active.focus, 672 | .btn-danger.active.focus, 673 | .open > .dropdown-toggle.btn-danger.focus { 674 | color: #ffffff; 675 | background-color: #ac2925; 676 | border-color: #761c19; 677 | } 678 | .btn-danger:active, 679 | .btn-danger.active, 680 | .open > .dropdown-toggle.btn-danger { 681 | background-image: none; 682 | } 683 | .btn-danger.disabled:hover, 684 | .btn-danger[disabled]:hover, 685 | fieldset[disabled] .btn-danger:hover, 686 | .btn-danger.disabled:focus, 687 | .btn-danger[disabled]:focus, 688 | fieldset[disabled] .btn-danger:focus, 689 | .btn-danger.disabled.focus, 690 | .btn-danger[disabled].focus, 691 | fieldset[disabled] .btn-danger.focus { 692 | background-color: #d9534f; 693 | border-color: #d43f3a; 694 | } 695 | .btn-danger .badge { 696 | color: #d9534f; 697 | background-color: #ffffff; 698 | } 699 | .btn-link { 700 | color: #337ab7; 701 | font-weight: normal; 702 | border-radius: 0; 703 | } 704 | .btn-link, 705 | .btn-link:active, 706 | .btn-link.active, 707 | .btn-link[disabled], 708 | fieldset[disabled] .btn-link { 709 | background-color: transparent; 710 | -webkit-box-shadow: none; 711 | box-shadow: none; 712 | } 713 | .btn-link, 714 | .btn-link:hover, 715 | .btn-link:focus, 716 | .btn-link:active { 717 | border-color: transparent; 718 | } 719 | .btn-link:hover, 720 | .btn-link:focus { 721 | color: #23527c; 722 | text-decoration: underline; 723 | background-color: transparent; 724 | } 725 | .btn-link[disabled]:hover, 726 | fieldset[disabled] .btn-link:hover, 727 | .btn-link[disabled]:focus, 728 | fieldset[disabled] .btn-link:focus { 729 | color: #777777; 730 | text-decoration: none; 731 | } 732 | .btn-lg { 733 | padding: 10px 16px; 734 | font-size: 18px; 735 | line-height: 1.3333333; 736 | border-radius: 6px; 737 | } 738 | .btn-sm { 739 | padding: 5px 10px; 740 | font-size: 12px; 741 | line-height: 1.5; 742 | border-radius: 3px; 743 | } 744 | .btn-xs { 745 | padding: 1px 5px; 746 | font-size: 12px; 747 | line-height: 1.5; 748 | border-radius: 3px; 749 | } 750 | .btn-block { 751 | display: block; 752 | width: 100%; 753 | } 754 | .btn-block + .btn-block { 755 | margin-top: 5px; 756 | } 757 | input[type="submit"].btn-block, 758 | input[type="reset"].btn-block, 759 | input[type="button"].btn-block { 760 | width: 100%; 761 | } 762 | .clearfix:before, 763 | .clearfix:after { 764 | content: " "; 765 | display: table; 766 | } 767 | .clearfix:after { 768 | clear: both; 769 | } 770 | .center-block { 771 | display: block; 772 | margin-left: auto; 773 | margin-right: auto; 774 | } 775 | .pull-right { 776 | float: right !important; 777 | } 778 | .pull-left { 779 | float: left !important; 780 | } 781 | .hide { 782 | display: none !important; 783 | } 784 | .show { 785 | display: block !important; 786 | } 787 | .invisible { 788 | visibility: hidden; 789 | } 790 | .text-hide { 791 | font: 0/0 a; 792 | color: transparent; 793 | text-shadow: none; 794 | background-color: transparent; 795 | border: 0; 796 | } 797 | .hidden { 798 | display: none !important; 799 | } 800 | .affix { 801 | position: fixed; 802 | } 803 | -------------------------------------------------------------------------------- /example_www/css/index.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | * { 20 | -webkit-tap-highlight-color: rgba(0,0,0,0); /* make transparent link selection, adjust last value opacity 0 to 1.0 */ 21 | } 22 | 23 | body { 24 | -webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */ 25 | -webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */ 26 | -webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */ 27 | background-color:#E4E4E4; 28 | background-image:linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%); 29 | background-image:-webkit-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%); 30 | background-image:-ms-linear-gradient(top, #A7A7A7 0%, #E4E4E4 51%); 31 | background-image:-webkit-gradient( 32 | linear, 33 | left top, 34 | left bottom, 35 | color-stop(0, #A7A7A7), 36 | color-stop(0.51, #E4E4E4) 37 | ); 38 | background-attachment:fixed; 39 | font-family:'HelveticaNeue-Light', 'HelveticaNeue', Helvetica, Arial, sans-serif; 40 | font-size:12px; 41 | height:100%; 42 | margin:0px; 43 | padding:0px; 44 | text-transform:uppercase; 45 | width:100%; 46 | } 47 | 48 | /* Portrait layout (default) */ 49 | .app { 50 | background:url(../img/logo.png) no-repeat center top; /* 170px x 200px */ 51 | position:absolute; /* position in the center of the screen */ 52 | left:50%; 53 | top:25%; 54 | height:50px; /* text area height */ 55 | width:225px; /* text area width */ 56 | text-align:center; 57 | padding:180px 0px 0px 0px; /* image height is 200px (bottom 20px are overlapped with text) */ 58 | margin:-115px 0px 0px -112px; /* offset vertical: half of image height and text area height */ 59 | /* offset horizontal: half of text area width */ 60 | } 61 | 62 | /* Landscape layout (with min-width) */ 63 | @media screen and (min-aspect-ratio: 1/1) and (min-width:400px) { 64 | .app { 65 | background-position:left center; 66 | padding:75px 0px 75px 170px; /* padding-top + padding-bottom + text area = image height */ 67 | margin:-90px 0px 0px -198px; /* offset vertical: half of image height */ 68 | /* offset horizontal: half of image width and text area width */ 69 | } 70 | } 71 | 72 | h1 { 73 | font-size:24px; 74 | font-weight:normal; 75 | margin:0px; 76 | overflow:visible; 77 | padding:0px; 78 | text-align:center; 79 | } 80 | 81 | .event { 82 | border-radius:4px; 83 | -webkit-border-radius:4px; 84 | color:#FFFFFF; 85 | font-size:12px; 86 | margin:0px 30px; 87 | padding:2px 0px; 88 | } 89 | 90 | .event.listening { 91 | background-color:#333333; 92 | display:block; 93 | } 94 | 95 | .event.received { 96 | background-color:#4B946A; 97 | display:none; 98 | } 99 | 100 | @keyframes fade { 101 | from { opacity: 1.0; } 102 | 50% { opacity: 0.4; } 103 | to { opacity: 1.0; } 104 | } 105 | 106 | @-webkit-keyframes fade { 107 | from { opacity: 1.0; } 108 | 50% { opacity: 0.4; } 109 | to { opacity: 1.0; } 110 | } 111 | 112 | .blink { 113 | animation:fade 3000ms infinite; 114 | -webkit-animation:fade 3000ms infinite; 115 | } 116 | -------------------------------------------------------------------------------- /example_www/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iVanPan/Cordova_QQ/8c799b5a1c055d39321db390d6f53e4e4bfe239c/example_www/img/logo.png -------------------------------------------------------------------------------- /example_www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 | Corodva QQ Plugin Exmaple 19 | 20 | 21 |
22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /example_www/js/index.js: -------------------------------------------------------------------------------- 1 | var app = function () { 2 | 3 | this.checkClientInstalled = function () { 4 | var args = {}; 5 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 6 | QQSDK.checkClientInstalled(function () { 7 | alert('client is installed'); 8 | }, function () { 9 | // if installed QQ Client version is not supported sso,also will get this error 10 | alert('client is not installed'); 11 | }, args); 12 | }; 13 | 14 | this.ssoLogin = function () { 15 | var args = {}; 16 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 17 | QQSDK.ssoLogin(function (result) { 18 | alert('token is ' + result.access_token); 19 | alert('userid is ' + result.userid); 20 | alert('expires_time is ' + new Date(parseInt(result.expires_time)) + ' TimeStamp is ' + result.expires_time); 21 | }, function (failReason) { 22 | alert(failReason); 23 | }, args); 24 | }; 25 | 26 | this.logout = function () { 27 | QQSDK.logout(function () { 28 | alert('logout success'); 29 | }, function (failReason) { 30 | alert(failReason); 31 | }); 32 | }; 33 | 34 | this.shareText = function () { 35 | var args = {}; 36 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 37 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 38 | args.text = '这个是 Cordova QQ 分享文字'; 39 | QQSDK.shareText(function () { 40 | alert('shareText success'); 41 | }, function (failReason) { 42 | alert(failReason); 43 | }, args); 44 | }; 45 | 46 | this.shareImage = function () { 47 | var args = {}; 48 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 49 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 50 | args.title = '这个是 Cordova QQ 图片分享的标题'; 51 | args.description = '这个是 Cordova QQ 图片分享的描述'; 52 | args.image = 'https://cordova.apache.org/static/img/cordova_bot.png'; 53 | QQSDK.shareImage(function () { 54 | alert('shareImage success'); 55 | }, function (failReason) { 56 | alert(failReason); 57 | }, args); 58 | }; 59 | 60 | this.shareBase64Image = function () { 61 | var base64 = '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'; 62 | var args = {}; 63 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 64 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 65 | args.title = '这个是 Cordova QQ 图片分享的标题'; 66 | args.description = '这个是 Cordova QQ 图片分享的描述'; 67 | args.image = base64; 68 | QQSDK.shareImage(function () { 69 | alert('shareImage success'); 70 | }, function (failReason) { 71 | alert(failReason); 72 | }, args); 73 | }; 74 | 75 | this.shareLocalImage = function () { 76 | var args = {}; 77 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 78 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 79 | args.title = '这个是 Cordova QQ 图片分享的标题'; 80 | args.description = '这个是 Cordova QQ 图片分享的描述'; 81 | args.image = 'https://cordova.apache.org/static/img/cordova_bot.png'; 82 | navigator.camera.getPicture(function (pic) { 83 | args.image = pic.split("://")[1]; 84 | console.log('pic is ', pic); 85 | QQSDK.shareImage(function () { 86 | alert('shareImage success'); 87 | }, function (failReason) { 88 | alert(failReason); 89 | }, args); 90 | }, null, {targetWidth: 60, targetHeight: 60} 91 | ); 92 | }; 93 | 94 | this.shareNews = function () { 95 | var args = {}; 96 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 97 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 98 | args.url = 'https://cordova.apache.org/'; 99 | args.title = '这个是 Cordova QQ 新闻分享的标题'; 100 | args.description = '这个是 Cordova QQ 新闻分享的描述'; 101 | args.image = 'https://cordova.apache.org/static/img/cordova_bot.png'; 102 | QQSDK.shareNews(function () { 103 | alert('shareNews success'); 104 | }, function (failReason) { 105 | alert(failReason); 106 | }, args); 107 | }; 108 | 109 | this.shareAudio = function () { 110 | var args = {}; 111 | args.client = QQSDK.ClientType.QQ;//QQSDK.ClientType.QQ,QQSDK.ClientType.TIM; 112 | args.scene = QQSDK.Scene.QQ;//QQSDK.Scene.QQZone,QQSDK.Scene.Favorite 113 | args.url = 'https://y.qq.com/portal/song/001OyHbk2MSIi4.html'; 114 | args.title = '十年'; 115 | args.description = '陈奕迅'; 116 | args.image = 'https://y.gtimg.cn/music/photo_new/T001R300x300M000003Nz2So3XXYek.jpg'; 117 | args.flashUrl = 'http://stream20.qqmusic.qq.com/30577158.mp3'; 118 | QQSDK.shareAudio(function () { 119 | alert('shareAudio success'); 120 | }, function (failReason) { 121 | alert(failReason); 122 | }, args); 123 | }; 124 | } 125 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-qqsdk", 3 | "version": "0.9.7", 4 | "description": "codrova/phonegap wrapper for qq sdk", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/iVanPan/Cordova_QQ.git" 12 | }, 13 | "cordova": { 14 | "id": "cordova-plugin-qqsdk", 15 | "platforms": [ 16 | "android", 17 | "ios" 18 | ] 19 | }, 20 | "keywords": [ 21 | "ecosystem:cordova", 22 | "cordova-android", 23 | "cordova-ios", 24 | "cordova", 25 | "phonegap", 26 | "plugin", 27 | "qqsdk", 28 | "qq", 29 | "TIM", 30 | "Tencent", 31 | "login", 32 | "share", 33 | "favorites" 34 | ], 35 | "engines": [ 36 | { 37 | "name": "cordova-android", 38 | "version": ">=7.0.0" 39 | } 40 | ], 41 | "author": "https://github.com/iVanPan", 42 | "license": "MIT", 43 | "bugs": { 44 | "url": "https://github.com/iVanPan/Cordova_QQ/issues" 45 | }, 46 | "homepage": "https://github.com/iVanPan/Cordova_QQ" 47 | } 48 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | QQSDK 9 | Cordova Plugin QQSDK 10 | MIT 11 | cordova,qq 12 | https://github.com/iVanPan/Cordova_QQ 13 | https://github.com/iVanPan/Cordova_QQ/issues 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 | 39 | 40 | 41 | CFBundleTypeRole 42 | Editor 43 | CFBundleURLName 44 | tencentopenapi 45 | CFBundleURLSchemes 46 | 47 | tencent$QQ_APP_ID 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | mqqapi 57 | mqq 58 | mqqOpensdkSSoLogin 59 | mqqconnect 60 | mqqopensdkdataline 61 | mqqopensdkgrouptribeshare 62 | mqqopensdkfriend 63 | mqqopensdkapi 64 | mqqopensdkapiV2 65 | mqqopensdkapiV3 66 | mqqopensdkapiV4 67 | mqzoneopensdk 68 | wtloginmqq 69 | wtloginmqq2 70 | mqqwpa 71 | mqzone 72 | mqzonev2 73 | mqzoneshare 74 | wtloginqzone 75 | mqzonewx 76 | mqzoneopensdkapiV2 77 | mqzoneopensdkapi19 78 | mqzoneopensdkapi 79 | mqzoneopensdk 80 | mqqgamebindinggroup 81 | tencentapi.qq.reqContent 82 | tencentapi.qzone.reqContent 83 | tim 84 | timapi 85 | timopensdkfriend 86 | timwpa 87 | timgamebindinggroup 88 | timapiwallet 89 | timOpensdkSSoLogin 90 | wtlogintim 91 | timopensdkgrouptribeshare 92 | timopensdkapiV4 93 | timgamebindinggroup 94 | timopensdkdataline 95 | wtlogintimV1 96 | timapiV1 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 1.安装完这个插件,请用 Xcode 打开工程,查看 URL Types 里面 QQ 的 URL Type 有没有,如果没有请手动添加。 116 | 1.after installing this plugin,check the URL Types in your Xcode project.If you don't find URL Types for QQ SDK,manually add it. 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /src/android/QQSDKPlugin.java: -------------------------------------------------------------------------------- 1 | package me.vanpan.qqsdk; 2 | 3 | import android.content.Intent; 4 | import android.content.pm.ApplicationInfo; 5 | import android.content.pm.PackageManager; 6 | import android.graphics.Bitmap; 7 | import android.graphics.BitmapFactory; 8 | import android.os.Bundle; 9 | import android.text.TextUtils; 10 | import android.util.Base64; 11 | import android.util.Log; 12 | import android.webkit.URLUtil; 13 | import com.tencent.connect.common.Constants; 14 | import com.tencent.connect.share.QQShare; 15 | import com.tencent.connect.share.QzonePublish; 16 | import com.tencent.connect.share.QzoneShare; 17 | import com.tencent.open.GameAppOperation; 18 | import com.tencent.tauth.IUiListener; 19 | import com.tencent.tauth.Tencent; 20 | import com.tencent.tauth.UiError; 21 | import java.io.File; 22 | import java.io.FileNotFoundException; 23 | import java.io.FileOutputStream; 24 | import java.io.IOException; 25 | import java.io.InputStream; 26 | import java.net.HttpURLConnection; 27 | import java.net.URL; 28 | import java.text.SimpleDateFormat; 29 | import java.util.ArrayList; 30 | import java.util.Date; 31 | import org.apache.cordova.CallbackContext; 32 | import org.apache.cordova.CordovaArgs; 33 | import org.apache.cordova.CordovaPlugin; 34 | import org.apache.cordova.PluginResult; 35 | import org.json.JSONException; 36 | import org.json.JSONObject; 37 | 38 | import static org.apache.cordova.CordovaActivity.TAG; 39 | 40 | /** 41 | * Project: QQSDKPlugin 42 | * Created by Van on 2016/12/16. 43 | */ 44 | 45 | class ShareScene { 46 | public static final int QQ = 0; 47 | public static final int QQZone = 1; 48 | public static final int Favorite = 2; 49 | } 50 | 51 | public class QQSDKPlugin extends CordovaPlugin { 52 | private static Tencent mTencent; 53 | private CallbackContext currentCallbackContext; 54 | private String APP_ID; 55 | private static final String QQ_APP_ID = "qq_app_id"; 56 | private static final String QQ_CANCEL_BY_USER = "cancelled by user"; 57 | private static final String QQ_RESPONSE_ERROR = "QQ response is error"; 58 | private static final String QZONE_SHARE_CANCEL = "QZone share is cancelled"; 59 | private static final String QQFAVORITES_CANCEL = "QQ Favorites is cancelled"; 60 | private static final String QQ_Client_NOT_INSYALLED_ERROR = "QQ client is not installed"; 61 | private static final String QQ_PARAM_ERROR = "param incorrect"; 62 | 63 | @Override protected void pluginInitialize() { 64 | super.pluginInitialize(); 65 | APP_ID = webView.getPreferences().getString(QQ_APP_ID, ""); 66 | mTencent = Tencent.createInstance(APP_ID, this.cordova.getActivity().getApplicationContext()); 67 | } 68 | 69 | @Override 70 | public boolean execute(String action, final CordovaArgs args, final CallbackContext callbackContext) 71 | throws JSONException { 72 | if (action.equalsIgnoreCase("checkClientInstalled")) { 73 | return checkClientInstalled(callbackContext); 74 | } 75 | if (action.equals("ssoLogin")) { 76 | return ssoLogin(callbackContext); 77 | } 78 | if (action.equals("logout")) { 79 | return logout(callbackContext); 80 | } 81 | if (action.equals("shareText")) { 82 | return shareText(args,callbackContext); 83 | } 84 | if (action.equals("shareImage")) { 85 | return shareImage(args,callbackContext); 86 | } 87 | if (action.equals("shareNews")) { 88 | return shareNews(args,callbackContext); 89 | } 90 | if (action.equals("shareAudio")) { 91 | return shareAudio(args,callbackContext); 92 | } 93 | return super.execute(action, args, callbackContext); 94 | } 95 | 96 | /** 97 | * 检查手机QQ客户端是否安装 98 | */ 99 | private boolean checkClientInstalled(CallbackContext callbackContext) { 100 | Boolean installed = mTencent.isSupportSSOLogin(QQSDKPlugin.this.cordova.getActivity()); 101 | if (installed) { 102 | callbackContext.success(); 103 | } else { 104 | callbackContext.error(QQ_Client_NOT_INSYALLED_ERROR); 105 | } 106 | return true; 107 | } 108 | 109 | /** 110 | * QQ 单点登录 111 | */ 112 | private boolean ssoLogin(CallbackContext callbackContext) { 113 | currentCallbackContext = callbackContext; 114 | Runnable runnable = new Runnable() { 115 | @Override public void run() { 116 | mTencent.login(QQSDKPlugin.this.cordova.getActivity(), "all", loginListener); 117 | } 118 | }; 119 | this.cordova.getActivity().runOnUiThread(runnable); 120 | this.cordova.setActivityResultCallback(this); 121 | return true; 122 | } 123 | 124 | /** 125 | * QQ 登出 126 | */ 127 | private boolean logout(CallbackContext callbackContext) { 128 | mTencent.logout(this.cordova.getActivity()); 129 | callbackContext.success(); 130 | return true; 131 | } 132 | 133 | public boolean shareText(CordovaArgs args, CallbackContext callbackContext) { 134 | final Bundle params = new Bundle(); 135 | currentCallbackContext = callbackContext; 136 | final JSONObject data; 137 | try { 138 | data = args.getJSONObject(0); 139 | String text = data.has("text")? data.getString("text"): ""; 140 | int shareScene = data.has("scene")? data.getInt("scene"): 0; 141 | switch (shareScene) { 142 | case ShareScene.QQ: 143 | callbackContext.error("Android 不支持分享文字到 QQ"); 144 | break; 145 | case ShareScene.Favorite: 146 | params.putInt(GameAppOperation.QQFAV_DATALINE_REQTYPE, 147 | GameAppOperation.QQFAV_DATALINE_TYPE_TEXT); 148 | params.putString(GameAppOperation.QQFAV_DATALINE_TITLE, getAppName()); 149 | params.putString(GameAppOperation.QQFAV_DATALINE_DESCRIPTION, text); 150 | params.putString(GameAppOperation.QQFAV_DATALINE_APPNAME, getAppName()); 151 | Runnable favoritesRunnable = new Runnable() { 152 | @Override public void run() { 153 | mTencent.addToQQFavorites(QQSDKPlugin.this.cordova.getActivity(), params, 154 | addToQQFavoritesListener); 155 | } 156 | }; 157 | this.cordova.getActivity().runOnUiThread(favoritesRunnable); 158 | this.cordova.setActivityResultCallback(this); 159 | break; 160 | case ShareScene.QQZone: 161 | params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE, 162 | QzonePublish.PUBLISH_TO_QZONE_TYPE_PUBLISHMOOD); 163 | params.putString(QzoneShare.SHARE_TO_QQ_TITLE, text); 164 | Runnable zoneRunnable = new Runnable() { 165 | 166 | @Override public void run() { 167 | mTencent.publishToQzone(QQSDKPlugin.this.cordova.getActivity(), params, 168 | qZoneShareListener); 169 | } 170 | }; 171 | this.cordova.getActivity().runOnUiThread(zoneRunnable); 172 | this.cordova.setActivityResultCallback(this); 173 | break; 174 | default: 175 | break; 176 | } 177 | } catch (JSONException e) { 178 | callbackContext.error(QQ_PARAM_ERROR); 179 | return true; 180 | } 181 | return true; 182 | } 183 | 184 | public boolean shareImage(CordovaArgs args, CallbackContext callbackContext) { 185 | currentCallbackContext = callbackContext; 186 | final JSONObject data; 187 | try { 188 | data = args.getJSONObject(0); 189 | String title = data.has("title")? data.getString("title"): ""; 190 | String description = data.has("description")? data.getString("description"): ""; 191 | String image = data.has("image")? data.getString("image"): ""; 192 | int shareScene = data.has("scene")? data.getInt("scene"): 0; 193 | image = processImage(image); 194 | final Bundle params = new Bundle(); 195 | switch (shareScene) { 196 | case ShareScene.QQ: 197 | params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_IMAGE); 198 | params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, image); 199 | params.putString(QQShare.SHARE_TO_QQ_TITLE, title); 200 | params.putString(QQShare.SHARE_TO_QQ_SUMMARY, description); 201 | Runnable qqRunnable = new Runnable() { 202 | 203 | @Override public void run() { 204 | mTencent.shareToQQ(QQSDKPlugin.this.cordova.getActivity(), params, qqShareListener); 205 | } 206 | }; 207 | this.cordova.getActivity().runOnUiThread(qqRunnable); 208 | this.cordova.setActivityResultCallback(this); 209 | break; 210 | case ShareScene.Favorite: 211 | ArrayList imageUrls = new ArrayList(); 212 | imageUrls.add(image); 213 | params.putInt(GameAppOperation.QQFAV_DATALINE_REQTYPE, 214 | GameAppOperation.QQFAV_DATALINE_TYPE_IMAGE_TEXT); 215 | params.putString(GameAppOperation.QQFAV_DATALINE_TITLE, title); 216 | params.putString(GameAppOperation.QQFAV_DATALINE_DESCRIPTION, description); 217 | params.putString(GameAppOperation.QQFAV_DATALINE_IMAGEURL, image); 218 | params.putString(GameAppOperation.QQFAV_DATALINE_APPNAME, getAppName()); 219 | params.putStringArrayList(GameAppOperation.QQFAV_DATALINE_FILEDATA, imageUrls); 220 | Runnable favoritesRunnable = new Runnable() { 221 | @Override public void run() { 222 | mTencent.addToQQFavorites(QQSDKPlugin.this.cordova.getActivity(), params, 223 | addToQQFavoritesListener); 224 | } 225 | }; 226 | this.cordova.getActivity().runOnUiThread(favoritesRunnable); 227 | this.cordova.setActivityResultCallback(this); 228 | break; 229 | case ShareScene.QQZone: 230 | params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_IMAGE); 231 | params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, image); 232 | params.putString(QQShare.SHARE_TO_QQ_TITLE, title); 233 | params.putString(QQShare.SHARE_TO_QQ_SUMMARY, description); 234 | params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, QQShare.SHARE_TO_QQ_FLAG_QZONE_AUTO_OPEN); 235 | Runnable zoneRunnable = new Runnable() { 236 | 237 | @Override public void run() { 238 | mTencent.shareToQQ(QQSDKPlugin.this.cordova.getActivity(), params, qqShareListener); 239 | } 240 | }; 241 | this.cordova.getActivity().runOnUiThread(zoneRunnable); 242 | this.cordova.setActivityResultCallback(this); 243 | break; 244 | default: 245 | break; 246 | } 247 | } catch (JSONException e) { 248 | callbackContext.error(QQ_PARAM_ERROR); 249 | return true; 250 | } 251 | return true; 252 | } 253 | 254 | public boolean shareNews(CordovaArgs args, CallbackContext callbackContext) { 255 | currentCallbackContext = callbackContext; 256 | final JSONObject data; 257 | try { 258 | data = args.getJSONObject(0); 259 | String title = data.has("title")? data.getString("title"): ""; 260 | String description = data.has("description")? data.getString("description"): ""; 261 | String image = data.has("image")? data.getString("image"): ""; 262 | String url = data.has("url")? data.getString("url"): ""; 263 | int shareScene = data.has("scene")? data.getInt("scene"): 0; 264 | final Bundle params = new Bundle(); 265 | switch (shareScene) { 266 | case ShareScene.QQ: 267 | params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT); 268 | if(URLUtil.isHttpUrl(image) || URLUtil.isHttpsUrl(image)) { 269 | params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL,image); 270 | } else { 271 | params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL,processImage(image)); 272 | } 273 | params.putString(QQShare.SHARE_TO_QQ_TITLE, title); 274 | params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, url); 275 | params.putString(QQShare.SHARE_TO_QQ_SUMMARY, description); 276 | Runnable qqRunnable = new Runnable() { 277 | 278 | @Override public void run() { 279 | mTencent.shareToQQ(QQSDKPlugin.this.cordova.getActivity(), params, qqShareListener); 280 | } 281 | }; 282 | this.cordova.getActivity().runOnUiThread(qqRunnable); 283 | this.cordova.setActivityResultCallback(this); 284 | break; 285 | case ShareScene.Favorite: 286 | image = processImage(image); 287 | params.putInt(GameAppOperation.QQFAV_DATALINE_REQTYPE, 288 | GameAppOperation.QQFAV_DATALINE_TYPE_DEFAULT); 289 | params.putString(GameAppOperation.QQFAV_DATALINE_TITLE, title); 290 | params.putString(GameAppOperation.QQFAV_DATALINE_DESCRIPTION, description); 291 | params.putString(GameAppOperation.QQFAV_DATALINE_IMAGEURL, image); 292 | params.putString(GameAppOperation.QQFAV_DATALINE_URL, url); 293 | params.putString(GameAppOperation.QQFAV_DATALINE_APPNAME, getAppName()); 294 | Runnable favoritesRunnable = new Runnable() { 295 | @Override public void run() { 296 | mTencent.addToQQFavorites(QQSDKPlugin.this.cordova.getActivity(), params, 297 | addToQQFavoritesListener); 298 | } 299 | }; 300 | this.cordova.getActivity().runOnUiThread(favoritesRunnable); 301 | this.cordova.setActivityResultCallback(this); 302 | break; 303 | case ShareScene.QQZone: 304 | image = processImage(image); 305 | ArrayList imageUrls = new ArrayList(); 306 | imageUrls.add(image); 307 | params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE, 308 | QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT); 309 | params.putString(QzoneShare.SHARE_TO_QQ_TITLE, title); 310 | params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, description); 311 | params.putString(QzoneShare.SHARE_TO_QQ_TARGET_URL, url); 312 | params.putStringArrayList(QzoneShare.SHARE_TO_QQ_IMAGE_URL, imageUrls); 313 | Runnable zoneRunnable = new Runnable() { 314 | 315 | @Override public void run() { 316 | mTencent.shareToQzone(QQSDKPlugin.this.cordova.getActivity(), params, 317 | qZoneShareListener); 318 | } 319 | }; 320 | this.cordova.getActivity().runOnUiThread(zoneRunnable); 321 | this.cordova.setActivityResultCallback(this); 322 | break; 323 | default: 324 | break; 325 | } 326 | } catch (JSONException e) { 327 | callbackContext.error(QQ_PARAM_ERROR); 328 | return true; 329 | } 330 | return true; 331 | } 332 | 333 | public boolean shareAudio(CordovaArgs args, CallbackContext callbackContext) { 334 | currentCallbackContext = callbackContext; 335 | final JSONObject data; 336 | try { 337 | data = args.getJSONObject(0); 338 | String title = data.has("title")? data.getString("title"): ""; 339 | String description = data.has("description")? data.getString("description"): ""; 340 | String image = data.has("image")? data.getString("image"): ""; 341 | String url = data.has("url")? data.getString("url"): ""; 342 | String flashUrl = data.has("flashUrl")? data.getString("flashUrl"): ""; 343 | int shareScene = data.has("scene")? data.getInt("scene"): 0; 344 | final Bundle params = new Bundle(); 345 | switch (shareScene) { 346 | case ShareScene.QQ: 347 | params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT); 348 | if(URLUtil.isHttpUrl(image) || URLUtil.isHttpsUrl(image)) { 349 | params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL,image); 350 | } else { 351 | params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL,processImage(image)); 352 | } 353 | params.putString(QQShare.SHARE_TO_QQ_AUDIO_URL, flashUrl); 354 | params.putString(QQShare.SHARE_TO_QQ_TITLE, title); 355 | params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, url); 356 | params.putString(QQShare.SHARE_TO_QQ_SUMMARY, description); 357 | Runnable qqRunnable = new Runnable() { 358 | 359 | @Override public void run() { 360 | mTencent.shareToQQ(QQSDKPlugin.this.cordova.getActivity(), params, qqShareListener); 361 | } 362 | }; 363 | this.cordova.getActivity().runOnUiThread(qqRunnable); 364 | this.cordova.setActivityResultCallback(this); 365 | break; 366 | case ShareScene.Favorite: 367 | image = processImage(image); 368 | params.putInt(GameAppOperation.QQFAV_DATALINE_REQTYPE, 369 | GameAppOperation.QQFAV_DATALINE_TYPE_DEFAULT); 370 | params.putString(GameAppOperation.QQFAV_DATALINE_TITLE, title); 371 | params.putString(GameAppOperation.QQFAV_DATALINE_DESCRIPTION, description); 372 | params.putString(GameAppOperation.QQFAV_DATALINE_IMAGEURL, image); 373 | params.putString(GameAppOperation.QQFAV_DATALINE_URL, url); 374 | params.putString(GameAppOperation.QQFAV_DATALINE_APPNAME, getAppName()); 375 | params.putString(GameAppOperation.QQFAV_DATALINE_AUDIOURL, flashUrl); 376 | Runnable favoritesRunnable = new Runnable() { 377 | @Override public void run() { 378 | mTencent.addToQQFavorites(QQSDKPlugin.this.cordova.getActivity(), params, 379 | addToQQFavoritesListener); 380 | } 381 | }; 382 | this.cordova.getActivity().runOnUiThread(favoritesRunnable); 383 | this.cordova.setActivityResultCallback(this); 384 | break; 385 | case ShareScene.QQZone: 386 | image = processImage(image); 387 | ArrayList imageUrls = new ArrayList(); 388 | imageUrls.add(image); 389 | params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE, 390 | QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT); 391 | params.putString(QzoneShare.SHARE_TO_QQ_TITLE, title); 392 | params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, description); 393 | params.putString(QzoneShare.SHARE_TO_QQ_TARGET_URL, url); 394 | params.putString(QzoneShare.SHARE_TO_QQ_AUDIO_URL, flashUrl); 395 | params.putStringArrayList(QzoneShare.SHARE_TO_QQ_IMAGE_URL, imageUrls); 396 | Runnable zoneRunnable = new Runnable() { 397 | 398 | @Override public void run() { 399 | mTencent.shareToQzone(QQSDKPlugin.this.cordova.getActivity(), params, 400 | qZoneShareListener); 401 | } 402 | }; 403 | this.cordova.getActivity().runOnUiThread(zoneRunnable); 404 | this.cordova.setActivityResultCallback(this); 405 | break; 406 | default: 407 | break; 408 | } 409 | } catch (JSONException e) { 410 | callbackContext.error(QQ_PARAM_ERROR); 411 | return true; 412 | } 413 | return true; 414 | } 415 | 416 | /** 417 | * 保存token 和 openid 418 | */ 419 | public static void initOpenidAndToken(JSONObject jsonObject) { 420 | try { 421 | String token = jsonObject.getString(Constants.PARAM_ACCESS_TOKEN); 422 | String expires = jsonObject.getString(Constants.PARAM_EXPIRES_IN); 423 | String openId = jsonObject.getString(Constants.PARAM_OPEN_ID); 424 | if (!TextUtils.isEmpty(token) && !TextUtils.isEmpty(expires) && !TextUtils.isEmpty(openId)) { 425 | mTencent.setAccessToken(token, expires); 426 | mTencent.setOpenId(openId); 427 | } 428 | } catch (Exception e) { 429 | } 430 | } 431 | 432 | /** 433 | * 获取应用的名称 434 | */ 435 | private String getAppName() { 436 | PackageManager packageManager = this.cordova.getActivity().getPackageManager(); 437 | ApplicationInfo applicationInfo = null; 438 | try { 439 | applicationInfo = 440 | packageManager.getApplicationInfo(this.cordova.getActivity().getPackageName(), 0); 441 | } catch (final PackageManager.NameNotFoundException e) { 442 | } 443 | final String AppName = 444 | (String) ((applicationInfo != null) ? packageManager.getApplicationLabel(applicationInfo) 445 | : "AppName"); 446 | return AppName; 447 | } 448 | 449 | /** 450 | * 处理图片 451 | * @param image 452 | * @return 453 | */ 454 | private String processImage(String image) { 455 | if(URLUtil.isHttpUrl(image) || URLUtil.isHttpsUrl(image)) { 456 | return saveBitmapToFile(getBitmapFromURL(image)); 457 | } else if (isBase64(image)) { 458 | return saveBitmapToFile(decodeBase64ToBitmap(image)); 459 | } else if (image.startsWith("/") ){ 460 | File file = new File(image); 461 | return file.getAbsolutePath(); 462 | } else { 463 | return null; 464 | } 465 | } 466 | 467 | /** 468 | * 检查图片字符串是不是Base64 469 | * @param image 470 | * @return 471 | */ 472 | private boolean isBase64(String image) { 473 | try { 474 | byte[] decodedString = Base64.decode(image, Base64.DEFAULT); 475 | Bitmap bitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length); 476 | if (bitmap == null) { 477 | return false; 478 | } 479 | return true; 480 | } catch (Exception e) { 481 | return false; 482 | } 483 | } 484 | 485 | 486 | public static Bitmap getBitmapFromURL(String src) { 487 | try { 488 | URL url = new URL(src); 489 | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 490 | connection.setDoInput(true); 491 | connection.connect(); 492 | InputStream input = connection.getInputStream(); 493 | Bitmap bitmap = BitmapFactory.decodeStream(input); 494 | return bitmap; 495 | } catch (IOException e) { 496 | return null; 497 | } 498 | } 499 | 500 | /** 501 | * 将Base64解码成Bitmap 502 | */ 503 | 504 | private Bitmap decodeBase64ToBitmap(String Base64String) { 505 | byte[] decode = Base64.decode(Base64String, Base64.DEFAULT); 506 | Bitmap bitmap = BitmapFactory.decodeByteArray(decode, 0, decode.length); 507 | return bitmap; 508 | } 509 | 510 | /** 511 | * 将bitmap 保存成文件 512 | */ 513 | private String saveBitmapToFile(Bitmap bitmap) { 514 | File pictureFile = getOutputMediaFile(); 515 | if (pictureFile == null) { 516 | return null; 517 | } 518 | try { 519 | FileOutputStream fos = new FileOutputStream(pictureFile); 520 | bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos); 521 | fos.close(); 522 | } catch (FileNotFoundException e) { 523 | Log.d(TAG, "File not found: " + e.getMessage()); 524 | } catch (IOException e) { 525 | Log.d(TAG, "Error accessing file: " + e.getMessage()); 526 | } 527 | return pictureFile.getAbsolutePath(); 528 | } 529 | 530 | /** 531 | * 生成文件用来存储图片 532 | */ 533 | private File getOutputMediaFile() { 534 | File mediaStorageDir = this.cordova.getActivity().getExternalCacheDir(); 535 | if (!mediaStorageDir.exists()) { 536 | if (!mediaStorageDir.mkdirs()) { 537 | return null; 538 | } 539 | } 540 | String timeStamp = new SimpleDateFormat("ddMMyyyy_HHmm").format(new Date()); 541 | File mediaFile; 542 | String mImageName = "Cordova_" + timeStamp + ".jpg"; 543 | mediaFile = new File(mediaStorageDir.getPath() + File.separator + mImageName); 544 | return mediaFile; 545 | } 546 | 547 | /** 548 | * 登录监听 549 | */ 550 | IUiListener loginListener = new IUiListener() { 551 | @Override public void onComplete(Object response) { 552 | if (null == response) { 553 | QQSDKPlugin.this.webView.sendPluginResult( 554 | new PluginResult(PluginResult.Status.ERROR, QQ_RESPONSE_ERROR), 555 | currentCallbackContext.getCallbackId()); 556 | return; 557 | } 558 | JSONObject jsonResponse = (JSONObject) response; 559 | if (null != jsonResponse && jsonResponse.length() == 0) { 560 | QQSDKPlugin.this.webView.sendPluginResult( 561 | new PluginResult(PluginResult.Status.ERROR, QQ_RESPONSE_ERROR), 562 | currentCallbackContext.getCallbackId()); 563 | return; 564 | } 565 | initOpenidAndToken(jsonResponse); 566 | JSONObject jo = 567 | makeJson(mTencent.getAccessToken(), mTencent.getOpenId(), mTencent.getExpiresIn()); 568 | QQSDKPlugin.this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK, jo), 569 | currentCallbackContext.getCallbackId()); 570 | } 571 | 572 | @Override public void onError(UiError e) { 573 | QQSDKPlugin.this.webView.sendPluginResult( 574 | new PluginResult(PluginResult.Status.ERROR, e.errorMessage), 575 | currentCallbackContext.getCallbackId()); 576 | } 577 | 578 | @Override public void onCancel() { 579 | QQSDKPlugin.this.webView.sendPluginResult( 580 | new PluginResult(PluginResult.Status.ERROR, QQ_CANCEL_BY_USER), 581 | currentCallbackContext.getCallbackId()); 582 | } 583 | }; 584 | /** 585 | * QQ分享监听 586 | */ 587 | IUiListener qqShareListener = new IUiListener() { 588 | @Override public void onCancel() { 589 | QQSDKPlugin.this.webView.sendPluginResult( 590 | new PluginResult(PluginResult.Status.ERROR, QQ_CANCEL_BY_USER), 591 | currentCallbackContext.getCallbackId()); 592 | } 593 | 594 | @Override public void onComplete(Object response) { 595 | QQSDKPlugin.this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK), 596 | currentCallbackContext.getCallbackId()); 597 | } 598 | 599 | @Override public void onError(UiError e) { 600 | QQSDKPlugin.this.webView.sendPluginResult( 601 | new PluginResult(PluginResult.Status.ERROR, e.errorMessage), 602 | currentCallbackContext.getCallbackId()); 603 | } 604 | }; 605 | /** 606 | * QQZONE 分享监听 607 | */ 608 | IUiListener qZoneShareListener = new IUiListener() { 609 | 610 | @Override public void onCancel() { 611 | QQSDKPlugin.this.webView.sendPluginResult( 612 | new PluginResult(PluginResult.Status.ERROR, QZONE_SHARE_CANCEL), 613 | currentCallbackContext.getCallbackId()); 614 | } 615 | 616 | @Override public void onError(UiError e) { 617 | QQSDKPlugin.this.webView.sendPluginResult( 618 | new PluginResult(PluginResult.Status.ERROR, e.errorMessage), 619 | currentCallbackContext.getCallbackId()); 620 | } 621 | 622 | @Override public void onComplete(Object response) { 623 | QQSDKPlugin.this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK), 624 | currentCallbackContext.getCallbackId()); 625 | } 626 | }; 627 | /** 628 | * 添加到QQ收藏监听 629 | */ 630 | IUiListener addToQQFavoritesListener = new IUiListener() { 631 | @Override public void onCancel() { 632 | QQSDKPlugin.this.webView.sendPluginResult( 633 | new PluginResult(PluginResult.Status.ERROR, QQFAVORITES_CANCEL), 634 | currentCallbackContext.getCallbackId()); 635 | } 636 | 637 | @Override public void onComplete(Object response) { 638 | QQSDKPlugin.this.webView.sendPluginResult(new PluginResult(PluginResult.Status.OK), 639 | currentCallbackContext.getCallbackId()); 640 | } 641 | 642 | @Override public void onError(UiError e) { 643 | QQSDKPlugin.this.webView.sendPluginResult( 644 | new PluginResult(PluginResult.Status.ERROR, e.errorMessage), 645 | currentCallbackContext.getCallbackId()); 646 | } 647 | }; 648 | 649 | /** 650 | * 组装JSON 651 | */ 652 | private JSONObject makeJson(String access_token, String userid, long expires_time) { 653 | String json = "{\"access_token\": \"" + access_token + "\", " + 654 | " \"userid\": \"" + userid + "\", " + 655 | " \"expires_time\": \"" + String.valueOf(expires_time) + "\"" + 656 | "}"; 657 | JSONObject jo = null; 658 | try { 659 | jo = new JSONObject(json); 660 | } catch (JSONException e) { 661 | e.printStackTrace(); 662 | } 663 | return jo; 664 | } 665 | 666 | @Override public void onActivityResult(int requestCode, int resultCode, Intent intent) { 667 | if (resultCode == Constants.ACTIVITY_OK) { 668 | if (requestCode == Constants.REQUEST_LOGIN) { 669 | Tencent.onActivityResultData(requestCode, resultCode, intent, loginListener); 670 | } 671 | if (requestCode == Constants.REQUEST_QQ_SHARE) { 672 | Tencent.onActivityResultData(requestCode, resultCode, intent, qqShareListener); 673 | } 674 | if (requestCode == Constants.REQUEST_QQ_FAVORITES) { 675 | Tencent.onActivityResultData(requestCode, resultCode, intent, addToQQFavoritesListener); 676 | } 677 | } 678 | super.onActivityResult(requestCode, resultCode, intent); 679 | } 680 | 681 | @Override public void onDestroy() { 682 | super.onDestroy(); 683 | if (mTencent != null) { 684 | mTencent.releaseResource(); 685 | } 686 | } 687 | } 688 | -------------------------------------------------------------------------------- /src/android/mta-sdk-1.6.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iVanPan/Cordova_QQ/8c799b5a1c055d39321db390d6f53e4e4bfe239c/src/android/mta-sdk-1.6.2.jar -------------------------------------------------------------------------------- /src/android/open_sdk_r5793.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iVanPan/Cordova_QQ/8c799b5a1c055d39321db390d6f53e4e4bfe239c/src/android/open_sdk_r5793.jar -------------------------------------------------------------------------------- /src/ios/CDVQQSDK.h: -------------------------------------------------------------------------------- 1 | // 2 | // CDVQQSDK.h 3 | // QQ 4 | // 5 | // Created by Van on 2016/12/16. 6 | // 7 | // 8 | #import 9 | #import 10 | #import 11 | #import 12 | 13 | typedef NS_ENUM(NSInteger, QQShareScene) { 14 | QQ, 15 | QQZone, 16 | Favorite, 17 | }; 18 | 19 | typedef NS_ENUM(NSInteger, QQShareType) { 20 | TextMessage, 21 | ImageMesssage, 22 | NewsMessageWithNetworkImage, 23 | NewsMessageWithLocalImage, 24 | AudioMessage, 25 | VideoMessage, 26 | }; 27 | 28 | @interface CDVQQSDK : CDVPlugin 29 | 30 | @property (nonatomic, copy) NSString *callback; 31 | 32 | - (void)checkClientInstalled:(CDVInvokedUrlCommand *)command; 33 | 34 | - (void)ssoLogin:(CDVInvokedUrlCommand *)command; 35 | 36 | - (void)logout:(CDVInvokedUrlCommand *)command; 37 | 38 | - (void)shareText:(CDVInvokedUrlCommand *)command; 39 | 40 | - (void)shareImage:(CDVInvokedUrlCommand *)command; 41 | 42 | - (void)shareNews:(CDVInvokedUrlCommand *)command; 43 | 44 | //- (void)shareAudio:(NSString *)previewUrl flashUrl:(NSString *)flashUrl 45 | // image:(NSString *)image 46 | // withTitle:(NSString *)title 47 | // description:(NSString *)description 48 | // shareScene:(QQShareScene)scene 49 | // command:(CDVInvokedUrlCommand 50 | // *)command; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /src/ios/CDVQQSDK.m: -------------------------------------------------------------------------------- 1 | // 2 | // CDVQQSDK.m 3 | // QQ 4 | // 5 | // Created by Van on 2016/12/16. 6 | // 7 | // 8 | 9 | #import "CDVQQSDK.h" 10 | 11 | NSString *QQ_NOT_INSTALLED = @"QQ Client is not installed"; 12 | NSString *QQ_PARAM_NOT_FOUND = @"param is not found"; 13 | NSString *QQ_IMAGE_PARAM_INCORRECT = @"image param is incorrect"; 14 | NSString *QQ_LOGIN_ERROR = @"QQ login error"; 15 | NSString *QQ_LOGIN_CANCEL = @"QQ login cancelled"; 16 | NSString *QQ_LOGIN_NETWORK_ERROR = @"QQ login network error"; 17 | NSString *QQ_SHARE_CANCEL = @"QQ share cancelled by user"; 18 | NSString *appId = @""; 19 | 20 | @implementation CDVQQSDK { 21 | TencentOAuth *tencentOAuth; 22 | } 23 | /** 24 | * 插件初始化,主要用户appkey注册 25 | */ 26 | - (void)pluginInitialize { 27 | appId = [[self.commandDelegate settings] objectForKey:@"qq_app_id"]; 28 | if (nil == tencentOAuth) { 29 | tencentOAuth = [[TencentOAuth alloc] initWithAppId:appId andDelegate:self]; 30 | } 31 | } 32 | /** 33 | * 处理URL 34 | * 35 | * @param notification cordova 传递进来的消息 36 | */ 37 | - (void)handleOpenURL:(NSNotification *)notification { 38 | NSURL *url = [notification object]; 39 | NSString *schemaPrefix = [@"tencent" stringByAppendingString:appId]; 40 | if ([url isKindOfClass:[NSURL class]] && [[url absoluteString] hasPrefix:[schemaPrefix stringByAppendingString:@"://response_from_qq"]]) { 41 | [QQApiInterface handleOpenURL:url delegate:self]; 42 | } else { 43 | [TencentOAuth HandleOpenURL:url]; 44 | } 45 | } 46 | 47 | /** 48 | * 检查QQ官方客户端是否安装 49 | * 50 | * @param command CDVInvokedUrlCommand 51 | */ 52 | - (void)checkClientInstalled:(CDVInvokedUrlCommand *)command { 53 | NSDictionary *args = [command.arguments objectAtIndex:0]; 54 | int type = [[args valueForKey:@"client"] intValue]; 55 | if(type == 0) { 56 | [tencentOAuth setAuthShareType:AuthShareType_QQ]; 57 | [self checkQQInstalled:command]; 58 | } else if (type == 1) { 59 | [self checkTIMInstalled:command]; 60 | } else { 61 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; 62 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 63 | } 64 | } 65 | /** 66 | * 检查QQ官方客户端是否安装 67 | * 68 | * @param command CDVInvokedUrlCommand 69 | */ 70 | - (void)checkQQInstalled:(CDVInvokedUrlCommand *)command { 71 | if ([TencentOAuth iphoneQQInstalled] && [TencentOAuth iphoneQQSupportSSOLogin]) { 72 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 73 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 74 | } else { 75 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; 76 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 77 | } 78 | } 79 | 80 | /** 81 | * 检查TIM客户端是否安装 82 | * 83 | * @param command CDVInvokedUrlCommand 84 | */ 85 | - (void)checkTIMInstalled:(CDVInvokedUrlCommand *)command { 86 | if ([TencentOAuth iphoneTIMInstalled] && [TencentOAuth iphoneTIMSupportSSOLogin]) { 87 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 88 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 89 | } else { 90 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; 91 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 92 | } 93 | } 94 | /** 95 | * QQ 登出 96 | * 97 | * @param command CDVInvokedUrlCommand 98 | */ 99 | - (void)logout:(CDVInvokedUrlCommand *)command { 100 | self.callback = command.callbackId; 101 | [tencentOAuth logout:self]; 102 | } 103 | 104 | /** 105 | * QQ 登录 106 | * 107 | * @param command CDVInvokedUrlCommand 108 | */ 109 | - (void)ssoLogin:(CDVInvokedUrlCommand *)command { 110 | if (nil == tencentOAuth) { 111 | tencentOAuth = [[TencentOAuth alloc] initWithAppId:appId andDelegate:self]; 112 | } 113 | NSDictionary *args = [command.arguments objectAtIndex:0]; 114 | self.callback = command.callbackId; 115 | NSArray *permissions = [NSArray arrayWithObjects: 116 | kOPEN_PERMISSION_GET_USER_INFO, 117 | kOPEN_PERMISSION_GET_SIMPLE_USER_INFO, 118 | kOPEN_PERMISSION_ADD_ALBUM, 119 | kOPEN_PERMISSION_ADD_ONE_BLOG, 120 | kOPEN_PERMISSION_ADD_SHARE, 121 | kOPEN_PERMISSION_ADD_TOPIC, 122 | kOPEN_PERMISSION_CHECK_PAGE_FANS, 123 | kOPEN_PERMISSION_GET_INFO, 124 | kOPEN_PERMISSION_GET_OTHER_INFO, 125 | kOPEN_PERMISSION_LIST_ALBUM, 126 | kOPEN_PERMISSION_UPLOAD_PIC, 127 | kOPEN_PERMISSION_GET_VIP_INFO, 128 | kOPEN_PERMISSION_GET_VIP_RICH_INFO, 129 | nil]; 130 | int type = [[args valueForKey:@"client"] intValue]; 131 | if (type == 0) { 132 | [tencentOAuth setAuthShareType:AuthShareType_QQ]; 133 | } else if (type == 1) { 134 | [tencentOAuth setAuthShareType:AuthShareType_TIM]; 135 | } 136 | [tencentOAuth authorize:permissions]; 137 | 138 | } 139 | 140 | /** 141 | 分享文本 142 | 143 | @param command cordova参数 144 | */ 145 | - (void)shareText:(CDVInvokedUrlCommand *)command { 146 | self.callback = command.callbackId; 147 | NSDictionary *args = [command.arguments objectAtIndex:0]; 148 | if ([args objectForKey:@"text"]) { 149 | NSString *text = [args objectForKey:@"text"]; 150 | int scene = [[args valueForKey:@"scene"] intValue]; 151 | int type = [[args valueForKey:@"client"] intValue]; 152 | [self shareObjectWithData:@{ @"text" : text } Type:TextMessage Scene:scene ClientType:type]; 153 | } else { 154 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_PARAM_NOT_FOUND]; 155 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 156 | } 157 | } 158 | 159 | /** 160 | 分享图片 161 | 162 | @param command Cordova参数 163 | */ 164 | - (void)shareImage:(CDVInvokedUrlCommand *)command { 165 | self.callback = command.callbackId; 166 | NSDictionary *args = [command.arguments objectAtIndex:0]; 167 | if (args) { 168 | NSString *title = [self check:@"title" in:args]; 169 | NSString *image = [self check:@"image" in:args]; 170 | NSString *description = [self check:@"description" in:args]; 171 | int scene = [[args valueForKey:@"scene"] intValue]; 172 | int type = [[args valueForKey:@"client"] intValue]; 173 | NSData *imageData = [self processImage:image]; 174 | if(!imageData) { 175 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_IMAGE_PARAM_INCORRECT]; 176 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 177 | } else { 178 | [self shareObjectWithData:@{ @"image" : imageData, 179 | @"title" : title, 180 | @"description" : description } 181 | Type:ImageMesssage 182 | Scene:scene 183 | ClientType:type]; 184 | } 185 | } else { 186 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_PARAM_NOT_FOUND]; 187 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 188 | } 189 | } 190 | 191 | /** 192 | 分享新闻链接 193 | 194 | @param command Cordova参数 195 | */ 196 | - (void)shareNews:(CDVInvokedUrlCommand *)command { 197 | self.callback = command.callbackId; 198 | NSDictionary *args = [command.arguments objectAtIndex:0]; 199 | if (args) { 200 | NSString *title = [self check:@"title" in:args]; 201 | NSString *image = [self check:@"image" in:args]; 202 | NSString *description = [self check:@"description" in:args]; 203 | NSString *url = [self check:@"url" in:args]; 204 | int scene = [[args valueForKey:@"scene"] intValue]; 205 | int type = [[args valueForKey:@"client"] intValue]; 206 | NSData *imageData = [self processImage:image]; 207 | if(!imageData) { 208 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_IMAGE_PARAM_INCORRECT]; 209 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 210 | } else { 211 | [self shareObjectWithData:@{ @"url" : url, 212 | @"image" : imageData, 213 | @"title" : title, 214 | @"description" : description } 215 | Type:NewsMessageWithLocalImage 216 | Scene:scene 217 | ClientType:type]; 218 | 219 | } 220 | } else { 221 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_PARAM_NOT_FOUND]; 222 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 223 | } 224 | } 225 | 226 | /** 227 | 分享音乐链接 228 | 229 | @param command Cordova参数 230 | */ 231 | - (void)shareAudio:(CDVInvokedUrlCommand *)command { 232 | self.callback = command.callbackId; 233 | NSDictionary *args = [command.arguments objectAtIndex:0]; 234 | if (args) { 235 | NSString *title = [self check:@"title" in:args]; 236 | NSString *image = [self check:@"image" in:args]; 237 | NSString *description = [self check:@"description" in:args]; 238 | NSString *url = [self check:@"url" in:args]; 239 | NSString *flashUrl = [self check:@"flashUrl" in:args]; 240 | int scene = [[args valueForKey:@"scene"] intValue]; 241 | int type = [[args valueForKey:@"client"] intValue]; 242 | NSData *imageData = [self processImage:image]; 243 | if(!imageData) { 244 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_IMAGE_PARAM_INCORRECT]; 245 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 246 | } else { 247 | [self shareObjectWithData:@{ @"url" : url, 248 | @"image" : imageData, 249 | @"flashUrl" : flashUrl, 250 | @"title" : title, 251 | @"description" : description } 252 | Type:AudioMessage 253 | Scene:scene 254 | ClientType:type]; 255 | } 256 | } else { 257 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_PARAM_NOT_FOUND]; 258 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 259 | } 260 | } 261 | 262 | /** 263 | 分享视频链接 264 | 265 | @param command Cordova参数 266 | */ 267 | - (void)shareVideo:(CDVInvokedUrlCommand *)command { 268 | self.callback = command.callbackId; 269 | NSDictionary *args = [command.arguments objectAtIndex:0]; 270 | if (args) { 271 | NSString *title = [self check:@"title" in:args]; 272 | NSString *image = [self check:@"image" in:args]; 273 | NSString *description = [self check:@"description" in:args]; 274 | NSString *url = [self check:@"url" in:args]; 275 | NSString *flashUrl = [self check:@"flashUrl" in:args]; 276 | int scene = [[args valueForKey:@"scene"] intValue]; 277 | int type = [[args valueForKey:@"client"] intValue]; 278 | NSData *imageData = [self processImage:image]; 279 | if(!imageData) { 280 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_IMAGE_PARAM_INCORRECT]; 281 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 282 | } else { 283 | [self shareObjectWithData:@{ @"url" : url, 284 | @"image" : imageData, 285 | @"flashUrl" : flashUrl, 286 | @"title" : title, 287 | @"description" : description } 288 | Type:VideoMessage 289 | Scene:scene 290 | ClientType:type]; 291 | } 292 | } else { 293 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_PARAM_NOT_FOUND]; 294 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 295 | } 296 | } 297 | 298 | /** 299 | 分享文本到QQ空间 300 | 301 | @param text 分享文本 302 | */ 303 | - (void)shareTextToQQZone:(NSString *)text Client:(int) client { 304 | QQApiImageArrayForQZoneObject *txtObj = [QQApiImageArrayForQZoneObject objectWithimageDataArray:nil title:text extMap:nil]; if (client == 1) { 305 | txtObj.shareDestType = AuthShareType_TIM; 306 | } else { 307 | txtObj.shareDestType = AuthShareType_QQ; 308 | } 309 | SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:txtObj]; 310 | QQApiSendResultCode sent = [QQApiInterface SendReqToQZone:req]; 311 | [self handleSendResult:sent]; 312 | } 313 | 314 | /** 315 | 分享方法 316 | 317 | @param shareData 分享数据 318 | @param type 分享的类型 319 | @param scene 分享的场景 320 | */ 321 | - (void)shareObjectWithData:(NSDictionary *)shareData Type:(QQShareType)type Scene:(QQShareScene)scene ClientType:(int) client { 322 | switch (type) { 323 | case TextMessage: { 324 | NSString *msg = [shareData objectForKey:@"text"]; 325 | QQApiTextObject *txtObj = [QQApiTextObject objectWithText:msg]; 326 | [txtObj setCflag:kQQAPICtrlFlagQZoneShareOnStart]; 327 | switch (scene) { 328 | case QQZone: 329 | [self shareTextToQQZone:msg Client:client]; 330 | return; 331 | case Favorite: 332 | [txtObj setCflag:kQQAPICtrlFlagQQShareFavorites]; 333 | break; 334 | default: 335 | [txtObj setCflag:kQQAPICtrlFlagQQShare]; 336 | break; 337 | } 338 | if (client == 1) { 339 | txtObj.shareDestType = AuthShareType_TIM; 340 | } else { 341 | txtObj.shareDestType = AuthShareType_QQ; 342 | } 343 | SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:txtObj]; 344 | QQApiSendResultCode sent = [QQApiInterface sendReq:req]; 345 | [self handleSendResult:sent]; 346 | } break; 347 | case ImageMesssage: { 348 | NSData *data = [shareData objectForKey:@"image"]; 349 | NSString *title = [shareData objectForKey:@"title"]; 350 | NSString *description = [shareData objectForKey:@"description"]; 351 | QQApiImageObject *imgObj = [QQApiImageObject objectWithData:data 352 | previewImageData:nil 353 | title:title 354 | description:description]; 355 | switch (scene) { 356 | case QQZone: 357 | [imgObj setCflag:kQQAPICtrlFlagQZoneShareOnStart]; 358 | break; 359 | case Favorite: 360 | [imgObj setCflag:kQQAPICtrlFlagQQShareFavorites]; 361 | break; 362 | default: 363 | [imgObj setCflag:kQQAPICtrlFlagQQShare]; 364 | break; 365 | } 366 | if (client == 1) { 367 | imgObj.shareDestType = AuthShareType_TIM; 368 | } else { 369 | imgObj.shareDestType = AuthShareType_QQ; 370 | } 371 | SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:imgObj]; 372 | QQApiSendResultCode sent = [QQApiInterface sendReq:req]; 373 | [self handleSendResult:sent]; 374 | } break; 375 | case NewsMessageWithLocalImage: { 376 | NSData *data = [shareData objectForKey:@"image"]; 377 | NSURL *url = [NSURL URLWithString:[shareData objectForKey:@"url"]]; 378 | NSString *title = [shareData objectForKey:@"title"]; 379 | NSString *description = [shareData objectForKey:@"description"]; 380 | QQApiNewsObject *newsObj = [QQApiNewsObject objectWithURL:url 381 | title:title 382 | description:description 383 | previewImageData:data]; 384 | switch (scene) { 385 | case QQZone: 386 | [newsObj setCflag:kQQAPICtrlFlagQZoneShareOnStart]; 387 | break; 388 | case Favorite: 389 | [newsObj setCflag:kQQAPICtrlFlagQQShareFavorites]; 390 | break; 391 | default: 392 | [newsObj setCflag:kQQAPICtrlFlagQQShare]; 393 | break; 394 | } 395 | if (client == 1) { 396 | newsObj.shareDestType = AuthShareType_TIM; 397 | } else { 398 | newsObj.shareDestType = AuthShareType_QQ; 399 | } 400 | SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:newsObj]; 401 | QQApiSendResultCode sent = [QQApiInterface sendReq:req]; 402 | [self handleSendResult:sent]; 403 | } break; 404 | case AudioMessage: { 405 | NSData *data = [shareData objectForKey:@"image"]; 406 | NSURL *url = [NSURL URLWithString:[shareData objectForKey:@"url"]]; 407 | NSString *title = [shareData objectForKey:@"title"]; 408 | NSString *description = [shareData objectForKey:@"description"]; 409 | NSURL *flashUrl = [NSURL URLWithString:[shareData objectForKey:@"url"]]; 410 | QQApiAudioObject *audioObj = [QQApiAudioObject objectWithURL:url 411 | title:title 412 | description:description 413 | previewImageData:data]; 414 | [audioObj setFlashURL:flashUrl]; 415 | switch (scene) { 416 | case QQZone: 417 | [audioObj setCflag:kQQAPICtrlFlagQZoneShareOnStart]; 418 | break; 419 | case Favorite: 420 | [audioObj setCflag:kQQAPICtrlFlagQQShareFavorites]; 421 | break; 422 | default: 423 | [audioObj setCflag:kQQAPICtrlFlagQQShare]; 424 | break; 425 | } 426 | if (client == 1) { 427 | audioObj.shareDestType = AuthShareType_TIM; 428 | } else { 429 | audioObj.shareDestType = AuthShareType_QQ; 430 | } 431 | SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:audioObj]; 432 | QQApiSendResultCode sent = [QQApiInterface sendReq:req]; 433 | [self handleSendResult:sent]; 434 | } break; 435 | case VideoMessage: { 436 | NSData *data = [shareData objectForKey:@"image"]; 437 | NSURL *url = [NSURL URLWithString:[shareData objectForKey:@"url"]]; 438 | NSString *title = [shareData objectForKey:@"title"]; 439 | NSString *description = [shareData objectForKey:@"description"]; 440 | NSURL *flashUrl = [NSURL URLWithString:[shareData objectForKey:@"url"]]; 441 | QQApiVideoObject *videoObj = [QQApiVideoObject objectWithURL:url 442 | title:title 443 | description:description 444 | previewImageData:data]; 445 | [videoObj setFlashURL:flashUrl]; 446 | switch (scene) { 447 | case QQZone: 448 | [videoObj setCflag:kQQAPICtrlFlagQZoneShareOnStart]; 449 | break; 450 | case Favorite: 451 | [videoObj setCflag:kQQAPICtrlFlagQQShareFavorites]; 452 | break; 453 | default: 454 | [videoObj setCflag:kQQAPICtrlFlagQQShare]; 455 | break; 456 | } 457 | if (client == 1) { 458 | videoObj.shareDestType = AuthShareType_TIM; 459 | } else { 460 | videoObj.shareDestType = AuthShareType_QQ; 461 | } 462 | SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:videoObj]; 463 | QQApiSendResultCode sent = [QQApiInterface sendReq:req]; 464 | [self handleSendResult:sent]; 465 | } 466 | default: 467 | break; 468 | } 469 | } 470 | 471 | /** 472 | 分析那个结果处理 473 | 474 | @param sendResult 分享结果 475 | */ 476 | - (void)handleSendResult:(QQApiSendResultCode)sendResult { 477 | switch (sendResult) { 478 | case EQQAPISENDSUCESS: 479 | break; 480 | case EQQAPIAPPSHAREASYNC: 481 | break; 482 | case EQQAPIAPPNOTREGISTED: { 483 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"App 未注册"]; 484 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 485 | break; 486 | } 487 | case EQQAPIMESSAGECONTENTINVALID: 488 | case EQQAPIMESSAGECONTENTNULL: 489 | case EQQAPIMESSAGETYPEINVALID: { 490 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"发送参数错误"]; 491 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 492 | break; 493 | } 494 | case EQQAPITIMNOTINSTALLED: { 495 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"没有安装 TIM"]; 496 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 497 | break; 498 | } 499 | case EQQAPIQQNOTINSTALLED: { 500 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"没有安装手机 QQ"]; 501 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 502 | break; 503 | } 504 | case EQQAPITIMNOTSUPPORTAPI: 505 | case EQQAPIQQNOTSUPPORTAPI: { 506 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"API 接口不支持"]; 507 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 508 | break; 509 | } 510 | case EQQAPISENDFAILD: { 511 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"发送失败"]; 512 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 513 | break; 514 | } 515 | case EQQAPIVERSIONNEEDUPDATE: { 516 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"当前 QQ 版本太低"]; 517 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 518 | break; 519 | } 520 | case ETIMAPIVERSIONNEEDUPDATE: { 521 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"当前 TIM 版本太低"]; 522 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 523 | break; 524 | } 525 | case EQQAPIQZONENOTSUPPORTTEXT: { 526 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"QQZone 不支持 QQApiTextObject 分享"]; 527 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 528 | break; 529 | } 530 | case EQQAPIQZONENOTSUPPORTIMAGE: { 531 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"QQZone 不支持 QQApiImageObject 分享"]; 532 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 533 | break; 534 | } 535 | case EQQAPISHAREDESTUNKNOWN: { 536 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"未指定分享到 QQ 或 TIM"]; 537 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 538 | break; 539 | } 540 | default: { 541 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"发生其他错误"]; 542 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 543 | break; 544 | } 545 | } 546 | } 547 | 548 | #pragma mark - QQApiInterfaceDelegate 549 | - (void)onReq:(QQBaseReq *)req { 550 | } 551 | 552 | - (void)onResp:(QQBaseResp *)resp { 553 | switch ([resp.result integerValue]) { 554 | case 0: { 555 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 556 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 557 | break; 558 | } 559 | case -4: { 560 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_SHARE_CANCEL]; 561 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 562 | break; 563 | } 564 | default: { 565 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; 566 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 567 | break; 568 | } 569 | } 570 | } 571 | 572 | - (void)isOnlineResponse:(NSDictionary *)response { 573 | } 574 | 575 | #pragma mark - TencentSessionDelegate 576 | - (void)tencentDidLogin { 577 | if (tencentOAuth.accessToken && 0 != [tencentOAuth.accessToken length]) { 578 | NSMutableDictionary *Dic = [NSMutableDictionary dictionaryWithCapacity:2]; 579 | [Dic setObject:tencentOAuth.openId forKey:@"userid"]; 580 | [Dic setObject:tencentOAuth.accessToken forKey:@"access_token"]; 581 | [Dic setObject:[NSString stringWithFormat:@"%f", [tencentOAuth.expirationDate timeIntervalSince1970] * 1000] forKey:@"expires_time"]; 582 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:Dic]; 583 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 584 | } else { 585 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_LOGIN_ERROR]; 586 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 587 | } 588 | } 589 | 590 | - (void)tencentDidLogout { 591 | tencentOAuth = nil; 592 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 593 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 594 | } 595 | 596 | - (void)tencentDidNotLogin:(BOOL)cancelled { 597 | if (cancelled) { 598 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_LOGIN_CANCEL]; 599 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 600 | } else { 601 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_LOGIN_ERROR]; 602 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 603 | } 604 | } 605 | 606 | - (void)tencentDidNotNetWork { 607 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:QQ_LOGIN_NETWORK_ERROR]; 608 | [self.commandDelegate sendPluginResult:pluginResult callbackId:self.callback]; 609 | } 610 | 611 | /** 612 | 图片处理 613 | 614 | @param image 图片数据 615 | @return 图片NSdata数据 616 | */ 617 | - (NSData *)processImage:(NSString *)image { 618 | if ([self isBase64Data:image]) { 619 | return [[NSData alloc] initWithBase64EncodedString:image options:0]; 620 | } else if ([image hasPrefix:@"http://"] || [image hasPrefix:@"https://"]) { 621 | NSURL *url = [NSURL URLWithString:image]; 622 | return [NSData dataWithContentsOfURL:url]; 623 | } else { 624 | return [NSData dataWithContentsOfFile:image]; 625 | } 626 | } 627 | 628 | /** 629 | 检查图片是不是Base64 630 | 631 | @param data 图片数据 632 | @return 结果true or false 633 | */ 634 | - (BOOL)isBase64Data:(NSString *)data { 635 | data = [[data componentsSeparatedByCharactersInSet: 636 | [NSCharacterSet whitespaceAndNewlineCharacterSet]] 637 | componentsJoinedByString:@""]; 638 | if ([data length] % 4 == 0) { 639 | static NSCharacterSet *invertedBase64CharacterSet = nil; 640 | if (invertedBase64CharacterSet == nil) { 641 | invertedBase64CharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="] invertedSet]; 642 | } 643 | return [data rangeOfCharacterFromSet:invertedBase64CharacterSet options:NSLiteralSearch].location == NSNotFound; 644 | } 645 | return NO; 646 | } 647 | 648 | /** 649 | 检查参数是否存在 650 | 651 | @param param 要检查的参数 652 | @param args 参数字典 653 | @return 参数 654 | */ 655 | - (NSString *)check:(NSString *)param in:(NSDictionary *)args { 656 | NSString *data = [args objectForKey:param]; 657 | return data?data:@""; 658 | } 659 | 660 | @end 661 | -------------------------------------------------------------------------------- /src/ios/TencentOpenAPI.framework/Headers/QQApiInterface.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// \file QQApiInterface.h 3 | /// \brief QQApi接口简化封装 4 | /// 5 | /// Created by Tencent on 12-5-15. 6 | /// Copyright (c) 2012年 Tencent. All rights reserved. 7 | /// 8 | 9 | #import 10 | #import "QQApiInterfaceObject.h" 11 | 12 | /** 13 | \brief 处理来至QQ的请求及响应的回调协议 14 | */ 15 | @protocol QQApiInterfaceDelegate 16 | 17 | /** 18 | 处理来至QQ的请求 19 | */ 20 | - (void)onReq:(QQBaseReq *)req; 21 | 22 | /** 23 | 处理来至QQ的响应 24 | */ 25 | - (void)onResp:(QQBaseResp *)resp; 26 | 27 | /** 28 | 处理QQ在线状态的回调 29 | */ 30 | - (void)isOnlineResponse:(NSDictionary *)response; 31 | 32 | @end 33 | 34 | /** 35 | \brief 对QQApi的简单封装类 36 | */ 37 | @interface QQApiInterface : NSObject 38 | 39 | /** 40 | 处理由手Q唤起的跳转请求 41 | \param url 待处理的url跳转请求 42 | \param delegate 第三方应用用于处理来至QQ请求及响应的委托对象 43 | \return 跳转请求处理结果,YES表示成功处理,NO表示不支持的请求协议或处理失败 44 | */ 45 | + (BOOL)handleOpenURL:(NSURL *)url delegate:(id)delegate; 46 | 47 | /** 48 | 向手Q发起分享请求 49 | \param req 分享内容的请求 50 | \return 请求发送结果码 51 | */ 52 | + (QQApiSendResultCode)sendReq:(QQBaseReq *)req; 53 | 54 | /** 55 | 向手Q QZone结合版发起分享请求 56 | \note H5分享只支持单张网络图片的传递 57 | \param req 分享内容的请求 58 | \return 请求发送结果码 59 | */ 60 | + (QQApiSendResultCode)SendReqToQZone:(QQBaseReq *)req; 61 | 62 | /** 63 | 向手Q 群部落发起分享请求 64 | \note H5分享只支持单张网络图片的传递 65 | \param req 分享内容的请求 66 | \return 请求发送结果码 67 | */ 68 | + (QQApiSendResultCode)SendReqToQQGroupTribe:(QQBaseReq *)req; 69 | 70 | /** 71 | 向手Q发送应答消息 72 | \param resp 应答消息 73 | \return 应答发送结果码 74 | */ 75 | + (QQApiSendResultCode)sendResp:(QQBaseResp *)resp; 76 | 77 | /** 78 | 检测是否已安装QQ 79 | \return 如果QQ已安装则返回YES,否则返回NO 80 | */ 81 | + (BOOL)isQQInstalled; 82 | 83 | /** 84 | 检测是否已安装TIM 85 | \return 如果TIM已安装则返回YES,否则返回NO 86 | */ 87 | + (BOOL)isTIMInstalled; 88 | 89 | /** 90 | 批量检测QQ号码是否在线 91 | */ 92 | + (void)getQQUinOnlineStatues:(NSArray *)QQUins delegate:(id)delegate; 93 | 94 | /** 95 | 检测QQ是否支持API调用 96 | \return 如果当前安装QQ版本支持API调用则返回YES,否则返回NO 97 | */ 98 | + (BOOL)isQQSupportApi; 99 | 100 | /** 101 | 检测TIM是否支持API调用 102 | \return 如果当前安装TIM版本支持API调用则返回YES,否则返回NO 103 | */ 104 | + (BOOL)isTIMSupportApi; 105 | 106 | /** 107 | 启动QQ 108 | \return 成功返回YES,否则返回NO 109 | */ 110 | + (BOOL)openQQ; 111 | 112 | /** 113 | 启动TIM 114 | \return 成功返回YES,否则返回NO 115 | */ 116 | + (BOOL)openTIM; 117 | 118 | /** 119 | 获取QQ下载地址 120 | 121 | 如果App通过QQApiInterface#isQQInstalledQQApiInterface#isQQSupportApi检测发现QQ没安装或当前版本QQ不支持API调用,可引导用户通过打开此链接下载最新版QQ。 122 | \return iPhoneQQ下载地址 123 | */ 124 | + (NSString *)getQQInstallUrl; 125 | 126 | /** 127 | 获取TIM下载地址 128 | 129 | 如果App通过QQApiInterface#isTIMInstalledQQApiInterface#isTIMSupportApi检测发现TIM没安装或当前版本TIM不支持API调用,可引导用户通过打开此链接下载最新版TIM。 130 | \return iPhoneTIM下载地址 131 | */ 132 | + (NSString *)getTIMInstallUrl; 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /src/ios/TencentOpenAPI.framework/Headers/QQApiInterfaceObject.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// \file QQApiInterfaceObject.h 3 | /// \brief QQApiInterface所依赖的请求及应答消息对象封装帮助类 4 | /// 5 | /// Created by Tencent on 12-5-15. 6 | /// Copyright (c) 2012年 Tencent. All rights reserved. 7 | /// 8 | 9 | #ifndef QQApiInterface_QQAPIOBJECT_h 10 | #define QQApiInterface_QQAPIOBJECT_h 11 | 12 | #import 13 | 14 | 15 | typedef enum 16 | { 17 | EQQAPISENDSUCESS = 0, 18 | EQQAPIQQNOTINSTALLED = 1, 19 | EQQAPIQQNOTSUPPORTAPI = 2, 20 | EQQAPIMESSAGETYPEINVALID = 3, 21 | EQQAPIMESSAGECONTENTNULL = 4, 22 | EQQAPIMESSAGECONTENTINVALID = 5, 23 | EQQAPIAPPNOTREGISTED = 6, 24 | EQQAPIAPPSHAREASYNC = 7, 25 | EQQAPIQQNOTSUPPORTAPI_WITH_ERRORSHOW = 8, 26 | EQQAPISENDFAILD = -1, 27 | EQQAPISHAREDESTUNKNOWN = -2, //未指定分享到QQ或TIM 28 | 29 | EQQAPITIMNOTINSTALLED = 11, //TIM未安装 30 | EQQAPITIMNOTSUPPORTAPI = 12, // TIM api不支持 31 | //qzone分享不支持text类型分享 32 | EQQAPIQZONENOTSUPPORTTEXT = 10000, 33 | //qzone分享不支持image类型分享 34 | EQQAPIQZONENOTSUPPORTIMAGE = 10001, 35 | //当前QQ版本太低,需要更新至新版本才可以支持 36 | EQQAPIVERSIONNEEDUPDATE = 10002, 37 | ETIMAPIVERSIONNEEDUPDATE = 10004, 38 | } QQApiSendResultCode; 39 | 40 | #pragma mark - QQApiObject(分享对象类型) 41 | 42 | // QQApiObject control flags 43 | enum 44 | { 45 | kQQAPICtrlFlagQZoneShareOnStart = 0x01, 46 | kQQAPICtrlFlagQZoneShareForbid = 0x02, 47 | kQQAPICtrlFlagQQShare = 0x04, 48 | kQQAPICtrlFlagQQShareFavorites = 0x08, //收藏 49 | kQQAPICtrlFlagQQShareDataline = 0x10, //数据线 50 | }; 51 | 52 | // 分享到QQ或TIM 53 | typedef enum ShareDestType { 54 | ShareDestTypeQQ, 55 | ShareDestTypeTIM, 56 | }ShareDestType; 57 | 58 | // QQApiObject 59 | /** \brief 所有在QQ及插件间发送的数据对象的根类。 60 | */ 61 | __attribute__((visibility("default"))) @interface QQApiObject : NSObject 62 | @property(nonatomic,retain) NSString* title; ///< 标题,最长128个字符 63 | @property(nonatomic,retain) NSString* description; ///<简要描述,最长512个字符 64 | 65 | @property (nonatomic, assign) uint64_t cflag; 66 | @property (nonatomic, assign) ShareDestType shareDestType; //分享到QQ或TIM,必须指定 67 | @end 68 | 69 | // QQApiResultObject 70 | /** \brief 用于请求回应的数据类型。 71 |

可能错误码及描述如下:

72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
errorerrorDescription注释
0nil成功
-1param error参数错误
-2group code is invalid该群不在自己的群列表里面
-3upload photo failed上传图片失败
-4user give up the current operation用户放弃当前操作
-5client internal error客户端内部处理错误
81 | */ 82 | __attribute__((visibility("default"))) @interface QQApiResultObject : QQApiObject 83 | @property(nonatomic,retain) NSString* error; ///<错误 84 | @property(nonatomic,retain) NSString* errorDescription; ///<错误描述 85 | @property(nonatomic,retain) NSString* extendInfo; ///<扩展信息 86 | @end 87 | 88 | // QQApiTextObject 89 | /** \brief 文本对象 90 | */ 91 | @interface QQApiTextObject : QQApiObject 92 | @property(nonatomic,retain)NSString* text; ///<文本内容,必填,最长1536个字符 93 | 94 | -(id)initWithText:(NSString*)text; ///<初始化方法 95 | +(id)objectWithText:(NSString*)text;///<工厂方法,获取一个QQApiTextObject对象. 96 | @end 97 | 98 | // QQApiURLObject 99 | typedef enum QQApiURLTargetType{ 100 | QQApiURLTargetTypeNotSpecified = 0x00, 101 | QQApiURLTargetTypeAudio = 0x01, 102 | QQApiURLTargetTypeVideo = 0x02, 103 | QQApiURLTargetTypeNews = 0x03 104 | }QQApiURLTargetType; 105 | 106 | /** @brief URL对象类型。 107 | 108 | 包括URL地址,URL地址所指向的目标类型及预览图像。 109 | */ 110 | __attribute__((visibility("default"))) @interface QQApiURLObject : QQApiObject 111 | /** 112 | URL地址所指向的目标类型. 113 | @note 参见QQApi.h 中的 QQApiURLTargetType 定义. 114 | */ 115 | @property(nonatomic)QQApiURLTargetType targetContentType; 116 | 117 | @property(nonatomic,retain)NSURL* url; ///QQApiExtendObject对象 161 | @param data 数据内容 162 | @param previewImageData 用于预览的图片 163 | @param title 标题 164 | @param description 此对象,分享的描述 165 | @return 166 | 一个自动释放的QQApiExtendObject实例 167 | */ 168 | + (id)objectWithData:(NSData*)data previewImageData:(NSData*)previewImageData title:(NSString*)title description:(NSString*)description; 169 | 170 | /** 171 | helper方法获取一个autorelease的QQApiExtendObject对象 172 | @param data 数据内容 173 | @param previewImageData 用于预览的图片 174 | @param title 标题 175 | @param description 此对象,分享的描述 176 | @param imageDataArray 发送的多张图片队列 177 | @return 178 | 一个自动释放的QQApiExtendObject实例 179 | */ 180 | + (id)objectWithData:(NSData*)data previewImageData:(NSData*)previewImageData title:(NSString*)title description:(NSString*)description imageDataArray:(NSArray*)imageDataArray; 181 | 182 | @end 183 | 184 | // QQApiImageObject 185 | /** @brief 图片对象 186 | 用于分享图片内容的对象,是一个指定为图片类型的QQApiExtendObject 187 | */ 188 | @interface QQApiImageObject : QQApiExtendObject 189 | @end 190 | 191 | // QQApiImageArrayForQZoneObject 192 | /** @brief 图片对象 193 | 用于分享图片到空间,走写说说路径,是一个指定为图片类型的,当图片数组为空时,默认走文本写说说QQApiObject 194 | */ 195 | @interface QQApiImageArrayForQZoneObject : QQApiObject 196 | 197 | @property(nonatomic,retain) NSArray* imageDataArray;///图片数组 198 | @property(nonatomic,retain) NSDictionary* extMap; // 扩展字段 199 | 200 | /** 201 | 初始化方法 202 | @param imageDataArray 图片数组 203 | @param title 写说说的内容,可以为空 204 | @param extMap 扩展字段 205 | */ 206 | - (id)initWithImageArrayData:(NSArray*)imageDataArray title:(NSString*)title extMap:(NSDictionary *)extMap; 207 | 208 | /** 209 | helper方法获取一个autorelease的QQApiExtendObject对象 210 | @param title 写说说的内容,可以为空 211 | @param imageDataArray 发送的多张图片队列 212 | @param extMap 扩展字段 213 | @return 214 | 一个自动释放的QQApiExtendObject实例 215 | */ 216 | + (id)objectWithimageDataArray:(NSArray*)imageDataArray title:(NSString*)title extMap:(NSDictionary *)extMap; 217 | 218 | @end 219 | 220 | // QQApiVideoForQZoneObject 221 | /** @brief 视频对象 222 | 用于分享视频到空间,走写说说路径QQApiObject 223 | assetURL可传ALAsset的ALAssetPropertyAssetURL,或者PHAsset的localIdentifier 224 | @param extMap 扩展字段 225 | */ 226 | @interface QQApiVideoForQZoneObject : QQApiObject 227 | 228 | @property(nonatomic, retain) NSString *assetURL; 229 | @property(nonatomic,retain) NSDictionary* extMap; // 扩展字段 230 | 231 | - (id)initWithAssetURL:(NSString*)assetURL title:(NSString*)title extMap:(NSDictionary *)extMap; 232 | 233 | + (id)objectWithAssetURL:(NSString*)assetURL title:(NSString*)title extMap:(NSDictionary *)extMap; 234 | 235 | @end 236 | 237 | // QQApiWebImageObject 238 | /** @brief 图片对象 239 | 用于分享网络图片内容的对象,是一个指定网络图片url的: 该类型只在2.9.0的h5分享中才支持, 240 | 原有的手q分享是不支持该类型的。 241 | */ 242 | @interface QQApiWebImageObject : QQApiObject 243 | 244 | @property(nonatomic, retain) NSURL *previewImageURL; ///<预览图像URL 245 | 246 | /** 247 | 初始化方法 248 | @param previewImageURL 用于预览的图片 249 | @param title 标题 250 | @param description 此对象,分享的描述 251 | */ 252 | - (id)initWithPreviewImageURL:(NSURL*)previewImageURL title:(NSString*)title description:(NSString*)description; 253 | 254 | /** 255 | helper方法获取一个autorelease的QQApiWebImageObject对象 256 | @param previewImageURL 用于预览的图片 257 | @param title 标题 258 | @param description 此对象,分享的描述 259 | */ 260 | + (id)objectWithPreviewImageURL:(NSURL*)previewImageURL title:(NSString*)title description:(NSString*)description; 261 | 262 | @end 263 | 264 | // QQApiGroupTribeImageObject 265 | /** @brief 群部落图片对象 266 | 用于分享图片内容的对象,是一个指定为图片类型的 可以指定一些其他的附加数据QQApiExtendObject 267 | */ 268 | @interface QQApiGroupTribeImageObject : QQApiImageObject 269 | { 270 | NSString *_bid; 271 | NSString *_bname; 272 | } 273 | // 群部落id 274 | @property (nonatomic, retain)NSString* bid; 275 | 276 | // 群部落名称 277 | @property (nonatomic, retain)NSString* bname; 278 | 279 | @end 280 | 281 | 282 | //QQApiFileObject 283 | /** @brief 本地文件对象(暂只支持分享到手机QQ数据线功能) 284 | 用于分享文件内容的对象,是一个指定为文件类型的QQApiExtendObject 285 | */ 286 | @interface QQApiFileObject : QQApiExtendObject 287 | { 288 | NSString* _fileName; 289 | } 290 | @property(nonatomic, retain)NSString* fileName; 291 | @end 292 | 293 | // QQApiAudioObject 294 | /** @brief 音频URL对象 295 | 用于分享目标内容为音频的URL的对象 296 | */ 297 | @interface QQApiAudioObject : QQApiURLObject 298 | 299 | @property (nonatomic, retain) NSURL *flashURL; ///<音频URL地址,最长512个字符 300 | 301 | /** 302 | 获取一个autorelease的QQApiAudioObject 303 | @param url 音频内容的目标URL 304 | @param title 分享内容的标题 305 | @param description 分享内容的描述 306 | @param data 分享内容的预览图像 307 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 308 | */ 309 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; 310 | 311 | /** 312 | 获取一个autorelease的QQApiAudioObject 313 | @param url 音频内容的目标URL 314 | @param title 分享内容的标题 315 | @param description 分享内容的描述 316 | @param previewURL 分享内容的预览图像URL 317 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 318 | */ 319 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; 320 | 321 | @end 322 | 323 | // QQApiVideoObject 324 | /** @brief 视频URL对象 325 | 用于分享目标内容为视频的URL的对象 326 | 327 | QQApiVideoObject类型的分享,目前在Android和PC QQ上接收消息时,展现有待完善,待手机QQ版本以后更新支持 328 | 目前如果要分享视频,推荐使用 QQApiNewsObject 类型 329 | */ 330 | @interface QQApiVideoObject : QQApiURLObject 331 | 332 | @property (nonatomic, retain) NSURL *flashURL; ///<视频URL地址,最长512个字符 333 | 334 | /** 335 | 获取一个autorelease的QQApiVideoObject 336 | @param url 视频内容的目标URL 337 | @param title 分享内容的标题 338 | @param description 分享内容的描述 339 | @param data 分享内容的预览图像 340 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 341 | */ 342 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; 343 | 344 | /** 345 | 获取一个autorelease的QQApiVideoObject 346 | @param url 视频内容的目标URL 347 | @param title 分享内容的标题 348 | @param description 分享内容的描述 349 | @param previewURL 分享内容的预览图像URL 350 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 351 | */ 352 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; 353 | 354 | @end 355 | 356 | // QQApiNewsObject 357 | /** @brief 新闻URL对象 358 | 用于分享目标内容为新闻的URL的对象 359 | */ 360 | @interface QQApiNewsObject : QQApiURLObject 361 | /** 362 | 获取一个autorelease的QQApiNewsObject 363 | @param url 视频内容的目标URL 364 | @param title 分享内容的标题 365 | @param description 分享内容的描述 366 | @param data 分享内容的预览图像 367 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 368 | */ 369 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageData:(NSData*)data; 370 | 371 | /** 372 | 获取一个autorelease的QQApiNewsObject 373 | @param url 视频内容的目标URL 374 | @param title 分享内容的标题 375 | @param description 分享内容的描述 376 | @param previewURL 分享内容的预览图像URL 377 | @note 如果url为空,调用QQApi#sendMessage:时将返回FALSE 378 | */ 379 | +(id)objectWithURL:(NSURL*)url title:(NSString*)title description:(NSString*)description previewImageURL:(NSURL*)previewURL; 380 | 381 | @end 382 | 383 | // QQApiPayObject 384 | /** \brief 支付对象 385 | */ 386 | @interface QQApiPayObject : QQApiObject 387 | @property(nonatomic,retain)NSString* OrderNo; ///<支付订单号,必填 388 | @property(nonatomic,retain)NSString* AppInfo; ///<支付来源信息,必填 389 | 390 | -(id)initWithOrderNo:(NSString*)OrderNo AppInfo:(NSString*)AppInfo; ///<初始化方法 391 | +(id)objectWithOrderNo:(NSString*)OrderNo AppInfo:(NSString*)AppInfo;///<工厂方法,获取一个QQApiPayObject对象. 392 | @end 393 | 394 | // QQApiCommonContentObject; 395 | /** @brief 通用模板类型对象 396 | 用于分享一个固定显示模板的图文混排对象 397 | @note 图片列表和文本列表不能同时为空 398 | */ 399 | @interface QQApiCommonContentObject : QQApiObject 400 | /** 401 | 预定义的界面布局类型 402 | */ 403 | @property(nonatomic,assign) unsigned int layoutType; 404 | @property(nonatomic,assign) NSData* previewImageData;///<预览图 405 | @property(nonatomic,retain) NSArray* textArray;///<文本列表 406 | @property(nonatomic,retain) NSArray* pictureDataArray;///<图片列表 407 | +(id)objectWithLayoutType:(int)layoutType textArray:(NSArray*)textArray pictureArray:(NSArray*)pictureArray previewImageData:(NSData*)data; 408 | /** 409 | 将一个NSDictionary对象转化为QQApiCommomContentObject,如果无法转换,则返回空 410 | */ 411 | +(id)objectWithDictionary:(NSDictionary*)dic; 412 | -(NSDictionary*)toDictionary; 413 | @end 414 | 415 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 416 | // Ad item object definition 417 | //////////////////////////////////////////////////////////////////////////////////////////////////////////// 418 | /** @brief 广告数据对象 419 | */ 420 | @interface QQApiAdItem : NSObject 421 | @property(nonatomic,retain) NSString* title; ///<名称 422 | @property(nonatomic,retain) NSString* description;///<描述 423 | @property(nonatomic,retain) NSData* imageData;///<广告图片 424 | @property(nonatomic,retain) NSURL* target;///<广告目标链接 425 | @end 426 | 427 | // QQApiWPAObject 428 | /** \brief 发起WPA对象 429 | */ 430 | @interface QQApiWPAObject : QQApiObject 431 | @property(nonatomic,retain)NSString* uin; ///<想要对话的QQ号 432 | 433 | -(id)initWithUin:(NSString*)uin; ///<初始化方法 434 | +(id)objectWithUin:(NSString*)uin;///<工厂方法,获取一个QQApiWPAObject对象. 435 | @end 436 | 437 | // QQApiAddFriendObject 438 | /** \brief 添加好友 439 | */ 440 | @interface QQApiAddFriendObject : QQApiObject 441 | @property (nonatomic,retain)NSString* openID; 442 | @property (nonatomic,retain)NSString* subID; 443 | @property (nonatomic,retain)NSString* remark; 444 | 445 | -(id)initWithOpenID:(NSString*)openID; ///<初始化方法 446 | +(id)objecWithOpenID:(NSString*)openID; ///<工厂方法,获取一个QQApiAddFriendObject对象. 447 | 448 | @end 449 | 450 | // QQApiGameConsortiumBindingGroupObject 451 | /** \brief 游戏公会绑定群 452 | */ 453 | @interface QQApiGameConsortiumBindingGroupObject : QQApiObject 454 | @property (nonatomic,retain)NSString* signature; 455 | @property (nonatomic,retain)NSString* unionid; 456 | @property (nonatomic,retain)NSString* zoneID; 457 | @property (nonatomic,retain)NSString* appDisplayName; 458 | 459 | -(id)initWithGameConsortium:(NSString*)signature unionid:(NSString*)unionid zoneID:(NSString*)zoneID appDisplayName:(NSString*)appDisplayName; ///<初始化方法 460 | +(id)objectWithGameConsortium:(NSString*)signature unionid:(NSString*)unionid zoneID:(NSString*)zoneID appDisplayName:(NSString*)appDisplayName; ///<工厂方法,获取一个QQApiAddFriendObject对象. 461 | 462 | @end 463 | 464 | // QQApiGameConsortiumBindingGroupObject 465 | /** \brief 加入群 466 | */ 467 | @interface QQApiJoinGroupObject : QQApiObject 468 | @property (nonatomic,retain)NSString* groupUin; 469 | @property (nonatomic,retain)NSString* groupKey; 470 | 471 | - (id)initWithGroupInfo:(NSString*)groupUin key:(NSString*)groupKey; ///<初始化方法 472 | + (id)objectWithGroupInfo:(NSString*)groupUin key:(NSString*)groupKey; ///<同时提供群号和群KEY 工厂方法,获取一个QQApiAddFriendObject对象. 473 | + (id)objectWithGroupKey:(NSString*)groupKey; ///<只需要群的KEY 工厂方法,获取一个QQApiAddFriendObject对象. 474 | 475 | @end 476 | 477 | // QQApiGroupChatObject 478 | /** \brief 发起群会话对象 479 | */ 480 | @interface QQApiGroupChatObject : QQApiObject 481 | @property(nonatomic,retain)NSString* groupID; ///<想要对话的群号 482 | 483 | -(id)initWithGroup:(NSString*)groupID; ///<初始化方法 484 | +(id)objectWithGroup:(NSString*)groupID;///<工厂方法,获取一个QQApiGroupChatObject对象. 485 | @end 486 | 487 | #pragma mark - QQApi请求消息类型 488 | 489 | /** 490 | QQApi请求消息类型 491 | */ 492 | enum QQApiInterfaceReqType 493 | { 494 | EGETMESSAGEFROMQQREQTYPE = 0, ///< 手Q -> 第三方应用,请求第三方应用向手Q发送消息 495 | ESENDMESSAGETOQQREQTYPE = 1, ///< 第三方应用 -> 手Q,第三方应用向手Q分享消息 496 | ESHOWMESSAGEFROMQQREQTYPE = 2 ///< 手Q -> 第三方应用,请求第三方应用展现消息中的数据 497 | }; 498 | 499 | /** 500 | QQApi应答消息类型 501 | */ 502 | enum QQApiInterfaceRespType 503 | { 504 | ESHOWMESSAGEFROMQQRESPTYPE = 0, ///< 第三方应用 -> 手Q,第三方应用应答消息展现结果 505 | EGETMESSAGEFROMQQRESPTYPE = 1, ///< 第三方应用 -> 手Q,第三方应用回应发往手Q的消息 506 | ESENDMESSAGETOQQRESPTYPE = 2 ///< 手Q -> 第三方应用,手Q应答处理分享消息的结果 507 | }; 508 | 509 | /** 510 | QQApi请求消息基类 511 | */ 512 | @interface QQBaseReq : NSObject 513 | 514 | /** 请求消息类型,参见\ref QQApiInterfaceReqType */ 515 | @property (nonatomic, assign) int type; 516 | 517 | @end 518 | 519 | /** 520 | QQApi应答消息基类 521 | */ 522 | @interface QQBaseResp : NSObject 523 | 524 | /** 请求处理结果 */ 525 | @property (nonatomic, copy) NSString* result; 526 | 527 | /** 具体错误描述信息 */ 528 | @property (nonatomic, copy) NSString* errorDescription; 529 | 530 | /** 应答消息类型,参见\ref QQApiInterfaceRespType */ 531 | @property (nonatomic, assign) int type; 532 | 533 | /** 扩展信息 */ 534 | @property (nonatomic, assign) NSString* extendInfo; 535 | 536 | @end 537 | 538 | /** 539 | GetMessageFromQQReq请求帮助类 540 | */ 541 | @interface GetMessageFromQQReq : QQBaseReq 542 | 543 | /** 544 | 创建一个GetMessageFromQQReq请求实例 545 | */ 546 | + (GetMessageFromQQReq *)req; 547 | 548 | @end 549 | 550 | /** 551 | GetMessageFromQQResp应答帮助类 552 | */ 553 | @interface GetMessageFromQQResp : QQBaseResp 554 | 555 | /** 556 | 创建一个GetMessageFromQQResp应答实例 557 | \param message 具体分享消息实例 558 | \return 新创建的GetMessageFromQQResp应答实例 559 | */ 560 | + (GetMessageFromQQResp *)respWithContent:(QQApiObject *)message; 561 | 562 | /** 具体分享消息 */ 563 | @property (nonatomic, retain) QQApiObject *message; 564 | 565 | @end 566 | 567 | /** 568 | SendMessageToQQReq请求帮助类 569 | */ 570 | @interface SendMessageToQQReq : QQBaseReq 571 | 572 | /** 573 | 创建一个SendMessageToQQReq请求实例 574 | \param message 具体分享消息实例 575 | \return 新创建的SendMessageToQQReq请求实例 576 | */ 577 | + (SendMessageToQQReq *)reqWithContent:(QQApiObject *)message; 578 | 579 | /** 具体分享消息 */ 580 | @property (nonatomic, retain) QQApiObject *message; 581 | 582 | @end 583 | 584 | /** 585 | SendMessageToQQResp应答帮助类 586 | */ 587 | @interface SendMessageToQQResp : QQBaseResp 588 | 589 | /** 590 | 创建一个SendMessageToQQResp应答实例 591 | \param result 请求处理结果 592 | \param errDesp 具体错误描述信息 593 | \param extendInfo 扩展信息 594 | \return 新创建的SendMessageToQQResp应答实例 595 | */ 596 | + (SendMessageToQQResp *)respWithResult:(NSString *)result errorDescription:(NSString *)errDesp extendInfo:(NSString*)extendInfo; 597 | 598 | @end 599 | 600 | /** 601 | ShowMessageFromQQReq请求帮助类 602 | */ 603 | @interface ShowMessageFromQQReq : QQBaseReq 604 | 605 | /** 606 | 创建一个ShowMessageFromQQReq请求实例 607 | \param message 具体待展现消息实例 608 | \return 新创建的ShowMessageFromQQReq请求实例 609 | */ 610 | + (ShowMessageFromQQReq *)reqWithContent:(QQApiObject *)message; 611 | 612 | /** 具体待展现消息 */ 613 | @property (nonatomic, retain) QQApiObject *message; 614 | 615 | @end 616 | 617 | /** 618 | ShowMessageFromQQResp应答帮助类 619 | */ 620 | @interface ShowMessageFromQQResp : QQBaseResp 621 | 622 | /** 623 | 创建一个ShowMessageFromQQResp应答实例 624 | \param result 展现消息结果 625 | \param errDesp 具体错误描述信息 626 | \return 新创建的ShowMessageFromQQResp应答实例 627 | */ 628 | + (ShowMessageFromQQResp *)respWithResult:(NSString *)result errorDescription:(NSString *)errDesp; 629 | 630 | @end 631 | 632 | #endif 633 | -------------------------------------------------------------------------------- /src/ios/TencentOpenAPI.framework/Headers/TencentApiInterface.h: -------------------------------------------------------------------------------- 1 | // 2 | // TencentMessage.h 3 | // TencentOpenApi_IOS 4 | // 5 | // Created by qqconnect on 13-5-29. 6 | // Copyright (c) 2013年 Tencent. All rights reserved. 7 | // 8 | 9 | #ifndef QQ_OPEN_SDK_LITE 10 | 11 | #import 12 | #import "TencentMessageObject.h" 13 | 14 | typedef enum 15 | { 16 | kIphoneQQ, 17 | kIphoneQZONE, 18 | kIphoneTIM, 19 | kThirdApp, 20 | } 21 | TecnentPlatformType; 22 | 23 | typedef enum 24 | { 25 | kTencentApiSuccess, 26 | kTencentApiPlatformUninstall, 27 | kTencentApiPlatformNotSupport, 28 | kTencentApiParamsError, 29 | kTencentApiFail, 30 | } 31 | TencentApiRetCode; 32 | 33 | @class TencentApiReq; 34 | @class TencentApiResp; 35 | 36 | /** 37 | * \brief TencentApiInterface的回调 38 | * 39 | * TencentApiInterface的回调接口 40 | * \note v1.0版本只支持腾讯业务拉起第三方请求内容 41 | */ 42 | @protocol TencentApiInterfaceDelegate 43 | 44 | @optional 45 | /** 46 | * 请求获得内容 当前版本只支持第三方相应腾讯业务请求 47 | */ 48 | - (BOOL)onTencentReq:(TencentApiReq *)req; 49 | 50 | /** 51 | * 响应请求答复 当前版本只支持腾讯业务相应第三方的请求答复 52 | */ 53 | - (BOOL)onTencentResp:(TencentApiResp *)resp; 54 | 55 | @end 56 | 57 | /** 58 | * \brief TencentApiInterface的回调 59 | * 60 | * TencentApiInterface的调用接口 61 | * \note v1.0版本只支持第三方答复内容 62 | */ 63 | @interface TencentApiInterface : NSObject 64 | 65 | /** 66 | * 发送答复返回腾讯业务 67 | * \param resp 答复内容 68 | * \return 返回码 69 | */ 70 | + (TencentApiRetCode)sendRespMessageToTencentApp:(TencentApiResp *)resp; 71 | 72 | /** 73 | * 是否可以处理拉起协议 74 | * \param url 75 | * \param delegate 指定的回调 76 | * \return 是否是腾讯API认识的消息类型 77 | */ 78 | + (BOOL)canOpenURL:(NSURL *)url delegate:(id)delegate; 79 | 80 | /** 81 | * 处理应用拉起协议 82 | * \param url 83 | * \param delegate 指定的回调 84 | * \return 是否是腾讯API认识的消息类型 85 | */ 86 | + (BOOL)handleOpenURL:(NSURL *)url delegate:(id)delegate; 87 | 88 | /** 89 | * 用户设备是否安装腾讯APP 90 | * \param platform 指定的腾讯业务 91 | * \return YES:安装 NO:未安装 92 | */ 93 | + (BOOL)isTencentAppInstall:(TecnentPlatformType)platform; 94 | 95 | /** 96 | * 用户设备是否支持调用SDK 97 | * \param platform 指定的腾讯业务 98 | * \return YES:支持 NO:不支持 99 | */ 100 | + (BOOL)isTencentAppSupportTencentApi:(TecnentPlatformType)platform; 101 | 102 | @end 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /src/ios/TencentOpenAPI.framework/Headers/TencentMessageObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // TencentMessageObject.h 3 | // TencentOpenApi_IOS 4 | // 5 | // Created by qqconnect on 13-5-27. 6 | // Copyright (c) 2013年 Tencent. All rights reserved. 7 | // 8 | 9 | #ifndef QQ_OPEN_SDK_LITE 10 | 11 | #import 12 | #import 13 | #import "sdkdef.h" 14 | 15 | #define kTextLimit (1024 * 1024) 16 | #define kDataLimit (1024 * 1024 * 10) 17 | #define kPreviewDataLimit (1024 * 1024) 18 | 19 | @class TencentApiReq; 20 | @class TencentApiResp; 21 | 22 | /** 23 | * 必填的NSArray型参数 24 | */ 25 | typedef NSArray *TCRequiredArray; 26 | 27 | /** 28 | * 必填的NSDictionary型参数 29 | */ 30 | typedef NSDictionary *TCRequiredDictionary; 31 | 32 | /** 33 | * 必填的TencentApiReq型参数 34 | */ 35 | typedef TencentApiReq *TCRequiredReq; 36 | 37 | /** 38 | * 可选的UIImage类型参数 39 | */ 40 | typedef NSData *TCOptionalData; 41 | 42 | 43 | /** 44 | * 可选的NSArray型参数 45 | */ 46 | typedef NSArray *TCOptionalArray; 47 | 48 | /** 49 | * 可选的TencentApiReq型参数 50 | */ 51 | typedef TencentApiReq *TCOptionalReq; 52 | 53 | /** 54 | * TencentReqMessageType 请求类型枚举参数 55 | */ 56 | typedef enum 57 | { 58 | /** TX APP请求内容填充(需要第三方开发者填充完成内容后需要主动调用sendRespMessageToTencentApp)*/ 59 | ReqFromTencentAppQueryContent, 60 | /** TX APP请求展现内容 (不用调用答复) */ 61 | ReqFromTencentAppShowContent, 62 | /** 第三方 APP 请求内容 */ 63 | ReqFromThirdAppQueryContent, 64 | /** 第三方 APP 请求展现内容(类似分享)*/ 65 | ReqFromThirdAppShowContent, 66 | } 67 | TencentReqMessageType; 68 | 69 | typedef enum 70 | { 71 | RespFromTencentAppQueryContent, 72 | RespFromTencentAppShowContent, 73 | RespFromThirdAppQueryContent, 74 | RespFromThirdAppShowContent, 75 | } 76 | TencentRespMessageType; 77 | 78 | /** 79 | * TencentObjVersion 腾讯API消息类型枚举 80 | */ 81 | typedef enum 82 | { 83 | /** 文本类型 */ 84 | TencentTextObj, 85 | /** 图片类型 */ 86 | TencentImageObj, 87 | /** 音频类型 */ 88 | TencentAudioObj, 89 | /** 视频类型 */ 90 | TencentVideoObj, 91 | /** 图片视频类 */ 92 | TencentImageAndVideoObj, 93 | } 94 | TencentObjVersion; 95 | 96 | /** 97 | * \brief 请求包 98 | * 99 | * TencentApiReq用来向其他业务发送请求包 100 | */ 101 | @interface TencentApiReq : NSObject 102 | 103 | /** 104 | * 根据序列号生成一个请求包 105 | * \param apiSeq 请求序列号 106 | * \param type 请求类型 107 | * \return tencentApiReq实例 108 | */ 109 | + (TencentApiReq *)reqFromSeq:(NSInteger)apiSeq type:(TencentReqMessageType)type; 110 | 111 | /** 请求类型 */ 112 | @property (readonly, assign, nonatomic)TCRequiredInt nMessageType; 113 | 114 | /** 请求平台 */ 115 | @property (readonly, assign, nonatomic)NSInteger nPlatform; 116 | 117 | /** 请求的SDK版本号 */ 118 | @property (readonly, assign, nonatomic)NSInteger nSdkVersion; 119 | 120 | /** 请求序列号 */ 121 | @property (readonly, assign, nonatomic)TCRequiredInt nSeq; 122 | 123 | /** 第三方的APPID */ 124 | @property (nonatomic, retain)TCRequiredStr sAppID; 125 | 126 | /** 请求内容 TencentBaseMessageObj对象数组 */ 127 | @property (nonatomic, retain)TCOptionalArray arrMessage; 128 | 129 | /** 请求的描述 可以用于告诉对方这个请求的特定场景 */ 130 | @property (nonatomic, retain)TCOptionalStr sDescription; 131 | 132 | @end 133 | 134 | /** 135 | * \brief 答复包 136 | * 137 | * TencentApiResp用来向其他业务发送答复包 138 | */ 139 | @interface TencentApiResp : NSObject 140 | 141 | /** 142 | * 根据序列号生成一个答复包 143 | * \param req 答复对应的请求包(如果req不是TencentApiReq或者他的子类,会抛出异常) 144 | * \return 答复包体 145 | */ 146 | + (TencentApiResp *)respFromReq:(TencentApiReq *)req; 147 | 148 | /** 返回码 */ 149 | @property (nonatomic, assign)TCOptionalInt nRetCode; 150 | 151 | /** 返回消息 */ 152 | @property (nonatomic, retain)TCOptionalStr sRetMsg; 153 | 154 | /** 答复对应的请求包 */ 155 | @property (nonatomic, retain)TCOptionalReq objReq; 156 | 157 | @end 158 | 159 | /** 160 | * \brief 消息体 161 | * 162 | * TencentBaseMessageObj 应用之间传递消息体 163 | */ 164 | @interface TencentBaseMessageObj : NSObject 165 | 166 | /** 消息类型 */ 167 | @property (nonatomic, assign)NSInteger nVersion; 168 | 169 | /** 消息描述 */ 170 | @property (nonatomic, retain)NSString *sName; 171 | 172 | /** 消息的扩展信息 主要是可以用来进行一些请求消息体的描述 譬如图片要求的width height 文字的关键字什么的, 也可以不用填写*/ 173 | @property (nonatomic, retain)NSDictionary *dictExpandInfo; 174 | 175 | /** 176 | * 消息是否有效 177 | */ 178 | - (BOOL)isVaild; 179 | 180 | @end 181 | 182 | #pragma mark TencentTextMessage 183 | /** 184 | * \brief 文本的消息体 185 | * 186 | * TencentTextMessageObjV1 应用之间传递的文本消息体 187 | */ 188 | @interface TencentTextMessageObjV1 : TencentBaseMessageObj 189 | 190 | /** 191 | * 文本 192 | * \note 文本长度不能超过4096个字 193 | */ 194 | @property (nonatomic, retain) NSString *sText; 195 | 196 | 197 | /** 198 | * 初始化文本消息 199 | * \param text 文本 200 | * \return 初始化返回的文本消息 201 | */ 202 | - (id)initWithText:(NSString *)text; 203 | 204 | @end 205 | 206 | 207 | #pragma mark TecentImageMessage 208 | 209 | /** 210 | * TencentApiImageSourceType 图片数据类型(请求方对数据类型可能会有限制) 211 | */ 212 | typedef enum 213 | { 214 | /** 图片数据是url或二进制数据 */ 215 | AllImage, 216 | /** 图片数据是url */ 217 | UrlImage, 218 | /** 图片数据是二进制数据 */ 219 | DataImage, 220 | }TencentApiImageSourceType; 221 | 222 | /** 223 | * \brief 图片的消息体 224 | * 225 | * TencentImageMessageObjV1 应用之间传递的图片消息体 226 | */ 227 | @interface TencentImageMessageObjV1 : TencentBaseMessageObj 228 | 229 | /** 230 | * 图片数据 231 | * \note 图片不能大于10M 232 | */ 233 | @property (nonatomic, retain) NSData *dataImage; 234 | 235 | /** 236 | * 缩略图的数据 237 | * \note 图片不能大于1M 238 | */ 239 | @property (nonatomic, retain) NSData *dataThumbImage; 240 | 241 | /** 图片URL */ 242 | @property (nonatomic, retain) NSString *sUrl; 243 | 244 | /** 图片的描述 */ 245 | @property (nonatomic, retain) NSString *sDescription; 246 | 247 | /** 图片的size */ 248 | @property (nonatomic, assign) CGSize szImage; 249 | 250 | /** 251 | * 图片来源 252 | * \note TencentApiImageSourceType对应的类型 253 | */ 254 | @property (readonly, assign) NSInteger nType; 255 | 256 | /** 257 | * 初始化图片消息 258 | * \param dataImage 图片类型 259 | * \return 初始化返回的图片消息 260 | */ 261 | - (id)initWithImageData:(NSData *)dataImage; 262 | 263 | /** 264 | * 初始化图片消息 265 | * \param url 图片url 266 | * \return 初始化返回的图片消息 267 | */ 268 | - (id)initWithImageUrl:(NSString *)url; 269 | 270 | /** 271 | * 初始化图片消息 272 | * \param type 图片类型 273 | * \return 初始化返回的图片消息 274 | */ 275 | - (id)initWithType:(TencentApiImageSourceType)type; 276 | @end 277 | 278 | 279 | #pragma mark TencentAudioMessage 280 | /** 281 | * \brief 音频的消息体 282 | * 283 | * TencentAudioMessageObjV1 应用之间传递的音频消息体 284 | */ 285 | @interface TencentAudioMessageObjV1 : TencentBaseMessageObj 286 | 287 | /** 音频URL */ 288 | @property (nonatomic, retain) NSString *sUrl; 289 | 290 | /** 291 | * 音频的预览图 292 | * \note图片不能大于1M 293 | */ 294 | @property (nonatomic, retain) NSData *dataImagePreview; 295 | 296 | /** 音频的预览图URL */ 297 | @property (nonatomic, retain) NSString *sImagePreviewUrl; 298 | 299 | /** 音频的描述 */ 300 | @property (nonatomic, retain) NSString *sDescription; 301 | 302 | /** 303 | * 初始化图片消息 304 | * \param url 音频URL 305 | * \return 初始化返回的音频消息 306 | */ 307 | - (id)initWithAudioUrl:(NSString *)url; 308 | 309 | @end 310 | 311 | 312 | #pragma mark TencentVideoMessage 313 | 314 | /** 315 | * TencentApiVideoSourceType 视频数据类型(请求方对数据类型可能会有限制) 316 | */ 317 | 318 | typedef enum 319 | { 320 | /** 视频来源于本地或网络 */ 321 | AllVideo, 322 | /** 视频来源于本地 */ 323 | LocalVideo, 324 | /** 视频来源于网络 */ 325 | NetVideo, 326 | }TencentApiVideoSourceType; 327 | 328 | /** 329 | * \brief 视频的消息体 330 | * 331 | * TencentVideoMessageV1 应用之间传递的视频消息体 332 | */ 333 | @interface TencentVideoMessageV1 : TencentBaseMessageObj 334 | 335 | /** 336 | * 视频URL 337 | * \note 不能超过1024 338 | */ 339 | @property (nonatomic, retain) NSString *sUrl; 340 | 341 | /** 342 | * 视频来源 主要是用来让发起方指定视频的来源 343 | * \note TencentApiVideoSourceType 对应的类型 只读参数 344 | */ 345 | @property (readonly, assign, nonatomic) NSInteger nType; 346 | 347 | /** 348 | * 视频的预览图 349 | * \note 图片不能大于1M 350 | */ 351 | @property (nonatomic, retain) NSData *dataImagePreview; 352 | 353 | /** 视频的预览图URL */ 354 | @property (nonatomic, retain) NSString *sImagePreviewUrl; 355 | 356 | /** 视频的描述 */ 357 | @property (nonatomic, retain) NSString *sDescription; 358 | 359 | /** 360 | * 初始化视频消息 361 | * \param url 视频URL 362 | * \param type 视频来源类型 363 | * \return 初始化返回的视频消息 364 | */ 365 | - (id)initWithVideoUrl:(NSString *)url type:(TencentApiVideoSourceType)type; 366 | 367 | 368 | /** 369 | * 初始化视频消息 370 | * \param type 视频来源类型 371 | * \return 初始化返回的视频消息 372 | */ 373 | - (id)initWithType:(TencentApiVideoSourceType)type; 374 | @end 375 | 376 | #pragma mark TencentImageMessageObj 377 | /** 378 | * \brief 视频图片消息体 379 | * 380 | * TencentVideoMessageV1 这是一个扩展的类 是一个图片视频类 381 | * \note 图片视频可以任选一个内容填充 但是注意只能填一个 当有一种类型被填充后 另外一个种类型就无法填充了 382 | */ 383 | @interface TencentImageAndVideoMessageObjV1 : TencentBaseMessageObj 384 | 385 | /** 图片消息 */ 386 | @property (nonatomic, retain) TencentImageMessageObjV1 *objImageMessage; 387 | 388 | /** 视频消息 */ 389 | @property (nonatomic, retain) TencentVideoMessageV1 *objVideoMessage; 390 | 391 | /** 392 | * 初始化图片消息 393 | * \param dataImage 图片数据 394 | * \param url 视频url 395 | * \return 初始化返回的图片视频消息 396 | */ 397 | - (id)initWithMessage:(NSData *)dataImage videoUrl:(NSString *)url; 398 | 399 | /** 400 | * 设置图片 401 | * \param dataImage 图片数据 402 | */ 403 | - (void)setDataImage:(NSData *)dataImage; 404 | 405 | /** 406 | * 设置视频 407 | * \param videoUrl 视频URL 408 | */ 409 | - (void)setVideoUrl:(NSString *)videoUrl; 410 | @end 411 | 412 | #endif 413 | -------------------------------------------------------------------------------- /src/ios/TencentOpenAPI.framework/Headers/TencentOAuth.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// \file TencentOAuth.h 3 | /// \brief QQ互联开放平台授权登录及相关开放接口实现类 4 | /// 5 | /// Created by Tencent on 12-12-21. 6 | /// Copyright (c) 2012年 Tencent. All rights reserved. 7 | /// 8 | 9 | #import 10 | #import "sdkdef.h" 11 | #import "TencentOAuthObject.h" 12 | #import "TencentApiInterface.h" 13 | 14 | @protocol TencentSessionDelegate; 15 | @protocol TencentLoginDelegate; 16 | @protocol TencentApiInterfaceDelegate; 17 | @protocol TencentWebViewDelegate; 18 | 19 | @class TencentApiReq; 20 | @class TencentApiResp; 21 | 22 | typedef enum 23 | { 24 | kTencentNotAuthorizeState, 25 | kTencentSSOAuthorizeState, 26 | kTencentWebviewAuthorzieState, 27 | } TencentAuthorizeState; 28 | 29 | typedef enum 30 | { 31 | kAuthModeClientSideToken, 32 | kAuthModeServerSideCode, 33 | } TencentAuthMode; 34 | 35 | #pragma mark - TencentOAuth(授权登录及相关开放接口调用) 36 | 37 | /** 38 | * \brief TencentOpenAPI授权登录及相关开放接口调用 39 | * 40 | * TencentOAuth实现授权登录逻辑以及相关开放接口的请求调用 41 | */ 42 | @interface TencentOAuth : NSObject 43 | { 44 | NSMutableDictionary* _apiRequests; 45 | NSString* _accessToken; 46 | NSDate* _expirationDate; 47 | id _sessionDelegate; 48 | NSString* _localAppId; 49 | NSString* _openId; 50 | NSString* _redirectURI; 51 | NSArray* _permissions; 52 | } 53 | 54 | /** Access Token凭证,用于后续访问各开放接口 */ 55 | @property(nonatomic, copy) NSString* accessToken; 56 | 57 | /** Access Token的失效期 */ 58 | @property(nonatomic, copy) NSDate* expirationDate; 59 | 60 | /** 已实现的开放接口的回调委托对象 */ 61 | @property(nonatomic, assign) id sessionDelegate; 62 | 63 | /** 第三方应用在开发过程中设置的URLSchema,用于浏览器登录后后跳到第三方应用 */ 64 | @property(nonatomic, copy) NSString* localAppId; 65 | 66 | /** 用户授权登录后对该用户的唯一标识 */ 67 | @property(nonatomic, copy) NSString* openId; 68 | 69 | /** 用户登录成功过后的跳转页面地址 */ 70 | @property(nonatomic, copy) NSString* redirectURI; 71 | 72 | /** 第三方应用在互联开放平台申请的appID */ 73 | @property(nonatomic, retain) NSString* appId; 74 | 75 | /** 主要是互娱的游戏设置uin */ 76 | @property(nonatomic, retain) NSString* uin; 77 | 78 | /** 主要是互娱的游戏设置鉴定票据 */ 79 | @property(nonatomic, retain) NSString* skey; 80 | 81 | /** 登陆透传的数据 */ 82 | @property(nonatomic, copy) NSDictionary* passData; 83 | 84 | /** 授权方式(Client Side Token或者Server Side Code) */ 85 | @property(nonatomic, assign) TencentAuthMode authMode; 86 | 87 | /** union id */ 88 | @property(nonatomic, retain) NSString* unionid; 89 | 90 | /** 第三方在授权登录/分享 时选择 QQ,还是TIM 。在授权前一定要指定其中一个类型*/ 91 | @property(nonatomic, assign) TencentAuthShareType authShareType; 92 | 93 | /** 94 | * 用来获得当前sdk的版本号 95 | * \return 返回sdk版本号 96 | **/ 97 | 98 | + (NSString*)sdkVersion; 99 | 100 | /** 101 | * 用来获得当前sdk的小版本号 102 | * \return 返回sdk小版本号 103 | **/ 104 | 105 | + (NSString*)sdkSubVersion; 106 | 107 | /** 108 | * 用来获得当前sdk的是否精简版 109 | * \return 返回YES表示精简版 110 | **/ 111 | 112 | + (BOOL)isLiteSDK; 113 | 114 | /** 115 | * 主要是用来帮助判断是否有登陆被发起,但是还没有过返回结果 116 | * \return 117 | * kTencentNotAuthorizeState:无授权 118 | * kTencentSSOAuthorizeState:有人发起了sso授权但无返回 119 | * kTencentWebviewAuthorzieState:有人发起了webview授权还未返回 120 | **/ 121 | 122 | + (TencentAuthorizeState *)authorizeState; 123 | 124 | /** 125 | * 用来获得当前手机qq的版本号 126 | * \return 返回手机qq版本号 127 | **/ 128 | + (QQVersion)iphoneQQVersion; 129 | 130 | 131 | /** 132 | * 用来获得当前手机TIM的版本号 133 | * \return 返回手机qq版本号 134 | **/ 135 | + (QQVersion)iphoneTIMVersion; 136 | 137 | /** 138 | * 初始化TencentOAuth对象 139 | * \param appId 第三方应用在互联开放平台申请的唯一标识 140 | * \param delegate 第三方应用用于接收请求返回结果的委托对象 141 | * \return 初始化后的授权登录对象 142 | */ 143 | - (id)initWithAppId:(NSString *)appId 144 | andDelegate:(id)delegate; 145 | 146 | 147 | /** 148 | * 判断用户手机上是否安装手机QQ 149 | * \return YES:安装 NO:没安装 150 | */ 151 | + (BOOL)iphoneQQInstalled; 152 | 153 | /** 154 | * 判断用户手机上是否安装手机TIM 155 | * \return YES:安装 NO:没安装 156 | */ 157 | + (BOOL)iphoneTIMInstalled; 158 | 159 | /** 160 | * 判断用户手机上的手机QQ是否支持SSO登录 161 | * \return YES:支持 NO:不支持 162 | */ 163 | + (BOOL)iphoneQQSupportSSOLogin; 164 | 165 | /** 166 | * 判断用户手机上的手机TIM是否支持SSO登录 167 | * \return YES:支持 NO:不支持 168 | */ 169 | + (BOOL)iphoneTIMSupportSSOLogin; 170 | 171 | /** 172 | * 判断用户手机上是否安装手机QZone 173 | * \return YES:安装 NO:没安装 174 | */ 175 | + (BOOL)iphoneQZoneInstalled; 176 | 177 | /** 178 | * 判断用户手机上的手机QZone是否支持SSO登录 179 | * \return YES:支持 NO:不支持 180 | */ 181 | + (BOOL)iphoneQZoneSupportSSOLogin; 182 | 183 | /** 184 | * 登录授权 185 | * 186 | * \param permissions 授权信息列 187 | */ 188 | - (BOOL)authorize:(NSArray *)permissions; 189 | 190 | /** 191 | * 登录授权 192 | * \param permissions 授权信息列表 193 | * \param bInSafari 是否使用safari进行登录.IOS SDK 1.3版本开始此参数废除 194 | */ 195 | - (BOOL)authorize:(NSArray *)permissions 196 | inSafari:(BOOL)bInSafari; 197 | 198 | /** 199 | * 登录授权 200 | * \param permissions 授权信息列表 201 | * \param localAppId 应用APPID 202 | * \param bInSafari 是否使用safari进行登录.IOS SDK 1.3版本开始此参数废除 203 | */ 204 | - (BOOL)authorize:(NSArray *)permissions 205 | localAppId:(NSString *)localAppId 206 | inSafari:(BOOL)bInSafari; 207 | 208 | /** 209 | * 增量授权,因用户没有授予相应接口调用的权限,需要用户确认是否授权 210 | * \param permissions 需增量授权的信息列表 211 | * \return 增量授权调用是否成功 212 | */ 213 | - (BOOL)incrAuthWithPermissions:(NSArray *)permissions; 214 | 215 | /** 216 | * 重新授权,因token废除或失效导致接口调用失败,需用户重新授权 217 | * \param permissions 授权信息列表,同登录授权 218 | * \return 授权调用是否成功 219 | */ 220 | - (BOOL)reauthorizeWithPermissions:(NSArray *)permissions; 221 | 222 | /** 223 | * 获取UnindID,可以根据UnindID的比较来确定OpenID是否属于同一个用户 224 | * \return NO未登录,信息不足;YES条件满足,发送请求成功,请等待回调 225 | */ 226 | - (BOOL)RequestUnionId; 227 | 228 | /** 229 | * (静态方法)处理应用拉起协议 230 | * \param url 处理被其他应用呼起时的逻辑 231 | * \return 处理结果,YES表示成功,NO表示失败 232 | */ 233 | + (BOOL)HandleOpenURL:(NSURL *)url; 234 | 235 | /** 236 | * (静态方法)sdk是否可以处理应用拉起协议 237 | * \param url 处理被其他应用呼起时的逻辑 238 | * \return 处理结果,YES表示可以 NO表示不行 239 | */ 240 | + (BOOL)CanHandleOpenURL:(NSURL *)url; 241 | 242 | /** 243 | * (静态方法)获取TencentOAuth调用的上一次错误信息 244 | */ 245 | + (NSString *)getLastErrorMsg; 246 | 247 | /** 248 | * 以Server Side Code模式授权登录时,通过此接口获取返回的code值; 249 | * 以Client Side Token模式授权登录时,忽略此接口。 250 | */ 251 | - (NSString *)getServerSideCode; 252 | 253 | /** 254 | * 退出登录(退出登录后,TecentOAuth失效,需要重新初始化) 255 | * \param delegate 第三方应用用于接收请求返回结果的委托对象 256 | */ 257 | - (void)logout:(id)delegate; 258 | 259 | /** 260 | * 判断登录态是否有效 261 | * \return 处理结果,YES表示有效,NO表示无效,请用户重新登录授权 262 | */ 263 | - (BOOL)isSessionValid; 264 | 265 | /** 266 | * 获取用户个人信息 267 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 268 | */ 269 | - (BOOL)getUserInfo; 270 | 271 | /** 272 | * SDK内置webview实现定向分享时,第三方应用可以根据应用是否在白名单里来开启该配置开关,默认为关闭; 273 | * 在白名单里的应用调用该接口后,即打开sdk内置webview的二级白名单开关(相对与sdk后台的白名单), 274 | * 那么在sdk后台白名单校验请求失败的情况下,会继续先尝试采用内置webview进行分享。 275 | */ 276 | - (void)openSDKWebViewQQShareEnable; 277 | 278 | 279 | /** 280 | * 获取用户QZone相册列表 281 | * \attention 需\ref apply_perm 282 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 283 | */ 284 | - (BOOL)getListAlbum; 285 | 286 | /** 287 | * 获取用户QZone相片列表 288 | * \attention 需\ref apply_perm 289 | * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCListPhotoDic 290 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 291 | */ 292 | - (BOOL)getListPhotoWithParams:(NSMutableDictionary *)params; 293 | 294 | 295 | /** 296 | * 分享到QZone 297 | * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCAddShareDic 298 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 299 | */ 300 | - (BOOL)addShareWithParams:(NSMutableDictionary *)params; 301 | 302 | 303 | /** 304 | * 上传照片到QZone指定相册 305 | * \attention 需\ref apply_perm 306 | * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCUploadPicDic 307 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 308 | */ 309 | - (BOOL)uploadPicWithParams:(NSMutableDictionary *)params; 310 | 311 | /** 312 | * 在QZone相册中创建一个新的相册 313 | * \attention 需\ref apply_perm 314 | * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCAddAlbumDic 315 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 316 | */ 317 | - (BOOL)addAlbumWithParams:(NSMutableDictionary *)params; 318 | 319 | /** 320 | * 检查是否是QZone某个用户的粉丝 321 | * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCCheckPageFansDic 322 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 323 | */ 324 | - (BOOL)checkPageFansWithParams:(NSMutableDictionary *)params; 325 | 326 | /** 327 | * 在QZone中发表一篇日志 328 | * \attention 需\ref apply_perm 329 | * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCAddOneBlogDic 330 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 331 | */ 332 | - (BOOL)addOneBlogWithParams:(NSMutableDictionary *)params; 333 | 334 | /** 335 | * 在QZone中发表一条说说 336 | * \attention 需\ref apply_perm 337 | * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCAddTopicDic 338 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 339 | */ 340 | - (BOOL)addTopicWithParams:(NSMutableDictionary *)params; 341 | 342 | /** 343 | * 设置QQ头像 使用默认的效果处理设置头像的界面 344 | * \attention 需\ref apply_perm 345 | * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCSetUserHeadpic 346 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 347 | */ 348 | - (BOOL)setUserHeadpic:(NSMutableDictionary *)params; 349 | 350 | 351 | /** 352 | * 设置QQ头像 会返回设置头像由第三方自己处理界面的弹出方式 353 | * \attention 需\ref apply_perm 354 | * \param params 参数字典,字典的关键字参见TencentOAuthObject.h中的\ref TCSetUserHeadpic 355 | * \param viewController 设置头像的界面 356 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 357 | */ 358 | - (BOOL)setUserHeadpic:(NSMutableDictionary *)params andViewController:(UIViewController **)viewController; 359 | 360 | /** 361 | * 获取QQ会员信息(仅包括是否为QQ会员,是否为年费QQ会员) 362 | * \attention 需\ref apply_perm 363 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 364 | */ 365 | - (BOOL)getVipInfo; 366 | 367 | /** 368 | * 获取QQ会员详细信息 369 | * \attention 需\ref apply_perm 370 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 371 | */ 372 | - (BOOL)getVipRichInfo; 373 | 374 | /** 375 | * QZone定向分享,可以@到具体好友,完成后将触发responseDidReceived:forMessage:回调,message:“SendStory” 376 | * \param params 参数字典 377 | * \param fopenIdArray 第三方应用预传人好友列表,好友以openid标识 378 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 379 | */ 380 | - (BOOL)sendStory:(NSMutableDictionary *)params friendList:(NSArray *)fopenIdArray; 381 | 382 | /** 383 | * 发送应用邀请,完成后将触发responseDidReceived:forMessage:回调,message:“AppInvitation” 384 | * \param desc 应用的描述文字,不超过35字符,如果为nil或@“”则显示默认描述 385 | * \param imageUrl 应用的图标,如果为nil或者@“”则显示默认图标 386 | * \param source 透传参数,由开发者自定义该参数内容 387 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 388 | */ 389 | - (BOOL)sendAppInvitationWithDescription:(NSString *)desc imageURL:(NSString *)imageUrl source:(NSString *)source; 390 | 391 | /** 392 | * 发起PK或者发送炫耀,完成后将触发responseDidReceived:forMessage:回调,message:“AppChallenge” 393 | * \param receiver 必须指定一位进行PK或者炫耀的好友,填写其OpenID,填写多个OpenID将截取第一个 394 | * \param type 类型,"pk"或者“brag” 395 | * \param imageUrl 炫耀/挑战场景图的URL 396 | * \param message 炫耀/挑战中的内容描述,不超过50个字符,超过限制则自动截断 397 | * \param source 透传参数,由开发者自定义该参数内容 398 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 399 | */ 400 | - (BOOL)sendChallenge:(NSString *)receiver type:(NSString *)type imageURL:(NSString *)imageUrl message:(NSString *)message source:(NSString *)source; 401 | 402 | /** 403 | * 赠送或者请求礼物,完成后将触发responseDidReceived:forMessage:回调,message:“AppGiftRequest” 404 | * \param receiver 赠送或者请求礼物的好友的OpenID,支持填写多个,OpenID之用","分隔,为nil时将由用户通过好友选择器选择好友 405 | * \param exclude 用户通过好友选择器选择好友场景下,希望排除的好友(不显示在好友选择器) 406 | * \param specified 用户通过好友选择器选择好友场景下,希望出现的指定好友 407 | * \param only 是否只显示specified指定的好友 408 | * \param type 类型,"request"或者“freegift” 409 | * \param title 免费礼物或请求名称,不超过6个字符 410 | * \param message 礼物或请求的默认赠言,控制在35个汉字以内,超过限制自动截断 411 | * \param imageUrl 请求或礼物配图的URL,如果不传,则默认在弹框中显示应用的icon 412 | * \param source 透传参数,由开发者自定义该参数内容 413 | * \return 处理结果,YES表示API调用成功,NO表示API调用失败,登录态失败,重新登录 414 | */ 415 | - (BOOL)sendGiftRequest:(NSString *)receiver exclude:(NSString *)exclude specified:(NSString *)specified only:(BOOL)only type:(NSString *)type title:(NSString *)title message:(NSString *)message imageURL:(NSString *)imageUrl source:(NSString *)source; 416 | 417 | 418 | /** 419 | * 退出指定API调用 420 | * \param userData 用户调用某条API的时候传入的保留参数 421 | * \return 处理结果,YES表示成功 NO表示失败 422 | */ 423 | - (BOOL)cancel:(id)userData; 424 | 425 | /** 426 | * CGI类任务创建接口 427 | * \param apiURL CGI请求的URL地址 428 | * \param method CGI请求方式:"GET","POST" 429 | * \param params CGI请求参数字典 430 | * \param callback CGI请求结果的回调接口对象 431 | * \return CGI请求任务实例,用于取消任务,返回nil代表任务创建失败 432 | */ 433 | - (TCAPIRequest *)cgiRequestWithURL:(NSURL *)apiURL method:(NSString *)method params:(NSDictionary *)params callback:(id)callback; 434 | 435 | /** 436 | * TencentOpenApi发送任务统一接口 437 | * \param request 请求发送的任务 438 | * \param callback 任务发送后的回调地址 439 | */ 440 | - (BOOL)sendAPIRequest:(TCAPIRequest *)request callback:(id)callback; 441 | 442 | - (NSString *)getUserOpenID; 443 | 444 | @end 445 | 446 | #pragma mark - TencentLoginDelegate(授权登录回调协议) 447 | 448 | /** 449 | * \brief TencentLoginDelegate iOS Open SDK 1.3 API回调协议 450 | * 451 | * 第三方应用实现登录的回调协议 452 | */ 453 | @protocol TencentLoginDelegate 454 | 455 | @required 456 | 457 | /** 458 | * 登录成功后的回调 459 | */ 460 | - (void)tencentDidLogin; 461 | 462 | /** 463 | * 登录失败后的回调 464 | * \param cancelled 代表用户是否主动退出登录 465 | */ 466 | - (void)tencentDidNotLogin:(BOOL)cancelled; 467 | 468 | /** 469 | * 登录时网络有问题的回调 470 | */ 471 | - (void)tencentDidNotNetWork; 472 | 473 | @optional 474 | /** 475 | * 登录时权限信息的获得 476 | */ 477 | - (NSArray *)getAuthorizedPermissions:(NSArray *)permissions withExtraParams:(NSDictionary *)extraParams; 478 | 479 | /** 480 | * unionID获得 481 | */ 482 | - (void)didGetUnionID; 483 | 484 | @end 485 | 486 | #pragma mark - TencentSessionDelegate(开放接口回调协议) 487 | 488 | /** 489 | * \brief TencentSessionDelegate iOS Open SDK 1.3 API回调协议 490 | * 491 | * 第三方应用需要实现每条需要调用的API的回调协议 492 | */ 493 | @protocol TencentSessionDelegate 496 | 497 | @optional 498 | 499 | /** 500 | * 退出登录的回调 501 | */ 502 | - (void)tencentDidLogout; 503 | 504 | /** 505 | * 因用户未授予相应权限而需要执行增量授权。在用户调用某个api接口时,如果服务器返回操作未被授权,则触发该回调协议接口,由第三方决定是否跳转到增量授权页面,让用户重新授权。 506 | * \param tencentOAuth 登录授权对象。 507 | * \param permissions 需增量授权的权限列表。 508 | * \return 是否仍然回调返回原始的api请求结果。 509 | * \note 不实现该协议接口则默认为不开启增量授权流程。若需要增量授权请调用\ref TencentOAuth#incrAuthWithPermissions: \n注意:增量授权时用户可能会修改登录的帐号 510 | */ 511 | - (BOOL)tencentNeedPerformIncrAuth:(TencentOAuth *)tencentOAuth withPermissions:(NSArray *)permissions; 512 | 513 | /** 514 | * [该逻辑未实现]因token失效而需要执行重新登录授权。在用户调用某个api接口时,如果服务器返回token失效,则触发该回调协议接口,由第三方决定是否跳转到登录授权页面,让用户重新授权。 515 | * \param tencentOAuth 登录授权对象。 516 | * \return 是否仍然回调返回原始的api请求结果。 517 | * \note 不实现该协议接口则默认为不开启重新登录授权流程。若需要重新登录授权请调用\ref TencentOAuth#reauthorizeWithPermissions: \n注意:重新登录授权时用户可能会修改登录的帐号 518 | */ 519 | - (BOOL)tencentNeedPerformReAuth:(TencentOAuth *)tencentOAuth; 520 | 521 | /** 522 | * 用户通过增量授权流程重新授权登录,token及有效期限等信息已被更新。 523 | * \param tencentOAuth token及有效期限等信息更新后的授权实例对象 524 | * \note 第三方应用需更新已保存的token及有效期限等信息。 525 | */ 526 | - (void)tencentDidUpdate:(TencentOAuth *)tencentOAuth; 527 | 528 | /** 529 | * 用户增量授权过程中因取消或网络问题导致授权失败 530 | * \param reason 授权失败原因,具体失败原因参见sdkdef.h文件中\ref UpdateFailType 531 | */ 532 | - (void)tencentFailedUpdate:(UpdateFailType)reason; 533 | 534 | /** 535 | * 获取用户个人信息回调 536 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 537 | * \remarks 正确返回示例: \snippet example/getUserInfoResponse.exp success 538 | * 错误返回示例: \snippet example/getUserInfoResponse.exp fail 539 | */ 540 | - (void)getUserInfoResponse:(APIResponse*) response; 541 | 542 | 543 | /** 544 | * 获取用户QZone相册列表回调 545 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 546 | * \remarks 正确返回示例: \snippet example/getListAlbumResponse.exp success 547 | * 错误返回示例: \snippet example/getListAlbumResponse.exp fail 548 | */ 549 | - (void)getListAlbumResponse:(APIResponse*) response; 550 | 551 | /** 552 | * 获取用户QZone相片列表 553 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 554 | * \remarks 正确返回示例: \snippet example/getListPhotoResponse.exp success 555 | * 错误返回示例: \snippet example/getListPhotoResponse.exp fail 556 | */ 557 | - (void)getListPhotoResponse:(APIResponse*) response; 558 | 559 | /** 560 | * 检查是否是QZone某个用户的粉丝回调 561 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 562 | * \remarks 正确返回示例: \snippet example/checkPageFansResponse.exp success 563 | * 错误返回示例: \snippet example/checkPageFansResponse.exp fail 564 | */ 565 | - (void)checkPageFansResponse:(APIResponse*) response; 566 | 567 | /** 568 | * 分享到QZone回调 569 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 570 | * \remarks 正确返回示例: \snippet example/addShareResponse.exp success 571 | * 错误返回示例: \snippet example/addShareResponse.exp fail 572 | */ 573 | - (void)addShareResponse:(APIResponse*) response; 574 | 575 | /** 576 | * 在QZone相册中创建一个新的相册回调 577 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 578 | * \remarks 正确返回示例: \snippet example/addAlbumResponse.exp success 579 | * 错误返回示例: \snippet example/addAlbumResponse.exp fail 580 | */ 581 | - (void)addAlbumResponse:(APIResponse*) response; 582 | 583 | /** 584 | * 上传照片到QZone指定相册回调 585 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 586 | * \remarks 正确返回示例: \snippet example/uploadPicResponse.exp success 587 | * 错误返回示例: \snippet example/uploadPicResponse.exp fail 588 | */ 589 | - (void)uploadPicResponse:(APIResponse*) response; 590 | 591 | 592 | /** 593 | * 在QZone中发表一篇日志回调 594 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 595 | * \remarks 正确返回示例: \snippet example/addOneBlogResponse.exp success 596 | * 错误返回示例: \snippet example/addOneBlogResponse.exp fail 597 | */ 598 | - (void)addOneBlogResponse:(APIResponse*) response; 599 | 600 | /** 601 | * 在QZone中发表一条说说回调 602 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 603 | * \remarks 正确返回示例: \snippet example/addTopicResponse.exp success 604 | * 错误返回示例: \snippet example/addTopicResponse.exp fail 605 | */ 606 | - (void)addTopicResponse:(APIResponse*) response; 607 | 608 | /** 609 | * 设置QQ头像回调 610 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 611 | * \remarks 正确返回示例: \snippet example/setUserHeadpicResponse.exp success 612 | * 错误返回示例: \snippet example/setUserHeadpicResponse.exp fail 613 | */ 614 | - (void)setUserHeadpicResponse:(APIResponse*) response; 615 | 616 | /** 617 | * 获取QQ会员信息回调 618 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 619 | * \remarks 正确返回示例: \snippet example/getVipInfoResponse.exp success 620 | * 错误返回示例: \snippet example/getVipInfoResponse.exp fail 621 | */ 622 | - (void)getVipInfoResponse:(APIResponse*) response; 623 | 624 | /** 625 | * 获取QQ会员详细信息回调 626 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 627 | */ 628 | - (void)getVipRichInfoResponse:(APIResponse*) response; 629 | 630 | /** 631 | * sendStory分享的回调(已废弃,使用responseDidReceived:forMessage:) 632 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 633 | */ 634 | - (void)sendStoryResponse:(APIResponse*) response; 635 | 636 | 637 | /** 638 | * 社交API统一回调接口 639 | * \param response API返回结果,具体定义参见sdkdef.h文件中\ref APIResponse 640 | * \param message 响应的消息,目前支持‘SendStory’,‘AppInvitation’,‘AppChallenge’,‘AppGiftRequest’ 641 | */ 642 | - (void)responseDidReceived:(APIResponse*)response forMessage:(NSString *)message; 643 | 644 | /** 645 | * post请求的上传进度 646 | * \param tencentOAuth 返回回调的tencentOAuth对象 647 | * \param bytesWritten 本次回调上传的数据字节数 648 | * \param totalBytesWritten 总共已经上传的字节数 649 | * \param totalBytesExpectedToWrite 总共需要上传的字节数 650 | * \param userData 用户自定义数据 651 | */ 652 | - (void)tencentOAuth:(TencentOAuth *)tencentOAuth didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite userData:(id)userData; 653 | 654 | 655 | /** 656 | * 通知第三方界面需要被关闭 657 | * \param tencentOAuth 返回回调的tencentOAuth对象 658 | * \param viewController 需要关闭的viewController 659 | */ 660 | - (void)tencentOAuth:(TencentOAuth *)tencentOAuth doCloseViewController:(UIViewController *)viewController; 661 | 662 | @end 663 | 664 | #pragma mark - TencentWebViewDelegate(H5登录webview旋转方向回调) 665 | 666 | /** 667 | * \brief TencentWebViewDelegate: H5登录webview旋转方向回调协议 668 | * 669 | * 第三方应用可以根据自己APP的旋转方向限制,通过此协议设置 670 | */ 671 | @protocol TencentWebViewDelegate 672 | @optional 673 | - (BOOL) tencentWebViewShouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation; 674 | - (NSUInteger) tencentWebViewSupportedInterfaceOrientationsWithWebkit; 675 | - (BOOL) tencentWebViewShouldAutorotateWithWebkit; 676 | @end 677 | -------------------------------------------------------------------------------- /src/ios/TencentOpenAPI.framework/Headers/TencentOAuthObject.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// \file TencentOAuthObject.h 3 | /// 对开放接口的调用提供参数字典封装的辅助类 4 | /// 5 | /// Created by Tencent on 12-12-28. 6 | /// Copyright (c) 2012年 Tencent. All rights reserved. 7 | /// 8 | 9 | #import 10 | #import 11 | #import "sdkdef.h" 12 | 13 | 14 | #pragma mark - 15 | #pragma mark TCAddTopicDic 16 | 17 | /** 18 | * \brief 发表说说的参数字典定义 19 | * 20 | * 可以直接填写相应参数后将对象当作参数传入API中 21 | */ 22 | @interface TCAddTopicDic : TCAPIRequest 23 | 24 | /** 25 | * 返回一个对象用来进行API参数的填充 26 | * \note 不用释放,返回的对象是自动释放的 27 | */ 28 | + (TCAddTopicDic *) dictionary; 29 | 30 | /** 31 | * 发布心情时引用的信息的类型。 32 | * \note 1表示图片; 2表示网页; 3表示视频 33 | */ 34 | @property (nonatomic, retain) TCOptionalStr paramRichtype; 35 | 36 | /** 37 | * 发布心情时引用的信息的值。有richtype时必须有richval 38 | * 39 | * \note 40 | * -# 当richtype为图片(即richtype为1,应用场景为发布心情时引用某张图片)时,\n 41 | * richval需要传入该图片的相关参数。引用的图片来源分为两种:一种为网站图片,\n 42 | * 一种为QQ空间相册中的某张图片。 43 | * - 当引用的图片来自网站,richval包含下列参数的值:\n 44 | * | 参数名称 | 是否必须 | 类型 | 描述 | 45 | * | ------ | ------- | ------ | ----------------- | 46 | * | url | 必须 | string | 网站图片的URL | 47 | * | height | 必须 | string | 图片高度,单位: px | 48 | * | width | 必须 | string | 图片宽度,单位: px | 49 | * \n 50 | * 输入时每个值中间用“&”分隔,如下所示:\n 51 | * “url=http://qq.com/logo.png&width=25&height=21” 52 | * 53 | * - 当引用的图片来自QQ空间相册,richval包含下列参数的值。\n 54 | * 这些值都需要通过调用相册OpenAPI来获得。参数意义如下:\n 55 | * | 参数名称 | 是否必须 | 类型 | 描述 | 56 | * | --------- | ------ | ------ | ---------------------------------- | 57 | * | albumid | 必须 | string | 图片所属空间相册的ID | 58 | * | pictureid | 必须 | string | 图片ID | 59 | * | sloc | 必须 | string | 小图ID | 60 | * | pictype | | string | 图片类型(JPG = 1;GIF = 2;PNG = 3) | 61 | * | picheight | | string | 图片高度,单位: px | 62 | * | picwidth | | string | 图片宽度,单位: px | 63 | * 输入时每个值中间用逗号分隔,如下所示 :\n 64 | * “albumid,pictureid,sloc,pictype,picheight,picwidth” 65 | * -# 当richtype为网页(即richtype为2,应用场景为针对某网页发表评论)时,\n 66 | * richval需要传入该网页的URL,发表为feeds时,后台会自动将该URL转换为短URL。 67 | * -# 当richtype为视频(即richtype为3,应用场景为针对某视频发表评论)时,\n 68 | * richval需要传入该视频的URL,发表为feeds时,后台会对该URL进行解析,\n 69 | * 在feeds上显示播放器,视频源及缩略图。 70 | */ 71 | @property (nonatomic, retain) TCOptionalStr paramRichval; 72 | 73 | /** 74 | * 发布的心情的内容。 75 | */ 76 | @property (nonatomic, retain) TCRequiredStr paramCon; 77 | 78 | /** 79 | * 地址文。例如:广东省深圳市南山区高新科技园腾讯大厦。lbs_nm,lbs_x,lbs_y通常一起使用,来明确标识一个地址。 80 | */ 81 | @property (nonatomic, retain) TCOptionalStr paramLbs_nm; 82 | 83 | /** 84 | * 经度。-180.0到+180.0,+表示东经。lbs_nm,lbs_x,lbs_y通常一起使用,来明确标识一个地址。 85 | */ 86 | @property (nonatomic, retain) TCOptionalStr paramLbs_x; 87 | 88 | /** 89 | * 纬度。-90.0到+90.0,+表示北纬。lbs_nm,lbs_x,lbs_y通常一起使用,来明确标识一个地址。 90 | */ 91 | @property (nonatomic, retain) TCOptionalStr paramLbs_y; 92 | 93 | /** 94 | * 第三方应用的平台类型。 95 | * \note 1表示QQ空间; 2表示腾讯朋友; 3表示腾讯微博平台; 4表示腾讯Q+平台。 96 | */ 97 | @property (nonatomic, retain) TCOptionalStr paramThirdSource; 98 | @end 99 | 100 | 101 | #pragma mark - 102 | #pragma mark TCAddOneBlogDic 103 | /** 104 | * \brief 发表日志的参数字典定义 105 | * 106 | * 可以直接填写相应参数后将对象当作参数传入API中 107 | */ 108 | @interface TCAddOneBlogDic : TCAPIRequest 109 | 110 | /** 111 | * 返回一个对象用来进行API参数的填充 112 | * \note 不用释放,返回的对象是自动释放的 113 | */ 114 | + (TCAddOneBlogDic *) dictionary; 115 | 116 | /** 117 | * 日志标题(纯文本,最大长度128个字节,utf-8编码)。 118 | */ 119 | @property (nonatomic, retain) TCRequiredStr paramTitle; 120 | 121 | /** 122 | * content 文章内容(html数据,最大长度100*1024个字节,utf-8编码) 123 | */ 124 | @property (nonatomic, retain) TCRequiredStr paramContent; 125 | @end 126 | 127 | #pragma mark - 128 | #pragma mark TCAddAlbumDic 129 | /** 130 | * \brief 创建空间相册的参数字典定义 131 | * 132 | * 可以直接填写相应参数后将对象当作参数传入API中 133 | */ 134 | @interface TCAddAlbumDic : TCAPIRequest 135 | 136 | /** 137 | * 返回一个对象用来进行API参数的填充 138 | * 139 | * \note 不用释放,返回的对象是自动释放的 140 | */ 141 | + (TCAddAlbumDic *) dictionary; 142 | 143 | /** 144 | * albumname 必须 string 相册名 不能超过30个字符。 145 | */ 146 | @property (nonatomic, retain) TCRequiredStr paramAlbumname; 147 | 148 | 149 | /** 150 | * albumdesc string 相册描述,不能超过200个字符。 151 | */ 152 | @property (nonatomic, retain) TCOptionalStr paramAlbumdesc; 153 | 154 | /** 155 | * priv string 相册权限 156 | * 157 | * \note 其取值含义为: 1=公开;3=只主人可见; 4=QQ好友可见; 5=问答加密。\n 158 | * 不传则相册默认为公开权限。\n 159 | * 如果priv取值为5,即相册是问答加密的,则必须包含问题和答案两个参数:\n 160 | * - question: 问题,不能超过30个字符。 161 | * - answer: 答案,不能超过30个字符。 162 | */ 163 | @property (nonatomic, retain) TCOptionalStr paramPriv; 164 | 165 | /** 166 | * question 问题,不能超过30个字符。 167 | * \note 如果priv取值为5,必须包含这个参数: 168 | **/ 169 | @property (nonatomic, retain) TCOptionalStr paramQuestion; 170 | 171 | /** 172 | * answer 答案,不能超过30个字符。 173 | * \note 如果priv取值为5,必须包含这个参数: 174 | **/ 175 | @property (nonatomic, retain) TCOptionalStr paramAnswer; 176 | 177 | @end 178 | 179 | #pragma mark - 180 | #pragma mark TCUploadPicDic 181 | /** 182 | * \brief 上传一张照片到QQ空间相册的参数字典定义 183 | * 184 | * 可以直接填写相应参数后将对象当作参数传入API中 185 | */ 186 | @interface TCUploadPicDic : TCAPIRequest 187 | 188 | /** 189 | * 返回一个对象用来进行API参数的填充 190 | * \note 不用释放,返回的对象是自动释放的 191 | */ 192 | + (TCUploadPicDic *) dictionary; 193 | 194 | /** 195 | * photodesc string 照片描述,注意照片描述不能超过200个字符。 196 | */ 197 | @property (nonatomic, retain) TCOptionalStr paramPhotodesc; 198 | /** 199 | * string 照片的命名,必须以.jpg, .gif, .png, .jpeg, .bmp此类后缀结尾。 200 | */ 201 | @property (nonatomic, retain) TCOptionalStr paramTitle; 202 | 203 | /** 204 | * string 相册id。可不填,不填时则根据“mobile”标识选择默认上传的相册。 205 | */ 206 | @property (nonatomic, retain) TCOptionalStr paramAlbumid; 207 | 208 | /** 209 | * 标志位 210 | * 211 | * \note 0表示PC,1表示手机。用于当不传相册id时(即albumid为空时)控制是否传到手机相册。\n 212 | * -# 如果传1,则当albumid为空时,图片会上传到手机相册; 213 | * -# 如果不传或传0,则当albumid为空时,图片会上传到贴图相册; 214 | */ 215 | @property (nonatomic, assign) TCOptionalStr paramMobile; 216 | 217 | /** 218 | * x string 照片拍摄时的地理位置的经度。请使用原始数据(纯经纬度,0-360)。 219 | */ 220 | @property (nonatomic, retain) TCOptionalStr paramX; 221 | 222 | /** 223 | * y string 照片拍摄时的地理位置的纬度。请使用原始数据(纯经纬度,0-360)。 224 | */ 225 | @property (nonatomic, retain) TCOptionalStr paramY; 226 | 227 | /** 228 | * picture 必须 string 上传照片的文件名以及图片的内容(在发送请求时,图片内容以二进制数据流的形式发送,见下面的请求示例),注意照片名称不能超过30个字符。 229 | */ 230 | @property (nonatomic, retain) TCRequiredImage paramPicture; 231 | 232 | /** 233 | * needfeed int 标识上传照片时是否要发feed 234 | * \note(0:不发feed; 1:发feed)。如果不填则默认为发feed。 235 | */ 236 | @property (nonatomic, assign)TCOptionalStr paramNeedfeed; 237 | 238 | /** 239 | * successnum int 批量上传照片时,已成功上传的张数,指明上传完成情况。 240 | * \note 单张上传时可以不填,不填则默认为0。 241 | */ 242 | @property (nonatomic, assign)TCOptionalStr paramSuccessnum; 243 | 244 | /** 245 | * picnum int 批量上传照片的总张数,如果不填则默认为1。 246 | * \note 247 | * - 如果picnum=1,为单张上传,发送单张上传feed; 248 | * - 如果picnum>1,为批量上传,发送批量上传feed。 249 | * 批量上传方式:picnum为一次上传照片的张数,successnum初始值为0,每调用一次照片上传接口后递增其值。 250 | * 信息中心中的feed表现形式:批量上传时最新的7张在feed中展示。其中最新上传的一张图片展示为大图,剩下的 251 | * 六张按从新到旧的顺序展示为小图,其他图片不在feed中展示。 252 | */ 253 | @property (nonatomic, assign)TCOptionalStr paramPicnum; 254 | 255 | @end 256 | 257 | #pragma mark - 258 | #pragma mark TCAddShareDic 259 | /** 260 | * \brief 同步分享到QQ空间,腾讯微博的参数字典定义 261 | * 262 | * 可以直接填写相应参数后将对象当作参数传入API中 263 | */ 264 | @interface TCAddShareDic : TCAPIRequest 265 | 266 | /** 267 | * 返回一个对象用来进行API参数的填充 268 | * 269 | * \note 不用释放,返回的对象是自动释放的 270 | */ 271 | + (TCAddShareDic *) dictionary; 272 | 273 | /** 274 | * title 必须 string feeds的标题 最长36个中文字,超出部分会被截断。 275 | */ 276 | @property (nonatomic, retain) TCRequiredStr paramTitle; 277 | 278 | 279 | /** 280 | * url 必须 string 分享所在网页资源的链接,点击后跳转至第三方网页,对应上文接口说明中2的超链接。请以http://开头。 281 | */ 282 | @property (nonatomic, retain) TCRequiredStr paramUrl; 283 | 284 | 285 | /** 286 | * comment string 用户评论内容,也叫发表分享时的分享理由 禁止使用系统生产的语句进行代替。 287 | * 最长40个中文字,超出部分会被截断。 288 | */ 289 | @property (nonatomic, retain) TCOptionalStr paramComment; 290 | 291 | 292 | /** 293 | * summary string 所分享的网页资源的摘要内容,或者是网页的概要描述 最长80个中文字,超出部分会被截断。 294 | */ 295 | @property (nonatomic, retain) TCOptionalStr paramSummary; 296 | 297 | /** 298 | * images string 所分享的网页资源的代表性图片链接",请以http://开头,长度限制255字符。多张图片以竖线(|)分隔,目前只有第一张图片有效,图片规格100*100为佳。 299 | */ 300 | @property (nonatomic, retain) TCOptionalStr paramImages; 301 | 302 | /** 303 | * type string 分享内容的类型。 304 | * 305 | * \note 4表示网页;5表示视频(type=5时,必须传入playurl) 306 | */ 307 | @property (nonatomic, retain) TCOptionalStr paramType; 308 | 309 | /** 310 | * playurl string 长度限制为256字节。仅在type=5的时候有效,表示视频的swf播放地址。 311 | */ 312 | @property (nonatomic, retain) TCOptionalStr paramPlayurl; 313 | 314 | /** 315 | * site 必须 string 分享的来源网站名称,请填写网站申请接入时注册的网站名称 316 | */ 317 | @property (nonatomic, retain) TCRequiredStr paramSite; 318 | 319 | /** 320 | * fromurl 必须 string 分享的来源网站对应的网站地址url 请以http://开头。 321 | */ 322 | @property (nonatomic, retain) TCRequiredStr paramFromurl; 323 | 324 | /** 325 | * nswb string 值为1时,表示分享不默认同步到微博,其他值或者不传此参数表示默认同步到微博。 326 | */ 327 | @property (nonatomic, retain) TCOptionalStr paramNswb; 328 | 329 | @end 330 | 331 | #pragma mark - 332 | #pragma mark TCCheckPageFansDic 333 | /** 334 | * \brief 验证是否认证空间粉丝tttyttyyyu的参数字典定义 335 | * 336 | * 可以直接填写相应参数后将对象当作参数传入API中 337 | */ 338 | @interface TCCheckPageFansDic : TCAPIRequest 339 | 340 | /** 341 | * 返回一个对象用来进行API参数的填充 342 | * 343 | * \note 不用释放,返回的对象是自动释放的 344 | */ 345 | + (TCCheckPageFansDic *) dictionary; 346 | 347 | /** 348 | * 表示认证空间的QQ号码 349 | */ 350 | @property (nonatomic, retain) TCRequiredStr paramPage_id; 351 | @end 352 | 353 | #pragma mark - 354 | #pragma mark TCSetUserHeadpic 355 | /** 356 | * \brief 设置用户头像 357 | * 358 | * 可以直接填写相应参数后将对象当作参数传入API中 359 | */ 360 | @interface TCSetUserHeadpic : TCAPIRequest 361 | 362 | /** 363 | * 返回一个对象用来进行API参数的填充 364 | * \note 不用释放,返回的对象是自动释放的 365 | */ 366 | + (TCSetUserHeadpic *) dictionary; 367 | 368 | /** 369 | * 设置用户头像的图片 370 | */ 371 | @property (nonatomic, retain) TCRequiredImage paramImage; 372 | 373 | /** 374 | * 图片的文件名 375 | */ 376 | @property (nonatomic, retain) TCOptionalStr paramFileName; 377 | @end 378 | 379 | #pragma mark - 380 | #pragma mark TCListPhotoDic 381 | 382 | /** 383 | * \brief 获取用户QQ空间相册中的照片列表 384 | * 385 | * 可以直接填写相应参数后将对象当作参数传入API中 386 | */ 387 | @interface TCListPhotoDic : TCAPIRequest 388 | 389 | /** 390 | * 返回一个对象用来进行API参数的填充 391 | * 392 | * \note 不用释放,返回的对象是自动释放的 393 | */ 394 | + (TCListPhotoDic *) dictionary; 395 | 396 | /** 397 | * 表示要获取的照片列表所在的相册ID 398 | */ 399 | @property (nonatomic, retain) TCRequiredStr paramAlbumid; 400 | 401 | @end 402 | 403 | #pragma mark - 404 | #pragma mark TCSendStoryDic 405 | /** 406 | * \brief QQ空间定向分享的参数字典定义 407 | * 408 | * 该分享支持@到指定好友,最多支持10个好友。 409 | * 其中第三方应用可预传最多5个指定好友的openid,其余好友由用户自行选择。 410 | * 该分享形式仅提供跳QZone分享和本地Html5分享两种形式。 411 | * sendStroy不支持userData参数 412 | */ 413 | @interface TCSendStoryDic : TCAPIRequest 414 | 415 | /** 416 | * 返回一个对象用来进行API参数的填充 417 | * 418 | * \note 不用释放,返回的对象是自动释放的 419 | */ 420 | + (TCSendStoryDic *) dictionary; 421 | 422 | /** 423 | * 分享的标题 424 | */ 425 | @property (nonatomic, retain) TCRequiredStr paramTitle; 426 | 427 | /** 428 | * 故事摘要,最多不超过50个汉字,可以为空 429 | */ 430 | @property (nonatomic, retain) TCOptionalStr paramSummary; 431 | 432 | /** 433 | * 默认展示在输入框里的分享理由,最多120个汉字,可以为空 434 | */ 435 | @property (nonatomic, retain) TCOptionalStr paramDescription; 436 | 437 | /** 438 | * 图片url 439 | */ 440 | @property (nonatomic, retain) TCOptionalStr paramPics; 441 | 442 | /** 443 | * 如果不填,则默认为"进入应用" 444 | */ 445 | @property (nonatomic, retain) TCRequiredStr paramAct; 446 | 447 | /** 448 | * 点击分享的Url 449 | */ 450 | @property (nonatomic, retain) TCOptionalStr paramShareUrl; 451 | 452 | @end 453 | -------------------------------------------------------------------------------- /src/ios/TencentOpenAPI.framework/Headers/sdkdef.h: -------------------------------------------------------------------------------- 1 | /// 2 | /// \file sdkdef.h 3 | /// \brief SDK中相关常量定义 4 | /// 5 | /// Created by Tencent on 12-12-25. 6 | /// Copyright (c) 2012年 Tencent. All rights reserved. 7 | /// 8 | 9 | #import 10 | #import 11 | 12 | /** 13 | * \brief 设置sdk的log等级 14 | */ 15 | typedef enum { 16 | TCOLogLevel_Disabled = -1, // 关闭所有log 17 | TCOLogLevel_Error = 0, 18 | TCOLogLevel_Warning, 19 | TCOLogLevel_Info, 20 | TCOLogLevel_Debug, 21 | } TCOLogLevel; 22 | 23 | /** 24 | * \brief 手机qq的当前版本 25 | */ 26 | typedef enum QQVersion 27 | { 28 | kQQUninstall, 29 | kQQVersion3_0, 30 | kQQVersion4_0, //支持sso登陆 31 | kQQVersion4_2_1, //ios7兼容 32 | kQQVersion4_5, //4.5版本,wpa会话 33 | kQQVersion4_6, //4.6版本,sso登陆信令通道切换 34 | kQQVersion4_7, //4.7版本 不确定新支持了什么样的属性 35 | } QQVersion; 36 | 37 | 38 | /** 39 | * \breif TIM的当前版本 40 | */ 41 | typedef enum TIMVersion { 42 | kTIMUinstall, 43 | kTIMVersion1_1, 44 | }TIMVersion; 45 | 46 | /** 47 | * \breif 授权/分享 方式 48 | */ 49 | typedef enum TencentAuthShareType { 50 | AuthShareType_QQ, 51 | AuthShareType_TIM, 52 | }TencentAuthShareType; 53 | 54 | /** 55 | * \brief APIResponse.retCode可能的枚举常量 56 | */ 57 | typedef enum 58 | { 59 | URLREQUEST_SUCCEED = 0, /**< 网络请求成功发送至服务器,并且服务器返回数据格式正确 60 | * \note 这里包括所请求业务操作失败的情况,例如没有授权等原因导致 61 | */ 62 | 63 | URLREQUEST_FAILED = 1, /**< 网络异常,或服务器返回的数据格式不正确导致无法解析 */ 64 | } REPONSE_RESULT; 65 | 66 | /** 67 | * \brief 增量授权失败原因 68 | * 69 | * \note 增量授权失败不影响原token的有效性(原token已失效的情况除外) 70 | */ 71 | typedef enum 72 | { 73 | kUpdateFailUnknown = 1, ///< 未知原因 74 | kUpdateFailUserCancel, ///< 用户取消 75 | kUpdateFailNetwork, ///< 网络问题 76 | } UpdateFailType; 77 | 78 | /** 79 | * \brief 封装服务器返回的结果 80 | * 81 | * APIResponse用于封装所有请求的返回结果,包括错误码、错误信息、原始返回数据以及返回数据的json格式字典 82 | */ 83 | @interface APIResponse : NSObject { 84 | int _detailRetCode; 85 | int _retCode; 86 | int _seq; 87 | NSString *_errorMsg; 88 | NSDictionary *_jsonResponse; 89 | NSString *_message; 90 | id _userData; 91 | } 92 | 93 | /** 94 | * 新增的详细错误码\n 95 | * detailRetCode主要用于区分不同的错误情况,参见\ref OpenSDKError 96 | */ 97 | @property (nonatomic, assign) int detailRetCode; 98 | 99 | /** 100 | * 网络请求是否成功送达服务器,以及服务器返回的数据格式是否正确\n 101 | * retCode具体取值可参考\ref REPONSE_RESULT 102 | */ 103 | @property (nonatomic, assign) int retCode; 104 | 105 | /** 106 | * 网络请求对应的递增序列号,方便内部管理 107 | */ 108 | @property (nonatomic, assign) int seq; 109 | 110 | /** 111 | * 错误提示语 112 | */ 113 | @property (nonatomic, retain) NSString *errorMsg; 114 | 115 | /** 116 | * 服务器返回数据的json格式字典\n 117 | * 字典内具体参数的命名和含义请参考\ref api_spec 118 | */ 119 | @property (nonatomic, retain) NSDictionary *jsonResponse; 120 | 121 | /** 122 | * 服务器返回的原始数据字符串 123 | */ 124 | @property (nonatomic, retain) NSString *message; 125 | 126 | /** 127 | * 用户保留数据 128 | */ 129 | @property (nonatomic, retain) id userData; 130 | 131 | @end 132 | 133 | 134 | /** 135 | * 用户自定义的保留字段 136 | */ 137 | FOUNDATION_EXTERN NSString * const PARAM_USER_DATA; 138 | 139 | /** 140 | * \name 应用邀请参数字段定义 141 | */ 142 | ///@{ 143 | 144 | /** 应用邀请展示图片url的key */ 145 | FOUNDATION_EXTERN NSString * const PARAM_APP_ICON; 146 | 147 | /** 应用邀请描述文本的key */ 148 | FOUNDATION_EXTERN NSString * const PARAM_APP_DESC; 149 | 150 | /** 应用邀请好友列表的key */ 151 | FOUNDATION_EXTERN NSString * const PARAM_APP_INVITED_OPENIDS; 152 | 153 | ///@} 154 | 155 | /** 156 | * \name sendStory新分享参数字段定义 157 | */ 158 | ///@{ 159 | 160 | /** 预填入接受人列表的key */ 161 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_RECEIVER; 162 | 163 | /** 分享feeds标题的key */ 164 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_TITLE; 165 | 166 | /** 分享feeds评论内容的key */ 167 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_COMMENT; 168 | 169 | /** 分享feeds摘要的key */ 170 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_SUMMARY; 171 | 172 | /** 分享feeds展示图片url的key */ 173 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_IMAGE; 174 | 175 | /** 分享feeds跳转链接url的key */ 176 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_URL; 177 | 178 | /** 分享feeds点击操作默认行为的key */ 179 | FOUNDATION_EXTERN NSString * const PARAM_SENDSTORY_ACT; 180 | 181 | ///@} 182 | 183 | /** 184 | * \name 设置头像参数字段定义 185 | */ 186 | ///@{ 187 | 188 | /** 头像图片数据的key */ 189 | FOUNDATION_EXTERN NSString * const PARAM_SETUSERHEAD_PIC; 190 | 191 | /** 头像图片文件名的key */ 192 | FOUNDATION_EXTERN NSString * const PARAM_SETUSERHEAD_FILENAME; 193 | 194 | ///@} 195 | 196 | /** 197 | * \name 服务器返回数据的参数字段定义 198 | */ 199 | ///@{ 200 | 201 | /** 服务器返回码的key */ 202 | FOUNDATION_EXTERN NSString * const PARAM_RETCODE; 203 | 204 | /** 服务器返回错误信息的key */ 205 | FOUNDATION_EXTERN NSString * const PARAM_MESSAGE; 206 | 207 | /** 服务器返回额外数据的key */ 208 | FOUNDATION_EXTERN NSString * const PARAM_DATA; 209 | 210 | ///@} 211 | 212 | /** 213 | * \name 错误信息相关常量定义 214 | */ 215 | ///@{ 216 | 217 | /** 详细错误信息字典中额外信息的key */ 218 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyExtraInfo; 219 | 220 | /** 详细错误信息字典中返回码的key */ 221 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyRetCode; 222 | 223 | /** 详细错误信息字典中错误语句的key */ 224 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorKeyMsg; 225 | 226 | /** 不支持的接口 */ 227 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUnsupportedAPI; 228 | 229 | /** 操作成功 */ 230 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgSuccess; 231 | 232 | /** 未知错误 */ 233 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUnknown; 234 | 235 | /** 用户取消 */ 236 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUserCancel; 237 | 238 | /** 请重新登录 */ 239 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgReLogin; 240 | 241 | /** 应用没有操作权限 */ 242 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgOperationDeny; 243 | 244 | /** 网络异常或没有网络 */ 245 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgNetwork; 246 | 247 | /** URL格式或协议错误 */ 248 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgURL; 249 | 250 | /** 解析数据出错 */ 251 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgDataParse; 252 | 253 | /** 传入参数有误 */ 254 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgParam; 255 | 256 | /** 连接超时 */ 257 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgTimeout; 258 | 259 | /** 安全问题 */ 260 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgSecurity; 261 | 262 | /** 文件读写错误 */ 263 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgIO; 264 | 265 | /** 服务器端错误 */ 266 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgServer; 267 | 268 | /** 页面错误 */ 269 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgWebPage; 270 | 271 | /** 设置头像图片过大 */ 272 | FOUNDATION_EXTERN NSString * const TCOpenSDKErrorMsgUserHeadPicLarge; 273 | 274 | ///@} 275 | 276 | /** 277 | * \brief SDK新增详细错误常量 278 | */ 279 | typedef enum 280 | { 281 | kOpenSDKInvalid = -1, ///< 无效的错误码 282 | kOpenSDKErrorUnsupportedAPI = -2, ///< 不支持的接口 283 | 284 | /** 285 | * \name CommonErrorCode 286 | * 公共错误码 287 | */ 288 | ///@{ 289 | kOpenSDKErrorSuccess = 0, ///< 成功 290 | kOpenSDKErrorUnknown, ///< 未知错误 291 | kOpenSDKErrorUserCancel, ///< 用户取消 292 | kOpenSDKErrorReLogin, ///< token无效或用户未授权相应权限需要重新登录 293 | kOpenSDKErrorOperationDeny, ///< 第三方应用没有该api操作的权限 294 | ///@} 295 | 296 | /** 297 | * \name NetworkRelatedErrorCode 298 | * 网络相关错误码 299 | */ 300 | ///@{ 301 | kOpenSDKErrorNetwork, ///< 网络错误,网络不通或连接不到服务器 302 | kOpenSDKErrorURL, ///< URL格式或协议错误 303 | kOpenSDKErrorDataParse, ///< 数据解析错误,服务器返回的数据解析出错 304 | kOpenSDKErrorParam, ///< 传入参数错误 305 | kOpenSDKErrorConnTimeout, ///< http连接超时 306 | kOpenSDKErrorSecurity, ///< 安全问题 307 | kOpenSDKErrorIO, ///< 下载和文件IO错误 308 | kOpenSDKErrorServer, ///< 服务器端错误 309 | ///@} 310 | 311 | /** 312 | * \name WebViewRelatedError 313 | * webview特有错误 314 | */ 315 | ///@{ 316 | kOpenSDKErrorWebPage, ///< 页面错误 317 | ///@} 318 | 319 | /** 320 | * \name SetUserHeadRelatedErrorCode 321 | * 设置头像自定义错误码段 322 | */ 323 | ///@{ 324 | kOpenSDKErrorUserHeadPicLarge = 0x010000, ///< 图片过大 设置头像自定义错误码 325 | ///@} 326 | } OpenSDKError; 327 | 328 | /** 329 | * \name SDK版本(v1.3)支持的授权列表常量 330 | */ 331 | ///@{ 332 | 333 | /** 发表一条说说到QQ空间(需要申请权限) */ 334 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_TOPIC; 335 | 336 | /** 发表一篇日志到QQ空间(需要申请权限) */ 337 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_ONE_BLOG; 338 | 339 | /** 创建一个QQ空间相册(需要申请权限) */ 340 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_ALBUM; 341 | 342 | /** 上传一张照片到QQ空间相册(需要申请权限) */ 343 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_UPLOAD_PIC; 344 | 345 | /** 获取用户QQ空间相册列表(需要申请权限) */ 346 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_LIST_ALBUM; 347 | 348 | /** 同步分享到QQ空间、腾讯微博 */ 349 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_ADD_SHARE; 350 | 351 | /** 验证是否认证空间粉丝 */ 352 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_CHECK_PAGE_FANS; 353 | 354 | /** 获取登录用户自己的详细信息 */ 355 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_INFO; 356 | 357 | /** 获取其他用户的详细信息 */ 358 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_OTHER_INFO; 359 | 360 | /** 获取会员用户基本信息 */ 361 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_VIP_INFO; 362 | 363 | /** 获取会员用户详细信息 */ 364 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_VIP_RICH_INFO; 365 | 366 | /** 获取用户信息 */ 367 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_USER_INFO; 368 | 369 | /** 移动端获取用户信息 */ 370 | FOUNDATION_EXTERN NSString *const kOPEN_PERMISSION_GET_SIMPLE_USER_INFO; 371 | ///@} 372 | 373 | 374 | /** 375 | * \name CGI接口相关参数类型定义 376 | */ 377 | ///@{ 378 | 379 | /** 必填的字符串类型参数 */ 380 | typedef NSString *TCRequiredStr; 381 | 382 | /** 必填的UIImage类型参数 */ 383 | typedef UIImage *TCRequiredImage; 384 | 385 | /** 必填的整型参数 */ 386 | typedef NSInteger TCRequiredInt; 387 | 388 | /** 必填的数字类型 */ 389 | typedef NSNumber *TCRequiredNumber; 390 | 391 | /** 必填的NSData参数 */ 392 | typedef NSData *TCRequiredData; 393 | 394 | /** 可选的字符串类型参数 */ 395 | typedef NSString *TCOptionalStr; 396 | 397 | /** 可选的UIImage类型参数 */ 398 | typedef UIImage *TCOptionalImage; 399 | 400 | /** 可选的整型参数 */ 401 | typedef NSInteger TCOptionalInt; 402 | 403 | /** 可选的数字类型 */ 404 | typedef NSNumber *TCOptionalNumber; 405 | 406 | /** 可选的不定类型参数 */ 407 | typedef id TCRequiredId; 408 | ///@} 409 | 410 | 411 | /** 412 | * \brief CGI请求的参数字典封装辅助基类 413 | * 414 | * 将相应属性的值以key-value的形式保存到参数字典中 415 | */ 416 | @interface TCAPIRequest : NSMutableDictionary 417 | 418 | /** CGI请求的URL地址 */ 419 | @property (nonatomic, readonly) NSURL *apiURL; 420 | 421 | /** CGI请求方式:"GET","POST" */ 422 | @property (nonatomic, readonly) NSString *method; 423 | 424 | /** 425 | * API参数中的保留字段,可以塞入任意字典支持的类型,再调用完成后会带回给调用方 426 | */ 427 | @property (nonatomic, retain) TCRequiredId paramUserData; 428 | 429 | /** 430 | * APIResponse,API的返回结果 431 | */ 432 | @property (nonatomic, readonly) APIResponse *response; 433 | 434 | /** 取消相应的CGI请求任务 */ 435 | - (void)cancel; 436 | 437 | @end 438 | 439 | @protocol TCAPIRequestDelegate 440 | @optional 441 | - (void)cgiRequest:(TCAPIRequest *)request didResponse:(APIResponse *)response; 442 | 443 | @end 444 | 445 | -------------------------------------------------------------------------------- /src/ios/TencentOpenAPI.framework/Resources/ios_open_sdk_3.2.3.501_iphone_release: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iVanPan/Cordova_QQ/8c799b5a1c055d39321db390d6f53e4e4bfe239c/src/ios/TencentOpenAPI.framework/Resources/ios_open_sdk_3.2.3.501_iphone_release -------------------------------------------------------------------------------- /src/ios/TencentOpenAPI.framework/TencentOpenAPI: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iVanPan/Cordova_QQ/8c799b5a1c055d39321db390d6f53e4e4bfe239c/src/ios/TencentOpenAPI.framework/TencentOpenAPI -------------------------------------------------------------------------------- /src/ios/TencentOpenApi_IOS_Bundle.bundle/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iVanPan/Cordova_QQ/8c799b5a1c055d39321db390d6f53e4e4bfe239c/src/ios/TencentOpenApi_IOS_Bundle.bundle/Info.plist -------------------------------------------------------------------------------- /src/ios/TencentOpenApi_IOS_Bundle.bundle/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iVanPan/Cordova_QQ/8c799b5a1c055d39321db390d6f53e4e4bfe239c/src/ios/TencentOpenApi_IOS_Bundle.bundle/error.png -------------------------------------------------------------------------------- /src/ios/TencentOpenApi_IOS_Bundle.bundle/local.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 社交渠道 7 | 8 | 9 | 10 | 17 | 18 | 19 |
20 |
21 |

22 | 返回 23 | 24 |
25 |
26 |
27 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/ios/TencentOpenApi_IOS_Bundle.bundle/qqicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iVanPan/Cordova_QQ/8c799b5a1c055d39321db390d6f53e4e4bfe239c/src/ios/TencentOpenApi_IOS_Bundle.bundle/qqicon.png -------------------------------------------------------------------------------- /src/ios/TencentOpenApi_IOS_Bundle.bundle/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iVanPan/Cordova_QQ/8c799b5a1c055d39321db390d6f53e4e4bfe239c/src/ios/TencentOpenApi_IOS_Bundle.bundle/success.png -------------------------------------------------------------------------------- /www/qq.js: -------------------------------------------------------------------------------- 1 | 2 | var cordova = require('cordova'); 3 | module.exports = { 4 | Scene: { 5 | QQ: 0, // QQ 好友 6 | QQZone: 1, // QQ 空间 7 | Favorite: 2 // 收藏 8 | }, 9 | ClientType: { 10 | QQ: 0, // QQ 手机客户端 11 | TIM: 1 // TIM 客户端 12 | }, 13 | ssoLogin:function(successCallback, errorCallback, args){ 14 | if(args === undefined) { 15 | args = {} 16 | } 17 | cordova.exec(successCallback, errorCallback, "QQSDK", "ssoLogin",[args]); 18 | }, 19 | logout:function(successCallback, errorCallback){ 20 | cordova.exec(successCallback, errorCallback, "QQSDK", "logout", []); 21 | }, 22 | checkClientInstalled:function(successCallback, errorCallback, args){ 23 | if(args === undefined) { 24 | args = {} 25 | } 26 | cordova.exec(successCallback, errorCallback, "QQSDK", "checkClientInstalled", [args]); 27 | }, 28 | shareText:function(successCallback, errorCallback, args){ 29 | cordova.exec(successCallback, errorCallback, "QQSDK", "shareText", [args]); 30 | }, 31 | shareImage:function(successCallback, errorCallback, args){ 32 | cordova.exec(successCallback, errorCallback, "QQSDK", "shareImage", [args]); 33 | }, 34 | shareNews:function(successCallback, errorCallback, args){ 35 | cordova.exec(successCallback, errorCallback, "QQSDK", "shareNews", [args]); 36 | }, 37 | shareAudio:function(successCallback, errorCallback, args){ 38 | cordova.exec(successCallback, errorCallback, "QQSDK", "shareAudio", [args]); 39 | }, 40 | }; 41 | --------------------------------------------------------------------------------