Flutter integrates a push push - Android native articles

Please add a picture description

foreword

Among the many integrated pushes, I chose a push, which flutteris relatively simple in the integration, just follow the official website step by step. Today's article does not involve flutterthe 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 flutterdefault is kotlinyes, so this article is also kotlinbased on the code.

Preparation

The project integrates Getui and configures Getui appIdand all manufacturers appId, appKeyetc.

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

intentThe 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: Here hostis the configuration above host.
  • path: This can be written casually, according to your own needs.
  • scheme: is also in the above scheme.
<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.ktfile 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 MainActivitydeclare the channel name and payload in the class.

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

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

write native kotlincode

We need to rewrite onCreate, onNewIntent, and configureFlutterEnginethese 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 getIntentDatamethod 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 dartcode

Now we go back to flutterthe layer, start writing dartthe code, and communicate with the channel we wrote.

Declare an getIntentasynchronous Futurefunction 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 invokeMethodthe form to call the method name we exposed in the native aspect.

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

Next, judge resultwhether 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 fluttercall and use it at the whole level. Since he is a string, I need to convert it into Mapa 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 payloadis a converted jsonstring, if you are not this kind of string, remember to add it.

If you don't know what a converted jsonstring 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) {
    
    }
    }


}

fluttercode:

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.

Guess you like

Origin blog.csdn.net/qq_44500360/article/details/130385070