Flutter集成个推推送-安卓原生篇

请添加图片描述

前言

在众多的集成化推送中选择了个推,个推在flutter集成中还是比较简单的,只需要跟着官网一步一步走就可以了。今天这篇文章不涉及到flutter项目个推的集成,只是记录个推离线走安卓厂商时,进行获取一个离线的点击通知数据。

在个推的官网中提供的例子是java的,不符合我的意向,再加上flutter默认是kotlin的,所以本篇文章也是以kotlin的代码为主。

准备工作

项目以集成个推推送并配置好了个推的appId和各方厂商的appIdappKey等。

在服务端的推送代码配置中需要添加push_channel键值对,可以参考下面的代码。

{
    "push_channel":{
        "android":{
            "ups":{
                "notification":{
                    "title":"标题",
                    "body":"内容",
                    "click_type":"intent",
                    "url": "", // 不填
                    "intent": ""
                }
            }
        }
    }
}

原生配置说明

intent 已下面这种为参考进行配置。

  • host: host。这个是自定义的想咋写就咋写。
  • scheme: 协议方案。这个是自定义的想咋写就咋写。
  • package: app 包名。
  • component: 是一个启动的 Activity。
  • payload: 自定义传递的参数。

intent://host?#Intent;scheme=scheme;launchFlags=0x4000000;package=package;component=component;S.payload=payload;S.gttask=;end

配置好的样子大概就是下面这个样子:

intent://host?#Intent;scheme=scheme;launchFlags=0x4000000;package=package;component=包名/包名.MainActivity;S.payload=payload;S.gttask=;end

我们需要在android/app/src/main/AndroidManifest.xmlactivity中找到你配置个推的那块添加下面这样一段代码:

  • host: 这里的host就是上文中配置的host
  • path: 这个可以随便写,根据自己需求来。
  • scheme: 也是上文中的scheme
<data android:host="host" android:path="path" android:scheme="scheme" />

大概就是下面这个样子的:

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleTop"
    ...
    >
    ...
    
    
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

            <!-- 自定义的 -->
            <data android:host="host" android:path="path" android:scheme="scheme" />
    </intent-filter>
    
    ...
</activity>

上面这样就已经配置好了,现在开始来写代码。

上路

打开项目的android/app/src/main/kotlin/com/xx/xx/MainActivity.kt文件,引入下面的依赖。

import android.content.Intent 
import android.os.Bundle
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodCall
import io.flutter.embedding.engine.FlutterEngine

然后在MainActivity类中申明通道名称和payload。

// 通道名称
protected var channel: String = "通道名称";

// 获取推送,发给flutter
protected var payLoad: String? = null;

编写原生kotlin代码

我们需要重写onCreateonNewIntentconfigureFlutterEngine这三个方法,我们自己进行重新就可以了,在创建的项目代码中是没有这三个方法的。

一、onCreate

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // 获取自定义透传参数值
    val intent: Intent? = getIntent()
    if (null != intent) {
        payLoad = intent.getStringExtra("payload")
    }
}

二、onNewIntent

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)

    // 获取自定义透传参数值
    if (null != intent) {
        payLoad = intent.getStringExtra("payload")
    }
}

三、configureFlutterEngine

这里我们设置一个名为getIntentData的方法名,并进行判断是否是传递的这个方法名,并进行相关处理。我们后面获取数据全靠它。

override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)

    payLoad = intent.getStringExtra("payload");

    try {

        // 通过MethodChannel调用通知flutter开启参数
        MethodChannel(
                flutterEngine.dartExecutor.binaryMessenger,
                channel
        ).setMethodCallHandler { call: MethodCall, result: MethodChannel.Result -> 
            if (call.method == "getIntentData") {
                result.success("$payLoad")
            } 
        }

    } catch (err: Exception) {}

}

编写dart代码

现在我们回到flutter层面,开始写dart的代码,并进行与我们写的通道进行通信。

申明一个getIntentFuture的异步函数,并创建通道。这里的通道名称一定要和上面我们写的原生通道名称一致,不然没法调用通信。

getIntent() async {
    // 设置通道名称
    const MethodChannel channel = MethodChannel("通道名称");
}

通过invokeMethod的形式去调用我们在原生方面外露的方法名。

String result = await channel.invokeMethod("getIntentData");

接下来判断result是否是正确的值,因为我这边在原生那边通信的时候是将它转成了一个字符串,所以我们判断的是否要以字符串的形式去判断。像下面这样。

if (['null'].contains(result)){}

当我们拿到合规正确的值过后就可以全程在flutter层面进行调用使用了。由于他是一个字符串,我需要将他转成Map的形式来方便使用。

try {
    Map data = json.decode(result);
} catch (error) {
    throw Exception('from-> $result to Map fail, incorrect format');
}

注意

我这里在服务端传递payload的数据时是一个被json化了的字符串,如果朋友你不是这种的字符串记得加处理哦。

如果不知道什么是被json化了的字符串,可以看下面这个:

“{a: 1}”

这个我们就写完啦。这个不能边跑边调试,需要每次以离线跑进行调试,还是稍微有点麻烦。只能以冷启动进行调试。

完整代码

原生代码:

package 包名

import io.flutter.embedding.android.FlutterActivity

import android.content.Intent 
import android.os.Bundle
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodCall
import io.flutter.embedding.engine.FlutterEngine

class MainActivity: FlutterActivity() {

    // 通道名称
    protected var channel: String = "通道名称";
    
    // 获取推送,发给flutter
    protected var payLoad: String? = null;

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 获取自定义透传参数值
        val intent: Intent? = getIntent()
        if (null != intent) {
            payLoad = intent.getStringExtra("payload")
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)

        // 获取自定义透传参数值
        if (null != intent) {
            payLoad = intent.getStringExtra("payload")
        }
    }

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        payLoad = intent.getStringExtra("payload");

        try {

            // 通过MethodChannel调用通知flutter开启参数
            MethodChannel(
                    flutterEngine.dartExecutor.binaryMessenger,
                    channel
            ).setMethodCallHandler { call: MethodCall, result: MethodChannel.Result -> 
                if (call.method == "getIntentData") {
                    result.success("$payLoad")
                } 
            }

        } catch (err: Exception) {}
    }


}

flutter代码:

Future<Map<String, dynamic>> getIntent() async {
    // 设置通道名称
    const MethodChannel channel = MethodChannel("通道名称");
    
    String result = await channel.invokeMethod("getIntentData");
    Map<String, dynamic> resultData = {};

    if (['null'].contains(result)){
        return resultData;
    }

    try {
        Map data = json.decode(result);
        resultData = data as Map<String, dynamic>;
    } catch (error) {
        throw Exception('from-> $result to Map fail, incorrect format');
    }
    
    return resultData;        
}

最后

以上就是本篇文章的全部内容,希望对此时此刻的你有所帮助。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
好的,下面是Flutter集成极光的步骤: 1. 在极光官网注册账号并创建应用,获取AppKey。 2. 在Flutter项目中添加极光插件,如:jpush_flutter。 3. 在AndroidManifest.xml文件中添加以下代码: ```xml <!-- 极光权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 极光服务 --> <service android:name="cn.jpush.android.service.PushService" android:enabled="true" android:exported="false" android:process=":pushcore" > <intent-filter> <action android:name="cn.jpush.android.intent.REGISTER" /> <action android:name="cn.jpush.android.intent.REPORT" /> <action android:name="cn.jpush.android.intent.PushService" /> <action android:name="cn.jpush.android.intent.PUSH_TIME" /> </intent-filter> </service> <receiver android:name="cn.jpush.android.service.PushReceiver" android:enabled="true" android:exported="false" > <intent-filter android:priority="1000"> <action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <category android:name="你的包名" /> </intent-filter> <intent-filter> <action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED_PROXY" /> <category android:name="你的包名" /> </intent-filter> <intent-filter> <action android:name="cn.jpush.android.intent.REGISTRATION" /> <category android:name="你的包名" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.USER_PRESENT" /> <category android:name="你的包名" /> </intent-filter> <intent-filter> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> <category android:name="你的包名" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.PACKAGE_ADDED" /> <data android:scheme="package" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.PACKAGE_REMOVED" /> <data android:scheme="package" /> </intent-filter> </receiver> ``` 4. 在iOS项目中,到极光官网下载JPush SDK并导入到项目中,在AppDelegate.m文件中添加以下代码: ```objective-c #import "JPUSHService.h" // iOS 10 及以上需导入 UserNotifications.framework #import <UserNotifications/UserNotifications.h> // Override point for customization after application launch. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 初始化 JPush SDK [JPUSHService setupWithOption:launchOptions appKey:@"your_appkey" channel:nil apsForProduction:NO]; return YES; } // 注册APNs成功并上报DeviceToken - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [JPUSHService registerDeviceToken:deviceToken]; } // 实现注册APNs失败接口 - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"did Fail To Register For Remote Notifications With Error: %@", error); } // 添加处理APNs通知回调方法 #ifdef NSFoundationVersionNumber_iOS_9_x_Max // iOS 10之前收到通知 - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // Required, iOS 7 Support [JPUSHService handleRemoteNotification:userInfo]; completionHandler(UIBackgroundFetchResultNewData); } // iOS 10之前收到本地通知 - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { // Required, iOS 7 Support [JPUSHService showLocalNotificationAtFront:notification identifierKey:nil]; } // iOS 10及以上收到通知 - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler { NSDictionary * userInfo = notification.request.content.userInfo; if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) { [JPUSHService handleRemoteNotification:userInfo]; } completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge | UNNotificationPresentationOptionSound); } // iOS 10及以上收到本地通知 - (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler { NSDictionary * userInfo = response.notification.request.content.userInfo; if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) { [JPUSHService handleRemoteNotification:userInfo]; } completionHandler(); } #endif ``` 5. 在Flutter代码中,初始化JPush并监听事件: ```dart import 'package:jpush_flutter/jpush_flutter.dart'; // 初始化JPush JPush jpush = new JPush(); // 监听事件 jpush.addEventHandler( onReceiveNotification: (Map<String, dynamic> message) async { print("Flutter onReceiveNotification: $message"); }, onOpenNotification: (Map<String, dynamic> message) async { print("Flutter onOpenNotification: $message"); }, onReceiveMessage: (Map<String, dynamic> message) async { print("Flutter onReceiveMessage: $message"); }, ); // 启动JPush jpush.setup( appKey: "your_appkey", // 极光官网申请的AppKey channel: "developer-default", // 渠道,默认值为“developer-default” production: false, // 是否生产环境 debug: true, // 是否开启调试模式 ); ``` 以上就是Flutter集成极光的步骤,希望能对你有所帮助。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值