nullsafety

This commit is contained in:
v7lin 2021-03-19 16:16:07 +08:00
parent 8c505c5a74
commit db4c1712c2
36 changed files with 849 additions and 1152 deletions

View File

@ -16,19 +16,9 @@ steps:
# - name: pub-cache # - name: pub-cache
# path: /opt/flutter/.pub-cache # path: /opt/flutter/.pub-cache
# commands: # commands:
# - flutter pub run build_runner clean
# - flutter pub run build_runner build --delete-conflicting-outputs # - flutter pub run build_runner build --delete-conflicting-outputs
#- name: android-check
# image: v7lin/flutter:1.17.3-stable
# volumes:
# - name: pub-cache
# path: /opt/flutter/.pub-cache
# - name: gradle
# path: /root/.gradle
# commands:
# - cd example/android/
# - ./gradlew :wechat_kit:check
# docker run --rm -it -v ${PWD}:/src v7lin/clang:5.0.2-r0 sh -c "clang-format -style=file -i src/Classes/*.h src/Classes/*.m" # docker run --rm -it -v ${PWD}:/src v7lin/clang:5.0.2-r0 sh -c "clang-format -style=file -i src/Classes/*.h src/Classes/*.m"
#- name: ios-format #- name: ios-format
# image: v7lin/clang # image: v7lin/clang

4
.gitignore vendored
View File

@ -6,6 +6,6 @@
build/ build/
# custom #
.idea/
*.iml *.iml
.idea/

View File

@ -1,3 +1,9 @@
## 2.0.0
* nullsafety
* Android embedding v1
* Weibo
## 1.1.0 ## 1.1.0
* *

View File

@ -1,24 +1,24 @@
# weibo_kit # weibo_kit
[![Build Status](https://cloud.drone.io/api/badges/v7lin/weibo_kit/status.svg)](https://cloud.drone.io/v7lin/weibo_kit) [![Build Status](https://cloud.drone.io/api/badges/rxreader/weibo_kit/status.svg)](https://cloud.drone.io/rxreader/weibo_kit)
[![Codecov](https://codecov.io/gh/v7lin/weibo_kit/branch/master/graph/badge.svg)](https://codecov.io/gh/v7lin/weibo_kit) [![Codecov](https://codecov.io/gh/rxreader/weibo_kit/branch/master/graph/badge.svg)](https://codecov.io/gh/rxreader/weibo_kit)
[![GitHub Tag](https://img.shields.io/github/tag/v7lin/weibo_kit.svg)](https://github.com/v7lin/weibo_kit/releases) [![GitHub Tag](https://img.shields.io/github/tag/rxreader/weibo_kit.svg)](https://github.com/rxreader/weibo_kit/releases)
[![Pub Package](https://img.shields.io/pub/v/weibo_kit.svg)](https://pub.dartlang.org/packages/weibo_kit) [![Pub Package](https://img.shields.io/pub/v/weibo_kit.svg)](https://pub.dartlang.org/packages/weibo_kit)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/v7lin/weibo_kit/blob/master/LICENSE) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/rxreader/weibo_kit/blob/master/LICENSE)
flutter版新浪微博SDK flutter版新浪微博SDK
## fake libraries ## fake libraries
* [flutter版微信SDK](https://github.com/v7lin/wechat_kit) * [flutter版微信SDK](https://github.com/rxreader/wechat_kit)
* [flutter版腾讯(QQ)SDK](https://github.com/v7lin/tencent_kit) * [flutter版腾讯(QQ)SDK](https://github.com/rxreader/tencent_kit)
* [flutter版新浪微博SDK](https://github.com/v7lin/weibo_kit) * [flutter版新浪微博SDK](https://github.com/rxreader/weibo_kit)
* [flutter版支付宝SDK](https://github.com/v7lin/alipay_kit) * [flutter版支付宝SDK](https://github.com/rxreader/alipay_kit)
* [flutter版walle渠道打包工具](https://github.com/v7lin/walle_kit) * [flutter版walle渠道打包工具](https://github.com/rxreader/walle_kit)
## dart/flutter ## dart/flutter
* [simple_pub_server](https://github.com/v7lin/simple_pub_server) * [simple_pub_server](https://github.com/rxreader/simple_pub_server)
## docs ## docs
@ -29,6 +29,15 @@ flutter版新浪微博SDK
## android ## android
```groovy
buildscript {
dependencies {
// 3.5.4/3.6.4/4.x.x
classpath 'com.android.tools.build:gradle:3.5.4'
}
}
```
``` ```
# #
# Library Library apk # Library Library apk
@ -153,13 +162,16 @@ iOS 9系统策略更新限制了http协议的访问此外应用需要在
``` ```
## flutter ## flutter
* break change
* 2.0.0: nullsafety & Android embedding v1 & Weibo
* snapshot * snapshot
``` ```
dependencies: dependencies:
weibo_kit: weibo_kit:
git: git:
url: https://github.com/v7lin/weibo_kit.git url: https://github.com/rxreader/weibo_kit.git
``` ```
* release * release

59
analysis_options.yaml Executable file → Normal file
View File

@ -29,12 +29,15 @@ analyzer:
missing_return: warning missing_return: warning
# allow having TODOs in the code # allow having TODOs in the code
todo: ignore 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 # Ignore analyzer hints for updating pubspecs when using Future or
# Stream and not importing dart:async # Stream and not importing dart:async
# Please see https://github.com/flutter/flutter/pull/24528 for details. # Please see https://github.com/flutter/flutter/pull/24528 for details.
sdk_version_async_exported_from_core: ignore sdk_version_async_exported_from_core: ignore
exclude: exclude:
- "**/*.g.dart" - "lib/*.g.dart"
linter: linter:
rules: rules:
@ -46,6 +49,7 @@ linter:
# - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219
- always_require_non_null_named_parameters - always_require_non_null_named_parameters
- always_specify_types - always_specify_types
- always_use_package_imports # we do this commonly
- annotate_overrides - annotate_overrides
# - avoid_annotating_with_dynamic # conflicts with always_specify_types # - avoid_annotating_with_dynamic # conflicts with always_specify_types
# - avoid_as # required for implicit-casts: true # - avoid_as # required for implicit-casts: true
@ -55,7 +59,8 @@ linter:
- avoid_classes_with_only_static_members - avoid_classes_with_only_static_members
# - avoid_double_and_int_checks # only useful when targeting JS runtime # - avoid_double_and_int_checks # only useful when targeting JS runtime
- avoid_empty_else - avoid_empty_else
# - avoid_equals_and_hash_code_on_mutable_classes # not yet tested - avoid_equals_and_hash_code_on_mutable_classes
# - avoid_escaping_inner_quotes # not yet tested
- avoid_field_initializers_in_const_classes - avoid_field_initializers_in_const_classes
- avoid_function_literals_in_foreach_calls - avoid_function_literals_in_foreach_calls
# - avoid_implementing_value_types # not yet tested # - avoid_implementing_value_types # not yet tested
@ -74,9 +79,10 @@ linter:
- avoid_returning_null_for_void - avoid_returning_null_for_void
# - avoid_returning_this # there are plenty of valid reasons to return this # - avoid_returning_this # there are plenty of valid reasons to return this
# - avoid_setters_without_getters # not yet tested # - avoid_setters_without_getters # not yet tested
# - avoid_shadowing_type_parameters # not yet tested - avoid_shadowing_type_parameters
- avoid_single_cascade_in_expression_statements - avoid_single_cascade_in_expression_statements
- avoid_slow_async_io - avoid_slow_async_io
# - avoid_type_to_string # we do this commonly
- avoid_types_as_parameter_names - avoid_types_as_parameter_names
# - avoid_types_on_closure_parameters # conflicts with always_specify_types # - avoid_types_on_closure_parameters # conflicts with always_specify_types
# - avoid_unnecessary_containers # not yet tested # - avoid_unnecessary_containers # not yet tested
@ -88,60 +94,66 @@ linter:
- camel_case_types - camel_case_types
- cancel_subscriptions - cancel_subscriptions
# - cascade_invocations # not yet tested # - cascade_invocations # not yet tested
- cast_nullable_to_non_nullable
# - close_sinks # not reliable enough # - close_sinks # not reliable enough
# - comment_references # blocked on https://github.com/flutter/flutter/issues/20765 # - comment_references # blocked on https://github.com/flutter/flutter/issues/20765
# - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204 # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204
- control_flow_in_finally - control_flow_in_finally
# - curly_braces_in_flow_control_structures # not yet tested # - curly_braces_in_flow_control_structures # not required by flutter style
# - diagnostic_describe_all_properties # not yet tested # - diagnostic_describe_all_properties # not yet tested
- directives_ordering - directives_ordering
# - do_not_use_environment # we do this commonly
- empty_catches - empty_catches
- empty_constructor_bodies - empty_constructor_bodies
- empty_statements - empty_statements
# - file_names # not yet tested - exhaustive_cases
- file_names # not yet tested
- flutter_style_todos - flutter_style_todos
- hash_and_equals - hash_and_equals
- implementation_imports - implementation_imports
# - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811 # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811
- iterable_contains_unrelated_type - iterable_contains_unrelated_type
# - join_return_with_assignment # not yet tested # - join_return_with_assignment # not required by flutter style
- leading_newlines_in_multiline_strings
- library_names - library_names
- library_prefixes - library_prefixes
# - lines_longer_than_80_chars # not yet tested # - lines_longer_than_80_chars # not required by flutter style
- list_remove_unrelated_type - list_remove_unrelated_type
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181
# - missing_whitespace_between_adjacent_strings # not yet tested # - missing_whitespace_between_adjacent_strings # not yet tested
- no_adjacent_strings_in_list - no_adjacent_strings_in_list
# - no_default_cases # too many false positives
- no_duplicate_case_values - no_duplicate_case_values
# - no_logic_in_create_state # not yet tested - no_logic_in_create_state
# - no_runtimeType_toString # not yet tested # - no_runtimeType_toString # ok in tests; we enable this only in packages/
- non_constant_identifier_names - non_constant_identifier_names
# - null_closures # not yet tested - null_check_on_nullable_type_parameter
# - null_closures # not required by flutter style
# - omit_local_variable_types # opposite of always_specify_types # - omit_local_variable_types # opposite of always_specify_types
# - one_member_abstracts # too many false positives # - one_member_abstracts # too many false positives
# - only_throw_errors # https://github.com/flutter/flutter/issues/5792 # - only_throw_errors # https://github.com/flutter/flutter/issues/5792
- overridden_fields - overridden_fields
- package_api_docs - package_api_docs
- package_names # - package_names # non conforming packages in sdk
- package_prefixed_library_names - package_prefixed_library_names
# - parameter_assignments # we do this commonly # - parameter_assignments # we do this commonly
- prefer_adjacent_string_concatenation - prefer_adjacent_string_concatenation
- prefer_asserts_in_initializer_lists - prefer_asserts_in_initializer_lists
# - prefer_asserts_with_message # not yet tested # - prefer_asserts_with_message # not required by flutter style
- prefer_collection_literals - prefer_collection_literals
- prefer_conditional_assignment - prefer_conditional_assignment
- prefer_const_constructors - prefer_const_constructors
- prefer_const_constructors_in_immutables - prefer_const_constructors_in_immutables
- prefer_const_declarations - prefer_const_declarations
- prefer_const_literals_to_create_immutables - prefer_const_literals_to_create_immutables
# - prefer_constructors_over_static_methods # not yet tested # - prefer_constructors_over_static_methods # far too many false positives
- prefer_contains - prefer_contains
# - prefer_double_quotes # opposite of prefer_single_quotes # - prefer_double_quotes # opposite of prefer_single_quotes
- prefer_equal_for_default_values - prefer_equal_for_default_values
# - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods
# - prefer_final_fields - prefer_final_fields
# - prefer_final_in_for_each - prefer_final_in_for_each
# - prefer_final_locals - prefer_final_locals
- prefer_for_elements_to_map_fromIterable - prefer_for_elements_to_map_fromIterable
- prefer_foreach - prefer_foreach
# - prefer_function_declarations_over_variables # not yet tested # - prefer_function_declarations_over_variables # not yet tested
@ -166,16 +178,18 @@ linter:
# - provide_deprecation_message # not yet tested # - provide_deprecation_message # not yet tested
# - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml
- recursive_getters - recursive_getters
# - sized_box_for_whitespace # not yet tested
- slash_for_doc_comments - slash_for_doc_comments
# - sort_child_properties_last # not yet tested # - sort_child_properties_last # not yet tested
- sort_constructors_first - sort_constructors_first
- sort_pub_dependencies # - sort_pub_dependencies # prevents separating pinned transitive dependencies
- sort_unnamed_constructors_first - sort_unnamed_constructors_first
- test_types_in_equals - test_types_in_equals
- throw_in_finally - throw_in_finally
- tighten_type_of_initializing_formals
# - type_annotate_public_apis # subset of always_specify_types # - type_annotate_public_apis # subset of always_specify_types
- type_init_formals - type_init_formals
# - unawaited_futures # too many false positives - unawaited_futures # too many false positives
# - unnecessary_await_in_return # not yet tested # - unnecessary_await_in_return # not yet tested
- unnecessary_brace_in_string_interps - unnecessary_brace_in_string_interps
- unnecessary_const - unnecessary_const
@ -184,20 +198,27 @@ linter:
# - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498
- unnecessary_new - unnecessary_new
- unnecessary_null_aware_assignments - unnecessary_null_aware_assignments
# - unnecessary_null_checks # not yet tested
- unnecessary_null_in_if_null_operators - unnecessary_null_in_if_null_operators
- unnecessary_nullable_for_final_variable_declarations
- unnecessary_overrides - unnecessary_overrides
- unnecessary_parenthesis - unnecessary_parenthesis
# - unnecessary_raw_strings # not yet tested
- unnecessary_statements - unnecessary_statements
- unnecessary_string_escapes
- unnecessary_string_interpolations - unnecessary_string_interpolations
- unnecessary_this - unnecessary_this
- unrelated_type_equality_checks - unrelated_type_equality_checks
# - unsafe_html # not yet tested # - unsafe_html # not yet tested
- use_full_hex_values_for_flutter_colors - use_full_hex_values_for_flutter_colors
# - use_function_type_syntax_for_parameters # not yet tested # - use_function_type_syntax_for_parameters # not yet tested
- use_is_even_rather_than_modulo
# - use_key_in_widget_constructors # not yet tested # - use_key_in_widget_constructors # not yet tested
- use_late_for_private_fields_and_variables
- use_raw_strings
- use_rethrow_when_possible - use_rethrow_when_possible
# - use_setters_to_change_properties # not yet tested # - use_setters_to_change_properties # not yet tested
# - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182
# - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
- valid_regexps - valid_regexps
- void_checks - void_checks

View File

@ -1,5 +1,5 @@
group 'io.github.v7lin.weibo_kit' group 'io.github.v7lin.weibo_kit'
version '1.1.0' version '2.0.0'
buildscript { buildscript {
repositories { repositories {
@ -8,7 +8,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.0' classpath 'com.android.tools.build:gradle:4.1.0'
} }
} }
@ -25,7 +25,6 @@ rootProject.allprojects {
} }
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
apply from: './quality.gradle'
android { android {
compileSdkVersion 28 compileSdkVersion 28
@ -54,8 +53,6 @@ android {
} }
dependencies { dependencies {
implementation 'androidx.annotation:annotation:1.0.0'
// v9.12.0 // v9.12.0
vendorImplementation 'androidx.appcompat:appcompat:1.0.0' vendorImplementation 'androidx.appcompat:appcompat:1.0.0'
vendorImplementation 'com.sina.weibo.sdk:core:9.12.0:openDefaultRelease@aar' vendorImplementation 'com.sina.weibo.sdk:core:9.12.0:openDefaultRelease@aar'

View File

@ -1,135 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
<module name="Checker">
<!--module name="NewlineAtEndOfFile"/-->
<module name="FileLength"/>
<module name="FileTabCharacter"/>
<!-- Trailing spaces -->
<module name="RegexpSingleline">
<property name="format" value="\s+$"/>
<property name="message" value="Line has trailing spaces."/>
</module>
<!-- Space after 'for' and 'if' -->
<module name="RegexpSingleline">
<property name="format" value="^\s*(for|if)[^ ]\("/>
<property name="message" value="Space needed before opening parenthesis."/>
</module>
<!-- For each spacing -->
<module name="RegexpSingleline">
<property name="format" value="^\s*for \(.*?([^ ]:|:[^ ])"/>
<property name="message" value="Space needed around ':' character."/>
</module>
<module name="TreeWalker">
<!--<property name="cacheFile" value="${checkstyle.cache.file}"/>-->
<!-- Checks for Javadoc comments. -->
<!-- See http://checkstyle.sf.net/config_javadoc.html -->
<!--module name="JavadocMethod"/-->
<!--module name="JavadocType"/-->
<!--module name="JavadocVariable"/-->
<!--module name="JavadocStyle"/-->
<!-- Checks for Naming Conventions. -->
<!-- See http://checkstyle.sf.net/config_naming.html -->
<!--<module name="ConstantName"/>-->
<module name="LocalFinalVariableName"/>
<module name="LocalVariableName"/>
<module name="MemberName"/>
<module name="MethodName">
<property name="format" value="^[a-z][a-zA-Z0-9_]*$"/>
</module>
<module name="PackageName"/>
<module name="ParameterName"/>
<module name="StaticVariableName"/>
<module name="TypeName"/>
<!-- Checks for imports -->
<!-- See http://checkstyle.sf.net/config_import.html -->
<module name="AvoidStarImport"/>
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports">
<property name="processJavadoc" value="true"/>
</module>
<!-- Checks for Size Violations. -->
<!-- See http://checkstyle.sf.net/config_sizes.html -->
<module name="LineLength">
<property name="max" value="200"/>
</module>
<module name="MethodLength"/>
<!--module name="ParameterNumber"/-->
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="GenericWhitespace"/>
<module name="EmptyForIteratorPad"/>
<module name="MethodParamPad"/>
<!--<module name="NoWhitespaceAfter"/>-->
<module name="NoWhitespaceBefore"/>
<module name="OperatorWrap"/>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround"/>
<!-- Modifier Checks -->
<!-- See http://checkstyle.sf.net/config_modifiers.html -->
<module name="ModifierOrder"/>
<module name="RedundantModifier"/>
<!-- Checks for blocks. You know, those {}'s -->
<!-- See http://checkstyle.sf.net/config_blocks.html -->
<!--module name="AvoidNestedBlocks"/-->
<!--module name="EmptyBlock"/-->
<module name="LeftCurly"/>
<!--module name="NeedBraces"/-->
<module name="RightCurly"/>
<!-- Checks for common coding problems -->
<!-- See http://checkstyle.sf.net/config_coding.html -->
<!--module name="AvoidInlineConditionals"/-->
<module name="CovariantEquals"/>
<module name="EmptyStatement"/>
<!--<module name="EqualsAvoidNull"/>-->
<module name="EqualsHashCode"/>
<!--module name="HiddenField"/-->
<module name="IllegalInstantiation"/>
<!--<module name="InnerAssignment"/>-->
<!--module name="MagicNumber"/-->
<module name="MissingSwitchDefault"/>
<!--<module name="RedundantThrows"/>-->
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<!-- Checks for class design -->
<!-- See http://checkstyle.sf.net/config_design.html -->
<!--module name="DesignForExtension"/-->
<!--module name="FinalClass"/-->
<!--module name="HideUtilityClassConstructor"/-->
<!--module name="InterfaceIsType"/-->
<!--module name="VisibilityModifier"/-->
<!-- Miscellaneous other checks. -->
<!-- See http://checkstyle.sf.net/config_misc.html -->
<!--module name="ArrayTypeStyle"/-->
<!--module name="FinalParameters"/-->
<!--module name="TodoComment"/-->
<module name="UpperEll"/>
</module>
</module>

View File

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

View File

@ -1,17 +0,0 @@
apply plugin: 'checkstyle'
check.dependsOn 'checkstyle'
checkstyle {
// toolVersion = "6.15"
}
task checkstyle(type: Checkstyle) {
configFile project.file('checkstyle.xml')
source 'src/main/java'
ignoreFailures false
showViolations true
include '**/*.java'
classpath = files()
}

View File

@ -1,274 +0,0 @@
package io.github.v7lin.weibo_kit;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.sina.weibo.sdk.api.ImageObject;
import com.sina.weibo.sdk.api.TextObject;
import com.sina.weibo.sdk.api.WebpageObject;
import com.sina.weibo.sdk.api.WeiboMultiMessage;
import com.sina.weibo.sdk.auth.AuthInfo;
import com.sina.weibo.sdk.auth.Oauth2AccessToken;
import com.sina.weibo.sdk.auth.WbAuthListener;
import com.sina.weibo.sdk.common.UiError;
import com.sina.weibo.sdk.openapi.IWBAPI;
import com.sina.weibo.sdk.openapi.WBAPIFactory;
import com.sina.weibo.sdk.share.WbShareCallback;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;
public class WeiboKit implements MethodChannel.MethodCallHandler, PluginRegistry.ActivityResultListener {
private static class WeiboErrorCode {
public static final int SUCCESS = 0;//
public static final int USERCANCEL = -1;//
public static final int SENT_FAIL = -2;//
public static final int AUTH_DENY = -3;//
public static final int USERCANCEL_INSTALL = -4;//
public static final int PAY_FAIL = -5;//
public static final int SHARE_IN_SDK_FAILED = -8;// response UserInfo
public static final int UNSUPPORT = -99;//
public static final int UNKNOWN = -100;
}
private static final String METHOD_REGISTERAPP = "registerApp";
private static final String METHOD_ISINSTALLED = "isInstalled";
private static final String METHOD_AUTH = "auth";
private static final String METHOD_SHARETEXT = "shareText";
private static final String METHOD_SHAREIMAGE = "shareImage";
private static final String METHOD_SHAREWEBPAGE = "shareWebpage";
private static final String METHOD_ONAUTHRESP = "onAuthResp";
private static final String METHOD_ONSHAREMSGRESP = "onShareMsgResp";
private static final String ARGUMENT_KEY_APPKEY = "appKey";
private static final String ARGUMENT_KEY_SCOPE = "scope";
private static final String ARGUMENT_KEY_REDIRECTURL = "redirectUrl";
private static final String ARGUMENT_KEY_TEXT = "text";
private static final String ARGUMENT_KEY_TITLE = "title";
private static final String ARGUMENT_KEY_DESCRIPTION = "description";
private static final String ARGUMENT_KEY_THUMBDATA = "thumbData";
private static final String ARGUMENT_KEY_IMAGEDATA = "imageData";
private static final String ARGUMENT_KEY_IMAGEURI = "imageUri";
private static final String ARGUMENT_KEY_WEBPAGEURL = "webpageUrl";
private static final String ARGUMENT_KEY_RESULT_ERRORCODE = "errorCode";
private static final String ARGUMENT_KEY_RESULT_ERRORMESSAGE = "errorMessage";
private static final String ARGUMENT_KEY_RESULT_USERID = "userId";
private static final String ARGUMENT_KEY_RESULT_ACCESSTOKEN = "accessToken";
private static final String ARGUMENT_KEY_RESULT_REFRESHTOKEN = "refreshToken";
private static final String ARGUMENT_KEY_RESULT_EXPIRESIN = "expiresIn";
//
private Context applicationContext;
private Activity activity;
private MethodChannel channel;
private IWBAPI iwbapi;
public WeiboKit() {
super();
}
public WeiboKit(Context applicationContext, Activity activity) {
this.applicationContext = applicationContext;
this.activity = activity;
}
//
public void setApplicationContext(@Nullable Context applicationContext) {
this.applicationContext = applicationContext;
}
public void setActivity(@Nullable Activity activity) {
this.activity = activity;
}
public void startListening(@NonNull BinaryMessenger messenger) {
channel = new MethodChannel(messenger, "v7lin.github.io/weibo_kit");
channel.setMethodCallHandler(this);
}
public void stopListening() {
channel.setMethodCallHandler(null);
channel = null;
}
// --- MethodCallHandler
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (METHOD_REGISTERAPP.equals(call.method)) {
String appKey = call.argument(ARGUMENT_KEY_APPKEY);
String scope = call.argument(ARGUMENT_KEY_SCOPE);
String redirectUrl = call.argument(ARGUMENT_KEY_REDIRECTURL);
iwbapi = WBAPIFactory.createWBAPI(activity);
iwbapi.registerApp(applicationContext, new AuthInfo(applicationContext, appKey, redirectUrl, scope));
result.success(null);
} else if (METHOD_ISINSTALLED.equals(call.method)) {
result.success(iwbapi.isWBAppInstalled());
} else if (METHOD_AUTH.equals(call.method)) {
handleAuthCall(call, result);
} else if (METHOD_SHARETEXT.equals(call.method)) {
handleShareTextCall(call, result);
} else if (METHOD_SHAREIMAGE.equals(call.method) ||
METHOD_SHAREWEBPAGE.equals(call.method)) {
handleShareMediaCall(call, result);
} else {
result.notImplemented();
}
}
private void handleAuthCall(MethodCall call, MethodChannel.Result result) {
if (iwbapi != null) {
iwbapi.authorize(new WbAuthListener() {
@Override
public void onComplete(Oauth2AccessToken token) {
Map<String, Object> map = new HashMap<>();
if (token.isSessionValid()) {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.SUCCESS);
map.put(ARGUMENT_KEY_RESULT_USERID, token.getUid());
map.put(ARGUMENT_KEY_RESULT_ACCESSTOKEN, token.getAccessToken());
map.put(ARGUMENT_KEY_RESULT_REFRESHTOKEN, token.getRefreshToken());
long expiresIn = (long) Math.ceil((token.getExpiresTime() - System.currentTimeMillis()) / 1000.0);
map.put(ARGUMENT_KEY_RESULT_EXPIRESIN, expiresIn);//
} else {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.UNKNOWN);
}
if (channel != null) {
channel.invokeMethod(METHOD_ONAUTHRESP, map);
}
}
@Override
public void onError(UiError uiError) {
Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.UNKNOWN);
channel.invokeMethod(METHOD_ONAUTHRESP, map);
}
@Override
public void onCancel() {
Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.USERCANCEL);
if (channel != null) {
channel.invokeMethod(METHOD_ONAUTHRESP, map);
}
}
});
}
result.success(null);
}
private void handleShareTextCall(MethodCall call, MethodChannel.Result result) {
WeiboMultiMessage message = new WeiboMultiMessage();
TextObject object = new TextObject();
object.text = call.argument(ARGUMENT_KEY_TEXT);// 1024
message.textObject = object;
if (iwbapi != null) {
iwbapi.shareMessage(message, false);
}
result.success(null);
}
private void handleShareMediaCall(MethodCall call, MethodChannel.Result result) {
WeiboMultiMessage message = new WeiboMultiMessage();
if (METHOD_SHAREIMAGE.equals(call.method)) {
if (call.hasArgument(ARGUMENT_KEY_TEXT)) {
TextObject object = new TextObject();
object.text = call.argument(ARGUMENT_KEY_TEXT);// 1024
message.textObject = object;
}
ImageObject object = new ImageObject();
if (call.hasArgument(ARGUMENT_KEY_IMAGEDATA)) {
object.imageData = call.argument(ARGUMENT_KEY_IMAGEDATA);// 2 * 1024 * 1024
} else if (call.hasArgument(ARGUMENT_KEY_IMAGEURI)) {
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
object.imagePath = Uri.parse(imageUri).getPath();// 512 - 10 * 1024 * 1024
}
message.mediaObject = object;
} else if (METHOD_SHAREWEBPAGE.equals(call.method)) {
WebpageObject object = new WebpageObject();
object.identify = UUID.randomUUID().toString();
object.title = call.argument(ARGUMENT_KEY_TITLE);// 512
object.description = call.argument(ARGUMENT_KEY_DESCRIPTION);// 1024
object.thumbData = call.argument(ARGUMENT_KEY_THUMBDATA);// 32 * 1024
object.defaultText = call.argument(ARGUMENT_KEY_DESCRIPTION);
object.actionUrl = call.argument(ARGUMENT_KEY_WEBPAGEURL);// 512
message.mediaObject = object;
}
if (iwbapi != null) {
iwbapi.shareMessage(message, false);
}
result.success(null);
}
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 32973:
if (iwbapi != null) {
iwbapi.authorizeCallback(requestCode, resultCode, data);
}
return true;
case 10001:
if (iwbapi != null) {
iwbapi.doResultIntent(data, new WbShareCallback() {
@Override
public void onComplete() {
Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.SUCCESS);
if (channel != null) {
channel.invokeMethod(METHOD_ONSHAREMSGRESP, map);
}
}
@Override
public void onError(UiError uiError) {
Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.SHARE_IN_SDK_FAILED);
if (channel != null) {
channel.invokeMethod(METHOD_ONSHAREMSGRESP, map);
}
}
@Override
public void onCancel() {
Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.USERCANCEL);
if (channel != null) {
channel.invokeMethod(METHOD_ONSHAREMSGRESP, map);
}
}
});
}
return true;
}
return false;
}
}

View File

@ -1,76 +1,294 @@
package io.github.v7lin.weibo_kit; package io.github.v7lin.weibo_kit;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.sina.weibo.sdk.api.ImageObject;
import com.sina.weibo.sdk.api.TextObject;
import com.sina.weibo.sdk.api.WebpageObject;
import com.sina.weibo.sdk.api.WeiboMultiMessage;
import com.sina.weibo.sdk.auth.AuthInfo;
import com.sina.weibo.sdk.auth.Oauth2AccessToken;
import com.sina.weibo.sdk.auth.WbAuthListener;
import com.sina.weibo.sdk.common.UiError;
import com.sina.weibo.sdk.openapi.IWBAPI;
import com.sina.weibo.sdk.openapi.WBAPIFactory;
import com.sina.weibo.sdk.share.WbShareCallback;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.PluginRegistry.Registrar; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry;
/** WeiboKitPlugin */ /**
public class WeiboKitPlugin implements FlutterPlugin, ActivityAware { * WeiboKitPlugin
// This static function is optional and equivalent to onAttachedToEngine. It supports the old */
// pre-Flutter-1.12 Android projects. You are encouraged to continue supporting public class WeiboKitPlugin implements FlutterPlugin, ActivityAware, PluginRegistry.ActivityResultListener, MethodCallHandler {
// plugin registration via this function while apps migrate to use the new Android APIs
// post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
//
// It is encouraged to share logic between onAttachedToEngine and registerWith to keep
// them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
// depending on the user's project. onAttachedToEngine or registerWith must both be defined
// in the same class.
public static void registerWith(Registrar registrar) {
WeiboKit weiboKit = new WeiboKit(registrar.context(), registrar.activity());
registrar.addActivityResultListener(weiboKit);
weiboKit.startListening(registrar.messenger());
}
// --- FlutterPlugin private static class WeiboErrorCode {
public static final int SUCCESS = 0;//
public static final int USERCANCEL = -1;//
public static final int SENT_FAIL = -2;//
public static final int AUTH_DENY = -3;//
public static final int USERCANCEL_INSTALL = -4;//
public static final int PAY_FAIL = -5;//
public static final int SHARE_IN_SDK_FAILED = -8;// response UserInfo
public static final int UNSUPPORT = -99;//
public static final int UNKNOWN = -100;
}
private final WeiboKit weiboKit; private static final String METHOD_REGISTERAPP = "registerApp";
private static final String METHOD_ISINSTALLED = "isInstalled";
private static final String METHOD_AUTH = "auth";
private static final String METHOD_SHARETEXT = "shareText";
private static final String METHOD_SHAREIMAGE = "shareImage";
private static final String METHOD_SHAREWEBPAGE = "shareWebpage";
private ActivityPluginBinding pluginBinding; private static final String METHOD_ONAUTHRESP = "onAuthResp";
private static final String METHOD_ONSHAREMSGRESP = "onShareMsgResp";
public WeiboKitPlugin() { private static final String ARGUMENT_KEY_APPKEY = "appKey";
weiboKit = new WeiboKit(); private static final String ARGUMENT_KEY_SCOPE = "scope";
} private static final String ARGUMENT_KEY_REDIRECTURL = "redirectUrl";
private static final String ARGUMENT_KEY_TEXT = "text";
private static final String ARGUMENT_KEY_TITLE = "title";
private static final String ARGUMENT_KEY_DESCRIPTION = "description";
private static final String ARGUMENT_KEY_THUMBDATA = "thumbData";
private static final String ARGUMENT_KEY_IMAGEDATA = "imageData";
private static final String ARGUMENT_KEY_IMAGEURI = "imageUri";
private static final String ARGUMENT_KEY_WEBPAGEURL = "webpageUrl";
@Override private static final String ARGUMENT_KEY_RESULT_ERRORCODE = "errorCode";
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { private static final String ARGUMENT_KEY_RESULT_ERRORMESSAGE = "errorMessage";
weiboKit.setApplicationContext(binding.getApplicationContext()); private static final String ARGUMENT_KEY_RESULT_USERID = "userId";
weiboKit.setActivity(null); private static final String ARGUMENT_KEY_RESULT_ACCESSTOKEN = "accessToken";
weiboKit.startListening(binding.getBinaryMessenger()); private static final String ARGUMENT_KEY_RESULT_REFRESHTOKEN = "refreshToken";
} private static final String ARGUMENT_KEY_RESULT_EXPIRESIN = "expiresIn";
@Override /// The MethodChannel that will the communication between Flutter and native Android
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { ///
weiboKit.stopListening(); /// This local reference serves to register the plugin with the Flutter Engine and unregister it
weiboKit.setActivity(null); /// when the Flutter Engine is detached from the Activity
weiboKit.setApplicationContext(null); private MethodChannel channel;
} private Context applicationContext;
private ActivityPluginBinding activityPluginBinding;
// --- ActivityAware private IWBAPI iwbapi;
@Override // --- FlutterPlugin
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
weiboKit.setActivity(binding.getActivity());
pluginBinding = binding;
pluginBinding.addActivityResultListener(weiboKit);
}
@Override @Override
public void onDetachedFromActivityForConfigChanges() { public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
onDetachedFromActivity(); channel = new MethodChannel(binding.getBinaryMessenger(), "v7lin.github.io/weibo_kit");
} channel.setMethodCallHandler(this);
applicationContext = binding.getApplicationContext();
}
@Override @Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
onAttachedToActivity(binding); channel.setMethodCallHandler(null);
} channel = null;
applicationContext = null;
}
@Override // --- ActivityAware
public void onDetachedFromActivity() {
weiboKit.setActivity(null); @Override
pluginBinding.removeActivityResultListener(weiboKit); public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
pluginBinding = null; activityPluginBinding = binding;
} activityPluginBinding.addActivityResultListener(this);
}
@Override
public void onDetachedFromActivityForConfigChanges() {
onDetachedFromActivity();
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
onAttachedToActivity(binding);
}
@Override
public void onDetachedFromActivity() {
activityPluginBinding.removeActivityResultListener(this);
activityPluginBinding = null;
}
// --- ActivityResultListener
@Override
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 32973:
if (iwbapi != null) {
iwbapi.authorizeCallback(requestCode, resultCode, data);
}
return true;
case 10001:
if (iwbapi != null) {
iwbapi.doResultIntent(data, new WbShareCallback() {
@Override
public void onComplete() {
Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.SUCCESS);
if (channel != null) {
channel.invokeMethod(METHOD_ONSHAREMSGRESP, map);
}
}
@Override
public void onError(UiError uiError) {
Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.SHARE_IN_SDK_FAILED);
if (channel != null) {
channel.invokeMethod(METHOD_ONSHAREMSGRESP, map);
}
}
@Override
public void onCancel() {
Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.USERCANCEL);
if (channel != null) {
channel.invokeMethod(METHOD_ONSHAREMSGRESP, map);
}
}
});
}
return true;
}
return false;
}
// --- MethodCallHandler
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (METHOD_REGISTERAPP.equals(call.method)) {
String appKey = call.argument(ARGUMENT_KEY_APPKEY);
String scope = call.argument(ARGUMENT_KEY_SCOPE);
String redirectUrl = call.argument(ARGUMENT_KEY_REDIRECTURL);
iwbapi = WBAPIFactory.createWBAPI(activityPluginBinding.getActivity());
iwbapi.registerApp(applicationContext, new AuthInfo(applicationContext, appKey, redirectUrl, scope));
result.success(null);
} else if (METHOD_ISINSTALLED.equals(call.method)) {
result.success(iwbapi.isWBAppInstalled());
} else if (METHOD_AUTH.equals(call.method)) {
handleAuthCall(call, result);
} else if (METHOD_SHARETEXT.equals(call.method)) {
handleShareTextCall(call, result);
} else if (METHOD_SHAREIMAGE.equals(call.method) ||
METHOD_SHAREWEBPAGE.equals(call.method)) {
handleShareMediaCall(call, result);
} else {
result.notImplemented();
}
}
private void handleAuthCall(@NonNull MethodCall call, @NonNull Result result) {
if (iwbapi != null) {
iwbapi.authorize(new WbAuthListener() {
@Override
public void onComplete(Oauth2AccessToken token) {
Map<String, Object> map = new HashMap<>();
if (token.isSessionValid()) {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.SUCCESS);
map.put(ARGUMENT_KEY_RESULT_USERID, token.getUid());
map.put(ARGUMENT_KEY_RESULT_ACCESSTOKEN, token.getAccessToken());
map.put(ARGUMENT_KEY_RESULT_REFRESHTOKEN, token.getRefreshToken());
long expiresIn = (long) Math.ceil((token.getExpiresTime() - System.currentTimeMillis()) / 1000.0);
map.put(ARGUMENT_KEY_RESULT_EXPIRESIN, expiresIn);//
} else {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.UNKNOWN);
}
if (channel != null) {
channel.invokeMethod(METHOD_ONAUTHRESP, map);
}
}
@Override
public void onError(UiError uiError) {
Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.UNKNOWN);
if (channel != null) {
channel.invokeMethod(METHOD_ONAUTHRESP, map);
}
}
@Override
public void onCancel() {
Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, WeiboErrorCode.USERCANCEL);
if (channel != null) {
channel.invokeMethod(METHOD_ONAUTHRESP, map);
}
}
});
}
result.success(null);
}
private void handleShareTextCall(@NonNull MethodCall call, @NonNull Result result) {
WeiboMultiMessage message = new WeiboMultiMessage();
TextObject object = new TextObject();
object.text = call.argument(ARGUMENT_KEY_TEXT);// 1024
message.textObject = object;
if (iwbapi != null) {
iwbapi.shareMessage(message, false);
}
result.success(null);
}
private void handleShareMediaCall(@NonNull MethodCall call, @NonNull Result result) {
WeiboMultiMessage message = new WeiboMultiMessage();
if (METHOD_SHAREIMAGE.equals(call.method)) {
if (call.hasArgument(ARGUMENT_KEY_TEXT)) {
TextObject object = new TextObject();
object.text = call.argument(ARGUMENT_KEY_TEXT);// 1024
message.textObject = object;
}
ImageObject object = new ImageObject();
if (call.hasArgument(ARGUMENT_KEY_IMAGEDATA)) {
object.imageData = call.argument(ARGUMENT_KEY_IMAGEDATA);// 2 * 1024 * 1024
} else if (call.hasArgument(ARGUMENT_KEY_IMAGEURI)) {
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
object.imagePath = Uri.parse(imageUri).getPath();// 512 - 10 * 1024 * 1024
}
message.mediaObject = object;
} else if (METHOD_SHAREWEBPAGE.equals(call.method)) {
WebpageObject object = new WebpageObject();
object.identify = UUID.randomUUID().toString();
object.title = call.argument(ARGUMENT_KEY_TITLE);// 512
object.description = call.argument(ARGUMENT_KEY_DESCRIPTION);// 1024
object.thumbData = call.argument(ARGUMENT_KEY_THUMBDATA);// 32 * 1024
object.defaultText = call.argument(ARGUMENT_KEY_DESCRIPTION);
object.actionUrl = call.argument(ARGUMENT_KEY_WEBPAGEURL);// 512
message.mediaObject = object;
}
if (iwbapi != null) {
iwbapi.shareMessage(message, false);
}
result.success(null);
}
} }

View File

@ -3,4 +3,9 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<queries>
<!-- targetSdkVersion>=30 -> Android 11 -->
<package android:name="com.sina.weibo" />
</queries>
</manifest> </manifest>

7
example/.gitignore vendored
View File

@ -22,6 +22,7 @@
# Flutter/Dart/Pub related # Flutter/Dart/Pub related
**/doc/api/ **/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/ .dart_tool/
.flutter-plugins .flutter-plugins
.flutter-plugins-dependencies .flutter-plugins-dependencies
@ -39,5 +40,7 @@ app.*.symbols
# Obfuscation related # Obfuscation related
app.*.map.json app.*.map.json
# Exceptions to above rules. # Android Studio will place build artifacts here
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages /android/app/debug
/android/app/profile
/android/app/release

View File

@ -5,3 +5,7 @@ gradle-wrapper.jar
/gradlew.bat /gradlew.bat
/local.properties /local.properties
GeneratedPluginRegistrant.java GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties

View File

@ -5,7 +5,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.0' classpath 'com.android.tools.build:gradle:4.1.0'
} }
} }

View File

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

View File

@ -10,75 +10,29 @@ project 'Runner', {
'Release' => :release, 'Release' => :release,
} }
def parse_KV_file(file, separator='=') def flutter_root
file_abs_path = File.expand_path(file) generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
if !File.exists? file_abs_path unless File.exist?(generated_xcode_build_settings_path)
return []; raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end end
generated_key_values = {}
skip_line_start_symbols = ["#", "/"] File.foreach(generated_xcode_build_settings_path) do |line|
File.foreach(file_abs_path) do |line| matches = line.match(/FLUTTER_ROOT\=(.*)/)
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } return matches[1].strip if matches
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{path}", file_abs_path)
generated_key_values[podname] = podpath
else
puts "Invalid plugin specification: #{line}"
end
end end
generated_key_values raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do target 'Runner' do
# Flutter Pod flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
copied_flutter_dir = File.join(__dir__, 'Flutter')
copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
# Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
# That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
# CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
unless File.exist?(generated_xcode_build_settings_path)
raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
unless File.exist?(copied_framework_path)
FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
end
unless File.exist?(copied_podspec_path)
FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
end
end
# Keep pod path relative so it can be checked into Podfile.lock.
pod 'Flutter', :path => 'Flutter'
# Plugin Pods
# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.
system('rm -rf .symlinks')
system('mkdir -p .symlinks/plugins')
plugin_pods = parse_KV_file('../.flutter-plugins')
plugin_pods.each do |name, path|
symlink = File.join('.symlinks', 'plugins', name)
File.symlink(path, symlink)
pod name, :path => File.join(symlink, 'ios')
end
end end
post_install do |installer| post_install do |installer|
installer.pods_project.targets.each do |target| installer.pods_project.targets.each do |target|
target.build_configurations.each do |config| flutter_additional_ios_build_settings(target)
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end end
end end

View File

@ -1,15 +1,17 @@
PODS: PODS:
- Flutter (1.0.0) - Flutter (1.0.0)
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- path_provider (0.0.1): - path_provider (0.0.1):
- Flutter - Flutter
- path_provider_linux (0.0.1): - sqflite (0.0.2):
- Flutter - Flutter
- path_provider_macos (0.0.1): - FMDB (>= 2.7.5)
- weibo_kit (2.0.0):
- Flutter - Flutter
- weibo_kit (1.1.0): - weibo_kit/vendor (= 2.0.0)
- Flutter - weibo_kit/vendor (2.0.0):
- weibo_kit/vendor (= 1.1.0)
- weibo_kit/vendor (1.1.0):
- Flutter - Flutter
- Weibo_SDK (~> 3.2.7) - Weibo_SDK (~> 3.2.7)
- Weibo_SDK (3.2.7) - Weibo_SDK (3.2.7)
@ -17,12 +19,12 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- Flutter (from `Flutter`) - Flutter (from `Flutter`)
- path_provider (from `.symlinks/plugins/path_provider/ios`) - path_provider (from `.symlinks/plugins/path_provider/ios`)
- path_provider_linux (from `.symlinks/plugins/path_provider_linux/ios`) - sqflite (from `.symlinks/plugins/sqflite/ios`)
- path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`)
- weibo_kit (from `.symlinks/plugins/weibo_kit/ios`) - weibo_kit (from `.symlinks/plugins/weibo_kit/ios`)
SPEC REPOS: SPEC REPOS:
trunk: trunk:
- FMDB
- Weibo_SDK - Weibo_SDK
EXTERNAL SOURCES: EXTERNAL SOURCES:
@ -30,21 +32,19 @@ EXTERNAL SOURCES:
:path: Flutter :path: Flutter
path_provider: path_provider:
:path: ".symlinks/plugins/path_provider/ios" :path: ".symlinks/plugins/path_provider/ios"
path_provider_linux: sqflite:
:path: ".symlinks/plugins/path_provider_linux/ios" :path: ".symlinks/plugins/sqflite/ios"
path_provider_macos:
:path: ".symlinks/plugins/path_provider_macos/ios"
weibo_kit: weibo_kit:
:path: ".symlinks/plugins/weibo_kit/ios" :path: ".symlinks/plugins/weibo_kit/ios"
SPEC CHECKSUMS: SPEC CHECKSUMS:
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4 sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0 weibo_kit: 9327afb47ffde6c4fd4b091973f91eae4440a0c4
weibo_kit: 82a3b5501bbe2ae59528e683a80277079ecc95cb
Weibo_SDK: 5a4d08f7e1fedbb635435e4585c8c0439c7da089 Weibo_SDK: 5a4d08f7e1fedbb635435e4585c8c0439c7da089
PODFILE CHECKSUM: f32fb4e7c14f8b3ca19a369d7be425dd9241af27 PODFILE CHECKSUM: 8e679eca47255a8ca8067c4c67aab20e64cb974d
COCOAPODS: 1.8.4 COCOAPODS: 1.10.0

View File

@ -149,7 +149,6 @@
97C146EC1CF9000F007C117D /* Resources */, 97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */, 9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
1F77EE1FF4C528197971DB94 /* [CP] Embed Pods Frameworks */,
BEFF80007E7E4E2B2694658C /* [CP] Copy Pods Resources */, BEFF80007E7E4E2B2694658C /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
@ -208,23 +207,6 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
1F77EE1FF4C528197971DB94 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;

View File

@ -3,26 +3,22 @@ import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:image/image.dart' as image; import 'package:image/image.dart' as image;
import 'package:okhttp_kit/okhttp_kit.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart' as path_provider;
import 'package:weibo_kit/weibo_kit.dart'; import 'package:weibo_kit/weibo_kit.dart';
void main() { const String _WEIBO_APP_KEY = 'your weibo app key';
runZoned(() { const List<String> _WEIBO_SCOPE = <String>[
runApp(MyApp()); WeiboScope.ALL,
}, onError: (dynamic error, dynamic stack) { ];
print(error);
print(stack);
});
if (Platform.isAndroid) { void main() {
SystemUiOverlayStyle systemUiOverlayStyle = WidgetsFlutterBinding.ensureInitialized();
const SystemUiOverlayStyle(statusBarColor: Colors.transparent); Weibo.instance.registerApp(
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle); appKey: _WEIBO_APP_KEY,
} scope: _WEIBO_SCOPE,
);
runApp(MyApp());
} }
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
@ -42,48 +38,33 @@ class Home extends StatefulWidget {
} }
class _HomeState extends State<Home> { class _HomeState extends State<Home> {
static const String _WEIBO_APP_KEY = 'your weibo app key'; late final StreamSubscription<WeiboAuthResp> _auth =
static const List<String> _WEIBO_SCOPE = <String>[ Weibo.instance.authResp().listen(_listenAuth);
WeiboScope.ALL, late final StreamSubscription<WeiboSdkResp> _share =
]; Weibo.instance.shareMsgResp().listen(_listenShareMsg);
Weibo _weibo = Weibo() WeiboAuthResp? _authResp;
..registerApp(
appKey: _WEIBO_APP_KEY,
scope: _WEIBO_SCOPE,
);
StreamSubscription<WeiboAuthResp> _auth;
StreamSubscription<WeiboSdkResp> _share;
WeiboAuthResp _authResp;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_auth = _weibo.authResp().listen(_listenAuth);
_share = _weibo.shareMsgResp().listen(_listenShareMsg);
} }
void _listenAuth(WeiboAuthResp resp) { void _listenAuth(WeiboAuthResp resp) {
_authResp = resp; _authResp = resp;
String content = 'auth: ${resp.errorCode}'; final String content = 'auth: ${resp.errorCode}';
_showTips('登录', content); _showTips('登录', content);
} }
void _listenShareMsg(WeiboSdkResp resp) { void _listenShareMsg(WeiboSdkResp resp) {
String content = 'share: ${resp.errorCode}'; final String content = 'share: ${resp.errorCode}';
_showTips('分享', content); _showTips('分享', content);
} }
@override @override
void dispose() { void dispose() {
if (_auth != null) { _auth.cancel();
_auth.cancel(); _share.cancel();
}
if (_share != null) {
_share.cancel();
}
super.dispose(); super.dispose();
} }
@ -98,14 +79,15 @@ class _HomeState extends State<Home> {
ListTile( ListTile(
title: const Text('环境检查'), title: const Text('环境检查'),
onTap: () async { onTap: () async {
String content = 'weibo: ${await _weibo.isInstalled()}'; final String content =
'weibo: ${await Weibo.instance.isInstalled()}';
_showTips('环境检查', content); _showTips('环境检查', content);
}, },
), ),
ListTile( ListTile(
title: const Text('登录'), title: const Text('登录'),
onTap: () { onTap: () {
_weibo.auth( Weibo.instance.auth(
appKey: _WEIBO_APP_KEY, appKey: _WEIBO_APP_KEY,
scope: _WEIBO_SCOPE, scope: _WEIBO_SCOPE,
); );
@ -114,15 +96,14 @@ class _HomeState extends State<Home> {
ListTile( ListTile(
title: const Text('用户信息'), title: const Text('用户信息'),
onTap: () async { onTap: () async {
if (_authResp != null && if (_authResp?.isSuccessful ?? false) {
_authResp.errorCode == WeiboSdkResp.SUCCESS) { final WeiboUserInfoResp userInfoResp =
WeiboUserInfoResp userInfoResp = await _weibo.getUserInfo( await Weibo.instance.getUserInfo(
appkey: _WEIBO_APP_KEY, appkey: _WEIBO_APP_KEY,
userId: _authResp.userId, userId: _authResp!.userId!,
accessToken: _authResp.accessToken, accessToken: _authResp!.accessToken!,
); );
if (userInfoResp != null && if (userInfoResp.isSuccessful) {
userInfoResp.errorCode == WeiboApiResp.ERROR_CODE_SUCCESS) {
_showTips('用户信息', _showTips('用户信息',
'${userInfoResp.screenName}\n${userInfoResp.description}\n${userInfoResp.location}\n${userInfoResp.profileImageUrl}'); '${userInfoResp.screenName}\n${userInfoResp.description}\n${userInfoResp.location}\n${userInfoResp.profileImageUrl}');
} else { } else {
@ -135,7 +116,7 @@ class _HomeState extends State<Home> {
ListTile( ListTile(
title: const Text('文字分享'), title: const Text('文字分享'),
onTap: () { onTap: () {
_weibo.shareText( Weibo.instance.shareText(
text: 'Share Text', text: 'Share Text',
); );
}, },
@ -143,70 +124,32 @@ class _HomeState extends State<Home> {
ListTile( ListTile(
title: const Text('图片分享'), title: const Text('图片分享'),
onTap: () async { onTap: () async {
OkHttpClient client = OkHttpClientBuilder().build(); final File file = await DefaultCacheManager().getSingleFile(
Response resp = await client 'https://www.baidu.com/img/bd_logo1.png?where=super');
.newCall(RequestBuilder() await Weibo.instance.shareImage(
.get() text: 'Share Text',
.url(HttpUrl.parse( imageUri: Uri.file(file.path),
'https://www.baidu.com/img/bd_logo1.png?where=super')) );
.build())
.enqueue();
if (resp.isSuccessful()) {
Directory saveDir = Platform.isAndroid
? await path_provider.getExternalStorageDirectory()
: await path_provider.getApplicationDocumentsDirectory();
File saveFile = File(path.join(saveDir.path, 'timg.png'));
if (!saveFile.existsSync()) {
saveFile.createSync(recursive: true);
saveFile.writeAsBytesSync(
await resp.body().bytes(),
flush: true,
);
}
await _weibo.shareImage(
text: 'Share Text',
imageUri: Uri.file(saveFile.path),
);
}
}, },
), ),
ListTile( ListTile(
title: const Text('网页分享'), title: const Text('网页分享'),
onTap: () async { onTap: () async {
OkHttpClient client = OkHttpClientBuilder().build(); final File file = await DefaultCacheManager().getSingleFile(
Response resp = await client 'https://www.baidu.com/img/bd_logo1.png?where=super');
.newCall(RequestBuilder() final image.Image thumbnail =
.get() image.decodeImage(file.readAsBytesSync())!;
.url(HttpUrl.parse( Uint8List thumbData = thumbnail.getBytes();
'https://www.baidu.com/img/bd_logo1.png?where=super')) if (thumbData.length > 32 * 1024) {
.build()) thumbData = Uint8List.fromList(image.encodeJpg(thumbnail,
.enqueue(); quality: 100 * 32 * 1024 ~/ thumbData.length));
if (resp.isSuccessful()) {
Directory saveDir = Platform.isAndroid
? await path_provider.getExternalStorageDirectory()
: await path_provider.getApplicationDocumentsDirectory();
File saveFile = File(path.join(saveDir.path, 'timg.png'));
if (!saveFile.existsSync()) {
saveFile.createSync(recursive: true);
saveFile.writeAsBytesSync(
await resp.body().bytes(),
flush: true,
);
}
image.Image thumbnail =
image.decodePng(saveFile.readAsBytesSync());
Uint8List thumbData = thumbnail.getBytes();
if (thumbData.length > 32 * 1024) {
thumbData = Uint8List.fromList(image.encodeJpg(thumbnail,
quality: 100 * 32 * 1024 ~/ thumbData.length));
}
await _weibo.shareWebpage(
title: 'title',
description: 'share webpage',
thumbData: thumbData.buffer.asUint8List(),
webpageUrl: 'https://www.baidu.com',
);
} }
await Weibo.instance.shareWebpage(
title: 'title',
description: 'share webpage',
thumbData: thumbData.buffer.asUint8List(),
webpageUrl: 'https://www.baidu.com',
);
}, },
), ),
], ],

View File

@ -7,206 +7,227 @@ packages:
name: archive name: archive
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.13" version: "3.1.2"
args:
dependency: transitive
description:
name: args
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.6.0"
async: async:
dependency: transitive dependency: transitive
description: description:
name: async name: async
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.4.1" version: "2.5.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
name: boolean_selector name: boolean_selector
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
name: charcode name: charcode
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.3" version: "1.2.0"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.14.12" version: "1.15.0"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.1"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
name: crypto name: crypto
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.4" version: "3.0.0"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
name: cupertino_icons name: cupertino_icons
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.1.3" version: "1.0.2"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.0"
file: file:
dependency: transitive dependency: transitive
description: description:
name: file name: file
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "5.2.0" version: "6.1.0"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.10.11"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_cache_manager:
dependency: "direct main"
description:
name: flutter_cache_manager
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.0-nullsafety.1"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
image: http:
dependency: transitive dependency: transitive
description:
name: http
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.13.0"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.0.0"
image:
dependency: "direct main"
description: description:
name: image name: image
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.12" version: "3.0.1"
intl:
dependency: transitive
description:
name: intl
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.16.1"
json_annotation: json_annotation:
dependency: transitive dependency: transitive
description: description:
name: json_annotation name: json_annotation
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.1" version: "4.0.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.12.6" version: "0.12.10"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.8" version: "1.3.0"
okhttp_kit:
dependency: "direct main"
description:
name: okhttp_kit
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.2"
path: path:
dependency: "direct main" dependency: transitive
description: description:
name: path name: path
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.6.4" version: "1.8.0"
path_provider: path_provider:
dependency: "direct main" dependency: transitive
description: description:
name: path_provider name: path_provider
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.6.11" version: "2.0.1"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
name: path_provider_linux name: path_provider_linux
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.0.1+1" version: "2.0.0"
path_provider_macos: path_provider_macos:
dependency: transitive dependency: transitive
description: description:
name: path_provider_macos name: path_provider_macos
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.0.4+3" version: "2.0.0"
path_provider_platform_interface: path_provider_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: path_provider_platform_interface name: path_provider_platform_interface
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.2" version: "2.0.1"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0"
pedantic: pedantic:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: pedantic name: pedantic
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.9.0" version: "1.11.0"
petitparser: petitparser:
dependency: transitive dependency: transitive
description: description:
name: petitparser name: petitparser
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.4.0" version: "4.0.2"
platform: platform:
dependency: transitive dependency: transitive
description: description:
name: platform name: platform
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.2.1" version: "3.0.0"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: plugin_platform_interface name: plugin_platform_interface
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.2" version: "2.0.0"
process: process:
dependency: transitive dependency: transitive
description: description:
name: process name: process
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.13" version: "4.1.0"
quiver: rxdart:
dependency: transitive dependency: transitive
description: description:
name: quiver name: rxdart
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.3" version: "0.26.0"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -218,77 +239,112 @@ packages:
name: source_span name: source_span
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.7.0" version: "1.8.0"
sqflite:
dependency: transitive
description:
name: sqflite
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0+3"
sqflite_common:
dependency: transitive
description:
name: sqflite_common
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0+2"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.9.3" version: "1.10.0"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.1.0"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.5" version: "1.1.0"
synchronized:
dependency: transitive
description:
name: synchronized
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.0"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
name: term_glyph name: term_glyph
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.0" version: "1.2.0"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.2.15" version: "0.2.19"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.6" version: "1.3.0"
uuid:
dependency: transitive
description:
name: uuid
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.8" version: "2.1.0"
weibo_kit: weibo_kit:
dependency: "direct main" dependency: "direct main"
description: description:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "1.1.0" version: "2.0.0"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.4"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
name: xdg_directories name: xdg_directories
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.1.0" version: "0.2.0"
xml: xml:
dependency: transitive dependency: transitive
description: description:
name: xml name: xml
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.6.1" version: "5.0.2"
sdks: sdks:
dart: ">=2.7.0 <3.0.0" dart: ">=2.12.0 <3.0.0"
flutter: ">=1.12.13+hotfix.5 <2.0.0" flutter: ">=1.24.0-10"

View File

@ -1,12 +1,14 @@
name: weibo_kit_example name: weibo_kit_example
description: Demonstrates how to use the weibo_kit plugin. description: Demonstrates how to use the weibo_kit plugin.
version: 1.0.0+1000
# The following line prevents the package from being accidentally published to # The following line prevents the package from being accidentally published to
# pub.dev using `pub publish`. This is preferred for private packages. # pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
environment: environment:
sdk: ">=2.7.0 <3.0.0" sdk: ">=2.12.0 <3.0.0"
version: 1.0.0+100
dependencies: dependencies:
flutter: flutter:
@ -22,12 +24,10 @@ dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.3 cupertino_icons: ^1.0.2
path: ^1.6.4 image: ^3.0.1
path_provider: ^1.4.0 flutter_cache_manager: ^3.0.0-nullsafety.1
okhttp_kit: ^1.0.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

44
ios/.clang-format Executable file
View File

@ -0,0 +1,44 @@
#
BasedOnStyle: LLVM
#
IndentWidth: 4
#
BreakBeforeBraces: Attach
#
AllowShortLoopsOnASingleLine: false
# if
AllowShortIfStatementsOnASingleLine: false
# switch的case缩进
IndentCaseLabels: true
# OC的block的缩进宽度
ObjCBlockIndentWidth: 4
# OC
ObjCSpaceAfterProperty: true
#
ColumnLimit: 0
#
AlignTrailingComments: true
#
SpaceAfterCStyleCast: false
#
SpacesInParentheses: false
#
SpacesInSquareBrackets: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false

View File

@ -4,7 +4,7 @@
# #
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'weibo_kit' s.name = 'weibo_kit'
s.version = '1.1.0' s.version = '2.0.0'
s.summary = 'A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Weibo SDKs.' s.summary = 'A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Weibo SDKs.'
s.description = <<-DESC s.description = <<-DESC
A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Weibo SDKs. A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Weibo SDKs.

View File

@ -1,14 +1,21 @@
import 'package:json_annotation/json_annotation.dart';
abstract class WeiboApiResp { abstract class WeiboApiResp {
WeiboApiResp({ const WeiboApiResp({
int errorCode, required this.errorCode,
this.error, this.error,
this.request, this.request,
}) : errorCode = errorCode ?? ERROR_CODE_SUCCESS; });
static const int ERROR_CODE_SUCCESS = 0; static const int ERROR_CODE_SUCCESS = 0;
/// https://open.weibo.com/wiki/Help/error /// https://open.weibo.com/wiki/Help/error
@JsonKey(
defaultValue: ERROR_CODE_SUCCESS,
)
final int errorCode; final int errorCode;
final String error; final String? error;
final String request; final String? request;
bool get isSuccessful => errorCode == ERROR_CODE_SUCCESS;
} }

View File

@ -4,15 +4,14 @@ import 'package:weibo_kit/src/model/api/weibo_api_resp.dart';
part 'weibo_user_info_resp.g.dart'; part 'weibo_user_info_resp.g.dart';
@JsonSerializable( @JsonSerializable(
anyMap: true,
explicitToJson: true, explicitToJson: true,
fieldRename: FieldRename.snake, fieldRename: FieldRename.snake,
) )
class WeiboUserInfoResp extends WeiboApiResp { class WeiboUserInfoResp extends WeiboApiResp {
WeiboUserInfoResp({ const WeiboUserInfoResp({
int errorCode, required int errorCode,
String error, String? error,
String request, String? request,
this.id, this.id,
this.idstr, this.idstr,
this.screenName, this.screenName,
@ -25,46 +24,42 @@ class WeiboUserInfoResp extends WeiboApiResp {
this.avatarHd, this.avatarHd,
}) : super(errorCode: errorCode, error: error, request: request); }) : super(errorCode: errorCode, error: error, request: request);
factory WeiboUserInfoResp.fromJson(Map<dynamic, dynamic> json) => factory WeiboUserInfoResp.fromJson(Map<String, dynamic> json) =>
_$WeiboUserInfoRespFromJson(json); _$WeiboUserInfoRespFromJson(json);
/// UIDint64 /// UIDint64
final int id; final int? id;
/// UID /// UID
final String idstr; final String? idstr;
/// ///
final String screenName; final String? screenName;
/// ///
final String name; final String? name;
/// ///
final String location; final String? location;
/// ///
final String description; final String? description;
/// 50×50 /// 50×50
final String profileImageUrl; final String? profileImageUrl;
/// mfn /// mfn
final String gender; final String? gender;
/// ///
final String avatarLarge; final String? avatarLarge;
/// ///
final String avatarHd; final String? avatarHd;
bool isMale() { bool get isMale => gender == 'm';
return gender == 'm';
}
bool isFemale() { bool get isFemale => gender == 'f';
return gender == 'f';
}
Map<dynamic, dynamic> toJson() => _$WeiboUserInfoRespToJson(this); Map<String, dynamic> toJson() => _$WeiboUserInfoRespToJson(this);
} }

View File

@ -6,21 +6,21 @@ part of 'weibo_user_info_resp.dart';
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
WeiboUserInfoResp _$WeiboUserInfoRespFromJson(Map json) { WeiboUserInfoResp _$WeiboUserInfoRespFromJson(Map<String, dynamic> json) {
return WeiboUserInfoResp( return WeiboUserInfoResp(
errorCode: json['error_code'] as int, errorCode: json['error_code'] as int? ?? 0,
error: json['error'] as String, error: json['error'] as String?,
request: json['request'] as String, request: json['request'] as String?,
id: json['id'] as int, id: json['id'] as int?,
idstr: json['idstr'] as String, idstr: json['idstr'] as String?,
screenName: json['screen_name'] as String, screenName: json['screen_name'] as String?,
name: json['name'] as String, name: json['name'] as String?,
location: json['location'] as String, location: json['location'] as String?,
description: json['description'] as String, description: json['description'] as String?,
profileImageUrl: json['profile_image_url'] as String, profileImageUrl: json['profile_image_url'] as String?,
gender: json['gender'] as String, gender: json['gender'] as String?,
avatarLarge: json['avatar_large'] as String, avatarLarge: json['avatar_large'] as String?,
avatarHd: json['avatar_hd'] as String, avatarHd: json['avatar_hd'] as String?,
); );
} }

View File

@ -4,27 +4,26 @@ import 'package:weibo_kit/src/model/sdk/weibo_sdk_resp.dart';
part 'weibo_auth_resp.g.dart'; part 'weibo_auth_resp.g.dart';
@JsonSerializable( @JsonSerializable(
anyMap: true,
explicitToJson: true, explicitToJson: true,
) )
class WeiboAuthResp extends WeiboSdkResp { class WeiboAuthResp extends WeiboSdkResp {
WeiboAuthResp({ WeiboAuthResp({
int errorCode, required int errorCode,
String errorMessage, String? errorMessage,
this.userId, this.userId,
this.accessToken, this.accessToken,
this.refreshToken, this.refreshToken,
this.expiresIn, this.expiresIn,
}) : super(errorCode: errorCode, errorMessage: errorMessage); }) : super(errorCode: errorCode, errorMessage: errorMessage);
factory WeiboAuthResp.fromJson(Map<dynamic, dynamic> json) => factory WeiboAuthResp.fromJson(Map<String, dynamic> json) =>
_$WeiboAuthRespFromJson(json); _$WeiboAuthRespFromJson(json);
final String userId; final String? userId;
final String accessToken; final String? accessToken;
final String refreshToken; final String? refreshToken;
final int expiresIn; final int? expiresIn;
@override @override
Map<dynamic, dynamic> toJson() => _$WeiboAuthRespToJson(this); Map<String, dynamic> toJson() => _$WeiboAuthRespToJson(this);
} }

View File

@ -6,14 +6,14 @@ part of 'weibo_auth_resp.dart';
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
WeiboAuthResp _$WeiboAuthRespFromJson(Map json) { WeiboAuthResp _$WeiboAuthRespFromJson(Map<String, dynamic> json) {
return WeiboAuthResp( return WeiboAuthResp(
errorCode: json['errorCode'] as int, errorCode: json['errorCode'] as int? ?? 0,
errorMessage: json['errorMessage'] as String, errorMessage: json['errorMessage'] as String?,
userId: json['userId'] as String, userId: json['userId'] as String?,
accessToken: json['accessToken'] as String, accessToken: json['accessToken'] as String?,
refreshToken: json['refreshToken'] as String, refreshToken: json['refreshToken'] as String?,
expiresIn: json['expiresIn'] as int, expiresIn: json['expiresIn'] as int?,
); );
} }

View File

@ -3,16 +3,15 @@ import 'package:json_annotation/json_annotation.dart';
part 'weibo_sdk_resp.g.dart'; part 'weibo_sdk_resp.g.dart';
@JsonSerializable( @JsonSerializable(
anyMap: true,
explicitToJson: true, explicitToJson: true,
) )
class WeiboSdkResp { class WeiboSdkResp {
WeiboSdkResp({ const WeiboSdkResp({
int errorCode, required this.errorCode,
this.errorMessage, this.errorMessage,
}) : errorCode = errorCode ?? SUCCESS; });
factory WeiboSdkResp.fromJson(Map<dynamic, dynamic> json) => factory WeiboSdkResp.fromJson(Map<String, dynamic> json) =>
_$WeiboSdkRespFromJson(json); _$WeiboSdkRespFromJson(json);
/// ///
@ -42,8 +41,15 @@ class WeiboSdkResp {
/// ///
static const int UNKNOWN = -100; static const int UNKNOWN = -100;
@JsonKey(
defaultValue: SUCCESS,
)
final int errorCode; final int errorCode;
final String errorMessage; final String? errorMessage;
Map<dynamic, dynamic> toJson() => _$WeiboSdkRespToJson(this); bool get isSuccessful => errorCode == SUCCESS;
bool get isCancelled => errorCode == USERCANCEL;
Map<String, dynamic> toJson() => _$WeiboSdkRespToJson(this);
} }

View File

@ -6,10 +6,10 @@ part of 'weibo_sdk_resp.dart';
// JsonSerializableGenerator // JsonSerializableGenerator
// ************************************************************************** // **************************************************************************
WeiboSdkResp _$WeiboSdkRespFromJson(Map json) { WeiboSdkResp _$WeiboSdkRespFromJson(Map<String, dynamic> json) {
return WeiboSdkResp( return WeiboSdkResp(
errorCode: json['errorCode'] as int, errorCode: json['errorCode'] as int? ?? 0,
errorMessage: json['errorMessage'] as String, errorMessage: json['errorMessage'] as String?,
); );
} }

View File

@ -3,16 +3,18 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:weibo_kit/src/model/api/weibo_user_info_resp.dart'; import 'package:weibo_kit/src/model/api/weibo_user_info_resp.dart';
import 'package:weibo_kit/src/model/sdk/weibo_auth_resp.dart'; import 'package:weibo_kit/src/model/sdk/weibo_auth_resp.dart';
import 'package:weibo_kit/src/model/sdk/weibo_sdk_resp.dart'; import 'package:weibo_kit/src/model/sdk/weibo_sdk_resp.dart';
class Weibo { class Weibo {
Weibo() { ///
_channel.setMethodCallHandler(_handleMethod); Weibo._();
}
static Weibo get instance => _instance;
static final Weibo _instance = Weibo._();
static const String _METHOD_REGISTERAPP = 'registerApp'; static const String _METHOD_REGISTERAPP = 'registerApp';
static const String _METHOD_ISINSTALLED = 'isInstalled'; static const String _METHOD_ISINSTALLED = 'isInstalled';
@ -40,8 +42,9 @@ class Weibo {
static const String _DEFAULT_REDIRECTURL = static const String _DEFAULT_REDIRECTURL =
'https://api.weibo.com/oauth2/default.html'; 'https://api.weibo.com/oauth2/default.html';
final MethodChannel _channel = late final MethodChannel _channel =
const MethodChannel('v7lin.github.io/weibo_kit'); const MethodChannel('v7lin.github.io/weibo_kit')
..setMethodCallHandler(_handleMethod);
final StreamController<WeiboAuthResp> _authRespStreamController = final StreamController<WeiboAuthResp> _authRespStreamController =
StreamController<WeiboAuthResp>.broadcast(); StreamController<WeiboAuthResp>.broadcast();
@ -50,13 +53,11 @@ class Weibo {
StreamController<WeiboSdkResp>.broadcast(); StreamController<WeiboSdkResp>.broadcast();
Future<void> registerApp({ Future<void> registerApp({
@required String appKey, required String appKey,
@required List<String> scope, required List<String> scope,
String redirectUrl = String redirectUrl =
_DEFAULT_REDIRECTURL, // -> -> -> -> OAuth2.0 _DEFAULT_REDIRECTURL, // -> -> -> -> OAuth2.0
}) { }) {
assert(appKey != null && appKey.isNotEmpty);
assert(scope != null && scope.isNotEmpty);
return _channel.invokeMethod<void>( return _channel.invokeMethod<void>(
_METHOD_REGISTERAPP, _METHOD_REGISTERAPP,
<String, dynamic>{ <String, dynamic>{
@ -71,11 +72,11 @@ class Weibo {
switch (call.method) { switch (call.method) {
case _METHOD_ONAUTHRESP: case _METHOD_ONAUTHRESP:
_authRespStreamController.add( _authRespStreamController.add(
WeiboAuthResp.fromJson(call.arguments as Map<dynamic, dynamic>)); WeiboAuthResp.fromJson(call.arguments as Map<String, dynamic>));
break; break;
case _METHOD_ONSHAREMSGRESP: case _METHOD_ONSHAREMSGRESP:
_shareMsgRespStreamController.add( _shareMsgRespStreamController
WeiboSdkResp.fromJson(call.arguments as Map<dynamic, dynamic>)); .add(WeiboSdkResp.fromJson(call.arguments as Map<String, dynamic>));
break; break;
} }
} }
@ -90,18 +91,16 @@ class Weibo {
return _shareMsgRespStreamController.stream; return _shareMsgRespStreamController.stream;
} }
Future<bool> isInstalled() { Future<bool> isInstalled() async {
return _channel.invokeMethod<bool>(_METHOD_ISINSTALLED); return await _channel.invokeMethod<bool>(_METHOD_ISINSTALLED) ?? false;
} }
/// ///
Future<void> auth({ Future<void> auth({
@required String appKey, required String appKey,
@required List<String> scope, required List<String> scope,
String redirectUrl = _DEFAULT_REDIRECTURL, String redirectUrl = _DEFAULT_REDIRECTURL,
}) { }) {
assert(appKey != null && appKey.isNotEmpty);
assert(scope != null && scope.isNotEmpty);
return _channel.invokeMethod<void>( return _channel.invokeMethod<void>(
_METHOD_AUTH, _METHOD_AUTH,
<String, dynamic>{ <String, dynamic>{
@ -114,13 +113,11 @@ class Weibo {
/// ///
Future<WeiboUserInfoResp> getUserInfo({ Future<WeiboUserInfoResp> getUserInfo({
@required String appkey, required String appkey,
@required String userId, required String userId,
@required String accessToken, required String accessToken,
}) { }) {
assert(userId != null && userId.isNotEmpty); final Map<String, String> params = <String, String>{
assert(accessToken != null && accessToken.isNotEmpty);
Map<String, String> params = <String, String>{
'uid': userId, 'uid': userId,
}; };
return HttpClient() return HttpClient()
@ -130,9 +127,9 @@ class Weibo {
return request.close(); return request.close();
}).then((HttpClientResponse response) async { }).then((HttpClientResponse response) async {
if (response.statusCode == HttpStatus.ok) { if (response.statusCode == HttpStatus.ok) {
String content = await utf8.decodeStream(response); final String content = await utf8.decodeStream(response);
return WeiboUserInfoResp.fromJson( return WeiboUserInfoResp.fromJson(
json.decode(content) as Map<dynamic, dynamic>); json.decode(content) as Map<String, dynamic>);
} }
throw HttpException( throw HttpException(
'HttpResponse statusCode: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}.'); 'HttpResponse statusCode: ${response.statusCode}, reasonPhrase: ${response.reasonPhrase}.');
@ -147,10 +144,10 @@ class Weibo {
) { ) {
params['source'] = appkey; params['source'] = appkey;
params['access_token'] = accessToken; params['access_token'] = accessToken;
Uri baseUri = Uri.parse(baseUrl); final Uri baseUri = Uri.parse(baseUrl);
Map<String, List<String>> queryParametersAll = final Map<String, List<String>> queryParametersAll =
Map<String, List<String>>.of(baseUri.queryParametersAll); Map<String, List<String>>.of(baseUri.queryParametersAll);
for (MapEntry<String, String> entry in params.entries) { for (final MapEntry<String, String> entry in params.entries) {
queryParametersAll.remove(entry.key); queryParametersAll.remove(entry.key);
queryParametersAll.putIfAbsent(entry.key, () => <String>[entry.value]); queryParametersAll.putIfAbsent(entry.key, () => <String>[entry.value]);
} }
@ -159,9 +156,8 @@ class Weibo {
/// - /// -
Future<void> shareText({ Future<void> shareText({
@required String text, required String text,
}) { }) {
assert(text != null && text.length <= 1024);
return _channel.invokeMethod<void>( return _channel.invokeMethod<void>(
_METHOD_SHARETEXT, _METHOD_SHARETEXT,
<String, dynamic>{ <String, dynamic>{
@ -172,9 +168,9 @@ class Weibo {
/// - /// -
Future<void> shareImage({ Future<void> shareImage({
String text, String? text,
Uint8List imageData, Uint8List? imageData,
Uri imageUri, Uri? imageUri,
}) { }) {
assert(text == null || text.length <= 1024); assert(text == null || text.length <= 1024);
assert((imageData != null && imageData.lengthInBytes <= 2 * 1024 * 1024) || assert((imageData != null && imageData.lengthInBytes <= 2 * 1024 * 1024) ||
@ -194,19 +190,15 @@ class Weibo {
/// - /// -
Future<void> shareWebpage({ Future<void> shareWebpage({
@required String title, required String title,
@required String description, required String description,
@required Uint8List thumbData, required Uint8List thumbData,
@required String webpageUrl, required String webpageUrl,
}) { }) {
assert(title != null && title.isNotEmpty && title.length <= 512); assert(title.length <= 512);
assert(description != null && assert(description.isNotEmpty && description.length <= 1024);
description.isNotEmpty && assert(thumbData.lengthInBytes <= 32 * 1024);
description.length <= 1024); assert(webpageUrl.length <= 255);
assert(thumbData != null && thumbData.lengthInBytes <= 32 * 1024);
assert(webpageUrl != null &&
webpageUrl.isNotEmpty &&
webpageUrl.length <= 255);
return _channel.invokeMethod<void>( return _channel.invokeMethod<void>(
_METHOD_SHAREWEBPAGE, _METHOD_SHAREWEBPAGE,
<String, dynamic>{ <String, dynamic>{

View File

@ -1,5 +1,5 @@
class WeiboScope { class WeiboScope {
WeiboScope._(); const WeiboScope._();
static const String EMAIL = 'email'; static const String EMAIL = 'email';
static const String DIRECT_MESSAGES_READ = 'direct_messages_read'; static const String DIRECT_MESSAGES_READ = 'direct_messages_read';

View File

@ -7,168 +7,182 @@ packages:
name: _fe_analyzer_shared name: _fe_analyzer_shared
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "4.0.0" version: "18.0.0"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.39.10" version: "1.2.0"
archive:
dependency: transitive
description:
name: archive
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.13"
args: args:
dependency: transitive dependency: transitive
description: description:
name: args name: args
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.6.0" version: "2.0.0"
async: async:
dependency: transitive dependency: transitive
description: description:
name: async name: async
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.4.1" version: "2.5.0"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
name: boolean_selector name: boolean_selector
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.1.0"
build: build:
dependency: transitive dependency: transitive
description: description:
name: build name: build
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.3.0" version: "2.0.0"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
name: build_config name: build_config
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.4.2" version: "0.4.7"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.4" version: "2.1.10"
build_resolvers: build_resolvers:
dependency: transitive dependency: transitive
description: description:
name: build_resolvers name: build_resolvers
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.3.9" version: "2.0.0"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.10.0" version: "1.12.2"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "5.2.0" version: "6.1.12"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
name: built_collection name: built_collection
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "4.3.2" version: "5.0.0"
built_value: built_value:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "7.1.0" version: "8.0.3"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
charcode: charcode:
dependency: transitive dependency: transitive
description: description:
name: charcode name: charcode
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.3" version: "1.2.0"
checked_yaml: checked_yaml:
dependency: transitive dependency: transitive
description: description:
name: checked_yaml name: checked_yaml
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.2" 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:
name: clock
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
code_builder: code_builder:
dependency: transitive dependency: transitive
description: description:
name: code_builder name: code_builder
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.3.0" version: "3.7.0"
collection: collection:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.14.12" version: "1.15.0"
convert: convert:
dependency: transitive dependency: transitive
description: description:
name: convert name: convert
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.1" version: "3.0.0"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
name: crypto name: crypto
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.4" version: "3.0.0"
csslib:
dependency: transitive
description:
name: csslib
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.16.1"
dart_style: dart_style:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.3.6" version: "1.3.14"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
file: file:
dependency: transitive dependency: transitive
description: description:
name: file name: file
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "5.2.0" version: "6.1.0"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
name: fixnum name: fixnum
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.10.11" version: "1.0.0"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -185,245 +199,140 @@ packages:
name: glob name: glob
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.2.0" version: "2.0.0"
graphs: graphs:
dependency: transitive dependency: transitive
description: description:
name: graphs name: graphs
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.2.0" version: "1.0.0"
html:
dependency: transitive
description:
name: html
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.14.0+3"
http_multi_server: http_multi_server:
dependency: transitive dependency: transitive
description: description:
name: http_multi_server name: http_multi_server
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.2.0" version: "3.0.0"
http_parser: http_parser:
dependency: transitive dependency: transitive
description: description:
name: http_parser name: http_parser
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.1.4" version: "4.0.0"
image:
dependency: transitive
description:
name: image
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.12"
intl:
dependency: transitive
description:
name: intl
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.16.1"
io: io:
dependency: transitive dependency: transitive
description: description:
name: io name: io
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.3.4" version: "1.0.0"
js: js:
dependency: transitive dependency: transitive
description: description:
name: js name: js
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.6.2" version: "0.6.3"
json_annotation: json_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
name: json_annotation name: json_annotation
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.1" version: "4.0.0"
json_serializable: json_serializable:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: json_serializable name: json_serializable
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.3.0" version: "4.0.3"
logging: logging:
dependency: transitive dependency: transitive
description: description:
name: logging name: logging
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.11.4" version: "1.0.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.12.6" version: "0.12.10"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.8" version: "1.3.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
name: mime name: mime
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.9.6+3" version: "1.0.0"
node_interop:
dependency: transitive
description:
name: node_interop
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
node_io:
dependency: transitive
description:
name: node_io
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
okhttp_kit:
dependency: "direct dev"
description:
name: okhttp_kit
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.2"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
name: package_config name: package_config
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.9.3" version: "2.0.0"
path: path:
dependency: "direct dev" dependency: transitive
description: description:
name: path name: path
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.6.4" version: "1.8.0"
path_provider:
dependency: "direct dev"
description:
name: path_provider
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.6.11"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.1+1"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.4+3"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.2"
pedantic: pedantic:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: pedantic name: pedantic
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.9.0" version: "1.11.0"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.0"
platform:
dependency: transitive
description:
name: platform
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.1"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.2"
pool: pool:
dependency: transitive dependency: transitive
description: description:
name: pool name: pool
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.4.0" version: "1.5.0"
process:
dependency: transitive
description:
name: process
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.13"
pub_semver: pub_semver:
dependency: transitive dependency: transitive
description: description:
name: pub_semver name: pub_semver
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.4.4" version: "2.0.0"
pubspec_parse: pubspec_parse:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.1.5" version: "1.0.0"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.3"
shelf: shelf:
dependency: transitive dependency: transitive
description: description:
name: shelf name: shelf
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.7.5" version: "1.1.0"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
name: shelf_web_socket name: shelf_web_socket
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.2.3" version: "1.0.1"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -435,112 +344,98 @@ packages:
name: source_gen name: source_gen
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.9.5" version: "0.9.10+4"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.7.0" version: "1.8.0"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
name: stack_trace name: stack_trace
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.9.3" version: "1.10.0"
stream_channel: stream_channel:
dependency: transitive dependency: transitive
description: description:
name: stream_channel name: stream_channel
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.0" version: "2.1.0"
stream_transform: stream_transform:
dependency: transitive dependency: transitive
description: description:
name: stream_transform name: stream_transform
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.2.0" version: "2.0.0"
string_scanner: string_scanner:
dependency: transitive dependency: transitive
description: description:
name: string_scanner name: string_scanner
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.5" version: "1.1.0"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
name: term_glyph name: term_glyph
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.0" version: "1.2.0"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.2.15" version: "0.2.19"
timing: timing:
dependency: transitive dependency: transitive
description: description:
name: timing name: timing
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.1.1+2" version: "1.0.0"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
name: typed_data name: typed_data
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.6" version: "1.3.0"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
name: vector_math name: vector_math
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.8" version: "2.1.0"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:
name: watcher name: watcher
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "0.9.7+15" version: "1.0.0"
web_socket_channel: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
name: web_socket_channel name: web_socket_channel
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.1.0" version: "2.0.0"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.0"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.6.1"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:
name: yaml name: yaml
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.2.1" version: "3.1.0"
sdks: sdks:
dart: ">=2.7.0 <3.0.0" dart: ">=2.12.0 <3.0.0"
flutter: ">=1.12.13+hotfix.5 <2.0.0" flutter: ">=1.20.0"

View File

@ -1,28 +1,23 @@
name: weibo_kit name: weibo_kit
description: A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Weibo SDKs. description: A powerful Flutter plugin allowing developers to auth/share with natvie Android & iOS Weibo SDKs.
version: 1.1.0 version: 2.0.0
# author: v7lin <v7lin@qq.com> # author: v7lin <v7lin@qq.com>
homepage: https://github.com/v7lin/fake_weibo homepage: https://github.com/rxreader/weibo_kit.git
environment: environment:
sdk: ">=2.7.0 <3.0.0" sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.10.0" flutter: ">=1.20.0"
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
json_annotation: '>=2.0.0 <4.0.0' json_annotation: ^4.0.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
path: ^1.6.4
path_provider: ^1.4.0
okhttp_kit: ^1.0.0
pedantic: pedantic:
build_runner: build_runner:

View File

@ -10,7 +10,6 @@ void main() {
TestWidgetsFlutterBinding.ensureInitialized(); TestWidgetsFlutterBinding.ensureInitialized();
const MethodChannel channel = MethodChannel('v7lin.github.io/weibo_kit'); const MethodChannel channel = MethodChannel('v7lin.github.io/weibo_kit');
final Weibo weibo = Weibo();
setUp(() { setUp(() {
channel.setMockMethodCallHandler((MethodCall call) async { channel.setMockMethodCallHandler((MethodCall call) async {
@ -24,7 +23,7 @@ void main() {
channel.name, channel.name,
channel.codec.encodeMethodCall( channel.codec.encodeMethodCall(
MethodCall('onAuthResp', json.decode('{"errorCode":-1}'))), MethodCall('onAuthResp', json.decode('{"errorCode":-1}'))),
(ByteData data) { (ByteData? data) {
// mock success // mock success
}, },
)); ));
@ -36,7 +35,7 @@ void main() {
channel.name, channel.name,
channel.codec.encodeMethodCall( channel.codec.encodeMethodCall(
MethodCall('onShareMsgResp', json.decode('{"errorCode":-1}'))), MethodCall('onShareMsgResp', json.decode('{"errorCode":-1}'))),
(ByteData data) { (ByteData? data) {
// mock success // mock success
}, },
)); ));
@ -51,15 +50,15 @@ void main() {
}); });
test('isInstalled', () async { test('isInstalled', () async {
expect(await weibo.isInstalled(), true); expect(await Weibo.instance.isInstalled(), true);
}); });
test('auth', () async { test('auth', () async {
StreamSubscription<WeiboAuthResp> sub = final StreamSubscription<WeiboAuthResp> sub =
weibo.authResp().listen((WeiboAuthResp resp) { Weibo.instance.authResp().listen((WeiboAuthResp resp) {
expect(resp.errorCode, WeiboSdkResp.USERCANCEL); expect(resp.errorCode, WeiboSdkResp.USERCANCEL);
}); });
await weibo.auth( await Weibo.instance.auth(
appKey: 'your weibo app key', appKey: 'your weibo app key',
scope: <String>[WeiboScope.ALL], scope: <String>[WeiboScope.ALL],
); );
@ -67,11 +66,11 @@ void main() {
}); });
test('share', () async { test('share', () async {
StreamSubscription<WeiboSdkResp> sub = final StreamSubscription<WeiboSdkResp> sub =
weibo.shareMsgResp().listen((WeiboSdkResp resp) { Weibo.instance.shareMsgResp().listen((WeiboSdkResp resp) {
expect(resp.errorCode, WeiboSdkResp.USERCANCEL); expect(resp.errorCode, WeiboSdkResp.USERCANCEL);
}); });
await weibo.shareText( await Weibo.instance.shareText(
text: 'share text', text: 'share text',
); );
await sub.cancel(); await sub.cancel();