1
0
mirror of https://github.com/RxReader/tencent_kit.git synced 2025-06-06 08:04:03 +08:00

升级Flutter 3.0

This commit is contained in:
v7lin
2022-05-16 18:47:39 +08:00
parent 26e7039c4f
commit 27f5f8cc7d
62 changed files with 1399 additions and 1041 deletions

12
.github/FUNDING.yml vendored

@ -1,12 +0,0 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: https://v7lin.github.io/docsify/#/navbar/sponsor # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

33
.gitignore vendored

@ -1,11 +1,30 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store .DS_Store
.dart_tool/ .atom/
.buildlog/
.history
.svn/
migrate_working_dir/
.packages # IntelliJ related
.pub/
build/
#
*.iml *.iml
*.ipr
*.iws
.idea/ .idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/

@ -1,10 +1,33 @@
# This file tracks properties of this Flutter project. # This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc. # Used by Flutter tool to assess capabilities and perform upgrades etc.
# #
# This file should be version controlled and should not be manually edited. # This file should be version controlled.
version: version:
revision: b041144f833e05cf463b8887fa12efdec9493488 revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
channel: stable channel: stable
project_type: plugin project_type: plugin
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
- platform: android
create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
- platform: ios
create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

@ -1,3 +1,9 @@
## 4.0.0
* Flutter 3.0
* Android/iOS SDK
* break change:
## 3.1.0 ## 3.1.0
* Android/iOS SDK * Android/iOS SDK

@ -26,15 +26,6 @@ flutter版腾讯(QQ)SDK
## android ## android
```groovy
buildscript {
dependencies {
// Android 11兼容需升级Gradle到3.5.4/3.6.4/4.x.y
classpath 'com.android.tools.build:gradle:3.5.4'
}
}
```
```groovy ```groovy
android { android {
defaultConfig{ defaultConfig{
@ -121,24 +112,25 @@ Capabilities -> Associated Domain -> Domain -> applinks:${your applinks}
|QZone||||||| |QZone|||||||
* break change * break change
* 3.1.0: setIsPermissionGranted / * 4.0.0:
* 3.0.0: * 3.1.0: setIsPermissionGranted /
* 2.1.0: nullsafety & Android embedding v1 & Tencent * 3.0.0:
* 2.1.0: nullsafety & Android embedding v1 & Tencent
* compat * 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| post_install do |installer|
installer.pods_project.targets.each do |target| installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target) flutter_additional_ios_build_settings(target)
# Flutter 2.5 # Flutter 2.5
target.build_configurations.each do |config| target.build_configurations.each do |config|
# config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' # config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'i386 arm64' config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'i386 arm64'
end
end end
end end
``` end
```
* snapshot * snapshot

@ -5,39 +5,44 @@
# #
# For a list of lints, see: http://dart-lang.github.io/linter/lints/ # For a list of lints, see: http://dart-lang.github.io/linter/lints/
# See the configuration guide for more # See the configuration guide for more
# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer # https://github.com/dart-lang/sdk/tree/main/pkg/analyzer#configuring-the-analyzer
# #
# There are other similar analysis options files in the flutter repos, # There are other similar analysis options files in the flutter repos,
# which should be kept in sync with this file: # which should be kept in sync with this file:
# #
# - analysis_options.yaml (this file) # - analysis_options.yaml (this file)
# - packages/flutter/lib/analysis_options_user.yaml
# - https://github.com/flutter/plugins/blob/master/analysis_options.yaml # - https://github.com/flutter/plugins/blob/master/analysis_options.yaml
# - https://github.com/flutter/engine/blob/master/analysis_options.yaml # - https://github.com/flutter/engine/blob/master/analysis_options.yaml
# - https://github.com/flutter/packages/blob/master/analysis_options.yaml
# #
# This file contains the analysis options used by Flutter tools, such as IntelliJ, # This file contains the analysis options used by Flutter tools, such as IntelliJ,
# Android Studio, and the `flutter analyze` command. # Android Studio, and the `flutter analyze` command.
analyzer: analyzer:
strong-mode: language:
implicit-casts: false strict-raw-types: true
implicit-dynamic: false
errors: errors:
# treat missing required parameters as a warning (not a hint) # treat missing required parameters as a warning (not a hint)
missing_required_param: warning missing_required_param: warning
# treat missing returns as a warning (not a hint) # treat missing returns as a warning (not a hint)
missing_return: warning missing_return: warning
# allow having TODOs in the code # allow having TODO comments in the code
todo: ignore todo: ignore
# allow self-reference to deprecated members (we do this because otherwise we have # allow self-reference to deprecated members (we do this because otherwise we have
# to annotate every member in every test, assert, etc, when we deprecate something) # to annotate every member in every test, assert, etc, when we deprecate something)
deprecated_member_use_from_same_package: ignore deprecated_member_use_from_same_package: ignore
# Ignore analyzer hints for updating pubspecs when using Future or # TODO(ianh): https://github.com/flutter/flutter/issues/74381
# Stream and not importing dart:async # Clean up existing unnecessary imports, and remove line to ignore.
# Please see https://github.com/flutter/flutter/pull/24528 for details. unnecessary_import: ignore
sdk_version_async_exported_from_core: ignore # Turned off until null-safe rollout is complete.
unnecessary_null_comparison: ignore
exclude: exclude:
- "bin/cache/**"
# Ignore protoc generated files
- "dev/conductor/lib/proto/*"
#
- "lib/*.g.dart" - "lib/*.g.dart"
- "lib/**/*.g.dart"
linter: linter:
rules: rules:
@ -49,65 +54,71 @@ linter:
# - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219
- always_require_non_null_named_parameters - always_require_non_null_named_parameters
- always_specify_types - always_specify_types
- always_use_package_imports # we do this commonly # - always_use_package_imports # we do this commonly
- annotate_overrides - annotate_overrides
# - avoid_annotating_with_dynamic # conflicts with always_specify_types # - avoid_annotating_with_dynamic # conflicts with always_specify_types
# - avoid_as # required for implicit-casts: true
- avoid_bool_literals_in_conditional_expressions - avoid_bool_literals_in_conditional_expressions
# - avoid_catches_without_on_clauses # we do this commonly # - avoid_catches_without_on_clauses # blocked on https://github.com/dart-lang/linter/issues/3023
# - avoid_catching_errors # we do this commonly # - avoid_catching_errors # blocked on https://github.com/dart-lang/linter/issues/3023
- avoid_classes_with_only_static_members - avoid_classes_with_only_static_members
# - avoid_double_and_int_checks # only useful when targeting JS runtime - avoid_double_and_int_checks
- avoid_dynamic_calls
- avoid_empty_else - avoid_empty_else
- avoid_equals_and_hash_code_on_mutable_classes - avoid_equals_and_hash_code_on_mutable_classes
# - avoid_escaping_inner_quotes # not yet tested - avoid_escaping_inner_quotes
- avoid_field_initializers_in_const_classes - avoid_field_initializers_in_const_classes
# - avoid_final_parameters # incompatible with prefer_final_parameters
- avoid_function_literals_in_foreach_calls - avoid_function_literals_in_foreach_calls
# - avoid_implementing_value_types # not yet tested - avoid_implementing_value_types
- avoid_init_to_null - avoid_init_to_null
# - avoid_js_rounded_ints # only useful when targeting JS runtime - avoid_js_rounded_ints
# - avoid_multiple_declarations_per_line # seems to be a stylistic choice we don't subscribe to
- avoid_null_checks_in_equality_operators - avoid_null_checks_in_equality_operators
# - avoid_positional_boolean_parameters # not yet tested # - avoid_positional_boolean_parameters # would have been nice to enable this but by now there's too many places that break it
# - avoid_print # not yet tested - avoid_print
# - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356)
# - avoid_redundant_argument_values # not yet tested - avoid_redundant_argument_values
- avoid_relative_lib_imports - avoid_relative_lib_imports
- avoid_renaming_method_parameters - avoid_renaming_method_parameters
- avoid_return_types_on_setters - avoid_return_types_on_setters
# - avoid_returning_null # there are plenty of valid reasons to return null # - avoid_returning_null # still violated by some pre-nnbd code that we haven't yet migrated
# - avoid_returning_null_for_future # not yet tested - avoid_returning_null_for_future
- avoid_returning_null_for_void - avoid_returning_null_for_void
# - avoid_returning_this # there are plenty of valid reasons to return this # - avoid_returning_this # there are enough valid reasons to return `this` that this lint ends up with too many false positives
# - avoid_setters_without_getters # not yet tested - avoid_setters_without_getters
- avoid_shadowing_type_parameters - avoid_shadowing_type_parameters
- avoid_single_cascade_in_expression_statements - avoid_single_cascade_in_expression_statements
- avoid_slow_async_io - avoid_slow_async_io
# - avoid_type_to_string # we do this commonly - avoid_type_to_string
- avoid_types_as_parameter_names - avoid_types_as_parameter_names
# - avoid_types_on_closure_parameters # conflicts with always_specify_types # - avoid_types_on_closure_parameters # conflicts with always_specify_types
# - avoid_unnecessary_containers # not yet tested - avoid_unnecessary_containers
- avoid_unused_constructor_parameters - avoid_unused_constructor_parameters
- avoid_void_async - avoid_void_async
# - avoid_web_libraries_in_flutter # not yet tested # - avoid_web_libraries_in_flutter # we use web libraries in web-specific code, and our tests prevent us from using them elsewhere
- await_only_futures - await_only_futures
- camel_case_extensions - camel_case_extensions
- camel_case_types - camel_case_types
- cancel_subscriptions - cancel_subscriptions
# - cascade_invocations # not yet tested # - cascade_invocations # doesn't match the typical style of this repo
- cast_nullable_to_non_nullable - cast_nullable_to_non_nullable
# - close_sinks # not reliable enough # - close_sinks # not reliable enough
# - comment_references # blocked on https://github.com/flutter/flutter/issues/20765 # - comment_references # blocked on https://github.com/dart-lang/linter/issues/1142
# - conditional_uri_does_not_exist # not yet tested
# - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204 # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204
- control_flow_in_finally - control_flow_in_finally
# - curly_braces_in_flow_control_structures # not required by flutter style # - curly_braces_in_flow_control_structures # not required by flutter style
# - diagnostic_describe_all_properties # not yet tested - depend_on_referenced_packages
- deprecated_consistency
# - diagnostic_describe_all_properties # enabled only at the framework level (packages/flutter/lib)
- directives_ordering - directives_ordering
# - do_not_use_environment # we do this commonly # - do_not_use_environment # there are appropriate times to use the environment, especially in our tests and build logic
- empty_catches - empty_catches
- empty_constructor_bodies - empty_constructor_bodies
- empty_statements - empty_statements
- eol_at_end_of_file
- exhaustive_cases - exhaustive_cases
- file_names # not yet tested - file_names
- flutter_style_todos - flutter_style_todos
- hash_and_equals - hash_and_equals
- implementation_imports - implementation_imports
@ -117,24 +128,28 @@ linter:
- leading_newlines_in_multiline_strings - leading_newlines_in_multiline_strings
- library_names - library_names
- library_prefixes - library_prefixes
- library_private_types_in_public_api
# - lines_longer_than_80_chars # not required by flutter style # - lines_longer_than_80_chars # not required by flutter style
- list_remove_unrelated_type - list_remove_unrelated_type
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/linter/issues/453
# - missing_whitespace_between_adjacent_strings # not yet tested - missing_whitespace_between_adjacent_strings
- no_adjacent_strings_in_list - no_adjacent_strings_in_list
# - no_default_cases # too many false positives - no_default_cases
- no_duplicate_case_values - no_duplicate_case_values
- no_leading_underscores_for_library_prefixes
- no_leading_underscores_for_local_identifiers
- no_logic_in_create_state - no_logic_in_create_state
# - no_runtimeType_toString # ok in tests; we enable this only in packages/ # - no_runtimeType_toString # ok in tests; we enable this only in packages/
- non_constant_identifier_names - non_constant_identifier_names
- noop_primitive_operations
- null_check_on_nullable_type_parameter - null_check_on_nullable_type_parameter
# - null_closures # not required by flutter style - null_closures
# - omit_local_variable_types # opposite of always_specify_types # - omit_local_variable_types # opposite of always_specify_types
# - one_member_abstracts # too many false positives # - one_member_abstracts # too many false positives
# - only_throw_errors # https://github.com/flutter/flutter/issues/5792 - only_throw_errors # this does get disabled in a few places where we have legacy code that uses strings et al
- overridden_fields - overridden_fields
- package_api_docs - package_api_docs
# - package_names # non conforming packages in sdk - package_names
- package_prefixed_library_names - package_prefixed_library_names
# - parameter_assignments # we do this commonly # - parameter_assignments # we do this commonly
- prefer_adjacent_string_concatenation - prefer_adjacent_string_concatenation
@ -142,10 +157,10 @@ linter:
# - prefer_asserts_with_message # not required by flutter style # - prefer_asserts_with_message # not required by flutter style
- prefer_collection_literals - prefer_collection_literals
- prefer_conditional_assignment - prefer_conditional_assignment
- prefer_const_constructors # - prefer_const_constructors
- prefer_const_constructors_in_immutables - prefer_const_constructors_in_immutables
- prefer_const_declarations - prefer_const_declarations
- prefer_const_literals_to_create_immutables # - prefer_const_literals_to_create_immutables
# - prefer_constructors_over_static_methods # far too many false positives # - prefer_constructors_over_static_methods # far too many false positives
- prefer_contains - prefer_contains
# - prefer_double_quotes # opposite of prefer_single_quotes # - prefer_double_quotes # opposite of prefer_single_quotes
@ -154,33 +169,38 @@ linter:
- prefer_final_fields - prefer_final_fields
- prefer_final_in_for_each - prefer_final_in_for_each
- prefer_final_locals - prefer_final_locals
# - prefer_final_parameters # we should enable this one day when it can be auto-fixed (https://github.com/dart-lang/linter/issues/3104), see also parameter_assignments
- prefer_for_elements_to_map_fromIterable - prefer_for_elements_to_map_fromIterable
- prefer_foreach - prefer_foreach
# - prefer_function_declarations_over_variables # not yet tested - prefer_function_declarations_over_variables
- prefer_generic_function_type_aliases - prefer_generic_function_type_aliases
- prefer_if_elements_to_conditional_expressions - prefer_if_elements_to_conditional_expressions
- prefer_if_null_operators - prefer_if_null_operators
- prefer_initializing_formals - prefer_initializing_formals
- prefer_inlined_adds - prefer_inlined_adds
# - prefer_int_literals # not yet tested # - prefer_int_literals # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#use-double-literals-for-double-constants
# - prefer_interpolation_to_compose_strings # not yet tested - prefer_interpolation_to_compose_strings
- prefer_is_empty - prefer_is_empty
- prefer_is_not_empty - prefer_is_not_empty
- prefer_is_not_operator - prefer_is_not_operator
- prefer_iterable_whereType - prefer_iterable_whereType
# - prefer_mixin # https://github.com/dart-lang/language/issues/32 # - prefer_mixin # Has false positives, see https://github.com/dart-lang/linter/issues/3018
# - prefer_null_aware_operators # disable until NNBD, see https://github.com/flutter/flutter/pull/32711#issuecomment-492930932 # - prefer_null_aware_method_calls # "call()" is confusing to people new to the language since it's not documented anywhere
# - prefer_relative_imports # not yet tested - prefer_null_aware_operators
# - prefer_relative_imports
- prefer_single_quotes - prefer_single_quotes
- prefer_spread_collections - prefer_spread_collections
- prefer_typing_uninitialized_variables - prefer_typing_uninitialized_variables
- prefer_void_to_null - prefer_void_to_null
# - provide_deprecation_message # not yet tested - provide_deprecation_message
# - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml
- recursive_getters - recursive_getters
# - sized_box_for_whitespace # not yet tested # - require_trailing_commas # blocked on https://github.com/dart-lang/sdk/issues/47441
- secure_pubspec_urls
- sized_box_for_whitespace
# - sized_box_shrink_expand # not yet tested
- slash_for_doc_comments - slash_for_doc_comments
# - sort_child_properties_last # not yet tested - sort_child_properties_last
- sort_constructors_first - sort_constructors_first
# - sort_pub_dependencies # prevents separating pinned transitive dependencies # - sort_pub_dependencies # prevents separating pinned transitive dependencies
- sort_unnamed_constructors_first - sort_unnamed_constructors_first
@ -189,36 +209,43 @@ linter:
- tighten_type_of_initializing_formals - tighten_type_of_initializing_formals
# - type_annotate_public_apis # subset of always_specify_types # - type_annotate_public_apis # subset of always_specify_types
- type_init_formals - type_init_formals
- unawaited_futures # too many false positives # - unawaited_futures # too many false positives, especially with the way AnimationController works
# - unnecessary_await_in_return # not yet tested - unnecessary_await_in_return
- unnecessary_brace_in_string_interps - unnecessary_brace_in_string_interps
- unnecessary_const - unnecessary_const
- unnecessary_constructor_name
# - unnecessary_final # conflicts with prefer_final_locals # - unnecessary_final # conflicts with prefer_final_locals
- unnecessary_getters_setters - unnecessary_getters_setters
# - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498
- unnecessary_late
- unnecessary_new - unnecessary_new
- unnecessary_null_aware_assignments - unnecessary_null_aware_assignments
# - unnecessary_null_checks # not yet tested - unnecessary_null_checks
- unnecessary_null_in_if_null_operators - unnecessary_null_in_if_null_operators
- unnecessary_nullable_for_final_variable_declarations - unnecessary_nullable_for_final_variable_declarations
- unnecessary_overrides - unnecessary_overrides
- unnecessary_parenthesis - unnecessary_parenthesis
# - unnecessary_raw_strings # not yet tested # - unnecessary_raw_strings # what's "necessary" is a matter of opinion; consistency across strings can help readability more than this lint
- unnecessary_statements - unnecessary_statements
- unnecessary_string_escapes - unnecessary_string_escapes
- unnecessary_string_interpolations - unnecessary_string_interpolations
- unnecessary_this - unnecessary_this
- unrelated_type_equality_checks - unrelated_type_equality_checks
# - unsafe_html # not yet tested - unsafe_html
- use_build_context_synchronously
# - use_decorated_box # not yet tested
- use_full_hex_values_for_flutter_colors - use_full_hex_values_for_flutter_colors
# - use_function_type_syntax_for_parameters # not yet tested - use_function_type_syntax_for_parameters
- use_if_null_to_convert_nulls_to_bools
- use_is_even_rather_than_modulo - use_is_even_rather_than_modulo
# - use_key_in_widget_constructors # not yet tested - use_key_in_widget_constructors
- use_late_for_private_fields_and_variables - use_late_for_private_fields_and_variables
- use_named_constants
- use_raw_strings - use_raw_strings
- use_rethrow_when_possible - use_rethrow_when_possible
# - use_setters_to_change_properties # not yet tested - use_setters_to_change_properties
# - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182
- use_test_throws_matchers
# - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
- valid_regexps - valid_regexps
- void_checks - void_checks

1
android/.gitignore vendored

@ -6,3 +6,4 @@
.DS_Store .DS_Store
/build /build
/captures /captures
.cxx

@ -1,5 +1,5 @@
group 'io.github.v7lin.tencent_kit' group 'io.github.v7lin.tencent_kit'
version '3.1.0' version '4.0.0'
buildscript { buildscript {
repositories { repositories {
@ -8,7 +8,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.0' classpath 'com.android.tools.build:gradle:7.1.2'
} }
} }
@ -24,6 +24,11 @@ apply plugin: 'com.android.library'
android { android {
compileSdkVersion 31 compileSdkVersion 31
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// useLibrary 'org.apache.http.legacy' // useLibrary 'org.apache.http.legacy'
resourcePrefix 'tencent_kit' resourcePrefix 'tencent_kit'
@ -54,5 +59,4 @@ android {
dependencies { dependencies {
// //
vendorImplementation fileTree(include: ['*.jar'], dir: 'libs') vendorImplementation fileTree(include: ['*.jar'], dir: 'libs')
// vendorImplementation 'com.tencent.tauth:qqopensdk:3.53.0'
} }

@ -1,4 +0,0 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true

@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip

@ -1,6 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.v7lin.tencent_kit"> package="io.github.v7lin.tencent_kit">
<application> <application>
<provider <provider
android:name=".TencentKitFileProvider" android:name=".TencentKitFileProvider"

@ -11,6 +11,7 @@ import android.os.Bundle;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.tencent.connect.common.Constants; import com.tencent.connect.common.Constants;
import com.tencent.connect.share.QQShare; import com.tencent.connect.share.QQShare;
@ -58,45 +59,6 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
static final int RET_USERCANCEL = -2; static final int RET_USERCANCEL = -2;
} }
//
private static final String METHOD_REGISTERAPP = "registerApp";
private static final String METHOD_ISQQINSTALLED = "isQQInstalled";
private static final String METHOD_ISTIMINSTALLED = "isTIMInstalled";
private static final String METHOD_LOGIN = "login";
private static final String METHOD_LOGOUT = "logout";
private static final String METHOD_SHAREMOOD = "shareMood";
private static final String METHOD_SHARETEXT = "shareText";
private static final String METHOD_SHAREIMAGE = "shareImage";
private static final String METHOD_SHAREMUSIC = "shareMusic";
private static final String METHOD_SHAREWEBPAGE = "shareWebpage";
private static final String METHOD_ONLOGINRESP = "onLoginResp";
private static final String METHOD_ONSHARERESP = "onShareResp";
private static final String ARGUMENT_KEY_APPID = "appId";
// private static final String ARGUMENT_KEY_UNIVERSALLINK = "universalLink";
private static final String ARGUMENT_KEY_SCOPE = "scope";
private static final String ARGUMENT_KEY_SCENE = "scene";
private static final String ARGUMENT_KEY_TITLE = "title";
private static final String ARGUMENT_KEY_SUMMARY = "summary";
private static final String ARGUMENT_KEY_IMAGEURI = "imageUri";
private static final String ARGUMENT_KEY_IMAGEURIS = "imageUris";
private static final String ARGUMENT_KEY_VIDEOURI = "videoUri";
private static final String ARGUMENT_KEY_MUSICURL = "musicUrl";
private static final String ARGUMENT_KEY_TARGETURL = "targetUrl";
private static final String ARGUMENT_KEY_APPNAME = "appName";
private static final String ARGUMENT_KEY_EXTINT = "extInt";
private static final String ARGUMENT_KEY_RESULT_RET = "ret";
private static final String ARGUMENT_KEY_RESULT_MSG = "msg";
private static final String ARGUMENT_KEY_RESULT_OPENID = "openid";
private static final String ARGUMENT_KEY_RESULT_ACCESS_TOKEN = "access_token";
private static final String ARGUMENT_KEY_RESULT_EXPIRES_IN = "expires_in";
private static final String ARGUMENT_KEY_RESULT_CREATE_AT = "create_at";
private static final String SCHEME_FILE = "file";
/// The MethodChannel that will the communication between Flutter and native Android /// The MethodChannel that will the communication between Flutter and native Android
/// ///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it /// This local reference serves to register the plugin with the Flutter Engine and unregister it
@ -150,7 +112,7 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
// --- ActivityResultListener // --- ActivityResultListener
@Override @Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) { public boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode) { switch (requestCode) {
case Constants.REQUEST_LOGIN: case Constants.REQUEST_LOGIN:
return Tencent.onActivityResultData(requestCode, resultCode, data, loginListener); return Tencent.onActivityResultData(requestCode, resultCode, data, loginListener);
@ -176,9 +138,9 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
Tencent.setIsPermissionGranted(granted); Tencent.setIsPermissionGranted(granted);
} }
result.success(null); result.success(null);
} else if (METHOD_REGISTERAPP.equals(call.method)) { } else if ("registerApp".equals(call.method)) {
final String appId = call.argument(ARGUMENT_KEY_APPID); final String appId = call.argument("appId");
// final String universalLink = call.argument(ARGUMENT_KEY_UNIVERSALLINK); // final String universalLink = call.argument("universalLink");
String authority = null; String authority = null;
try { try {
ProviderInfo providerInfo = applicationContext.getPackageManager().getProviderInfo(new ComponentName(applicationContext, TencentKitFileProvider.class), PackageManager.MATCH_DEFAULT_ONLY); ProviderInfo providerInfo = applicationContext.getPackageManager().getProviderInfo(new ComponentName(applicationContext, TencentKitFileProvider.class), PackageManager.MATCH_DEFAULT_ONLY);
@ -192,23 +154,23 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
tencent = Tencent.createInstance(appId, applicationContext); tencent = Tencent.createInstance(appId, applicationContext);
} }
result.success(null); result.success(null);
} else if (METHOD_ISQQINSTALLED.equals(call.method)) { } else if ("isQQInstalled".equals(call.method)) {
result.success(isAppInstalled(applicationContext, "com.tencent.mobileqq")); result.success(isAppInstalled(applicationContext, "com.tencent.mobileqq"));
} else if (METHOD_ISTIMINSTALLED.equals(call.method)) { } else if ("isTIMInstalled".equals(call.method)) {
result.success(isAppInstalled(applicationContext, "com.tencent.tim")); result.success(isAppInstalled(applicationContext, "com.tencent.tim"));
} else if (METHOD_LOGIN.equals(call.method)) { } else if ("login".equals(call.method)) {
login(call, result); login(call, result);
} else if (METHOD_LOGOUT.equals(call.method)) { } else if ("logout".equals(call.method)) {
logout(call, result); logout(call, result);
} else if (METHOD_SHAREMOOD.equals(call.method)) { } else if ("shareMood".equals(call.method)) {
shareMood(call, result); shareMood(call, result);
} else if (METHOD_SHARETEXT.equals(call.method)) { } else if ("shareText".equals(call.method)) {
shareText(call, result); shareText(call, result);
} else if (METHOD_SHAREIMAGE.equals(call.method)) { } else if ("shareImage".equals(call.method)) {
shareImage(call, result); shareImage(call, result);
} else if (METHOD_SHAREMUSIC.equals(call.method)) { } else if ("shareMusic".equals(call.method)) {
shareMusic(call, result); shareMusic(call, result);
} else if (METHOD_SHAREWEBPAGE.equals(call.method)) { } else if ("shareWebpage".equals(call.method)) {
shareWebpage(call, result); shareWebpage(call, result);
} else { } else {
result.notImplemented(); result.notImplemented();
@ -216,7 +178,7 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
} }
private void login(@NonNull MethodCall call, @NonNull Result result) { private void login(@NonNull MethodCall call, @NonNull Result result) {
String scope = call.argument(ARGUMENT_KEY_SCOPE); final String scope = call.argument("scope");
if (tencent != null) { if (tencent != null) {
tencent.login(activityPluginBinding.getActivity(), scope, loginListener); tencent.login(activityPluginBinding.getActivity(), scope, loginListener);
} }
@ -226,59 +188,59 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
private IUiListener loginListener = new IUiListener() { private IUiListener loginListener = new IUiListener() {
@Override @Override
public void onComplete(Object o) { public void onComplete(Object o) {
Map<String, Object> map = new HashMap<>(); final Map<String, Object> map = new HashMap<>();
try { try {
if (o != null && o instanceof JSONObject) { if (o != null && o instanceof JSONObject) {
JSONObject object = (JSONObject) o; final JSONObject object = (JSONObject) o;
int ret = !object.isNull(ARGUMENT_KEY_RESULT_RET) ? object.getInt(ARGUMENT_KEY_RESULT_RET) : TencentRetCode.RET_FAILED; final int ret = !object.isNull("ret") ? object.getInt("ret") : TencentRetCode.RET_FAILED;
String msg = !object.isNull(ARGUMENT_KEY_RESULT_MSG) ? object.getString(ARGUMENT_KEY_RESULT_MSG) : null; final String msg = !object.isNull("msg") ? object.getString("msg") : null;
if (ret == TencentRetCode.RET_SUCCESS) { if (ret == TencentRetCode.RET_SUCCESS) {
String openId = !object.isNull(ARGUMENT_KEY_RESULT_OPENID) ? object.getString(ARGUMENT_KEY_RESULT_OPENID) : null; final String openId = !object.isNull("openid") ? object.getString("openid") : null;
String accessToken = !object.isNull(ARGUMENT_KEY_RESULT_ACCESS_TOKEN) ? object.getString(ARGUMENT_KEY_RESULT_ACCESS_TOKEN) : null; final String accessToken = !object.isNull("access_token") ? object.getString("access_token") : null;
int expiresIn = !object.isNull(ARGUMENT_KEY_RESULT_EXPIRES_IN) ? object.getInt(ARGUMENT_KEY_RESULT_EXPIRES_IN) : 0; final int expiresIn = !object.isNull("expires_in") ? object.getInt("expires_in") : 0;
long createAt = System.currentTimeMillis(); final long createAt = System.currentTimeMillis();
if (!TextUtils.isEmpty(openId) && !TextUtils.isEmpty(accessToken)) { if (!TextUtils.isEmpty(openId) && !TextUtils.isEmpty(accessToken)) {
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_SUCCESS); map.put("ret", TencentRetCode.RET_SUCCESS);
map.put(ARGUMENT_KEY_RESULT_OPENID, openId); map.put("openid", openId);
map.put(ARGUMENT_KEY_RESULT_ACCESS_TOKEN, accessToken); map.put("access_token", accessToken);
map.put(ARGUMENT_KEY_RESULT_EXPIRES_IN, expiresIn); map.put("expires_in", expiresIn);
map.put(ARGUMENT_KEY_RESULT_CREATE_AT, createAt); map.put("create_at", createAt);
} else { } else {
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON); map.put("ret", TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_MSG, "openId or accessToken is null."); map.put("msg", "openId or accessToken is null.");
} }
} else { } else {
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON); map.put("ret", TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_MSG, msg); map.put("msg", msg);
} }
} }
} catch (JSONException e) { } catch (JSONException e) {
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON); map.put("ret", TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_MSG, e.getMessage()); map.put("msg", e.getMessage());
} }
if (channel != null) { if (channel != null) {
channel.invokeMethod(METHOD_ONLOGINRESP, map); channel.invokeMethod("onLoginResp", map);
} }
} }
@Override @Override
public void onError(UiError uiError) { public void onError(UiError uiError) {
// 登录失败 // 登录失败
Map<String, Object> map = new HashMap<>(); final Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON); map.put("ret", TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_MSG, uiError.errorMessage); map.put("msg", uiError.errorMessage);
if (channel != null) { if (channel != null) {
channel.invokeMethod(METHOD_ONLOGINRESP, map); channel.invokeMethod("onLoginResp", map);
} }
} }
@Override @Override
public void onCancel() { public void onCancel() {
// 取消登录 // 取消登录
Map<String, Object> map = new HashMap<>(); final Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_USERCANCEL); map.put("ret", TencentRetCode.RET_USERCANCEL);
if (channel != null) { if (channel != null) {
channel.invokeMethod(METHOD_ONLOGINRESP, map); channel.invokeMethod("onLoginResp", map);
} }
} }
@ -295,25 +257,25 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
} }
private void shareMood(@NonNull MethodCall call, @NonNull Result result) { private void shareMood(@NonNull MethodCall call, @NonNull Result result) {
int scene = call.argument(ARGUMENT_KEY_SCENE); final int scene = call.argument("scene");
if (scene == TencentScene.SCENE_QZONE) { if (scene == TencentScene.SCENE_QZONE) {
String summary = call.argument(ARGUMENT_KEY_SUMMARY); final String summary = call.argument("summary");
List<String> imageUris = call.argument(ARGUMENT_KEY_IMAGEURIS); final List<String> imageUris = call.argument("imageUris");
String videoUri = call.argument(ARGUMENT_KEY_VIDEOURI); final String videoUri = call.argument("videoUri");
Bundle params = new Bundle(); final Bundle params = new Bundle();
if (!TextUtils.isEmpty(summary)) { if (!TextUtils.isEmpty(summary)) {
params.putString(QzonePublish.PUBLISH_TO_QZONE_SUMMARY, summary); params.putString(QzonePublish.PUBLISH_TO_QZONE_SUMMARY, summary);
} }
if (imageUris != null && !imageUris.isEmpty()) { if (imageUris != null && !imageUris.isEmpty()) {
ArrayList<String> uris = new ArrayList<>(); final ArrayList<String> uris = new ArrayList<>();
for (String imageUri : imageUris) { for (String imageUri : imageUris) {
uris.add(Uri.parse(imageUri).getPath()); uris.add(Uri.parse(imageUri).getPath());
} }
params.putStringArrayList(QzonePublish.PUBLISH_TO_QZONE_IMAGE_URL, uris); params.putStringArrayList(QzonePublish.PUBLISH_TO_QZONE_IMAGE_URL, uris);
} }
if (!TextUtils.isEmpty(videoUri)) { if (!TextUtils.isEmpty(videoUri)) {
String videoPath = Uri.parse(videoUri).getPath(); final String videoPath = Uri.parse(videoUri).getPath();
params.putString(QzonePublish.PUBLISH_TO_QZONE_VIDEO_PATH, videoPath); params.putString(QzonePublish.PUBLISH_TO_QZONE_VIDEO_PATH, videoPath);
params.putInt(QzonePublish.PUBLISH_TO_QZONE_KEY_TYPE, QzonePublish.PUBLISH_TO_QZONE_TYPE_PUBLISHVIDEO); params.putInt(QzonePublish.PUBLISH_TO_QZONE_KEY_TYPE, QzonePublish.PUBLISH_TO_QZONE_TYPE_PUBLISHVIDEO);
} else { } else {
@ -327,16 +289,16 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
} }
private void shareText(@NonNull MethodCall call, @NonNull Result result) { private void shareText(@NonNull MethodCall call, @NonNull Result result) {
int scene = call.argument(ARGUMENT_KEY_SCENE); final int scene = call.argument("scene");
if (scene == TencentScene.SCENE_QQ) { if (scene == TencentScene.SCENE_QQ) {
String summary = call.argument(ARGUMENT_KEY_SUMMARY); final String summary = call.argument("summary");
Intent sendIntent = new Intent(); final Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND); sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, summary); sendIntent.putExtra(Intent.EXTRA_TEXT, summary);
sendIntent.setType("text/*"); sendIntent.setType("text/*");
// 普通大众版 > 办公简洁版 > 急速轻聊版 // 普通大众版 > 办公简洁版 > 急速轻聊版
PackageManager packageManager = applicationContext.getPackageManager(); final PackageManager packageManager = applicationContext.getPackageManager();
List<PackageInfo> infos = packageManager.getInstalledPackages(0); final List<PackageInfo> infos = packageManager.getInstalledPackages(0);
if (infos != null && !infos.isEmpty()) { if (infos != null && !infos.isEmpty()) {
for (String packageName : Arrays.asList("com.tencent.mobileqq", "com.tencent.tim", "com.tencent.qqlite")) { for (String packageName : Arrays.asList("com.tencent.mobileqq", "com.tencent.tim", "com.tencent.qqlite")) {
for (PackageInfo info : infos) { for (PackageInfo info : infos) {
@ -356,13 +318,13 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
} }
private void shareImage(@NonNull MethodCall call, @NonNull Result result) { private void shareImage(@NonNull MethodCall call, @NonNull Result result) {
int scene = call.argument(ARGUMENT_KEY_SCENE); final int scene = call.argument("scene");
if (scene == TencentScene.SCENE_QQ) { if (scene == TencentScene.SCENE_QQ) {
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI); final String imageUri = call.argument("imageUri");
String appName = call.argument(ARGUMENT_KEY_APPNAME); final String appName = call.argument("appName");
int extInt = call.argument(ARGUMENT_KEY_EXTINT); final int extInt = call.argument("extInt");
Bundle params = new Bundle(); final Bundle params = new Bundle();
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_IMAGE); params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_IMAGE);
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, Uri.parse(imageUri).getPath()); params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, Uri.parse(imageUri).getPath());
if (!TextUtils.isEmpty(appName)) { if (!TextUtils.isEmpty(appName)) {
@ -377,15 +339,15 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
} }
private void shareMusic(@NonNull MethodCall call, @NonNull Result result) { private void shareMusic(@NonNull MethodCall call, @NonNull Result result) {
int scene = call.argument(ARGUMENT_KEY_SCENE); final int scene = call.argument("scene");
if (scene == TencentScene.SCENE_QQ) { if (scene == TencentScene.SCENE_QQ) {
String title = call.argument(ARGUMENT_KEY_TITLE); final String title = call.argument("title");
String summary = call.argument(ARGUMENT_KEY_SUMMARY); final String summary = call.argument("summary");
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI); final String imageUri = call.argument("imageUri");
String musicUrl = call.argument(ARGUMENT_KEY_MUSICURL); final String musicUrl = call.argument("musicUrl");
String targetUrl = call.argument(ARGUMENT_KEY_TARGETURL); final String targetUrl = call.argument("targetUrl");
String appName = call.argument(ARGUMENT_KEY_APPNAME); final String appName = call.argument("appName");
int extInt = call.argument(ARGUMENT_KEY_EXTINT); final int extInt = call.argument("extInt");
Bundle params = new Bundle(); Bundle params = new Bundle();
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_AUDIO); params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_AUDIO);
@ -395,7 +357,7 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
} }
if (!TextUtils.isEmpty(imageUri)) { if (!TextUtils.isEmpty(imageUri)) {
Uri uri = Uri.parse(imageUri); Uri uri = Uri.parse(imageUri);
if (TextUtils.equals(SCHEME_FILE, uri.getScheme())) { if (TextUtils.equals("file", uri.getScheme())) {
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, uri.getPath()); params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, uri.getPath());
} else { } else {
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, imageUri); params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, imageUri);
@ -415,15 +377,15 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
} }
private void shareWebpage(@NonNull MethodCall call, @NonNull Result result) { private void shareWebpage(@NonNull MethodCall call, @NonNull Result result) {
int scene = call.argument(ARGUMENT_KEY_SCENE); final int scene = call.argument("scene");
String title = call.argument(ARGUMENT_KEY_TITLE); final String title = call.argument("title");
String summary = call.argument(ARGUMENT_KEY_SUMMARY); final String summary = call.argument("summary");
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI); final String imageUri = call.argument("imageUri");
String targetUrl = call.argument(ARGUMENT_KEY_TARGETURL); final String targetUrl = call.argument("targetUrl");
String appName = call.argument(ARGUMENT_KEY_APPNAME); final String appName = call.argument("appName");
int extInt = call.argument(ARGUMENT_KEY_EXTINT); final int extInt = call.argument("extInt");
Bundle params = new Bundle(); final Bundle params = new Bundle();
switch (scene) { switch (scene) {
case TencentScene.SCENE_QQ: case TencentScene.SCENE_QQ:
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT); params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
@ -432,8 +394,8 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
params.putString(QQShare.SHARE_TO_QQ_SUMMARY, summary); params.putString(QQShare.SHARE_TO_QQ_SUMMARY, summary);
} }
if (!TextUtils.isEmpty(imageUri)) { if (!TextUtils.isEmpty(imageUri)) {
Uri uri = Uri.parse(imageUri); final Uri uri = Uri.parse(imageUri);
if (TextUtils.equals(SCHEME_FILE, uri.getScheme())) { if (TextUtils.equals("file", uri.getScheme())) {
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, uri.getPath()); params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, uri.getPath());
} else { } else {
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, imageUri); params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, imageUri);
@ -455,9 +417,9 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, summary); params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, summary);
} }
if (!TextUtils.isEmpty(imageUri)) { if (!TextUtils.isEmpty(imageUri)) {
ArrayList<String> uris = new ArrayList<>(); final ArrayList<String> uris = new ArrayList<>();
Uri uri = Uri.parse(imageUri); final Uri uri = Uri.parse(imageUri);
if (TextUtils.equals(SCHEME_FILE, uri.getScheme())) { if (TextUtils.equals("file", uri.getScheme())) {
uris.add(uri.getPath()); uris.add(uri.getPath());
} else { } else {
uris.add(imageUri); uris.add(imageUri);
@ -478,44 +440,44 @@ public class TencentKitPlugin implements FlutterPlugin, ActivityAware, ActivityR
private IUiListener shareListener = new IUiListener() { private IUiListener shareListener = new IUiListener() {
@Override @Override
public void onComplete(Object o) { public void onComplete(Object o) {
Map<String, Object> map = new HashMap<>(); final Map<String, Object> map = new HashMap<>();
try { try {
if (o != null && o instanceof JSONObject) { if (o != null && o instanceof JSONObject) {
JSONObject object = (JSONObject) o; final JSONObject object = (JSONObject) o;
int ret = !object.isNull(ARGUMENT_KEY_RESULT_RET) ? object.getInt(ARGUMENT_KEY_RESULT_RET) : TencentRetCode.RET_FAILED; final int ret = !object.isNull("ret") ? object.getInt("ret") : TencentRetCode.RET_FAILED;
String msg = !object.isNull(ARGUMENT_KEY_RESULT_MSG) ? object.getString(ARGUMENT_KEY_RESULT_MSG) : null; final String msg = !object.isNull("msg") ? object.getString("msg") : null;
if (ret == TencentRetCode.RET_SUCCESS) { if (ret == TencentRetCode.RET_SUCCESS) {
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_SUCCESS); map.put("ret", TencentRetCode.RET_SUCCESS);
} else { } else {
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON); map.put("ret", TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_MSG, msg); map.put("msg", msg);
} }
} }
} catch (JSONException e) { } catch (JSONException e) {
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON); map.put("ret", TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_MSG, e.getMessage()); map.put("msg", e.getMessage());
} }
if (channel != null) { if (channel != null) {
channel.invokeMethod(METHOD_ONSHARERESP, map); channel.invokeMethod("onShareResp", map);
} }
} }
@Override @Override
public void onError(UiError error) { public void onError(UiError error) {
Map<String, Object> map = new HashMap<>(); final Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON); map.put("ret", TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_MSG, error.errorMessage); map.put("msg", error.errorMessage);
if (channel != null) { if (channel != null) {
channel.invokeMethod(METHOD_ONSHARERESP, map); channel.invokeMethod("onShareResp", map);
} }
} }
@Override @Override
public void onCancel() { public void onCancel() {
Map<String, Object> map = new HashMap<>(); final Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_USERCANCEL); map.put("ret", TencentRetCode.RET_USERCANCEL);
if (channel != null) { if (channel != null) {
channel.invokeMethod(METHOD_ONSHARERESP, map); channel.invokeMethod("onShareResp", map);
} }
} }

1
example/.gitignore vendored

@ -8,6 +8,7 @@
.buildlog/ .buildlog/
.history .history
.svn/ .svn/
migrate_working_dir/
# IntelliJ related # IntelliJ related
*.iml *.iml

@ -1,10 +0,0 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: b041144f833e05cf463b8887fa12efdec9493488
channel: stable
project_type: app

@ -8,9 +8,9 @@ This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project: A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter, view our For help getting started with Flutter development, view the
[online documentation](https://flutter.dev/docs), which offers tutorials, [online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference. samples, guidance on mobile development, and a full API reference.

@ -9,3 +9,5 @@ GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore. # Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties key.properties
**/*.keystore
**/*.jks

@ -27,14 +27,18 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
compileSdkVersion flutter.compileSdkVersion compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
lintOptions { compileOptions {
disable 'InvalidPackage' sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
} }
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "io.github.v7lin.tencent_kit_example" applicationId "io.github.v7lin.tencent_kit_example"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion flutter.minSdkVersion minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()

@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.v7lin.tencent_kit_example"> package="io.github.v7lin.tencent_kit_example">
<!-- Flutter needs it to communicate with the running application <!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
--> -->
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>

@ -1,11 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.v7lin.tencent_kit_example"> package="io.github.v7lin.tencent_kit_example">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that <application
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:label="tencent_kit_example" android:label="tencent_kit_example"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Theme applied to the Android Window while the process is starting --> <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame --> the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started. <!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its Flutter UI initializes, as well as behind your Flutter UI while its
running. running.
This Theme is only used starting with V2 of Flutter's Android embedding. --> This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">@android:color/white</item> <item name="android:windowBackground">?android:colorBackground</item>
</style> </style>
</resources> </resources>

@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.v7lin.tencent_kit_example"> package="io.github.v7lin.tencent_kit_example">
<!-- Flutter needs it to communicate with the running application <!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
--> -->
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>

@ -6,7 +6,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.0' classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
} }
} }

@ -1,4 +1,3 @@
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip

@ -1,7 +1,3 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
include ':app' include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties") def localPropertiesFile = new File(rootProject.projectDir, "local.properties")

@ -1,3 +1,4 @@
**/dgph
*.mode1v3 *.mode1v3
*.mode2v3 *.mode2v3
*.moved-aside *.moved-aside
@ -18,6 +19,7 @@ Flutter/App.framework
Flutter/Flutter.framework Flutter/Flutter.framework
Flutter/Flutter.podspec Flutter/Flutter.podspec
Flutter/Generated.xcconfig Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx Flutter/app.flx
Flutter/app.zip Flutter/app.zip
Flutter/flutter_assets/ Flutter/flutter_assets/

@ -3,7 +3,7 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>en</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>App</string> <string>App</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>

@ -1,2 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"

@ -1,2 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"

@ -3,20 +3,20 @@ PODS:
- FMDB (2.7.5): - FMDB (2.7.5):
- FMDB/standard (= 2.7.5) - FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5) - FMDB/standard (2.7.5)
- path_provider (0.0.1): - path_provider_ios (0.0.1):
- Flutter - Flutter
- sqflite (0.0.2): - sqflite (0.0.2):
- Flutter - Flutter
- FMDB (>= 2.7.5) - FMDB (>= 2.7.5)
- tencent_kit (3.1.0): - tencent_kit (4.0.0):
- Flutter - Flutter
- tencent_kit/vendor (= 3.1.0) - tencent_kit/vendor (= 4.0.0)
- tencent_kit/vendor (3.1.0): - tencent_kit/vendor (4.0.0):
- Flutter - Flutter
DEPENDENCIES: DEPENDENCIES:
- Flutter (from `Flutter`) - Flutter (from `Flutter`)
- path_provider (from `.symlinks/plugins/path_provider/ios`) - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`) - sqflite (from `.symlinks/plugins/sqflite/ios`)
- tencent_kit (from `.symlinks/plugins/tencent_kit/ios`) - tencent_kit (from `.symlinks/plugins/tencent_kit/ios`)
@ -27,8 +27,8 @@ SPEC REPOS:
EXTERNAL SOURCES: EXTERNAL SOURCES:
Flutter: Flutter:
:path: Flutter :path: Flutter
path_provider: path_provider_ios:
:path: ".symlinks/plugins/path_provider/ios" :path: ".symlinks/plugins/path_provider_ios/ios"
sqflite: sqflite:
:path: ".symlinks/plugins/sqflite/ios" :path: ".symlinks/plugins/sqflite/ios"
tencent_kit: tencent_kit:
@ -37,9 +37,9 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS: SPEC CHECKSUMS:
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
tencent_kit: 430a6d2980a5c07fef3ce4671025f92e0c575d29 tencent_kit: 9db7aefcc6dd501bfa258b3d385cf4422701b9cd
PODFILE CHECKSUM: 8e679eca47255a8ca8067c4c67aab20e64cb974d PODFILE CHECKSUM: 8e679eca47255a8ca8067c4c67aab20e64cb974d

@ -14,7 +14,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
A47B4E2D2788685E8EC83B05 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E550C709F5BE86F04F5B1E81 /* libPods-Runner.a */; }; A6615287E8BD6BA6D4AE1EBE /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E5762F657D7B04C64ACF0DB /* libPods-Runner.a */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
@ -34,10 +34,11 @@
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
53A10B2DDA9A7FDE61260A2F /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; }; 56A441886BA7D00789B81833 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
7E5762F657D7B04C64ACF0DB /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -46,9 +47,8 @@
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9DFC57B207F1D38FE813698A /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; }; D2AE0A0966226C328A4CC959 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
E550C709F5BE86F04F5B1E81 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; F7BFE312BA992C4AD37E1D1C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
E87D3240E5D4E8343B925839 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -56,13 +56,32 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A47B4E2D2788685E8EC83B05 /* libPods-Runner.a in Frameworks */, A6615287E8BD6BA6D4AE1EBE /* libPods-Runner.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
251E60BE95A3A323CC8D7115 /* Pods */ = {
isa = PBXGroup;
children = (
D2AE0A0966226C328A4CC959 /* Pods-Runner.debug.xcconfig */,
56A441886BA7D00789B81833 /* Pods-Runner.release.xcconfig */,
F7BFE312BA992C4AD37E1D1C /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
507FBD31C3A53172D6239896 /* Frameworks */ = {
isa = PBXGroup;
children = (
7E5762F657D7B04C64ACF0DB /* libPods-Runner.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = { 9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -80,8 +99,8 @@
9740EEB11CF90186004384FC /* Flutter */, 9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
CE8D8412E01C39B4EF41A68B /* Pods */, 251E60BE95A3A323CC8D7115 /* Pods */,
D66298A71A1FFA013550393B /* Frameworks */, 507FBD31C3A53172D6239896 /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -117,24 +136,6 @@
name = "Supporting Files"; name = "Supporting Files";
sourceTree = "<group>"; sourceTree = "<group>";
}; };
CE8D8412E01C39B4EF41A68B /* Pods */ = {
isa = PBXGroup;
children = (
53A10B2DDA9A7FDE61260A2F /* Pods-Runner.debug.xcconfig */,
E87D3240E5D4E8343B925839 /* Pods-Runner.release.xcconfig */,
9DFC57B207F1D38FE813698A /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
D66298A71A1FFA013550393B /* Frameworks */ = {
isa = PBXGroup;
children = (
E550C709F5BE86F04F5B1E81 /* libPods-Runner.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -142,7 +143,7 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
052B95C45234CE56B9E3CD76 /* [CP] Check Pods Manifest.lock */, 033F50648A25B66BDFFF058D /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */, 9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */, 97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */, 97C146EB1CF9000F007C117D /* Frameworks */,
@ -206,7 +207,7 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
052B95C45234CE56B9E3CD76 /* [CP] Check Pods Manifest.lock */ = { 033F50648A25B66BDFFF058D /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
@ -347,20 +348,13 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 78W43A3TE2;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = io.github.v7lin.tencentKitExample; PRODUCT_BUNDLE_IDENTIFIER = io.github.v7lin.tencentKitExample;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
@ -478,20 +472,13 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 78W43A3TE2;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = io.github.v7lin.tencentKitExample; PRODUCT_BUNDLE_IDENTIFIER = io.github.v7lin.tencentKitExample;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
@ -504,20 +491,13 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 78W43A3TE2;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = io.github.v7lin.tencentKitExample; PRODUCT_BUNDLE_IDENTIFIER = io.github.v7lin.tencentKitExample;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict/> <dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist> </plist>

@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"> shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion> <MacroExpansion>
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
@ -38,8 +36,8 @@
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</MacroExpansion> </MacroExpansion>
<AdditionalOptions> <Testables>
</AdditionalOptions> </Testables>
</TestAction> </TestAction>
<LaunchAction <LaunchAction
buildConfiguration = "Debug" buildConfiguration = "Debug"
@ -61,8 +59,6 @@
ReferencedContainer = "container:Runner.xcodeproj"> ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Profile" buildConfiguration = "Profile"

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

@ -4,6 +4,8 @@
<dict> <dict>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Tencent Kit</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@ -137,5 +139,7 @@
</array> </array>
<key>UIViewControllerBasedStatusBarAppearance</key> <key>UIViewControllerBasedStatusBarAppearance</key>
<false/> <false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
</dict> </dict>
</plist> </plist>

@ -0,0 +1,57 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:tencent_kit_example/api/model/tencent_api_resp.dart';
import 'package:tencent_kit_example/api/model/tencent_unionid_resp.dart';
class TencentApi {
TencentApi._();
/// 用户信息
/// https://wiki.connect.qq.com/get_user_info
static Future<TencentUserInfoResp> getUserInfo({
required String appId,
required String openid,
required String accessToken,
}) {
return HttpClient().getUrl(Uri.parse('https://graph.qq.com/user/get_user_info?access_token=$accessToken&oauth_consumer_key=$appId&openid=$openid')).then((HttpClientRequest request) {
return request.close();
}).then((HttpClientResponse response) async {
if (response.statusCode == HttpStatus.ok) {
final ContentType? contentType = response.headers.contentType;
final Encoding encoding = Encoding.getByName(contentType?.charset) ?? utf8;
final String content = await encoding.decodeStream(response);
return TencentUserInfoResp.fromJson(json.decode(content) as Map<String, dynamic>);
}
throw HttpException('HttpResponse statusCode: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}.');
});
}
/// UnionID
/// https://wiki.connect.qq.com/unionid%E4%BB%8B%E7%BB%8D
static Future<TencentUnionidResp> getUnionId({
required String accessToken,
String unionid = '1',
}) {
return HttpClient().getUrl(Uri.parse('https://graph.qq.com/oauth2.0/me?access_token=$accessToken&unionid=$unionid')).then((HttpClientRequest request) {
return request.close();
}).then((HttpClientResponse response) async {
if (response.statusCode == HttpStatus.ok) {
final ContentType? contentType = response.headers.contentType;
final Encoding encoding = Encoding.getByName(contentType?.charset) ?? utf8;
final String callback = await encoding.decodeStream(response);
// 腾讯有毒 callback( $json );
final RegExp exp = RegExp(r'callback\( (.*) \)\;');
final Match? match = exp.firstMatch(callback);
if (match?.groupCount == 1) {
final String? content = match!.group(1);
if (content != null) {
return TencentUnionidResp.fromJson(json.decode(content) as Map<String, dynamic>);
}
}
}
throw HttpException('HttpResponse statusCode: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}.');
});
}
}

@ -4,19 +4,19 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:tencent_kit/tencent_kit.dart'; import 'package:tencent_kit/tencent_kit.dart';
import 'package:tencent_kit_example/model/tencent_api_resp.dart'; import 'package:tencent_kit_example/api/model/tencent_api_resp.dart';
import 'package:tencent_kit_example/model/tencent_unionid_resp.dart'; import 'package:tencent_kit_example/api/model/tencent_unionid_resp.dart';
import 'package:tencent_kit_example/tencent.dart'; import 'package:tencent_kit_example/api/tencent_api.dart';
const String _TENCENT_APPID = 'your tencent appId'; const String _TENCENT_APPID = 'your tencent appId';
void main() { void main() {
WidgetsFlutterBinding.ensureInitialized();
Tencent.instance.registerApp(appId: _TENCENT_APPID);
runApp(MyApp()); runApp(MyApp());
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
@ -26,6 +26,8 @@ class MyApp extends StatelessWidget {
} }
class Home extends StatefulWidget { class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() {
return _HomeState(); return _HomeState();
@ -40,7 +42,7 @@ class _HomeState extends State<Home> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_respSubs = Tencent.instance.respStream().listen(_listenLogin); _respSubs = Tencent.respStream().listen(_listenLogin);
} }
void _listenLogin(BaseResp resp) { void _listenLogin(BaseResp resp) {
@ -64,47 +66,50 @@ class _HomeState extends State<Home> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('Tencent Kit Demo'), title: Text('Tencent Kit Demo'),
), ),
body: ListView( body: ListView(
children: <Widget>[ children: <Widget>[
ListTile( ListTile(
title: const Text('环境检查'), title: Text('注册APP'),
onTap: () async { onTap: () async {
final String content = await Tencent.registerApp(appId: _TENCENT_APPID);
'QQ install: ${await Tencent.instance.isQQInstalled()}\nTIM install: ${await Tencent.instance.isTIMInstalled()}'; _showTips('注册APP', '注册成功');
},
),
ListTile(
title: Text('环境检查'),
onTap: () async {
final String content = 'QQ install: ${await Tencent.isQQInstalled()}\nTIM install: ${await Tencent.isTIMInstalled()}';
_showTips('环境检查', content); _showTips('环境检查', content);
}, },
), ),
ListTile( ListTile(
title: const Text('3.1.0 之后的版本请先获取权限'), title: Text('3.1.0 之后的版本请先获取权限'),
onTap: () async { onTap: () async {
await Tencent.instance.setIsPermissionGranted(granted: true); await Tencent.setIsPermissionGranted(granted: true);
_showTips('授权', '已授权获取设备信息/同意隐私协议'); _showTips('授权', '已授权获取设备信息/同意隐私协议');
}, },
), ),
ListTile( ListTile(
title: const Text('登录'), title: Text('登录'),
onTap: () { onTap: () {
Tencent.instance.login( Tencent.login(
scope: <String>[TencentScope.GET_SIMPLE_USERINFO], scope: <String>[TencentScope.GET_SIMPLE_USERINFO],
); );
}, },
), ),
ListTile( ListTile(
title: const Text('获取用户信息'), title: Text('获取用户信息'),
onTap: () async { onTap: () async {
if ((_loginResp?.isSuccessful ?? false) && if ((_loginResp?.isSuccessful ?? false) && !(_loginResp!.isExpired ?? true)) {
!(_loginResp!.isExpired ?? true)) { final TencentUserInfoResp userInfo = await TencentApi.getUserInfo(
final TencentUserInfoResp userInfo =
await Tencent.instance.getUserInfo(
appId: _TENCENT_APPID, appId: _TENCENT_APPID,
openid: _loginResp!.openid!, openid: _loginResp!.openid!,
accessToken: _loginResp!.accessToken!, accessToken: _loginResp!.accessToken!,
); );
if (userInfo.isSuccessful) { if (userInfo.isSuccessful) {
_showTips('用户信息', _showTips('用户信息', '${userInfo.nickname} - ${userInfo.gender} - ${userInfo.genderType}');
'${userInfo.nickname} - ${userInfo.gender} - ${userInfo.genderType}');
} else { } else {
_showTips('用户信息', '${userInfo.ret} - ${userInfo.msg}'); _showTips('用户信息', '${userInfo.ret} - ${userInfo.msg}');
} }
@ -112,57 +117,52 @@ class _HomeState extends State<Home> {
}, },
), ),
ListTile( ListTile(
title: const Text('获取UnionID'), title: Text('获取UnionID'),
onTap: () async { onTap: () async {
if ((_loginResp?.isSuccessful ?? false) && if ((_loginResp?.isSuccessful ?? false) && !(_loginResp!.isExpired ?? true)) {
!(_loginResp!.isExpired ?? true)) { final TencentUnionidResp unionid = await TencentApi.getUnionId(
final TencentUnionidResp unionid =
await Tencent.instance.getUnionId(
accessToken: _loginResp!.accessToken!, accessToken: _loginResp!.accessToken!,
); );
if (unionid.isSuccessful) { if (unionid.isSuccessful) {
_showTips('UnionID', _showTips('UnionID', '${unionid.clientId} - ${unionid.openid} - ${unionid.unionid}');
'${unionid.clientId} - ${unionid.openid} - ${unionid.unionid}');
} else { } else {
_showTips('UnionID', _showTips('UnionID', '${unionid.error} - ${unionid.errorDescription}');
'${unionid.error} - ${unionid.errorDescription}');
} }
} }
}, },
), ),
ListTile( ListTile(
title: const Text('分享说说'), title: Text('分享说说'),
onTap: () { onTap: () {
Tencent.instance.shareMood( Tencent.shareMood(
scene: TencentScene.SCENE_QZONE, scene: TencentScene.SCENE_QZONE,
summary: '分享测试', summary: '分享测试',
); );
}, },
), ),
ListTile( ListTile(
title: const Text('文本分享'), title: Text('文本分享'),
onTap: () { onTap: () {
Tencent.instance.shareText( Tencent.shareText(
scene: TencentScene.SCENE_QQ, scene: TencentScene.SCENE_QQ,
summary: '分享测试', summary: '分享测试',
); );
}, },
), ),
ListTile( ListTile(
title: const Text('图片分享'), title: Text('图片分享'),
onTap: () async { onTap: () async {
final File file = await DefaultCacheManager().getSingleFile( final File file = await DefaultCacheManager().getSingleFile('https://www.baidu.com/img/bd_logo1.png?where=super');
'https://www.baidu.com/img/bd_logo1.png?where=super'); await Tencent.shareImage(
await Tencent.instance.shareImage(
scene: TencentScene.SCENE_QQ, scene: TencentScene.SCENE_QQ,
imageUri: Uri.file(file.path), imageUri: Uri.file(file.path),
); );
}, },
), ),
ListTile( ListTile(
title: const Text('网页分享'), title: Text('网页分享'),
onTap: () { onTap: () {
Tencent.instance.shareWebpage( Tencent.shareWebpage(
scene: TencentScene.SCENE_QQ, scene: TencentScene.SCENE_QQ,
title: 'title', title: 'title',
targetUrl: 'https://www.baidu.com/', targetUrl: 'https://www.baidu.com/',

@ -1,68 +0,0 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:tencent_kit/tencent_kit.dart';
import 'package:tencent_kit_example/model/tencent_api_resp.dart';
import 'package:tencent_kit_example/model/tencent_unionid_resp.dart';
extension MixerTencent on Tencent {
/// 用户信息
/// https://wiki.connect.qq.com/get_user_info
Future<TencentUserInfoResp> getUserInfo({
required String appId,
required String openid,
required String accessToken,
}) {
return HttpClient()
.getUrl(Uri.parse(
'https://graph.qq.com/user/get_user_info?access_token=$accessToken&oauth_consumer_key=$appId&openid=$openid'))
.then((HttpClientRequest request) {
return request.close();
}).then((HttpClientResponse response) async {
if (response.statusCode == HttpStatus.ok) {
final ContentType? contentType = response.headers.contentType;
final Encoding encoding =
Encoding.getByName(contentType?.charset) ?? utf8;
final String content = await encoding.decodeStream(response);
return TencentUserInfoResp.fromJson(
json.decode(content) as Map<String, dynamic>);
}
throw HttpException(
'HttpResponse statusCode: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}.');
});
}
/// UnionID
/// https://wiki.connect.qq.com/unionid%E4%BB%8B%E7%BB%8D
Future<TencentUnionidResp> getUnionId({
required String accessToken,
String unionid = '1',
}) {
return HttpClient()
.getUrl(Uri.parse(
'https://graph.qq.com/oauth2.0/me?access_token=$accessToken&unionid=$unionid'))
.then((HttpClientRequest request) {
return request.close();
}).then((HttpClientResponse response) async {
if (response.statusCode == HttpStatus.ok) {
final ContentType? contentType = response.headers.contentType;
final Encoding encoding =
Encoding.getByName(contentType?.charset) ?? utf8;
final String callback = await encoding.decodeStream(response);
// 腾讯有毒 callback( $json );
final RegExp exp = RegExp(r'callback\( (.*) \)\;');
final Match? match = exp.firstMatch(callback);
if (match?.groupCount == 1) {
final String? content = match!.group(1);
if (content != null) {
return TencentUnionidResp.fromJson(
json.decode(content) as Map<String, dynamic>);
}
}
}
throw HttpException(
'HttpResponse statusCode: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}.');
});
}
}

@ -5,198 +5,191 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "22.0.0" version: "39.0.0"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.7.2" version: "4.0.0"
args: args:
dependency: transitive dependency: transitive
description: description:
name: args name: args
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.2.0" version: "2.3.1"
async: async:
dependency: transitive dependency: transitive
description: description:
name: async name: async
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.8.2" version: "2.8.2"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
name: boolean_selector name: boolean_selector
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
build: build:
dependency: transitive dependency: transitive
description: description:
name: build name: build
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.3" version: "2.3.0"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
name: build_config name: build_config
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.7" version: "1.0.0"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.10" version: "3.1.0"
build_resolvers: build_resolvers:
dependency: transitive dependency: transitive
description: description:
name: build_resolvers name: build_resolvers
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.4" version: "2.0.8"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.12.2" version: "2.1.10"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.12" version: "7.2.3"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
name: built_collection name: built_collection
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "5.1.0" version: "5.1.1"
built_value: built_value:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "8.1.1" version: "8.3.0"
characters: characters:
dependency: transitive dependency: transitive
description: description:
name: characters name: characters
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
name: charcode name: charcode
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.1" version: "1.3.1"
checked_yaml: checked_yaml:
dependency: transitive dependency: transitive
description: description:
name: checked_yaml name: checked_yaml
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.1" version: "2.0.1"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.3"
clock: clock:
dependency: transitive dependency: transitive
description: description:
name: clock name: clock
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
code_builder: code_builder:
dependency: transitive dependency: transitive
description: description:
name: code_builder name: code_builder
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.7.0" version: "4.1.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.15.0" version: "1.16.0"
convert: convert:
dependency: transitive dependency: transitive
description: description:
name: convert name: convert
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.1" version: "3.0.1"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
name: crypto name: crypto
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.2"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
name: cupertino_icons name: cupertino_icons
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.2" version: "1.0.4"
dart_style: dart_style:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.14" version: "2.2.3"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
name: fake_async name: fake_async
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.3.0"
ffi: ffi:
dependency: transitive dependency: transitive
description: description:
name: ffi name: ffi
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "1.2.1"
file: file:
dependency: transitive dependency: transitive
description: description:
name: file name: file
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "6.1.0" version: "6.1.2"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
name: fixnum name: fixnum
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "1.0.1"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -206,229 +199,264 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_cache_manager name: flutter_cache_manager
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.3.0" version: "3.3.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.2"
glob: glob:
dependency: transitive dependency: transitive
description: description:
name: glob name: glob
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.1" version: "2.0.2"
graphs: graphs:
dependency: transitive dependency: transitive
description: description:
name: graphs name: graphs
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "2.1.0"
http: http:
dependency: transitive dependency: transitive
description: description:
name: http name: http
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.13.0" version: "0.13.4"
http_multi_server: http_multi_server:
dependency: transitive dependency: transitive
description: description:
name: http_multi_server name: http_multi_server
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.1" version: "3.2.0"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
name: http_parser name: http_parser
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.0" version: "4.0.0"
io: io:
dependency: transitive dependency: transitive
description: description:
name: io name: io
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.3" version: "1.0.3"
js: js:
dependency: transitive dependency: transitive
description: description:
name: js name: js
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.6.3" version: "0.6.4"
json_annotation: json_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
name: json_annotation name: json_annotation
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.0" version: "4.5.0"
json_serializable: json_serializable:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: json_serializable name: json_serializable
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.0.3" version: "6.2.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
logging: logging:
dependency: transitive dependency: transitive
description: description:
name: logging name: logging
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.1" version: "1.0.2"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.12.11" version: "0.12.11"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.1.3" version: "0.1.4"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.7.0" version: "1.7.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
name: mime name: mime
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "1.0.2"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
name: package_config name: package_config
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.0.2"
path: path:
dependency: transitive dependency: transitive
description: description:
name: path name: path
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.0" version: "1.8.1"
path_provider: path_provider:
dependency: transitive dependency: transitive
description: description:
name: path_provider name: path_provider
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.1" version: "2.0.10"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.14"
path_provider_ios:
dependency: transitive
description:
name: path_provider_ios
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.9"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
name: path_provider_linux name: path_provider_linux
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.1.6"
path_provider_macos: path_provider_macos:
dependency: transitive dependency: transitive
description: description:
name: path_provider_macos name: path_provider_macos
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.0.6"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: path_provider_platform_interface name: path_provider_platform_interface
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.1" version: "2.0.4"
path_provider_windows: path_provider_windows:
dependency: transitive dependency: transitive
description: description:
name: path_provider_windows name: path_provider_windows
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.0.6"
pedantic: pedantic:
dependency: "direct dev" dependency: transitive
description: description:
name: pedantic name: pedantic
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.11.0" version: "1.11.1"
platform: platform:
dependency: transitive dependency: transitive
description: description:
name: platform name: platform
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.0" version: "3.1.0"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: plugin_platform_interface name: plugin_platform_interface
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.1.2"
pool: pool:
dependency: transitive dependency: transitive
description: description:
name: pool name: pool
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.5.0" version: "1.5.0"
process: process:
dependency: transitive dependency: transitive
description: description:
name: process name: process
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "4.1.0" version: "4.2.4"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
name: pub_semver name: pub_semver
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.1.1"
pubspec_parse: pubspec_parse:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "1.2.0"
rxdart: rxdart:
dependency: transitive dependency: transitive
description: description:
name: rxdart name: rxdart
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.26.0" version: "0.27.3"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
name: shelf name: shelf
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.3.0"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
name: shelf_web_socket name: shelf_web_socket
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.1" version: "1.0.1"
sky_engine: sky_engine:
@ -440,149 +468,156 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_gen name: source_gen
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.9.10+4" version: "1.2.2"
source_helper:
dependency: transitive
description:
name: source_helper
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.2"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.8.1" version: "1.8.2"
sqflite: sqflite:
dependency: transitive dependency: transitive
description: description:
name: sqflite name: sqflite
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0+3" version: "2.0.2+1"
sqflite_common: sqflite_common:
dependency: transitive dependency: transitive
description: description:
name: sqflite_common name: sqflite_common
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0+2" version: "2.2.1+1"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.10.0" version: "1.10.0"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.1.0"
stream_transform: stream_transform:
dependency: transitive dependency: transitive
description: description:
name: stream_transform name: stream_transform
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
synchronized: synchronized:
dependency: transitive dependency: transitive
description: description:
name: synchronized name: synchronized
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.0" version: "3.0.0+2"
tencent_kit: tencent_kit:
dependency: "direct main" dependency: "direct main"
description: description:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "3.1.0" version: "4.0.0"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
name: term_glyph name: term_glyph
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.4.8" version: "0.4.9"
timing: timing:
dependency: transitive dependency: transitive
description: description:
name: timing name: timing
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "1.0.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.3.0" version: "1.3.1"
uuid: uuid:
dependency: transitive dependency: transitive
description: description:
name: uuid name: uuid
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.0.1" version: "3.0.6"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:
name: watcher name: watcher
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.0.0" version: "1.0.1"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
name: web_socket_channel name: web_socket_channel
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.1.0" version: "2.2.0"
win32: win32:
dependency: transitive dependency: transitive
description: description:
name: win32 name: win32
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.4" version: "2.6.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
name: xdg_directories name: xdg_directories
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.0" version: "0.2.0+1"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:
name: yaml name: yaml
url: "https://pub.flutter-io.cn" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "3.1.0" version: "3.1.1"
sdks: sdks:
dart: ">=2.14.0 <3.0.0" dart: ">=2.17.0 <3.0.0"
flutter: ">=1.24.0-10" flutter: ">=2.8.1"

@ -2,14 +2,20 @@ name: tencent_kit_example
description: Demonstrates how to use the tencent_kit plugin. description: Demonstrates how to use the tencent_kit plugin.
# The following line prevents the package from being accidentally published to # The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages. # pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+100 version: 1.0.0+100
environment: environment:
sdk: ">=2.12.0 <3.0.0" sdk: ">=2.17.0 <3.0.0"
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
@ -19,7 +25,7 @@ dependencies:
# tencent_kit: ^x.y.z # tencent_kit: ^x.y.z
# See https://dart.dev/tools/pub/dependencies#version-constraints # See https://dart.dev/tools/pub/dependencies#version-constraints
# The example app is bundled with the plugin so we use a path dependency on # The example app is bundled with the plugin so we use a path dependency on
# the parent directory to use the current plugin's version. # the parent directory to use the current plugin's version.
path: ../ path: ../
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
@ -28,13 +34,18 @@ dependencies:
flutter_cache_manager: ^3.0.0 flutter_cache_manager: ^3.0.0
json_annotation: ^4.0.0 json_annotation: ^4.5.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
pedantic: # The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^2.0.0
build_runner: build_runner:
json_serializable: json_serializable:
@ -42,7 +53,7 @@ dev_dependencies:
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter. # The following section is specific to Flutter packages.
flutter: flutter:
# The following line ensures that the Material Icons font is # The following line ensures that the Material Icons font is
@ -56,7 +67,7 @@ flutter:
# - images/a_dot_ham.jpeg # - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see # An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware. # https://flutter.dev/assets-and-images/#resolution-aware
# For details regarding adding assets from package dependencies, see # For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages # https://flutter.dev/assets-and-images/#from-packages

@ -1,8 +1,27 @@
// This is a basic Flutter widget test. // This is a basic Flutter widget test.
// //
// To perform an interaction with a widget in your test, use the WidgetTester // To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll // utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget // gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct. // tree, read text, and verify that the values of widget properties are correct.
void main() {} import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tencent_kit_example/main.dart';
void main() {
testWidgets('Verify Platform version', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());
// Verify that platform version is retrieved.
expect(
find.byWidgetPredicate(
(Widget widget) => widget is Text &&
widget.data!.startsWith('Running on:'),
),
findsOneWidget,
);
});
}

1
ios/.gitignore vendored

@ -34,4 +34,5 @@ Icon?
.tags* .tags*
/Flutter/Generated.xcconfig /Flutter/Generated.xcconfig
/Flutter/ephemeral/
/Flutter/flutter_export_environment.sh /Flutter/flutter_export_environment.sh

@ -1,4 +1,4 @@
#import <Flutter/Flutter.h> #import <Flutter/Flutter.h>
@interface TencentKitPlugin : NSObject <FlutterPlugin> @interface TencentKitPlugin : NSObject<FlutterPlugin>
@end @end

@ -36,43 +36,6 @@ enum TencentRetCode {
[registrar addMethodCallDelegate:instance channel:channel]; [registrar addMethodCallDelegate:instance channel:channel];
} }
static NSString *const METHOD_REGISTERAPP = @"registerApp";
static NSString *const METHOD_ISQQINSTALLED = @"isQQInstalled";
static NSString *const METHOD_ISTIMINSTALLED = @"isTIMInstalled";
static NSString *const METHOD_LOGIN = @"login";
static NSString *const METHOD_LOGOUT = @"logout";
static NSString *const METHOD_SHAREMOOD = @"shareMood";
static NSString *const METHOD_SHARETEXT = @"shareText";
static NSString *const METHOD_SHAREIMAGE = @"shareImage";
static NSString *const METHOD_SHAREMUSIC = @"shareMusic";
static NSString *const METHOD_SHAREWEBPAGE = @"shareWebpage";
static NSString *const METHOD_ONLOGINRESP = @"onLoginResp";
static NSString *const METHOD_ONSHARERESP = @"onShareResp";
static NSString *const ARGUMENT_KEY_APPID = @"appId";
static NSString *const ARGUMENT_KEY_UNIVERSALLINK = @"universalLink";
static NSString *const ARGUMENT_KEY_SCOPE = @"scope";
static NSString *const ARGUMENT_KEY_SCENE = @"scene";
static NSString *const ARGUMENT_KEY_TITLE = @"title";
static NSString *const ARGUMENT_KEY_SUMMARY = @"summary";
static NSString *const ARGUMENT_KEY_IMAGEURI = @"imageUri";
static NSString *const ARGUMENT_KEY_IMAGEURIS = @"imageUris";
static NSString *const ARGUMENT_KEY_VIDEOURI = @"videoUri";
static NSString *const ARGUMENT_KEY_MUSICURL = @"musicUrl";
static NSString *const ARGUMENT_KEY_TARGETURL = @"targetUrl";
static NSString *const ARGUMENT_KEY_APPNAME = @"appName";
static NSString *const ARGUMENT_KEY_EXTINT = @"extInt";
static NSString *const ARGUMENT_KEY_RESULT_RET = @"ret";
static NSString *const ARGUMENT_KEY_RESULT_MSG = @"msg";
static NSString *const ARGUMENT_KEY_RESULT_OPENID = @"openid";
static NSString *const ARGUMENT_KEY_RESULT_ACCESS_TOKEN = @"access_token";
static NSString *const ARGUMENT_KEY_RESULT_EXPIRES_IN = @"expires_in";
static NSString *const ARGUMENT_KEY_RESULT_CREATE_AT = @"create_at";
static NSString *const SCHEME_FILE = @"file";
- (instancetype)initWithChannel:(FlutterMethodChannel *)channel { - (instancetype)initWithChannel:(FlutterMethodChannel *)channel {
self = [super init]; self = [super init];
if (self) { if (self) {
@ -87,9 +50,9 @@ static NSString *const SCHEME_FILE = @"file";
NSNumber *granted = call.arguments[@"granted"]; NSNumber *granted = call.arguments[@"granted"];
[TencentOAuth setIsUserAgreedAuthorization: [granted boolValue]]; [TencentOAuth setIsUserAgreedAuthorization: [granted boolValue]];
result(nil); result(nil);
} else if ([METHOD_REGISTERAPP isEqualToString:call.method]) { } else if ([@"registerApp" isEqualToString:call.method]) {
NSString *appId = call.arguments[ARGUMENT_KEY_APPID]; NSString *appId = call.arguments[@"appId"];
NSString *universalLink = call.arguments[ARGUMENT_KEY_UNIVERSALLINK]; NSString *universalLink = call.arguments[@"universalLink"];
if (universalLink != nil) { if (universalLink != nil) {
_oauth = [[TencentOAuth alloc] initWithAppId:appId _oauth = [[TencentOAuth alloc] initWithAppId:appId
andUniversalLink:universalLink andUniversalLink:universalLink
@ -98,23 +61,23 @@ static NSString *const SCHEME_FILE = @"file";
_oauth = [[TencentOAuth alloc] initWithAppId:appId andDelegate:self]; _oauth = [[TencentOAuth alloc] initWithAppId:appId andDelegate:self];
} }
result(nil); result(nil);
} else if ([METHOD_ISQQINSTALLED isEqualToString:call.method]) { } else if ([@"isQQInstalled" isEqualToString:call.method]) {
result([NSNumber numberWithBool:[TencentOAuth iphoneQQInstalled]]); result([NSNumber numberWithBool:[TencentOAuth iphoneQQInstalled]]);
} else if ([METHOD_ISTIMINSTALLED isEqualToString:call.method]) { } else if ([@"isTIMInstalled" isEqualToString:call.method]) {
result([NSNumber numberWithBool:[TencentOAuth iphoneTIMInstalled]]); result([NSNumber numberWithBool:[TencentOAuth iphoneTIMInstalled]]);
} else if ([METHOD_LOGIN isEqualToString:call.method]) { } else if ([@"login" isEqualToString:call.method]) {
[self login:call result:result]; [self login:call result:result];
} else if ([METHOD_LOGOUT isEqualToString:call.method]) { } else if ([@"logout" isEqualToString:call.method]) {
[self logout:call result:result]; [self logout:call result:result];
} else if ([METHOD_SHAREMOOD isEqualToString:call.method]) { } else if ([@"shareMood" isEqualToString:call.method]) {
[self shareMood:call result:result]; [self shareMood:call result:result];
} else if ([METHOD_SHARETEXT isEqualToString:call.method]) { } else if ([@"shareText" isEqualToString:call.method]) {
[self shareText:call result:result]; [self shareText:call result:result];
} else if ([METHOD_SHAREIMAGE isEqualToString:call.method]) { } else if ([@"shareImage" isEqualToString:call.method]) {
[self shareImage:call result:result]; [self shareImage:call result:result];
} else if ([METHOD_SHAREMUSIC isEqualToString:call.method]) { } else if ([@"shareMusic" isEqualToString:call.method]) {
[self shareMusic:call result:result]; [self shareMusic:call result:result];
} else if ([METHOD_SHAREWEBPAGE isEqualToString:call.method]) { } else if ([@"shareWebpage" isEqualToString:call.method]) {
[self shareWebpage:call result:result]; [self shareWebpage:call result:result];
} else { } else {
result(FlutterMethodNotImplemented); result(FlutterMethodNotImplemented);
@ -123,7 +86,7 @@ static NSString *const SCHEME_FILE = @"file";
- (void)login:(FlutterMethodCall *)call result:(FlutterResult)result { - (void)login:(FlutterMethodCall *)call result:(FlutterResult)result {
if (_oauth != nil) { if (_oauth != nil) {
NSString *scope = call.arguments[ARGUMENT_KEY_SCOPE]; NSString *scope = call.arguments[@"scope"];
NSArray *permissions = [scope componentsSeparatedByString:@","]; NSArray *permissions = [scope componentsSeparatedByString:@","];
[_oauth authorize:permissions]; [_oauth authorize:permissions];
} }
@ -138,11 +101,11 @@ static NSString *const SCHEME_FILE = @"file";
} }
- (void)shareMood:(FlutterMethodCall *)call result:(FlutterResult)result { - (void)shareMood:(FlutterMethodCall *)call result:(FlutterResult)result {
NSNumber *scene = call.arguments[ARGUMENT_KEY_SCENE]; NSNumber *scene = call.arguments[@"scene"];
if (scene.intValue == SCENE_QZONE) { if (scene.intValue == SCENE_QZONE) {
NSString *summary = call.arguments[ARGUMENT_KEY_SUMMARY]; NSString *summary = call.arguments[@"summary"];
NSArray *imageUris = call.arguments[ARGUMENT_KEY_IMAGEURIS]; NSArray *imageUris = call.arguments[@"imageUris"];
NSString *videoUri = call.arguments[ARGUMENT_KEY_VIDEOURI]; NSString *videoUri = call.arguments[@"videoUri"];
if (videoUri == nil || videoUri.length == 0) { if (videoUri == nil || videoUri.length == 0) {
NSMutableArray *imageDatas = [NSMutableArray array]; NSMutableArray *imageDatas = [NSMutableArray array];
@ -172,9 +135,9 @@ static NSString *const SCHEME_FILE = @"file";
} }
- (void)shareText:(FlutterMethodCall *)call result:(FlutterResult)result { - (void)shareText:(FlutterMethodCall *)call result:(FlutterResult)result {
NSNumber *scene = call.arguments[ARGUMENT_KEY_SCENE]; NSNumber *scene = call.arguments[@"scene"];
if (scene.intValue == SCENE_QQ) { if (scene.intValue == SCENE_QQ) {
NSString *summary = call.arguments[ARGUMENT_KEY_SUMMARY]; NSString *summary = call.arguments[@"summary"];
QQApiTextObject *object = [QQApiTextObject objectWithText:summary]; QQApiTextObject *object = [QQApiTextObject objectWithText:summary];
SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:object]; SendMessageToQQReq *req = [SendMessageToQQReq reqWithContent:object];
[QQApiInterface sendReq:req]; [QQApiInterface sendReq:req];
@ -183,11 +146,11 @@ static NSString *const SCHEME_FILE = @"file";
} }
- (void)shareImage:(FlutterMethodCall *)call result:(FlutterResult)result { - (void)shareImage:(FlutterMethodCall *)call result:(FlutterResult)result {
NSNumber *scene = call.arguments[ARGUMENT_KEY_SCENE]; NSNumber *scene = call.arguments[@"scene"];
if (scene.intValue == SCENE_QQ) { if (scene.intValue == SCENE_QQ) {
NSString *imageUri = call.arguments[ARGUMENT_KEY_IMAGEURI]; NSString *imageUri = call.arguments[@"imageUri"];
// NSString *appName = call.arguments[ARGUMENT_KEY_APPNAME]; // NSString *appName = call.arguments[@"appName"];
// NSNumber *extInt = call.arguments[ARGUMENT_KEY_EXTINT]; // NSNumber *extInt = call.arguments[@"extInt"];
NSURL *imageUrl = [NSURL URLWithString:imageUri]; NSURL *imageUrl = [NSURL URLWithString:imageUri];
NSData *imageData = [NSData dataWithContentsOfFile:imageUrl.path]; NSData *imageData = [NSData dataWithContentsOfFile:imageUrl.path];
@ -202,18 +165,18 @@ static NSString *const SCHEME_FILE = @"file";
} }
- (void)shareMusic:(FlutterMethodCall *)call result:(FlutterResult)result { - (void)shareMusic:(FlutterMethodCall *)call result:(FlutterResult)result {
NSNumber *scene = call.arguments[ARGUMENT_KEY_SCENE]; NSNumber *scene = call.arguments[@"scene"];
NSString *title = call.arguments[ARGUMENT_KEY_TITLE]; NSString *title = call.arguments[@"title"];
NSString *summary = call.arguments[ARGUMENT_KEY_SUMMARY]; NSString *summary = call.arguments[@"summary"];
NSString *imageUri = call.arguments[ARGUMENT_KEY_IMAGEURI]; NSString *imageUri = call.arguments[@"imageUri"];
NSString *musicUrl = call.arguments[ARGUMENT_KEY_MUSICURL]; NSString *musicUrl = call.arguments[@"musicUrl"];
NSString *targetUrl = call.arguments[ARGUMENT_KEY_TARGETURL]; NSString *targetUrl = call.arguments[@"targetUrl"];
// NSString *appName = call.arguments[ARGUMENT_KEY_APPNAME]; // NSString *appName = call.arguments[@"appName"];
// NSNumber *extInt = call.arguments[ARGUMENT_KEY_EXTINT]; // NSNumber *extInt = call.arguments[@"extInt"];
if (scene.intValue == SCENE_QQ) { if (scene.intValue == SCENE_QQ) {
QQApiAudioObject *object = nil; QQApiAudioObject *object = nil;
NSURL *imageUrl = [NSURL URLWithString:imageUri]; NSURL *imageUrl = [NSURL URLWithString:imageUri];
if ([SCHEME_FILE isEqualToString:imageUrl.scheme]) { if ([@"file" isEqualToString:imageUrl.scheme]) {
NSData *imageData = [NSData dataWithContentsOfFile:imageUrl.path]; NSData *imageData = [NSData dataWithContentsOfFile:imageUrl.path];
object = [QQApiAudioObject objectWithURL:[NSURL URLWithString:targetUrl] object = [QQApiAudioObject objectWithURL:[NSURL URLWithString:targetUrl]
title:title title:title
@ -233,17 +196,17 @@ static NSString *const SCHEME_FILE = @"file";
} }
- (void)shareWebpage:(FlutterMethodCall *)call result:(FlutterResult)result { - (void)shareWebpage:(FlutterMethodCall *)call result:(FlutterResult)result {
NSNumber *scene = call.arguments[ARGUMENT_KEY_SCENE]; NSNumber *scene = call.arguments[@"scene"];
NSString *title = call.arguments[ARGUMENT_KEY_TITLE]; NSString *title = call.arguments[@"title"];
NSString *summary = call.arguments[ARGUMENT_KEY_SUMMARY]; NSString *summary = call.arguments[@"summary"];
NSString *imageUri = call.arguments[ARGUMENT_KEY_IMAGEURI]; NSString *imageUri = call.arguments[@"imageUri"];
NSString *targetUrl = call.arguments[ARGUMENT_KEY_TARGETURL]; NSString *targetUrl = call.arguments[@"targetUrl"];
// NSString *appName = call.arguments[ARGUMENT_KEY_APPNAME]; // NSString *appName = call.arguments[@"appName"];
// NSNumber *extInt = call.arguments[ARGUMENT_KEY_EXTINT]; // NSNumber *extInt = call.arguments[@"extInt"];
QQApiNewsObject *object = nil; QQApiNewsObject *object = nil;
NSURL *imageUrl = [NSURL URLWithString:imageUri]; NSURL *imageUrl = [NSURL URLWithString:imageUri];
if ([SCHEME_FILE isEqualToString:imageUrl.scheme]) { if ([@"file" isEqualToString:imageUrl.scheme]) {
NSData *imageData = [NSData dataWithContentsOfFile:imageUrl.path]; NSData *imageData = [NSData dataWithContentsOfFile:imageUrl.path];
object = [QQApiNewsObject objectWithURL:[NSURL URLWithString:targetUrl] object = [QQApiNewsObject objectWithURL:[NSURL URLWithString:targetUrl]
title:title title:title
@ -319,19 +282,19 @@ static NSString *const SCHEME_FILE = @"file";
ceil(_oauth.expirationDate.timeIntervalSinceNow); // 向上取整 ceil(_oauth.expirationDate.timeIntervalSinceNow); // 向上取整
long long createAt = [[NSDate date] timeIntervalSince1970] * 1000.0; long long createAt = [[NSDate date] timeIntervalSince1970] * 1000.0;
[dictionary setValue:[NSNumber numberWithInt:RET_SUCCESS] [dictionary setValue:[NSNumber numberWithInt:RET_SUCCESS]
forKey:ARGUMENT_KEY_RESULT_RET]; forKey:@"ret"];
[dictionary setValue:openId forKey:ARGUMENT_KEY_RESULT_OPENID]; [dictionary setValue:openId forKey:@"openid"];
[dictionary setValue:accessToken forKey:ARGUMENT_KEY_RESULT_ACCESS_TOKEN]; [dictionary setValue:accessToken forKey:@"access_token"];
[dictionary setValue:[NSNumber numberWithLongLong:expiresIn] [dictionary setValue:[NSNumber numberWithLongLong:expiresIn]
forKey:ARGUMENT_KEY_RESULT_EXPIRES_IN]; forKey:@"expires_in"];
[dictionary setValue:[NSNumber numberWithLongLong:createAt] [dictionary setValue:[NSNumber numberWithLongLong:createAt]
forKey:ARGUMENT_KEY_RESULT_CREATE_AT]; forKey:@"create_at"];
} else { } else {
// 登录失败 // 登录失败
[dictionary setValue:[NSNumber numberWithInt:RET_COMMON] [dictionary setValue:[NSNumber numberWithInt:RET_COMMON]
forKey:ARGUMENT_KEY_RESULT_RET]; forKey:@"ret"];
} }
[_channel invokeMethod:METHOD_ONLOGINRESP arguments:dictionary]; [_channel invokeMethod:@"onLoginResp" arguments:dictionary];
} }
- (void)tencentDidNotLogin:(BOOL)cancelled { - (void)tencentDidNotLogin:(BOOL)cancelled {
@ -339,21 +302,21 @@ static NSString *const SCHEME_FILE = @"file";
if (cancelled) { if (cancelled) {
// 取消登录 // 取消登录
[dictionary setValue:[NSNumber numberWithInt:RET_USERCANCEL] [dictionary setValue:[NSNumber numberWithInt:RET_USERCANCEL]
forKey:ARGUMENT_KEY_RESULT_RET]; forKey:@"ret"];
} else { } else {
// 登录失败 // 登录失败
[dictionary setValue:[NSNumber numberWithInt:RET_COMMON] [dictionary setValue:[NSNumber numberWithInt:RET_COMMON]
forKey:ARGUMENT_KEY_RESULT_RET]; forKey:@"ret"];
} }
[_channel invokeMethod:METHOD_ONLOGINRESP arguments:dictionary]; [_channel invokeMethod:@"onLoginResp" arguments:dictionary];
} }
- (void)tencentDidNotNetWork { - (void)tencentDidNotNetWork {
// 登录失败 // 登录失败
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setValue:[NSNumber numberWithInt:RET_COMMON] [dictionary setValue:[NSNumber numberWithInt:RET_COMMON]
forKey:ARGUMENT_KEY_RESULT_RET]; forKey:@"ret"];
[_channel invokeMethod:METHOD_ONLOGINRESP arguments:dictionary]; [_channel invokeMethod:@"onLoginResp" arguments:dictionary];
} }
#pragma mark - QQApiInterfaceDelegate #pragma mark - QQApiInterfaceDelegate
@ -368,23 +331,23 @@ static NSString *const SCHEME_FILE = @"file";
case 0: case 0:
// 分享成功 // 分享成功
[dictionary setValue:[NSNumber numberWithInt:RET_SUCCESS] [dictionary setValue:[NSNumber numberWithInt:RET_SUCCESS]
forKey:ARGUMENT_KEY_RESULT_RET]; forKey:@"ret"];
break; break;
case -4: case -4:
// 用户取消 // 用户取消
[dictionary setValue:[NSNumber numberWithInt:RET_USERCANCEL] [dictionary setValue:[NSNumber numberWithInt:RET_USERCANCEL]
forKey:ARGUMENT_KEY_RESULT_RET]; forKey:@"ret"];
break; break;
default: default:
[dictionary setValue:[NSNumber numberWithInt:RET_COMMON] [dictionary setValue:[NSNumber numberWithInt:RET_COMMON]
forKey:ARGUMENT_KEY_RESULT_RET]; forKey:@"ret"];
NSString *errorMsg = NSString *errorMsg =
[NSString stringWithFormat:@"result: %@, description: %@.", [NSString stringWithFormat:@"result: %@, description: %@.",
resp.result, resp.errorDescription]; resp.result, resp.errorDescription];
[dictionary setValue:errorMsg forKey:ARGUMENT_KEY_RESULT_MSG]; [dictionary setValue:errorMsg forKey:@"msg"];
break; break;
} }
[_channel invokeMethod:METHOD_ONSHARERESP arguments:dictionary]; [_channel invokeMethod:@"onShareResp" arguments:dictionary];
} }
} }

@ -1,10 +1,10 @@
# #
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint tencent_kit.podspec' to validate before publishing. # Run `pod lib lint tencent_kit.podspec` to validate before publishing.
# #
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'tencent_kit' s.name = 'tencent_kit'
s.version = '3.1.0' s.version = '4.0.0'
s.summary = 'A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Tencent SDKs.' s.summary = 'A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Tencent SDKs.'
s.description = <<-DESC s.description = <<-DESC
A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Tencent SDKs. A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Tencent SDKs.
@ -16,16 +16,16 @@ A powerful Flutter plugin allowing developers to auth/share with natvie Android
s.source_files = 'Classes/**/*' s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h' s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter' s.dependency 'Flutter'
s.platform = :ios, '8.0' s.platform = :ios, '9.0'
# v3.5.10 # v3.5.11
s.subspec 'vendor' do |sp| s.subspec 'vendor' do |sp|
sp.vendored_frameworks = 'Libraries/*.framework' sp.vendored_frameworks = 'Libraries/*.framework'
sp.frameworks = 'Security', 'SystemConfiguration', 'CoreGraphics', 'CoreTelephony', 'WebKit' sp.frameworks = 'Security', 'SystemConfiguration', 'CoreGraphics', 'CoreTelephony', 'WebKit'
sp.libraries = 'iconv', 'sqlite3', 'stdc++', 'z' sp.libraries = 'iconv', 'sqlite3', 'stdc++', 'z'
sp.requires_arc = true sp.requires_arc = true
end end
# Flutter.framework does not contain a i386 slice. # Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
end end

@ -1,192 +1,103 @@
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:tencent_kit/src/model/resp.dart'; import 'package:tencent_kit/src/model/resp.dart';
import 'package:tencent_kit/src/tencent_constant.dart'; import 'package:tencent_kit/src/tencent_constant.dart';
/// import 'tencent_kit_platform_interface.dart';
class Tencent { class Tencent {
///
Tencent._(); Tencent._();
static Tencent get instance => _instance;
static final Tencent _instance = Tencent._();
static const String _METHOD_REGISTERAPP = 'registerApp';
static const String _METHOD_ISQQINSTALLED = 'isQQInstalled';
static const String _METHOD_ISTIMINSTALLED = 'isTIMInstalled';
static const String _METHOD_LOGIN = 'login';
static const String _METHOD_LOGOUT = 'logout';
static const String _METHOD_SHAREMOOD = 'shareMood';
static const String _METHOD_SHARETEXT = 'shareText';
static const String _METHOD_SHAREIMAGE = 'shareImage';
static const String _METHOD_SHAREMUSIC = 'shareMusic';
static const String _METHOD_SHAREWEBPAGE = 'shareWebpage';
static const String _METHOD_ONLOGINRESP = 'onLoginResp';
static const String _METHOD_ONSHARERESP = 'onShareResp';
static const String _ARGUMENT_KEY_APPID = 'appId';
static const String _ARGUMENT_KEY_UNIVERSALLINK = 'universalLink';
static const String _ARGUMENT_KEY_SCOPE = 'scope';
static const String _ARGUMENT_KEY_SCENE = 'scene';
static const String _ARGUMENT_KEY_TITLE = 'title';
static const String _ARGUMENT_KEY_SUMMARY = 'summary';
static const String _ARGUMENT_KEY_IMAGEURI = 'imageUri';
static const String _ARGUMENT_KEY_IMAGEURIS = 'imageUris';
static const String _ARGUMENT_KEY_VIDEOURI = 'videoUri';
static const String _ARGUMENT_KEY_MUSICURL = 'musicUrl';
static const String _ARGUMENT_KEY_TARGETURL = 'targetUrl';
static const String _ARGUMENT_KEY_APPNAME = 'appName';
static const String _ARGUMENT_KEY_EXTINT = 'extInt';
static const String _SCHEME_FILE = 'file';
late final MethodChannel _channel =
const MethodChannel('v7lin.github.io/tencent_kit')
..setMethodCallHandler(_handleMethod);
final StreamController<BaseResp> _respStreamController =
StreamController<BaseResp>.broadcast();
Future<dynamic> _handleMethod(MethodCall call) async {
switch (call.method) {
case _METHOD_ONLOGINRESP:
_respStreamController.add(LoginResp.fromJson(
(call.arguments as Map<dynamic, dynamic>).cast<String, dynamic>()));
break;
case _METHOD_ONSHARERESP:
_respStreamController.add(ShareMsgResp.fromJson(
(call.arguments as Map<dynamic, dynamic>).cast<String, dynamic>()));
break;
}
}
/// 设置是否已授权获取设备信息/是否同意隐私协议 /// 设置是否已授权获取设备信息/是否同意隐私协议
Future<void> setIsPermissionGranted({ static Future<void> setIsPermissionGranted({
required bool granted, required bool granted,
String? buildModel /* android.os.Build.MODEL */, String? buildModel /* android.os.Build.MODEL */,
}) { }) {
return _channel.invokeMethod( return TencentKitPlatform.instance.setIsPermissionGranted(
'setIsPermissionGranted', granted: granted,
<String, dynamic>{ buildModel: buildModel,
'granted': granted,
if (buildModel?.isNotEmpty ?? false) 'build_model': buildModel,
},
); );
} }
/// 向 Open_SDK 注册 /// 向 Open_SDK 注册
Future<void> registerApp({ static Future<void> registerApp({
required String appId, required String appId,
String? universalLink, String? universalLink,
}) { }) {
return _channel.invokeMethod<void>( return TencentKitPlatform.instance.registerApp(
_METHOD_REGISTERAPP, appId: appId,
<String, dynamic>{ universalLink: universalLink,
_ARGUMENT_KEY_APPID: appId,
if (universalLink?.isNotEmpty ?? false)
_ARGUMENT_KEY_UNIVERSALLINK: universalLink,
},
); );
} }
/// 检查QQ是否已安装
static Future<bool> isQQInstalled() {
return TencentKitPlatform.instance.isQQInstalled();
}
/// 检查QQ是否已安装
static Future<bool> isTIMInstalled() {
return TencentKitPlatform.instance.isTIMInstalled();
}
/// ///
Stream<BaseResp> respStream() { static Stream<BaseResp> respStream() {
return _respStreamController.stream; return TencentKitPlatform.instance.respStream();
}
/// 检查QQ是否已安装
Future<bool> isQQInstalled() async {
return await _channel.invokeMethod<bool>(_METHOD_ISQQINSTALLED) ?? false;
}
/// 检查QQ是否已安装
Future<bool> isTIMInstalled() async {
return await _channel.invokeMethod<bool>(_METHOD_ISTIMINSTALLED) ?? false;
} }
/// 登录 /// 登录
Future<void> login({ static Future<void> login({
required List<String> scope, required List<String> scope,
}) { }) {
return _channel.invokeMethod<void>( return TencentKitPlatform.instance.login(scope: scope);
_METHOD_LOGIN,
<String, dynamic>{
_ARGUMENT_KEY_SCOPE: scope.join(','),
},
);
} }
/// 登出 /// 登出
Future<void> logout() { static Future<void> logout() {
return _channel.invokeMethod<void>(_METHOD_LOGOUT); return TencentKitPlatform.instance.logout();
} }
/// 分享 - 说说 /// 分享 - 说说
Future<void> shareMood({ static Future<void> shareMood({
required int scene, required int scene,
String? summary, String? summary,
List<Uri>? imageUris, List<Uri>? imageUris,
Uri? videoUri, Uri? videoUri,
}) { }) {
assert(scene == TencentScene.SCENE_QZONE); return TencentKitPlatform.instance.shareMood(
assert((summary?.isNotEmpty ?? false) || scene: scene,
((imageUris?.isNotEmpty ?? false) && summary: summary,
imageUris! imageUris: imageUris,
.every((Uri element) => element.isScheme(_SCHEME_FILE))) || videoUri: videoUri,
(videoUri != null && videoUri.isScheme(_SCHEME_FILE)));
return _channel.invokeMethod<void>(
_METHOD_SHAREMOOD,
<String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
if (summary?.isNotEmpty ?? false) _ARGUMENT_KEY_SUMMARY: summary,
if (imageUris?.isNotEmpty ?? false)
_ARGUMENT_KEY_IMAGEURIS:
imageUris!.map((Uri imageUri) => imageUri.toString()).toList(),
if (videoUri != null) _ARGUMENT_KEY_VIDEOURI: videoUri.toString(),
},
); );
} }
/// 分享 - 文本Android调用的是系统API故而不会有回调 /// 分享 - 文本Android调用的是系统API故而不会有回调
Future<void> shareText({ static Future<void> shareText({
required int scene, required int scene,
required String summary, required String summary,
}) { }) {
assert(scene == TencentScene.SCENE_QQ); return TencentKitPlatform.instance.shareText(
return _channel.invokeMethod<void>( scene: scene,
_METHOD_SHARETEXT, summary: summary,
<String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_SUMMARY: summary,
},
); );
} }
/// 分享 - 图片 /// 分享 - 图片
Future<void> shareImage({ static Future<void> shareImage({
required int scene, required int scene,
required Uri imageUri, required Uri imageUri,
String? appName, String? appName,
int extInt = TencentQZoneFlag.DEFAULT, int extInt = TencentQZoneFlag.DEFAULT,
}) { }) {
assert(scene == TencentScene.SCENE_QQ); return TencentKitPlatform.instance.shareImage(
assert(imageUri.isScheme(_SCHEME_FILE)); scene: scene,
return _channel.invokeMethod<void>( imageUri: imageUri,
_METHOD_SHAREIMAGE, appName: appName,
<String, dynamic>{ extInt: extInt,
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_IMAGEURI: imageUri.toString(),
if (appName?.isNotEmpty ?? false) _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
},
); );
} }
/// 分享 - 音乐 /// 分享 - 音乐
Future<void> shareMusic({ static Future<void> shareMusic({
required int scene, required int scene,
required String title, required String title,
String? summary, String? summary,
@ -196,24 +107,20 @@ class Tencent {
String? appName, String? appName,
int extInt = TencentQZoneFlag.DEFAULT, int extInt = TencentQZoneFlag.DEFAULT,
}) { }) {
assert(scene == TencentScene.SCENE_QQ); return TencentKitPlatform.instance.shareMusic(
return _channel.invokeMethod<void>( scene: scene,
_METHOD_SHAREMUSIC, title: title,
<String, dynamic>{ summary: summary,
_ARGUMENT_KEY_SCENE: scene, imageUri: imageUri,
_ARGUMENT_KEY_TITLE: title, musicUrl: musicUrl,
if (summary?.isNotEmpty ?? false) _ARGUMENT_KEY_SUMMARY: summary, targetUrl: targetUrl,
if (imageUri != null) _ARGUMENT_KEY_IMAGEURI: imageUri.toString(), appName: appName,
_ARGUMENT_KEY_MUSICURL: musicUrl, extInt: extInt,
_ARGUMENT_KEY_TARGETURL: targetUrl,
if (appName?.isNotEmpty ?? false) _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
},
); );
} }
/// 分享 - 网页 /// 分享 - 网页
Future<void> shareWebpage({ static Future<void> shareWebpage({
required int scene, required int scene,
required String title, required String title,
String? summary, String? summary,
@ -222,17 +129,14 @@ class Tencent {
String? appName, String? appName,
int extInt = TencentQZoneFlag.DEFAULT, int extInt = TencentQZoneFlag.DEFAULT,
}) { }) {
return _channel.invokeMethod<void>( return TencentKitPlatform.instance.shareWebpage(
_METHOD_SHAREWEBPAGE, scene: scene,
<String, dynamic>{ title: title,
_ARGUMENT_KEY_SCENE: scene, summary: summary,
_ARGUMENT_KEY_TITLE: title, imageUri: imageUri,
if (summary?.isNotEmpty ?? false) _ARGUMENT_KEY_SUMMARY: summary, targetUrl: targetUrl,
if (imageUri != null) _ARGUMENT_KEY_IMAGEURI: imageUri.toString(), appName: appName,
_ARGUMENT_KEY_TARGETURL: targetUrl, extInt: extInt,
if (appName?.isNotEmpty ?? false) _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
},
); );
} }
} }

@ -0,0 +1,201 @@
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:tencent_kit/src/model/resp.dart';
import 'package:tencent_kit/src/tencent_constant.dart';
import 'tencent_kit_platform_interface.dart';
/// An implementation of [TencentKitPlatform] that uses method channels.
class MethodChannelTencentKit extends TencentKitPlatform {
/// The method channel used to interact with the native platform.
@visibleForTesting
late final MethodChannel methodChannel = const MethodChannel('v7lin.github.io/tencent_kit')..setMethodCallHandler(_handleMethod);
final StreamController<BaseResp> _respStreamController = StreamController<BaseResp>.broadcast();
Future<dynamic> _handleMethod(MethodCall call) async {
switch (call.method) {
case 'onLoginResp':
_respStreamController.add(LoginResp.fromJson((call.arguments as Map<dynamic, dynamic>).cast<String, dynamic>()));
break;
case 'onShareResp':
_respStreamController.add(ShareMsgResp.fromJson((call.arguments as Map<dynamic, dynamic>).cast<String, dynamic>()));
break;
}
}
@override
Future<void> setIsPermissionGranted({
required bool granted,
String? buildModel /* android.os.Build.MODEL */,
}) {
return methodChannel.invokeMethod(
'setIsPermissionGranted',
<String, dynamic>{
'granted': granted,
if (buildModel?.isNotEmpty ?? false) 'build_model': buildModel,
},
);
}
@override
Future<void> registerApp({
required String appId,
String? universalLink,
}) {
return methodChannel.invokeMethod<void>(
'registerApp',
<String, dynamic>{
'appId': appId,
if (universalLink?.isNotEmpty ?? false)
'universalLink': universalLink,
},
);
}
@override
Future<bool> isQQInstalled() async {
return await methodChannel.invokeMethod<bool>('isQQInstalled') ?? false;
}
@override
Future<bool> isTIMInstalled() async {
return await methodChannel.invokeMethod<bool>('isTIMInstalled') ?? false;
}
@override
Stream<BaseResp> respStream() {
return _respStreamController.stream;
}
@override
Future<void> login({
required List<String> scope,
}) {
return methodChannel.invokeMethod<void>(
'login',
<String, dynamic>{
'scope': scope.join(','),
},
);
}
@override
Future<void> logout() {
return methodChannel.invokeMethod<void>('logout');
}
@override
Future<void> shareMood({
required int scene,
String? summary,
List<Uri>? imageUris,
Uri? videoUri,
}) {
assert(scene == TencentScene.SCENE_QZONE);
assert((summary?.isNotEmpty ?? false) ||
((imageUris?.isNotEmpty ?? false) &&
imageUris!
.every((Uri element) => element.isScheme('file'))) ||
(videoUri != null && videoUri.isScheme('file')));
return methodChannel.invokeMethod<void>(
'shareMood',
<String, dynamic>{
'scene': scene,
if (summary?.isNotEmpty ?? false) 'summary': summary,
if (imageUris?.isNotEmpty ?? false)
'imageUris':
imageUris!.map((Uri imageUri) => imageUri.toString()).toList(),
if (videoUri != null) 'videoUri': videoUri.toString(),
},
);
}
@override
Future<void> shareText({
required int scene,
required String summary,
}) {
assert(scene == TencentScene.SCENE_QQ);
return methodChannel.invokeMethod<void>(
'shareText',
<String, dynamic>{
'scene': scene,
'summary': summary,
},
);
}
@override
Future<void> shareImage({
required int scene,
required Uri imageUri,
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
assert(scene == TencentScene.SCENE_QQ);
assert(imageUri.isScheme('file'));
return methodChannel.invokeMethod<void>(
'shareImage',
<String, dynamic>{
'scene': scene,
'imageUri': imageUri.toString(),
if (appName?.isNotEmpty ?? false) 'appName': appName,
'extInt': extInt,
},
);
}
@override
Future<void> shareMusic({
required int scene,
required String title,
String? summary,
Uri? imageUri,
required String musicUrl,
required String targetUrl,
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
assert(scene == TencentScene.SCENE_QQ);
return methodChannel.invokeMethod<void>(
'shareMusic',
<String, dynamic>{
'scene': scene,
'title': title,
if (summary?.isNotEmpty ?? false) 'summary': summary,
if (imageUri != null) 'imageUri': imageUri.toString(),
'musicUrl': musicUrl,
'targetUrl': targetUrl,
if (appName?.isNotEmpty ?? false) 'appName': appName,
'extInt': extInt,
},
);
}
@override
Future<void> shareWebpage({
required int scene,
required String title,
String? summary,
Uri? imageUri,
required String targetUrl,
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
return methodChannel.invokeMethod<void>(
'shareWebpage',
<String, dynamic>{
'scene': scene,
'title': title,
if (summary?.isNotEmpty ?? false) 'summary': summary,
if (imageUri != null) 'imageUri': imageUri.toString(),
'targetUrl': targetUrl,
if (appName?.isNotEmpty ?? false) 'appName': appName,
'extInt': extInt,
},
);
}
}

@ -0,0 +1,113 @@
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:tencent_kit/src/model/resp.dart';
import 'package:tencent_kit/src/tencent_constant.dart';
import 'tencent_kit_method_channel.dart';
abstract class TencentKitPlatform extends PlatformInterface {
/// Constructs a TencentKitPlatform.
TencentKitPlatform() : super(token: _token);
static final Object _token = Object();
static TencentKitPlatform _instance = MethodChannelTencentKit();
/// The default instance of [TencentKitPlatform] to use.
///
/// Defaults to [MethodChannelTencentKit].
static TencentKitPlatform get instance => _instance;
/// Platform-specific implementations should set this with their own
/// platform-specific class that extends [TencentKitPlatform] when
/// they register themselves.
static set instance(TencentKitPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
Future<void> setIsPermissionGranted({
required bool granted,
String? buildModel /* android.os.Build.MODEL */,
}) {
throw UnimplementedError('setIsPermissionGranted({required granted, buildModel}) has not been implemented.');
}
Future<void> registerApp({
required String appId,
String? universalLink,
}) {
throw UnimplementedError('registerApp({required appId, universalLink}) has not been implemented.');
}
Future<bool> isQQInstalled() {
throw UnimplementedError('isQQInstalled() has not been implemented.');
}
Future<bool> isTIMInstalled() {
throw UnimplementedError('isTIMInstalled() has not been implemented.');
}
Stream<BaseResp> respStream() {
throw UnimplementedError('respStream() has not been implemented.');
}
Future<void> login({
required List<String> scope,
}) {
throw UnimplementedError('login({required scope}) has not been implemented.');
}
Future<void> logout() {
throw UnimplementedError('logout() has not been implemented.');
}
Future<void> shareMood({
required int scene,
String? summary,
List<Uri>? imageUris,
Uri? videoUri,
}) {
throw UnimplementedError('shareMood({required scene, summary, imageUris, videoUri}) has not been implemented.');
}
Future<void> shareText({
required int scene,
required String summary,
}) {
throw UnimplementedError('shareText({required scene, required summary}) has not been implemented.');
}
Future<void> shareImage({
required int scene,
required Uri imageUri,
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
throw UnimplementedError('shareImage({required scene, required imageUri, appName, extInt}) has not been implemented.');
}
Future<void> shareMusic({
required int scene,
required String title,
String? summary,
Uri? imageUri,
required String musicUrl,
required String targetUrl,
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
throw UnimplementedError('shareMusic({required scene, required title, summary, imageUri, required musicUrl, required targetUrl, appName, extInt}) has not been implemented.');
}
Future<void> shareWebpage({
required int scene,
required String title,
String? summary,
Uri? imageUri,
required String targetUrl,
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
throw UnimplementedError('shareWebpage({required scene, required title, summary, imageUri, required targetUrl, appName, extInt}) has not been implemented.');
}
}

@ -7,21 +7,21 @@ packages:
name: _fe_analyzer_shared name: _fe_analyzer_shared
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "18.0.0" version: "39.0.0"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.2.0" version: "4.0.0"
args: args:
dependency: transitive dependency: transitive
description: description:
name: args name: args
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.3.1"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -42,56 +42,56 @@ packages:
name: build name: build
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.3.0"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
name: build_config name: build_config
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.4.7" version: "1.0.0"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.10" version: "3.1.0"
build_resolvers: build_resolvers:
dependency: transitive dependency: transitive
description: description:
name: build_resolvers name: build_resolvers
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.0.8"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.12.2" version: "2.1.10"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "6.1.12" version: "7.2.3"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
name: built_collection name: built_collection
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "5.0.0" version: "5.1.1"
built_value: built_value:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "8.0.3" version: "8.3.0"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@ -113,13 +113,6 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.1" version: "2.0.1"
cli_util:
dependency: transitive
description:
name: cli_util
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.0"
clock: clock:
dependency: transitive dependency: transitive
description: description:
@ -133,87 +126,101 @@ packages:
name: code_builder name: code_builder
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.7.0" version: "4.1.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.15.0" version: "1.16.0"
convert: convert:
dependency: transitive dependency: transitive
description: description:
name: convert name: convert
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.0" version: "3.0.1"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
name: crypto name: crypto
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.0" version: "3.0.2"
dart_style: dart_style:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.3.14" version: "2.2.3"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
name: fake_async name: fake_async
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.2.0" version: "1.3.0"
file: file:
dependency: transitive dependency: transitive
description: description:
name: file name: file
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "6.1.0" version: "6.1.2"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
name: fixnum name: fixnum
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.0" version: "1.0.1"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.1"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.2"
glob: glob:
dependency: transitive dependency: transitive
description: description:
name: glob name: glob
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.0.2"
graphs: graphs:
dependency: transitive dependency: transitive
description: description:
name: graphs name: graphs
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.0" version: "2.1.0"
http_multi_server: http_multi_server:
dependency: transitive dependency: transitive
description: description:
name: http_multi_server name: http_multi_server
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.0" version: "3.2.0"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
@ -227,35 +234,42 @@ packages:
name: io name: io
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.0" version: "1.0.3"
js: js:
dependency: transitive dependency: transitive
description: description:
name: js name: js
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.6.3" version: "0.6.4"
json_annotation: json_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
name: json_annotation name: json_annotation
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "4.0.0" version: "4.5.0"
json_serializable: json_serializable:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: json_serializable name: json_serializable
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "4.0.3" version: "6.2.0"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0"
logging: logging:
dependency: transitive dependency: transitive
description: description:
name: logging name: logging
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.0" version: "1.0.2"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -263,6 +277,13 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.12.11" version: "0.12.11"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.4"
meta: meta:
dependency: transitive dependency: transitive
description: description:
@ -276,28 +297,28 @@ packages:
name: mime name: mime
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.0" version: "1.0.2"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
name: package_config name: package_config
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.0.2"
path: path:
dependency: transitive dependency: transitive
description: description:
name: path name: path
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.8.0" version: "1.8.1"
pedantic: plugin_platform_interface:
dependency: "direct dev" dependency: "direct main"
description: description:
name: pedantic name: plugin_platform_interface
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.11.0" version: "2.1.2"
pool: pool:
dependency: transitive dependency: transitive
description: description:
@ -311,21 +332,21 @@ packages:
name: pub_semver name: pub_semver
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.1.1"
pubspec_parse: pubspec_parse:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.0" version: "1.2.0"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
name: shelf name: shelf
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.0" version: "1.3.0"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
@ -344,14 +365,21 @@ packages:
name: source_gen name: source_gen
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.9.10+4" version: "1.2.2"
source_helper:
dependency: transitive
description:
name: source_helper
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.2"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.8.1" version: "1.8.2"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@ -393,7 +421,7 @@ packages:
name: test_api name: test_api
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.4.3" version: "0.4.9"
timing: timing:
dependency: transitive dependency: transitive
description: description:
@ -407,35 +435,35 @@ packages:
name: typed_data name: typed_data
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.3.0" version: "1.3.1"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.1" version: "2.1.2"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:
name: watcher name: watcher
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.0" version: "1.0.1"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
name: web_socket_channel name: web_socket_channel
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.2.0"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:
name: yaml name: yaml
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.1.0" version: "3.1.1"
sdks: sdks:
dart: ">=2.14.0 <3.0.0" dart: ">=2.17.0 <3.0.0"
flutter: ">=1.20.0" flutter: ">=2.5.0"

@ -1,24 +1,24 @@
name: tencent_kit name: tencent_kit
description: A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Tencent SDKs. description: A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Tencent SDKs.
version: 3.1.0 version: 4.0.0
# author: v7lin <v7lin@qq.com> # author: v7lin <v7lin@qq.com>
homepage: https://github.com/v7lin/fake_tencent homepage: https://github.com/RxReader/tencent_kit.git
environment: environment:
sdk: ">=2.12.0 <3.0.0" sdk: ">=2.17.0 <3.0.0"
flutter: ">=1.20.0" flutter: ">=2.5.0"
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
plugin_platform_interface: ^2.0.2
json_annotation: ^4.0.0 json_annotation: ^4.5.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
flutter_lints: ^2.0.0
pedantic:
build_runner: build_runner:
json_serializable: json_serializable:
@ -26,11 +26,17 @@ dev_dependencies:
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter. # The following section is specific to Flutter packages.
flutter: flutter:
# This section identifies this Flutter project as a plugin project. # This section identifies this Flutter project as a plugin project.
# The 'pluginClass' and Android 'package' identifiers should not ordinarily # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
# be modified. They are used by the tooling to maintain consistency when # which should be registered in the plugin registry. This is required for
# using method channels.
# The Android 'package' specifies package in which the registered class is.
# This is required for using method channels on Android.
# The 'ffiPlugin' specifies that native code should be built and bundled.
# This is required for using `dart:ffi`.
# All these are used by the tooling to maintain consistency when
# adding or updating assets for this project. # adding or updating assets for this project.
plugin: plugin:
platforms: platforms:
@ -49,7 +55,7 @@ flutter:
# https://flutter.dev/assets-and-images/#from-packages # https://flutter.dev/assets-and-images/#from-packages
# #
# An image asset can refer to one or more resolution-specific "variants", see # An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware. # https://flutter.dev/assets-and-images/#resolution-aware
# To add custom fonts to your plugin package, add a fonts section here, # To add custom fonts to your plugin package, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a # in this "flutter" section. Each entry in this list should have a

@ -0,0 +1,27 @@
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tencent_kit/src/tencent_kit_method_channel.dart';
void main() {
final MethodChannelTencentKit platform = MethodChannelTencentKit();
const MethodChannel channel = MethodChannel('v7lin.github.io/tencent_kit');
TestWidgetsFlutterBinding.ensureInitialized();
setUp(() {
channel.setMockMethodCallHandler((MethodCall methodCall) async {
switch(methodCall.method) {
case 'isQQInstalled':
return true;
}
});
});
tearDown(() {
channel.setMockMethodCallHandler(null);
});
test('getPlatformVersion', () async {
expect(await platform.isQQInstalled(), true);
});
}

@ -1,94 +0,0 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:pedantic/pedantic.dart';
import 'package:tencent_kit/tencent_kit.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
const MethodChannel channel = MethodChannel('v7lin.github.io/tencent_kit');
setUp(() {
channel.setMockMethodCallHandler((MethodCall call) async {
switch (call.method) {
case 'registerApp':
return null;
case 'isQQInstalled':
return true;
case 'isTIMInstalled':
return true;
case 'login':
unawaited(channel.binaryMessenger.handlePlatformMessage(
channel.name,
channel.codec.encodeMethodCall(
MethodCall('onLoginResp', json.decode('{"ret":-2}'))),
(ByteData? data) {
// mock success
},
));
return null;
case 'logout':
return null;
case 'shareMood':
case 'shareText':
case 'shareImage':
case 'shareMusic':
case 'shareWebpage':
unawaited(channel.binaryMessenger.handlePlatformMessage(
channel.name,
channel.codec.encodeMethodCall(
MethodCall('onShareResp', json.decode('{"ret":0}'))),
(ByteData? data) {
// mock success
},
));
return null;
}
throw PlatformException(code: '0', message: '想啥呢升级插件不想升级Mock');
});
});
tearDown(() {
channel.setMockMethodCallHandler(null);
});
test('isQQInstalled', () async {
expect(await Tencent.instance.isQQInstalled(), true);
});
test('isTIMInstalled', () async {
expect(await Tencent.instance.isTIMInstalled(), true);
});
test('login', () async {
final StreamSubscription<BaseResp> subs =
Tencent.instance.respStream().listen((BaseResp resp) {
expect(resp.runtimeType, LoginResp);
expect(resp.ret, BaseResp.RET_USERCANCEL);
});
await Tencent.instance.login(
scope: <String>[
TencentScope.GET_SIMPLE_USERINFO,
],
);
await Future<void>.delayed(const Duration(seconds: 1));
await subs.cancel();
});
test('share', () async {
final StreamSubscription<BaseResp> subs =
Tencent.instance.respStream().listen((BaseResp resp) {
expect(resp.runtimeType, ShareMsgResp);
expect(resp.ret, BaseResp.RET_SUCCESS);
});
await Tencent.instance.shareMood(
scene: TencentScene.SCENE_QZONE,
summary: 'share text',
);
await Future<void>.delayed(const Duration(seconds: 1));
await subs.cancel();
});
}

123
test/tencent_test.dart Normal file

@ -0,0 +1,123 @@
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'package:tencent_kit/src/tencent_constant.dart';
import 'package:tencent_kit/src/tencent_kit_method_channel.dart';
import 'package:tencent_kit/src/tencent_kit_platform_interface.dart';
import 'package:tencent_kit/tencent_kit.dart';
class MockTencentKitPlatform with MockPlatformInterfaceMixin implements TencentKitPlatform {
@override
Future<void> setIsPermissionGranted({
required bool granted,
String? buildModel,
}) {
throw UnimplementedError();
}
@override
Future<void> registerApp({
required String appId,
String? universalLink,
}) async {
throw UnimplementedError();
}
@override
Future<bool> isQQInstalled() {
return Future<bool>.value(true);
}
@override
Future<bool> isTIMInstalled() {
throw UnimplementedError();
}
@override
Stream<BaseResp> respStream() {
throw UnimplementedError();
}
@override
Future<void> login({
required List<String> scope,
}) {
throw UnimplementedError();
}
@override
Future<void> logout() {
throw UnimplementedError();
}
@override
Future<void> shareImage({
required int scene,
required Uri imageUri,
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
throw UnimplementedError();
}
@override
Future<void> shareMood({
required int scene,
String? summary,
List<Uri>? imageUris,
Uri? videoUri,
}) {
throw UnimplementedError();
}
@override
Future<void> shareMusic({
required int scene,
required String title,
String? summary,
Uri? imageUri,
required String musicUrl,
required String targetUrl,
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
throw UnimplementedError();
}
@override
Future<void> shareText({
required int scene,
required String summary,
}) {
throw UnimplementedError();
}
@override
Future<void> shareWebpage({
required int scene,
required String title,
String? summary,
Uri? imageUri,
required String targetUrl,
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
throw UnimplementedError();
}
}
void main() {
final TencentKitPlatform initialPlatform = TencentKitPlatform.instance;
test('$MethodChannelTencentKit is the default instance', () {
expect(initialPlatform, isInstanceOf<MethodChannelTencentKit>());
});
test('getPlatformVersion', () async {
final MockTencentKitPlatform fakePlatform = MockTencentKitPlatform();
TencentKitPlatform.instance = fakePlatform;
expect(await Tencent.isQQInstalled(), true);
});
}