Commit f386c125bba2c49222175b36301343f697317fbe

Authored by weixin_45529955
1 parent 82702a0d

删.git

Showing 94 changed files with 4653 additions and 2 deletions

Too many changes to show.

To preserve performance only 94 of 94+ files are displayed.

... ... @@ -5180,7 +5180,7 @@ class InvicationPageState extends State<InvicationPage>
//跳转
if (reserverPhone != null) {
List<String> phoneNumber = [reserverPhone!,'18765434543'];
List<String> phoneNumber = [reserverPhone!];
try {
String _result = await sendSMS(
... ...
Subproject commit a5349371525462b1d1b6cfa4cf4d2a59503f1435
zq.xcuserdatad/
!contents.xcworkspacedata
.DS_Store
xcuserdata/
!xcschemes/
!xcbaselines/
.editorconfig
.idea
build/
### PreCI ###
.codecc
\ No newline at end of file
... ...
{
"preCI.localCodeCheck.filter.whitePath": "",
"preCI.localCodeCheck.filter.skipPath": ".*/\\.codecc/.*,.*/\\.git,.*/\\.git/.*,.*/\\.svn/.*",
"preCI.localCodeCheck.preCommit": "none",
"preCI.localCodeCheck.prePush": "none",
"preCI.pipeline.yamlFilePath": "build.yml",
"preCI.localCodeCheck.toolType": "binary",
"preCI.localCodeCheck.checkerSet.JAVA": [
"standard_java"
],
"preCI.localCodeCheck.checkerSet.OC/OC++": [
"bkcheck_oc_rule"
],
"preCI.localCodeCheck.checkerSet.Other": [
"standard_scc"
],
"preCI.localCodeCheck.checkerSet.C/C++": [
"standard_cpp"
],
"preCI.localCodeCheck.checkerSet.Kotlin": [
"standard_kotlin"
]
}
\ No newline at end of file
... ...
## V1.3.4
* use TPNS iOS SDK 1.4.0.5
## V1.3.3
* use TPNS iOS SDK 1.4.0.4
## V1.3.2
* build.gradle add namespace
## V1.3.1
* use Android SDK 1.4.3.8
## V1.3.0
* iOS support privacyInfo
* use TPNS iOS SDK 1.4.0.1
## V1.2.9
* demo support null safety
* use TPNS iOS SDK 1.4.0.0
## V1.2.8
* Standard iOS/Android callback
## V1.2.7
* Use TPNS Android SDK 1.4.0.1
* Use TPNS iOS SDK 1.3.9.8
* configureClusterDomainName api support Android
## V1.2.6
* Use TPNS iOS SDK 1.3.9.7
## V1.2.5
* Use TPNS iOS SDK 1.3.9.6
## V1.2.4
* Use TPNS Android SDK 1.4.0.1
## V1.2.3
* Use TPNS iOS SDK 1.3.9.5
## V1.2.2
* Use TPNS iOS SDK 1.3.9.4
## V1.2.1
* Use TPNS iOS SDK 1.3.9.3
## V1.2.0
* Use TPNS iOS SDK 1.3.9.2
* Change API Doc
## V1.1.9
* Add iOS CallBack xgPushNetworkConnected
## V1.1.8
* Use TPNS iOS SDK 1.3.9.1
## V1.1.7
* Use TPNS Android SDK 1.3.4.3
* Use TPNS iOS SDK 1.3.9.0
## V1.1.6
* Use TPNS Android SDK 1.3.2.0
## V1.1.5
* Use TPNS Android SDK 1.2.7.1
* Add Api for attributes operation
## V1.1.4
* Use TPNS iOS SDK 1.3.4.1
## V1.1.3
* update TPNS Android SDK 1.2.3.1
* remove redundant manifest configuration in android
## V1.1.2
* iOS start add optional notification online display
* Use TPNS iOS SDK 1.3.3.0
## V1.1.1_oc
* plugin delete swift file
## V1.1.1
* Support null safety
* Use TPNS iOS SDK 1.3.1.1
## V1.0.7
* Use TPNS iOS SDK 1.2.9.0
* Use TPNS Android SDK 1.2.2.4
* Add badge configuration api for Android
## V1.0.6
* Fix api setAccount() not compatible with old version flutter binder
* Add api getOtherPushType for Android
## V1.0.5
* Add Api getOtherPushToken for Android
## V1.0.4
* Account and Tag API updates
* Add set ApplicationBadge on iOS
* Modify callback method on Android
## V1.0.3
* Use TPNS iOS SDK 1.2.7.2
* Use TPNS Android SDK 1.2.0.2 此版本较旧版本有包名变更,请注意参考 README.md 修改混淆配置;请注意修改 OPPO 通道混淆配置:
## V1.0.1
* Use TPNS iOS SDK 1.2.6.0
## V1.0.0
* Use TPNS iOS SDK 1.2.5.4
* Use TPNS Android SDK 1.1.5.2
\ No newline at end of file
... ...
MIT License
Copyright (c) 2020 Tencent
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
... ...
# tpns_flutter_plugin
## 安装
- 在工程 pubspec.yaml 中加入 dependencies,在命令行中运行:flutter pub get进行安装
```yaml
dependencies:
tpns_flutter_plugin:
git:
url: https://github.com/TencentCloud/TPNS-Flutter-Plugin
ref: V1.3.4
```
- 注意:由于TPNS插件名变更xg_flutter_plugin->tpns_flutter_plugin,更新插件时V1.0.4及以上版本请使用tpns_flutter_plugin
## 使用
### 集群域名配置(如果您的应用非广州集群请按照以下方法进行域名配置,广州集群请忽略)
**说明** : 此接口V1.2.7开始支持安卓,若您插件版本>=1.2.7,建议您将原来的Manifest对应域名设置删除,以接口为准.
#### 集群域名:
中国上海:tpns.sh.tencent.com
中国香港:tpns.hk.tencent.com
新加坡:tpns.sgp.tencent.com
- 需要在注册方法startXg之前调用以下域名配置函数
- domainStr 对应集群域名
```dart
void configureClusterDomainName(String domainStr);
```
### iOS
- 执行flutter pub get安装好插件后进入iOS文件目录(cd ios)执行:pod install安装依赖库
- 在 xcode8 之后需要点开推送选项: TARGETS -> Capabilities -> Push Notification 设为 on 状态
```dart
import 'package:tpns_flutter_plugin/tpns_flutter_plugin.dart';
```
说明(接口使用参考/tpns_flutter_plugin/example/lib/main.dart和/tpns_flutter_plugin/example/lib/ios/homeTest.dart文件)
### Android
#### 1. 环境配置
```groovy
android: {
....
defaultConfig {
applicationId "替换成自己应用 ID"
...
ndk {
/// 选择要添加的对应.so 库。
abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64', 'mips', 'mips64', 'arm64-v8a',
}
//
manifestPlaceholders = [
XG_ACCESS_ID : "替换自己的ACCESS_ID", // 信鸽官网注册所得ACCESS_ID
XG_ACCESS_KEY : "替换自己的ACCESS_KEY", // 信鸽官网注册所得ACCESS_KEY
]
}
}
```
#### 2. 代码混淆
```
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep class com.tencent.android.tpush.** {*;}
-keep class com.tencent.tpns.baseapi.** {*;}
-keep class com.tencent.tpns.mqttchannel.** {*;}
-keep class com.tencent.tpns.dataacquisition.** {*;}
-keep class com.tencent.bigdata.baseapi.** {*;} // TPNS-Android-SDK 1.2.0.1 及以上版本不需要此条配置
-keep class com.tencent.bigdata.mqttchannel.** {*;} // TPNS-Android-SDK 1.2.0.1 及以上版本不需要此条配置
```
#### 3. 厂商通道接入说明
**说明** : 提供安卓各厂商通道接入方法。
[点击查看](./documents/vendor.md)
### 启用推送
/// iOS前台收到通知不希望展示时可将withInAppAlert参数置为false
/// android 接入厂商通道时,请在此注册方法前调用各厂商通道参数配置接口
```dart
void startXg(String accessId, String accessKey, {bool withInAppAlert = true});
```
### APIs
**说明** : 提供TPNS的所有业务接口。
[点击查看](./documents/APIs.md)
### TPNS-Flutter 使用常见问题参考
[点击查看](https://cloud.tencent.com/document/product/548/48803)
... ...
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
... ...
group 'com.tencent.tpns.plugin'
version '1.0-SNAPSHOT'
buildscript {
ext.kotlin_version = '1.5.31'
repositories {
mavenCentral()
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
rootProject.allprojects {
repositories {
mavenCentral()
google()
jcenter()
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
namespace "com.tencent.tpns"
compileSdkVersion 31
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
minSdkVersion 16
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
//添加以下依赖
implementation 'com.tencent.tpns:tpns:1.4.3.8-release'
compileOnly files('libs/flutter.jar')
}
... ...
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
... ...
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
... ...
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tencent.tpns.plugin">
<application>
<!-- 【可选】APP实现的Receiver,用于接收消息透传和操作结果的回调,请根据需要添加 -->
<!-- YOUR_PACKAGE_PATH.CustomPushReceiver需要改为自己的Receiver: -->
<receiver android:name="com.tencent.tpns.plugin.XGMessageReceiver"
android:exported="true">
<intent-filter>
<!-- 接收消息透传 -->
<action android:name="com.tencent.android.xg.vip.action.PUSH_MESSAGE" />
<!-- 监听注册、反注册、设置/删除标签、通知被点击等处理结果 -->
<action android:name="com.tencent.android.xg.vip.action.FEEDBACK" />
</intent-filter>
</receiver>
</application>
</manifest>
... ...
package com.tencent.tpns.plugin;
import android.util.Log;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.UUID;
/**
* 获取系统设备信息的工具类
*/
public class DeviceInfoUtil {
/* 获取手机唯一序列号 */
public static String getDeviceId(Context context) {
TelephonyManager tm =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String deviceId = tm.getDeviceId();// 手机设备ID,这个ID会被用为用户访问统计
if (deviceId == null) {
deviceId = UUID.randomUUID().toString().replaceAll("-", "");
}
return deviceId;
}
/* 获取操作系统版本号 */
public static String getOsVersion() {
return Build.VERSION.RELEASE;
}
/* 获取手机型号 */
public static String getModel() {
return Build.MODEL;
}
/* 获取手机厂商 */
public static String getManufacturers() {
return Build.MANUFACTURER;
}
/* 获取app的版本信息 */
public static int getVersionCode(Context context) {
PackageManager manager = context.getPackageManager();
try {
PackageInfo packageInfo = manager.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;// 系统版本号
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return 0;
}
public static String getVersionName(Context context) {
PackageManager manager = context.getPackageManager();
try {
PackageInfo packageInfo = manager.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionName;// 系统版本名
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return "";
}
/**
* getSystemProperty
*
* @param propName property name
* @return result
*/
public static String getSystemProperty(String propName) {
String line;
BufferedReader input = null;
try {
Process p = Runtime.getRuntime().exec("getprop " + propName);
input = new BufferedReader(new InputStreamReader(p.getInputStream()), 1024);
line = input.readLine();
input.close();
} catch (IOException ex) {
return null;
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
Log.d("DeviceInfoUtil", "close bufferedReader error " + e.toString());
}
}
}
return line;
}
/**
* 判断 google miui emui meizu oppo vivo 360 Rom
*
* @return result
*/
public static boolean isGoogleRom() {
String property = getSystemProperty("ro.product.vendor.manufacturer");
return !TextUtils.isEmpty(property) && property.toLowerCase().contains("google");
}
public static boolean isMiuiRom() {
String property = getSystemProperty("ro.miui.ui.version.name");
return !TextUtils.isEmpty(property);
}
public static boolean isEmuiRom() {
String property = getSystemProperty("ro.build.version.emui");
return !TextUtils.isEmpty(property);
}
public static boolean isMeizuRom() {
String property = getSystemProperty("ro.build.display.id");
return property != null && property.toLowerCase().contains("flyme");
}
public static boolean isOppoRom() {
String property = getSystemProperty("ro.build.version.opporom");
return !TextUtils.isEmpty(property);
}
public static boolean isVivoRom() {
String property = getSystemProperty("ro.vivo.os.version");
return !TextUtils.isEmpty(property);
}
public static boolean is360Rom() {
return Build.MANUFACTURER != null
&& (Build.MANUFACTURER.toLowerCase().contains("qiku")
|| Build.MANUFACTURER.contains("360"));
}
}
... ...
package com.tencent.tpns.plugin;
public interface Extras {
//参数
String DEBUG = "enableDebug";
String TAG_NAME = "tagName"; //tag名称
String TAG_NAMES = "tagNames"; //tag名称集合
String ATTRIBUTES = "attributes";
String CONTENT = "content"; //
String RESULT_CODE = "resultCode";
String MESSAGE = "message";
String PUSH_TOKEN = "pushToken";
String TITLE = "title";
String CUSTOM_MESSAGE = "customMessage";
String PUSH_CHANNEL = "pushChannel";
String NOTIFACTION_ID = "notifactionId";
String NOTIFACTION_ACTION_TYPE = "notifactionActionType";
String MSG_ID = "msgId";
String ACTIVITY = "activity";
String ACTIVITY_NAME = "activityName";
String ACTION_TYPE = "actionType";
String ACCOUNT = "account";
String ACCOUNT_TYPE = "accountType";
String APP_KEY = "appKey";
String APP_ID = "appId";
String HEADER_BEAT_INTERVAL_MS = "heartBeatIntervalMs";
String XG_PUSH_DID_SET_BADGE = "xgPushDidSetBadge";
String BADGE_NUM = "badgeNum";
String CHANNEL_ID = "channelId";
String CHANNEL_NAME = "channelName";
String ENABLE_VIBRATION = "enableVibration";
String ENABLE_LIGHTS = "enableLights";
String ENABLE_SOUND = "enableSound";
String SOUND_FILE_NAME = "soundFileName";
String ADDR = "addr";
String ACCESSID = "accessId";
String ACCESSKEY = "accessKey";
//Flutter调用native的函数名称
String FOR_FLUTTER_METHOD_SET_ACCESSID = "setAccessId";
String FOR_FLUTTER_METHOD_SET_ACCESSKEY = "setAccessKey";
String FOR_FLUTTER_METHOD_SET_SERVERSUFFIX = "setServerSuffix";
String FOR_FLUTTER_METHOD_REG_PUSH = "regPush";
String FOR_FLUTTER_METHOD_UNREGISTER_PUSH = "stopXg";
String FOR_FLUTTER_METHOD_SET_TAG = "setXgTag";
String FOR_FLUTTER_METHOD_SET_TAGS = "setXgTags";
String FOR_FLUTTER_METHOD_ADD_TAGS = "addXgTags";
String FOR_FLUTTER_METHOD_DELETE_TAG = "deleteXgTag";
String FOR_FLUTTER_METHOD_DELETE_TAGS = "deleteXgTags";
String FOR_FLUTTER_METHOD_CLEAN_TAGS = "cleanXgTags";
String FOR_FLUTTER_METHOD_GET_TOKEN = "xgToken";
String FOR_FLUTTER_METHOD_GET_SDK_VERSION = "xgSdkVersion";
String FOR_FLUTTER_METHOD_BIND_ACCOUNT = "bindAccount";
String FOR_FLUTTER_METHOD_APPEND_ACCOUNT = "appendAccount";
String FOR_FLUTTER_METHOD_DEL_ACCOUNT = "delAccount";
String FOR_FLUTTER_METHOD_DEL_ALL_ACCOUNT = "delAllAccount";
String FOR_FLUTTER_METHOD_UPSERT_ATTRIBUTES = "upsertAttributes";
String FOR_FLUTTER_METHOD_DEL_ATTRIBUTES = "delAttributes";
String FOR_FLUTTER_METHOD_CLEAR_AND_APPEND_ATTRIBUTES = "clearAndAppendAttributes";
String FOR_FLUTTER_METHOD_CLEAR_ATTRIBUTES = "clearAttributes";
String FOR_FLUTTER_METHOD_ENABLE_OTHER_PUSH = "enableOtherPush";
String FOR_FLUTTER_METHOD_ENABLE_OTHER_PUSH2 = "enableOtherPush2";
String FOR_FLUTTER_METHOD_GET_OTHER_PUSH_TOKEN = "getOtherPushToken";
String FOR_FLUTTER_METHOD_GET_OTHER_PUSH_TYPE = "getOtherPushType";
String FOR_FLUTTER_METHOD_ENABLE_PULL_UP_OTHER_APP = "enablePullUpOtherApp";
String FOR_FLUTTER_METHOD_SET_BADGE_NUM = "setBadgeNum";
String FOR_FLUTTER_METHOD_RESET_BADGE_NUM = "resetBadgeNum";
String FOR_FLUTTER_METHOD_CANCEL_ALL_NOTIFICATION = "cancelAllNotification";
String FOR_FLUTTER_METHOD_CREATE_NOTIFICATION_CHANNEL = "createNotificationChannel";
String FOR_FLUTTER_METHOD_SET_MI_PUSH_APP_ID = "setMiPushAppId";
String FOR_FLUTTER_METHOD_SET_MI_PUSH_APP_KEY = "setMiPushAppKey";
String FOR_FLUTTER_METHOD_SET_MZ_PUSH_ID = "setMzPushAppId";
String FOR_FLUTTER_METHOD_SET_MZ_PUSH_KEY = "setMzPushAppKey";
String FOR_FLUTTER_METHOD_ENABLE_OPPO_NOTIFICATION = "enableOppoNotification";
String FOR_FLUTTER_METHOD_SET_OPPO_PUSH_APP_ID = "setOppoPushAppId";
String FOR_FLUTTER_METHOD_SET_OPPO_PUSH_APP_KEY = "setOppoPushAppKey";
String FOR_FLUTTER_METHOD_IS_MIUI_ROM = "isMiuiRom";
String FOR_FLUTTER_METHOD_IS_EMUI_ROM = "isEmuiRom";
String FOR_FLUTTER_METHOD_IS_MEIZU_ROM = "isMeizuRom";
String FOR_FLUTTER_METHOD_IS_OPPO_ROM = "isOppoRom";
String FOR_FLUTTER_METHOD_IS_VIVO_ROM = "isVivoRom";
String FOR_FLUTTER_METHOD_IS_360_ROM = "is360Rom";
String FOR_FLUTTER_METHOD_IS_FCM_ROM = "isFcmRom";
String FOR_FLUTTER_METHOD_IS_GOOGLE_ROM = "isGoogleRom";
String FOR_FLUTTER_METHOD_ENABLE_DEBUG = "setEnableDebug";
String FOR_FLUTTER_METHOD_SET_HEADER_BEAT_INTERVAL_MS = "setHeartbeatIntervalMs";
//调用Flutter的函数名称
String ON_REGISTERED_DEVICE_TOKEN = "onRegisteredDeviceToken"; //注册失败回调
String ON_REGISTERED_DONE = "onRegisteredDone"; //注册成功回调
String UN_REGISTERED = "unRegistered"; //反注册回调
String ON_RECEIVE_NOTIFICATION_RESPONSE = "onReceiveNotificationResponse"; //收到通知
String ON_RECEIVE_MESSAGE = "onReceiveMessage"; //收到透传通知
String XG_PUSH_DID_BIND_WITH_IDENENTIFIER = "xgPushDidBindWithIdentifier"; // 绑定账号跟标签
String XG_PUSH_DID_UNBIND_WITH_IDENENTIFIER = "xgPushDidUnbindWithIdentifier"; //解绑账号跟标签
String XG_PUSH_DID_UPDATED_WITH_IDENENTIFIER = "xgPushDidUpdatedBindedIdentifier"; //更新账号跟标签
String XG_PUSH_DID_CLEAR_WITH_IDENENTIFIER = "xgPushDidClearAllIdentifiers"; //清除账号跟标签
String XG_PUSH_CLICK_ACTION = "xgPushClickAction"; //通知点击事件
}
... ...
package com.tencent.tpns.plugin;
import android.os.Handler;
import android.os.Looper;
public class MainHandler extends Handler {
private static volatile MainHandler instance;
public static MainHandler getInstance() {
if (null == instance) {
synchronized (MainHandler.class) {
if (null == instance) {
instance = new MainHandler();
}
}
}
return instance;
}
private MainHandler() {
super(Looper.getMainLooper());
}
}
... ...
package com.tencent.tpns.plugin;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import com.tencent.android.tpush.XGPushBaseReceiver;
import com.tencent.android.tpush.XGPushClickedResult;
import com.tencent.android.tpush.XGPushRegisterResult;
import com.tencent.android.tpush.XGPushShowedResult;
import com.tencent.android.tpush.XGPushTextMessage;
import java.util.HashMap;
import java.util.Map;
public class XGMessageReceiver extends XGPushBaseReceiver {
private static final String TAG = "XGMessageReceiver";
private static ReceiverHandler receiverHandler;
private class ReceiverHandler extends Handler {
private Context context;
private XGPushClickedResult clickedResult;
public ReceiverHandler(Context context, XGPushClickedResult clickedResult) {
this.context = context;
this.clickedResult = clickedResult;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.i(TAG, "ReceiverHandler handleMessage from XgFlutterPlugin init");
processClickActionToFlutter(context, clickedResult);
receiverHandler = null;
}
}
/**
* 通知点击冷启动时,MethodChannel 初始化和点击回调的触发时机不固定,可能导致点击回调触发时,MethodChannel 还未初始化。
*
* 此处再 MethodChannel 初始化时尝试触发一次 handler,补偿冷启动时点击事件回调给 flutter
*/
public static void sendHandlerMessage(){
if (receiverHandler != null) {
Message m = receiverHandler.obtainMessage();
m.sendToTarget();
} else {
Log.i(TAG, "ReceiverHandler sendHandlerMessage XgFlutterPlugin already init");
}
}
@Override
public void onRegisterResult(Context context, int errorCode, XGPushRegisterResult message) {
try {
if (XgFlutterPlugin.instance == null) {
Log.w(TAG, "XgFlutterPlugin.instance has not initialized");
return;
}
if (context == null || message == null) {
String msg = "TPNS token: null" + " error: context==null||message == null";
XgFlutterPlugin.instance.toFlutterMethod(Extras.ON_REGISTERED_DEVICE_TOKEN, msg);
return;
}
if (errorCode == XGPushBaseReceiver.SUCCESS) {
String token = message.getToken();
// 过滤掉厂商通道注册结果
if (!TextUtils.isEmpty(token)) {
String msg = token;
XgFlutterPlugin.instance.toFlutterMethod(Extras.ON_REGISTERED_DONE, msg);
}
} else {
String msg = "TPNS token: " + message.getToken() + " error: " + errorCode;
XgFlutterPlugin.instance.toFlutterMethod(Extras.ON_REGISTERED_DEVICE_TOKEN, msg);
}
} catch (Throwable e) {
Log.w(TAG, "onRegisterResult error: " + e.toString());
}
}
@Override
public void onUnregisterResult(Context context, int errorCode) {
try {
if (XgFlutterPlugin.instance == null) {
Log.w(TAG, "XgFlutterPlugin.instance has not initialized");
return;
}
if (context == null) {
String msg = "context == null---->Unregister failure";
XgFlutterPlugin.instance.toFlutterMethod(Extras.UN_REGISTERED, msg);
return;
}
String text = "";
if (errorCode == XGPushBaseReceiver.SUCCESS) {
String msg = "Unregister successful";
XgFlutterPlugin.instance.toFlutterMethod(Extras.UN_REGISTERED, msg);
} else {
String msg = "Unregister failure---->code==" + errorCode;
XgFlutterPlugin.instance.toFlutterMethod(Extras.UN_REGISTERED, msg);
}
} catch (Throwable e) {
Log.w(TAG, "onUnregisterResult error: " + e.toString());
}
}
@Override
public void onSetTagResult(Context context, int errorCode, String s) {
}
@Override
public void onDeleteTagResult(Context context, int errorCode, String s) {
}
@Override
public void onSetAccountResult(Context context, int i, String s) {
}
@Override
public void onDeleteAccountResult(Context context, int i, String s) {
}
@Override
public void onSetAttributeResult(Context context, int i, String s) {
}
@Override
public void onDeleteAttributeResult(Context context, int i, String s) {
}
@Override
public void onQueryTagsResult(Context context, int i, String s, String o) {
}
@Override
public void onTextMessage(Context context, XGPushTextMessage message) {
try {
if (XgFlutterPlugin.instance == null) {
Log.w(TAG, "XgFlutterPlugin.instance has not initialized");
return;
}
long msgId = message.getMsgId();
String content = message.getContent();
String customContent = message.getCustomContent();
String title = message.getTitle();
int pushChannel = message.getPushChannel();
Map<String, Object> para = new HashMap<>();
para.put(Extras.MSG_ID, msgId);
para.put(Extras.TITLE, title);
para.put(Extras.CONTENT, content);
para.put(Extras.CUSTOM_MESSAGE, customContent);
para.put(Extras.PUSH_CHANNEL, pushChannel);
//交由Flutter自主处理
XgFlutterPlugin.instance.toFlutterMethod(Extras.ON_RECEIVE_MESSAGE, para);
} catch (Throwable e) {
Log.w(TAG, "onTextMessage error: " + e.toString());
}
}
@Override
public void onNotificationClickedResult(Context context, XGPushClickedResult notifiShowedRlt) {
try {
if (XgFlutterPlugin.instance == null) {
Log.w(TAG, "XgFlutterPlugin.instance has not initialized");
receiverHandler = new ReceiverHandler(context, notifiShowedRlt);
} else {
processClickActionToFlutter(context, notifiShowedRlt);
}
} catch (Throwable e) {
Log.w(TAG, "onNotificationClickedResult error: " + e.toString());
}
}
private void processClickActionToFlutter(Context context, XGPushClickedResult notifiShowedRlt) {
try {
if (context == null || notifiShowedRlt == null) {
Map<String, Object> para = new HashMap<>();
para.put(Extras.RESULT_CODE, -1);
para.put(Extras.MESSAGE, "通知栏展示失败----context == null || notifiShowedRlt == null");
// XgFlutterPlugin.instance.toFlutterMethod(
// Extras.TO_FLUTTER_METHOD_NOTIFACTION_SHOW_RESULT, para);
return;
}
String content = notifiShowedRlt.getContent();
String customContent = notifiShowedRlt.getCustomContent();
String title = notifiShowedRlt.getTitle();
int notificationActionType = notifiShowedRlt.getNotificationActionType();
long msgId = notifiShowedRlt.getMsgId();
String activityName = notifiShowedRlt.getActivityName();
long actionType = notifiShowedRlt.getActionType();
Map<String, Object> para = new HashMap<>();
para.put(Extras.TITLE, title);
para.put(Extras.CONTENT, content);
para.put(Extras.CUSTOM_MESSAGE, customContent);
para.put(Extras.MSG_ID, msgId);
para.put(Extras.NOTIFACTION_ACTION_TYPE, notificationActionType);
para.put(Extras.ACTIVITY_NAME, activityName);
para.put(Extras.ACTION_TYPE, actionType);
//交由Flutter自主处理
XgFlutterPlugin.instance.toFlutterMethod(Extras.XG_PUSH_CLICK_ACTION, para);
} catch (Throwable e) {
Log.w(TAG, "processClickActionToFlutter error: " + e.toString());
}
}
@Override
public void onNotificationShowedResult(Context context, XGPushShowedResult message) {
try {
if (XgFlutterPlugin.instance == null) {
Log.w(TAG, "XgFlutterPlugin.instance has not initialized");
return;
}
if (context == null || message == null) {
Map<String, Object> para = new HashMap<>();
para.put(Extras.RESULT_CODE, -1);
para.put(Extras.MESSAGE, "点击通知失败----context == null || XGPushClickedResult == null");
// XgFlutterPlugin.instance.toFlutterMethod(
// Extras.TO_FLUTTER_METHOD_NOTIFACTION_SHOW_RESULT, para);
return;
}
String content = message.getContent();
String customContent = message.getCustomContent();
int notifactionId = message.getNotifactionId();
String title = message.getTitle();
long msgId = message.getMsgId();
String activityPath = message.getActivity();
int pushChannel = message.getPushChannel();
int notificationActionType = message.getNotificationActionType();
Map<String, Object> para = new HashMap<>();
para.put(Extras.CONTENT, content);
para.put(Extras.CUSTOM_MESSAGE, customContent);
para.put(Extras.TITLE, title);
para.put(Extras.PUSH_CHANNEL, pushChannel);
para.put(Extras.NOTIFACTION_ID, notifactionId);
para.put(Extras.MSG_ID, msgId);
para.put(Extras.ACTIVITY, activityPath);
para.put(Extras.NOTIFACTION_ACTION_TYPE, notificationActionType);
//交由Flutter自主处理
XgFlutterPlugin.instance.toFlutterMethod(Extras.ON_RECEIVE_NOTIFICATION_RESPONSE, para);
} catch (Throwable e) {
Log.w(TAG, "onNotificationShowedResult error: " + e.toString());
}
}
}
... ...
package com.tencent.tpns.plugin
import android.net.Uri;
import android.util.Log
import androidx.annotation.NonNull
import com.tencent.android.tpush.XGIOperateCallback
import com.tencent.android.tpush.XGPushConfig
import com.tencent.tpns.baseapi.XGApiConfig
import com.tencent.android.tpush.XGPushManager
import com.tencent.android.tpush.XGPushConstants
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.PluginRegistry.Registrar
import java.util.*
public class XgFlutterPlugin : FlutterPlugin, MethodCallHandler {
private var TAG = "| XgpushpPlugin | Flutter | Android | "
constructor() {
instance = this
}
constructor(binding: FlutterPlugin.FlutterPluginBinding, methodChannel: MethodChannel) {
mPluginBinding = binding
channel = methodChannel
instance = this
}
constructor(mRegistrar: Registrar, mChannel: MethodChannel) {
channel = mChannel
registrar = mRegistrar
instance = this
}
companion object {
lateinit var instance: XgFlutterPlugin
lateinit var mPluginBinding: FlutterPlugin.FlutterPluginBinding
lateinit var channel: MethodChannel
lateinit var registrar: Registrar
@JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "tpns_flutter_plugin")
channel.setMethodCallHandler(XgFlutterPlugin(registrar, channel))
Log.i("| XgpushpPlugin | Flutter | Android | ", "methodChannel registerWith XgFlutterPlugin")
Log.i("| XgpushpPlugin | Flutter | Android | ", "instance = " + instance)
}
fun checkPluginBindingInit() : Boolean {
return this::mPluginBinding.isInitialized
}
// 为兼容老版本 Flutter 项目插件加载方式,结合 kotlin lateinit 对象特性,
// 需要在判断 mPluginBinding == mull 之前先判断是否有初始化
fun isPluginBindingValid() : Boolean {
if (checkPluginBindingInit()) {
// Log.i("| XgpushpPlugin | Flutter | Android | ",
// "mPluginBinding initialzed, " + (mPluginBinding != null))
return mPluginBinding != null
} else {
Log.i("| XgpushpPlugin | Flutter | Android | ", "mPluginBinding not initialzed")
return false
}
}
}
override fun onMethodCall(@NonNull p0: MethodCall, @NonNull p1: MethodChannel.Result) {
Log.i(TAG, p0.method)
if (!isPluginBindingValid() && registrar == null) {
Log.i(TAG, "调用native的函数" + p0.method + "失败mPluginBinding==null&&registrar==null")
return
}
when (p0.method) {
Extras.FOR_FLUTTER_METHOD_REG_PUSH -> regPush(p0, p1)
Extras.FOR_FLUTTER_METHOD_UNREGISTER_PUSH -> stopXg(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_TAG -> setXgTag(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_TAGS -> setXgTags(p0, p1)
Extras.FOR_FLUTTER_METHOD_ADD_TAGS -> addXgTags(p0, p1)
Extras.FOR_FLUTTER_METHOD_DELETE_TAG -> deleteXgTag(p0, p1)
Extras.FOR_FLUTTER_METHOD_DELETE_TAGS -> deleteXgTags(p0, p1)
Extras.FOR_FLUTTER_METHOD_CLEAN_TAGS -> cleanXgTags(p0, p1)
Extras.FOR_FLUTTER_METHOD_GET_TOKEN -> xgToken(p0, p1)
Extras.FOR_FLUTTER_METHOD_GET_SDK_VERSION -> xgSdkVersion(p0, p1)
Extras.FOR_FLUTTER_METHOD_BIND_ACCOUNT -> bindAccount(p0, p1)
Extras.FOR_FLUTTER_METHOD_APPEND_ACCOUNT -> appendAccount(p0, p1)
Extras.FOR_FLUTTER_METHOD_DEL_ACCOUNT -> delAccount(p0, p1)
Extras.FOR_FLUTTER_METHOD_DEL_ALL_ACCOUNT -> delAllAccount(p0, p1)
Extras.FOR_FLUTTER_METHOD_UPSERT_ATTRIBUTES -> upsertAttributes(p0, p1)
Extras.FOR_FLUTTER_METHOD_DEL_ATTRIBUTES -> delAttributes(p0, p1)
Extras.FOR_FLUTTER_METHOD_CLEAR_AND_APPEND_ATTRIBUTES -> clearAndAppendAttributes(p0, p1)
Extras.FOR_FLUTTER_METHOD_CLEAR_ATTRIBUTES -> clearAttributes(p0, p1)
Extras.FOR_FLUTTER_METHOD_ENABLE_OTHER_PUSH -> enableOtherPush(p0, p1)
Extras.FOR_FLUTTER_METHOD_ENABLE_OTHER_PUSH2 -> enableOtherPush2(p0, p1)
Extras.FOR_FLUTTER_METHOD_GET_OTHER_PUSH_TOKEN -> getOtherPushToken(p0, p1)
Extras.FOR_FLUTTER_METHOD_GET_OTHER_PUSH_TYPE -> getOtherPushType(p0, p1)
Extras.FOR_FLUTTER_METHOD_ENABLE_PULL_UP_OTHER_APP -> enablePullUpOtherApp(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_BADGE_NUM -> setBadgeNum(p0, p1)
Extras.FOR_FLUTTER_METHOD_RESET_BADGE_NUM -> resetBadgeNum(p0, p1)
Extras.FOR_FLUTTER_METHOD_CANCEL_ALL_NOTIFICATION -> cancelAllNotification(p0, p1);
Extras.FOR_FLUTTER_METHOD_CREATE_NOTIFICATION_CHANNEL -> createNotificationChannel(p0, p1);
Extras.FOR_FLUTTER_METHOD_SET_MI_PUSH_APP_ID -> setMiPushAppId(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_MI_PUSH_APP_KEY -> setMiPushAppKey(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_MZ_PUSH_ID -> setMzPushAppId(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_MZ_PUSH_KEY -> setMzPushAppKey(p0, p1)
Extras.FOR_FLUTTER_METHOD_ENABLE_OPPO_NOTIFICATION -> enableOppoNotification(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_OPPO_PUSH_APP_KEY -> setOppoPushAppKey(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_OPPO_PUSH_APP_ID -> setOppoPushAppId(p0, p1)
Extras.FOR_FLUTTER_METHOD_IS_MIUI_ROM -> isMiuiRom(p0, p1)
Extras.FOR_FLUTTER_METHOD_IS_EMUI_ROM -> isEmuiRom(p0, p1)
Extras.FOR_FLUTTER_METHOD_IS_MEIZU_ROM -> isMeizuRom(p0, p1)
Extras.FOR_FLUTTER_METHOD_IS_OPPO_ROM -> isOppoRom(p0, p1)
Extras.FOR_FLUTTER_METHOD_IS_VIVO_ROM -> isVivoRom(p0, p1)
Extras.FOR_FLUTTER_METHOD_IS_FCM_ROM -> isFcmRom(p0, p1)
Extras.FOR_FLUTTER_METHOD_IS_GOOGLE_ROM -> isGoogleRom(p0, p1)
Extras.FOR_FLUTTER_METHOD_IS_360_ROM -> is360Rom(p0, p1)
Extras.FOR_FLUTTER_METHOD_ENABLE_DEBUG -> setEnableDebug(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_HEADER_BEAT_INTERVAL_MS -> setHeartbeatIntervalMs(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_SERVERSUFFIX -> setServerSuffix(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_ACCESSID -> setAccessId(p0, p1)
Extras.FOR_FLUTTER_METHOD_SET_ACCESSKEY -> setAccessKey(p0, p1)
}
}
/**
* 调用Flutter 函数
*
* @param methodName 函数名称
* @param para 参数
*/
fun toFlutterMethod(methodName: String, para: Map<String, Any?>?) {
Log.i(TAG, "调用Flutter=>${methodName}")
MainHandler.getInstance().post { channel.invokeMethod(methodName, para) }
}
fun toFlutterMethod(methodName: String, para: String) {
Log.i(TAG, "调用Flutter=>${methodName}")
MainHandler.getInstance().post { channel.invokeMethod(methodName, para) }
}
/**
* 设置accessId
*/
private fun setAccessId(call: MethodCall, result: MethodChannel.Result) {
val map = call.arguments<Map<String, String>>()
val accessId = map[Extras.ACCESSID] as String
val value = accessId.toLong();
Log.i(TAG, "调用信鸽SDK-->setAccessId()-----accessId=${value}")
XGPushConfig.setAccessId(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, value);
}
/**
* 设置accessKey
*/
private fun setAccessKey(call: MethodCall, result: MethodChannel.Result) {
val map = call.arguments<Map<String, String>>()
val accessKey = map[Extras.ACCESSKEY]
Log.i(TAG, "调用信鸽SDK-->setAccessKey()-----accessKey=${accessKey}")
XGPushConfig.setAccessKey(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, accessKey);
}
/**
* 设置接入域名
*/
private fun setServerSuffix(call: MethodCall, result: MethodChannel.Result) {
val map = call.arguments<Map<String, String>>()
val addr = map[Extras.ADDR]
Log.i(TAG, "调用信鸽SDK-->setServerSuffix()-----addr=${addr}")
XGApiConfig.setServerSuffix(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, addr);
}
/**
* 信鸽推送注册
*/
fun regPush(call: MethodCall?, result: MethodChannel.Result?) {
Log.i(TAG, "调用信鸽SDK-->registerPush()")
XGPushManager.registerPush(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext)
}
fun mRegPush(methodName: String, para: Map<String, Any?>?) {
MainHandler.getInstance().post { channel.invokeMethod("startXg", para) }
}
/**
* 开启Debug模式
*/
private fun setEnableDebug(call: MethodCall, result: MethodChannel.Result) {
val map = call.arguments<HashMap<String, Any>>()
val debug = map[Extras.DEBUG] as Boolean
Log.i(TAG, "调用信鸽SDK-->enableDebug()----->isDebug=${debug}")
XGPushConfig.enableDebug(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, debug)
}
/**
* 设置心跳时间间隔
*/
fun setHeartbeatIntervalMs(call: MethodCall, result: MethodChannel.Result) {
val map = call.arguments<HashMap<String, Any>>()
val interval = map[Extras.HEADER_BEAT_INTERVAL_MS] as Int
Log.i(TAG, "调用信鸽SDK-->setHeartbeatIntervalMs()----->interval=${interval}")
XGPushConfig.setHeartbeatIntervalMs(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, interval)
}
/**
* 反注册
*
*
* 当用户已退出或 App 被关闭,不再需要接收推送时,可以取消注册 App,即反注册。
* (一旦设备反注册,直到这个设备重新注册成功期间内,下发的消息该设备都无法收到)
*
* @param call 方法
* @param result 结果
*/
fun stopXg(call: MethodCall?, result: MethodChannel.Result?) {
Log.i(TAG, "调用信鸽SDK-->unregisterPush()")
XGPushManager.unregisterPush(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext)
}
/**
* 设置标签,单个标签 call传参为TagName
*
* @param call 方法
* @param result 结果
*/
fun setXgTag(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<HashMap<String, String>>()
val tagName = map[Extras.TAG_NAME]
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
Log.i(TAG, "调用信鸽SDK-->setTag()---->tagName${tagName}")
XGPushManager.setTag(context, tagName, object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "setTag successful")
val paraDict = mapOf("code" to 0,"type" to "tag", "msg" to "setTag successful")
toFlutterMethod(Extras.XG_PUSH_DID_UPDATED_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "setTag failure")
val paraDict = mapOf("code" to p1,"type" to "tag", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_UPDATED_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 设置多tag call传参为List<String>tag的集合
* 一次设置多个标签,会覆盖这个设备之前设置的标签。
*
* @param call 方法
* @param result 结果
</String> */
fun setXgTags(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, List<String>>>()
val tags = HashSet<String>(map[Extras.TAG_NAMES])
//operateName用户定义的操作名称,回调结果会原样返回,用于标识回调属于哪次操作。
val operateName = "setTags:" + System.currentTimeMillis()
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
Log.i(TAG, "调用信鸽SDK-->setTags()")
XGPushManager.setTags(context, operateName, tags, object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "setTags successful")
val paraDict = mapOf("code" to 0,"type" to "tag", "msg" to "setTags successful")
toFlutterMethod(Extras.XG_PUSH_DID_UPDATED_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "setTags failure")
val paraDict = mapOf("code" to p1,"type" to "tag", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_UPDATED_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 添加多个标签 call传参为List<String>tag的集合 每个 tag 不能超过40字节(超过会抛弃)不能包含空格(含有空格会删除空格)
* 最多设置1000个 tag,超过部分会抛弃
* 一次设置多个标签,会覆盖这个设备之前设置的标签。
*
*
* 如果新增的标签的格式为 "test:2 level:2",则会删除这个设备的全部历史标签,再新增 test:2 和 level。
* 如果新增的标签有部分不带:号,如 "test:2 level",则会删除这个设备的全部历史标签,再新增 test:2 和 level 标签。
*
*
* 新增的 tags 中,:号为后台关键字,请根据具体的业务场景使用。
* 此接口调用的时候需要间隔一段时间(建议大于5s),否则可能造成更新失败。
*
* @param call 方法
* @param result 结果
</String> */
fun addXgTags(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, List<String>>>()
val tags = HashSet<String>(map[Extras.TAG_NAMES])
//operateName用户定义的操作名称,回调结果会原样返回,用于标识回调属于哪次操作。
val operateName = "addTags:" + System.currentTimeMillis()
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
Log.i(TAG, "调用信鸽SDK-->addTags()")
XGPushManager.addTags(context, operateName, tags, object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "addTags successful")
val paraDict = mapOf("code" to 0,"type" to "tag", "msg" to "addTags successful")
toFlutterMethod(Extras.XG_PUSH_DID_BIND_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "addTags failure")
val paraDict = mapOf("code" to p1,"type" to "tag", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_BIND_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 删除指定标签 call传参为TagName需要删除的标签名称
*
* @param call 方法
* @param result 结果
*/
fun deleteXgTag(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, String>>()
val tagName = map[Extras.TAG_NAME]
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
Log.i(TAG, "调用信鸽SDK-->deleteTag()----tagName=${tagName}")
XGPushManager.deleteTag(context, tagName, object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "deleteTag successful")
val paraDict = mapOf("code" to 0,"type" to "tag", "msg" to "deleteTag successful")
toFlutterMethod(Extras.XG_PUSH_DID_UNBIND_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "deleteTag failure")
val para = "deleteTag failure----->code=${p1}--->message=${p2}"
val paraDict = mapOf("code" to p1,"type" to "tag", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_UNBIND_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 删除多个标签 call传参为List<String>tag的集合 每个标签是一个 String。限制:
* 每个 tag 不能超过40字节(超过会抛弃),不能包含空格(含有空格会删除空格)。最多设置1000个tag,超过部分会抛弃。
*
* @param call 方法
* @param result 结果
</String> */
fun deleteXgTags(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, List<String>>>()
val tags = HashSet<String>(map[Extras.TAG_NAMES])
//operateName用户定义的操作名称,回调结果会原样返回,用于标识回调属于哪次操作。
val operateName = "deleteTags:" + System.currentTimeMillis()
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
Log.i(TAG, "调用信鸽SDK-->deleteTags()----operateName=${operateName}")
XGPushManager.deleteTags(context, operateName, tags, object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "deleteTags successful")
val paraDict = mapOf("code" to 0,"type" to "tag", "msg" to "deleteTags successful")
toFlutterMethod(Extras.XG_PUSH_DID_UNBIND_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "deleteTags failure")
val paraDict = mapOf("code" to p1,"type" to "tag", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_UNBIND_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 清楚所有标签
*
* @param call 方法
* @param result 结果
*/
fun cleanXgTags(call: MethodCall?, result: MethodChannel.Result?) { //operateName用户定义的操作名称,回调结果会原样返回,用于标识回调属于哪次操作。
val operateName = "cleanTags:" + System.currentTimeMillis()
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
Log.i(TAG, "调用信鸽SDK-->cleanTags()----operateName=${operateName}")
XGPushManager.cleanTags(context, operateName, object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "cleanTags successful")
val paraDict = mapOf("code" to 0,"type" to "tag", "msg" to "cleanTags successful")
toFlutterMethod(Extras.XG_PUSH_DID_CLEAR_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "cleanTags failure")
val paraDict = mapOf("code" to p1,"type" to "tag", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_CLEAR_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 获取Xg的token
* App 第一次注册会产生 Token,之后一直存在手机上,不管以后注销注册操作,该 Token 一直存在,
* 当 App 完全卸载重装了 Token 会发生变化。不同 App 之间的 Token 不一样。
*/
fun xgToken(call: MethodCall?, result: MethodChannel.Result) {
val token: String = XGPushConfig.getToken(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext)
Log.i(TAG, "调用信鸽SDK-->getToken()----token=${token}")
result.success(token)
}
fun xgSdkVersion(call: MethodCall?, result: MethodChannel.Result) {
val sdkVersion: String = XGPushConstants.SDK_VERSION
Log.i(TAG, "调用信鸽SDK-->SDK_VERSION----${sdkVersion}")
result.success(sdkVersion)
}
fun getAccountType(accountType: String): Int {
when (accountType) {
"UNKNOWN" -> return XGPushManager.AccountType.UNKNOWN.getValue()
"CUSTOM" -> return XGPushManager.AccountType.CUSTOM.getValue()
// "IDFA" -> return XGPushManager.AccountType.IDFA.getValue()
"PHONE_NUMBER" -> return XGPushManager.AccountType.PHONE_NUMBER.getValue()
"WX_OPEN_ID" -> return XGPushManager.AccountType.WX_OPEN_ID.getValue()
"QQ_OPEN_ID" -> return XGPushManager.AccountType.QQ_OPEN_ID.getValue()
"EMAIL" -> return XGPushManager.AccountType.EMAIL.getValue()
"SINA_WEIBO" -> return XGPushManager.AccountType.SINA_WEIBO.getValue()
"ALIPAY" -> return XGPushManager.AccountType.ALIPAY.getValue()
"TAOBAO" -> return XGPushManager.AccountType.TAOBAO.getValue()
"DOUBAN" -> return XGPushManager.AccountType.DOUBAN.getValue()
"FACEBOOK" -> return XGPushManager.AccountType.FACEBOOK.getValue()
"TWITTER" -> return XGPushManager.AccountType.TWITTER.getValue()
"GOOGLE" -> return XGPushManager.AccountType.GOOGLE.getValue()
"BAIDU" -> return XGPushManager.AccountType.BAIDU.getValue()
"JINGDONG" -> return XGPushManager.AccountType.JINGDONG.getValue()
"LINKEDIN" -> return XGPushManager.AccountType.LINKEDIN.getValue()
"IMEI" -> return XGPushManager.AccountType.IMEI.getValue()
else -> return XGPushManager.AccountType.UNKNOWN.getValue()
}
}
/**
* 绑定账号注册
* 推荐有账号体系的App使用(此接口会覆盖设备之前绑定过的账号,仅当前注册的账号生效)
*
* @param call String 账号
* @param result 结果
*/
fun bindAccount(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, String>>()
val account = map[Extras.ACCOUNT]
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
var accountType: String = (map[Extras.ACCOUNT_TYPE]) ?: "UNKNOWN"
Log.i(TAG, "调用信鸽SDK-->bindAccount()----account=${account}, accountType=${accountType}")
XGPushManager.bindAccount(context, account, getAccountType(accountType), object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "bindAccount successful")
val paraDict = mapOf("code" to 0,"type" to "account", "msg" to "bindAccount successful")
toFlutterMethod(Extras.XG_PUSH_DID_BIND_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "bindAccount failure")
val paraDict = mapOf("code" to p1,"type" to "account", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_BIND_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 添加账号
* 推荐有账号体系的App使用(此接口保留之前的账号,只做增加操作,一个token下最多只能有10个账号超过限制会自动顶掉之前绑定的账号)
*
* @param call String 账号
* @param result 结果
*/
fun appendAccount(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, String>>()
val account = map[Extras.ACCOUNT]
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
var accountType: String = (map[Extras.ACCOUNT_TYPE]) ?: "UNKNOWN"
Log.i(TAG, "调用信鸽SDK-->appendAccount()----account=${account}, accountType=${accountType}")
XGPushManager.appendAccount(context, account, getAccountType(accountType), object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "appendAccount successful")
val paraDict = mapOf("code" to 0,"type" to "account", "msg" to "appendAccount successful")
toFlutterMethod(Extras.XG_PUSH_DID_BIND_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "appendAccount failure")
val paraDict = mapOf("code" to p1,"type" to "account", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_BIND_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 解除指定账号绑定
* 账号解绑只是解除 Token 与 App 账号的关联,若使用全量/标签/Token 推送仍然能收到通知/消息。
*
* @param call String账号
* @param result 结果
*/
fun delAccount(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, String>>()
val account = map[Extras.ACCOUNT]
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
var accountType: String = (map[Extras.ACCOUNT_TYPE]) ?: "UNKNOWN"
Log.i(TAG, "调用信鸽SDK-->delAccount()----account=${account}, accountType=${accountType}")
XGPushManager.delAccount(context, account, getAccountType(accountType), object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "delAccount successful")
val paraDict = mapOf("code" to 0,"type" to "account", "msg" to "delAccount successful")
toFlutterMethod(Extras.XG_PUSH_DID_UNBIND_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "delAccount failure")
val paraDict = mapOf("code" to p1,"type" to "account", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_UNBIND_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 清除全部账号
*/
fun delAllAccount(call: MethodCall, result: MethodChannel.Result?) {
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
Log.i(TAG, "调用信鸽SDK-->delAllAccount()")
XGPushManager.delAllAccount(context, object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "delAllAccount successful")
val paraDict = mapOf("code" to 0,"type" to "account", "msg" to "delAllAccount successful")
toFlutterMethod(Extras.XG_PUSH_DID_CLEAR_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "delAllAccount failure")
val paraDict = mapOf("code" to p1,"type" to "account", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_CLEAR_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 新增用户属性
*/
fun upsertAttributes(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, String>>()
val attributesMap = map[Extras.ATTRIBUTES] as HashMap<String, String>
Log.i(TAG, "调用信鸽SDK-->upsertAttributes()----->attributes=${attributesMap}")
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
XGPushManager.upsertAttributes(context, "upsertAttributes", attributesMap, object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "upsertAttributes successful")
val paraDict = mapOf("code" to 0,"type" to "attributes", "msg" to "upsertAttributes successful")
toFlutterMethod(Extras.XG_PUSH_DID_BIND_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "upsertAttributes failure")
val paraDict = mapOf("code" to p1,"type" to "attributes", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_BIND_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 删除用户属性
*/
fun delAttributes(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, List<String>>>()
val attributesList = HashSet<String>(map[Extras.ATTRIBUTES])
Log.i(TAG, "调用信鸽SDK-->delAttributes()----->attributes=${attributesList}")
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
XGPushManager.delAttributes(context, "delAttributes", attributesList, object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "delAttributes successful")
val paraDict = mapOf("code" to 0,"type" to "attributes", "msg" to "delAttributes successful")
toFlutterMethod(Extras.XG_PUSH_DID_UNBIND_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "delAttributes failure")
val paraDict = mapOf("code" to p1,"type" to "attributes", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_UNBIND_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 更新用户属性
*/
fun clearAndAppendAttributes(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, String>>()
val attributesMap = map[Extras.ATTRIBUTES] as HashMap<String, String>
Log.i(TAG, "调用信鸽SDK-->clearAndAppendAttributes()----->attributes=${attributesMap}")
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
XGPushManager.clearAndAppendAttributes(context, "clearAndAppendAttributes", attributesMap, object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "clearAndAppendAttributes successful")
val paraDict = mapOf("code" to 0,"type" to "attributes", "msg" to "clearAndAppendAttributes successful")
toFlutterMethod(Extras.XG_PUSH_DID_UPDATED_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "clearAndAppendAttributes failure")
val paraDict = mapOf("code" to p1,"type" to "attributes", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_UPDATED_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 清除全部用户属性
*/
fun clearAttributes(call: MethodCall, result: MethodChannel.Result?) {
Log.i(TAG, "调用信鸽SDK-->clearAttributes()")
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
XGPushManager.clearAttributes(context, "clearAttributes", object : XGIOperateCallback {
override fun onSuccess(p0: Any?, p1: Int) {
Log.i(TAG, "clearAttributes successful")
val paraDict = mapOf("code" to 0,"type" to "attributes", "msg" to "clearAttributes successful")
toFlutterMethod(Extras.XG_PUSH_DID_CLEAR_WITH_IDENENTIFIER, paraDict)
}
override fun onFail(p0: Any?, p1: Int, p2: String?) {
Log.i(TAG, "clearAttributes failure")
val paraDict = mapOf("code" to p1,"type" to "attributes", "msg" to p2)
toFlutterMethod(Extras.XG_PUSH_DID_CLEAR_WITH_IDENENTIFIER, paraDict)
}
})
}
/**
* 开启其他推送 XGPushManager.registerPush 前,开启第三方推送
*/
fun enableOtherPush(call: MethodCall, result: MethodChannel.Result?) {
Log.i(TAG, "调用信鸽SDK-->enableOtherPush()")
XGPushConfig.enableOtherPush(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, true)
}
/**
* 开启其他推送 XGPushManager.registerPush 前,开启第三方推送
*/
fun enableOtherPush2(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<HashMap<String, Any>>()
val enable = map["enable"] as Boolean
Log.i(TAG, "调用信鸽SDK-->enableOtherPush2()")
XGPushConfig.enableOtherPush(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, enable)
}
/**
* 获取厂商推送 token XGPushManager.registerPush 成功后
*/
fun getOtherPushToken(call: MethodCall?, result: MethodChannel.Result) {
val otherPushToken: String = (XGPushConfig.getOtherPushToken(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext))?:""
Log.i(TAG, "调用信鸽SDK-->getOtherPushToken()---otherPushToken=${otherPushToken}")
result.success(otherPushToken)
}
/**
* 获取厂商推送品牌 XGPushManager.registerPush 成功后
*/
fun getOtherPushType(call: MethodCall?, result: MethodChannel.Result) {
val otherPushType: String = (XGPushConfig.getOtherPushType(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext))?:""
Log.i(TAG, "调用信鸽SDK-->getOtherPushType()---otherPushType=${otherPushType}")
result.success(otherPushType)
}
fun enablePullUpOtherApp(call: MethodCall, result: MethodChannel.Result) {
val map = call.arguments<HashMap<String, Any>>()
val enable = map["enable"] as Boolean
Log.i(TAG, "调用信鸽SDK-->enablePullUpOtherApp()")
XGPushConfig.enablePullUpOtherApp(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, enable)
}
fun setBadgeNum(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, Int>>()
val badgeNum = map[Extras.BADGE_NUM] as Int
Log.i(TAG, "调用信鸽SDK-->setBadgeNum()-----badgeNum=${badgeNum}")
XGPushConfig.setBadgeNum(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, badgeNum)
}
fun resetBadgeNum(call: MethodCall, result: MethodChannel.Result?) {
Log.i(TAG, "调用信鸽SDK-->resetBadgeNum()")
XGPushConfig.resetBadgeNum(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext)
}
fun cancelAllNotification(call: MethodCall, result: MethodChannel.Result?) {
Log.i(TAG, "调用信鸽SDK-->cancelAllNotification()")
XGPushManager.cancelAllNotifaction(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext)
}
fun createNotificationChannel(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, Int>>()
val channelId = map[Extras.CHANNEL_ID] as String
val channelName = map[Extras.CHANNEL_NAME] as String
if (map.size == 2) {
Log.i(TAG, "调用信鸽SDK-->createNotificationChannel(${channelId}, ${channelName})")
XGPushManager.createNotificationChannel(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext,
channelId, channelName, true, true, true, null)
} else {
val enableVibration = map[Extras.ENABLE_VIBRATION] as Boolean
val enableLights = map[Extras.ENABLE_LIGHTS] as Boolean
val enableSound = map[Extras.ENABLE_SOUND] as Boolean
val soundFileName = map[Extras.SOUND_FILE_NAME] as String
val context = if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext
val soundFileId = context.getResources().getIdentifier(soundFileName, "raw", context.getPackageName())
if (soundFileId > 0) {
val soundUri = "android.resource://" + context.getPackageName() + "/" + soundFileId;
Log.i(TAG, "调用信鸽SDK-->createNotificationChannel(${channelId}, ${channelName}, ${enableVibration}, ${enableLights}, ${enableSound}, ${soundUri})")
XGPushManager.createNotificationChannel(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext,
channelId, channelName, enableVibration, enableLights, enableSound, Uri.parse(soundUri))
} else {
Log.i(TAG, "调用信鸽SDK-->createNotificationChannel(${channelId}, ${channelName}, ${enableVibration}, ${enableLights}, ${enableSound}, null)")
XGPushManager.createNotificationChannel(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext,
channelId, channelName, enableVibration, enableLights, enableSound, null)
}
}
}
/**
* 设置小米平台的APP_KEY
* 推荐有账号体系的App使用(此接口保留之前的账号,只做增加操作,一个token下最多只能有10个账号超过限制会自动顶掉之前绑定的账号)
*
* @param call String APP_KEY
* @param result 结果
*/
fun setMiPushAppKey(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, String>>()
val appKey = map[Extras.APP_KEY]
Log.i(TAG, "调用信鸽SDK-->setMiPushAppKey()-----key=${appKey}")
XGPushConfig.setMiPushAppKey(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, appKey)
}
/**
* 设置小米平台的APP_ID
*
* @param call String app_id
* @param result 结果
*/
fun setMiPushAppId(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, String>>()
val appId = map[Extras.APP_ID]
Log.i(TAG, "调用信鸽SDK-->setMiPushAppId()-----appId=${appId}")
XGPushConfig.setMiPushAppId(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, appId)
}
/**
* 设置魅族平台的的APP_KEy
*/
fun setMzPushAppKey(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, String>>()
val appKey = map[Extras.APP_KEY]
Log.i(TAG, "调用信鸽SDK-->setMzPushAppKey()-----appKey=${appKey}")
XGPushConfig.setMzPushAppKey(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, appKey)
}
/**
* 设置魅族平台的的APP_KEy
*/
fun setMzPushAppId(call: MethodCall, result: MethodChannel.Result?) {
val map = call.arguments<Map<String, String>>()
val appId = map[Extras.APP_ID]
Log.i(TAG, "调用信鸽SDK-->setMzPushAppId()-----appId=${appId}")
XGPushConfig.setMzPushAppId(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, appId)
}
/**
* 在调用腾讯移动推送 XGPushManager.registerPush前,调用以下代码:
* 在应用首次启动时弹出通知栏权限请求窗口,应用安装周期内,提示弹窗仅展示一次。需 TPNS-OPPO 依赖包版本在 1.1.5.1 及以上支持,系统 ColorOS 5.0 以上有效。
*/
private fun enableOppoNotification(call: MethodCall, result: MethodChannel.Result) {
val map = call.arguments<Map<String, Any>>()
val isNotification = map["isNotification"] as Boolean
Log.i(TAG, "调用信鸽SDK-->enableOppoNotification()-----isNotification=${isNotification}")
XGPushConfig.enableOppoNotification(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, isNotification)
}
/**
* 设置OPPO的key
*
* @param call String类型的APPKey
* @param result
*/
private fun setOppoPushAppKey(call: MethodCall, result: MethodChannel.Result) {
val map = call.arguments<Map<String, String>>()
val appKey = map[Extras.APP_KEY]
Log.i(TAG, "调用信鸽SDK-->setOppoPushAppKey()-----appKey=${appKey}")
XGPushConfig.setOppoPushAppKey(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, appKey)
}
/**
* 设置OPPO的appID
*
* @param call String 类型发AppId
* @param result
*/
private fun setOppoPushAppId(call: MethodCall, result: MethodChannel.Result) {
val map = call.arguments<Map<String, String>>()
val appId = map[Extras.APP_ID]
Log.i(TAG, "调用信鸽SDK-->setOppoPushAppId()-----appId=${appId}")
XGPushConfig.setOppoPushAppId(if (!isPluginBindingValid()) registrar.context() else mPluginBinding.applicationContext, appId)
}
/**
* 判断是否为支持FCM手机
*/
fun isFcmRom(call: MethodCall?, result: MethodChannel.Result?) { // boolean is
}
/**
* 判断是否为谷歌手机
*/
private fun isGoogleRom(call: MethodCall, result: MethodChannel.Result) {
result.success(DeviceInfoUtil.isGoogleRom())
}
/**
* 判断是否为360手机
*/
private fun is360Rom(call: MethodCall, result: MethodChannel.Result) {
Log.i(TAG, "is360Rom===" + DeviceInfoUtil.is360Rom())
result.success(DeviceInfoUtil.is360Rom())
}
/**
* 判断是否为Vivo手机
*/
private fun isVivoRom(call: MethodCall, result: MethodChannel.Result) {
Log.i(TAG, "isVivoRom===" + DeviceInfoUtil.isVivoRom())
result.success(DeviceInfoUtil.isVivoRom())
}
/**
* 判断是否为Oppo手机
*/
private fun isOppoRom(call: MethodCall, result: MethodChannel.Result) {
Log.i(TAG, "isOppoRom===" + DeviceInfoUtil.isOppoRom())
result.success(DeviceInfoUtil.isOppoRom())
}
/**
* 判断是否为魅族手机
*/
private fun isMeizuRom(call: MethodCall, result: MethodChannel.Result) {
Log.i(TAG, "isMeizuRom===" + DeviceInfoUtil.isMeizuRom())
result.success(DeviceInfoUtil.isMeizuRom())
}
/**
* 判断是否为华为手机
*/
private fun isEmuiRom(call: MethodCall, result: MethodChannel.Result) {
Log.i(TAG, "isEmuiRom===" + DeviceInfoUtil.isEmuiRom())
result.success(DeviceInfoUtil.isEmuiRom())
}
/**
* 判断是否为小米手机
*/
private fun isMiuiRom(call: MethodCall, result: MethodChannel.Result) {
Log.i(TAG, "isMiuiRom===" + DeviceInfoUtil.isMiuiRom())
result.success(DeviceInfoUtil.isMiuiRom())
}
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
val channel1 = MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "tpns_flutter_plugin")
channel1.setMethodCallHandler(XgFlutterPlugin(flutterPluginBinding, channel1))
Log.i("| XgpushpPlugin | Flutter | Android | ", "methodChannel onAttachedToEngine XgFlutterPlugin")
Log.i("| XgpushpPlugin | Flutter | Android | ", "onAttachedToEngine instance = " + instance)
XGMessageReceiver.sendHandlerMessage()
}
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
}
}
... ...
version: v2.0
stages:
- name: "stage1"
jobs:
job1:
runs-on:
pool-name: docker-on-devcloud #docker-on-devcloud、docker、local、agentless
container:
image: mirrors.tencent.com/ci/tlinux3_ci:2.1.0
needs:
jdk: "1.8.0_161"
steps:
- uses: syncLocalCode@latest
name: 同步文件到云端插件
with:
syncGitRepository: false
- uses: CodeccCheckAtomDebug@4.*
name: 腾讯代码分析
with:
beAutoLang: true
# languages: # 工程语言, 可取值:"C_CPP", "JAVA", "C_SHARP", "JS", "OC", "PYTHON", "PHP", "RUBY", "GOLANG", "SWIFT", "TYPESCRIPT", "KOTLIN", "LUA", "OTHERS"
# - "JAVA"
checkerSetType: "openScan" #openScan对应按开源治理要求配置规则集,epcScan对应按PCG EPC要求配置,normal对应自主配置规则集
toolScanType: "0" # 扫描方式。0是全量扫描,1是增量扫描。
fileCacheEnable: true # 由于IDE中代码可能没有上传Git,因此需要开启代码缓存,便于在CodeCC查看代码详情
\ No newline at end of file
... ...
## 通用 API 接口说明
#### 1. 注册推送服务
/// iOS前台收到通知不希望展示时可将withInAppAlert参数置为false
/// android接入厂商通道时,请先参考 [厂商通道接入说明](vendor.md) 配置各厂商通道参数信息后,再调用此注册方法。
```dart
void startXg(String accessId, String accessKey, {bool withInAppAlert = true});
```
#### 2. 注销推送服务
```dart
void stopXg();
```
#### 3. 设置debug模式
```dart
void setEnableDebug(bool enableDebug);
```
#### 4. 账号类型枚举
/// UNKNOWN 默认类型,当前只支持此类型的推送
/// CUSTOM 自定义
/// IDFA 广告唯一标识,iOS 专用,安卓侧默认为UNKNOWN类型
/// PHONE_NUMBER 手机号码
/// WX_OPEN_ID 微信 OPENID
/// QQ_OPEN_ID QQ OPENID
/// EMAIL 邮箱
/// SINA_WEIBO 新浪微博
/// ALIPAY 支付宝
/// TAOBAO 淘宝
/// DOUBAN 豆瓣
/// BAIDU 百度
/// JINGDONG 京东
/// IMEI 安卓手机标识,安卓专用,iOS默认为UNKNOWN类型
```dart
enum AccountType { UNKNOWN, CUSTOM, IDFA, PHONE_NUMBER, WX_OPEN_ID, QQ_OPEN_ID, EMAIL, SINA_WEIBO, ALIPAY, TAOBAO, DOUBAN, FACEBOOK, TWITTER, GOOGLE, BAIDU, JINGDONG, LINKEDIN, IMEI }
```
#### 5. 设置账号
/// account 账号标识
/// accountType 账号类型枚举
/// note 同一账号类型对应一个唯一账号,覆盖操作,多账号体系请使用不同账号类型
```dart
void setAccount(String account, AccountType accountType);
```
#### 6. 删除指定账号
/// account 账号标识
/// accountType 账号类型枚举
```dart
void deleteAccount(String account, AccountType accountType);
```
#### 7. 删除所有账号
```dart
void cleanAccounts();
```
#### 8. 追加标签
/// tags 标签字符串数组(标签字符串不允许有空格或者是tab字符)
```dart
void addTags(List<String> tags);
```
#### 9. 覆盖标签(清除所有标签再追加)
/// tags 标签字符串数组(标签字符串不允许有空格或者是tab字符)
```dart
void setTags(List<String> tags);
```
#### 10. 删除指定标签
/// tags 标签字符串数组(标签字符串不允许有空格或者是tab字符)
```dart
void deleteTags(List<String> tags);
```
#### 11. 清除所有标签
```dart
void cleanTags();
```
#### 12. 同步角标(同步角标值到TPNS,仅iOS)
/// badgeSum 角标值
```dart
void setBadge(int badgeSum);
```
#### 13. 设置应用角标(同步到TPNS成功后用于设置应用角标数,仅iOS)
/// badgeSum 角标值
```dart
void setAppBadge(int badgeSum);
```
#### 14. 获取 XgAndroidApi
/// 获取 XgAndroidApi 调用Android里的api接口
```dart
XgAndroidApi getXgAndroidApi();
```
#### 15. 新增用户属性
/// attributes 类型为 Map 字典(k, v字符串不允许有空格或者是tab字符)
```dart
void upsertAttributes(Map<String, String> attributes);
```
#### 16. 删除用户属性
/// attributes 类型为要删除属性 key 的字符串数组(字符串不允许有空格或者是tab字符)
```dart
void delAttributes(List<String> attributes);
```
#### 17. 更新用户属性
/// attributes 类型为 Map 字典(k, v字符串不允许有空格或者是tab字符)
```dart
void clearAndAppendAttributes(Map<String, String> attributes);
```
#### 18. 清除全部用户属性
```dart
void clearAttributes();
```
## 回调接口说明
#### 1 静默消息(iOS)/透传消息(Android)回调
```dart
_onReceiveMessage 数据类型 Map<String, Object> para: iOS/Android返回不同的消息体,以双端返回kv为准
```
#### 2 收到通知消息回调
```dart
_onReceiveNotificationResponse 数据类型 Map<String, Object> para: iOS/Android返回不同的消息体,以双端返回kv为准
```
#### 3 通知点击回调
```dart
_xgPushClickAction 数据类型 Map<String, Object> para: iOS/Android返回不同的消息体,以双端返回kv为准
```
#### 4 注册成功回调
```dart
_onRegisteredDone 数据类型 String para: 注册成功信息
```
#### 5 注册失败回调
```dart
_onRegisteredDeviceToken 数据类型 String para: xgToken,注册失败如果有xgToken则返回
```
#### 6 注销完成的回调
```dart
_unRegistered 数据类型 String para: 注销成功或者失败信息
```
#### 7 绑定账号/标签/用户属性回调
**说明**V1.2.8开始返回类型由String->Map,新增code及type标识!
```dart
_xgPushDidBindWithIdentifier 数据类型 Map<String, Object> para:
key:
code:int类型,操作结果,0代表成功
type: String类型,操作类型,取值为account/tag/attributes
msg: String类型,提示信息
```
#### 8 解绑账号/标签/用户属性回调
**说明**V1.2.8开始返回类型由String->Map,新增code及type标识!
```dart
_xgPushDidUnbindWithIdentifier 数据类型 Map<String, Object> para:
key:
code:int类型,操作结果,0代表成功
type: String类型,操作类型,取值为account/tag/attributes
msg: String类型,提示信息
```
#### 9 更新标签/用户属性回调
**说明**V1.2.8开始返回类型由String->Map,新增code及type标识!
```dart
_xgPushDidUpdatedBindedIdentifier 数据类型 Map<String, Object> para:
key:
code:int类型,操作结果,0代表成功
type: String类型,操作类型,取值为tag/attributes
msg: String类型,提示信息
```
#### 10 清除所有账号/标签/用户属性回调
**说明**V1.2.8开始返回类型由String->Map,新增code及type标识!
```dart
_xgPushDidClearAllIdentifiers 数据类型 Map<String, Object> para:
key:
code:int类型,操作结果,0代表成功
type: String类型,操作类型,取值为account/tag/attributes
msg: String类型,提示信息
```
## 安卓端 XgAndroidApi 接口说明
> 说明:XgAndroidApi 为针对安卓独立接口的内部再次封装,可以通过 `XgFlutterPlugin.xgApi` 直接访问,例如:
> ```dart
> // 调用示例:开启厂商其他推送接口
> XgFlutterPlugin.xgApi.enableOtherPush()
> ```
#### 1. 开启其他推送
```dart
enableOtherPush();
```
#### 2. 设置小米推送的APP_ID
```dart
setMiPushAppId({String appId});
```
#### 3. 设置小米推送的APP_KEY
```dart
setMiPushAppKey({String appKey});
```
#### 4. 设置魅族推送所需appID
```dart
setMzPushAppId({String appId});
```
#### 5. 设置魅族推送所需appKey
```dart
setMzPushAppKey({String appKey});
```
#### 6. 开启Oppo通知
```dart
enableOppoNotification();
```
#### 7. 设置Oppo推送ID
```dart
setOppoPushAppId({String appId});
```
#### 8. 设置Oppo推送Key
```dart
setOppoPushAppKey({String appKey});
```
#### 9. 清空当前应用在通知栏的通知
```dart
cancelAllNotification();
```
#### 10. 配置是否关闭拉起其他 App;填入 false 为不拉起,默认为 true
```dart
enablePullUpOtherApp({bool enable})
```
#### 11. 安卓角标设置,支持华为、OPPO、vivo,其中 OPPO 需另外向厂商申请角标展示权限
```dart
setBadgeNum({int badgeNum})
```
#### 12. 设置手机应用角标归0,支持华为、OPPO、vivo,其中 OPPO 需另外向厂商申请角标展示权限
```dart
resetBadgeNum()
```
... ...
## 厂商通道接入说明
>? TPNS 已封装各厂商推送通道 SDK,请参考下文引入对应厂商推送 SDK 依赖。
> 如您的工程同时接入其他离线推送产品遇到依赖冲突,可对对应冲突依赖筛选使用其一。
### 1. 华为通道接入,可参考移动推送 TPNS [华为通道接入](https://cloud.tencent.com/document/product/548/45909)
#### 1.1 工程配置:
##### 1.1.1 在安卓项目级目录 build.gradle 文件,【buildscript】>【 repositories & dependencies】下分别添加华为仓库地址和 HMS gradle 插件依赖:
```
buildscript {
repositories {
google()
jcenter()
maven {url 'http://developer.huawei.com/repo/'} // 华为 maven 仓库地址
}
dependencies {
// 其他classpath配置
classpath 'com.huawei.agconnect:agcp:1.9.1.301' // 华为推送 gradle 插件依赖
}
}
```
##### 1.1.2 在安卓项目级目录 build.gradle 文件,【allprojects】>【repositories】下添加华为依赖仓库地址:
```
allprojects {
repositories {
google()
jcenter()
maven {url 'http://developer.huawei.com/repo/'} // 华为 maven 仓库地址
}
}
```
##### 1.1.3. 将从华为推送平台获取的应用配置文件 agconnect-services.json 拷贝到 app 模块目录下。
![](https://main.qcloudimg.com/raw/338c87faaeb388f648835f17aeddc490.png)
##### 1.1.4. 在 app 模块下 build.gradle 文件添加以下配置:
```
// app 其他 gradle 插件
apply plugin: 'com.huawei.agconnect' // HMS SDK gradle 插件
android {
// app 配置内容
}
```
##### 1.1.5. 在 app 模块下 build.gradle 文件内导入华为推送相关依赖:
```
dependencies {
// ... 程序其他依赖
// 华为推送 [VERSION] 为当前最新 SDK 版本号,版本号可在 SDK 下载页查看
// TPNS Android SDK 自 1.2.1.3 版本起正式支持华为推送 V5 版本,请使用 1.2.1.3 及以上版本的 TPNS 华为依赖以避免集成冲突问题。
implementation 'com.tencent.tpns:huawei:[VERSION]-release'
// HMS Core Push 模块依赖包
implementation 'com.huawei.hms:push:6.12.0.300'
}
```
#### 1.2 开启华为推送
在调用 `regPush()`注册信鸽推送之前调用启用三方通道接口以开启厂商推送:
```dart
XgFlutterPlugin.xgApi.enableOtherPush();
XgFlutterPlugin.xgApi.regPush();
```
#### 1.3 代码混淆
```
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
```
### 2. 小米通道接入,可参考移动推送 TPNS [小米通道接入](https://cloud.tencent.com/document/product/548/36654)
#### 2.1 引入小米推送的依赖
```
implementation 'com.tencent.tpns:xiaomi:[VERSION]-release' // 小米推送 [VERSION] 为当前SDK版本号,版本号可在SDK下载页查看
```
#### 2.2 开启小米推送
```dart
// 设置小米 AppID 和 AppKey。
XgFlutterPlugin.xgApi.setMiPushAppId(appId:"APP_ID");
XgFlutterPlugin.xgApi.setMiPushAppKey(appKey: "APPKEY");
// 打开第三方推送并注册
XgFlutterPlugin.xgApi.enableOtherPush();
XgFlutterPlugin.xgApi.regPush();
```
#### 2.3 代码混淆
```
-keep class com.xiaomi.**{*;}
-keep public class * extends com.xiaomi.mipush.sdk.PushMessageReceiver
```
### 3. 魅族通道接入,可参考移动推送 TPNS [魅族通道接入](https://cloud.tencent.com/document/product/548/36655)
#### 3.1 引入魅族推送的依赖
```
implementation 'com.tencent.tpns:meizu:[VERSION]-release' // 魅族推送 [VERSION] 为当前SDK版本号,版本号可在SDK下载页查看
```
#### 3.2 开启魅族推送
```dart
/// 设置魅族 AppID 和 AppKey
XgFlutterPlugin.xgApi.setMzPushAppId(appId:"APP_ID");
XgFlutterPlugin.xgApi.setMzPushAppKey(appKey: "APPKEY");
/// 打开第三方推送
XgFlutterPlugin.xgApi.enableOtherPush();
XgFlutterPlugin.xgApi.regPush();
```
#### 3.3 代码混淆
```
-dontwarn com.meizu.cloud.pushsdk.**
-keep class com.meizu.cloud.pushsdk.**{*;}
```
### 4. vivo通道接入,可参考移动推送 TPNS [vivo通道接入](https://cloud.tencent.com/document/product/548/36657)
#### 4.1 在 App 模块下的 build.gradle 文件内
```
android: {
defaultConfig {
manifestPlaceholders = [
....
VIVO_APPID: "VIVO的APPID"
VIVO_APPKEY:"VIVO的APP_KEy",
.....
]
}
}
```
```
/// 引入 vivo 推送的依赖
implementation 'com.tencent.tpns:vivo:[VERSION]-release' // vivo 推送 [VERSION] 为当前SDK版本号,版本号可在SDK下载页查看
```
#### 4.2 启用 vivo 推送
```dart
/// 打开第三方推送
XgFlutterPlugin.xgApi.enableOtherPush();
XgFlutterPlugin.xgApi.regPush();
```
#### 4.3代码混淆
```
-dontwarn com.vivo.push.**
-keep class com.vivo.push.**{*; }
-keep class com.vivo.vms.**{*; }
-keep class com.tencent.android.vivopush.VivoPushMessageReceiver{*;}
```
### 5. OPPO通道接入,可参考移动推送 TPNS [OPPO通道接入](https://cloud.tencent.com/document/product/548/36658)
#### 5.1 引入 OPPO 推送的依赖
```
implementation 'com.tencent.tpns:oppo:[VERSION]-release' // OPPO 推送 [VERSION] 为当前SDK版本号,版本号可在SDK下载页查看
```
#### 5.2 开启推送
```dart
/// 设置OPPO AppKey 和 AppSecret
XgFlutterPlugin.xgApi.setOppoPushAppId(appId:"Oppo的AppKey");
XgFlutterPlugin.xgApi.setOppoPushAppKey(appKey: "Oppo的AppSecret");
/// 打开第三方推送
XgFlutterPlugin.xgApi.enableOtherPush();
XgFlutterPlugin.xgApi.regPush();
```
#### 5.3 代码混淆
```
-keep public class * extends android.app.Service
-keep class com.heytap.mcssdk.** {*;}
-keep class com.heytap.msp.push.** { *;}
```
### 6. FCM通道接入,可参考移动推送 TPNS [FCM通道接入](https://cloud.tencent.com/document/product/548/36656)
#### 6.1 添加 google-services.json 文件,请参考[FCM通道配置文件](https://cloud.tencent.com/document/product/548/36656#.E9.85.8D.E7.BD.AE.E5.86.85.E5.AE.B9)。
#### 6.2 在项目级的 build.gradle 文件中的 dependencies 节点中添加下面代码,集成谷歌 service
```
classpath 'com.google.gms:google-services:4.2.0'
```
#### 6.3 在应用级的 build.gradle 文件中,添加依赖:
```
implementation 'com.tencent.tpns:fcm:[VERSION]-release' // fcm 推送 [VERSION] 为当前SDK版本号,版本号可在SDK下载页查看
implementation 'com.google.firebase:firebase-messaging:17.6.0'
```
  并在应用级的 build.gradle 文件末尾新增:
```
apply plugin: 'com.google.gms.google-services'
```
#### 6.4 启用 FCM 推送
```dart
/// 打开第三方推送
XgFlutterPlugin.xgApi.enableOtherPush();
XgFlutterPlugin.xgApi.regPush();
```
### 7. 荣耀通道接入,可参考移动推送 TPNS [荣耀通道接入](https://cloud.tencent.com/document/product/548/74465)
#### 7.1 在 App 模块下的 build.gradle 文件内
```
android: {
defaultConfig {
manifestPlaceholders = [
....
HONOR_APPID : "xxxx"
.....
]
}
}
```
```
/// 引入 vivo 推送的依赖
implementation 'com.tencent.tpns:honor:[VERSION]-release' // 荣耀 推送 [VERSION] 为当前SDK版本号,版本号可在SDK下载页查看
```
#### 7.2 启用 荣耀 推送
```dart
/// 打开第三方推送
XgFlutterPlugin.xgApi.enableOtherPush();
XgFlutterPlugin.xgApi.regPush();
```
#### 7.3代码混淆
```
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.hihonor.push.framework.aidl.**{*;}
-keep class com.hihonor.push.sdk.**{*;}
```
## 厂商通道注册失败排查指南
如您的应用接入了厂商通道,但在应用运行日志中观察到如下类似日志:
```
[OtherPushClient] handleUpdateToken other push token is : other push type: huawei
```
表示您的应用注册该厂商通道失败。您可以通过获取厂商通道注册失败的返回码来进行问题定位和排查,详情参考 [厂商通道注册失败排查指南](https://cloud.tencent.com/document/product/548/45659)。
... ...
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
... ...
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
version:
revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
base_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
- platform: android
create_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
base_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
- platform: ios
create_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
base_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
- platform: linux
create_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
base_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
- platform: macos
create_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
base_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
- platform: web
create_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
base_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
- platform: windows
create_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
base_revision: bcea432bce54a83306b3c00a7ad0ed98f777348d
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'
... ...
# tpns_flutter_plugin
## 安装
在工程 pubspec.yaml 中加入 dependencies
```
dependencies:
tpns_flutter_plugin:
git:
url: https://github.com/TencentCloud/TPNS-Flutter-Plugin
ref: V1.3.4
```
## 使用
- 执行flutter pub get安装好插件后进入iOS文件目录(cd ios)执行:pod install安装依赖库
- 在 xcode8 之后需要点开推送选项: TARGETS -> Capabilities -> Push Notification 设为 on 状态
```dart
import 'package:tpns_flutter_plugin/tpns_flutter_plugin.dart';
```
说明(接口使用参考/tpns_flutter_plugin/example/lib/main.dart和/tpns_flutter_plugin/example/lib/ios/homeTest.dart文件)
... ...
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
... ...
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks
... ...
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.tencent.example"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
manifestPlaceholders = [
XG_ACCESS_ID : "1500004343",
XG_ACCESS_KEY : "ANCVHDQ0DO3E",
]
}
buildTypes {
release {
// 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
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
... ...
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tencent.example">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
... ...
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tencent.example">
<application
android:label="example"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<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>
... ...
package com.tencent.example
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}
... ...
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
... ...
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
... ...
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
... ...
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>
... ...
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tencent.example">
<!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
... ...
buildscript {
ext.kotlin_version = '1.6.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
... ...
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
... ...
#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-7.4-all.zip
... ...
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
... ...
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
... ...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict>
</plist>
... ...
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
... ...
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
... ...
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
... ...
PODS:
- Flutter (1.0.0)
- TPNS-iOS (1.4.0.5)
- tpns_flutter_plugin (1.3.4):
- Flutter
- TPNS-iOS (= 1.4.0.5)
DEPENDENCIES:
- Flutter (from `Flutter`)
- tpns_flutter_plugin (from `.symlinks/plugins/tpns_flutter_plugin/ios`)
SPEC REPOS:
trunk:
- TPNS-iOS
EXTERNAL SOURCES:
Flutter:
:path: Flutter
tpns_flutter_plugin:
:path: ".symlinks/plugins/tpns_flutter_plugin/ios"
SPEC CHECKSUMS:
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
TPNS-iOS: 757b0439d967beb8c5d6be6a8e9ad23e11d1e36c
tpns_flutter_plugin: 54270cae525b4a255f9140b9b7f745724601646a
PODFILE CHECKSUM: c4c93c5f6502fe2754f48404d3594bf779584011
COCOAPODS: 1.16.2
... ...
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
2DDE509E727BD43954A7C76A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46E5BF2F00BA5FE35FD91D82 /* Pods_Runner.framework */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
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>"; };
1B1E0FCD23C4ADF20072DC3A /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
46E5BF2F00BA5FE35FD91D82 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
60F13BDE7DC0855DBCFC12F2 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9E01C11A453962BD60DABB7C /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
EEAD574267970C6F5031E634 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
2DDE509E727BD43954A7C76A /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
0FD4F9FC8439C49779381BD0 /* Frameworks */ = {
isa = PBXGroup;
children = (
46E5BF2F00BA5FE35FD91D82 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
232F5FF2451FA860FA3BC0F4 /* Pods */ = {
isa = PBXGroup;
children = (
60F13BDE7DC0855DBCFC12F2 /* Pods-Runner.debug.xcconfig */,
EEAD574267970C6F5031E634 /* Pods-Runner.release.xcconfig */,
9E01C11A453962BD60DABB7C /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
232F5FF2451FA860FA3BC0F4 /* Pods */,
0FD4F9FC8439C49779381BD0 /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
1B1E0FCD23C4ADF20072DC3A /* Runner.entitlements */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
2D231361BD2B90879FC56479 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
CA9D2F060B4EAED2F2EA8812 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = 299MFJ63GP;
LastSwiftMigration = 1100;
ProvisioningStyle = Manual;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
2D231361BD2B90879FC56479 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
CA9D2F060B4EAED2F2EA8812 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh",
"${PODS_CONFIGURATION_BUILD_DIR}/TPNS-iOS/TPNS-iOS-Privacy.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/TPNS-iOS-Privacy.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 299MFJ63GP;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
NEW_SETTING = "";
PRODUCT_BUNDLE_IDENTIFIER = com.tencent.tpns;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = com.tencent.tpns_dev;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 299MFJ63GP;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
NEW_SETTING = "";
PRODUCT_BUNDLE_IDENTIFIER = com.tencent.tpns;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = com.tencent.tpns_dev;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 299MFJ63GP;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
NEW_SETTING = "";
PRODUCT_BUNDLE_IDENTIFIER = com.tencent.tpns;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = com.tencent.tpns_dev;
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
... ...
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
... ...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
... ...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
... ...
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
... ...
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
... ...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
... ...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>
... ...
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
... ...
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "xg-120.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "xg-180.png",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
},
{
"idiom" : "ios-marketing",
"size" : "1024x1024",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
... ...
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
... ...
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
... ...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
... ...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>tpns_flutter_demo</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
... ...
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>
... ...
library flutter_tableview;
import 'package:flutter/material.dart';
typedef int RowCountAtSection(int section);
typedef Widget ListViewFatherWidgetBuilder(
BuildContext context, Widget canScrollWidget);
typedef Widget SectionHeaderBuilder(BuildContext context, int section);
typedef Widget CellBuilder(BuildContext context, int section, int row);
typedef double CellHeight(BuildContext context, int section, int row);
typedef double SectionHeaderHeight(BuildContext context, int section);
const String ErorrFlagBegin =
'\n\n\n====================FlutterTableView Error========================\n\n\n\n';
const String ErorrFlagEnd =
'\n\n\n\n\n==================================================================\n\n\n\n.';
class FlutterTableView extends StatefulWidget {
FlutterTableView({
required this.sectionCount,
required this.rowCountAtSection,
required this.sectionHeaderBuilder,
required this.cellBuilder,
required this.sectionHeaderHeight,
required this.cellHeight,
this.listViewFatherWidgetBuilder,
this.controller,
this.physics,
this.shrinkWrap = false,
this.padding = const EdgeInsets.all(0.0),
this.cacheExtent = 50.0,
this.backgroundColor = Colors.transparent,
}) : assert(
(sectionCount != null && sectionCount > 0),
'$ErorrFlagBegin sectionCount must > 0 and could not be null. $ErorrFlagEnd',
),
assert(
(rowCountAtSection != null),
'$ErorrFlagBegin function rowCountAtSection could not be null. $ErorrFlagEnd',
),
assert(
(sectionHeaderBuilder != null),
'$ErorrFlagBegin function sectionHeaderBuilder could not be null. $ErorrFlagEnd',
),
assert(
(cellBuilder != null),
'$ErorrFlagBegin function cellBuilder could not be null. $ErorrFlagEnd',
),
assert(
(sectionHeaderHeight != null),
'$ErorrFlagBegin function sectionHeaderHeight could not be null. $ErorrFlagEnd',
),
assert(
(cellHeight != null),
'$ErorrFlagBegin function cellHeight could not be null. $ErorrFlagEnd',
);
@override
_FlutterTableViewState createState() {
return _FlutterTableViewState();
}
/// How many section.
final int sectionCount;
/// How many item in each section.
final RowCountAtSection rowCountAtSection;
/// You can through sectionHeaderBuilder create section header widget.
/// Each section has at most one headWidget.
/// In a special section, if you don't need section header widget, you can return null.
final SectionHeaderBuilder sectionHeaderBuilder;
/// You can through cellBuilder create items.
final CellBuilder cellBuilder;
/// return each item widget height.
final CellHeight cellHeight;
/// return each section header widget height.
final SectionHeaderHeight sectionHeaderHeight;
/// You can wrap a widget for listView
final ListViewFatherWidgetBuilder? listViewFatherWidgetBuilder;
/// see ScrollView controller
final ScrollController? controller;
/// see ScrollView physics
final ScrollPhysics? physics;
/// see ScrollView shrinkWrap
final bool shrinkWrap;
final EdgeInsetsGeometry padding;
/// see ScrollView cacheExtent
final double cacheExtent;
final Color backgroundColor;
}
class _FlutterTableViewState extends State<FlutterTableView> {
////////////////////////////////////////////////////////////////////
// variables
////////////////////////////////////////////////////////////////////
SectionHeaderModel? currentHeaderModel;
int totalItemCount = 0;
List<SectionHeaderModel> sectionHeaderList = [];
List<int> sectionTotalWidgetCountList = [];
ScrollController? scrollController;
ListView? listView;
bool insideSetStateFlag = false;
////////////////////////////////////////////////////////////////////
// init function
////////////////////////////////////////////////////////////////////
void _initBaseData() {
this.totalItemCount = 0;
this.sectionHeaderList.clear();
this.sectionTotalWidgetCountList.clear();
double offsetY = 0;
for (int section = 0; section < widget.sectionCount; section++) {
int rowCount = widget.rowCountAtSection(section);
Widget sectionHeader = widget.sectionHeaderBuilder(context, section);
double sectionHeight;
if (sectionHeader != null) {
sectionHeight = this.widget.sectionHeaderHeight(context, section);
} else {
sectionHeight = 0;
}
double sectionHeaderY = offsetY;
offsetY += sectionHeight;
int sectionWidgetCount = sectionHeader == null ? rowCount : rowCount + 1;
sectionTotalWidgetCountList.add(sectionWidgetCount);
this.totalItemCount += sectionWidgetCount;
for (int row = 0; row < rowCount; row++) {
offsetY += this.widget.cellHeight(context, section, row);
}
SectionHeaderModel model = SectionHeaderModel(
y: sectionHeaderY,
sectionMaxY: offsetY,
height: sectionHeight,
section: section,
headerWidget: sectionHeader,
);
sectionHeaderList.add(model);
}
}
void _initScrollController() {
this.scrollController = this.widget.controller;
if (this.scrollController == null) {
this.scrollController = ScrollController();
}
this.scrollController?.addListener(() {
double offsetY = this.scrollController?.offset ?? 0;
if (offsetY <= 0.0) {
this._updateCurrentSectionHeaderModel(SectionHeaderModel(), 0);
} else {
int section = 0;
for (int i = 0; i < this.sectionHeaderList.length; i++) {
SectionHeaderModel model = this.sectionHeaderList[i];
if (offsetY >= (model?.y ?? 0) && offsetY <= (model?.sectionMaxY ?? 0)) {
section = i;
break;
}
}
SectionHeaderModel model = this.sectionHeaderList[section];
double delta = (model.sectionMaxY ?? 0) - (this.scrollController?.offset ?? 0);
double topOffset;
if (delta >= (model?.height ?? 0)) {
topOffset = 0.0;
} else {
topOffset = delta - (model?.height ?? 0);
}
this._updateCurrentSectionHeaderModel(model, topOffset);
}
});
}
////////////////////////////////////////////////////////////////////
// create listView
////////////////////////////////////////////////////////////////////
void _createListView() {
if(this.insideSetStateFlag == false) {
this._initBaseData();
}
this.insideSetStateFlag = false;
this.listView = ListView.builder(
controller: this.scrollController,
physics: this.widget.physics ?? AlwaysScrollableScrollPhysics(),
shrinkWrap: this.widget.shrinkWrap,
cacheExtent: this.widget.cacheExtent,
itemBuilder: (BuildContext context, int index) {
Widget? itemWidget;
RowSectionModel model = this._getRowSectionModel(index) ?? RowSectionModel(section: 0, row: 0, haveHeaderWidget: false);
double height;
if (model.row == 0 && (model.haveHeaderWidget ?? false)) {
itemWidget = this.sectionHeaderList[model.section ?? 0].headerWidget;
height = this.widget.sectionHeaderHeight(context, model.section ?? 0);
} else {
int row = (model.haveHeaderWidget ?? false) == false ? (model.row ?? 0) : (model.row ?? 0) - 1;
itemWidget = this.widget.cellBuilder(context, model.section ?? 0, row);
height = this.widget.cellHeight(context, model.section ?? 0, row);
}
return ConstrainedBox(
constraints: BoxConstraints(
minHeight: height,
maxHeight: height,
),
child: itemWidget,
);
},
itemCount: this.totalItemCount,
);
}
////////////////////////////////////////////////////////////////////
// tool function
////////////////////////////////////////////////////////////////////
RowSectionModel? _getRowSectionModel(int index) {
int passCount = 0;
for (int section = 0;
section < this.sectionTotalWidgetCountList.length;
section++) {
int currentSectionWidgetCount = this.sectionTotalWidgetCountList[section];
if (index >= passCount && index < passCount + currentSectionWidgetCount) {
int row = index - passCount;
bool haveSectionHeaderWidget =
this.sectionHeaderList[section].headerWidget != null;
RowSectionModel model = RowSectionModel(
section: section,
row: row,
haveHeaderWidget: haveSectionHeaderWidget,
);
return model;
}
passCount += currentSectionWidgetCount;
}
return null;
}
void _updateCurrentSectionHeaderModel(
SectionHeaderModel model, double topOffset) {
bool needSetState = false;
if (model == null) {
if (this.currentHeaderModel != null) {
this.currentHeaderModel = null;
needSetState = true;
}
} else if (this.currentHeaderModel == null) {
this.currentHeaderModel = model;
this.currentHeaderModel?.topOffset = topOffset;
needSetState = true;
} else {
if (model != this.currentHeaderModel) {
this.currentHeaderModel = model;
needSetState = true;
} else if (model.topOffset != topOffset) {
needSetState = true;
}
this.currentHeaderModel?.topOffset = topOffset;
}
if (needSetState == true) {
this.insideSetStateFlag = true;
setState(() {});
}
}
////////////////////////////////////////////////////////////////////
// life cycle
////////////////////////////////////////////////////////////////////
@override
void dispose() {
super.dispose();
if (this.widget.controller == null) {
this.scrollController?.dispose();
}
}
@override
void initState() {
this._initScrollController();
super.initState();
}
@override
Widget build(BuildContext context) {
this._createListView();
Widget? listViewFatherWidget;
if (this.widget.listViewFatherWidgetBuilder != null) {
listViewFatherWidget =
this.widget.listViewFatherWidgetBuilder!(context, this.listView ?? ListView());
}
Widget? listViewWidget = listViewFatherWidget ?? this.listView;
if (this.currentHeaderModel != null &&
this.currentHeaderModel?.headerWidget != null) {
return Container(
padding: this.widget.padding,
color: widget.backgroundColor,
child: Stack(
children: <Widget>[
Container(
color: Colors.transparent,
child: listViewWidget,
),
Positioned(
top: this.currentHeaderModel?.topOffset,
left: 0.0,
right: 0.0,
height: this.currentHeaderModel?.height,
child: Container(
color: Colors.white,
child: this.currentHeaderModel?.headerWidget,
),
),
],
),
);
}
return Container(
padding: this.widget.padding,
color: this.widget.backgroundColor,
child: Stack(
children: [
Container(
color: Colors.transparent,
child: listViewWidget,
),
],
),
);
}
}
////////////////////////////////////////////////////////////////////
// model class
////////////////////////////////////////////////////////////////////
class RowSectionModel {
RowSectionModel({
this.section,
this.row,
this.haveHeaderWidget,
});
final int? section;
final int? row;
final bool? haveHeaderWidget;
}
class SectionHeaderModel {
SectionHeaderModel({
this.y,
this.sectionMaxY,
this.height,
this.section,
this.headerWidget,
});
final double? y;
final double? sectionMaxY;
final double? height;
final int? section;
final Widget? headerWidget;
double? topOffset;
}
... ...
import 'package:flutter/material.dart';
import 'flutter_tableview.dart';
import 'package:tpns_flutter_plugin/tpns_flutter_plugin.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
List<String> sectionTitleList = ['关于账号接口', '关于标签接口', '关于用户属性接口', '关于应用接口'];
List<List<String>> sectionList = [
['设置账号', '解绑账号', '清除全部账号'],
['绑定一个标签', '解绑一个标签', '更新标签', '清除全部标签'],
['新增用户属性', '删除用户属性', '更新用户属性', '清除全部用户属性'],
['注册推送服务', '注销推送服务', '设备推送标识', '上报当前角标数', 'SDK 版本']
];
class HomeTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('TPNS Demo'),
),
body: HomeTestBody(),
);
}
}
class HomeTestBody extends StatefulWidget {
@override
HomeTestBodyState createState() => HomeTestBodyState();
}
class HomeTestBodyState extends State<HomeTestBody> {
final XgFlutterPlugin tpush = new XgFlutterPlugin();
String inputStr = "flutter";
// Get row count.
int _rowCountAtSection(int section) {
if (section < sectionList.length) {
return sectionList[section].length;
} else {
return 0;
}
}
String _titleOfSection(int section) {
if (section < sectionTitleList.length) {
return sectionTitleList[section];
} else {
return 'null';
}
}
String _titleOfRow(int section, int row) {
if (section < sectionList.length) {
List<String> tmpList = sectionList[section];
if (row < tmpList.length) {
return tmpList[row];
} else {
return 'null';
}
} else {
return 'null';
}
}
void _showAlert(int section, int row) {
String title = sectionList[section][row];
Alert(
context: context,
title: title,
content: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
labelText: '请输入',
),
onChanged: (text) {
inputStr = text;
},
),
],
),
buttons: [
DialogButton(
onPressed: () {
Navigator.pop(context);
_doAction(section, row);
},
child: Text(
"确认",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
]).show();
}
//信鸽api接口调用函数
void _doAction(int section, int row) {
if (section == 0) {
if (row == 0) {
tpush.setAccount(inputStr, AccountType.UNKNOWN);
} else if (row == 1) {
tpush.deleteAccount(inputStr, AccountType.UNKNOWN);
} else if (row == 2) {
tpush.cleanAccounts();
}
} else if (section == 1) {
if (row == 0) {
tpush.addTags([inputStr]);
} else if (row == 1) {
tpush.deleteTags([inputStr]);
} else if (row == 2) {
tpush.setTags([inputStr]);
} else if (row == 3) {
tpush.cleanTags();
}
} else if (section == 2) {
if (row == 0) {
Map<String, String> attributes = {'nickname': "testAttribute"};
tpush.upsertAttributes(attributes);
} else if (row == 1) {
List<String> delAttr = ['nickname'];
tpush.delAttributes(delAttr);
} else if (row == 2) {
Map<String, String> attributes = {'nickname': "testAttribute2"};
tpush.clearAndAppendAttributes(attributes);
} else if (row == 3) {
tpush.clearAttributes();
}
} else if (section == 3) {
if (row == 0) {
tpush.startXg("1600007893", "IX4BGYYG8L4L");
} else if (row == 1) {
tpush.stopXg();
} else if (row == 2) {
getXgToken();
} else if (row == 3) {
tpush.setBadge(int.parse(inputStr));
} else if (row == 4) {
getXgSdkVersion();
}
}
}
// Section header widget builder.
Widget _sectionHeaderBuilder(BuildContext context, int section) {
return InkWell(
onTap: () {},
child: Container(
alignment: Alignment.centerLeft,
padding: EdgeInsets.only(left: 16.0),
color: Color.fromRGBO(220, 220, 220, 1),
height: 100,
child: Text(_titleOfSection(section)),
),
);
}
// cell item widget builder.
Widget _cellBuilder(BuildContext context, int section, int row) {
return InkWell(
onTap: () {
if ((section == 0 && row == 2) ||
(section == 1 && row == 3) ||
(section == 2) ||
(section == 3 && row != 3)) {
_doAction(section, row);
} else {
_showAlert(section, row);
}
},
child: Container(
padding: EdgeInsets.only(left: 16.0),
alignment: Alignment.centerLeft,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Color.fromRGBO(240, 240, 240, 1),
))),
height: 50.0,
child: Text(_titleOfRow(section, row)),
),
);
}
// Each section header height;
double _sectionHeaderHeight(BuildContext context, int section) {
return 50.0;
}
// Each cell item widget height.
double _cellHeight(BuildContext context, int section, int row) {
return 50.0;
}
Future<void> getXgSdkVersion() async {
try {
String? sdkVersion = await XgFlutterPlugin.xgSdkVersion;
print('xgSdkVersion: $sdkVersion');
Alert(context: context, title: sdkVersion, desc: "", buttons: [
DialogButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(
"确认",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
]).show();
} catch (e) {
print(e.toString());
}
}
Future<void> getXgToken() async {
try {
String? xgToken = await XgFlutterPlugin.xgToken;
print('xgtoken: $xgToken');
Alert(context: context, title: xgToken, desc: "", buttons: [
DialogButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(
"确认",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
]).show();
} catch (e) {
print(e.toString());
}
}
@override
Widget build(BuildContext context) {
return Container(
//FlutterTableView
child: FlutterTableView(
sectionCount: sectionList.length,
rowCountAtSection: _rowCountAtSection,
sectionHeaderBuilder: _sectionHeaderBuilder,
cellBuilder: _cellBuilder,
sectionHeaderHeight: _sectionHeaderHeight,
cellHeight: _cellHeight,
),
);
}
}
... ...
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:rflutter_alert/rflutter_alert.dart';
import 'ios/homeTest.dart';
import 'package:tpns_flutter_plugin/tpns_flutter_plugin.dart';
import 'dart:io';
void main() => runApp(new MaterialApp(
home: new MyApp(),
debugShowCheckedModeBanner: false,
));
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final XgFlutterPlugin tpush = new XgFlutterPlugin();
@override
void initState() {
super.initState();
initPlatformState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
/// 开启DEBUG
tpush.setEnableDebug(true);
/// 添加回调事件
tpush.addEventHandler(
/// TPNS注册失败会走此回调
onRegisteredDeviceToken: (String msg) async {
print("flutter onRegisteredDeviceToken: $msg");
},
/// TPNS注册成功会走此回调
onRegisteredDone: (String msg) async {
print("flutter onRegisteredDone: $msg");
_showAlert("注册成功");
},
unRegistered: (String msg) async {
print("flutter unRegistered: $msg");
_showAlert(msg);
},
onReceiveNotificationResponse: (Map<String, dynamic> msg) async {
print("flutter onReceiveNotificationResponse $msg");
},
onReceiveMessage: (Map<String, dynamic> msg) async {
print("flutter onReceiveMessage $msg");
},
xgPushNetworkConnected: (String msg) async {
print("flutter xgPushNetworkConnected: $msg");
/// 建议在此同步角标到TPNS后台
/// tpush.setBadge(0);
/// 同步到TPNS后台的同时,更新本地应用角标数
/// tpush.setAppBadge(0);
},
xgPushDidSetBadge: (String msg) async {
print("flutter xgPushDidSetBadge: $msg");
_showAlert(msg);
},
/// V1.2.8开始返回类型由String->Map,新增code及type标识!
xgPushDidBindWithIdentifier: (Map<String, dynamic> result) async {
print("flutter xgPushDidBindWithIdentifier: $result");
_showAlert(result["msg"]);
},
/// V1.2.8开始返回类型由String->Map,新增code及type标识!
xgPushDidUnbindWithIdentifier: (Map<String, dynamic> result) async {
print("flutter xgPushDidUnbindWithIdentifier: $result");
_showAlert(result["msg"]);
},
/// V1.2.8开始返回类型由String->Map,新增code及type标识!
xgPushDidUpdatedBindedIdentifier: (Map<String, dynamic> result) async {
print("flutter xgPushDidUpdatedBindedIdentifier: $result");
_showAlert(result["msg"]);
},
/// V1.2.8开始返回类型由String->Map,新增code及type标识!
xgPushDidClearAllIdentifiers: (Map<String, dynamic> result) async {
print("flutter xgPushDidClearAllIdentifiers: $result");
_showAlert(result["msg"]);
},
xgPushClickAction: (Map<String, dynamic> msg) async {
print("flutter xgPushClickAction $msg");
_showAlert("clickResponse");
},
);
/// 如果您的应用非广州集群则需要在startXG之前调用此函数
/// 香港:tpns.hk.tencent.com
/// 新加坡:tpns.sgp.tencent.com
/// 上海:tpns.sh.tencent.com
// tpush.configureClusterDomainName("tpns.hk.tencent.com");
/// 启动TPNS服务
/// 注意:为了不影响回调效果,建议在应用启动方法优先添加回调以及调用TPNS注册方法
if (Platform.isIOS) {
tpush.startXg("1600007893", "IX4BGYYG8L4L");
} else {
tpush.startXg("1500004343", "ANCVHDQ0DO3E");
}
}
void _showAlert(String title) {
Alert(context: context, title: title, buttons: [
DialogButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(
"确认",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
]).show();
}
@override
Widget build(BuildContext context) {
return HomeTest();
}
}
... ...