mirror of
https://github.com/RxReader/tencent_kit.git
synced 2025-05-20 16:56:33 +08:00
@ -1,3 +1,8 @@
|
||||
## 1.1.0 - 2020.06.13
|
||||
|
||||
* 升级 V2 插件
|
||||
* 升级 Android/iOS SDK
|
||||
|
||||
## 1.0.4 - 2019.12.16
|
||||
|
||||
* 适配 Android Q 本地分享适配(别问为什么,腾讯有毒!)
|
||||
|
@ -48,7 +48,9 @@ android {
|
||||
```
|
||||
|
||||
```
|
||||
<!-- 腾讯有毒吧,文档都不写,SDK里居然写死 android:authorities 为 com.tencent.tauth.fileprovider,而非不同应用不同 android:authorities -->
|
||||
<!-- 腾讯有毒吧,这特么是文档? -->
|
||||
<!-- 继续吐槽个,尼玛简直就是坑 -->
|
||||
<!-- 知道怎么集成使用 FileProvider 有用?不知道怎么测试好吗?写个简单的测试分享图片,图片都无法分享好吗?不带这么坑爹的好吗? -->
|
||||
<manifest>
|
||||
<!-- targetSdkVersion >= 29, 豁免 Android Q 的外部存储沙箱限制 -->
|
||||
<application android:requestLegacyExternalStorage="true">
|
||||
|
@ -8,7 +8,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.2'
|
||||
classpath 'com.android.tools.build:gradle:3.5.0'
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ android {
|
||||
minSdkVersion 16
|
||||
|
||||
// library 混淆 -> 随 library 引用,自动添加到 apk 打包混淆
|
||||
consumerProguardFiles 'consumer-proguard-rules.pro'
|
||||
consumerProguardFiles 'consumer-rules.pro'
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
|
||||
android.enableR8=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.enableR8=true
|
||||
|
5
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
|
Binary file not shown.
BIN
android/libs/open_sdk_r8353806_lite.jar
Normal file
BIN
android/libs/open_sdk_r8353806_lite.jar
Normal file
Binary file not shown.
@ -4,10 +4,9 @@
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<!--<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />-->
|
||||
<!--<uses-permission android:name="android.permission.WRITE_APN_SETTINGS"/>-->
|
||||
|
||||
<!-- 不建议使用 android:requestLegacyExternalStorage="true" 豁免 Android Q 的外部存储沙箱限制 -->
|
||||
<application
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="UnusedAttribute">
|
||||
@ -36,16 +35,15 @@
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||
|
||||
<!-- Android Q 的外部存储沙箱限制 -->
|
||||
<!-- 腾讯有毒吧,文档都不写,SDK里居然写死 android:authorities 为 com.tencent.tauth.fileprovider,而非不同应用不同 android:authorities -->
|
||||
<!-- <provider
|
||||
<provider
|
||||
android:name=".content.TencentKitFileProvider"
|
||||
android:authorities="com.tencent.tauth.fileprovider"
|
||||
android:authorities="${applicationId}.content.TencentKitFileProvider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/tencent_kit_file_paths" />
|
||||
</provider> -->
|
||||
</provider>
|
||||
</application>
|
||||
</manifest>
|
||||
|
@ -0,0 +1,488 @@
|
||||
package io.github.v7lin.tencent_kit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.tencent.connect.common.Constants;
|
||||
import com.tencent.connect.share.QQShare;
|
||||
import com.tencent.connect.share.QzonePublish;
|
||||
import com.tencent.connect.share.QzoneShare;
|
||||
import com.tencent.tauth.IUiListener;
|
||||
import com.tencent.tauth.Tencent;
|
||||
import com.tencent.tauth.UiError;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugin.common.MethodCall;
|
||||
import io.flutter.plugin.common.MethodChannel;
|
||||
import io.flutter.plugin.common.PluginRegistry;
|
||||
import io.github.v7lin.tencent_kit.content.TencentKitFileProvider;
|
||||
|
||||
public class TencentKit implements MethodChannel.MethodCallHandler, PluginRegistry.ActivityResultListener {
|
||||
|
||||
private static class TencentScene {
|
||||
static final int SCENE_QQ = 0;
|
||||
static final int SCENE_QZONE = 1;
|
||||
}
|
||||
|
||||
private static class TencentRetCode {
|
||||
// 网络请求成功发送至服务器,并且服务器返回数据格式正确
|
||||
// 这里包括所请求业务操作失败的情况,例如没有授权等原因导致
|
||||
static final int RET_SUCCESS = 0;
|
||||
// 网络异常,或服务器返回的数据格式不正确导致无法解析
|
||||
static final int RET_FAILED = 1;
|
||||
static final int RET_COMMON = -1;
|
||||
static final int RET_USERCANCEL = -2;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private static final String METHOD_REGISTERAPP = "registerApp";
|
||||
private static final String METHOD_ISQQINSTALLED = "isQQInstalled";
|
||||
private static final String METHOD_ISTIMINSTALLED = "isTIMInstalled";
|
||||
private static final String METHOD_LOGIN = "login";
|
||||
private static final String METHOD_LOGOUT = "logout";
|
||||
private static final String METHOD_SHAREMOOD = "shareMood";
|
||||
private static final String METHOD_SHARETEXT = "shareText";
|
||||
private static final String METHOD_SHAREIMAGE = "shareImage";
|
||||
private static final String METHOD_SHAREMUSIC = "shareMusic";
|
||||
private static final String METHOD_SHAREWEBPAGE = "shareWebpage";
|
||||
|
||||
private static final String METHOD_ONLOGINRESP = "onLoginResp";
|
||||
private static final String METHOD_ONSHARERESP = "onShareResp";
|
||||
|
||||
private static final String ARGUMENT_KEY_APPID = "appId";
|
||||
// private static final String ARGUMENT_KEY_UNIVERSALLINK = "universalLink";
|
||||
private static final String ARGUMENT_KEY_SCOPE = "scope";
|
||||
private static final String ARGUMENT_KEY_SCENE = "scene";
|
||||
private static final String ARGUMENT_KEY_TITLE = "title";
|
||||
private static final String ARGUMENT_KEY_SUMMARY = "summary";
|
||||
private static final String ARGUMENT_KEY_IMAGEURI = "imageUri";
|
||||
private static final String ARGUMENT_KEY_IMAGEURIS = "imageUris";
|
||||
private static final String ARGUMENT_KEY_VIDEOURI = "videoUri";
|
||||
private static final String ARGUMENT_KEY_MUSICURL = "musicUrl";
|
||||
private static final String ARGUMENT_KEY_TARGETURL = "targetUrl";
|
||||
private static final String ARGUMENT_KEY_APPNAME = "appName";
|
||||
private static final String ARGUMENT_KEY_EXTINT = "extInt";
|
||||
|
||||
private static final String ARGUMENT_KEY_RESULT_RET = "ret";
|
||||
private static final String ARGUMENT_KEY_RESULT_MSG = "msg";
|
||||
private static final String ARGUMENT_KEY_RESULT_OPENID = "openid";
|
||||
private static final String ARGUMENT_KEY_RESULT_ACCESS_TOKEN = "access_token";
|
||||
private static final String ARGUMENT_KEY_RESULT_EXPIRES_IN = "expires_in";
|
||||
private static final String ARGUMENT_KEY_RESULT_CREATE_AT = "create_at";
|
||||
|
||||
private static final String SCHEME_FILE = "file";
|
||||
|
||||
//
|
||||
|
||||
private Context applicationContext;
|
||||
private Activity activity;
|
||||
|
||||
private MethodChannel channel;
|
||||
private Tencent tencent;
|
||||
|
||||
public TencentKit() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TencentKit(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/tencent_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)) {
|
||||
final String appId = call.argument(ARGUMENT_KEY_APPID);
|
||||
// final String universalLink = call.argument(ARGUMENT_KEY_UNIVERSALLINK);
|
||||
String authority = null;
|
||||
try {
|
||||
ProviderInfo providerInfo = applicationContext.getPackageManager().getProviderInfo(new ComponentName(applicationContext, TencentKitFileProvider.class), PackageManager.MATCH_DEFAULT_ONLY);
|
||||
authority = providerInfo.authority;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
}
|
||||
if (!TextUtils.isEmpty(authority)) {
|
||||
tencent = Tencent.createInstance(appId, applicationContext, authority);
|
||||
} else {
|
||||
tencent = Tencent.createInstance(appId, applicationContext);
|
||||
}
|
||||
result.success(null);
|
||||
} else if (METHOD_ISQQINSTALLED.equals(call.method)) {
|
||||
result.success(isAppInstalled(applicationContext, "com.tencent.mobileqq"));
|
||||
} else if (METHOD_ISTIMINSTALLED.equals(call.method)) {
|
||||
result.success(isAppInstalled(applicationContext, "com.tencent.tim"));
|
||||
} else if (METHOD_LOGIN.equals(call.method)) {
|
||||
login(call, result);
|
||||
} else if (METHOD_LOGOUT.equals(call.method)) {
|
||||
logout(call, result);
|
||||
} else if (METHOD_SHAREMOOD.equals(call.method)) {
|
||||
shareMood(call, result);
|
||||
} else if (METHOD_SHARETEXT.equals(call.method)) {
|
||||
shareText(call, result);
|
||||
} else if (METHOD_SHAREIMAGE.equals(call.method)) {
|
||||
shareImage(call, result);
|
||||
} else if (METHOD_SHAREMUSIC.equals(call.method)) {
|
||||
shareMusic(call, result);
|
||||
} else if (METHOD_SHAREWEBPAGE.equals(call.method)) {
|
||||
shareWebpage(call, result);
|
||||
} else {
|
||||
result.notImplemented();
|
||||
}
|
||||
}
|
||||
|
||||
private void login(MethodCall call, MethodChannel.Result result) {
|
||||
if (tencent != null) {
|
||||
String scope = call.argument(ARGUMENT_KEY_SCOPE);
|
||||
tencent.login(activity, scope, loginListener);
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private IUiListener loginListener = new IUiListener() {
|
||||
@Override
|
||||
public void onComplete(Object o) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
try {
|
||||
if (o != null && o instanceof JSONObject) {
|
||||
JSONObject object = (JSONObject) o;
|
||||
int ret = !object.isNull(ARGUMENT_KEY_RESULT_RET) ? object.getInt(ARGUMENT_KEY_RESULT_RET) : TencentRetCode.RET_FAILED;
|
||||
String msg = !object.isNull(ARGUMENT_KEY_RESULT_MSG) ? object.getString(ARGUMENT_KEY_RESULT_MSG) : null;
|
||||
if (ret == TencentRetCode.RET_SUCCESS) {
|
||||
String openId = !object.isNull(ARGUMENT_KEY_RESULT_OPENID) ? object.getString(ARGUMENT_KEY_RESULT_OPENID) : null;
|
||||
String accessToken = !object.isNull(ARGUMENT_KEY_RESULT_ACCESS_TOKEN) ? object.getString(ARGUMENT_KEY_RESULT_ACCESS_TOKEN) : null;
|
||||
int expiresIn = !object.isNull(ARGUMENT_KEY_RESULT_EXPIRES_IN) ? object.getInt(ARGUMENT_KEY_RESULT_EXPIRES_IN) : 0;
|
||||
long createAt = System.currentTimeMillis();
|
||||
if (!TextUtils.isEmpty(openId) && !TextUtils.isEmpty(accessToken)) {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_SUCCESS);
|
||||
map.put(ARGUMENT_KEY_RESULT_OPENID, openId);
|
||||
map.put(ARGUMENT_KEY_RESULT_ACCESS_TOKEN, accessToken);
|
||||
map.put(ARGUMENT_KEY_RESULT_EXPIRES_IN, expiresIn);
|
||||
map.put(ARGUMENT_KEY_RESULT_CREATE_AT, createAt);
|
||||
} else {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, "openId or accessToken is null.");
|
||||
}
|
||||
} else {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, msg);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, e.getMessage());
|
||||
}
|
||||
channel.invokeMethod(METHOD_ONLOGINRESP, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(UiError uiError) {
|
||||
// 登录失败
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, uiError.errorMessage);
|
||||
channel.invokeMethod(METHOD_ONLOGINRESP, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// 取消登录
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_USERCANCEL);
|
||||
channel.invokeMethod(METHOD_ONLOGINRESP, map);
|
||||
}
|
||||
};
|
||||
|
||||
private void logout(MethodCall call, MethodChannel.Result result) {
|
||||
if (tencent != null) {
|
||||
tencent.logout(applicationContext);
|
||||
result.success(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void shareMood(MethodCall call, MethodChannel.Result result) {
|
||||
if (tencent != null) {
|
||||
int scene = call.argument(ARGUMENT_KEY_SCENE);
|
||||
if (scene == TencentScene.SCENE_QZONE) {
|
||||
String summary = call.argument(ARGUMENT_KEY_SUMMARY);
|
||||
List<String> imageUris = call.argument(ARGUMENT_KEY_IMAGEURIS);
|
||||
String videoUri = call.argument(ARGUMENT_KEY_VIDEOURI);
|
||||
|
||||
Bundle params = new Bundle();
|
||||
if (!TextUtils.isEmpty(summary)) {
|
||||
params.putString(QzonePublish.PUBLISH_TO_QZONE_SUMMARY, summary);
|
||||
}
|
||||
if (imageUris != null && !imageUris.isEmpty()) {
|
||||
ArrayList<String> uris = new ArrayList<>();
|
||||
for (String imageUri : imageUris) {
|
||||
uris.add(Uri.parse(imageUri).getPath());
|
||||
}
|
||||
params.putStringArrayList(QzonePublish.PUBLISH_TO_QZONE_IMAGE_URL, uris);
|
||||
}
|
||||
if (!TextUtils.isEmpty(videoUri)) {
|
||||
String videoPath = Uri.parse(videoUri).getPath();
|
||||
params.putString(QzonePublish.PUBLISH_TO_QZONE_VIDEO_PATH, videoPath);
|
||||
params.putInt(QzonePublish.PUBLISH_TO_QZONE_KEY_TYPE, QzonePublish.PUBLISH_TO_QZONE_TYPE_PUBLISHVIDEO);
|
||||
} else {
|
||||
params.putInt(QzonePublish.PUBLISH_TO_QZONE_KEY_TYPE, QzonePublish.PUBLISH_TO_QZONE_TYPE_PUBLISHMOOD);
|
||||
}
|
||||
tencent.publishToQzone(activity, params, shareListener);
|
||||
}
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private void shareText(MethodCall call, MethodChannel.Result result) {
|
||||
int scene = call.argument(ARGUMENT_KEY_SCENE);
|
||||
if (scene == TencentScene.SCENE_QQ) {
|
||||
String summary = call.argument(ARGUMENT_KEY_SUMMARY);
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, summary);
|
||||
sendIntent.setType("text/*");
|
||||
// 普通大众版 > 办公简洁版 > 急速轻聊版
|
||||
PackageManager packageManager = applicationContext.getPackageManager();
|
||||
List<PackageInfo> infos = packageManager.getInstalledPackages(0);
|
||||
if (infos != null && !infos.isEmpty()) {
|
||||
for (String packageName : Arrays.asList("com.tencent.mobileqq", "com.tencent.tim", "com.tencent.qqlite")) {
|
||||
for (PackageInfo info : infos) {
|
||||
if (packageName.equals(info.packageName)) {
|
||||
sendIntent.setPackage(packageName);
|
||||
if (sendIntent.resolveActivity(applicationContext.getPackageManager()) != null) {
|
||||
sendIntent.setComponent(new ComponentName(packageName, "com.tencent.mobileqq.activity.JumpActivity"));
|
||||
activity.startActivity(sendIntent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private void shareImage(MethodCall call, MethodChannel.Result result) {
|
||||
if (tencent != null) {
|
||||
int scene = call.argument(ARGUMENT_KEY_SCENE);
|
||||
if (scene == TencentScene.SCENE_QQ) {
|
||||
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
|
||||
String appName = call.argument(ARGUMENT_KEY_APPNAME);
|
||||
int extInt = call.argument(ARGUMENT_KEY_EXTINT);
|
||||
|
||||
Bundle params = new Bundle();
|
||||
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_IMAGE);
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, Uri.parse(imageUri).getPath());
|
||||
if (!TextUtils.isEmpty(appName)) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, appName);
|
||||
}
|
||||
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, extInt);
|
||||
tencent.shareToQQ(activity, params, shareListener);
|
||||
}
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private void shareMusic(MethodCall call, MethodChannel.Result result) {
|
||||
if (tencent != null) {
|
||||
int scene = call.argument(ARGUMENT_KEY_SCENE);
|
||||
if (scene == TencentScene.SCENE_QQ) {
|
||||
String title = call.argument(ARGUMENT_KEY_TITLE);
|
||||
String summary = call.argument(ARGUMENT_KEY_SUMMARY);
|
||||
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
|
||||
String musicUrl = call.argument(ARGUMENT_KEY_MUSICURL);
|
||||
String targetUrl = call.argument(ARGUMENT_KEY_TARGETURL);
|
||||
String appName = call.argument(ARGUMENT_KEY_APPNAME);
|
||||
int extInt = call.argument(ARGUMENT_KEY_EXTINT);
|
||||
|
||||
Bundle params = new Bundle();
|
||||
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_AUDIO);
|
||||
params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
|
||||
if (!TextUtils.isEmpty(summary)) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_SUMMARY, summary);
|
||||
}
|
||||
if (!TextUtils.isEmpty(imageUri)) {
|
||||
Uri uri = Uri.parse(imageUri);
|
||||
if (TextUtils.equals(SCHEME_FILE, uri.getScheme())) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, uri.getPath());
|
||||
} else {
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, imageUri);
|
||||
}
|
||||
}
|
||||
params.putString(QQShare.SHARE_TO_QQ_AUDIO_URL, musicUrl);
|
||||
params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, targetUrl);
|
||||
if (!TextUtils.isEmpty(appName)) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, appName);
|
||||
}
|
||||
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, extInt);
|
||||
tencent.shareToQQ(activity, params, shareListener);
|
||||
}
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private void shareWebpage(MethodCall call, MethodChannel.Result result) {
|
||||
if (tencent != null) {
|
||||
int scene = call.argument(ARGUMENT_KEY_SCENE);
|
||||
String title = call.argument(ARGUMENT_KEY_TITLE);
|
||||
String summary = call.argument(ARGUMENT_KEY_SUMMARY);
|
||||
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
|
||||
String targetUrl = call.argument(ARGUMENT_KEY_TARGETURL);
|
||||
String appName = call.argument(ARGUMENT_KEY_APPNAME);
|
||||
int extInt = call.argument(ARGUMENT_KEY_EXTINT);
|
||||
|
||||
Bundle params = new Bundle();
|
||||
switch (scene) {
|
||||
case TencentScene.SCENE_QQ:
|
||||
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
|
||||
params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
|
||||
if (!TextUtils.isEmpty(summary)) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_SUMMARY, summary);
|
||||
}
|
||||
if (!TextUtils.isEmpty(imageUri)) {
|
||||
Uri uri = Uri.parse(imageUri);
|
||||
if (TextUtils.equals(SCHEME_FILE, uri.getScheme())) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, uri.getPath());
|
||||
} else {
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, imageUri);
|
||||
}
|
||||
}
|
||||
params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, targetUrl);
|
||||
if (!TextUtils.isEmpty(appName)) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, appName);
|
||||
}
|
||||
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, extInt);
|
||||
tencent.shareToQQ(activity, params, shareListener);
|
||||
break;
|
||||
case TencentScene.SCENE_QZONE:
|
||||
params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE, QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT);
|
||||
params.putString(QzoneShare.SHARE_TO_QQ_TITLE, title);
|
||||
if (!TextUtils.isEmpty(summary)) {
|
||||
params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, summary);
|
||||
}
|
||||
if (!TextUtils.isEmpty(imageUri)) {
|
||||
ArrayList<String> uris = new ArrayList<>();
|
||||
Uri uri = Uri.parse(imageUri);
|
||||
if (TextUtils.equals(SCHEME_FILE, uri.getScheme())) {
|
||||
uris.add(uri.getPath());
|
||||
} else {
|
||||
uris.add(imageUri);
|
||||
}
|
||||
params.putStringArrayList(QzoneShare.SHARE_TO_QQ_IMAGE_URL, uris);
|
||||
}
|
||||
params.putString(QzoneShare.SHARE_TO_QQ_TARGET_URL, targetUrl);
|
||||
tencent.shareToQzone(activity, params, shareListener);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private IUiListener shareListener = new IUiListener() {
|
||||
@Override
|
||||
public void onComplete(Object o) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
try {
|
||||
if (o != null && o instanceof JSONObject) {
|
||||
JSONObject object = (JSONObject) o;
|
||||
int ret = !object.isNull(ARGUMENT_KEY_RESULT_RET) ? object.getInt(ARGUMENT_KEY_RESULT_RET) : TencentRetCode.RET_FAILED;
|
||||
String msg = !object.isNull(ARGUMENT_KEY_RESULT_MSG) ? object.getString(ARGUMENT_KEY_RESULT_MSG) : null;
|
||||
if (ret == TencentRetCode.RET_SUCCESS) {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_SUCCESS);
|
||||
} else {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, msg);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, e.getMessage());
|
||||
}
|
||||
channel.invokeMethod(METHOD_ONSHARERESP, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(UiError error) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, error.errorMessage);
|
||||
channel.invokeMethod(METHOD_ONSHARERESP, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_USERCANCEL);
|
||||
channel.invokeMethod(METHOD_ONSHARERESP, map);
|
||||
}
|
||||
};
|
||||
|
||||
// --- ActivityResultListener
|
||||
|
||||
@Override
|
||||
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
case Constants.REQUEST_LOGIN:
|
||||
return Tencent.onActivityResultData(requestCode, resultCode, data, loginListener);
|
||||
case Constants.REQUEST_QQ_SHARE:
|
||||
case Constants.REQUEST_QZONE_SHARE:
|
||||
return Tencent.onActivityResultData(requestCode, resultCode, data, shareListener);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---
|
||||
|
||||
private static boolean isAppInstalled(Context context, String packageName) {
|
||||
PackageInfo packageInfo = null;
|
||||
try {
|
||||
packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
}
|
||||
return packageInfo != null;
|
||||
}
|
||||
}
|
@ -1,460 +1,78 @@
|
||||
package io.github.v7lin.tencent_kit;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.tencent.connect.common.Constants;
|
||||
import com.tencent.connect.share.QQShare;
|
||||
import com.tencent.connect.share.QzonePublish;
|
||||
import com.tencent.connect.share.QzoneShare;
|
||||
import com.tencent.tauth.IUiListener;
|
||||
import com.tencent.tauth.Tencent;
|
||||
import com.tencent.tauth.UiError;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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.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;
|
||||
import io.flutter.plugin.common.PluginRegistry.Registrar;
|
||||
|
||||
/**
|
||||
* TencentKitPlugin
|
||||
*/
|
||||
public class TencentKitPlugin implements MethodCallHandler, PluginRegistry.ActivityResultListener {
|
||||
/**
|
||||
* Plugin registration.
|
||||
*/
|
||||
public static void registerWith(Registrar registrar) {
|
||||
final MethodChannel channel = new MethodChannel(registrar.messenger(), "v7lin.github.io/tencent_kit");
|
||||
TencentKitPlugin plugin = new TencentKitPlugin(registrar, channel);
|
||||
registrar.addActivityResultListener(plugin);
|
||||
channel.setMethodCallHandler(plugin);
|
||||
public class TencentKitPlugin 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(PluginRegistry.Registrar registrar) {
|
||||
TencentKit tencentKit = new TencentKit(registrar.context(), registrar.activity());
|
||||
registrar.addActivityResultListener(tencentKit);
|
||||
tencentKit.startListening(registrar.messenger());
|
||||
}
|
||||
|
||||
private static class TencentScene {
|
||||
static final int SCENE_QQ = 0;
|
||||
static final int SCENE_QZONE = 1;
|
||||
}
|
||||
// --- FlutterPlugin
|
||||
|
||||
private static class TencentRetCode {
|
||||
// 网络请求成功发送至服务器,并且服务器返回数据格式正确
|
||||
// 这里包括所请求业务操作失败的情况,例如没有授权等原因导致
|
||||
static final int RET_SUCCESS = 0;
|
||||
// 网络异常,或服务器返回的数据格式不正确导致无法解析
|
||||
static final int RET_FAILED = 1;
|
||||
static final int RET_COMMON = -1;
|
||||
static final int RET_USERCANCEL = -2;
|
||||
}
|
||||
private final TencentKit tencentKit;
|
||||
|
||||
private static final String METHOD_REGISTERAPP = "registerApp";
|
||||
private static final String METHOD_ISQQINSTALLED = "isQQInstalled";
|
||||
private static final String METHOD_ISTIMINSTALLED = "isTIMInstalled";
|
||||
private static final String METHOD_ISQQLITEINSTALLED = "isQQLiteInstalled";
|
||||
private static final String METHOD_LOGIN = "login";
|
||||
private static final String METHOD_LOGOUT = "logout";
|
||||
private static final String METHOD_SHAREMOOD = "shareMood";
|
||||
private static final String METHOD_SHARETEXT = "shareText";
|
||||
private static final String METHOD_SHAREIMAGE = "shareImage";
|
||||
private static final String METHOD_SHAREMUSIC = "shareMusic";
|
||||
private static final String METHOD_SHAREWEBPAGE = "shareWebpage";
|
||||
private ActivityPluginBinding pluginBinding;
|
||||
|
||||
private static final String METHOD_ONLOGINRESP = "onLoginResp";
|
||||
private static final String METHOD_ONSHARERESP = "onShareResp";
|
||||
|
||||
private static final String ARGUMENT_KEY_APPID = "appId";
|
||||
// private static final String ARGUMENT_KEY_UNIVERSALLINK = "universalLink";
|
||||
private static final String ARGUMENT_KEY_SCOPE = "scope";
|
||||
private static final String ARGUMENT_KEY_SCENE = "scene";
|
||||
private static final String ARGUMENT_KEY_TITLE = "title";
|
||||
private static final String ARGUMENT_KEY_SUMMARY = "summary";
|
||||
private static final String ARGUMENT_KEY_IMAGEURI = "imageUri";
|
||||
private static final String ARGUMENT_KEY_IMAGEURIS = "imageUris";
|
||||
private static final String ARGUMENT_KEY_VIDEOURI = "videoUri";
|
||||
private static final String ARGUMENT_KEY_MUSICURL = "musicUrl";
|
||||
private static final String ARGUMENT_KEY_TARGETURL = "targetUrl";
|
||||
private static final String ARGUMENT_KEY_APPNAME = "appName";
|
||||
private static final String ARGUMENT_KEY_EXTINT = "extInt";
|
||||
|
||||
private static final String ARGUMENT_KEY_RESULT_RET = "ret";
|
||||
private static final String ARGUMENT_KEY_RESULT_MSG = "msg";
|
||||
private static final String ARGUMENT_KEY_RESULT_OPENID = "openid";
|
||||
private static final String ARGUMENT_KEY_RESULT_ACCESS_TOKEN = "access_token";
|
||||
private static final String ARGUMENT_KEY_RESULT_EXPIRES_IN = "expires_in";
|
||||
private static final String ARGUMENT_KEY_RESULT_CREATE_AT = "create_at";
|
||||
|
||||
private static final String SCHEME_FILE = "file";
|
||||
|
||||
private final Registrar registrar;
|
||||
private final MethodChannel channel;
|
||||
|
||||
private Tencent tencent;
|
||||
|
||||
private TencentKitPlugin(Registrar registrar, MethodChannel channel) {
|
||||
this.registrar = registrar;
|
||||
this.channel = channel;
|
||||
public TencentKitPlugin() {
|
||||
tencentKit = new TencentKit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMethodCall(MethodCall call, @NonNull Result result) {
|
||||
if (METHOD_REGISTERAPP.equals(call.method)) {
|
||||
final String appId = call.argument(ARGUMENT_KEY_APPID);
|
||||
// final String universalLink = call.argument(ARGUMENT_KEY_UNIVERSALLINK);
|
||||
tencent = Tencent.createInstance(appId, registrar.context().getApplicationContext());
|
||||
result.success(null);
|
||||
} else if (METHOD_ISQQINSTALLED.equals(call.method)) {
|
||||
result.success(isAppInstalled(registrar.context(), "com.tencent.mobileqq"));
|
||||
} else if (METHOD_ISTIMINSTALLED.equals(call.method)) {
|
||||
result.success(isAppInstalled(registrar.context(), "com.tencent.tim"));
|
||||
} else if (METHOD_ISQQLITEINSTALLED.equals(call.method)) {
|
||||
result.success(isAppInstalled(registrar.context(), "com.tencent.qqlite"));
|
||||
} else if (METHOD_LOGIN.equals(call.method)) {
|
||||
login(call, result);
|
||||
} else if (METHOD_LOGOUT.equals(call.method)) {
|
||||
logout(call, result);
|
||||
} else if (METHOD_SHAREMOOD.equals(call.method)) {
|
||||
shareMood(call, result);
|
||||
} else if (METHOD_SHARETEXT.equals(call.method)) {
|
||||
shareText(call, result);
|
||||
} else if (METHOD_SHAREIMAGE.equals(call.method)) {
|
||||
shareImage(call, result);
|
||||
} else if (METHOD_SHAREMUSIC.equals(call.method)) {
|
||||
shareMusic(call, result);
|
||||
} else if (METHOD_SHAREWEBPAGE.equals(call.method)) {
|
||||
shareWebpage(call, result);
|
||||
} else {
|
||||
result.notImplemented();
|
||||
}
|
||||
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
|
||||
tencentKit.setApplicationContext(flutterPluginBinding.getApplicationContext());
|
||||
tencentKit.setActivity(null);
|
||||
tencentKit.startListening(flutterPluginBinding.getBinaryMessenger());
|
||||
}
|
||||
|
||||
private void login(MethodCall call, Result result) {
|
||||
if (tencent != null) {
|
||||
String scope = call.argument(ARGUMENT_KEY_SCOPE);
|
||||
tencent.login(registrar.activity(), scope, loginListener);
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private IUiListener loginListener = new IUiListener() {
|
||||
@Override
|
||||
public void onComplete(Object o) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
try {
|
||||
if (o != null && o instanceof JSONObject) {
|
||||
JSONObject object = (JSONObject) o;
|
||||
int ret = !object.isNull(ARGUMENT_KEY_RESULT_RET) ? object.getInt(ARGUMENT_KEY_RESULT_RET) : TencentRetCode.RET_FAILED;
|
||||
String msg = !object.isNull(ARGUMENT_KEY_RESULT_MSG) ? object.getString(ARGUMENT_KEY_RESULT_MSG) : null;
|
||||
if (ret == TencentRetCode.RET_SUCCESS) {
|
||||
String openId = !object.isNull(ARGUMENT_KEY_RESULT_OPENID) ? object.getString(ARGUMENT_KEY_RESULT_OPENID) : null;
|
||||
String accessToken = !object.isNull(ARGUMENT_KEY_RESULT_ACCESS_TOKEN) ? object.getString(ARGUMENT_KEY_RESULT_ACCESS_TOKEN) : null;
|
||||
int expiresIn = !object.isNull(ARGUMENT_KEY_RESULT_EXPIRES_IN) ? object.getInt(ARGUMENT_KEY_RESULT_EXPIRES_IN) : 0;
|
||||
long createAt = System.currentTimeMillis();
|
||||
if (!TextUtils.isEmpty(openId) && !TextUtils.isEmpty(accessToken)) {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_SUCCESS);
|
||||
map.put(ARGUMENT_KEY_RESULT_OPENID, openId);
|
||||
map.put(ARGUMENT_KEY_RESULT_ACCESS_TOKEN, accessToken);
|
||||
map.put(ARGUMENT_KEY_RESULT_EXPIRES_IN, expiresIn);
|
||||
map.put(ARGUMENT_KEY_RESULT_CREATE_AT, createAt);
|
||||
} else {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, "openId or accessToken is null.");
|
||||
}
|
||||
} else {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, msg);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, e.getMessage());
|
||||
}
|
||||
channel.invokeMethod(METHOD_ONLOGINRESP, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(UiError uiError) {
|
||||
// 登录失败
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, uiError.errorMessage);
|
||||
channel.invokeMethod(METHOD_ONLOGINRESP, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// 取消登录
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_USERCANCEL);
|
||||
channel.invokeMethod(METHOD_ONLOGINRESP, map);
|
||||
}
|
||||
};
|
||||
|
||||
private void logout(MethodCall call, Result result) {
|
||||
if (tencent != null) {
|
||||
tencent.logout(registrar.context());
|
||||
result.success(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void shareMood(MethodCall call, Result result) {
|
||||
if (tencent != null) {
|
||||
int scene = call.argument(ARGUMENT_KEY_SCENE);
|
||||
if (scene == TencentScene.SCENE_QZONE) {
|
||||
String summary = call.argument(ARGUMENT_KEY_SUMMARY);
|
||||
List<String> imageUris = call.argument(ARGUMENT_KEY_IMAGEURIS);
|
||||
String videoUri = call.argument(ARGUMENT_KEY_VIDEOURI);
|
||||
|
||||
Bundle params = new Bundle();
|
||||
if (!TextUtils.isEmpty(summary)) {
|
||||
params.putString(QzonePublish.PUBLISH_TO_QZONE_SUMMARY, summary);
|
||||
}
|
||||
if (imageUris != null && !imageUris.isEmpty()) {
|
||||
ArrayList<String> uris = new ArrayList<>();
|
||||
for (String imageUri : imageUris) {
|
||||
uris.add(Uri.parse(imageUri).getPath());
|
||||
}
|
||||
params.putStringArrayList(QzonePublish.PUBLISH_TO_QZONE_IMAGE_URL, uris);
|
||||
}
|
||||
if (!TextUtils.isEmpty(videoUri)) {
|
||||
String videoPath = Uri.parse(videoUri).getPath();
|
||||
params.putString(QzonePublish.PUBLISH_TO_QZONE_VIDEO_PATH, videoPath);
|
||||
params.putInt(QzonePublish.PUBLISH_TO_QZONE_KEY_TYPE, QzonePublish.PUBLISH_TO_QZONE_TYPE_PUBLISHVIDEO);
|
||||
} else {
|
||||
params.putInt(QzonePublish.PUBLISH_TO_QZONE_KEY_TYPE, QzonePublish.PUBLISH_TO_QZONE_TYPE_PUBLISHMOOD);
|
||||
}
|
||||
tencent.publishToQzone(registrar.activity(), params, shareListener);
|
||||
}
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private void shareText(MethodCall call, Result result) {
|
||||
int scene = call.argument(ARGUMENT_KEY_SCENE);
|
||||
if (scene == TencentScene.SCENE_QQ) {
|
||||
String summary = call.argument(ARGUMENT_KEY_SUMMARY);
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, summary);
|
||||
sendIntent.setType("text/*");
|
||||
// 普通大众版 > 办公简洁版 > 急速轻聊版
|
||||
PackageManager packageManager = registrar.context().getPackageManager();
|
||||
List<PackageInfo> infos = packageManager.getInstalledPackages(0);
|
||||
if (infos != null && !infos.isEmpty()) {
|
||||
for (String packageName : Arrays.asList("com.tencent.mobileqq", "com.tencent.tim", "com.tencent.qqlite")) {
|
||||
for (PackageInfo info : infos) {
|
||||
if (packageName.equals(info.packageName)) {
|
||||
sendIntent.setPackage(packageName);
|
||||
if (sendIntent.resolveActivity(registrar.context().getPackageManager()) != null) {
|
||||
sendIntent.setComponent(new ComponentName(packageName, "com.tencent.mobileqq.activity.JumpActivity"));
|
||||
registrar.activity().startActivity(sendIntent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private void shareImage(MethodCall call, Result result) {
|
||||
if (tencent != null) {
|
||||
int scene = call.argument(ARGUMENT_KEY_SCENE);
|
||||
if (scene == TencentScene.SCENE_QQ) {
|
||||
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
|
||||
String appName = call.argument(ARGUMENT_KEY_APPNAME);
|
||||
int extInt = call.argument(ARGUMENT_KEY_EXTINT);
|
||||
|
||||
Bundle params = new Bundle();
|
||||
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_IMAGE);
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_LOCAL_URL, Uri.parse(imageUri).getPath());
|
||||
if (!TextUtils.isEmpty(appName)) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, appName);
|
||||
}
|
||||
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, extInt);
|
||||
tencent.shareToQQ(registrar.activity(), params, shareListener);
|
||||
}
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private void shareMusic(MethodCall call, Result result) {
|
||||
if (tencent != null) {
|
||||
int scene = call.argument(ARGUMENT_KEY_SCENE);
|
||||
if (scene == TencentScene.SCENE_QQ) {
|
||||
String title = call.argument(ARGUMENT_KEY_TITLE);
|
||||
String summary = call.argument(ARGUMENT_KEY_SUMMARY);
|
||||
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
|
||||
String musicUrl = call.argument(ARGUMENT_KEY_MUSICURL);
|
||||
String targetUrl = call.argument(ARGUMENT_KEY_TARGETURL);
|
||||
String appName = call.argument(ARGUMENT_KEY_APPNAME);
|
||||
int extInt = call.argument(ARGUMENT_KEY_EXTINT);
|
||||
|
||||
Bundle params = new Bundle();
|
||||
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_AUDIO);
|
||||
params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
|
||||
if (!TextUtils.isEmpty(summary)) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_SUMMARY, summary);
|
||||
}
|
||||
if (!TextUtils.isEmpty(imageUri)) {
|
||||
Uri uri = Uri.parse(imageUri);
|
||||
if (TextUtils.equals(SCHEME_FILE, uri.getScheme())) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, uri.getPath());
|
||||
} else {
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, imageUri);
|
||||
}
|
||||
}
|
||||
params.putString(QQShare.SHARE_TO_QQ_AUDIO_URL, musicUrl);
|
||||
params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, targetUrl);
|
||||
if (!TextUtils.isEmpty(appName)) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, appName);
|
||||
}
|
||||
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, extInt);
|
||||
tencent.shareToQQ(registrar.activity(), params, shareListener);
|
||||
}
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private void shareWebpage(MethodCall call, Result result) {
|
||||
if (tencent != null) {
|
||||
int scene = call.argument(ARGUMENT_KEY_SCENE);
|
||||
String title = call.argument(ARGUMENT_KEY_TITLE);
|
||||
String summary = call.argument(ARGUMENT_KEY_SUMMARY);
|
||||
String imageUri = call.argument(ARGUMENT_KEY_IMAGEURI);
|
||||
String targetUrl = call.argument(ARGUMENT_KEY_TARGETURL);
|
||||
String appName = call.argument(ARGUMENT_KEY_APPNAME);
|
||||
int extInt = call.argument(ARGUMENT_KEY_EXTINT);
|
||||
|
||||
Bundle params = new Bundle();
|
||||
switch (scene) {
|
||||
case TencentScene.SCENE_QQ:
|
||||
params.putInt(QQShare.SHARE_TO_QQ_KEY_TYPE, QQShare.SHARE_TO_QQ_TYPE_DEFAULT);
|
||||
params.putString(QQShare.SHARE_TO_QQ_TITLE, title);
|
||||
if (!TextUtils.isEmpty(summary)) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_SUMMARY, summary);
|
||||
}
|
||||
if (!TextUtils.isEmpty(imageUri)) {
|
||||
Uri uri = Uri.parse(imageUri);
|
||||
if (TextUtils.equals(SCHEME_FILE, uri.getScheme())) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, uri.getPath());
|
||||
} else {
|
||||
params.putString(QQShare.SHARE_TO_QQ_IMAGE_URL, imageUri);
|
||||
}
|
||||
}
|
||||
params.putString(QQShare.SHARE_TO_QQ_TARGET_URL, targetUrl);
|
||||
if (!TextUtils.isEmpty(appName)) {
|
||||
params.putString(QQShare.SHARE_TO_QQ_APP_NAME, appName);
|
||||
}
|
||||
params.putInt(QQShare.SHARE_TO_QQ_EXT_INT, extInt);
|
||||
tencent.shareToQQ(registrar.activity(), params, shareListener);
|
||||
break;
|
||||
case TencentScene.SCENE_QZONE:
|
||||
params.putInt(QzoneShare.SHARE_TO_QZONE_KEY_TYPE, QzoneShare.SHARE_TO_QZONE_TYPE_IMAGE_TEXT);
|
||||
params.putString(QzoneShare.SHARE_TO_QQ_TITLE, title);
|
||||
if (!TextUtils.isEmpty(summary)) {
|
||||
params.putString(QzoneShare.SHARE_TO_QQ_SUMMARY, summary);
|
||||
}
|
||||
if (!TextUtils.isEmpty(imageUri)) {
|
||||
ArrayList<String> uris = new ArrayList<>();
|
||||
Uri uri = Uri.parse(imageUri);
|
||||
if (TextUtils.equals(SCHEME_FILE, uri.getScheme())) {
|
||||
uris.add(uri.getPath());
|
||||
} else {
|
||||
uris.add(imageUri);
|
||||
}
|
||||
params.putStringArrayList(QzoneShare.SHARE_TO_QQ_IMAGE_URL, uris);
|
||||
}
|
||||
params.putString(QzoneShare.SHARE_TO_QQ_TARGET_URL, targetUrl);
|
||||
tencent.shareToQzone(registrar.activity(), params, shareListener);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.success(null);
|
||||
}
|
||||
|
||||
private IUiListener shareListener = new IUiListener() {
|
||||
@Override
|
||||
public void onComplete(Object o) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
try {
|
||||
if (o != null && o instanceof JSONObject) {
|
||||
JSONObject object = (JSONObject) o;
|
||||
int ret = !object.isNull(ARGUMENT_KEY_RESULT_RET) ? object.getInt(ARGUMENT_KEY_RESULT_RET) : TencentRetCode.RET_FAILED;
|
||||
String msg = !object.isNull(ARGUMENT_KEY_RESULT_MSG) ? object.getString(ARGUMENT_KEY_RESULT_MSG) : null;
|
||||
if (ret == TencentRetCode.RET_SUCCESS) {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_SUCCESS);
|
||||
} else {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, msg);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, e.getMessage());
|
||||
}
|
||||
channel.invokeMethod(METHOD_ONSHARERESP, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(UiError error) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_COMMON);
|
||||
map.put(ARGUMENT_KEY_RESULT_MSG, error.errorMessage);
|
||||
channel.invokeMethod(METHOD_ONSHARERESP, map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(ARGUMENT_KEY_RESULT_RET, TencentRetCode.RET_USERCANCEL);
|
||||
channel.invokeMethod(METHOD_ONSHARERESP, map);
|
||||
}
|
||||
};
|
||||
|
||||
// --- ActivityResultListener
|
||||
|
||||
@Override
|
||||
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
case Constants.REQUEST_LOGIN:
|
||||
return Tencent.onActivityResultData(requestCode, resultCode, data, loginListener);
|
||||
case Constants.REQUEST_QQ_SHARE:
|
||||
case Constants.REQUEST_QZONE_SHARE:
|
||||
return Tencent.onActivityResultData(requestCode, resultCode, data, shareListener);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
|
||||
tencentKit.setApplicationContext(null);
|
||||
tencentKit.setActivity(null);
|
||||
tencentKit.stopListening();
|
||||
}
|
||||
|
||||
// ---
|
||||
// --- ActivityAware
|
||||
|
||||
private static boolean isAppInstalled(Context context, String packageName) {
|
||||
PackageInfo packageInfo = null;
|
||||
try {
|
||||
packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
}
|
||||
return packageInfo != null;
|
||||
@Override
|
||||
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
|
||||
tencentKit.setActivity(binding.getActivity());
|
||||
pluginBinding = binding;
|
||||
pluginBinding.addActivityResultListener(tencentKit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromActivityForConfigChanges() {
|
||||
onDetachedFromActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
|
||||
onAttachedToActivity(binding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromActivity() {
|
||||
tencentKit.setActivity(null);
|
||||
pluginBinding.removeActivityResultListener(tencentKit);
|
||||
pluginBinding = null;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--suppress AndroidDomInspection -->
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<root-path name="root" path="" />
|
||||
<files-path name="files" path="" />
|
||||
<cache-path name="cache" path="" />
|
||||
<external-path name="external" path="" />
|
||||
<external-files-path name="external_files" path="" />
|
||||
<external-cache-path name="external_cache" path="" />
|
||||
<external-media-path name="external_media" path="" />
|
||||
<paths>
|
||||
<external-files-path name="opensdk_external" path="Images/tmp"/>
|
||||
<root-path name="opensdk_root" path=""/>
|
||||
</paths>
|
@ -55,10 +55,6 @@ android {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.debug
|
||||
|
||||
minifyEnabled true
|
||||
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
9
example/android/app/proguard-rules.pro
vendored
9
example/android/app/proguard-rules.pro
vendored
@ -1,9 +0,0 @@
|
||||
# Flutter Wrapper
|
||||
|
||||
-keep class io.flutter.app.** { *; }
|
||||
-keep class io.flutter.plugin.** { *; }
|
||||
-keep class io.flutter.util.** { *; }
|
||||
-keep class io.flutter.view.** { *; }
|
||||
-keep class io.flutter.** { *; }
|
||||
-keep class io.flutter.plugins.** { *; }
|
||||
-dontwarn io.flutter.**
|
||||
|
@ -1,6 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="io.github.v7lin.tencent_kit_example">
|
||||
|
||||
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
|
||||
calls FlutterMain.startInitialization(this); in its onCreate method.
|
||||
In most cases you can leave this as-is, but you if you want to provide
|
||||
@ -14,20 +13,18 @@
|
||||
android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- This keeps the window background of the activity showing
|
||||
until Flutter renders its first frame. It can be removed if
|
||||
there is no splash screen (such as the default splash screen
|
||||
defined in @style/LaunchTheme). -->
|
||||
<meta-data
|
||||
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
|
||||
android:value="true" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- Don't delete the meta-data below.
|
||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
</manifest>
|
||||
|
@ -1,13 +1,7 @@
|
||||
package io.github.v7lin.tencent_kit_example;
|
||||
|
||||
import android.os.Bundle;
|
||||
import io.flutter.app.FlutterActivity;
|
||||
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||
import io.flutter.embedding.android.FlutterActivity;
|
||||
|
||||
public class MainActivity extends FlutterActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
GeneratedPluginRegistrant.registerWith(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.2'
|
||||
classpath 'com.android.tools.build:gradle:3.5.0'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
org.gradle.jvmargs=-Xmx1536M
|
||||
|
||||
android.enableR8=true
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.enableR8=true
|
||||
|
@ -1,6 +1,6 @@
|
||||
#Wed Nov 06 18:22:26 CST 2019
|
||||
#Fri Jun 23 08:50:38 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
|
||||
|
@ -75,7 +75,8 @@ class _HomeState extends State<Home> {
|
||||
ListTile(
|
||||
title: const Text('环境检查'),
|
||||
onTap: () async {
|
||||
String content = 'tencent: ${await _tencent.isInstalled()}';
|
||||
String content =
|
||||
'QQ install: ${await _tencent.isQQInstalled()}\nTIM install: ${await _tencent.isTIMInstalled()}';
|
||||
_showTips('环境检查', content);
|
||||
},
|
||||
),
|
||||
@ -139,7 +140,7 @@ class _HomeState extends State<Home> {
|
||||
title: const Text('文本分享'),
|
||||
onTap: () {
|
||||
_tencent.shareText(
|
||||
scene: TencentScene.SCENE_QZONE,
|
||||
scene: TencentScene.SCENE_QQ,
|
||||
summary: '分享测试',
|
||||
);
|
||||
},
|
||||
|
@ -39,7 +39,6 @@ enum TencentRetCode {
|
||||
static NSString *const METHOD_REGISTERAPP = @"registerApp";
|
||||
static NSString *const METHOD_ISQQINSTALLED = @"isQQInstalled";
|
||||
static NSString *const METHOD_ISTIMINSTALLED = @"isTIMInstalled";
|
||||
static NSString *const METHOD_ISQQLITEINSTALLED = @"isQQLiteInstalled";
|
||||
static NSString *const METHOD_LOGIN = @"login";
|
||||
static NSString *const METHOD_LOGOUT = @"logout";
|
||||
static NSString *const METHOD_SHAREMOOD = @"shareMood";
|
||||
@ -99,8 +98,6 @@ static NSString *const SCHEME_FILE = @"file";
|
||||
result([NSNumber numberWithBool:[TencentOAuth iphoneQQInstalled]]);
|
||||
} else if ([METHOD_ISTIMINSTALLED isEqualToString:call.method]) {
|
||||
result([NSNumber numberWithBool:[TencentOAuth iphoneTIMInstalled]]);
|
||||
} else if ([METHOD_ISQQLITEINSTALLED isEqualToString:call.method]) {
|
||||
result([NSNumber numberWithBool:NO]);
|
||||
} else if ([METHOD_LOGIN isEqualToString:call.method]) {
|
||||
[self login:call result:result];
|
||||
} else if ([METHOD_LOGOUT isEqualToString:call.method]) {
|
||||
|
@ -155,4 +155,20 @@ typedef void (^sendResultBlock)(NSDictionary *result);
|
||||
\return iPhoneTIM下载地址
|
||||
*/
|
||||
+ (NSString *)getTIMInstallUrl;
|
||||
|
||||
#pragma mark - Log
|
||||
/*! @brief 调用此函数可以导出QQSDK的Log到第三方中,用于定位问题
|
||||
|
||||
注意1:SDK会强引用这个block,注意不要导致内存泄漏,注意不要导致内存泄漏
|
||||
注意2:调用过一次startLog by block之后,如果再调用一次任意方式的startLoad,会释放上一次logBlock,不再回调上一个logBlock
|
||||
*
|
||||
* @param logBlock 打印log的回调block
|
||||
*/
|
||||
+ (void)startLogWithBlock:(QQApiLogBolock)logBlock;
|
||||
///停止回调打印
|
||||
+ (void)stopLog;
|
||||
///设置打印日志到文件开关on/off,如果不设置,默认不打印到文件
|
||||
+ (void)setSwitchPrintLogToFile:(BOOL)on;
|
||||
///日志文件目录
|
||||
+ (NSString*)getLogFilePath;
|
||||
@end
|
||||
|
@ -37,6 +37,7 @@ typedef NS_ENUM(NSInteger,QQApiSendResultCode) {
|
||||
EQQAPIQZONENOTSUPPORTIMAGE = 10001, //qzone分享不支持image类型分享
|
||||
EQQAPIVERSIONNEEDUPDATE = 10002, //当前QQ版本太低,需要更新至新版本才可以支持
|
||||
ETIMAPIVERSIONNEEDUPDATE = 10004, //当前TIM版本太低,需要更新至新版本才可以支持
|
||||
EAPPURLTYPESILLEGALITY = 20000, //(>=3.3.8)第三方APP的info.plist中UrlTypes字段存在QQ的UrlScheme
|
||||
};
|
||||
|
||||
#pragma mark - QQApiObject(分享对象类型)
|
||||
@ -66,6 +67,9 @@ typedef NS_ENUM(NSUInteger, MiniProgramType) {
|
||||
MiniProgramType_Preview=4, // 预览版
|
||||
};
|
||||
|
||||
/// 打印回调的block
|
||||
typedef void(^QQApiLogBolock)(NSString *logStr);
|
||||
|
||||
// QQApiObject
|
||||
/** \brief 所有在QQ及插件间发送的数据对象的根类。
|
||||
*/
|
||||
@ -106,9 +110,16 @@ __attribute__((visibility("default"))) @interface QQApiMiniProgramObject : NSObj
|
||||
//唤起小程序 - QQ 8.1.8
|
||||
__attribute__((visibility("default"))) @interface QQApiLaunchMiniProgramObject : QQApiObject
|
||||
@property(nonatomic,retain) NSString* miniAppID; //必填,小程序的AppId(注:必须在QQ互联平台中,将该小程序与分享的App绑定)
|
||||
@property(nonatomic,retain) NSString* miniPath; //必填,小程序的展示路径
|
||||
@property(nonatomic,retain) NSString* miniPath; //小程序的展示路径,不填展示默认小程序首页
|
||||
@property(nonatomic,assign) MiniProgramType miniprogramType; //非必填,小程序的类型,默认正式版(3),可选测试版(1)、开发版(0)
|
||||
@end
|
||||
|
||||
//小程序唤起第三方 - SDK 3.3.9
|
||||
__attribute__((visibility("default"))) @interface QQApiMiniProgramLaunchObject : QQApiObject
|
||||
@property(nonatomic,copy) NSString* appParameter; //小程序带来的数据,透传
|
||||
+ (instancetype)newWithAppParameter:(NSString*)parameter;
|
||||
@end
|
||||
|
||||
// QQApiResultObject
|
||||
/** \brief 用于请求回应的数据类型。
|
||||
<h3>可能错误码及描述如下:</h3>
|
||||
|
@ -164,8 +164,8 @@ typedef NS_ENUM(NSUInteger, TencentAuthMode) {
|
||||
|
||||
/**
|
||||
* 初始化TencentOAuth对象
|
||||
* \param appId 第三方应用在互联开放平台申请的唯一标识
|
||||
* \param delegate 第三方应用用于接收请求返回结果的委托对象
|
||||
* \param appId 不可为nil,第三方应用在互联开放平台申请的唯一标识
|
||||
* \param delegate 不可为nil,第三方应用用于接收请求返回结果的委托对象
|
||||
* \return 初始化后的授权登录对象
|
||||
*/
|
||||
- (id)initWithAppId:(NSString *)appId
|
||||
@ -173,15 +173,38 @@ typedef NS_ENUM(NSUInteger, TencentAuthMode) {
|
||||
|
||||
/**
|
||||
* 初始化TencentOAuth对象(>=3.3.7)
|
||||
* \param appId 第三方应用在互联开放平台申请的唯一标识
|
||||
* \param universalLink 第三方应用在互联开放平台注册的universallink,和bundleID一一对应
|
||||
* \param delegate 第三方应用用于接收请求返回结果的委托对象
|
||||
* \param appId 不可为nil,第三方应用在互联开放平台申请的唯一标识
|
||||
* \param universalLink 可以为nil,第三方应用在互联开放平台注册的UniversalLink,和bundleID一一对应(当为nil时,互联平台会按规则生成universallink,详见官网说明)
|
||||
* \param delegate 不可为nil,第三方应用用于接收请求返回结果的委托对象
|
||||
* \return 初始化后的授权登录对象
|
||||
*
|
||||
****【使用说明】*****
|
||||
* 1、支持BundleId与UniversalLink的一一对应,主要目的“是为了解决应用的iPhone版本和iPad HD版本共用同一个AppId,导致同时安装情况下的跳转问题"。
|
||||
* 2 、由于手Q版本在 >=8.1.8 后才支持了这种对应方式,所以一旦使用,“务必做到”及时知会用户升级手Q版本。
|
||||
****
|
||||
*/
|
||||
- (id)initWithAppId:(NSString *)appId
|
||||
andUniversalLink:(NSString *)universalLink
|
||||
andDelegate:(id<TencentSessionDelegate>)delegate;
|
||||
|
||||
/**
|
||||
* 初始化TencentOAuth对象(>=3.3.8)
|
||||
* \param appId 不可为nil,第三方应用在互联开放平台申请的唯一标识
|
||||
* \param enabled 默认为NO,第三方应用是否将sdk和手机QQ的交互方式切换为UniversalLink方式,启用后则在iOS9及以上的系统都会生效UniversalLink方式;否则,默认仅在iOS13及以上的系统生效UniversalLink方式。
|
||||
* \param universalLink 可以为nil,第三方应用在互联开放平台注册的UniversalLink,和bundleID一一对应(当为nil时,互联平台会按规则生成UniversalLink,详见官网说明)
|
||||
* \param delegate 不可为nil,第三方应用用于接收请求返回结果的委托对象
|
||||
* \return 初始化后的授权登录对象
|
||||
*
|
||||
*****【使用说明】*****
|
||||
* 1、支持sdk与手Q的交互切换为UniversalLink模式,主要目的"是为了避免手Q的UrlScheme被其他应用抢注后,导致sdk接口功能受到影响"。
|
||||
* 2 、由于手Q版本在 >=8.1.3 后才适配了UniversalLink,所以一旦开启了enabled开关,“务必做到”及时知会用户升级手Q版本。
|
||||
*****
|
||||
*/
|
||||
- (id)initWithAppId:(NSString *)appId
|
||||
enableUniveralLink:(BOOL)enabled
|
||||
universalLink:(NSString *)universalLink
|
||||
delegate:(id<TencentSessionDelegate>)delegate;
|
||||
|
||||
/**
|
||||
* 判断用户手机上是否安装手机QQ
|
||||
* \return YES:安装 NO:没安装
|
||||
|
Binary file not shown.
@ -20,7 +20,6 @@ class Tencent {
|
||||
static const String _METHOD_REGISTERAPP = 'registerApp';
|
||||
static const String _METHOD_ISQQINSTALLED = 'isQQInstalled';
|
||||
static const String _METHOD_ISTIMINSTALLED = 'isTIMInstalled';
|
||||
static const String _METHOD_ISQQLITEINSTALLED = 'isQQLiteInstalled';
|
||||
static const String _METHOD_LOGIN = 'login';
|
||||
static const String _METHOD_LOGOUT = 'logout';
|
||||
static const String _METHOD_SHAREMOOD = 'shareMood';
|
||||
@ -77,16 +76,14 @@ class Tencent {
|
||||
}) {
|
||||
assert(appId != null && appId.isNotEmpty);
|
||||
assert(!Platform.isIOS || universalLink == null);
|
||||
final Map<String, dynamic> arguments = <String, dynamic>{
|
||||
_ARGUMENT_KEY_APPID: appId,
|
||||
// _ARGUMENT_KEY_UNIVERSALLINK: universalLink,
|
||||
};
|
||||
|
||||
/// 兼容 iOS 空安全 -> NSNull
|
||||
if (universalLink != null) {
|
||||
arguments[_ARGUMENT_KEY_UNIVERSALLINK] = universalLink;
|
||||
}
|
||||
return _channel.invokeMethod(_METHOD_REGISTERAPP, arguments);
|
||||
return _channel.invokeMethod(
|
||||
_METHOD_REGISTERAPP,
|
||||
<String, dynamic>{
|
||||
_ARGUMENT_KEY_APPID: appId,
|
||||
if (universalLink?.isNotEmpty ?? false)
|
||||
_ARGUMENT_KEY_UNIVERSALLINK: universalLink,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 登录
|
||||
@ -99,13 +96,6 @@ class Tencent {
|
||||
return _shareRespStreamController.stream;
|
||||
}
|
||||
|
||||
/// 检查QQ是否已安装
|
||||
Future<bool> isInstalled() async {
|
||||
return (await isQQInstalled()) ||
|
||||
(await isTIMInstalled()) ||
|
||||
(await isQQLiteInstalled());
|
||||
}
|
||||
|
||||
/// 检查QQ是否已安装
|
||||
Future<bool> isQQInstalled() {
|
||||
return _channel.invokeMethod(_METHOD_ISQQINSTALLED);
|
||||
@ -116,11 +106,6 @@ class Tencent {
|
||||
return _channel.invokeMethod(_METHOD_ISTIMINSTALLED);
|
||||
}
|
||||
|
||||
/// 检查QQ是否已安装
|
||||
Future<bool> isQQLiteInstalled() {
|
||||
return _channel.invokeMethod(_METHOD_ISQQLITEINSTALLED);
|
||||
}
|
||||
|
||||
/// 登录
|
||||
Future<void> login({
|
||||
@required List<String> scope,
|
||||
@ -214,27 +199,17 @@ class Tencent {
|
||||
assert(imageUri != null && imageUri.isScheme(_SCHEME_FILE));
|
||||
});
|
||||
}
|
||||
final Map<String, dynamic> arguments = <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) {
|
||||
arguments[_ARGUMENT_KEY_SUMMARY] = summary;
|
||||
}
|
||||
if (imageUris != null && imageUris.isNotEmpty) {
|
||||
arguments[_ARGUMENT_KEY_IMAGEURIS] =
|
||||
imageUris.map((Uri imageUri) => imageUri.toString()).toList();
|
||||
}
|
||||
if (videoUri != null) {
|
||||
arguments[_ARGUMENT_KEY_VIDEOURI] = videoUri.toString();
|
||||
}
|
||||
return _channel.invokeMethod(_METHOD_SHAREMOOD, arguments);
|
||||
return _channel.invokeMethod(
|
||||
_METHOD_SHAREMOOD,
|
||||
<String, dynamic>{
|
||||
_ARGUMENT_KEY_SCENE: scene,
|
||||
if (summary?.isNotEmpty ?? false) _ARGUMENT_KEY_SUMMARY: summary,
|
||||
if (imageUris?.isNotEmpty ?? false)
|
||||
_ARGUMENT_KEY_IMAGEURIS:
|
||||
imageUris.map((Uri imageUri) => imageUri.toString()).toList(),
|
||||
if (videoUri != null) _ARGUMENT_KEY_VIDEOURI: videoUri.toString(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 分享 - 文本(Android调用的是系统API,故而不会有回调)
|
||||
@ -244,11 +219,13 @@ class Tencent {
|
||||
}) {
|
||||
assert(scene == TencentScene.SCENE_QQ);
|
||||
assert(summary != null && summary.isNotEmpty);
|
||||
final Map<String, dynamic> arguments = <String, dynamic>{
|
||||
_ARGUMENT_KEY_SCENE: scene,
|
||||
_ARGUMENT_KEY_SUMMARY: summary,
|
||||
};
|
||||
return _channel.invokeMethod(_METHOD_SHARETEXT, arguments);
|
||||
return _channel.invokeMethod(
|
||||
_METHOD_SHARETEXT,
|
||||
<String, dynamic>{
|
||||
_ARGUMENT_KEY_SCENE: scene,
|
||||
_ARGUMENT_KEY_SUMMARY: summary,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 分享 - 图片
|
||||
@ -260,18 +237,15 @@ class Tencent {
|
||||
}) {
|
||||
assert(scene == TencentScene.SCENE_QQ);
|
||||
assert(imageUri != null && imageUri.isScheme(_SCHEME_FILE));
|
||||
final Map<String, dynamic> arguments = <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) {
|
||||
arguments[_ARGUMENT_KEY_APPNAME] = appName;
|
||||
}
|
||||
return _channel.invokeMethod(_METHOD_SHAREIMAGE, arguments);
|
||||
return _channel.invokeMethod(
|
||||
_METHOD_SHAREIMAGE,
|
||||
<String, dynamic>{
|
||||
_ARGUMENT_KEY_SCENE: scene,
|
||||
_ARGUMENT_KEY_IMAGEURI: imageUri.toString(),
|
||||
if (appName?.isNotEmpty ?? false) _ARGUMENT_KEY_APPNAME: appName,
|
||||
_ARGUMENT_KEY_EXTINT: extInt,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 分享 - 音乐
|
||||
@ -289,28 +263,19 @@ class Tencent {
|
||||
assert(title != null && title.isNotEmpty);
|
||||
assert(musicUrl != null && musicUrl.isNotEmpty);
|
||||
assert(targetUrl != null && targetUrl.isNotEmpty);
|
||||
final Map<String, dynamic> arguments = <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) {
|
||||
arguments[_ARGUMENT_KEY_SUMMARY] = summary;
|
||||
}
|
||||
if (imageUri != null) {
|
||||
arguments[_ARGUMENT_KEY_IMAGEURI] = imageUri.toString();
|
||||
}
|
||||
if (appName != null && appName.isNotEmpty) {
|
||||
arguments[_ARGUMENT_KEY_APPNAME] = appName;
|
||||
}
|
||||
return _channel.invokeMethod(_METHOD_SHAREMUSIC, arguments);
|
||||
return _channel.invokeMethod(
|
||||
_METHOD_SHAREMUSIC,
|
||||
<String, dynamic>{
|
||||
_ARGUMENT_KEY_SCENE: scene,
|
||||
_ARGUMENT_KEY_TITLE: title,
|
||||
if (summary?.isNotEmpty ?? false) _ARGUMENT_KEY_SUMMARY: summary,
|
||||
if (imageUri != null) _ARGUMENT_KEY_IMAGEURI: imageUri.toString(),
|
||||
_ARGUMENT_KEY_MUSICURL: musicUrl,
|
||||
_ARGUMENT_KEY_TARGETURL: targetUrl,
|
||||
if (appName?.isNotEmpty ?? false) _ARGUMENT_KEY_APPNAME: appName,
|
||||
_ARGUMENT_KEY_EXTINT: extInt,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// 分享 - 网页
|
||||
@ -325,26 +290,17 @@ class Tencent {
|
||||
}) {
|
||||
assert(title != null && title.isNotEmpty);
|
||||
assert(targetUrl != null && targetUrl.isNotEmpty);
|
||||
final Map<String, dynamic> arguments = <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 (summary != null && summary.isNotEmpty) {
|
||||
arguments[_ARGUMENT_KEY_SUMMARY] = summary;
|
||||
}
|
||||
if (imageUri != null) {
|
||||
arguments[_ARGUMENT_KEY_IMAGEURI] = imageUri.toString();
|
||||
}
|
||||
if (appName != null && appName.isNotEmpty) {
|
||||
arguments[_ARGUMENT_KEY_APPNAME] = appName;
|
||||
}
|
||||
return _channel.invokeMethod(_METHOD_SHAREWEBPAGE, arguments);
|
||||
return _channel.invokeMethod(
|
||||
_METHOD_SHAREWEBPAGE,
|
||||
<String, dynamic>{
|
||||
_ARGUMENT_KEY_SCENE: scene,
|
||||
_ARGUMENT_KEY_TITLE: title,
|
||||
if (summary?.isNotEmpty ?? false) _ARGUMENT_KEY_SUMMARY: summary,
|
||||
if (imageUri != null) _ARGUMENT_KEY_IMAGEURI: imageUri.toString(),
|
||||
_ARGUMENT_KEY_TARGETURL: targetUrl,
|
||||
if (appName?.isNotEmpty ?? false) _ARGUMENT_KEY_APPNAME: appName,
|
||||
_ARGUMENT_KEY_EXTINT: extInt,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
name: tencent_kit
|
||||
description: A powerful Flutter plugin allowing developers to share or authorize with natvie android & iOS Tencent SDKs.
|
||||
version: 1.0.4
|
||||
version: 1.1.0
|
||||
# author: v7lin <v7lin@qq.com>
|
||||
homepage: https://github.com/v7lin/fake_tencent
|
||||
|
||||
environment:
|
||||
sdk: ">=2.1.0 <3.0.0"
|
||||
sdk: ">=2.3.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
Reference in New Issue
Block a user