We all used to envy others, but forget, we also used to be the envy of us.

preface

My latest mission, it’s been a lot of smashing and hammering.

But nice is, push together, can sort out a cough ~

Build it up.

Follow the boss ~

The early stage of the research

Mobile terminal development to the present, the various push SDK really dazzling, let people see the eye.

Here are a few I’ve used for a simple comparison, after all, chicken boss said, you don’t even have a basic argument comparison, and you play with a hammer (I made it up).

Here is a simple comparison from several dimensions that I care about (❌ : no support, ✅ : support. Special cases are indicated separately) :

category The aurora Their Allies Mob
Offline (vendor channel) Free service is not supported, advanced version and private cloud support (Huawei, Xiaomi, Vivo, OPPO, Meizu, FCM) Support xiaomi, Huawei, Meizu, OPPO, Vivo system level channel Support Huawei, Xiaomi, Meizu, OPPO, Vivo vendor level channel and FCM
Whether aliases are supported
Flutter support

For the small division, the price is a key point, really envy open VIP or Pro partners, acid.

In view of the above three, I think:

  • If the current application only online push, aurora, Mob, umeng can be;
  • If the current app only supports domestic and also supports offline push, Umeng and Mob are the best candidates.
  • If tuhao level application, and support foreign, then direct aurora VIP/Pro go, one-button support domestic manufacturers and FCM overseas push;
  • Instead, if you want to support overseas, honestly access FCM.

I’m a little confused. I saw that Mob supports FCM, but I didn’t see it on the official website.

By the way, today I happened to see some discussions about the aurora pushed by my friends:

Good or bad, pure technology sharing, nothing else involved, make your own choice.

In addition, seeing that some friends were not satisfied with Mob, I tried it alone, and the general process was as follows:

  • My friend had trouble using Mob ShareSDK, then I contacted Mob official, and the official reply was as follows:

From a personal point of view, I feel pretty good about it (actually, I liked Mob a few years ago). As for your friends what ideas, different people, different people.

This article is just a small summary of the personal use process and only discusses technology

No way, a penny, a hero! Not bad, hahaha.

Due to the privacy of the project, the corresponding renderings will not be placed here. PS: In fact, I prefer to put a rendering, at least the first up can see the effect, But confidential, oh ~

I. Key corresponding to umENG manufacturer’s application

Due to the account problem of our company, we cannot collect all manufacturers, which is embarrassing.

After all, boss Chicken has said he doesn’t say anything about things he hasn’t touched.

Therefore, please register and fill in the corresponding manufacturer information as required by UmENG:

Recommend a few good vendor push guidelines:

  • Alliance – Vendor channel integration documentation
  • Mob – Third party vendor push guide

Figure te much, and do not have what difficult point, according to the integration of corresponding platform to provide information for the corresponding manufacturer registration.

Two, Android native integration – Umeng V6.0.5

The reasons for adopting UmENG are as follows:

  • Support vendor push
  • It is convenient for operation partners to view all data directly

1.1 Adding an Alliance Dependency

It is not necessary to create the current application on the Umeng platform in the early stage. Note that the push of the Android version requires the bundle name.

As for the alliance push, it needs to be pushed offline by the vendor, so most of the configuration items are involved. Here, I directly extract a Gradle to avoid the chaos of the master Gradle.

First we add the ummon remote library in the project root directory:

// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { Jcenter repositories {Google () () / / maven here {url 'https://dl.bintray.com/umsdk/release'}} dependencies {/ /... }} AllProjects {repositories {flatDir {dirs 'libs'} Google () jCenter () Maven {url 'https://jitpack.io' maven { url 'https://dl.bintray.com/umsdk/release' } } } task clean(type: Delete) { delete rootProject.buildDir }Copy the code

Then create gradle which umeng depends on under app. Note here that due to our developer account, we failed to integrate all manufacturers:

Dependencies {/ / / / their Allies Push based component library dependencies (must) Push the 605 version must upgrade the new version Common SDK implementation 'com. Umeng. Umsdk: Common: 2.2.2' Implementation 'com. Umeng. Umsdk: utdid: 1.5.2' friends / / au push related dependence (must) implementation 'com. Umeng. Umsdk: push: 6.0.5/6.5.4' Implementation 'com. Umeng. Umsdk: alicloud - HTTPDNS: 1.2.5' implementation 'com. Umeng. Umsdk: alicloud - utils: 1.1.5' Implementation 'com. Umeng. Umsdk: alicloud_beacon: 1.0.1' implementation 'com. Umeng. Umsdk: agoo - accs: 3.3.8.8 - open - fix2' Implementation 'com. Umeng. Umsdk: agoo_networksdk: 2.6.2' implementation 'com. Umeng. Umsdk: agoo_tlog: 3.0.0.17' Implementation 'com.umeng.umsdk: agoo_tnet4Android :3.1.14.9' // ====== vendor integration Start // Implementation Push channel 'com.umeng.umsdk: mium-push :3.7.0' implementation 'com.umeng.umsdk: Mium-umengaccs :1.1.4' // Huawei Push channel implementation 'com. Umeng. Umsdk: huawei - basetb: 2.6.3.306' implementation 'com. Umeng. Umsdk: huawei - pushtb: 2.6.3.306' implementation 'com.umeng.umsdk: Huawei-umengaccs :1.2.4' // Oppo Push implementation 'com.umeng.umsdk:oppo-push:2.0.2' implementation 'com.umeng.umsdk:oppo-umengaccs:1.0.6' // implementation 'com.umeng.umsdk:vivo :2.3.5' implementation 'com. Umeng. Umsdk: vivo - umengaccs: 1.1.0'}Copy the code

Add this dependency to the master Gradle app:

// Apply from: 'umeng_push. gradle'Copy the code

1.2 Initialize alliance push and set notification bar click action

Initialize umENG push in Application and click the notification bar for operation:

Private fun initUMengSettings() {// Initialize SDK mContext? .let { UMConfigure.init( mContext, K_RELEASE_UMENG, it.getString(R.string.code_umeng), UMConfigure.DEVICE_TYPE_PHONE, K_UMENG_SECRET) initUMengPush(it)}} /** * initUMengPush(context: Val pushAgent = pushagent.getInstance (Context) // Register the push service, Every call register method callback the interface pushAgent. Register (mIUmengRegisterCallback) / / Settings. Click on the notification bar open operation pushAgent notificationClickHandler = MNotificationClickHandler initUMengPushSettings (pushAgent)} / * * * * / private registration recommendation val mIUmengRegisterCallback = object : IUmengRegisterCallback { override fun onSuccess(deviceToken: String?) {pwcLog("-------> Registered successfully: deviceToken: --------> $deviceToken")} Override fun onFailure(s: String? , s1: String?) {pwcLog("-------> Failed to register: S - > $s | | | s1 - > $s1 ")}} / * * * click on the notification bar Subsequent operations * / private val mNotificationClickHandler = object: UmengNotificationClickHandler () {/ * * * process users click on the notification bar messages * / override fun dealWithCustomAction (context: context? , uMessage: UMessage?) { super.dealWithCustomAction(context, uMessage) context ?: return uMessage ?: Val openType = extraMap["type"] val openID = ExtraMap ["id"] // */ private fun initUMengPushSettings(pushAgent: PushAgent) {// Set the maximum number of notifications to be displayed. Parameter number can be set to any integer from 0 to 10. If the parameter is 0, the notification is not merged. PushAgent. DisplayNotificationNumber = 0. / / set the client allow voice remind pushAgent notificationPlaySound = MsgConstant. NOTIFICATION_PLAY_SDK_ENABLE / / set the client allow breathing light pushAgent notificationPlayLights = MsgConstant. NOTIFICATION_PLAY_SDK_ENABLE / / set the client allow vibration pushAgent notificationPlayVibrate = Msgconstant. NOTIFICATION_PLAY_SDK_ENABLE // By default, the SDK does not ring or vibrate when receiving notification messages between 23:00 and 7:00. Don't flash pushAgent. SetNoDisturbMode (23, 0, 7, 0) / / set the cooling time Avoided a minute more notification is replaced and pushAgent. MuteDurationSeconds = 600}Copy the code

1.3 Offline push support

Initialize the vendor channel in Application:

/** * @author: heliquan * @date: 2020-05-07 * @desc: vendor push */ class PushSDKBizImpl: AppInterface {private var mContext: Context? = null override fun onCreate(knowledgeCore: KnowledgeCore) { if (mContext == null) { mContext = knowledgeCore.applicationContext } registerPush(knowledgeCore) } private fun registerPush(knowledgeCore: KnowledgeCore) {// MipushRegistar. register(mContext, K_XIAOMI_ID, K_XIAOMI_KEY) // Huawei Push Register Huaweiregister. register(knowledgeCore) // OPPO Push Register Opporegister.register (mContext, K_OPPO_KEY, K_OPPO_SECRET) // Vivo Push register vivoregister.register (mContext)} //. . }Copy the code

Most of the time, we expect that even if the user is not currently using the App, or the current App is killed, the background push message will still want to be received by the foreground.

So if we want to implement offline push, we need to improve the following step:

import com.umeng.message.UmengNotifyClickActivity import org.android.agoo.common.AgooConstants /** * @author Xiaomi, Huawei, etc have put a lot of restrictions on background processes. If you use one-click clearing, the application's channel process is cleared and cannot receive notifications. By accessing the hosted popup function, the above situation can be effectively prevented and the delivery rate of push messages can be increased. */ class PushActivity : UmengNotifyClickActivity() { private val mSelfActivity = PushActivity@ this override fun onMessage(intent: Intent?) {super.onMessage(intent) // Get data AgooConstants.MESSAGE_BODY Val offlinePushBean = intent? .getStringExtra(AgooConstants.MESSAGE_BODY)? .let {gsonutil.fromjson (it, // here we need to format the json object again: TypeToken<OfflinePushBean>() {})} Let {val intent = intent (mSelfActivity, SplashActivity::class.java) intent.putExtra(K_OFFLINE_PUSH_ID, it.id) intent.putExtra(K_OFFLINE_PUSH_TYPE, it.type) intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK startActivity(intent) finish() } } }Copy the code

Of course, the AndroidManifest content of this Activity is attached:

<activity
            android:name=".ui.activity.push.PushActivity"
            android:exported="true"
            android:launchMode="singleTask"
            android:theme="@style/FullScreenTransparentTheme" />
Copy the code

At this point, umeng Android integration push has been completed ~

3. Android native integration – FCM

Google Dad GCM integration is really a thief thoughtful, industry model ah.

I don’t blow, you see ~

Attach FCM address:

  • firebase.google.com/?hl=zh-cn

A few points to note:

  • Remember the test time, KE Xue online, I have encountered such a situation before, the display sent, the result App can not receive, the last reaction, no KE xue online.
  • Domestic mobile phones generally do not have Google Bucket, or Google service, you need to go to the pea pod to download.

3.1 Early Configuration of the FCM

First, inevitably, create projects:

Here’s a rule to note for creating projects:

  • The project name must contain at least four characters including letters, digits, Spaces, and the following characters: -! ‘”

Enter the project name as required and check the acceptance terms:

Add Google Analytics:

Step 3 Check the corresponding terms to complete the project creation:

There is also a small progress during the creation process.

Creation is fast:

3.2 FCM integration

After entering the home page, click the Android icon to start Android access/integration related work:

There are four steps as follows:

  • The first step is to fill in the corresponding package name and SHA-1, otherwise I fill in both.

  • Step 2 Download the configuration file and copy it to the app directory:

  • Step 3 Add the corresponding SDK

  • The fourth step runs validation, which can be ignored

Of course, Google also provides us with one-click configuration, but I tried and failed embarrassingly, but it’s a way to do it. Here’s how:

  • Add Firebase to your Android project

Here’s a diagram to get away from it:

3.3 FCM message processing

Improve dependencies in app build:

/ / FCM implementation 'com. Google. Firebase: firebase - analytics: 17.4.4' / / FCM Message processing implementation 'com. Google. Firebase: firebase - messaging: 20.2.2' / / FCM Message background processing implementation 'com. Google. Firebase: firebase - messaging - directboot: 20.2.2'Copy the code

Then create a Service to handle the FCM message. Here I’m directly using the manual creation of a notification after receiving a Google FCM message:

/** * @author HLQ_Struggle * @date 2020/7/8 * @desc */ class MyFirebaseMessagingService : FirebaseMessagingService() {override fun onMessageReceived(remoteMessage: RemoteMessage) { Log.d(TAG, "From: ${remoteMessage.from}") // Check if message contains a data payload. if (remoteMessage.data.isNotEmpty()) { Log.e(TAG, "Message data payload: Val remoteMessageMap = remotemessage.data sendNotification(${remotemessage.data}") remoteMessageMap["type"].toString(), remoteMessageMap["title"].toString(), remoteMessageMap["content"].toString() ) } remoteMessage.notification?.let { Log.e(TAG, "Message Notification Body: ${it. Body}")}} ${it. Body}") {override fun onNewToken(token: String) { Log.d(TAG, "Refreshed token: $token") sendRegistrationToServer(token)} /** * Private fun sendRegistrationToServer(token) String?) { Log.d(TAG, "sendRegistrationTokenToServer($token)") } /** * Create and show a simple notification containing the received FCM message. * * @param messageBody FCM message body received. */ private fun sendNotification(type: String, title: String, content: String) { val intent = Intent(this, SplashActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) val pendingIntent = PendingIntent.getActivity( this, 0 /* Request code */, intent, PendingIntent.FLAG_ONE_SHOT ) val channelId = getString(R.string.default_notification_channel_id) val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) val notificationBuilder = NotificationCompat.Builder(this, channelId) .setSmallIcon(R.mipmap.ic_launcher_round) .setContentTitle(title) .setContentText(content) .setAutoCancel(true) .setSound(defaultSoundUri) .setContentIntent(pendingIntent) val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager // Since android Oreo notification channel is needed. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( channelId, "Channel human readable title", NotificationManager.IMPORTANCE_DEFAULT ) notificationManager.createNotificationChannel(channel) } notificationManager.notify(0 /* ID of notification */, notificationBuilder.build()) } companion object { private const val TAG = "MyFirebaseMsgService" } }Copy the code

In AndroidManifest, Service:

<service
    android:name=".service.MyFirebaseMessagingService"
    android:directBootAware="true"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
Copy the code

3.4 Other FCM Configurations

Of course, there are also some modifiable contents, such as:

  • icon
  • notification_color

I’m just going to go with the default. Here the official website found, posted, to avoid small partners need to find.

    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@drawable/appicon" />
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/styleTitleOrange" />
    <meta-data
        android:name="firebase_messaging_auto_init_enabled"
        android:value="false" />
    <meta-data
        android:name="firebase_analytics_collection_enabled"
        android:value="false" />
Copy the code

At this point, FCM over ~

4. Flutter Android integrates Mob

This module integrates in a matter of minutes when vendor information is complete

Compared with Flutter access and push, Mob does a good job of directly implementing the Flutter plugin, which greatly facilitates Flutter developers. Please be careful ~ ❤️

Attach Mob plugin address:

  • Pub. Dev/packages/mo…

And the corresponding integration guide for Flutter:

  • Mob.com/wiki/detail…

Mob’s document is really conscience, easy to integrate, super easy to get started, let’s take a look.

2.1 Add Mob plugin dependencies

  • Mobpush_plugin: ^ 1.1.5

2.2 Configuring the Basic Android Environment

First, add the following build file to the root directory:

Dependencies {//... classpath 'com.mob.sdk:MobSDK:+' }Copy the code

Secondly, add the corresponding configuration items to the build file under app. The configuration of Mob here can be separately extracted from a Gradle file, which was originally implemented for implementation, so it is not removed.

Import plug-in:

Apply plugin: 'com.android.application' // Common projects come with this plugin, so you can ignore this apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply plugin: 'com.mob.sdk'Copy the code

Mob push related configuration:

  • Basic appKey and appSecret
  • Vendor keys and other information

The code is as follows:

MobSDK {appKey "Mob provides App Key" appSecret "Mob provides App Secret" // Configure MobPush MobPush {// Configure vendor push (optional, vendor push is not required, optional, DevInfo {// Configure XIAOMI vendors to push XIAOMI {appId" your XIAOMI platform appId" appKey" your XIAOMI platform appKey"} // Configure HUAWEI vendors to push HUAWEI { AppId "Your Huawei platform appId"} // Configure MEIZU vendor push MEIZU {appId" Your MEIZU platform appId" appKey" your MEIZU platform appKey"} // Configure FCM vendor push FCM {// Set the default notification display icon IconRes "@mipmap/ default_IC_launcher "} // Configure OPPO vendor push OPPO {appKey" your OPPO platform appKey" appSecret" your OPPO platform appSecret"} // Configure VIVO vendor push VIVO {appId" Your VIVO platform appId" appKey" your VIVO platform appKey"}}}}Copy the code

Then go to the MainActivity to register, usually no operation, I have written a channel before, attached some code:

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity : FlutterActivity() {

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine) 
    }

}
Copy the code

Finally, how to initialize Mob and receive Mob message push is quite simple. Here are a few points:

  • Since the project requires aliasing with a user name, the operation of adding an alias is also involved. In this case, a state is maintained locally, avoiding multiple aliases.
  • The second requirement is to refresh after receiving the push message, so HERE I directly receive the push message and send the status through eventBus to update the data.

The following is part of the code for your reference only:

Void initMobPush() {getCacheValue(memberInfo). Then ((userCache) {MemberInfoBean MemberInfoBean = memberInfoBeanFromJson(userCache); If (Platform. IsAndroid) {/ / set the privacy agreement authorized state MobpushPlugin. UpdatePrivacyPermissionStatus (true); GetCacheValue (pushAliaState).then((result) {logutil. e(" ===> get Mob registration status "); If (result == null) {logutil. e(" ===> Mob not registered need to register "); MobpushPlugin. SetAlias (memberInfoBean. MemberInfo. Id). Then ((Map < String, dynamic > Map) {LogUtil. E (" = = = > set Mob push alias:  -> res: ${map['res']} "); If (map['errorCode'] == '0') {setCacheValue(bool, pushAliaState, true); }}); }}); / / add push callback MobpushPlugin. AddPushReceiver (_onEvent _onError); }}); } void _onEvent(Object event) {logutil. e(' received message: $event'); eventBus.fire(PushEvent(true)); } void _onError(Object event) {}Copy the code

End

The content of this article is more, mainly to sort out the problems encountered in the previous period of time, in fact, it is not a problem, mainly caused by insufficient preparation of various accounts in the early stage and frequent product adjustment in the later stage.

Basically all attached source code.

A vegetable chicken, welcome you to correct ~

Thanks

  • The aurora push
  • Their Allies to push
  • Mob push