??????我們每天都在接收各種推送消息取逾,而最初的 Flutter 推送主要是與原生交互進(jìn)行岁歉;現(xiàn)階段極光推出了 Flutter JPush,雖不如原生強(qiáng)大职辅,但日常需求均可滿足,小菜嘗試集成了 Flutter 版的 JPush聂示;
前期準(zhǔn)備
- 在 極光 后臺(tái)注冊(cè)賬號(hào)并【創(chuàng)建應(yīng)用】域携;
- 在【推送設(shè)置】中設(shè)置 Android/iOS 基本信息,小菜以 Android 為例鱼喉,注意應(yīng)用包名為 ApplicationID秀鞭;
- 在【應(yīng)用信息】中獲取 AppKey 等關(guān)鍵參數(shù);
中期集成
Android 配置
??????與原生接入 JPush 相同扛禽,需要在 Android Gradle 加入配置信息锋边;
defaultConfig {
applicationId "com.example.flutterapp01"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
//選擇要添加的對(duì)應(yīng) cpu 類型的 .so 庫(kù)。
abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'x86_64', 'mips', 'mips64', 'arm64-v8a'
}
manifestPlaceholders = [
JPUSH_PKGNAME : "com.example.flutterapp01",
JPUSH_APPKEY : "AppKey", // NOTE: JPush 上注冊(cè)的包名對(duì)應(yīng)的 Appkey.
JPUSH_CHANNEL : "developer-default", //暫時(shí)填寫默認(rèn)值即可.
]
}
Flutter 配置
??????按照平常插件接入的方法在工程 pubspec.yaml 中加入 jpush_flutter: 0.1.0 并同步即可编曼;
dependencies:
jpush_flutter: 0.1.0
API 調(diào)用
JPush 的使用方式很簡(jiǎn)單豆巨,Demo 中都很全面,小菜僅嘗試常見(jiàn)的方法掐场;
1. 初始化
??????在原生開發(fā)中各類三方的插件幾乎均須在 Application 中初始化往扔,同樣 Flutter 也需要先調(diào)用 JPush.setup 進(jìn)行初始化;其中 channel 可自定義熊户,小菜未從源碼中獲取準(zhǔn)確消息萍膛,個(gè)人理解與高版本的 Android Channel 通道類似;
??????初始化成功之后即可獲取消息推送嚷堡,只是暫不能處理蝗罗;
final JPush _jPush = JPush();
@override
void initState() {
super.initState();
initPlatformState();
}
Future<void> initPlatformState() async {
_jPush.setup(
appKey: "后臺(tái)獲取 AppKey",
channel: "flutter_channel",
production: false,
debug: true,
);
if (!mounted) return;
}
2. RegistrationID
??????每個(gè)用戶均有作為接收消息的唯一標(biāo)識(shí) RegistrationID,方便對(duì)單個(gè)或多個(gè)設(shè)備進(jìn)行推送測(cè)試蝌戒;
_jPush.getRegistrationID().then((rid) {
setState(() {
_result = "JPush RegistrationID 唯一標(biāo)識(shí):\n $rid";
_registID = rid;
});
});
3. 本地通知
??????JPush 提供了本地推送的方法串塑,可以靈活調(diào)用獲取本地推送消息;注意 id 為 int 類型北苟,設(shè)置不能過(guò)長(zhǎng)桩匪;
// 源碼分析
const LocalNotification ({
@required this.id, // 通知 id, 可用于取消通知
@required this.title, // 通知標(biāo)題
@required this.content, // 通知內(nèi)容
@required this.fireTime, // 通知觸發(fā)時(shí)間(毫秒)
this.buildId, // 通知樣式:1 為基礎(chǔ)樣式,2 為自定義樣式(需先調(diào)用 'setStyleCustom' 設(shè)置自定義樣式)
this.extra, // 額外信息
this.badge = 0, // iOS:本地推送觸發(fā)后應(yīng)用角標(biāo)值
this.soundName, // iOS:指定推送的音頻文件
this.subtitle // iOS:子標(biāo)題
}):
onTap: () {
var fireDate = DateTime.fromMillisecondsSinceEpoch(DateTime.now().millisecondsSinceEpoch + 3000);
var localNotification = LocalNotification(
id: 000001,
title: 'Local Push 本地標(biāo)題',
buildId: 1,
content: 'Local Push 本地內(nèi)容',
fireTime: fireDate,
extra: {"extra_key": "extra_value"});
_jPush.sendLocalNotification(localNotification).then((res) {
setState(() {
_result = res;
});
});
}
4. 通知類消息
??????小菜集成原生推送時(shí)分為 通知類消息 和 透?jìng)黝愊?自定義消息)粹淋,兩種推送略有不同吸祟;通知類消息可以通過(guò)極光后臺(tái)配置消息標(biāo)題、消息內(nèi)容等多種信息桃移,且 App 接收到之后直接調(diào)用推送通道展現(xiàn)在通知欄中屋匕;
try {
_jPush.addEventHandler(
onReceiveNotification: (Map<String, dynamic> message) async {
// 獲取通知數(shù)據(jù)
print('Flutter JPush 獲取通知類數(shù)據(jù):\n $message');
setState(() {
_result = 'Flutter JPush 獲取通知類數(shù)據(jù):\n $message';
_message = message;
});
}
);
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
5. 透?jìng)黝愊?/h5>
??????透?jìng)黝愊⑼ㄟ^(guò)極光后臺(tái)配置發(fā)送,主要配置通知內(nèi)容借杰;App 接收到不會(huì)直接調(diào)用推送通道过吻,獲取內(nèi)容后我們可根據(jù)內(nèi)容靈活使用,是否展示推送消息或其他操作等;且通知類消息與透?jìng)黝愊@取參數(shù)不同纤虽;
try {
_jPush.addEventHandler(
onReceiveMessage: (Map<String, dynamic> message) async {
// 獲取透?jìng)鲾?shù)據(jù)
print('Flutter JPush 獲取透?jìng)黝悢?shù)據(jù):\n $message');
setState(() {
_result = 'Flutter JPush 獲取透?jìng)黝悢?shù)據(jù):\n $message';
_message = message;
});
}
);
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
6. 推送點(diǎn)擊監(jiān)聽(tīng)
??????獲取到推送之后注定要有點(diǎn)擊操作乳绕,JPush 也同樣提供了監(jiān)聽(tīng)方法,包括通知類消息和本地推送消息逼纸;
try {
_jPush.addEventHandler(
onOpenNotification: (Map<String, dynamic> message) async {
// 點(diǎn)擊通知信息
print('Flutter JPush 點(diǎn)擊通知消息:\n $message');
setState(() {
_result = 'Flutter JPush 點(diǎn)擊通知消息:\n $message';
_message = message;
});
}
);
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
7. 清空通知欄
??????在用戶收到推送通知后若未點(diǎn)擊洋措,原生 Android 可通過(guò) NotificationManager.cancel() 清除通知,Flutter 也提供了清空通知欄方法杰刽;但小菜測(cè)試只可清空通知類推送消息菠发,本地發(fā)送的通知消息無(wú)法清空;
Future clearAllNotifications() async {
await _channel.invokeMethod('clearAllNotifications');
}
_jPush.clearAllNotifications();
后期測(cè)試
1. 通知類消息
- 在極光后臺(tái)【發(fā)送通知】中按要求編輯目標(biāo)平臺(tái)贺嫂、通知標(biāo)題滓鸠、通知內(nèi)容、發(fā)送時(shí)間和選擇目標(biāo)等基本信息第喳;
-
App 接收消息糜俗,并展示推送消息,各參數(shù)如下:
2. 透?jìng)黝愊?/h4>
- 在極光后臺(tái)【自定義消息】中按要求編輯目標(biāo)平臺(tái)曲饱、通知內(nèi)容悠抹、發(fā)送時(shí)間和選擇目標(biāo)等基本信息;其中 Registration ID 為測(cè)試時(shí)獲取的唯一標(biāo)識(shí)渔工;
-
App 接收消息锌钮,不會(huì)展示推送消息,若需要可調(diào)用本地通知引矩;各參數(shù)如下:
onOpenNotification: (Map<String, dynamic> message) async {
setState(() {
_result = 'Flutter JPush 點(diǎn)擊通知消息:\n $message';
_message = message;
Map<String, dynamic> message2 = convert.jsonDecode(_message['extras']['cn.jpush.android.EXTRA']);
if (message2['type'] == "1") {
Toast.show('自定義通知消息!', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
}
});
}
onReceiveMessage: (Map<String, dynamic> message) async {
setState(() {
_result = 'Flutter JPush 獲取透?jìng)黝悢?shù)據(jù):\n $message';
_message = message;
Map<String, dynamic> message2 = convert.jsonDecode(_message['message']);
var fireDate = DateTime.fromMillisecondsSinceEpoch(DateTime.now().millisecondsSinceEpoch + 2000);
var localNotification = LocalNotification(
id: message2['id'],
title: message2['title'],
buildId: 1,
content: message2['context'],
fireTime: fireDate,
extra: {"type": message2['type']});
_jPush.sendLocalNotification(localNotification).then((res) {
setState(() { _result = res; });
});
});
}
onOpenNotification: (Map<String, dynamic> message) async {
setState(() {
_result = 'Flutter JPush 點(diǎn)擊通知消息:\n $message';
_message = message;
Map<String, dynamic> message2 = convert.jsonDecode(_message['extras']['cn.jpush.android.EXTRA']);
if (message2['type'] == "1") {
Toast.show('自定義通知消息!', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
}
});
}
onReceiveMessage: (Map<String, dynamic> message) async {
setState(() {
_result = 'Flutter JPush 獲取透?jìng)黝悢?shù)據(jù):\n $message';
_message = message;
Map<String, dynamic> message2 = convert.jsonDecode(_message['message']);
var fireDate = DateTime.fromMillisecondsSinceEpoch(DateTime.now().millisecondsSinceEpoch + 2000);
var localNotification = LocalNotification(
id: message2['id'],
title: message2['title'],
buildId: 1,
content: message2['context'],
fireTime: fireDate,
extra: {"type": message2['type']});
_jPush.sendLocalNotification(localNotification).then((res) {
setState(() { _result = res; });
});
});
}
??????小菜認(rèn)為 Flutter 版的極光推送與 Android 原生版本的差異在于,大部分的配置有 App 端移到了極光后臺(tái)侵浸,包括圖標(biāo) icon旺韭,頁(yè)面處理,通知級(jí)別等掏觉;小菜僅嘗試了基本的消息推送及處理区端,還是有很多細(xì)節(jié)需要認(rèn)真學(xué)習(xí);如有問(wèn)題澳腹,請(qǐng)多多指導(dǎo)织盼!
來(lái)源: 阿策小和尚