diff --git a/README.md b/README.md
index d15bfe3..eeda1ed 100644
--- a/README.md
+++ b/README.md
@@ -14,9 +14,9 @@ flutter版腾讯(QQ)SDK
* [Flutter版深度链接](https://github.com/RxReader/link_kit)
* [Flutter版walle渠道打包工具](https://github.com/RxReader/walle_kit)
-## dart/flutter 私服
+## Dart/Flutter Pub 私服
-* [simple_pub_server](https://github.com/rxreader/simple_pub_server)
+* [simple_pub_server](https://github.com/RxReader/simple_pub_server)
## 相关文档
@@ -25,13 +25,9 @@ flutter版腾讯(QQ)SDK
* [QQ 创建、填写及校验UniversalLinks](https://wiki.connect.qq.com/%E5%A1%AB%E5%86%99%E5%8F%8A%E6%A0%A1%E9%AA%8Cuniversallinks)
* [Apple Universal Links](https://developer.apple.com/library/archive/documentation/General/Conceptual/AppSearch/UniversalLinks.html)
-## FEATURE
-
-* 5.x.y 通过配置 pubspec.yaml 和 cli 抹平 Android/iOS 平台的复杂配置
-
## 开始使用
-### android
+### Android
* 接入
@@ -49,93 +45,52 @@ android {
# 混淆已打入 Library,随 Library 引用,自动添加到 apk 打包混淆
```
-### ios
-
-* 申明
+### iOS
```
-出于插件的基本需求,将 SDK 的 module.modulemap 内容修改
+# 不需要做任何额外接入工作
+# 配置已集成到脚本里
+```
-改前
-module TencentOpenApi{
- umbrella header "TencentOpenApiUmbrellaHeader.h"
- export *
-}
+* Universal Links
-改后
-framework module TencentOpenApi{
- umbrella header "TencentOpenApiUmbrellaHeader.h"
- export *
+apple-app-site-association - 通过 https://${your applinks domain}/.well-known/apple-app-site-association 链接可访问
+
+示例:
+
+https://${your applinks domain}/universal_link/${example_app}/qq_conn/${appId}
+
+```json
+{
+ "applinks": {
+ "apps": [],
+ "details": [
+ {
+ "appID": "${your team id}.${your app bundle id}",
+ "paths": [
+ "/universal_link/${example_app}/qq_conn/${your tencent app id}/*"
+ ]
+ }
+ ]
+ }
}
```
-* 接入
+> ⚠️ 很多 SDK 都会用到 universal_link,可为不同 SDK 分配不同的 path 以作区分
-```
-在Xcode中,选择你的工程设置项,选中“TARGETS”一栏,在“info”标签栏的“URL type“添加“URL scheme”为你所注册的应用程序id
-
-URL Types
-tencent: identifier=tencent schemes=tencent${appId}
-```
-
-```
-iOS 9系统策略更新,限制了http协议的访问,此外应用需要在“Info.plist”中将要使用的URL Schemes列为白名单,才可正常检查其他应用是否安装。
-
- LSApplicationQueriesSchemes
-
- tim
- mqq
- mqqapi
- mqqbrowser
- mttbrowser
- mqqOpensdkSSoLogin
- mqqopensdkapiV2
- mqqopensdkapiV4
- mqzone
- mqzoneopensdk
- mqzoneopensdkapi
- mqzoneopensdkapi19
- mqzoneopensdkapiV2
- mqqapiwallet
- mqqopensdkfriend
- mqqopensdkavatar
- mqqopensdkminiapp
- mqqopensdkdataline
- mqqgamebindinggroup
- mqqopensdkgrouptribeshare
- tencentapi.qq.reqContent
- tencentapi.qzone.reqContent
- mqqthirdappgroup
- mqqopensdklaunchminiapp
- mqqopensdkproxylogin
- mqqopensdknopasteboard
- mqqopensdkcheckauth
-
-```
-
-```
-Universal Links
-
-Capabilities -> Associated Domain -> Domain -> applinks:${your applinks}
-```
-
-### flutter
+### Flutter
|分享类型|说说(图/文/视频)|文本|图片|音乐|视频|网页|
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|QQ|不支持|不支持|支持|支持|不支持|支持|
|QZone|支持|不支持|不支持|不支持|不支持|支持|
-* ⚠️⚠️⚠️ registerApp 前必须先调用 setIsPermissionGranted [issues/60](https://github.com/RxReader/tencent_kit/issues/60) [issues/79](https://github.com/RxReader/tencent_kit/issues/79)
+* 注意
-* break change
- * 4.0.0: 按标准插件书写重构
- * 3.1.0: 新增 setIsPermissionGranted 函数,设置是否已授权获取设备信息/是否同意隐私协议
- * 3.0.0: 重构
- * 2.1.0: nullsafety & 不再支持 Android embedding v1 & Tencent 单例
+⚠️⚠️⚠️ registerApp 前必须先调用 setIsPermissionGranted [issues/60](https://github.com/RxReader/tencent_kit/issues/60) [issues/79](https://github.com/RxReader/tencent_kit/issues/79)
-* compat
- * flutter 2.5 兼容问题 [issues/54](https://github.com/RxReader/tencent_kit/issues/54)
+* 兼容
+ flutter 2.5 兼容问题 [issues/54](https://github.com/RxReader/tencent_kit/issues/54)
```
post_install do |installer|
installer.pods_project.targets.each do |target|
@@ -149,23 +104,21 @@ Capabilities -> Associated Domain -> Domain -> applinks:${your applinks}
end
```
-* snapshot
+* 配置
-```
-dependencies:
- tencent_kit:
- git:
- url: https://github.com/rxreader/tencent_kit.git
-```
-
-* release
-
-```
+```yaml
dependencies:
tencent_kit: ^${latestTag}
+# tencent_kit:
+# git:
+# url: https://github.com/rxreader/tencent_kit.git
+
+tencent_kit:
+ app_id: ${your tencent app id}
+ universal_link: https://${your applinks domain}/universal_link/${example_app}/qq_conn/${your tencent app id}/
```
-* example
+## 示例
[示例](./example/lib/main.dart)
diff --git a/example/lib/main.dart b/example/lib/main.dart
index e72a8f5..7b80312 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -9,7 +9,8 @@ import 'package:tencent_kit_example/api/model/tencent_api_resp.dart';
import 'package:tencent_kit_example/api/model/tencent_unionid_resp.dart';
import 'package:tencent_kit_example/api/tencent_api.dart';
-const String _TENCENT_APPID = 'your tencent appId';
+const String _TENCENT_APPID = 'your tencent app id';
+const String _UNIVERSAL_LINK = 'your tencent universal link';
void main() {
runApp(MyApp());
@@ -85,7 +86,7 @@ class _HomeState extends State {
ListTile(
title: Text('注册APP'),
onTap: () async {
- await TencentKitPlatform.instance.registerApp(appId: _TENCENT_APPID);
+ await TencentKitPlatform.instance.registerApp(appId: _TENCENT_APPID, universalLink: _UNIVERSAL_LINK);
_showTips('注册APP', '注册成功');
},
),
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index fcefbd7..9cee770 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -91,3 +91,7 @@ flutter:
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
+
+tencent_kit:
+ app_id: 123456789
+ universal_link: https://www.yourdomain.com/universal_link/example_app/qq_conn/123456789/
diff --git a/ios/tencent_kit.podspec b/ios/tencent_kit.podspec
index 6d12825..971b4ca 100644
--- a/ios/tencent_kit.podspec
+++ b/ios/tencent_kit.podspec
@@ -6,14 +6,23 @@
pubspec = YAML.load_file(File.join('..', 'pubspec.yaml'))
library_version = pubspec['version'].gsub('+', '-')
+current_dir = Dir.pwd
+calling_dir = File.dirname(__FILE__)
+project_dir = calling_dir.slice(0..(calling_dir.index('/.symlinks')))
+root_project_dir = calling_dir.slice(0..(calling_dir.index('/ios/.symlinks')))
+cfg = YAML.load_file(File.join(root_project_dir, 'pubspec.yaml'))
+if cfg['tencent_kit'] && (cfg['tencent_kit']['app_id'] && cfg['tencent_kit']['universal_link'])
+ app_id = cfg['tencent_kit']['app_id']
+ universal_link = cfg['tencent_kit']['universal_link']
+ system("ruby #{current_dir}/tencent_setup.rb -a #{app_id} -u #{universal_link} -p #{project_dir} -n Runner.xcodeproj")
+end
+
Pod::Spec.new do |s|
s.name = 'tencent_kit'
s.version = library_version
- s.summary = 'A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Tencent SDKs.'
- s.description = <<-DESC
-A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Tencent SDKs.
- DESC
- s.homepage = 'http://example.com'
+ s.summary = pubspec['description']
+ s.description = pubspec['description']
+ s.homepage = pubspec['homepage']
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
diff --git a/ios/tencent_setup.rb b/ios/tencent_setup.rb
new file mode 100644
index 0000000..20a4a5e
--- /dev/null
+++ b/ios/tencent_setup.rb
@@ -0,0 +1,156 @@
+#
+# 参考文献
+# https://github.com/firebase/flutterfire/blob/master/packages/firebase_crashlytics/firebase_crashlytics/ios/crashlytics_add_upload_symbols
+# https://github.com/MagicalWater/Base-APP-Env/blob/master/fastlane/actions/xcode_parse.rb
+#
+
+require 'xcodeproj'
+require 'plist'
+require 'optparse'
+
+# Dictionary to hold command line arguments
+options_dict = {}
+
+# Parse command line arguments into options_dict
+OptionParser.new do |options|
+ options.banner = "Setup the QQ to an Xcode target."
+
+ options.on("-p", "--projectDirectory=DIRECTORY", String, "Directory of the Xcode project") do |dir|
+ options_dict[:project_dir] = dir
+ end
+
+ options.on("-n", "--projectName=NAME", String, "Name of the Xcode project (ex: Runner.xcodeproj)") do |name|
+ options_dict[:project_name] = name
+ end
+
+ options.on("-a", "--appId=APPID", String, "App ID for QQ") do |opts|
+ options_dict[:app_id] = opts
+ end
+
+ options.on("-u", "--universalLink=UNIVERSALLINK", String, "Universal Link for QQ") do |opts|
+ options_dict[:universal_link] = opts
+ end
+end.parse!
+
+# Minimum required arguments are a project directory and project name
+unless (options_dict[:project_dir] and options_dict[:project_name])
+ abort("Must provide a project directory and project name.\n")
+end
+
+# Path to the Xcode project to modify
+project_path = File.join(options_dict[:project_dir], options_dict[:project_name])
+
+unless (File.exist?(project_path))
+ abort("Project at #{project_path} does not exist. Please check paths manually.\n");
+end
+
+# Actually open and modify the project
+project = Xcodeproj::Project.open(project_path)
+project.targets.each do |target|
+ if (target.name == "Runner")
+ app_id = options_dict[:app_id]
+ universal_link = options_dict[:universal_link]
+ applinks = "applinks:#{URI.parse(universal_link).host}"
+
+ sectionObject = {}
+ project.objects.each do |object|
+ if object.uuid == target.uuid
+ sectionObject = object
+ break
+ end
+ end
+ sectionObject.build_configurations.each do |config|
+ infoplist = config.build_settings["INFOPLIST_FILE"]
+ if (!infoplist)
+ puts("INFOPLIST_FILE is not exist")
+ exit(0)
+ end
+ infoplistFile = File.join(options_dict[:project_dir], infoplist)
+ if !File.exist?(infoplistFile)
+ puts("#{infoplist} is not exist")
+ exit(0)
+ end
+ result = Plist.parse_xml(infoplistFile, marshal: false)
+ if (!result)
+ result = {}
+ end
+ urlTypes = result["CFBundleURLTypes"]
+ if (!urlTypes)
+ urlTypes = []
+ result["CFBundleURLTypes"] = urlTypes
+ end
+ isUrlTypeExist = urlTypes.any? { |urlType| urlType["CFBundleURLSchemes"] && (urlType["CFBundleURLSchemes"].include? "tencent#{app_id}") }
+ if (!isUrlTypeExist)
+ urlTypes << {
+ "CFBundleTypeRole": "Editor",
+ "CFBundleURLName": "tencent",
+ "CFBundleURLSchemes": [ "tencent#{app_id}" ]
+ }
+ File.write(infoplistFile, Plist::Emit.dump(result))
+ end
+ queriesSchemes = result["LSApplicationQueriesSchemes"]
+ if (!queriesSchemes)
+ queriesSchemes = []
+ result["LSApplicationQueriesSchemes"] = queriesSchemes
+ end
+ tencentSchemes = [
+ "mqq",
+ "mqqapi",
+ "tim",
+ "mqqopensdknopasteboard",
+ "mqqopensdknopasteboardios16",
+ "mqqopensdkapiV2",
+ "mqqgamebindinggroup",
+ "mqqopensdkavatar",
+ "mqqopensdkfriend",
+ "mqqopensdklaunchminiapp",
+ "mqzone",
+ "tencentapi.qq.reqContent",
+ "tencentapi.qzone.reqContent",
+ "mqqthirdappgroup",
+ "mqqopensdkminiapp",
+ ]
+ if (tencentSchemes.any? { |scheme| !(queriesSchemes.include? scheme)} )
+ tencentSchemes.each do |scheme|
+ if (!(queriesSchemes.include? scheme))
+ queriesSchemes << scheme
+ end
+ end
+ File.write(infoplistFile, Plist::Emit.dump(result))
+ end
+ end
+ sectionObject.build_configurations.each do |config|
+ codeSignEntitlements = config.build_settings["CODE_SIGN_ENTITLEMENTS"]
+ if (!codeSignEntitlements)
+ codeSignEntitlements = "Runner/Runner.entitlements"
+ config.build_settings["CODE_SIGN_ENTITLEMENTS"] = codeSignEntitlements
+ project.save()
+ end
+ codeSignEntitlementsFile = File.join(options_dict[:project_dir], codeSignEntitlements)
+ if !File.exist?(codeSignEntitlementsFile)
+ content = Plist::Emit.dump({})
+ File.write(codeSignEntitlementsFile, content)
+ end
+ runnerTargetMainGroup = project.main_group.find_subpath('Runner', false)
+ isRefExist = runnerTargetMainGroup.files.any? { |file| file.path.include? File.basename(codeSignEntitlementsFile) }
+ if !isRefExist
+ runnerTargetMainGroup.new_reference(File.basename(codeSignEntitlementsFile))
+ project.save()
+ end
+ result = Plist.parse_xml(codeSignEntitlementsFile, marshal: false)
+ if (!result)
+ result = {}
+ end
+ domains = result["com.apple.developer.associated-domains"]
+ if (!domains)
+ domains = []
+ result["com.apple.developer.associated-domains"] = domains
+ end
+ isApplinksExist = domains.include? applinks
+ if (!isApplinksExist)
+ domains << applinks
+ File.write(codeSignEntitlementsFile, Plist::Emit.dump(result))
+ end
+ end
+ end
+end