万万哇 发表于 2024-7-18 03:12:01

【Flutter】极光推送配置流程(极光通道/华为厂商/IOS) 章一

极光推送配置流程
干系文章

推送配置共三篇(如下链接)
【Flutter】极光推送配置流程(极光通道/华为厂商/IOS) 章一
【Flutter】极光推送配置流程(小米厂商通道) 章二
【Flutter】极光推送配置流程(VIVO/OPPO/荣耀厂商通道) 章三
极光通道(在线)

配置时间 2024年3月11日
创建应用

https://img-blog.csdnimg.cn/direct/6bb30114532745ceb9adcf8d5f6eb184.png
应用列表 - 创建应用
https://img-blog.csdnimg.cn/direct/7329802b83b64ffe96e1f601df93329f.png
Android - 选中消息推送 - 下一步
创建Flutter项目
https://img-blog.csdnimg.cn/direct/6aee19e262244ac8a25b7ff80372bbee.png
填写包名
https://img-blog.csdnimg.cn/direct/3bc448e43c1547c0b3e194b1183a13db.png
创建完成
https://img-blog.csdnimg.cn/direct/d818dc97b9d2494da719b4c10e4bb0be.png
项目配置

运行下令行 flutter pub add jpush_flutter
https://img-blog.csdnimg.cn/direct/b290f289db264e48969a7db2fffd2305.png
Android -> app -> build.gradle 更改JPUSH_APPKEY的值
https://img-blog.csdnimg.cn/direct/8b522e60f7d542509126d7c3c110d8a3.png
https://img-blog.csdnimg.cn/direct/ddc42c43b8ea47e7a9e659a315066101.png
工具类注册JPush Android
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:jpush_flutter/jpush_flutter.dart';

class JPushUtil {
JPushUtil._internal();

static final _instance = JPushUtil._internal();

factory JPushUtil() => _instance;

final JPush jPush = JPush();

Future<void> initPlatformState() async {
    String? platformVersion;
    try {
      jPush.addEventHandler(
      onReceiveNotification: (message) async {
          print("flutter onReceiveNotification: $message");
      },
      onOpenNotification: (message) async {
          print("flutter onOpenNotification: $message");
      },
      onReceiveMessage: (message) async {
          print("flutter onReceiveMessage: $message");
      },
      onReceiveNotificationAuthorization: (message) async {
          print("flutter onReceiveNotificationAuthorization: $message");
      },
      onConnected: (message) {
          print("flutter onConnected: $message");
          return Future(() => null);
      },
      );
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
      print(platformVersion);
    }
    jPush.isNotificationEnabled().then((bool value) {
      print("通知授权是否打开: $value");
      if (!value) {
      Get.snackbar(
          "提示",
          "没有通知权限,点击跳转打开通知设置界面",
          duration: const Duration(seconds: 6),
          onTap: (_) {
            jPush.openSettingsForNotification();
          },
      );
      }
    }).catchError((onError) {
      print("通知授权是否打开: ${onError.toString()}");
    });

    jPush.enableAutoWakeup(enable: true);
    jPush.setup(
      appKey: '7f684a39ff1f95ef1657acdd',
      production: true,
      debug: true,
    );
    jPush.applyPushAuthority(
      const NotificationSettingsIOS(
      sound: true,
      alert: true,
      badge: true,
      ),
    );
    final rid = await jPush.getRegistrationID();
    print("flutter getRegistrationID: $rid");
}

setAlias(String aliasStr) {
    final alias = jPush.setAlias(aliasStr);
    print("Alias is $alias");
}
}
main.dart
import 'package:demonstration_project/jPushUtil.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

// This widget is the root of your application.
@override
Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter 极光推送',
      home: HomePage(),
    );
}
}

class HomePage extends StatefulWidget {
@override
State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
@override
void initState() {
    JPushUtil().initPlatformState();
    super.initState();
}

@override
Widget build(BuildContext context) {
    return const Scaffold(
      body: Center(
      child: Text("极光推送配置"),
      ),
    );
}
}
运行项目

运行项目在Android端,有getRegistrationID,则注册成功
https://img-blog.csdnimg.cn/direct/f6bcaecedd12487aa529ffefb2f56e8f.png
测试接收推送之前,先打开接收关照的权限
https://img-blog.csdnimg.cn/direct/3153edd016884ff4ad0a6957f0e7fb0f.png
在极光平台检测集成
https://img-blog.csdnimg.cn/direct/e269c61e7cbd4002803905de9e40bc6f.png
推送消息

平台推送

直接在平台客户端输入对应的数值来推送消息
https://img-blog.csdnimg.cn/direct/0f07fbf4385f4823bf9941ec68c265ab.png
https://img-blog.csdnimg.cn/direct/65f739d928a84ccfbc24a92827338201.png
注:当APP被杀死后,极光通道的推送就不能实时收到了,以是要配置厂商通道
推送API

通过接口调用推送
厂商通道(华为)

创建项目 创建应用

应用服务 - PUSH
https://img-blog.csdnimg.cn/direct/d39579f2d02f4af7becec52db6362e4e.png
https://img-blog.csdnimg.cn/direct/f6f7a69e8d654322b8fa95c03d8b37e1.png
继承
https://img-blog.csdnimg.cn/direct/741e119ec2054dca9afc51f16a635f11.png
选择中国
https://img-blog.csdnimg.cn/direct/a2903e5313e74c8eb13df291a4d19d41.png
开通推送服务
https://img-blog.csdnimg.cn/direct/fcbc029148a44b36a63c72c19e4bf0ba.png
https://img-blog.csdnimg.cn/direct/c59d573c2d8348a6aafd82b312ecaeba.png
添加应用
https://img-blog.csdnimg.cn/direct/987f0fed5c054346aafae9cda56de11d.png
输入干系信息
https://img-blog.csdnimg.cn/direct/a607265012d442cbb3752f514c41111e.png
下载agconnect-services.json
https://img-blog.csdnimg.cn/direct/8e6e3ace236e44e4955f981f9fdd6dc5.png
放到应用级目录下
https://img-blog.csdnimg.cn/direct/9462098e2010491d8e804995ea10e34d.png
SHA256证书指纹

https://img-blog.csdnimg.cn/direct/480e649e90a2402ca47694608c984823.png
天生签名jks

天生签名文件的参考文档链接
https://img-blog.csdnimg.cn/direct/ed971e82eae14d81a225d6ef8fdb6237.png
创建新的Key
https://img-blog.csdnimg.cn/direct/3b50458d877d469abda69d3d89cf45d6.png
https://img-blog.csdnimg.cn/direct/f1ce34a5d936406b886d625c25df4920.png
https://img-blog.csdnimg.cn/direct/4bc49a18a5124a80b4af1a7afec81a70.png
https://img-blog.csdnimg.cn/direct/1ef5e0302b7b46589c1dd4d06bd285e7.png
https://img-blog.csdnimg.cn/direct/e7c6d596a20b4e6880110a75bce04564.png
天生签名证书指纹

** keytool -list -v -keystore ./demostration_project_key.jks**
https://img-blog.csdnimg.cn/direct/61b3f3d2d4994b8796e55fa624562c6f.png
配置SHA256证书指纹

https://img-blog.csdnimg.cn/direct/77193f80dcaa49329c1e2734f875f49a.png
项目配置

若出现以下报错
https://img-blog.csdnimg.cn/direct/19434330d3284adc96dd17fd988e4f90.png
修改Manifest.xml文件
https://img-blog.csdnimg.cn/direct/714b989f5a5543f9b317ca2bb3947371.png
修改android/build.gradle文件
https://img-blog.csdnimg.cn/direct/10ec9ad10efa4046b4353a73e601e877.png
buildscript {
    ext.kotlin_version = '1.9.0'
    repositories {
      google()
      mavenCentral()
      // 配置HMS Core SDK的Maven仓地址。
      maven { url 'https://developer.huawei.com/repo/' }
    }

    dependencies {
      classpath 'com.android.tools.build:gradle:7.1.3'
      classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
      classpath 'com.huawei.agconnect:agcp:1.6.0.300'
    }
}
allprojects {
    repositories {
      google()
      mavenCentral()
      maven { url 'https://developer.huawei.com/repo/' }
    }
}
若出现以下报错
https://img-blog.csdnimg.cn/direct/f3b75ee883544d4284f6f402700895a9.png
那说明漏了配置AGC插件,参考干系链接
https://img-blog.csdnimg.cn/direct/e7639a99fdc440b19448a100482c2a48.png
接着添加依靠
https://img-blog.csdnimg.cn/direct/73f485e6d5c24b5f8383b067e5f9eb71.png
dependencies {
    // 极光推送'cn.jiguang.sdk:jpush:5.2.3' 和 'cn.jiguang.sdk.plugin:huawei:5.2.3' 版本需一致
    implementation 'cn.jiguang.sdk:jpush:5.2.3'
    implementation 'com.huawei.agconnect:agconnect-core:1.8.1.300'
    implementation 'com.huawei.hms:push:6.12.0.300'
    implementation 'cn.jiguang.sdk.plugin:huawei:5.2.3' // 这里版本一定要和极光插件版本一致!!!
}
最后配置签名文件,若出现以下错误,就代表没有配置签名
https://img-blog.csdnimg.cn/direct/66ac38369ec74b1ba25123f4b7fdae5f.png
https://img-blog.csdnimg.cn/direct/9f26322200834fe0ae73ecb11dd50c56.png
    signingConfigs {
      debug {
            //keystore中key的别名
            keyAlias 'demo_key'
            //keystore中key的密码
            keyPassword '123456'
            //keystore的文件路径,可以是绝对路径也可以是相对路径
            storeFile file('../demostration_project_key.jks')
            //keystore的密码l
            storePassword '123456'
      }
    }
最后在极光平台厂商通道配置设置App ID 和App Secret,并启用
https://img-blog.csdnimg.cn/direct/be5c4f5314ef49dc9c8a473ea4c37da1.png
华为平台配置

https://img-blog.csdnimg.cn/direct/513f0dd0d946428c8dad67a3d93e0dae.png
回执配置参考链接
https://img-blog.csdnimg.cn/direct/b1e9fd1e5cc44e05bbb5aabe97a887b2.png
https://img-blog.csdnimg.cn/direct/59b5c311f5e3432ebcf24d6e4d4cee51.png
https://img-blog.csdnimg.cn/direct/2f3eb50e8f7a4684a400338822ba8722.png
这里的自分类是华为控制滥发消息的,需要设置一下,参考链接
https://img-blog.csdnimg.cn/direct/dd66cf03af9b459eb57b0b68b4ef7b0f.png
选一个要发的场景
https://img-blog.csdnimg.cn/direct/8d577655a6254ccc870f97e154d63736.png
填写信息,和场景干系的信息
https://img-blog.csdnimg.cn/direct/082af19fbbea49e7a6989af7f80cd336.png
https://img-blog.csdnimg.cn/direct/794a4ed6be8d445abe45da92116f4a31.png
激活功能
https://img-blog.csdnimg.cn/direct/690caee874a444cd851f76da8721546e.png
https://img-blog.csdnimg.cn/direct/1576a039b0e24f3c944280b5a80058fb.png
https://img-blog.csdnimg.cn/direct/3f250139e61949188f90c8b2014e0881.png
找一台华为手机来运行项目

若出现以下这句,就代表配置成功了
https://img-blog.csdnimg.cn/direct/0d47dcf1306f4e2796218889d003c889.png
这里的检测会有延迟,真机测试能离线收到消息就ok
https://img-blog.csdnimg.cn/direct/21d47fbd8b84427c8cc980b76764416e.png
错误集锦

1、版本不同等

1、极光厂商插件版本和JPush版本不同等,即便输出huawei token,也是收不到离线消息的
    // 极光推送'cn.jiguang.sdk:jpush:5.2.3' 和 'cn.jiguang.sdk.plugin:huawei:5.2.3' 版本需一致
    implementation 'cn.jiguang.sdk:jpush:5.2.3'
    // 华为
    implementation 'com.huawei.agconnect:agconnect-core:1.8.1.300'
    implementation 'com.huawei.hms:push:6.12.0.300'
    implementation 'cn.jiguang.sdk.plugin:huawei:5.2.3'
2、权限

网络权限记得加上
<uses-permission android:name="android.permission.INTERNET" />
Ios

官方配置参考链接
Push

https://img-blog.csdnimg.cn/direct/a5b6ff10c4f940ab91f2e3732027a9a0.png
https://img-blog.csdnimg.cn/direct/5eca78bb5a984f21a71efa156b6e7ea0.png
https://img-blog.csdnimg.cn/direct/c9115915e88f4426bf6a32ac0d22ee79.png
Podfile

https://img-blog.csdnimg.cn/direct/3cf3ee18b6534b119b810b1bd6ae19aa.png
pod 'JPush'
pod 'JOperate'
pod 'JCore'
终端 pod install
https://img-blog.csdnimg.cn/direct/6fb8f2354f1b49bf95ae604b41c7e3d3.png
Token Authentication配置

https://img-blog.csdnimg.cn/direct/566b6938244543eca2731fce911cca4e.png
developer.apple.com
https://img-blog.csdnimg.cn/direct/3580586f262f4757818c0ec3ddac0b6a.png
后续步调直接参考上面的链接,很具体
最后获取到的
https://img-blog.csdnimg.cn/direct/925f39e3a1de429ba54114e076b7ce47.png
https://img-blog.csdnimg.cn/direct/49ebf78c14c4447f8690e82b64e412d5.png
https://img-blog.csdnimg.cn/direct/5e4db14318354f7b8b34c4ed2e7ecda5.png
运行项目

https://img-blog.csdnimg.cn/direct/2de61f0183ac4915b1dc2823cf705040.png
配置完成
推送API

推送API参考文档
鉴权方式

用冒号拼接appkey和masterSecret,并用base64加密该字符串,终极再拼上"Basic "
    final content = utf8.encode("$appKey:$masterSecret");
    String base64AuthString = "Basic ${base64Encode(content)}";
测试代码
import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
    return MaterialApp(
      title: '推送',
      theme: ThemeData(
      colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      useMaterial3: true,
      ),
      home: const MyHomePage(title: '信息推送'),
    );
}
}

class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});

final String title;

@override
State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
final String appKey = "XXX";
final String masterSecret = "XXX";
late String base64AuthString;
final Dio dio = Dio();

late String notificationAlert;
late String notificationTitle;
late String notificationAudienceAlias;

@override
void initState() {
    final content = utf8.encode("$appKey:$masterSecret");
    base64AuthString = "Basic ${base64Encode(content)}";
    super.initState();
}

@override
Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      title: Text(widget.title),
      ),
      body: Center(
      child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: ListView(
            children: [
            TextField(
                decoration: const InputDecoration(
                  labelText: "主标题",
                  hintText: "请输入...",
                ),
                onChanged: (s) {
                  notificationAlert = s;
                },
            ),
            TextField(
                decoration: const InputDecoration(
                  labelText: "副标题",
                  hintText: "请输入...",
                ),
                onChanged: (s) {
                  notificationTitle = s;
                },
            ),
            TextField(
                decoration: const InputDecoration(
                  labelText: "别名",
                  hintText: "请输入...",
                ),
                onChanged: (s) {
                  notificationAudienceAlias = s;
                },
            ),
            Padding(
                padding: const EdgeInsets.all(8.0),
                child: ElevatedButton(
                  onPressed: () {
                  showDialog(
                        context: context,
                        builder: (context) {
                        return SimpleDialog(
                            title: const Text("确定发送?"),
                            children: [
                              SimpleDialogOption(
                              child: const Text("确定"),
                              onPressed: () {
                                  pushMessage(
                                    notificationAlert: notificationAlert,
                                    notificationTitle: notificationTitle,
                                    notificationAudienceAlias: [
                                    notificationAudienceAlias
                                    ],
                                  );
                                  Navigator.of(context).pop();
                              },
                              ),
                              SimpleDialogOption(
                              child: const Text("取消"),
                              onPressed: () {
                                  Navigator.of(context).pop();
                              },
                              )
                            ],
                        );
                        });
                  },
                  child: const Text("推送消息"),
                ),
            ),
            ],
          ),
      ),
      ),
    );
}

/// 推送
pushMessage({
    required String notificationAlert,
    required String notificationTitle,
    required List<String> notificationAudienceAlias,
}) async {
    const String url = "https://api.jpush.cn/v3/push";
    var data = json.encode({
      "platform": ["android", "ios"],
      "inapp_message": {"inapp_message": false},
      "options": {
      "classification": 0,
      "time_to_live": 86400,
      "apns_production": false,
      "third_party_channel": {
          "huawei": {
            "skip_quota": false,
            "distribution": "secondary_push",
            "channel_id": "",
            "category": "DEVICE_REMINDER",
            "receipt_id": ""
          }
      }
      },
      "notification": {
      "alert": notificationAlert,
      "android": {
          "alert": notificationAlert,
          "title": notificationTitle,
          "intent": {"url": "intent:#Intent;action=android.intent.action.MAIN;end"},
          "sound": "",
          "priority": 0,
          "category": "",
          "alert_type": 7,
          "style": 0,
          "builder_id": 0,
          "large_icon": "",
          "badge_add_num": 1,
          "extras": {
            "param": "123"
          }
      },
      "ios": {
          "alert": {
            "title": notificationAlert,
            "body": notificationTitle,
          },
          "content-available": 0,
          "mutable-content": 1,
          "sound": "default",
          "badge": "+1",
          "thread-id": "",
          "interruption-level": "active",
          "filter-criteria": "",
          "extras": {
            "参数": "A"
          }
      }
      },
      "audience": {
      "alias": notificationAudienceAlias,
      }
    });
    final response = await dio.request(
      url,
      data: data,
      options: Options(
      headers: {
          HttpHeaders.authorizationHeader: base64AuthString,
      },
      method: "POST",
      ),
    );
    print(response.data.toString());
}
}


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【Flutter】极光推送配置流程(极光通道/华为厂商/IOS) 章一