前言
在众多的集成化推送中选择了个推,个推在flutter
集成中还是比较简单的,只需要跟着官网一步一步走就可以了。今天这篇文章不涉及到flutter
项目个推的集成,只是记录个推离线走安卓厂商时,进行获取一个离线的点击通知数据。
在个推的官网中提供的例子是java
的,不符合我的意向,再加上flutter
默认是kotlin
的,所以本篇文章也是以kotlin
的代码为主。
准备工作
项目以集成个推推送并配置好了个推的appId
和各方厂商的appId
、appKey
等。
在服务端的推送代码配置中需要添加push_channel
键值对,可以参考下面的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { "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.xml
的activity
中找到你配置个推的那块添加下面这样一段代码:
host
: 这里的host
就是上文中配置的host
。
path
: 这个可以随便写,根据自己需求来。
scheme
: 也是上文中的scheme
。
1
| <data android:host="host" android:path="path" android:scheme="scheme" />
|
大概就是下面这个样子的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <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
文件,引入下面的依赖。
1 2 3 4 5
| 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。
1 2 3 4 5 6
| protected var channel: String = "通道名称";
protected var payLoad: String? = null;
|
编写原生kotlin
代码
我们需要重写onCreate
、onNewIntent
、configureFlutterEngine
这三个方法,我们自己进行重新就可以了,在创建的项目代码中是没有这三个方法的。
一、onCreate
1 2 3 4 5 6 7 8 9 10
| override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)
val intent: Intent? = getIntent() if (null != intent) { payLoad = intent.getStringExtra("payload") } }
|
二、onNewIntent
1 2 3 4 5 6 7 8 9
| override fun onNewIntent(intent: Intent) { super.onNewIntent(intent)
if (null != intent) { payLoad = intent.getStringExtra("payload") } }
|
这里我们设置一个名为getIntentData
的方法名,并进行判断是否是传递的这个方法名,并进行相关处理。我们后面获取数据全靠它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine)
payLoad = intent.getStringExtra("payload");
try {
MethodChannel( flutterEngine.dartExecutor.binaryMessenger, channel ).setMethodCallHandler { call: MethodCall, result: MethodChannel.Result -> if (call.method == "getIntentData") { result.success("$payLoad") } }
} catch (err: Exception) {}
}
|
编写dart
代码
现在我们回到flutter
层面,开始写dart
的代码,并进行与我们写的通道进行通信。
申明一个getIntent
的Future
的异步函数,并创建通道。这里的通道名称一定要和上面我们写的原生通道名称一致,不然没法调用通信。
1 2 3 4
| getIntent() async { const MethodChannel channel = MethodChannel("通道名称"); }
|
通过invokeMethod
的形式去调用我们在原生方面外露的方法名。
1
| String result = await channel.invokeMethod("getIntentData");
|
接下来判断result
是否是正确的值,因为我这边在原生那边通信的时候是将它转成了一个字符串,所以我们判断的是否要以字符串的形式去判断。像下面这样。
1
| if (['null'].contains(result)){}
|
当我们拿到合规正确的值过后就可以全程在flutter
层面进行调用使用了。由于他是一个字符串,我需要将他转成Map
的形式来方便使用。
1 2 3 4 5
| try { Map data = json.decode(result); } catch (error) { throw Exception('from-> $result to Map fail, incorrect format'); }
|
注意
我这里在服务端传递payload
的数据时是一个被json
化了的字符串,如果朋友你不是这种的字符串记得加处理哦。
如果不知道什么是被json
化了的字符串,可以看下面这个:
“{a: 1}”
这个我们就写完啦。这个不能边跑边调试,需要每次以离线跑进行调试,还是稍微有点麻烦。只能以冷启动进行调试。
完整代码
原生代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| 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 = "通道名称"; 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( flutterEngine.dartExecutor.binaryMessenger, channel ).setMethodCallHandler { call: MethodCall, result: MethodChannel.Result -> if (call.method == "getIntentData") { result.success("$payLoad") } }
} catch (err: Exception) {} }
}
|
flutter
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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; }
|
最后
以上就是本篇文章的全部内容,希望对此时此刻的你有所帮助。