fake_tencent 0.1.0

This commit is contained in:
v7lin
2019-03-19 12:37:11 +08:00
parent 7544f851e7
commit a0bf78ca21
24 changed files with 769 additions and 674 deletions

View File

@ -3,7 +3,7 @@ name: default
steps: steps:
- name: prepare - name: prepare
image: nathansamson/flutter-builder-docker:v1.0.0 image: v7lin/flutter:1.2.1-stable
volumes: volumes:
- name: pub-cache - name: pub-cache
path: /opt/flutter/.pub-cache path: /opt/flutter/.pub-cache
@ -11,7 +11,7 @@ steps:
- flutter packages get - flutter packages get
- name: analyze - name: analyze
image: nathansamson/flutter-builder-docker:v1.0.0 image: v7lin/flutter:1.2.1-stable
volumes: volumes:
- name: pub-cache - name: pub-cache
path: /opt/flutter/.pub-cache path: /opt/flutter/.pub-cache
@ -19,16 +19,17 @@ steps:
- flutter analyze - flutter analyze
- name: test - name: test
image: nathansamson/flutter-builder-docker:v1.0.0 image: v7lin/flutter:1.2.1-stable
volumes: volumes:
- name: pub-cache - name: pub-cache
path: /opt/flutter/.pub-cache path: /opt/flutter/.pub-cache
commands: commands:
- flutter test
- pushd example/ - pushd example/
- flutter test - flutter test
- name: publish-check - name: publish-check
image: nathansamson/flutter-builder-docker:v1.0.0 image: v7lin/flutter:1.2.1-stable
volumes: volumes:
- name: pub-cache - name: pub-cache
path: /opt/flutter/.pub-cache path: /opt/flutter/.pub-cache

View File

@ -19,6 +19,10 @@ analyzer:
# 'super_goes_last' is a deprecated lint rule and should not be used included_file_warning # 'super_goes_last' is a deprecated lint rule and should not be used included_file_warning
included_file_warning: ignore included_file_warning: ignore
# jaguar_serializer
exclude:
- "**/*.jser.dart"
linter: linter:
rules: rules:
# these rules are documented on and in the same order as # these rules are documented on and in the same order as

View File

@ -22,7 +22,7 @@ rootProject.allprojects {
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
android { android {
compileSdkVersion 27 compileSdkVersion 28
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16

View File

@ -24,7 +24,6 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel;
@ -47,21 +46,24 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
channel.setMethodCallHandler(plugin); channel.setMethodCallHandler(plugin);
} }
private static class FakeTencentScene { private static class TencentScene {
public static final int SCENE_QQ = 0; public static final int SCENE_QQ = 0;
public static final int SCENE_QZONE = 1; public static final int SCENE_QZONE = 1;
} }
private static class FakeTencentErrorCode { private static class TencentRetCode {
public static final int ERRORCODE_SUCCESS = 0; // 网络请求成功发送至服务器,并且服务器返回数据格式正确
public static final int ERRORCODE_COMMON = -1; // 这里包括所请求业务操作失败的情况,例如没有授权等原因导致
public static final int ERRORCODE_USERCANCEL = -2; public static final int RET_SUCCESS = 0;
// 网络异常,或服务器返回的数据格式不正确导致无法解析
public static final int RET_FAILED = 1;
public static final int RET_COMMON = -1;
public static final int RET_USERCANCEL = -2;
} }
private static final String METHOD_REGISTERAPP = "registerApp"; private static final String METHOD_REGISTERAPP = "registerApp";
private static final String METHOD_ISQQINSTALLED = "isQQInstalled"; private static final String METHOD_ISQQINSTALLED = "isQQInstalled";
private static final String METHOD_ISQQSUPPORTSSOLOGIN = "isQQSupportSSOLogin"; private static final String METHOD_ISQQSUPPORTSSOLOGIN = "isQQSupportSSOLogin";
private static final String METHOD_SETACCESSTOKEN = "setAccessToken";
private static final String METHOD_LOGIN = "login"; private static final String METHOD_LOGIN = "login";
private static final String METHOD_LOGOUT = "logout"; private static final String METHOD_LOGOUT = "logout";
private static final String METHOD_GETUSERINFO = "getUserInfo"; private static final String METHOD_GETUSERINFO = "getUserInfo";
@ -75,9 +77,6 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
private static final String METHOD_ONSHARERESP = "onShareResp"; private static final String METHOD_ONSHARERESP = "onShareResp";
private static final String ARGUMENT_KEY_APPID = "appId"; private static final String ARGUMENT_KEY_APPID = "appId";
private static final String ARGUMENT_KEY_OPENID = "openId";
private static final String ARGUMENT_KEY_ACCESSTOKEN = "accessToken";
private static final String ARGUMENT_KEY_EXPIRATIONDATE = "expirationDate";
private static final String ARGUMENT_KEY_SCOPE = "scope"; private static final String ARGUMENT_KEY_SCOPE = "scope";
private static final String ARGUMENT_KEY_SCENE = "scene"; private static final String ARGUMENT_KEY_SCENE = "scene";
private static final String ARGUMENT_KEY_TITLE = "title"; private static final String ARGUMENT_KEY_TITLE = "title";
@ -90,19 +89,11 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
private static final String ARGUMENT_KEY_APPNAME = "appName"; private static final String ARGUMENT_KEY_APPNAME = "appName";
private static final String ARGUMENT_KEY_EXTINT = "extInt"; private static final String ARGUMENT_KEY_EXTINT = "extInt";
private static final String ARGUMENT_KEY_RESULT_ERRORCODE = "errorCode"; private static final String ARGUMENT_KEY_RESULT_RET = "ret";
private static final String ARGUMENT_KEY_RESULT_ERRORMSG = "errorMsg"; private static final String ARGUMENT_KEY_RESULT_MSG = "msg";
private static final String ARGUMENT_KEY_RESULT_OPENID = "openId"; private static final String ARGUMENT_KEY_RESULT_OPENID = "openid";
private static final String ARGUMENT_KEY_RESULT_ACCESSTOKEN = "accessToken"; private static final String ARGUMENT_KEY_RESULT_ACCESS_TOKEN = "access_token";
private static final String ARGUMENT_KEY_RESULT_EXPIRATIONDATE = "expirationDate"; private static final String ARGUMENT_KEY_RESULT_EXPIRES_IN = "expires_in";
private static final String URLREQUEST_KEY_RET = "ret";
private static final String URLREQUEST_KEY_MSG = "msg";
// 网络请求成功发送至服务器,并且服务器返回数据格式正确
// 这里包括所请求业务操作失败的情况,例如没有授权等原因导致
private static final int URLREQUEST_SUCCEED = 0;
// 网络异常,或服务器返回的数据格式不正确导致无法解析
private static final int URLREQUEST_FAILED = 1;
private static final String SCHEME_FILE = "file"; private static final String SCHEME_FILE = "file";
@ -133,8 +124,6 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
result.success(isQQInstalled); result.success(isQQInstalled);
} else if (METHOD_ISQQSUPPORTSSOLOGIN.equals(call.method)) { } else if (METHOD_ISQQSUPPORTSSOLOGIN.equals(call.method)) {
result.success(tencent.isSupportSSOLogin(registrar.activity())); result.success(tencent.isSupportSSOLogin(registrar.activity()));
} else if (METHOD_SETACCESSTOKEN.equals(call.method)) {
setAccessToken(call, result);
} else if (METHOD_LOGIN.equals(call.method)) { } else if (METHOD_LOGIN.equals(call.method)) {
login(call, result); login(call, result);
} else if (METHOD_LOGOUT.equals(call.method)) { } else if (METHOD_LOGOUT.equals(call.method)) {
@ -154,20 +143,6 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
} }
} }
private void setAccessToken(MethodCall call, Result result) {
if (tencent != null) {
String openId = call.argument(ARGUMENT_KEY_OPENID);
String accessToken = call.argument(ARGUMENT_KEY_ACCESSTOKEN);
long expirationDate = call.argument(ARGUMENT_KEY_EXPIRATIONDATE);
long expiresIn = TimeUnit.MILLISECONDS.toSeconds(expirationDate - System.currentTimeMillis());
if (expiresIn > 0) {
tencent.setOpenId(openId);
tencent.setAccessToken(accessToken, String.valueOf(expiresIn));
}
}
result.success(null);
}
private void login(MethodCall call, Result result) { private void login(MethodCall call, Result result) {
if (tencent != null) { if (tencent != null) {
String scope = call.argument(ARGUMENT_KEY_SCOPE); String scope = call.argument(ARGUMENT_KEY_SCOPE);
@ -177,9 +152,7 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
} }
private IUiListener loginListener = new IUiListener() { private IUiListener loginListener = new IUiListener() {
private static final String KEY_OPENID = "openid";
private static final String KEY_ACCESS_TOKEN = "access_token";
private static final String KEY_EXPIRES_IN = "expires_in";
@Override @Override
public void onComplete(Object o) { public void onComplete(Object o) {
@ -187,31 +160,31 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
try { try {
if (o != null && o instanceof JSONObject) { if (o != null && o instanceof JSONObject) {
JSONObject object = (JSONObject) o; JSONObject object = (JSONObject) o;
int ret = !object.isNull(URLREQUEST_KEY_RET) ? object.getInt(URLREQUEST_KEY_RET) : URLREQUEST_FAILED; int ret = !object.isNull(ARGUMENT_KEY_RESULT_RET) ? object.getInt(ARGUMENT_KEY_RESULT_RET) : TencentRetCode.RET_FAILED;
String msg = !object.isNull(URLREQUEST_KEY_MSG) ? object.getString(URLREQUEST_KEY_MSG) : null; String msg = !object.isNull(ARGUMENT_KEY_RESULT_MSG) ? object.getString(ARGUMENT_KEY_RESULT_MSG) : null;
if (ret == URLREQUEST_SUCCEED) { if (ret == TencentRetCode.RET_SUCCESS) {
String openId = !object.isNull(KEY_OPENID) ? object.getString(KEY_OPENID) : null; String openId = !object.isNull(ARGUMENT_KEY_RESULT_OPENID) ? object.getString(ARGUMENT_KEY_RESULT_OPENID) : null;
String accessToken = !object.isNull(KEY_ACCESS_TOKEN) ? object.getString(KEY_ACCESS_TOKEN) : null; String accessToken = !object.isNull(ARGUMENT_KEY_RESULT_ACCESS_TOKEN) ? object.getString(ARGUMENT_KEY_RESULT_ACCESS_TOKEN) : null;
final long expiresIn = !object.isNull(KEY_EXPIRES_IN) ? object.getLong(KEY_EXPIRES_IN) : 0; long expiresIn = !object.isNull(ARGUMENT_KEY_RESULT_EXPIRES_IN) ? object.getLong(ARGUMENT_KEY_RESULT_EXPIRES_IN) : 0;
if (!TextUtils.isEmpty(openId) && !TextUtils.isEmpty(accessToken)) { if (!TextUtils.isEmpty(openId) && !TextUtils.isEmpty(accessToken)) {
tencent.setOpenId(openId); tencent.setOpenId(openId);
tencent.setAccessToken(accessToken, String.valueOf(expiresIn)); tencent.setAccessToken(accessToken, String.valueOf(expiresIn));
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_SUCCESS); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_SUCCESS);
map.put(ARGUMENT_KEY_RESULT_OPENID, tencent.getOpenId()); map.put(ARGUMENT_KEY_RESULT_OPENID, openId);
map.put(ARGUMENT_KEY_RESULT_ACCESSTOKEN, tencent.getAccessToken()); map.put(ARGUMENT_KEY_RESULT_ACCESS_TOKEN, accessToken);
map.put(ARGUMENT_KEY_RESULT_EXPIRATIONDATE, tencent.getExpiresIn()); map.put(ARGUMENT_KEY_RESULT_EXPIRES_IN, expiresIn);
} else { } else {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_COMMON); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_ERRORMSG, "openId or accessToken is null."); map.put(ARGUMENT_KEY_RESULT_MSG, "openId or accessToken is null.");
} }
} else { } else {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_COMMON); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_ERRORMSG, msg); map.put(ARGUMENT_KEY_RESULT_MSG, msg);
} }
} }
} catch (JSONException e) { } catch (JSONException e) {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_COMMON); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_ERRORMSG, e.getMessage()); map.put(ARGUMENT_KEY_RESULT_MSG, e.getMessage());
} }
channel.invokeMethod(METHOD_ONLOGINRESP, map); channel.invokeMethod(METHOD_ONLOGINRESP, map);
} }
@ -220,8 +193,8 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
public void onError(UiError uiError) { public void onError(UiError uiError) {
// 登录失败 // 登录失败
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_COMMON); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_ERRORMSG, uiError.errorMessage); map.put(ARGUMENT_KEY_RESULT_MSG, uiError.errorMessage);
channel.invokeMethod(METHOD_ONLOGINRESP, map); channel.invokeMethod(METHOD_ONLOGINRESP, map);
} }
@ -229,7 +202,7 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
public void onCancel() { public void onCancel() {
// 取消登录 // 取消登录
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_USERCANCEL); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_USERCANCEL);
channel.invokeMethod(METHOD_ONLOGINRESP, map); channel.invokeMethod(METHOD_ONLOGINRESP, map);
} }
}; };
@ -251,23 +224,23 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
try { try {
if (o != null && o instanceof JSONObject) { if (o != null && o instanceof JSONObject) {
JSONObject object = (JSONObject) o; JSONObject object = (JSONObject) o;
int ret = !object.isNull(URLREQUEST_KEY_RET) ? object.getInt(URLREQUEST_KEY_RET) : URLREQUEST_FAILED; int ret = !object.isNull(ARGUMENT_KEY_RESULT_RET) ? object.getInt(ARGUMENT_KEY_RESULT_RET) : TencentRetCode.RET_FAILED;
String msg = !object.isNull(URLREQUEST_KEY_MSG) ? object.getString(URLREQUEST_KEY_MSG) : null; String msg = !object.isNull(ARGUMENT_KEY_RESULT_MSG) ? object.getString(ARGUMENT_KEY_RESULT_MSG) : null;
if (ret == URLREQUEST_SUCCEED) { if (ret == TencentRetCode.RET_SUCCESS) {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_SUCCESS); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_SUCCESS);
Iterator<String> keys = object.keys(); Iterator<String> keys = object.keys();
while (keys.hasNext()) { while (keys.hasNext()) {
String key = keys.next(); String key = keys.next();
map.put(key, object.get(key)); map.put(key, object.get(key));
} }
} else { } else {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_COMMON); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_ERRORMSG, msg); map.put(ARGUMENT_KEY_RESULT_MSG, msg);
} }
} }
} catch (JSONException e) { } catch (JSONException e) {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_COMMON); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_ERRORMSG, e.getMessage()); map.put(ARGUMENT_KEY_RESULT_MSG, e.getMessage());
} }
channel.invokeMethod(METHOD_ONGETUSERINFORESP, map); channel.invokeMethod(METHOD_ONGETUSERINFORESP, map);
} }
@ -275,8 +248,8 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
@Override @Override
public void onError(UiError error) { public void onError(UiError error) {
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_COMMON); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_ERRORMSG, error.errorMessage); map.put(ARGUMENT_KEY_RESULT_MSG, error.errorMessage);
channel.invokeMethod(METHOD_ONGETUSERINFORESP, map); channel.invokeMethod(METHOD_ONGETUSERINFORESP, map);
} }
@ -291,8 +264,8 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
private void shareMood(MethodCall call, Result result) { private void shareMood(MethodCall call, Result result) {
if (tencent != null) { if (tencent != null) {
final int scene = call.argument(ARGUMENT_KEY_SCENE); int scene = call.argument(ARGUMENT_KEY_SCENE);
if (scene == FakeTencentScene.SCENE_QZONE) { if (scene == TencentScene.SCENE_QZONE) {
String summary = call.argument(ARGUMENT_KEY_SUMMARY); String summary = call.argument(ARGUMENT_KEY_SUMMARY);
List<String> imageUris = call.argument(ARGUMENT_KEY_IMAGEURIS); List<String> imageUris = call.argument(ARGUMENT_KEY_IMAGEURIS);
String videoUri = call.argument(ARGUMENT_KEY_VIDEOURI); String videoUri = call.argument(ARGUMENT_KEY_VIDEOURI);
@ -323,8 +296,8 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
private void shareImage(MethodCall call, Result result) { private void shareImage(MethodCall call, Result result) {
if (tencent != null) { if (tencent != null) {
final int scene = call.argument(ARGUMENT_KEY_SCENE); int scene = call.argument(ARGUMENT_KEY_SCENE);
if (scene == FakeTencentScene.SCENE_QQ) { if (scene == TencentScene.SCENE_QQ) {
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI); String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
String appName = call.argument(ARGUMENT_KEY_APPNAME); String appName = call.argument(ARGUMENT_KEY_APPNAME);
int extInt = call.argument(ARGUMENT_KEY_EXTINT); int extInt = call.argument(ARGUMENT_KEY_EXTINT);
@ -344,8 +317,8 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
private void shareMusic(MethodCall call, Result result) { private void shareMusic(MethodCall call, Result result) {
if (tencent != null) { if (tencent != null) {
final int scene = call.argument(ARGUMENT_KEY_SCENE); int scene = call.argument(ARGUMENT_KEY_SCENE);
if (scene == FakeTencentScene.SCENE_QQ) { if (scene == TencentScene.SCENE_QQ) {
String title = call.argument(ARGUMENT_KEY_TITLE); String title = call.argument(ARGUMENT_KEY_TITLE);
String summary = call.argument(ARGUMENT_KEY_SUMMARY); String summary = call.argument(ARGUMENT_KEY_SUMMARY);
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI); String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
@ -382,7 +355,7 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
private void shareWebpage(MethodCall call, Result result) { private void shareWebpage(MethodCall call, Result result) {
if (tencent != null) { if (tencent != null) {
final int scene = call.argument(ARGUMENT_KEY_SCENE); int scene = call.argument(ARGUMENT_KEY_SCENE);
String title = call.argument(ARGUMENT_KEY_TITLE); String title = call.argument(ARGUMENT_KEY_TITLE);
String summary = call.argument(ARGUMENT_KEY_SUMMARY); String summary = call.argument(ARGUMENT_KEY_SUMMARY);
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI); String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
@ -392,7 +365,7 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
Bundle params = new Bundle(); Bundle params = new Bundle();
switch (scene) { switch (scene) {
case FakeTencentScene.SCENE_QQ: case TencentScene.SCENE_QQ:
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT); params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
params.putString(QQShare.SHARE_TO_QQ_TITLE, title); params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
if (!TextUtils.isEmpty(summary)) { if (!TextUtils.isEmpty(summary)) {
@ -413,7 +386,7 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, extInt); params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, extInt);
tencent.shareToQQ(registrar.activity(), params, shareListener); tencent.shareToQQ(registrar.activity(), params, shareListener);
break; break;
case FakeTencentScene.SCENE_QZONE: case TencentScene.SCENE_QZONE:
params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE, QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT); params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE, QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT);
params.putString(QzoneShare.SHARE_TO_QQ_TITLE, title); params.putString(QzoneShare.SHARE_TO_QQ_TITLE, title);
if (!TextUtils.isEmpty(summary)) { if (!TextUtils.isEmpty(summary)) {
@ -444,18 +417,18 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
try { try {
if (o != null && o instanceof JSONObject) { if (o != null && o instanceof JSONObject) {
JSONObject object = (JSONObject) o; JSONObject object = (JSONObject) o;
int ret = !object.isNull(URLREQUEST_KEY_RET) ? object.getInt(URLREQUEST_KEY_RET) : URLREQUEST_FAILED; int ret = !object.isNull(ARGUMENT_KEY_RESULT_RET) ? object.getInt(ARGUMENT_KEY_RESULT_RET) : TencentRetCode.RET_FAILED;
String msg = !object.isNull(URLREQUEST_KEY_MSG) ? object.getString(URLREQUEST_KEY_MSG) : null; String msg = !object.isNull(ARGUMENT_KEY_RESULT_MSG) ? object.getString(ARGUMENT_KEY_RESULT_MSG) : null;
if (ret == URLREQUEST_SUCCEED) { if (ret == TencentRetCode.RET_SUCCESS) {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_SUCCESS); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_SUCCESS);
} else { } else {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_COMMON); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_ERRORMSG, msg); map.put(ARGUMENT_KEY_RESULT_MSG, msg);
} }
} }
} catch (JSONException e) { } catch (JSONException e) {
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_COMMON); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_ERRORMSG, e.getMessage()); map.put(ARGUMENT_KEY_RESULT_MSG, e.getMessage());
} }
channel.invokeMethod(METHOD_ONSHARERESP, map); channel.invokeMethod(METHOD_ONSHARERESP, map);
} }
@ -463,15 +436,15 @@ public class FakeTencentPlugin implements MethodCallHandler, PluginRegistry.Acti
@Override @Override
public void onError(UiError error) { public void onError(UiError error) {
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_COMMON); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
map.put(ARGUMENT_KEY_RESULT_ERRORMSG, error.errorMessage); map.put(ARGUMENT_KEY_RESULT_MSG, error.errorMessage);
channel.invokeMethod(METHOD_ONSHARERESP, map); channel.invokeMethod(METHOD_ONSHARERESP, map);
} }
@Override @Override
public void onCancel() { public void onCancel() {
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put(ARGUMENT_KEY_RESULT_ERRORCODE, FakeTencentErrorCode.ERRORCODE_USERCANCEL); map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_USERCANCEL);
channel.invokeMethod(METHOD_ONSHARERESP, map); channel.invokeMethod(METHOD_ONSHARERESP, map);
} }
}; };

View File

@ -25,7 +25,7 @@ apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
compileSdkVersion 27 compileSdkVersion 28
lintOptions { lintOptions {
disable 'InvalidPackage' disable 'InvalidPackage'
@ -35,7 +35,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "io.github.v7lin.faketencentexample" applicationId "io.github.v7lin.faketencentexample"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 27 targetSdkVersion 28
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName

View File

@ -8,7 +8,6 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@ -41,7 +40,6 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; }; 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
@ -83,7 +81,6 @@
9740EEB11CF90186004384FC /* Flutter */ = { 9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
3B80C3931E831B6300D905FE /* App.framework */, 3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEBA1CF902C7004384FC /* Flutter.framework */,
@ -212,7 +209,6 @@
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;

View File

@ -23,9 +23,9 @@ void main() {
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
FakeTencent tencent = FakeTencent(); Tencent tencent = Tencent();
tencent.registerApp(appId: '222222'); tencent.registerApp(appId: '222222');
return FakeTencentProvider( return TencentProvider(
tencent: tencent, tencent: tencent,
child: MaterialApp( child: MaterialApp(
home: Home(tencent: tencent), home: Home(tencent: tencent),
@ -40,7 +40,7 @@ class Home extends StatefulWidget {
@required this.tencent, @required this.tencent,
}) : super(key: key); }) : super(key: key);
final FakeTencent tencent; final Tencent tencent;
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() {
@ -49,9 +49,9 @@ class Home extends StatefulWidget {
} }
class _HomeState extends State<Home> { class _HomeState extends State<Home> {
StreamSubscription<FakeTencentLoginResp> _login; StreamSubscription<TencentLoginResp> _login;
StreamSubscription<FakeTencentUserInfoResp> _userInfo; StreamSubscription<TencentUserInfoResp> _userInfo;
StreamSubscription<FakeTencentShareResp> _share; StreamSubscription<TencentShareResp> _share;
@override @override
void initState() { void initState() {
@ -61,18 +61,18 @@ class _HomeState extends State<Home> {
_share = widget.tencent.shareResp().listen(_listenShare); _share = widget.tencent.shareResp().listen(_listenShare);
} }
void _listenLogin(FakeTencentLoginResp resp) { void _listenLogin(TencentLoginResp resp) {
String content = 'login: ${resp.openId} - ${resp.accessToken}'; String content = 'login: ${resp.openid} - ${resp.accessToken}';
_showTips('登录', content); _showTips('登录', content);
} }
void _listenUserInfo(FakeTencentUserInfoResp resp) { void _listenUserInfo(TencentUserInfoResp resp) {
String content = 'user info: ${resp.nickName} - ${resp.gender}'; String content = 'user info: ${resp.nickname} - ${resp.gender}';
_showTips('用户', content); _showTips('用户', content);
} }
void _listenShare(FakeTencentShareResp resp) { void _listenShare(TencentShareResp resp) {
String content = 'share: ${resp.errorCode} - ${resp.errorMsg}'; String content = 'share: ${resp.ret} - ${resp.msg}';
_showTips('分享', content); _showTips('分享', content);
} }
@ -110,7 +110,7 @@ class _HomeState extends State<Home> {
title: const Text('登录'), title: const Text('登录'),
onTap: () { onTap: () {
widget.tencent.login( widget.tencent.login(
scope: [FakeTencentScope.GET_SIMPLE_USERINFO], scope: [TencentScope.GET_SIMPLE_USERINFO],
); );
}, },
), ),
@ -124,7 +124,7 @@ class _HomeState extends State<Home> {
title: const Text('分享文字'), title: const Text('分享文字'),
onTap: () { onTap: () {
widget.tencent.shareMood( widget.tencent.shareMood(
scene: FakeTencentScene.SCENE_QZONE, scene: TencentScene.SCENE_QZONE,
summary: '分享测试', summary: '分享测试',
); );
}, },
@ -133,7 +133,7 @@ class _HomeState extends State<Home> {
title: const Text('分享链接'), title: const Text('分享链接'),
onTap: () { onTap: () {
widget.tencent.shareWebpage( widget.tencent.shareWebpage(
scene: FakeTencentScene.SCENE_QQ, scene: TencentScene.SCENE_QQ,
title: 'title', title: 'title',
targetUrl: 'https://www.baidu.com/', targetUrl: 'https://www.baidu.com/',
); );

View File

@ -3,7 +3,7 @@ description: Demonstrates how to use the fake_tencent plugin.
publish_to: 'none' publish_to: 'none'
environment: environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0" sdk: ">=2.1.0 <3.0.0"
dependencies: dependencies:
flutter: flutter:

View File

@ -11,10 +11,14 @@ enum FakeTencentScene {
SCENE_QZONE = 1, SCENE_QZONE = 1,
}; };
enum FakeTencentErrorCode { enum FakeTencentRetCode {
ERRORCODE_SUCCESS = 0, // 网络请求成功发送至服务器,并且服务器返回数据格式正确
ERRORCODE_COMMON = -1, // 这里包括所请求业务操作失败的情况,例如没有授权等原因导致
ERRORCODE_USERCANCEL = -2, RET_SUCCESS = 0,
// 网络异常,或服务器返回的数据格式不正确导致无法解析
RET_FAILED = 1,
RET_COMMON = -1,
RET_USERCANCEL = -2,
}; };
@implementation FakeTencentPlugin { @implementation FakeTencentPlugin {
@ -34,7 +38,6 @@ enum FakeTencentErrorCode {
static NSString * const METHOD_REGISTERAPP = @"registerApp"; static NSString * const METHOD_REGISTERAPP = @"registerApp";
static NSString * const METHOD_ISQQINSTALLED = @"isQQInstalled"; static NSString * const METHOD_ISQQINSTALLED = @"isQQInstalled";
static NSString * const METHOD_ISQQSUPPORTSSOLOGIN = @"isQQSupportSSOLogin"; static NSString * const METHOD_ISQQSUPPORTSSOLOGIN = @"isQQSupportSSOLogin";
static NSString * const METHOD_SETACCESSTOKEN = @"setAccessToken";
static NSString * const METHOD_LOGIN = @"login"; static NSString * const METHOD_LOGIN = @"login";
static NSString * const METHOD_LOGOUT = @"logout"; static NSString * const METHOD_LOGOUT = @"logout";
static NSString * const METHOD_GETUSERINFO = @"getUserInfo"; static NSString * const METHOD_GETUSERINFO = @"getUserInfo";
@ -48,9 +51,6 @@ static NSString * const METHOD_ONGETUSERINFORESP = @"onGetUserInfoResp";
static NSString * const METHOD_ONSHARERESP = @"onShareResp"; static NSString * const METHOD_ONSHARERESP = @"onShareResp";
static NSString * const ARGUMENT_KEY_APPID = @"appId"; static NSString * const ARGUMENT_KEY_APPID = @"appId";
static NSString * const ARGUMENT_KEY_OPENID = @"openId";
static NSString * const ARGUMENT_KEY_ACCESSTOKEN = @"accessToken";
static NSString * const ARGUMENT_KEY_EXPIRATIONDATE = @"expirationDate";
static NSString * const ARGUMENT_KEY_SCOPE = @"scope"; static NSString * const ARGUMENT_KEY_SCOPE = @"scope";
static NSString * const ARGUMENT_KEY_SCENE = @"scene"; static NSString * const ARGUMENT_KEY_SCENE = @"scene";
static NSString * const ARGUMENT_KEY_TITLE = @"title"; static NSString * const ARGUMENT_KEY_TITLE = @"title";
@ -63,11 +63,11 @@ static NSString * const ARGUMENT_KEY_TARGETURL = @"targetUrl";
static NSString * const ARGUMENT_KEY_APPNAME = @"appName"; static NSString * const ARGUMENT_KEY_APPNAME = @"appName";
static NSString * const ARGUMENT_KEY_EXTINT = @"extInt"; static NSString * const ARGUMENT_KEY_EXTINT = @"extInt";
static NSString * const ARGUMENT_KEY_RESULT_ERRORCODE = @"errorCode"; static NSString * const ARGUMENT_KEY_RESULT_RET = @"ret";
static NSString * const ARGUMENT_KEY_RESULT_ERRORMSG = @"errorMsg"; static NSString * const ARGUMENT_KEY_RESULT_MSG = @"msg";
static NSString * const ARGUMENT_KEY_RESULT_OPENID = @"openId"; static NSString * const ARGUMENT_KEY_RESULT_OPENID = @"openid";
static NSString * const ARGUMENT_KEY_RESULT_ACCESSTOKEN = @"accessToken"; static NSString * const ARGUMENT_KEY_RESULT_ACCESS_TOKEN = @"access_token";
static NSString * const ARGUMENT_KEY_RESULT_EXPIRATIONDATE = @"expirationDate"; static NSString * const ARGUMENT_KEY_RESULT_EXPIRES_IN = @"expires_in";
static NSString * const SCHEME_FILE = @"file"; static NSString * const SCHEME_FILE = @"file";
@ -88,8 +88,6 @@ static NSString * const SCHEME_FILE = @"file";
result([NSNumber numberWithBool:[TencentOAuth iphoneQQInstalled]]); result([NSNumber numberWithBool:[TencentOAuth iphoneQQInstalled]]);
} else if ([METHOD_ISQQSUPPORTSSOLOGIN isEqualToString:call.method]) { } else if ([METHOD_ISQQSUPPORTSSOLOGIN isEqualToString:call.method]) {
result([NSNumber numberWithBool:[TencentOAuth iphoneQQSupportSSOLogin]]); result([NSNumber numberWithBool:[TencentOAuth iphoneQQSupportSSOLogin]]);
} else if ([METHOD_SETACCESSTOKEN isEqualToString:call.method]) {
[self setAccessToken:call result:result];
} else if ([METHOD_LOGIN isEqualToString:call.method]) { } else if ([METHOD_LOGIN isEqualToString:call.method]) {
[self login:call result:result]; [self login:call result:result];
} else if ([METHOD_LOGOUT isEqualToString:call.method]) { } else if ([METHOD_LOGOUT isEqualToString:call.method]) {
@ -109,17 +107,6 @@ static NSString * const SCHEME_FILE = @"file";
} }
} }
-(void)setAccessToken:(FlutterMethodCall*)call result:(FlutterResult)result {
NSString * openId = call.arguments[ARGUMENT_KEY_OPENID];
NSString * accessToken = call.arguments[ARGUMENT_KEY_ACCESSTOKEN];
NSNumber * expirationDate = call.arguments[ARGUMENT_KEY_EXPIRATIONDATE];
NSTimeInterval seconds = expirationDate.longLongValue / 1000.0;
[_oauth setOpenId:openId];
[_oauth setAccessToken:accessToken];
[_oauth setExpirationDate:[NSDate dateWithTimeIntervalSince1970:seconds]];
result(nil);
}
-(void)login:(FlutterMethodCall*)call result:(FlutterResult)result { -(void)login:(FlutterMethodCall*)call result:(FlutterResult)result {
NSString * scope = call.arguments[ARGUMENT_KEY_SCOPE]; NSString * scope = call.arguments[ARGUMENT_KEY_SCOPE];
NSArray * permissions = [scope componentsSeparatedByString:@","]; NSArray * permissions = [scope componentsSeparatedByString:@","];
@ -270,14 +257,14 @@ static NSString * const SCHEME_FILE = @"file";
if (_oauth.accessToken != nil && _oauth.accessToken.length > 0) { if (_oauth.accessToken != nil && _oauth.accessToken.length > 0) {
NSString * openId = _oauth.openId; NSString * openId = _oauth.openId;
NSString * accessToken = _oauth.accessToken; NSString * accessToken = _oauth.accessToken;
long long expirationDate = _oauth.expirationDate.timeIntervalSince1970 * 1000; long long expiresIn = _oauth.expirationDate.timeIntervalSinceNow * 1000.0 / 1000;
[dictionary setValue:[NSNumber numberWithInt:ERRORCODE_SUCCESS] forKey:ARGUMENT_KEY_RESULT_ERRORCODE]; [dictionary setValue:[NSNumber numberWithInt:RET_SUCCESS] forKey:ARGUMENT_KEY_RESULT_RET];
[dictionary setValue:openId forKey:ARGUMENT_KEY_RESULT_OPENID]; [dictionary setValue:openId forKey:ARGUMENT_KEY_RESULT_OPENID];
[dictionary setValue:accessToken forKey:ARGUMENT_KEY_RESULT_ACCESSTOKEN]; [dictionary setValue:accessToken forKey:ARGUMENT_KEY_RESULT_ACCESS_TOKEN];
[dictionary setValue:[NSNumber numberWithLongLong:expirationDate] forKey:ARGUMENT_KEY_RESULT_EXPIRATIONDATE]; [dictionary setValue:[NSNumber numberWithLongLong:expiresIn] forKey:ARGUMENT_KEY_RESULT_EXPIRES_IN];
} else { } else {
// 登录失败 // 登录失败
[dictionary setValue:[NSNumber numberWithInt:ERRORCODE_COMMON] forKey:ARGUMENT_KEY_RESULT_ERRORCODE]; [dictionary setValue:[NSNumber numberWithInt:RET_COMMON] forKey:ARGUMENT_KEY_RESULT_RET];
} }
[_channel invokeMethod:METHOD_ONLOGINRESP arguments:dictionary]; [_channel invokeMethod:METHOD_ONLOGINRESP arguments:dictionary];
} }
@ -286,10 +273,10 @@ static NSString * const SCHEME_FILE = @"file";
NSMutableDictionary * dictionary = [NSMutableDictionary dictionary]; NSMutableDictionary * dictionary = [NSMutableDictionary dictionary];
if (cancelled) { if (cancelled) {
// 取消登录 // 取消登录
[dictionary setValue:[NSNumber numberWithInt:ERRORCODE_USERCANCEL] forKey:ARGUMENT_KEY_RESULT_ERRORCODE]; [dictionary setValue:[NSNumber numberWithInt:RET_USERCANCEL] forKey:ARGUMENT_KEY_RESULT_RET];
} else { } else {
// 登录失败 // 登录失败
[dictionary setValue:[NSNumber numberWithInt:ERRORCODE_COMMON] forKey:ARGUMENT_KEY_RESULT_ERRORCODE]; [dictionary setValue:[NSNumber numberWithInt:RET_COMMON] forKey:ARGUMENT_KEY_RESULT_RET];
} }
[_channel invokeMethod:METHOD_ONLOGINRESP arguments:dictionary]; [_channel invokeMethod:METHOD_ONLOGINRESP arguments:dictionary];
} }
@ -297,19 +284,19 @@ static NSString * const SCHEME_FILE = @"file";
-(void)tencentDidNotNetWork { -(void)tencentDidNotNetWork {
// 登录失败 // 登录失败
NSMutableDictionary * dictionary = [NSMutableDictionary dictionary]; NSMutableDictionary * dictionary = [NSMutableDictionary dictionary];
[dictionary setValue:[NSNumber numberWithInt:ERRORCODE_COMMON] forKey:ARGUMENT_KEY_RESULT_ERRORCODE]; [dictionary setValue:[NSNumber numberWithInt:RET_COMMON] forKey:ARGUMENT_KEY_RESULT_RET];
[_channel invokeMethod:METHOD_ONLOGINRESP arguments:dictionary]; [_channel invokeMethod:METHOD_ONLOGINRESP arguments:dictionary];
} }
-(void)getUserInfoResponse:(APIResponse *)response { -(void)getUserInfoResponse:(APIResponse *)response {
NSMutableDictionary * dictionary = [NSMutableDictionary dictionary]; NSMutableDictionary * dictionary = [NSMutableDictionary dictionary];
if (response.retCode == URLREQUEST_SUCCEED) { if (response.retCode == URLREQUEST_SUCCEED) {
[dictionary setValue:[NSNumber numberWithInt:ERRORCODE_SUCCESS] forKey:ARGUMENT_KEY_RESULT_ERRORCODE]; [dictionary setValue:[NSNumber numberWithInt:RET_SUCCESS] forKey:ARGUMENT_KEY_RESULT_RET];
NSDictionary * json = response.jsonResponse; NSDictionary * json = response.jsonResponse;
[dictionary addEntriesFromDictionary:json]; [dictionary addEntriesFromDictionary:json];
} else { } else {
[dictionary setValue:[NSNumber numberWithInt:ERRORCODE_COMMON] forKey:ARGUMENT_KEY_RESULT_ERRORCODE]; [dictionary setValue:[NSNumber numberWithInt:RET_COMMON] forKey:ARGUMENT_KEY_RESULT_RET];
[dictionary setValue:response.errorMsg forKey:ARGUMENT_KEY_RESULT_ERRORMSG]; [dictionary setValue:response.errorMsg forKey:ARGUMENT_KEY_RESULT_MSG];
} }
[_channel invokeMethod:METHOD_ONGETUSERINFORESP arguments:dictionary]; [_channel invokeMethod:METHOD_ONGETUSERINFORESP arguments:dictionary];
} }
@ -326,16 +313,16 @@ static NSString * const SCHEME_FILE = @"file";
switch (resp.result.intValue) { switch (resp.result.intValue) {
case 0: case 0:
// 分享成功 // 分享成功
[dictionary setValue:[NSNumber numberWithInt:ERRORCODE_SUCCESS] forKey:ARGUMENT_KEY_RESULT_ERRORCODE]; [dictionary setValue:[NSNumber numberWithInt:RET_SUCCESS] forKey:ARGUMENT_KEY_RESULT_RET];
break; break;
case -4: case -4:
// 用户取消 // 用户取消
[dictionary setValue:[NSNumber numberWithInt:ERRORCODE_USERCANCEL] forKey:ARGUMENT_KEY_RESULT_ERRORCODE]; [dictionary setValue:[NSNumber numberWithInt:RET_USERCANCEL] forKey:ARGUMENT_KEY_RESULT_RET];
break; break;
default: default:
[dictionary setValue:[NSNumber numberWithInt:ERRORCODE_COMMON] forKey:ARGUMENT_KEY_RESULT_ERRORCODE]; [dictionary setValue:[NSNumber numberWithInt:RET_COMMON] forKey:ARGUMENT_KEY_RESULT_RET];
NSString * errorMsg = [NSString stringWithFormat:@"result: %@, description: %@.", resp.result, resp.errorDescription]; NSString * errorMsg = [NSString stringWithFormat:@"result: %@, description: %@.", resp.result, resp.errorDescription];
[dictionary setValue:errorMsg forKey:ARGUMENT_KEY_RESULT_ERRORMSG]; [dictionary setValue:errorMsg forKey:ARGUMENT_KEY_RESULT_MSG];
break; break;
} }
[_channel invokeMethod:METHOD_ONSHARERESP arguments:dictionary]; [_channel invokeMethod:METHOD_ONSHARERESP arguments:dictionary];

View File

@ -1,514 +1,11 @@
import 'dart:async'; library fake_tencent;
import 'package:flutter/services.dart'; export 'src/domain/tencent_base_resp.dart';
import 'package:flutter/widgets.dart'; export 'src/domain/tencent_login_resp.dart' hide TencentLoginRespSerializer;
import 'package:meta/meta.dart'; export 'src/domain/tencent_share_resp.dart' hide TencentShareRespSerializer;
export 'src/domain/tencent_user_info_resp.dart' hide TencentUserInfoRespSerializer;
class FakeTencentScope { export 'src/tencent.dart';
FakeTencentScope._(); export 'src/tencent_provider.dart';
export 'src/tencent_qzone_flag.dart';
/// 发表一条说说到QQ空间(需要申请权限) export 'src/tencent_scene.dart';
static const String OPEN_PERMISSION_ADD_TOPIC = 'add_topic'; export 'src/tencent_scope.dart';
/// 发表一篇日志到QQ空间(需要申请权限)
static const String OPEN_PERMISSION_ADD_ONE_BLOG = 'add_one_blog';
/// 创建一个QQ空间相册(需要申请权限)
static const String OPEN_PERMISSION_ADD_ALBUM = 'add_album';
/// 上传一张照片到QQ空间相册(需要申请权限)
static const String OPEN_PERMISSION_UPLOAD_PIC = 'upload_pic';
/// 获取用户QQ空间相册列表(需要申请权限)
static const String OPEN_PERMISSION_LIST_ALBUM = 'list_album';
/// 同步分享到QQ空间、腾讯微博
static const String OPEN_PERMISSION_ADD_SHARE = 'add_share';
/// 验证是否认证空间粉丝
static const String OPEN_PERMISSION_CHECK_PAGE_FANS = 'check_page_fans';
/// 获取登录用户自己的详细信息
static const String OPEN_PERMISSION_GET_INFO = 'get_info';
/// 获取其他用户的详细信息
static const String OPEN_PERMISSION_GET_OTHER_INFO = 'get_other_info';
/// 获取会员用户基本信息
static const String OPEN_PERMISSION_GET_VIP_INFO = 'get_vip_info';
/// 获取会员用户详细信息
static const String OPEN_PERMISSION_GET_VIP_RICH_INFO = 'get_vip_rich_info';
/// 获取用户信息
static const String GET_USER_INFO = 'get_user_info';
/// 移动端获取用户信息
static const String GET_SIMPLE_USERINFO = 'get_simple_userinfo';
/// 所有权限
static const String ALL = 'all';
}
class FakeTencentScene {
FakeTencentScene._();
/// QQ
static const int SCENE_QQ = 0;
/// QZone
static const int SCENE_QZONE = 1;
}
class FakeTencentQZoneFlag {
FakeTencentQZoneFlag._();
/// 默认是不隐藏分享到QZone按钮且不自动打开分享到QZone的对话框
static const int DEFAULT = 0;
/// 分享时自动打开分享到QZone的对话框
static const int AUTO_OPEN = 1;
/// 分享时隐藏分享到QZone按钮
static const int ITEM_HIDE = 2;
}
class FakeTencentErrorCode {
FakeTencentErrorCode._();
static const int ERRORCODE_SUCCESS = 0;
static const int ERRORCODE_COMMON = -1;
static const int ERRORCODE_USERCANCEL = -2;
}
abstract class FakeTencentBaseResp {
FakeTencentBaseResp({
@required this.errorCode,
@required this.errorMsg,
});
final int errorCode;
final String errorMsg;
}
class FakeTencentLoginResp extends FakeTencentBaseResp {
FakeTencentLoginResp._({
@required int errorCode,
@required String errorMsg,
this.openId,
this.accessToken,
this.expirationDate,
}) : super(errorCode: errorCode, errorMsg: errorMsg);
final String openId;
final String accessToken;
final int expirationDate;
}
class FakeTencentUserInfoResp extends FakeTencentBaseResp {
FakeTencentUserInfoResp._({
@required int errorCode,
@required String errorMsg,
this.nickName,
this.gender,
this.figureurlQQ1,
this.figureurlQQ2,
this.figureurl1,
this.figureurl2,
this.figureurl,
this.vip,
this.level,
this.isYellowVip,
this.isYellowYearVip,
this.yellowVipLevel,
}) : super(errorCode: errorCode, errorMsg: errorMsg);
final String nickName;
/// 男/女
final String gender;
final String figureurlQQ1;
final String figureurlQQ2;
final String figureurl1;
final String figureurl2;
final String figureurl;
final String vip;
final String level;
final String isYellowVip;
final String isYellowYearVip;
final String yellowVipLevel;
bool isMale() {
return gender == '';
}
bool isFemale() {
return gender == '';
}
String headImgUrl() {
if (figureurlQQ2 != null && figureurlQQ2.isNotEmpty) {
return figureurlQQ2;
}
if (figureurlQQ1 != null && figureurlQQ1.isNotEmpty) {
return figureurlQQ1;
}
if (figureurl2 != null && figureurl2.isNotEmpty) {
return figureurl2;
}
if (figureurl1 != null && figureurl1.isNotEmpty) {
return figureurl1;
}
return figureurl;
}
}
class FakeTencentShareResp extends FakeTencentBaseResp {
FakeTencentShareResp._({
@required int errorCode,
@required String errorMsg,
}) : super(errorCode: errorCode, errorMsg: errorMsg);
}
class FakeTencent {
static const String _METHOD_REGISTERAPP = 'registerApp';
static const String _METHOD_ISQQINSTALLED = 'isQQInstalled';
static const String _METHOD_ISQQSUPPORTSSOLOGIN = 'isQQSupportSSOLogin';
static const String _METHOD_SETACCESSTOKEN = 'setAccessToken';
static const String _METHOD_LOGIN = 'login';
static const String _METHOD_LOGOUT = 'logout';
static const String _METHOD_GETUSERINFO = 'getUserInfo';
static const String _METHOD_SHAREMOOD = 'shareMood';
static const String _METHOD_SHAREIMAGE = 'shareImage';
static const String _METHOD_SHAREMUSIC = 'shareMusic';
static const String _METHOD_SHAREWEBPAGE = 'shareWebpage';
static const String _METHOD_ONLOGINRESP = 'onLoginResp';
static const String _METHOD_ONGETUSERINFORESP = 'onGetUserInfoResp';
static const String _METHOD_ONSHARERESP = "onShareResp";
static const String _ARGUMENT_KEY_APPID = 'appId';
static const String _ARGUMENT_KEY_OPENID = 'openId';
static const String _ARGUMENT_KEY_ACCESSTOKEN = 'accessToken';
static const String _ARGUMENT_KEY_EXPIRATIONDATE = 'expirationDate';
static const String _ARGUMENT_KEY_SCOPE = 'scope';
static const String _ARGUMENT_KEY_SCENE = 'scene';
static const String _ARGUMENT_KEY_TITLE = 'title';
static const String _ARGUMENT_KEY_SUMMARY = 'summary';
static const String _ARGUMENT_KEY_IMAGEURI = 'imageUri';
static const String _ARGUMENT_KEY_IMAGEURIS = 'imageUris';
static const String _ARGUMENT_KEY_VIDEOURI = 'videoUri';
static const String _ARGUMENT_KEY_MUSICURL = 'musicUrl';
static const String _ARGUMENT_KEY_TARGETURL = 'targetUrl';
static const String _ARGUMENT_KEY_APPNAME = 'appName';
static const String _ARGUMENT_KEY_EXTINT = 'extInt';
static const String _ARGUMENT_KEY_RESULT_ERRORCODE = 'errorCode';
static const String _ARGUMENT_KEY_RESULT_ERRORMSG = 'errorMsg';
static const String _ARGUMENT_KEY_RESULT_OPENID = 'openId';
static const String _ARGUMENT_KEY_RESULT_ACCESSTOKEN = 'accessToken';
static const String _ARGUMENT_KEY_RESULT_EXPIRATIONDATE = 'expirationDate';
static const String _ARGUMENT_KEY_RESULT_NICKNAME = 'nickname';
static const String _ARGUMENT_KEY_RESULT_GENDER = 'gender';
static const String _ARGUMENT_KEY_RESULT_FIGUREURL_QQ_1 = 'figureurl_qq_1';
static const String _ARGUMENT_KEY_RESULT_FIGUREURL_QQ_2 = 'figureurl_qq_2';
static const String _ARGUMENT_KEY_RESULT_FIGUREURL_1 = 'figureurl_1';
static const String _ARGUMENT_KEY_RESULT_FIGUREURL_2 = 'figureurl_2';
static const String _ARGUMENT_KEY_RESULT_FIGUREURL = 'figureurl';
static const String _ARGUMENT_KEY_RESULT_VIP = 'vip';
static const String _ARGUMENT_KEY_RESULT_LEVEL = 'level';
static const String _ARGUMENT_KEY_RESULT_IS_YELLOW_VIP = 'is_yellow_vip';
static const String _ARGUMENT_KEY_RESULT_IS_YELLOW_YEAR_VIP =
'is_yellow_year_vip';
static const String _ARGUMENT_KEY_RESULT_YELLOW_VIP_LEVEL =
'yellow_vip_level';
static const String _SCHEME_FILE = 'file';
static const MethodChannel _channel =
MethodChannel('v7lin.github.io/fake_tencent');
final StreamController<FakeTencentLoginResp> _loginRespStreamController =
StreamController<FakeTencentLoginResp>.broadcast();
final StreamController<FakeTencentUserInfoResp>
_userInfoRespStreamController =
StreamController<FakeTencentUserInfoResp>.broadcast();
final StreamController<FakeTencentShareResp> _shareRespStreamController =
StreamController<FakeTencentShareResp>.broadcast();
Future<void> registerApp({
@required String appId,
}) {
assert(appId != null && appId.isNotEmpty);
_channel.setMethodCallHandler(_handleMethod);
return _channel.invokeMethod(
_METHOD_REGISTERAPP,
<String, dynamic>{
_ARGUMENT_KEY_APPID: appId,
},
);
}
Future<dynamic> _handleMethod(MethodCall call) async {
switch (call.method) {
case _METHOD_ONLOGINRESP:
_loginRespStreamController.add(FakeTencentLoginResp._(
errorCode: call.arguments[_ARGUMENT_KEY_RESULT_ERRORCODE] as int,
errorMsg: call.arguments[_ARGUMENT_KEY_RESULT_ERRORMSG] as String,
openId: call.arguments[_ARGUMENT_KEY_RESULT_OPENID] as String,
accessToken:
call.arguments[_ARGUMENT_KEY_RESULT_ACCESSTOKEN] as String,
expirationDate:
call.arguments[_ARGUMENT_KEY_RESULT_EXPIRATIONDATE] as int,
));
break;
case _METHOD_ONGETUSERINFORESP:
_userInfoRespStreamController.add(FakeTencentUserInfoResp._(
errorCode: call.arguments[_ARGUMENT_KEY_RESULT_ERRORCODE] as int,
errorMsg: call.arguments[_ARGUMENT_KEY_RESULT_ERRORMSG] as String,
nickName: call.arguments[_ARGUMENT_KEY_RESULT_NICKNAME] as String,
gender: call.arguments[_ARGUMENT_KEY_RESULT_GENDER] as String,
figureurlQQ1:
call.arguments[_ARGUMENT_KEY_RESULT_FIGUREURL_QQ_1] as String,
figureurlQQ2:
call.arguments[_ARGUMENT_KEY_RESULT_FIGUREURL_QQ_2] as String,
figureurl1:
call.arguments[_ARGUMENT_KEY_RESULT_FIGUREURL_1] as String,
figureurl2:
call.arguments[_ARGUMENT_KEY_RESULT_FIGUREURL_2] as String,
figureurl: call.arguments[_ARGUMENT_KEY_RESULT_FIGUREURL] as String,
vip: call.arguments[_ARGUMENT_KEY_RESULT_VIP] as String,
level: call.arguments[_ARGUMENT_KEY_RESULT_LEVEL] as String,
isYellowVip:
call.arguments[_ARGUMENT_KEY_RESULT_IS_YELLOW_VIP] as String,
isYellowYearVip:
call.arguments[_ARGUMENT_KEY_RESULT_IS_YELLOW_YEAR_VIP] as String,
yellowVipLevel:
call.arguments[_ARGUMENT_KEY_RESULT_YELLOW_VIP_LEVEL] as String,
));
break;
case _METHOD_ONSHARERESP:
_shareRespStreamController.add(FakeTencentShareResp._(
errorCode: call.arguments[_ARGUMENT_KEY_RESULT_ERRORCODE] as int,
errorMsg: call.arguments[_ARGUMENT_KEY_RESULT_ERRORMSG] as String,
));
break;
}
}
Stream<FakeTencentLoginResp> loginResp() {
return _loginRespStreamController.stream;
}
Stream<FakeTencentUserInfoResp> userInfoResp() {
return _userInfoRespStreamController.stream;
}
Stream<FakeTencentShareResp> shareResp() {
return _shareRespStreamController.stream;
}
Future<bool> isQQInstalled() async {
return (await _channel.invokeMethod(_METHOD_ISQQINSTALLED)) as bool;
}
Future<bool> isQQSupportSSOLogin() async {
return (await _channel.invokeMethod(_METHOD_ISQQSUPPORTSSOLOGIN)) as bool;
}
Future<void> setAccessToken({
@required String openId,
@required String accessToken,
@required int expirationDate,
}) {
assert(openId != null && openId.isNotEmpty);
assert(accessToken != null && accessToken.isNotEmpty);
return _channel.invokeMethod(
_METHOD_SETACCESSTOKEN,
<String, dynamic>{
_ARGUMENT_KEY_OPENID: openId,
_ARGUMENT_KEY_ACCESSTOKEN: accessToken,
_ARGUMENT_KEY_EXPIRATIONDATE: expirationDate,
},
);
}
Future<void> login({
@required List<String> scope,
}) {
assert(scope != null && scope.isNotEmpty);
return _channel.invokeMethod(
_METHOD_LOGIN,
<String, dynamic>{
_ARGUMENT_KEY_SCOPE: scope.join(','),
},
);
}
Future<void> logout() {
return _channel.invokeMethod(_METHOD_LOGOUT);
}
Future<void> getUserInfo() {
return _channel.invokeMethod(_METHOD_GETUSERINFO);
}
Future<void> shareMood({
@required int scene,
String summary,
List<Uri> imageUris,
Uri videoUri,
}) {
assert(scene == FakeTencentScene.SCENE_QZONE);
assert((summary != null && summary.isNotEmpty) ||
(imageUris != null && imageUris.isNotEmpty) ||
(videoUri != null && videoUri.isScheme(_SCHEME_FILE)));
if (imageUris != null && imageUris.isNotEmpty) {
imageUris.forEach((Uri imageUri) {
assert(imageUri != null && imageUri.isScheme(_SCHEME_FILE));
});
}
Map<String, dynamic> map = <String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
// _ARGUMENT_KEY_SUMMARY: summary,
// _ARGUMENT_KEY_IMAGEURIS: imageUris != null ? new List.generate(imageUris.length, (int index) {
// return imageUris[index].toString();
// }) : null,
// _ARGUMENT_KEY_VIDEOURI: videoUri != null ? videoUri.toString() : null,
};
/// 兼容 iOS 空安全 -> NSNull
if (summary != null && summary.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_SUMMARY, () => summary);
}
if (imageUris != null && imageUris.isNotEmpty) {
map.putIfAbsent(
_ARGUMENT_KEY_IMAGEURIS,
() => List<String>.generate(imageUris.length, (int index) {
return imageUris[index].toString();
}));
}
if (videoUri != null) {
map.putIfAbsent(_ARGUMENT_KEY_VIDEOURI, () => videoUri.toString());
}
return _channel.invokeMethod(_METHOD_SHAREMOOD, map);
}
Future<void> shareImage({
@required int scene,
@required Uri imageUri,
String appName,
int extInt = FakeTencentQZoneFlag.DEFAULT,
}) {
assert(scene == FakeTencentScene.SCENE_QQ);
assert(imageUri != null && imageUri.isScheme(_SCHEME_FILE));
Map<String, dynamic> map = <String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_IMAGEURI: imageUri.toString(),
// _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
};
/// 兼容 iOS 空安全 -> NSNull
if (appName != null && appName.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_APPNAME, () => appName);
}
return _channel.invokeMethod(_METHOD_SHAREIMAGE, map);
}
Future<void> shareMusic({
@required int scene,
@required String title,
String summary,
Uri imageUri,
@required String musicUrl,
@required String targetUrl,
String appName,
int extInt = FakeTencentQZoneFlag.DEFAULT,
}) {
assert(scene == FakeTencentScene.SCENE_QQ);
assert(title != null && title.isNotEmpty);
assert(musicUrl != null && musicUrl.isNotEmpty);
assert(targetUrl != null && targetUrl.isNotEmpty);
Map<String, dynamic> map = <String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_TITLE: title,
// _ARGUMENT_KEY_SUMMARY: summary,
// _ARGUMENT_KEY_IMAGEURI: imageUri != null ? imageUri.toString() : null,
_ARGUMENT_KEY_MUSICURL: musicUrl,
_ARGUMENT_KEY_TARGETURL: targetUrl,
// _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
};
/// 兼容 iOS 空安全 -> NSNull
if (summary != null && summary.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_SUMMARY, () => summary);
}
if (imageUri != null) {
map.putIfAbsent(_ARGUMENT_KEY_IMAGEURI, () => imageUri.toString());
}
if (appName != null && appName.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_APPNAME, () => appName);
}
return _channel.invokeMethod(_METHOD_SHAREMUSIC, map);
}
Future<void> shareWebpage({
@required int scene,
@required String title,
String summary,
Uri imageUri,
@required String targetUrl,
String appName,
int extInt = FakeTencentQZoneFlag.DEFAULT,
}) {
assert(title != null && title.isNotEmpty);
assert(targetUrl != null && targetUrl.isNotEmpty);
Map<String, dynamic> map = <String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_TITLE: title,
// _ARGUMENT_KEY_SUMMARY: summary,
// _ARGUMENT_KEY_IMAGEURI: imageUri != null ? imageUri.toString() : null,
_ARGUMENT_KEY_TARGETURL: targetUrl,
// _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
};
/// 兼容 iOS 空安全 -> NSNull
if (appName != null && appName.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_APPNAME, () => appName);
}
if (imageUri != null) {
map.putIfAbsent(_ARGUMENT_KEY_IMAGEURI, () => imageUri.toString());
}
if (appName != null && appName.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_APPNAME, () => appName);
}
return _channel.invokeMethod(_METHOD_SHAREWEBPAGE, map);
}
}
class FakeTencentProvider extends InheritedWidget {
FakeTencentProvider({
Key key,
@required this.tencent,
@required Widget child,
}) : super(key: key, child: child);
final FakeTencent tencent;
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
FakeTencentProvider oldProvider = oldWidget as FakeTencentProvider;
return tencent != oldProvider.tencent;
}
static FakeTencentProvider of(BuildContext context) {
return context.inheritFromWidgetOfExactType(FakeTencentProvider)
as FakeTencentProvider;
}
}

View File

@ -0,0 +1,22 @@
import 'package:meta/meta.dart';
abstract class TencentBaseResp {
TencentBaseResp({
@required this.ret,
@required this.msg,
});
/// 网络请求成功发送至服务器,并且服务器返回数据格式正确
/// 这里包括所请求业务操作失败的情况,例如没有授权等原因导致
static const int RET_SUCCESS = 0;
/// 网络异常,或服务器返回的数据格式不正确导致无法解析
static const int RET_FAILED = 1;
static const int RET_COMMON = -1;
static const int RET_USERCANCEL = -2;
final int ret;
final String msg;
}

View File

@ -0,0 +1,23 @@
import 'package:jaguar_serializer/jaguar_serializer.dart';
import 'package:fake_tencent/src/domain/tencent_base_resp.dart';
import 'package:meta/meta.dart';
part 'tencent_login_resp.jser.dart';
@GenSerializer(nameFormatter: toSnakeCase)
class TencentLoginRespSerializer extends Serializer<TencentLoginResp>
with _$TencentLoginRespSerializer {}
class TencentLoginResp extends TencentBaseResp {
TencentLoginResp({
@required int ret,
@required String msg,
this.openid,
this.accessToken,
this.expiresIn,
}) : super(ret: ret, msg: msg);
final String openid;
final String accessToken;
final int expiresIn;
}

View File

@ -0,0 +1,35 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'tencent_login_resp.dart';
// **************************************************************************
// JaguarSerializerGenerator
// **************************************************************************
abstract class _$TencentLoginRespSerializer
implements Serializer<TencentLoginResp> {
@override
Map<String, dynamic> toMap(TencentLoginResp model) {
if (model == null) return null;
Map<String, dynamic> ret = <String, dynamic>{};
setMapValue(ret, 'openid', model.openid);
setMapValue(ret, 'access_token', model.accessToken);
setMapValue(ret, 'expires_in', model.expiresIn);
setMapValue(ret, 'ret', model.ret);
setMapValue(ret, 'msg', model.msg);
return ret;
}
@override
TencentLoginResp fromMap(Map map) {
if (map == null) return null;
final obj = new TencentLoginResp(
ret: map['ret'] as int ?? getJserDefault('ret'),
msg: map['msg'] as String ?? getJserDefault('msg'),
openid: map['openid'] as String ?? getJserDefault('openid'),
accessToken:
map['access_token'] as String ?? getJserDefault('accessToken'),
expiresIn: map['expires_in'] as int ?? getJserDefault('expiresIn'));
return obj;
}
}

View File

@ -0,0 +1,16 @@
import 'package:jaguar_serializer/jaguar_serializer.dart';
import 'package:fake_tencent/src/domain/tencent_base_resp.dart';
import 'package:meta/meta.dart';
part 'tencent_share_resp.jser.dart';
@GenSerializer()
class TencentShareRespSerializer extends Serializer<TencentShareResp>
with _$TencentShareRespSerializer {}
class TencentShareResp extends TencentBaseResp {
TencentShareResp({
@required int ret,
@required String msg,
}) : super(ret: ret, msg: msg);
}

View File

@ -0,0 +1,28 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'tencent_share_resp.dart';
// **************************************************************************
// JaguarSerializerGenerator
// **************************************************************************
abstract class _$TencentShareRespSerializer
implements Serializer<TencentShareResp> {
@override
Map<String, dynamic> toMap(TencentShareResp model) {
if (model == null) return null;
Map<String, dynamic> ret = <String, dynamic>{};
setMapValue(ret, 'ret', model.ret);
setMapValue(ret, 'msg', model.msg);
return ret;
}
@override
TencentShareResp fromMap(Map map) {
if (map == null) return null;
final obj = new TencentShareResp(
ret: map['ret'] as int ?? getJserDefault('ret'),
msg: map['msg'] as String ?? getJserDefault('msg'));
return obj;
}
}

View File

@ -0,0 +1,67 @@
import 'package:fake_tencent/src/domain/tencent_base_resp.dart';
import 'package:jaguar_serializer/jaguar_serializer.dart';
import 'package:meta/meta.dart';
part 'tencent_user_info_resp.jser.dart';
@GenSerializer(nameFormatter: toSnakeCase)
class TencentUserInfoRespSerializer extends Serializer<TencentUserInfoResp>
with _$TencentUserInfoRespSerializer {}
class TencentUserInfoResp extends TencentBaseResp {
TencentUserInfoResp({
@required int ret,
@required String msg,
this.nickname,
this.gender,
this.figureurlQq1,
this.figureurlQq2,
this.figureurl1,
this.figureurl2,
this.figureurl,
this.vip,
this.level,
this.isYellowVip,
this.isYellowYearVip,
this.yellowVipLevel,
}) : super(ret: ret, msg: msg);
final String nickname;
/// 男/女
final String gender;
final String figureurlQq1;
final String figureurlQq2;
final String figureurl1;
final String figureurl2;
final String figureurl;
final String vip;
final String level;
final String isYellowVip;
final String isYellowYearVip;
final String yellowVipLevel;
bool isMale() {
return gender == '';
}
bool isFemale() {
return gender == '';
}
String headImgUrl() {
if (figureurlQq2 != null && figureurlQq2.isNotEmpty) {
return figureurlQq2;
}
if (figureurlQq1 != null && figureurlQq1.isNotEmpty) {
return figureurlQq1;
}
if (figureurl2 != null && figureurl2.isNotEmpty) {
return figureurl2;
}
if (figureurl1 != null && figureurl1.isNotEmpty) {
return figureurl1;
}
return figureurl;
}
}

View File

@ -0,0 +1,59 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'tencent_user_info_resp.dart';
// **************************************************************************
// JaguarSerializerGenerator
// **************************************************************************
abstract class _$TencentUserInfoRespSerializer
implements Serializer<TencentUserInfoResp> {
@override
Map<String, dynamic> toMap(TencentUserInfoResp model) {
if (model == null) return null;
Map<String, dynamic> ret = <String, dynamic>{};
setMapValue(ret, 'nickname', model.nickname);
setMapValue(ret, 'gender', model.gender);
setMapValue(ret, 'figureurl_qq_1', model.figureurlQq1);
setMapValue(ret, 'figureurl_qq_2', model.figureurlQq2);
setMapValue(ret, 'figureurl_1', model.figureurl1);
setMapValue(ret, 'figureurl_2', model.figureurl2);
setMapValue(ret, 'figureurl', model.figureurl);
setMapValue(ret, 'vip', model.vip);
setMapValue(ret, 'level', model.level);
setMapValue(ret, 'is_yellow_vip', model.isYellowVip);
setMapValue(ret, 'is_yellow_year_vip', model.isYellowYearVip);
setMapValue(ret, 'yellow_vip_level', model.yellowVipLevel);
setMapValue(ret, 'ret', model.ret);
setMapValue(ret, 'msg', model.msg);
return ret;
}
@override
TencentUserInfoResp fromMap(Map map) {
if (map == null) return null;
final obj = new TencentUserInfoResp(
ret: map['ret'] as int ?? getJserDefault('ret'),
msg: map['msg'] as String ?? getJserDefault('msg'),
nickname: map['nickname'] as String ?? getJserDefault('nickname'),
gender: map['gender'] as String ?? getJserDefault('gender'),
figureurlQq1:
map['figureurl_qq_1'] as String ?? getJserDefault('figureurlQq1'),
figureurlQq2:
map['figureurl_qq_2'] as String ?? getJserDefault('figureurlQq2'),
figureurl1:
map['figureurl_1'] as String ?? getJserDefault('figureurl1'),
figureurl2:
map['figureurl_2'] as String ?? getJserDefault('figureurl2'),
figureurl: map['figureurl'] as String ?? getJserDefault('figureurl'),
vip: map['vip'] as String ?? getJserDefault('vip'),
level: map['level'] as String ?? getJserDefault('level'),
isYellowVip:
map['is_yellow_vip'] as String ?? getJserDefault('isYellowVip'),
isYellowYearVip: map['is_yellow_year_vip'] as String ??
getJserDefault('isYellowYearVip'),
yellowVipLevel: map['yellow_vip_level'] as String ??
getJserDefault('yellowVipLevel'));
return obj;
}
}

260
lib/src/tencent.dart Normal file
View File

@ -0,0 +1,260 @@
import 'dart:async';
import 'dart:convert';
import 'package:fake_tencent/src/domain/tencent_login_resp.dart';
import 'package:fake_tencent/src/domain/tencent_share_resp.dart';
import 'package:fake_tencent/src/domain/tencent_user_info_resp.dart';
import 'package:fake_tencent/src/tencent_qzone_flag.dart';
import 'package:fake_tencent/src/tencent_scene.dart';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart';
class Tencent {
static const String _METHOD_REGISTERAPP = 'registerApp';
static const String _METHOD_ISQQINSTALLED = 'isQQInstalled';
static const String _METHOD_ISQQSUPPORTSSOLOGIN = 'isQQSupportSSOLogin';
static const String _METHOD_LOGIN = 'login';
static const String _METHOD_LOGOUT = 'logout';
static const String _METHOD_GETUSERINFO = 'getUserInfo';
static const String _METHOD_SHAREMOOD = 'shareMood';
static const String _METHOD_SHAREIMAGE = 'shareImage';
static const String _METHOD_SHAREMUSIC = 'shareMusic';
static const String _METHOD_SHAREWEBPAGE = 'shareWebpage';
static const String _METHOD_ONLOGINRESP = 'onLoginResp';
static const String _METHOD_ONGETUSERINFORESP = 'onGetUserInfoResp';
static const String _METHOD_ONSHARERESP = "onShareResp";
static const String _ARGUMENT_KEY_APPID = 'appId';
static const String _ARGUMENT_KEY_SCOPE = 'scope';
static const String _ARGUMENT_KEY_SCENE = 'scene';
static const String _ARGUMENT_KEY_TITLE = 'title';
static const String _ARGUMENT_KEY_SUMMARY = 'summary';
static const String _ARGUMENT_KEY_IMAGEURI = 'imageUri';
static const String _ARGUMENT_KEY_IMAGEURIS = 'imageUris';
static const String _ARGUMENT_KEY_VIDEOURI = 'videoUri';
static const String _ARGUMENT_KEY_MUSICURL = 'musicUrl';
static const String _ARGUMENT_KEY_TARGETURL = 'targetUrl';
static const String _ARGUMENT_KEY_APPNAME = 'appName';
static const String _ARGUMENT_KEY_EXTINT = 'extInt';
static const String _SCHEME_FILE = 'file';
static const MethodChannel _channel =
MethodChannel('v7lin.github.io/fake_tencent');
final StreamController<TencentLoginResp> _loginRespStreamController =
StreamController<TencentLoginResp>.broadcast();
final StreamController<TencentUserInfoResp> _userInfoRespStreamController =
StreamController<TencentUserInfoResp>.broadcast();
final StreamController<TencentShareResp> _shareRespStreamController =
StreamController<TencentShareResp>.broadcast();
Future<void> registerApp({
@required String appId,
}) {
assert(appId != null && appId.isNotEmpty);
_channel.setMethodCallHandler(_handleMethod);
return _channel.invokeMethod(
_METHOD_REGISTERAPP,
<String, dynamic>{
_ARGUMENT_KEY_APPID: appId,
},
);
}
Future<dynamic> _handleMethod(MethodCall call) async {
print('${json.encode(call.arguments)}');
switch (call.method) {
case _METHOD_ONLOGINRESP:
_loginRespStreamController.add(TencentLoginRespSerializer()
.fromMap(call.arguments as Map<dynamic, dynamic>));
break;
case _METHOD_ONGETUSERINFORESP:
_userInfoRespStreamController.add(TencentUserInfoRespSerializer()
.fromMap(call.arguments as Map<dynamic, dynamic>));
break;
case _METHOD_ONSHARERESP:
_shareRespStreamController.add(TencentShareRespSerializer()
.fromMap(call.arguments as Map<dynamic, dynamic>));
break;
}
}
Stream<TencentLoginResp> loginResp() {
return _loginRespStreamController.stream;
}
Stream<TencentUserInfoResp> userInfoResp() {
return _userInfoRespStreamController.stream;
}
Stream<TencentShareResp> shareResp() {
return _shareRespStreamController.stream;
}
Future<bool> isQQInstalled() async {
return (await _channel.invokeMethod(_METHOD_ISQQINSTALLED)) as bool;
}
Future<bool> isQQSupportSSOLogin() async {
return (await _channel.invokeMethod(_METHOD_ISQQSUPPORTSSOLOGIN)) as bool;
}
Future<void> login({
@required List<String> scope,
}) {
assert(scope != null && scope.isNotEmpty);
return _channel.invokeMethod(
_METHOD_LOGIN,
<String, dynamic>{
_ARGUMENT_KEY_SCOPE: scope.join(','),
},
);
}
Future<void> logout() {
return _channel.invokeMethod(_METHOD_LOGOUT);
}
Future<void> getUserInfo() {
return _channel.invokeMethod(_METHOD_GETUSERINFO);
}
Future<void> shareMood({
@required int scene,
String summary,
List<Uri> imageUris,
Uri videoUri,
}) {
assert(scene == TencentScene.SCENE_QZONE);
assert((summary != null && summary.isNotEmpty) ||
(imageUris != null && imageUris.isNotEmpty) ||
(videoUri != null && videoUri.isScheme(_SCHEME_FILE)));
if (imageUris != null && imageUris.isNotEmpty) {
imageUris.forEach((Uri imageUri) {
assert(imageUri != null && imageUri.isScheme(_SCHEME_FILE));
});
}
Map<String, dynamic> map = <String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
// _ARGUMENT_KEY_SUMMARY: summary,
// _ARGUMENT_KEY_IMAGEURIS: imageUris != null ? new List.generate(imageUris.length, (int index) {
// return imageUris[index].toString();
// }) : null,
// _ARGUMENT_KEY_VIDEOURI: videoUri != null ? videoUri.toString() : null,
};
/// 兼容 iOS 空安全 -> NSNull
if (summary != null && summary.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_SUMMARY, () => summary);
}
if (imageUris != null && imageUris.isNotEmpty) {
map.putIfAbsent(
_ARGUMENT_KEY_IMAGEURIS,
() => List<String>.generate(imageUris.length, (int index) {
return imageUris[index].toString();
}));
}
if (videoUri != null) {
map.putIfAbsent(_ARGUMENT_KEY_VIDEOURI, () => videoUri.toString());
}
return _channel.invokeMethod(_METHOD_SHAREMOOD, map);
}
Future<void> shareImage({
@required int scene,
@required Uri imageUri,
String appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
assert(scene == TencentScene.SCENE_QQ);
assert(imageUri != null && imageUri.isScheme(_SCHEME_FILE));
Map<String, dynamic> map = <String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_IMAGEURI: imageUri.toString(),
// _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
};
/// 兼容 iOS 空安全 -> NSNull
if (appName != null && appName.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_APPNAME, () => appName);
}
return _channel.invokeMethod(_METHOD_SHAREIMAGE, map);
}
Future<void> shareMusic({
@required int scene,
@required String title,
String summary,
Uri imageUri,
@required String musicUrl,
@required String targetUrl,
String appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
assert(scene == TencentScene.SCENE_QQ);
assert(title != null && title.isNotEmpty);
assert(musicUrl != null && musicUrl.isNotEmpty);
assert(targetUrl != null && targetUrl.isNotEmpty);
Map<String, dynamic> map = <String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_TITLE: title,
// _ARGUMENT_KEY_SUMMARY: summary,
// _ARGUMENT_KEY_IMAGEURI: imageUri != null ? imageUri.toString() : null,
_ARGUMENT_KEY_MUSICURL: musicUrl,
_ARGUMENT_KEY_TARGETURL: targetUrl,
// _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
};
/// 兼容 iOS 空安全 -> NSNull
if (summary != null && summary.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_SUMMARY, () => summary);
}
if (imageUri != null) {
map.putIfAbsent(_ARGUMENT_KEY_IMAGEURI, () => imageUri.toString());
}
if (appName != null && appName.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_APPNAME, () => appName);
}
return _channel.invokeMethod(_METHOD_SHAREMUSIC, map);
}
Future<void> shareWebpage({
@required int scene,
@required String title,
String summary,
Uri imageUri,
@required String targetUrl,
String appName,
int extInt = TencentQZoneFlag.DEFAULT,
}) {
assert(title != null && title.isNotEmpty);
assert(targetUrl != null && targetUrl.isNotEmpty);
Map<String, dynamic> map = <String, dynamic>{
_ARGUMENT_KEY_SCENE: scene,
_ARGUMENT_KEY_TITLE: title,
// _ARGUMENT_KEY_SUMMARY: summary,
// _ARGUMENT_KEY_IMAGEURI: imageUri != null ? imageUri.toString() : null,
_ARGUMENT_KEY_TARGETURL: targetUrl,
// _ARGUMENT_KEY_APPNAME: appName,
_ARGUMENT_KEY_EXTINT: extInt,
};
/// 兼容 iOS 空安全 -> NSNull
if (appName != null && appName.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_APPNAME, () => appName);
}
if (imageUri != null) {
map.putIfAbsent(_ARGUMENT_KEY_IMAGEURI, () => imageUri.toString());
}
if (appName != null && appName.isNotEmpty) {
map.putIfAbsent(_ARGUMENT_KEY_APPNAME, () => appName);
}
return _channel.invokeMethod(_METHOD_SHAREWEBPAGE, map);
}
}

View File

@ -0,0 +1,23 @@
import 'package:fake_tencent/src/tencent.dart';
import 'package:flutter/widgets.dart';
class TencentProvider extends InheritedWidget {
TencentProvider({
Key key,
@required this.tencent,
@required Widget child,
}) : super(key: key, child: child);
final Tencent tencent;
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
TencentProvider oldProvider = oldWidget as TencentProvider;
return tencent != oldProvider.tencent;
}
static TencentProvider of(BuildContext context) {
return context.inheritFromWidgetOfExactType(TencentProvider)
as TencentProvider;
}
}

View File

@ -0,0 +1,12 @@
class TencentQZoneFlag {
TencentQZoneFlag._();
/// 默认是不隐藏分享到QZone按钮且不自动打开分享到QZone的对话框
static const int DEFAULT = 0;
/// 分享时自动打开分享到QZone的对话框
static const int AUTO_OPEN = 1;
/// 分享时隐藏分享到QZone按钮
static const int ITEM_HIDE = 2;
}

View File

@ -0,0 +1,9 @@
class TencentScene {
TencentScene._();
/// QQ
static const int SCENE_QQ = 0;
/// QZone
static const int SCENE_QZONE = 1;
}

View File

@ -0,0 +1,45 @@
class TencentScope {
TencentScope._();
/// 发表一条说说到QQ空间(需要申请权限)
static const String OPEN_PERMISSION_ADD_TOPIC = 'add_topic';
/// 发表一篇日志到QQ空间(需要申请权限)
static const String OPEN_PERMISSION_ADD_ONE_BLOG = 'add_one_blog';
/// 创建一个QQ空间相册(需要申请权限)
static const String OPEN_PERMISSION_ADD_ALBUM = 'add_album';
/// 上传一张照片到QQ空间相册(需要申请权限)
static const String OPEN_PERMISSION_UPLOAD_PIC = 'upload_pic';
/// 获取用户QQ空间相册列表(需要申请权限)
static const String OPEN_PERMISSION_LIST_ALBUM = 'list_album';
/// 同步分享到QQ空间、腾讯微博
static const String OPEN_PERMISSION_ADD_SHARE = 'add_share';
/// 验证是否认证空间粉丝
static const String OPEN_PERMISSION_CHECK_PAGE_FANS = 'check_page_fans';
/// 获取登录用户自己的详细信息
static const String OPEN_PERMISSION_GET_INFO = 'get_info';
/// 获取其他用户的详细信息
static const String OPEN_PERMISSION_GET_OTHER_INFO = 'get_other_info';
/// 获取会员用户基本信息
static const String OPEN_PERMISSION_GET_VIP_INFO = 'get_vip_info';
/// 获取会员用户详细信息
static const String OPEN_PERMISSION_GET_VIP_RICH_INFO = 'get_vip_rich_info';
/// 获取用户信息
static const String GET_USER_INFO = 'get_user_info';
/// 移动端获取用户信息
static const String GET_SIMPLE_USERINFO = 'get_simple_userinfo';
/// 所有权限
static const String ALL = 'all';
}

View File

@ -5,7 +5,7 @@ author: v7lin <v7lin@qq.com>
homepage: https://github.com/v7lin/fake_tencent homepage: https://github.com/v7lin/fake_tencent
environment: environment:
sdk: ">=2.0.0-dev.68.0 <3.0.0" sdk: ">=2.1.0 <3.0.0"
dependencies: dependencies:
flutter: flutter:
@ -13,12 +13,17 @@ dependencies:
meta: ^1.1.6 meta: ^1.1.6
jaguar_serializer: ^2.2.12
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
pedantic: '>=1.4.0 <3.0.0' pedantic: '>=1.4.0 <3.0.0'
build_runner: ^1.2.3
jaguar_serializer_cli: ^2.2.5
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec # following page: https://www.dartlang.org/tools/pub/pubspec

33
test/jaguar_test.dart Normal file
View File

@ -0,0 +1,33 @@
import 'dart:convert';
import 'package:fake_tencent/src/domain/tencent_login_resp.dart';
import 'package:fake_tencent/src/domain/tencent_share_resp.dart';
import 'package:fake_tencent/src/domain/tencent_user_info_resp.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('smoke test - jaguar_serializer', () {
TencentLoginResp loginResp = TencentLoginRespSerializer().fromMap(json.decode(
'{"ret":0,"access_token":"D3A4D352A06D897D6FD4DED2B8BEEA46","openid":"A13514A5E6385A1D56E1D845303C5FDE","expires_in":7776000}')
as Map<dynamic, dynamic>);
expect(loginResp.ret, equals(0));
expect(loginResp.openid, equals('A13514A5E6385A1D56E1D845303C5FDE'));
expect(loginResp.accessToken, equals('D3A4D352A06D897D6FD4DED2B8BEEA46'));
expect(loginResp.expiresIn, equals(7776000));
TencentUserInfoResp userInfoResp = TencentUserInfoRespSerializer().fromMap(
json.decode(
'{"ret":0,"msg":"","is_lost":1,"gender":"男","is_yellow_vip":"0","city":"福州","year":"1989","level":"0","figureurl_2":"http://qzapp.qlogo.cn/qzapp/222222/942FEA70050EEAFBD4DCE2C1FC775E56/100","figureurl_1":"http://qzapp.qlogo.cn/qzapp/222222/942FEA70050EEAFBD4DCE2C1FC775E56/50","is_yellow_year_vip":"0","province":"福建","constellation":"","figureurl":"http://qzapp.qlogo.cn/qzapp/222222/942FEA70050EEAFBD4DCE2C1FC775E56/30","figureurl_type":"1","figureurl_qq":"http://thirdqq.qlogo.cn/g?b=oidb&k=aicFesDxFa5P0dImvuYicSGw&s=140","nickname":"qquser","yellow_vip_level":"0","figureurl_qq_1":"http://thirdqq.qlogo.cn/g?b=oidb&k=aicFesDxFa5P0dImvuYicSGw&s=40","vip":"0","figureurl_qq_2":"http://thirdqq.qlogo.cn/g?b=oidb&k=aicFesDxFa5P0dImvuYicSGw&s=100"}')
as Map<dynamic, dynamic>);
expect(userInfoResp.ret, equals(0));
expect(userInfoResp.nickname, equals('qquser'));
expect(
userInfoResp.figureurlQq1,
equals(
'http://thirdqq.qlogo.cn/g?b=oidb&k=aicFesDxFa5P0dImvuYicSGw&s=40'));
TencentShareResp shareResp = TencentShareRespSerializer()
.fromMap(json.decode('{"ret":0}') as Map<dynamic, dynamic>);
expect(shareResp.ret, equals(0));
});
}