文档管理中心
我的

自定义点击消息动作

场景介绍

关于通知栏消息,您可以自定义点击消息的动作,包括:打开应用首页、打开网页、打开应用自定义页面。

说明
  • 点击动作都是通过跨应用启动Activity的方式来实现,需要保证目标Activity无权限保护。
  • 推送消息时可携带data字段,用户点击消息后可将“data”中的数据传递给应用。“data”仅在NC版本为9.1.1及以上生效。

打开应用自定义页面

打开应用自定义页面可以通过服务端API指定intent或action参数实现,如果同时指定了两个参数,会优先使用intent参数。

指定intent参数

跨应用启动Activity必须使用指定intent方式,通过intent可以携带额外的数据给客户端应用。主要通过如下几步来完成。

  1. intent参数生成。

    Java
    Kotlin
    Intent intent = new Intent(Intent.ACTION_VIEW);
    // Scheme协议(例如:pushscheme://com.huawei.codelabpush/deeplink?)需要您自定义
    intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?"));
    
    // 往intent中添加参数,用户可以根据自己的需求添加参数
    intent.putExtra("name", "abc");
    intent.putExtra("age", 180);
    
    // 应用必须带上该Flag,如果不添加该选项有可能会显示重复的消息
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME);
    
    // 打印出的intentUri值就是设置到推送消息中intent字段的值
    Log.d("intentUri", intentUri);
    val intent = Intent(Intent.ACTION_VIEW)
    // Scheme协议(例如:pushscheme://com.huawei.codelabpush/deeplink?)需要您自定义
    intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?"))
    
    // 往intent中添加参数,用户可以根据自己的需求进行添加参数
    intent.putExtra("name", "abc")
    intent.putExtra("age", 180)
    
    // 应用必须带上该Flag,如果不添加该选项有可能会显示重复的消息
    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
    val intentUri = intent.toUri(Intent.URI_INTENT_SCHEME)
    
    // 打印出的intentUri值就是设置到推送消息中intent字段的值
    Log.d("intentUri", intentUri)

    intent中添加参数的方法:

    • 用“&”相连后添加参数(“name=abc”与“age=180”用“&”相连):
      Java
      Kotlin
      intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?name=abc&age=180"));
      intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?name=abc&age=180"))
    • 直接添加参数:
      Java
      Kotlin
      intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?"));
      intent.putExtra("name", "abc");
      intent.putExtra("age", 180);
      intent.setData(Uri.parse("pushscheme://com.huawei.codelabpush/deeplink?"))
      intent.putExtra("name", "abc")
      intent.putExtra("age", 180)

  2. 应用服务端消息体中指定intent值。

    服务端发送消息请参见发送下行消息。消息体样例:

    {
        "message": {
            "notification": {
                "title": "message title",
                "body": "message body"
            },
            "android": {
                "notification": {
                    "click_action": {
                        "type": 1,
                        "intent": "intent://com.huawei.codelabpush/deeplink?#Intent;scheme=pushscheme;launchFlags=0x04000000;i.age=180;S.name=abc;end"
                    }
                }
            },
            "token": [
                "pushtoken1"
            ]
        }
    }
    说明

    消息体中click_action字段的含义请参见click_action,intent的值必须设置为1中生成的intentUri值。

  3. 客户端应用“AndroidManifest.xml”文件注册待启动的Activity类。

    参照如下配置注册自定义的Activity,其中“host”、“path”、“scheme”需与intent参数生成中协议的配置相对应,否则不能跳转到指定的界面。
    <activity android:name=".DeeplinkActivity">
        <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="com.huawei.codelabpush"
                android:path="/deeplink"
                android:scheme="pushscheme" />
        </intent-filter>
    </activity>

  4. 通过上一步中您自定义Activity中接收数据。

    Java
    Kotlin
    // 此处DeeplinkActivity只是举例
    public class DeeplinkActivity extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_deeplink);
            Intent intent = getIntent();
    
            if (null != intent) {
                // 方法1(参数之间用“&”相连)
                String name1 = intent.getData().getQueryParameter("name");
                int age1 = Integer.parseInt(intent.getData().getQueryParameter("age"));
                // 方法2(intent直接添加参数)
                String name2 = intent.getStringExtra("name");
                int age2 = intent.getIntExtra("age", -1);
                Toast.makeText(this, "name " + name1 + ",age " + age1, Toast.LENGTH_SHORT).show();
            }
        }
    }
    // 此处DeepLinkActivity只是举例
    class DeeplinkActivity : Activity {
        public override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)   
            setContentView(R.layout.activity_deeplink)
            val intent = getIntent()
    
            if (null != intent) {
                // 方法1(参数之间用“&”相连)设置的数据通过如下方式获取
                val uri = intent.data
                val name1 = uri.getQueryParameter("name")
                val age1 = uri.getQueryParameter("age"))
                // 方法2(intent直接添加参数)设置的数据通过如下方式获取
                val name2 = intent.getStringExtra("name")
                val age2 = intent.getIntExtra("age", -1)
                Toast.makeText(this, "name $name1,age $age1", Toast.LENGTH_SHORT).show()
            }
        }
    }

指定action参数

指定的action参数需要与客户端应用“AndroidManifest.xml”文件中注册启动的Activity类中intent-filter标签中设置的action名一致。通过如下步骤实现打开应用自定义页面并携带数据给应用。

  1. 客户端应用“AndroidManifest.xml”文件注册待启动的Activity类。

    <activity android:name=".YourActivity">
        <intent-filter>
            <!-- 'name'值由您自定义 -->
            <action android:name="com.huawei.codelabpush.intent.action.test" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>

  2. 应用服务端消息体中指定action值。

    {
        "message": {
            "data": "{ 'score': '7', 'time': '16:42' }",
            "notification": {
                "title": "message title",
                "body": "message body"
            },
            "android": {
                "data": "{ 'androidData': '7', 'time': '16:42' }",
                "notification": {
                    "click_action": {
                        "type": 1,
                        "action": "com.huawei.codelabpush.intent.action.test"
                    }
                }
            },
            "token": [
                "pushtoken1"
            ]
        }
    }

  3. 通过上一步您自定义Activity类中接收数据。详情请参见打开应用首页中的接收数据部分示例代码。
说明
  • 支持action参数需要EMUI 9.1.0及以上,推送服务应用版本为10.1.0.306及以上。
  • Push SDK 4.0及以上版本支持将action参数与intent参数通过getClickAction和getIntentUri方法直接透传给应用,由应用自己处理。

打开应用首页

打开应用首页并携带数据给应用,开发步骤如下:

  1. 服务端发送通知栏消息。

    在Push Kit服务端提供的REST API的Message结构体中,data字段用于携带数据,click_action字段指定点击行为。如果存在message.android.data字段,会覆盖message.data字段值。服务端发送消息详情请参见发送下行消息。

    消息体样例:

    {
        "message": {
            "data": "{ 'score': '7', 'time': '16:42' }",
            "notification": {
                "title": "message title",
                "body": "message body"
            },
            "android": {
                "data": "{ 'androidData': '7', 'time': '16:42' }",
                "notification": {
                    "click_action": {
                        "type": 3
                    }
                }
            },
            "token": [
                "pushtoken1"
            ]
        }
    }

  2. 客户端应用“AndroidManifest.xml”文件注册主Activity。“AndroidManifest.xml”文件中主Activity声明参考如下,使得用户点击消息后能拉起应用首页。

    <activity android:name=".MainActivity">
        <intent-filter>
            <!-- 'name'值不可改变 -->
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>

  3. 客户端应用通过MainActivity中的onCreate方法接收数据。

    Java
    Kotlin
    public class MainActivity extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            getIntentData(getIntent());
        }
     
        @Override
        public void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
            setIntent(intent);
            getIntentData(intent);
        }
    
        private void getIntentData(Intent intent) {
            if (null != intent) {           
                // 获取data里的值
                Bundle bundle = intent.getExtras();
                if (bundle != null) {
                    for (String key : bundle.keySet()) {
                        String content = bundle.getString(key);
                        Log.i(TAG, "receive data from push, key = " + key + ", content = " + content);
                    }
                }
            } else {
                Log.i(TAG, "intent is null");
            }
        }
    }
    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)        
            setContentView(R.layout.activity_main)        
            getIntentData(intent)    
        }
        
        override fun onNewIntent(intent: Intent?) {
            super.onNewIntent(intent)          
            setIntent(intent)
            getIntentData(intent)            
        }
    
        private fun getIntentData(intent: Intent?) {
            if (null != intent) {
                // 获取data里的值
                val bundle = intent.extras            
                bundle?.keySet()?.forEach { key ->
                    val content = bundle.getString(key)                
                    Log.i(TAG, "receive data from push, key = $key, content = $content")
                }       
            } else {            
                Log.i(TAG, "intent = null")        
            }    
        }
    }
    说明

    为了确保在跳转的页面获取到传输的数据,请在“onNewIntent”方法中调用“setIntent”方法更新intent为跳转页面时传入的intent,并在“onCreate”和“onNewIntent”方法中调用同一个处理数据的方法(本文中以getIntentData方法为例)。