升级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
View File

@ -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
View File

@ -1,11 +1,30 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.dart_tool/
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
.packages
.pub/
build/
#
# IntelliJ related
*.iml
*.ipr
*.iws
.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/

View File

@ -1,10 +1,33 @@
# 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.
# This file should be version controlled.
version:
revision: b041144f833e05cf463b8887fa12efdec9493488
revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
channel: stable
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'

View File

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

View File

@ -26,15 +26,6 @@ flutter版腾讯(QQ)SDK
## 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
android {
defaultConfig{
@ -121,24 +112,25 @@ Capabilities -> Associated Domain -> Domain -> applinks:${your applinks}
|QZone|||||||
* break change
* 3.1.0: setIsPermissionGranted /
* 3.0.0:
* 2.1.0: nullsafety & Android embedding v1 & Tencent
* 4.0.0:
* 3.1.0: setIsPermissionGranted /
* 3.0.0:
* 2.1.0: nullsafety & Android embedding v1 & Tencent
* compat
* flutter 2.5 [issues/54](https://github.com/RxReader/tencent_kit/issues/54)
```
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
# Flutter 2.5
target.build_configurations.each do |config|
# config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'i386 arm64'
end
* flutter 2.5 [issues/54](https://github.com/RxReader/tencent_kit/issues/54)
```
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
# Flutter 2.5
target.build_configurations.each do |config|
# config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'i386 arm64'
end
end
```
end
```
* snapshot

View File

@ -5,39 +5,44 @@
#
# For a list of lints, see: http://dart-lang.github.io/linter/lints/
# 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,
# which should be kept in sync with 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/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,
# Android Studio, and the `flutter analyze` command.
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
language:
strict-raw-types: true
errors:
# treat missing required parameters as a warning (not a hint)
missing_required_param: warning
# treat missing returns as a warning (not a hint)
missing_return: warning
# allow having TODOs in the code
# allow having TODO comments in the code
todo: ignore
# 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)
deprecated_member_use_from_same_package: ignore
# Ignore analyzer hints for updating pubspecs when using Future or
# Stream and not importing dart:async
# Please see https://github.com/flutter/flutter/pull/24528 for details.
sdk_version_async_exported_from_core: ignore
# TODO(ianh): https://github.com/flutter/flutter/issues/74381
# Clean up existing unnecessary imports, and remove line to ignore.
unnecessary_import: ignore
# Turned off until null-safe rollout is complete.
unnecessary_null_comparison: ignore
exclude:
- "bin/cache/**"
# Ignore protoc generated files
- "dev/conductor/lib/proto/*"
#
- "lib/*.g.dart"
- "lib/**/*.g.dart"
linter:
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_require_non_null_named_parameters
- always_specify_types
- always_use_package_imports # we do this commonly
# - always_use_package_imports # we do this commonly
- annotate_overrides
# - avoid_annotating_with_dynamic # conflicts with always_specify_types
# - avoid_as # required for implicit-casts: true
- avoid_bool_literals_in_conditional_expressions
# - avoid_catches_without_on_clauses # we do this commonly
# - avoid_catching_errors # we do this commonly
# - avoid_catches_without_on_clauses # blocked on https://github.com/dart-lang/linter/issues/3023
# - avoid_catching_errors # blocked on https://github.com/dart-lang/linter/issues/3023
- 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_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_final_parameters # incompatible with prefer_final_parameters
- avoid_function_literals_in_foreach_calls
# - avoid_implementing_value_types # not yet tested
- avoid_implementing_value_types
- 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_positional_boolean_parameters # not yet tested
# - avoid_print # 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
# - 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_renaming_method_parameters
- avoid_return_types_on_setters
# - avoid_returning_null # there are plenty of valid reasons to return null
# - avoid_returning_null_for_future # not yet tested
# - avoid_returning_null # still violated by some pre-nnbd code that we haven't yet migrated
- avoid_returning_null_for_future
- avoid_returning_null_for_void
# - avoid_returning_this # there are plenty of valid reasons to return this
# - avoid_setters_without_getters # not yet tested
# - 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
- avoid_shadowing_type_parameters
- avoid_single_cascade_in_expression_statements
- avoid_slow_async_io
# - avoid_type_to_string # we do this commonly
- avoid_type_to_string
- avoid_types_as_parameter_names
# - avoid_types_on_closure_parameters # conflicts with always_specify_types
# - avoid_unnecessary_containers # not yet tested
- avoid_unnecessary_containers
- avoid_unused_constructor_parameters
- 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
- camel_case_extensions
- camel_case_types
- cancel_subscriptions
# - cascade_invocations # not yet tested
# - cascade_invocations # doesn't match the typical style of this repo
- cast_nullable_to_non_nullable
# - 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
- control_flow_in_finally
# - 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
# - 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_constructor_bodies
- empty_statements
- eol_at_end_of_file
- exhaustive_cases
- file_names # not yet tested
- file_names
- flutter_style_todos
- hash_and_equals
- implementation_imports
@ -117,24 +128,28 @@ linter:
- leading_newlines_in_multiline_strings
- library_names
- library_prefixes
- library_private_types_in_public_api
# - lines_longer_than_80_chars # not required by flutter style
- list_remove_unrelated_type
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181
# - missing_whitespace_between_adjacent_strings # not yet tested
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/linter/issues/453
- missing_whitespace_between_adjacent_strings
- no_adjacent_strings_in_list
# - no_default_cases # too many false positives
- no_default_cases
- no_duplicate_case_values
- no_leading_underscores_for_library_prefixes
- no_leading_underscores_for_local_identifiers
- no_logic_in_create_state
# - no_runtimeType_toString # ok in tests; we enable this only in packages/
- non_constant_identifier_names
- noop_primitive_operations
- null_check_on_nullable_type_parameter
# - null_closures # not required by flutter style
- null_closures
# - omit_local_variable_types # opposite of always_specify_types
# - 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
- package_api_docs
# - package_names # non conforming packages in sdk
- package_names
- package_prefixed_library_names
# - parameter_assignments # we do this commonly
- prefer_adjacent_string_concatenation
@ -142,10 +157,10 @@ linter:
# - prefer_asserts_with_message # not required by flutter style
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_const_constructors
# - prefer_const_constructors
- prefer_const_constructors_in_immutables
- 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_contains
# - prefer_double_quotes # opposite of prefer_single_quotes
@ -154,33 +169,38 @@ linter:
- prefer_final_fields
- prefer_final_in_for_each
- 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_foreach
# - prefer_function_declarations_over_variables # not yet tested
- prefer_function_declarations_over_variables
- prefer_generic_function_type_aliases
- prefer_if_elements_to_conditional_expressions
- prefer_if_null_operators
- prefer_initializing_formals
- prefer_inlined_adds
# - prefer_int_literals # not yet tested
# - prefer_interpolation_to_compose_strings # 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
- prefer_is_empty
- prefer_is_not_empty
- prefer_is_not_operator
- prefer_iterable_whereType
# - prefer_mixin # https://github.com/dart-lang/language/issues/32
# - prefer_null_aware_operators # disable until NNBD, see https://github.com/flutter/flutter/pull/32711#issuecomment-492930932
# - prefer_relative_imports # not yet tested
# - prefer_mixin # Has false positives, see https://github.com/dart-lang/linter/issues/3018
# - prefer_null_aware_method_calls # "call()" is confusing to people new to the language since it's not documented anywhere
- prefer_null_aware_operators
# - prefer_relative_imports
- prefer_single_quotes
- prefer_spread_collections
- prefer_typing_uninitialized_variables
- 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
- 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
# - sort_child_properties_last # not yet tested
- sort_child_properties_last
- sort_constructors_first
# - sort_pub_dependencies # prevents separating pinned transitive dependencies
- sort_unnamed_constructors_first
@ -189,36 +209,43 @@ linter:
- tighten_type_of_initializing_formals
# - type_annotate_public_apis # subset of always_specify_types
- type_init_formals
- unawaited_futures # too many false positives
# - unnecessary_await_in_return # not yet tested
# - unawaited_futures # too many false positives, especially with the way AnimationController works
- unnecessary_await_in_return
- unnecessary_brace_in_string_interps
- unnecessary_const
- unnecessary_constructor_name
# - unnecessary_final # conflicts with prefer_final_locals
- unnecessary_getters_setters
# - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498
- unnecessary_late
- unnecessary_new
- unnecessary_null_aware_assignments
# - unnecessary_null_checks # not yet tested
- unnecessary_null_checks
- unnecessary_null_in_if_null_operators
- unnecessary_nullable_for_final_variable_declarations
- unnecessary_overrides
- 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_string_escapes
- unnecessary_string_interpolations
- unnecessary_this
- 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_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_key_in_widget_constructors # not yet tested
- use_key_in_widget_constructors
- use_late_for_private_fields_and_variables
- use_named_constants
- use_raw_strings
- 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_test_throws_matchers
# - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
- valid_regexps
- void_checks

1
android/.gitignore vendored
View File

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

View File

@ -1,5 +1,5 @@
group 'io.github.v7lin.tencent_kit'
version '3.1.0'
version '4.0.0'
buildscript {
repositories {
@ -8,7 +8,7 @@ buildscript {
}
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 {
compileSdkVersion 31
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// useLibrary 'org.apache.http.legacy'
resourcePrefix 'tencent_kit'
@ -54,5 +59,4 @@ android {
dependencies {
//
vendorImplementation fileTree(include: ['*.jar'], dir: 'libs')
// vendorImplementation 'com.tencent.tauth:qqopensdk:3.53.0'
}

View File

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

View File

@ -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

View File

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

View File

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

1
example/.gitignore vendored
View File

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

View File

@ -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

View File

@ -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:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

View File

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

View File

@ -27,14 +27,18 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
lintOptions {
disable 'InvalidPackage'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
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
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()

View File

@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
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.
-->
<uses-permission android:name="android.permission.INTERNET"/>

View File

@ -1,11 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.github.v7lin.tencent_kit_example">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
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
<application
android:label="tencent_kit_example"
android:icon="@mipmap/ic_launcher">
<activity

View File

@ -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>

View File

@ -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>

View File

@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- 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.Light.NoTitleBar">
<!-- 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>
</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:color/white</item>
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
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.
-->
<uses-permission android:name="android.permission.INTERNET"/>

View File

@ -6,7 +6,7 @@ buildscript {
}
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"
}
}

View File

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

View File

@ -3,4 +3,4 @@ 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
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip

View File

@ -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'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")

View File

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

View File

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

View File

@ -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"

View File

@ -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"

View File

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

View File

@ -14,7 +14,7 @@
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
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 */
/* Begin PBXCopyFilesBuildPhase section */
@ -34,10 +34,11 @@
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>"; };
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>"; };
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>"; };
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>"; };
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; };
@ -46,9 +47,8 @@
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>"; };
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>"; };
E550C709F5BE86F04F5B1E81 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; };
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>"; };
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>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -56,13 +56,32 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A47B4E2D2788685E8EC83B05 /* libPods-Runner.a in Frameworks */,
A6615287E8BD6BA6D4AE1EBE /* libPods-Runner.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase 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 */ = {
isa = PBXGroup;
children = (
@ -80,8 +99,8 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
CE8D8412E01C39B4EF41A68B /* Pods */,
D66298A71A1FFA013550393B /* Frameworks */,
251E60BE95A3A323CC8D7115 /* Pods */,
507FBD31C3A53172D6239896 /* Frameworks */,
);
sourceTree = "<group>";
};
@ -117,24 +136,6 @@
name = "Supporting Files";
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 */
/* Begin PBXNativeTarget section */
@ -142,7 +143,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
052B95C45234CE56B9E3CD76 /* [CP] Check Pods Manifest.lock */,
033F50648A25B66BDFFF058D /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
@ -206,7 +207,7 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
052B95C45234CE56B9E3CD76 /* [CP] Check Pods Manifest.lock */ = {
033F50648A25B66BDFFF058D /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -347,20 +348,13 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 78W43A3TE2;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = io.github.v7lin.tencentKitExample;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
@ -478,20 +472,13 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 78W43A3TE2;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = io.github.v7lin.tencentKitExample;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
@ -504,20 +491,13 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = 78W43A3TE2;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = io.github.v7lin.tencentKitExample;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";

View File

@ -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>

View File

@ -1,5 +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/>
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

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

View File

@ -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>

View File

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

View File

@ -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}.');
});
}
}

View File

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

View File

@ -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}.');
});
}
}

View File

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

View File

@ -2,14 +2,20 @@ name: tencent_kit_example
description: Demonstrates how to use the tencent_kit plugin.
# 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
version: 1.0.0+100
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:
flutter:
sdk: flutter
@ -19,7 +25,7 @@ dependencies:
# tencent_kit: ^x.y.z
# 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 parent directory to use the current plugin's version.
# the parent directory to use the current plugin's version.
path: ../
# The following adds the Cupertino Icons font to your application.
@ -28,13 +34,18 @@ dependencies:
flutter_cache_manager: ^3.0.0
json_annotation: ^4.0.0
json_annotation: ^4.5.0
dev_dependencies:
flutter_test:
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:
json_serializable:
@ -42,7 +53,7 @@ dev_dependencies:
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
@ -56,7 +67,7 @@ flutter:
# - images/a_dot_ham.jpeg
# 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
# https://flutter.dev/assets-and-images/#from-packages

View File

@ -1,8 +1,27 @@
// This is a basic Flutter widget test.
//
// 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
// 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
View File

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

View File

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

View File

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

View File

@ -1,10 +1,10 @@
#
# 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|
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.description = <<-DESC
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.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.platform = :ios, '8.0'
s.platform = :ios, '9.0'
# v3.5.10
# v3.5.11
s.subspec 'vendor' do |sp|
sp.vendored_frameworks = 'Libraries/*.framework'
sp.frameworks = 'Security', 'SystemConfiguration', 'CoreGraphics', 'CoreTelephony', 'WebKit'
sp.libraries = 'iconv', 'sqlite3', 'stdc++', 'z'
sp.requires_arc = true
end
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
end

View File

@ -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/tencent_constant.dart';
///
import 'tencent_kit_platform_interface.dart';
class 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,
String? buildModel /* android.os.Build.MODEL */,
}) {
return _channel.invokeMethod(
'setIsPermissionGranted',
<String, dynamic>{
'granted': granted,
if (buildModel?.isNotEmpty ?? false) 'build_model': buildModel,
},
return TencentKitPlatform.instance.setIsPermissionGranted(
granted: granted,
buildModel: buildModel,
);
}
/// 向 Open_SDK 注册
Future<void> registerApp({
static Future<void> registerApp({
required String appId,
String? universalLink,
}) {
return _channel.invokeMethod<void>(
_METHOD_REGISTERAPP,
<String, dynamic>{
_ARGUMENT_KEY_APPID: appId,
if (universalLink?.isNotEmpty ?? false)
_ARGUMENT_KEY_UNIVERSALLINK: universalLink,
},
return TencentKitPlatform.instance.registerApp(
appId: appId,
universalLink: universalLink,
);
}
/// 检查QQ是否已安装
static Future<bool> isQQInstalled() {
return TencentKitPlatform.instance.isQQInstalled();
}
/// 检查QQ是否已安装
static Future<bool> isTIMInstalled() {
return TencentKitPlatform.instance.isTIMInstalled();
}
///
Stream<BaseResp> respStream() {
return _respStreamController.stream;
}
/// 检查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;
static Stream<BaseResp> respStream() {
return TencentKitPlatform.instance.respStream();
}
/// 登录
Future<void> login({
static Future<void> login({
required List<String> scope,
}) {
return _channel.invokeMethod<void>(
_METHOD_LOGIN,
<String, dynamic>{
_ARGUMENT_KEY_SCOPE: scope.join(','),
},
);
return TencentKitPlatform.instance.login(scope: scope);
}
/// 登出
Future<void> logout() {
return _channel.invokeMethod<void>(_METHOD_LOGOUT);
static Future<void> logout() {
return TencentKitPlatform.instance.logout();
}
/// 分享 - 说说
Future<void> shareMood({
static 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(_SCHEME_FILE))) ||
(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(),
},
return TencentKitPlatform.instance.shareMood(
scene: scene,
summary: summary,
imageUris: imageUris,
videoUri: videoUri,
);
}
/// 分享 - 文本Android调用的是系统API故而不会有回调
Future<void> shareText({
static Future<void> shareText({
required int scene,
required String summary,
}) {
assert(scene == TencentScene.SCENE_QQ);
return _channel.invokeMethod<void>(
_METHOD_SHARETEXT,
<String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_SUMMARY: summary,
},
return TencentKitPlatform.instance.shareText(
scene: scene,
summary: summary,
);
}
/// 分享 - 图片
Future<void> shareImage({
static Future<void> shareImage({
required int scene,
required Uri imageUri,
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
assert(scene == TencentScene.SCENE_QQ);
assert(imageUri.isScheme(_SCHEME_FILE));
return _channel.invokeMethod<void>(
_METHOD_SHAREIMAGE,
<String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_IMAGEURI: imageUri.toString(),
if (appName?.isNotEmpty ?? false) _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
},
return TencentKitPlatform.instance.shareImage(
scene: scene,
imageUri: imageUri,
appName: appName,
extInt: extInt,
);
}
/// 分享 - 音乐
Future<void> shareMusic({
static Future<void> shareMusic({
required int scene,
required String title,
String? summary,
@ -196,24 +107,20 @@ class Tencent {
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
assert(scene == TencentScene.SCENE_QQ);
return _channel.invokeMethod<void>(
_METHOD_SHAREMUSIC,
<String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_TITLE: title,
if (summary?.isNotEmpty ?? false) _ARGUMENT_KEY_SUMMARY: summary,
if (imageUri != null) _ARGUMENT_KEY_IMAGEURI: imageUri.toString(),
_ARGUMENT_KEY_MUSICURL: musicUrl,
_ARGUMENT_KEY_TARGETURL: targetUrl,
if (appName?.isNotEmpty ?? false) _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
},
return TencentKitPlatform.instance.shareMusic(
scene: scene,
title: title,
summary: summary,
imageUri: imageUri,
musicUrl: musicUrl,
targetUrl: targetUrl,
appName: appName,
extInt: extInt,
);
}
/// 分享 - 网页
Future<void> shareWebpage({
static Future<void> shareWebpage({
required int scene,
required String title,
String? summary,
@ -222,17 +129,14 @@ class Tencent {
String? appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
return _channel.invokeMethod<void>(
_METHOD_SHAREWEBPAGE,
<String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_TITLE: title,
if (summary?.isNotEmpty ?? false) _ARGUMENT_KEY_SUMMARY: summary,
if (imageUri != null) _ARGUMENT_KEY_IMAGEURI: imageUri.toString(),
_ARGUMENT_KEY_TARGETURL: targetUrl,
if (appName?.isNotEmpty ?? false) _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
},
return TencentKitPlatform.instance.shareWebpage(
scene: scene,
title: title,
summary: summary,
imageUri: imageUri,
targetUrl: targetUrl,
appName: appName,
extInt: extInt,
);
}
}

View File

@ -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,
},
);
}
}

View File

@ -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.');
}
}

View File

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

View File

@ -1,24 +1,24 @@
name: tencent_kit
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>
homepage: https://github.com/v7lin/fake_tencent
homepage: https://github.com/RxReader/tencent_kit.git
environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.20.0"
sdk: ">=2.17.0 <3.0.0"
flutter: ">=2.5.0"
dependencies:
flutter:
sdk: flutter
plugin_platform_interface: ^2.0.2
json_annotation: ^4.0.0
json_annotation: ^4.5.0
dev_dependencies:
flutter_test:
sdk: flutter
pedantic:
flutter_lints: ^2.0.0
build_runner:
json_serializable:
@ -26,11 +26,17 @@ dev_dependencies:
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
# The following section is specific to Flutter packages.
flutter:
# This section identifies this Flutter project as a plugin project.
# The 'pluginClass' and Android 'package' identifiers should not ordinarily
# be modified. They are used by the tooling to maintain consistency when
# The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.)
# 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.
plugin:
platforms:
@ -49,7 +55,7 @@ flutter:
# https://flutter.dev/assets-and-images/#from-packages
#
# 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,
# in this "flutter" section. Each entry in this list should have a

View File

@ -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);
});
}

View File

@ -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
View 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);
});
}