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
# path: /opt/flutter/.pub-cache
# commands:
# - flutter pub run build_runner clean
# - 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"
#- name: ios-format
# image: v7lin/clang

4
.gitignore vendored
View File

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

View File

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

View File

@ -1,24 +1,24 @@
# weibo_kit
[![Build Status](https://cloud.drone.io/api/badges/v7lin/weibo_kit/status.svg)](https://cloud.drone.io/v7lin/weibo_kit)
[![Codecov](https://codecov.io/gh/v7lin/weibo_kit/branch/master/graph/badge.svg)](https://codecov.io/gh/v7lin/weibo_kit)
[![GitHub Tag](https://img.shields.io/github/tag/v7lin/weibo_kit.svg)](https://github.com/v7lin/weibo_kit/releases)
[![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/rxreader/weibo_kit/branch/master/graph/badge.svg)](https://codecov.io/gh/rxreader/weibo_kit)
[![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)
[![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
## fake libraries
* [flutter版微信SDK](https://github.com/v7lin/wechat_kit)
* [flutter版腾讯(QQ)SDK](https://github.com/v7lin/tencent_kit)
* [flutter版新浪微博SDK](https://github.com/v7lin/weibo_kit)
* [flutter版支付宝SDK](https://github.com/v7lin/alipay_kit)
* [flutter版walle渠道打包工具](https://github.com/v7lin/walle_kit)
* [flutter版微信SDK](https://github.com/rxreader/wechat_kit)
* [flutter版腾讯(QQ)SDK](https://github.com/rxreader/tencent_kit)
* [flutter版新浪微博SDK](https://github.com/rxreader/weibo_kit)
* [flutter版支付宝SDK](https://github.com/rxreader/alipay_kit)
* [flutter版walle渠道打包工具](https://github.com/rxreader/walle_kit)
## dart/flutter
* [simple_pub_server](https://github.com/v7lin/simple_pub_server)
* [simple_pub_server](https://github.com/rxreader/simple_pub_server)
## docs
@ -29,6 +29,15 @@ flutter版新浪微博SDK
## 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
@ -153,13 +162,16 @@ iOS 9系统策略更新限制了http协议的访问此外应用需要在
```
## flutter
* break change
* 2.0.0: nullsafety & Android embedding v1 & Weibo
* snapshot
```
dependencies:
weibo_kit:
git:
url: https://github.com/v7lin/weibo_kit.git
url: https://github.com/rxreader/weibo_kit.git
```
* release

59
analysis_options.yaml Executable file → Normal file
View File

@ -29,12 +29,15 @@ analyzer:
missing_return: warning
# allow having TODOs in the code
todo: ignore
# allow self-reference to deprecated members (we do this because otherwise we have
# to annotate every member in every test, assert, etc, when we deprecate something)
deprecated_member_use_from_same_package: ignore
# Ignore analyzer hints for updating pubspecs when using Future or
# Stream and not importing dart:async
# Please see https://github.com/flutter/flutter/pull/24528 for details.
sdk_version_async_exported_from_core: ignore
exclude:
- "**/*.g.dart"
- "lib/*.g.dart"
linter:
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_require_non_null_named_parameters
- always_specify_types
- always_use_package_imports # we do this commonly
- annotate_overrides
# - avoid_annotating_with_dynamic # conflicts with always_specify_types
# - avoid_as # required for implicit-casts: true
@ -55,7 +59,8 @@ linter:
- avoid_classes_with_only_static_members
# - avoid_double_and_int_checks # only useful when targeting JS runtime
- 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_function_literals_in_foreach_calls
# - avoid_implementing_value_types # not yet tested
@ -74,9 +79,10 @@ linter:
- avoid_returning_null_for_void
# - avoid_returning_this # there are plenty of valid reasons to return this
# - avoid_setters_without_getters # not yet tested
# - avoid_shadowing_type_parameters # not yet tested
- avoid_shadowing_type_parameters
- avoid_single_cascade_in_expression_statements
- avoid_slow_async_io
# - avoid_type_to_string # we do this commonly
- avoid_types_as_parameter_names
# - avoid_types_on_closure_parameters # conflicts with always_specify_types
# - avoid_unnecessary_containers # not yet tested
@ -88,60 +94,66 @@ linter:
- camel_case_types
- cancel_subscriptions
# - cascade_invocations # not yet tested
- cast_nullable_to_non_nullable
# - close_sinks # not reliable enough
# - 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
- 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
- directives_ordering
# - do_not_use_environment # we do this commonly
- empty_catches
- empty_constructor_bodies
- empty_statements
# - file_names # not yet tested
- exhaustive_cases
- file_names # not yet tested
- flutter_style_todos
- hash_and_equals
- implementation_imports
# - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811
- 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_prefixes
# - lines_longer_than_80_chars # not yet tested
# - lines_longer_than_80_chars # not required by flutter style
- list_remove_unrelated_type
# - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181
# - missing_whitespace_between_adjacent_strings # not yet tested
- no_adjacent_strings_in_list
# - no_default_cases # too many false positives
- no_duplicate_case_values
# - no_logic_in_create_state # not yet tested
# - no_runtimeType_toString # not yet tested
- no_logic_in_create_state
# - no_runtimeType_toString # ok in tests; we enable this only in packages/
- 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
# - one_member_abstracts # too many false positives
# - only_throw_errors # https://github.com/flutter/flutter/issues/5792
- overridden_fields
- package_api_docs
- package_names
# - package_names # non conforming packages in sdk
- package_prefixed_library_names
# - parameter_assignments # we do this commonly
- prefer_adjacent_string_concatenation
- 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_conditional_assignment
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- 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_double_quotes # opposite of prefer_single_quotes
- 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_final_fields
# - prefer_final_in_for_each
# - prefer_final_locals
- prefer_final_fields
- prefer_final_in_for_each
- prefer_final_locals
- prefer_for_elements_to_map_fromIterable
- prefer_foreach
# - prefer_function_declarations_over_variables # not yet tested
@ -166,16 +178,18 @@ linter:
# - provide_deprecation_message # not yet tested
# - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml
- recursive_getters
# - sized_box_for_whitespace # not yet tested
- slash_for_doc_comments
# - sort_child_properties_last # not yet tested
- sort_constructors_first
- sort_pub_dependencies
# - sort_pub_dependencies # prevents separating pinned transitive dependencies
- sort_unnamed_constructors_first
- test_types_in_equals
- throw_in_finally
- tighten_type_of_initializing_formals
# - type_annotate_public_apis # subset of always_specify_types
- type_init_formals
# - unawaited_futures # too many false positives
- unawaited_futures # too many false positives
# - unnecessary_await_in_return # not yet tested
- unnecessary_brace_in_string_interps
- unnecessary_const
@ -184,20 +198,27 @@ linter:
# - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498
- unnecessary_new
- unnecessary_null_aware_assignments
# - unnecessary_null_checks # not yet tested
- unnecessary_null_in_if_null_operators
- unnecessary_nullable_for_final_variable_declarations
- unnecessary_overrides
- unnecessary_parenthesis
# - unnecessary_raw_strings # not yet tested
- unnecessary_statements
- unnecessary_string_escapes
- unnecessary_string_interpolations
- unnecessary_this
- unrelated_type_equality_checks
# - unsafe_html # not yet tested
- use_full_hex_values_for_flutter_colors
# - use_function_type_syntax_for_parameters # not yet tested
- use_is_even_rather_than_modulo
# - use_key_in_widget_constructors # not yet tested
- use_late_for_private_fields_and_variables
- use_raw_strings
- use_rethrow_when_possible
# - use_setters_to_change_properties # not yet tested
# - 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
- valid_regexps
- void_checks
- void_checks

View File

@ -1,5 +1,5 @@
group 'io.github.v7lin.weibo_kit'
version '1.1.0'
version '2.0.0'
buildscript {
repositories {
@ -8,7 +8,7 @@ buildscript {
}
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 from: './quality.gradle'
android {
compileSdkVersion 28
@ -54,8 +53,6 @@ android {
}
dependencies {
implementation 'androidx.annotation:annotation:1.0.0'
// v9.12.0
vendorImplementation 'androidx.appcompat:appcompat:1.0.0'
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
zipStoreBase=GRADLE_USER_HOME
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;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
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.activity.ActivityAware;
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 {
// 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
// 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());
}
/**
* WeiboKitPlugin
*/
public class WeiboKitPlugin implements FlutterPlugin, ActivityAware, PluginRegistry.ActivityResultListener, MethodCallHandler {
// --- 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() {
weiboKit = new WeiboKit();
}
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";
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
weiboKit.setApplicationContext(binding.getApplicationContext());
weiboKit.setActivity(null);
weiboKit.startListening(binding.getBinaryMessenger());
}
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";
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
weiboKit.stopListening();
weiboKit.setActivity(null);
weiboKit.setApplicationContext(null);
}
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private MethodChannel channel;
private Context applicationContext;
private ActivityPluginBinding activityPluginBinding;
// --- ActivityAware
private IWBAPI iwbapi;
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
weiboKit.setActivity(binding.getActivity());
pluginBinding = binding;
pluginBinding.addActivityResultListener(weiboKit);
}
// --- FlutterPlugin
@Override
public void onDetachedFromActivityForConfigChanges() {
onDetachedFromActivity();
}
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
channel = new MethodChannel(binding.getBinaryMessenger(), "v7lin.github.io/weibo_kit");
channel.setMethodCallHandler(this);
applicationContext = binding.getApplicationContext();
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
onAttachedToActivity(binding);
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
channel = null;
applicationContext = null;
}
@Override
public void onDetachedFromActivity() {
weiboKit.setActivity(null);
pluginBinding.removeActivityResultListener(weiboKit);
pluginBinding = null;
}
// --- ActivityAware
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
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.WRITE_EXTERNAL_STORAGE" />
<queries>
<!-- targetSdkVersion>=30 -> Android 11 -->
<package android:name="com.sina.weibo" />
</queries>
</manifest>

7
example/.gitignore vendored
View File

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

View File

@ -5,3 +5,7 @@ gradle-wrapper.jar
/gradlew.bat
/local.properties
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 {
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
zipStoreBase=GRADLE_USER_HOME
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,
}
def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
generated_key_values = {}
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) do |line|
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
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
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
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
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
# Flutter Pod
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
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
flutter_additional_ios_build_settings(target)
end
end

View File

@ -1,15 +1,17 @@
PODS:
- Flutter (1.0.0)
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- path_provider (0.0.1):
- Flutter
- path_provider_linux (0.0.1):
- sqflite (0.0.2):
- Flutter
- path_provider_macos (0.0.1):
- FMDB (>= 2.7.5)
- weibo_kit (2.0.0):
- Flutter
- weibo_kit (1.1.0):
- Flutter
- weibo_kit/vendor (= 1.1.0)
- weibo_kit/vendor (1.1.0):
- weibo_kit/vendor (= 2.0.0)
- weibo_kit/vendor (2.0.0):
- Flutter
- Weibo_SDK (~> 3.2.7)
- Weibo_SDK (3.2.7)
@ -17,12 +19,12 @@ PODS:
DEPENDENCIES:
- Flutter (from `Flutter`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- path_provider_linux (from `.symlinks/plugins/path_provider_linux/ios`)
- path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- weibo_kit (from `.symlinks/plugins/weibo_kit/ios`)
SPEC REPOS:
trunk:
- FMDB
- Weibo_SDK
EXTERNAL SOURCES:
@ -30,21 +32,19 @@ EXTERNAL SOURCES:
:path: Flutter
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
path_provider_linux:
:path: ".symlinks/plugins/path_provider_linux/ios"
path_provider_macos:
:path: ".symlinks/plugins/path_provider_macos/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
weibo_kit:
:path: ".symlinks/plugins/weibo_kit/ios"
SPEC CHECKSUMS:
Flutter: 0e3d915762c693b495b44d77113d4970485de6ec
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
path_provider_linux: 4d630dc393e1f20364f3e3b4a2ff41d9674a84e4
path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0
weibo_kit: 82a3b5501bbe2ae59528e683a80277079ecc95cb
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
weibo_kit: 9327afb47ffde6c4fd4b091973f91eae4440a0c4
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 */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
1F77EE1FF4C528197971DB94 /* [CP] Embed Pods Frameworks */,
BEFF80007E7E4E2B2694658C /* [CP] Copy Pods Resources */,
);
buildRules = (
@ -208,23 +207,6 @@
/* End PBXResourcesBuildPhase 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 */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;

View File

@ -3,26 +3,22 @@ import 'dart:io';
import 'dart:typed_data';
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: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';
void main() {
runZoned(() {
runApp(MyApp());
}, onError: (dynamic error, dynamic stack) {
print(error);
print(stack);
});
const String _WEIBO_APP_KEY = 'your weibo app key';
const List<String> _WEIBO_SCOPE = <String>[
WeiboScope.ALL,
];
if (Platform.isAndroid) {
SystemUiOverlayStyle systemUiOverlayStyle =
const SystemUiOverlayStyle(statusBarColor: Colors.transparent);
SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);
}
void main() {
WidgetsFlutterBinding.ensureInitialized();
Weibo.instance.registerApp(
appKey: _WEIBO_APP_KEY,
scope: _WEIBO_SCOPE,
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@ -42,48 +38,33 @@ class Home extends StatefulWidget {
}
class _HomeState extends State<Home> {
static const String _WEIBO_APP_KEY = 'your weibo app key';
static const List<String> _WEIBO_SCOPE = <String>[
WeiboScope.ALL,
];
late final StreamSubscription<WeiboAuthResp> _auth =
Weibo.instance.authResp().listen(_listenAuth);
late final StreamSubscription<WeiboSdkResp> _share =
Weibo.instance.shareMsgResp().listen(_listenShareMsg);
Weibo _weibo = Weibo()
..registerApp(
appKey: _WEIBO_APP_KEY,
scope: _WEIBO_SCOPE,
);
StreamSubscription<WeiboAuthResp> _auth;
StreamSubscription<WeiboSdkResp> _share;
WeiboAuthResp _authResp;
WeiboAuthResp? _authResp;
@override
void initState() {
super.initState();
_auth = _weibo.authResp().listen(_listenAuth);
_share = _weibo.shareMsgResp().listen(_listenShareMsg);
}
void _listenAuth(WeiboAuthResp resp) {
_authResp = resp;
String content = 'auth: ${resp.errorCode}';
final String content = 'auth: ${resp.errorCode}';
_showTips('登录', content);
}
void _listenShareMsg(WeiboSdkResp resp) {
String content = 'share: ${resp.errorCode}';
final String content = 'share: ${resp.errorCode}';
_showTips('分享', content);
}
@override
void dispose() {
if (_auth != null) {
_auth.cancel();
}
if (_share != null) {
_share.cancel();
}
_auth.cancel();
_share.cancel();
super.dispose();
}
@ -98,14 +79,15 @@ class _HomeState extends State<Home> {
ListTile(
title: const Text('环境检查'),
onTap: () async {
String content = 'weibo: ${await _weibo.isInstalled()}';
final String content =
'weibo: ${await Weibo.instance.isInstalled()}';
_showTips('环境检查', content);
},
),
ListTile(
title: const Text('登录'),
onTap: () {
_weibo.auth(
Weibo.instance.auth(
appKey: _WEIBO_APP_KEY,
scope: _WEIBO_SCOPE,
);
@ -114,15 +96,14 @@ class _HomeState extends State<Home> {
ListTile(
title: const Text('用户信息'),
onTap: () async {
if (_authResp != null &&
_authResp.errorCode == WeiboSdkResp.SUCCESS) {
WeiboUserInfoResp userInfoResp = await _weibo.getUserInfo(
if (_authResp?.isSuccessful ?? false) {
final WeiboUserInfoResp userInfoResp =
await Weibo.instance.getUserInfo(
appkey: _WEIBO_APP_KEY,
userId: _authResp.userId,
accessToken: _authResp.accessToken,
userId: _authResp!.userId!,
accessToken: _authResp!.accessToken!,
);
if (userInfoResp != null &&
userInfoResp.errorCode == WeiboApiResp.ERROR_CODE_SUCCESS) {
if (userInfoResp.isSuccessful) {
_showTips('用户信息',
'${userInfoResp.screenName}\n${userInfoResp.description}\n${userInfoResp.location}\n${userInfoResp.profileImageUrl}');
} else {
@ -135,7 +116,7 @@ class _HomeState extends State<Home> {
ListTile(
title: const Text('文字分享'),
onTap: () {
_weibo.shareText(
Weibo.instance.shareText(
text: 'Share Text',
);
},
@ -143,70 +124,32 @@ class _HomeState extends State<Home> {
ListTile(
title: const Text('图片分享'),
onTap: () async {
OkHttpClient client = OkHttpClientBuilder().build();
Response resp = await client
.newCall(RequestBuilder()
.get()
.url(HttpUrl.parse(
'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),
);
}
final File file = await DefaultCacheManager().getSingleFile(
'https://www.baidu.com/img/bd_logo1.png?where=super');
await Weibo.instance.shareImage(
text: 'Share Text',
imageUri: Uri.file(file.path),
);
},
),
ListTile(
title: const Text('网页分享'),
onTap: () async {
OkHttpClient client = OkHttpClientBuilder().build();
Response resp = await client
.newCall(RequestBuilder()
.get()
.url(HttpUrl.parse(
'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,
);
}
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',
);
final File file = await DefaultCacheManager().getSingleFile(
'https://www.baidu.com/img/bd_logo1.png?where=super');
final image.Image thumbnail =
image.decodeImage(file.readAsBytesSync())!;
Uint8List thumbData = thumbnail.getBytes();
if (thumbData.length > 32 * 1024) {
thumbData = Uint8List.fromList(image.encodeJpg(thumbnail,
quality: 100 * 32 * 1024 ~/ thumbData.length));
}
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
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.13"
args:
dependency: transitive
description:
name: args
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.6.0"
version: "3.1.2"
async:
dependency: transitive
description:
name: async
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.1"
version: "2.5.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.flutter-io.cn"
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:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
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:
dependency: transitive
description:
name: collection
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.14.12"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.1"
version: "1.15.0"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
version: "3.0.0"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
url: "https://pub.flutter-io.cn"
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:
dependency: transitive
description:
name: file
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.2.0"
fixnum:
dependency: transitive
description:
name: fixnum
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.10.11"
version: "6.1.0"
flutter:
dependency: "direct main"
description: flutter
source: sdk
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:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
image:
http:
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:
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"
version: "3.0.1"
json_annotation:
dependency: transitive
description:
name: json_annotation
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.1"
version: "4.0.0"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.12.6"
version: "0.12.10"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.8"
okhttp_kit:
dependency: "direct main"
description:
name: okhttp_kit
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.2"
version: "1.3.0"
path:
dependency: "direct main"
dependency: transitive
description:
name: path
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.6.4"
version: "1.8.0"
path_provider:
dependency: "direct main"
dependency: transitive
description:
name: path_provider
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.6.11"
version: "2.0.1"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.1+1"
version: "2.0.0"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.0.4+3"
version: "2.0.0"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.flutter-io.cn"
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:
dependency: "direct dev"
description:
name: pedantic
url: "https://pub.flutter-io.cn"
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"
version: "4.0.2"
platform:
dependency: transitive
description:
name: platform
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.1"
version: "3.0.0"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.2"
version: "2.0.0"
process:
dependency: transitive
description:
name: process
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.13"
quiver:
version: "4.1.0"
rxdart:
dependency: transitive
description:
name: quiver
name: rxdart
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.3"
version: "0.26.0"
sky_engine:
dependency: transitive
description: flutter
@ -218,77 +239,112 @@ packages:
name: source_span
url: "https://pub.flutter-io.cn"
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:
dependency: transitive
description:
name: stack_trace
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.9.3"
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0"
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.flutter-io.cn"
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:
dependency: transitive
description:
name: term_glyph
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.0"
version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.15"
version: "0.2.19"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.flutter-io.cn"
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:
dependency: transitive
description:
name: vector_math
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.8"
version: "2.1.0"
weibo_kit:
dependency: "direct main"
description:
path: ".."
relative: true
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:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.0"
version: "0.2.0"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.6.1"
version: "5.0.2"
sdks:
dart: ">=2.7.0 <3.0.0"
flutter: ">=1.12.13+hotfix.5 <2.0.0"
dart: ">=2.12.0 <3.0.0"
flutter: ">=1.24.0-10"

View File

@ -1,12 +1,14 @@
name: weibo_kit_example
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
# 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
environment:
sdk: ">=2.7.0 <3.0.0"
sdk: ">=2.12.0 <3.0.0"
version: 1.0.0+100
dependencies:
flutter:
@ -22,12 +24,10 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.3
cupertino_icons: ^1.0.2
path: ^1.6.4
path_provider: ^1.4.0
okhttp_kit: ^1.0.0
image: ^3.0.1
flutter_cache_manager: ^3.0.0-nullsafety.1
dev_dependencies:
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|
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.description = <<-DESC
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 {
WeiboApiResp({
int errorCode,
const WeiboApiResp({
required this.errorCode,
this.error,
this.request,
}) : errorCode = errorCode ?? ERROR_CODE_SUCCESS;
});
static const int ERROR_CODE_SUCCESS = 0;
/// https://open.weibo.com/wiki/Help/error
@JsonKey(
defaultValue: ERROR_CODE_SUCCESS,
)
final int errorCode;
final String error;
final String request;
final String? error;
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';
@JsonSerializable(
anyMap: true,
explicitToJson: true,
fieldRename: FieldRename.snake,
)
class WeiboUserInfoResp extends WeiboApiResp {
WeiboUserInfoResp({
int errorCode,
String error,
String request,
const WeiboUserInfoResp({
required int errorCode,
String? error,
String? request,
this.id,
this.idstr,
this.screenName,
@ -25,46 +24,42 @@ class WeiboUserInfoResp extends WeiboApiResp {
this.avatarHd,
}) : super(errorCode: errorCode, error: error, request: request);
factory WeiboUserInfoResp.fromJson(Map<dynamic, dynamic> json) =>
factory WeiboUserInfoResp.fromJson(Map<String, dynamic> json) =>
_$WeiboUserInfoRespFromJson(json);
/// UIDint64
final int id;
final int? id;
/// 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
final String profileImageUrl;
final String? profileImageUrl;
/// mfn
final String gender;
final String? gender;
///
final String avatarLarge;
final String? avatarLarge;
///
final String avatarHd;
final String? avatarHd;
bool isMale() {
return gender == 'm';
}
bool get isMale => gender == 'm';
bool isFemale() {
return gender == 'f';
}
bool get isFemale => 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
// **************************************************************************
WeiboUserInfoResp _$WeiboUserInfoRespFromJson(Map json) {
WeiboUserInfoResp _$WeiboUserInfoRespFromJson(Map<String, dynamic> json) {
return WeiboUserInfoResp(
errorCode: json['error_code'] as int,
error: json['error'] as String,
request: json['request'] as String,
id: json['id'] as int,
idstr: json['idstr'] as String,
screenName: json['screen_name'] as String,
name: json['name'] as String,
location: json['location'] as String,
description: json['description'] as String,
profileImageUrl: json['profile_image_url'] as String,
gender: json['gender'] as String,
avatarLarge: json['avatar_large'] as String,
avatarHd: json['avatar_hd'] as String,
errorCode: json['error_code'] as int? ?? 0,
error: json['error'] as String?,
request: json['request'] as String?,
id: json['id'] as int?,
idstr: json['idstr'] as String?,
screenName: json['screen_name'] as String?,
name: json['name'] as String?,
location: json['location'] as String?,
description: json['description'] as String?,
profileImageUrl: json['profile_image_url'] as String?,
gender: json['gender'] as String?,
avatarLarge: json['avatar_large'] 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';
@JsonSerializable(
anyMap: true,
explicitToJson: true,
)
class WeiboAuthResp extends WeiboSdkResp {
WeiboAuthResp({
int errorCode,
String errorMessage,
required int errorCode,
String? errorMessage,
this.userId,
this.accessToken,
this.refreshToken,
this.expiresIn,
}) : super(errorCode: errorCode, errorMessage: errorMessage);
factory WeiboAuthResp.fromJson(Map<dynamic, dynamic> json) =>
factory WeiboAuthResp.fromJson(Map<String, dynamic> json) =>
_$WeiboAuthRespFromJson(json);
final String userId;
final String accessToken;
final String refreshToken;
final int expiresIn;
final String? userId;
final String? accessToken;
final String? refreshToken;
final int? expiresIn;
@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
// **************************************************************************
WeiboAuthResp _$WeiboAuthRespFromJson(Map json) {
WeiboAuthResp _$WeiboAuthRespFromJson(Map<String, dynamic> json) {
return WeiboAuthResp(
errorCode: json['errorCode'] as int,
errorMessage: json['errorMessage'] as String,
userId: json['userId'] as String,
accessToken: json['accessToken'] as String,
refreshToken: json['refreshToken'] as String,
expiresIn: json['expiresIn'] as int,
errorCode: json['errorCode'] as int? ?? 0,
errorMessage: json['errorMessage'] as String?,
userId: json['userId'] as String?,
accessToken: json['accessToken'] as String?,
refreshToken: json['refreshToken'] as String?,
expiresIn: json['expiresIn'] as int?,
);
}

View File

@ -3,16 +3,15 @@ import 'package:json_annotation/json_annotation.dart';
part 'weibo_sdk_resp.g.dart';
@JsonSerializable(
anyMap: true,
explicitToJson: true,
)
class WeiboSdkResp {
WeiboSdkResp({
int errorCode,
const WeiboSdkResp({
required this.errorCode,
this.errorMessage,
}) : errorCode = errorCode ?? SUCCESS;
});
factory WeiboSdkResp.fromJson(Map<dynamic, dynamic> json) =>
factory WeiboSdkResp.fromJson(Map<String, dynamic> json) =>
_$WeiboSdkRespFromJson(json);
///
@ -42,8 +41,15 @@ class WeiboSdkResp {
///
static const int UNKNOWN = -100;
@JsonKey(
defaultValue: SUCCESS,
)
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
// **************************************************************************
WeiboSdkResp _$WeiboSdkRespFromJson(Map json) {
WeiboSdkResp _$WeiboSdkRespFromJson(Map<String, dynamic> json) {
return WeiboSdkResp(
errorCode: json['errorCode'] as int,
errorMessage: json['errorMessage'] as String,
errorCode: json['errorCode'] as int? ?? 0,
errorMessage: json['errorMessage'] as String?,
);
}

View File

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

View File

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

View File

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

View File

@ -1,28 +1,23 @@
name: weibo_kit
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>
homepage: https://github.com/v7lin/fake_weibo
homepage: https://github.com/rxreader/weibo_kit.git
environment:
sdk: ">=2.7.0 <3.0.0"
flutter: ">=1.10.0"
sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.20.0"
dependencies:
flutter:
sdk: flutter
json_annotation: '>=2.0.0 <4.0.0'
json_annotation: ^4.0.0
dev_dependencies:
flutter_test:
sdk: flutter
path: ^1.6.4
path_provider: ^1.4.0
okhttp_kit: ^1.0.0
pedantic:
build_runner:

View File

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