foreword
Among the many integrated pushes, I chose a push, which flutter
is relatively simple in the integration, just follow the official website step by step. Today's article does not involve flutter
the integration of the project and push, but only records the acquisition of an offline click notification data when a push goes offline to an Android manufacturer.
The example provided on Getui’s official website is yes java
, which does not meet my intentions, and the flutter
default is kotlin
yes, so this article is also kotlin
based on the code.
Preparation
The project integrates Getui and configures Getui appId
and all manufacturers appId
, appKey
etc.
You need to add key-value pairs in the push code configuration on the server side push_channel
, you can refer to the following code.
{
"push_channel":{
"android":{
"ups":{
"notification":{
"title":"标题",
"body":"内容",
"click_type":"intent",
"url": "", // 不填
"intent": ""
}
}
}
}
}
Native configuration instructions
intent
The configuration below is for reference.
host
: host. This is a custom one that you can write whatever you want.scheme
: protocol scheme. This is a custom one that you can write whatever you want.package
: app package name.component
: is a started Activity.payload
: Custom passed parameters.
intent://host?#Intent;scheme=scheme;launchFlags=0x4000000;package=package;component=component;S.payload=payload;S.gttask=;end
The configuration looks roughly like this:
intent://host?#Intent;scheme=scheme;launchFlags=0x4000000;package=package;component=包名/包名.MainActivity;S.payload=payload;S.gttask=;end
We need to find the piece where you configure a push in and add the following piece of code android/app/src/main/AndroidManifest.xml
:activity
host
: Herehost
is the configuration abovehost
.path
: This can be written casually, according to your own needs.scheme
: is also in the abovescheme
.
<data android:host="host" android:path="path" android:scheme="scheme" />
Probably something like this:
<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>
The above is already configured, now let's start writing the code.
hit the road
Open the project android/app/src/main/kotlin/com/xx/xx/MainActivity.kt
file and import the following dependencies.
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
Then MainActivity
declare the channel name and payload in the class.
// 通道名称
protected var channel: String = "通道名称";
// 获取推送,发给flutter
protected var payLoad: String? = null;
write native kotlin
code
We need to rewrite onCreate
, onNewIntent
, and configureFlutterEngine
these three methods, and we can rewrite them ourselves. There are no these three methods in the created project code.
one,onCreate
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 获取自定义透传参数值
val intent: Intent? = getIntent()
if (null != intent) {
payLoad = intent.getStringExtra("payload")
}
}
two,onNewIntent
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
// 获取自定义透传参数值
if (null != intent) {
payLoad = intent.getStringExtra("payload")
}
}
three,configureFlutterEngine
Here we set a named getIntentData
method name, and judge whether it is the passed method name, and perform related processing. We rely on it to obtain data later.
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) {
}
}
write dart
code
Now we go back to flutter
the layer, start writing dart
the code, and communicate with the channel we wrote.
Declare an getIntent
asynchronous Future
function and create a channel. The channel name here must be the same as the original channel name we wrote above, otherwise the communication cannot be called.
getIntent() async {
// 设置通道名称
const MethodChannel channel = MethodChannel("通道名称");
}
Through invokeMethod
the form to call the method name we exposed in the native aspect.
String result = await channel.invokeMethod("getIntentData");
Next, judge result
whether it is the correct value, because when I communicate with the native side, it is converted into a string, so we judge whether it should be judged in the form of a string. like below.
if (['null'].contains(result)){
}
When we get the compliant and correct value, we can flutter
call and use it at the whole level. Since he is a string, I need to convert it into Map
a form for easy use.
try {
Map data = json.decode(result);
} catch (error) {
throw Exception('from-> $result to Map fail, incorrect format');
}
Notice
The data I pass on the server here payload
is a converted json
string, if you are not this kind of string, remember to add it.
If you don't know what a converted json
string is, you can see the following:
“{a: 1}”
We're done with this. This cannot be debugged while running. It needs to be debugged offline every time, which is still a little troublesome. Commissioning is only possible with a cold start.
full code
Native code:
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
code:
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;
}
at last
The above is the whole content of this article, I hope it will be helpful to you at this moment.