Androidアプリを公開しており、アプリのバックエンドサーバーから HMSプッシュサービス を介して下記のようにプッシュ通知を携帯電話に送信できます。
ただし、アプリ内でプッシュ通知ペイロードにアクセスする方法はどうでしょうか。
これが私が現在プッシュ通知を送信する方法です-
最初に、バックエンドのPOSTを https://login.vmall.com/oauth2/token 以下に送信します。
grant_type=client_credentials&
client_id=MY_APP_ID&
client_secret=MY_APP_SECRET
hMSバックエンドからアクセストークンを正常に取得します。
{
"access_token":"CF1/tI97Ncjts68jeXaUmxjmu8BARYGCzd2UjckO5SphMcFN/EESRlfPqhi37EL7hI2YQgPibPpE7xeCI5ej/A==",
"expires_in":604800
}
次に、私のバックエンドのPOSTを(つまり、{"ver":"1", "appId":"MY_APP_ID"}
のURLエンコード)-
https://api.Push.hicloud.com/pushsend.do?nsp_ctx=
%7B%22ver%22%3A%221%22%2C+%22appId%22%3A%22101130655%22%7D
次のURLエンコードされた本文:
access_token=CF1/tI97Ncjts68jeXaUmxjmu8BARYGCzd2UjckO5SphMcFN/EESRlfPqhi37EL7hI2YQgPibPpE7xeCI5ej/A==
&nsp_svc=openpush.message.api.send
&nsp_ts=1568056994
&device_token_list=%5B%220869268048295821300004507000DE01%22%5D
&payload=%7B%22hps%22%3A%7B%22msg%22%3A%7B%22action%22%3A%7B%22param%22%3A%7B%22appPkgName%22%3A%22de%2Eslova%2Ehuawei%22%7D%2C%22type%22%3A3%7D%2C%22type%22%3A3%2C%22body%22%3A%7B%22title%22%3A%22Alexander%3A+How+to+access+payload%3F%22%2C%22content%22%3A%22Alexander%3A+How+to+access+payload%3F%22%7D%7D%2C%22ext%22%3A%7B%22gid%22%3A86932%7D%7D%7D
ここで、payload
値は(正しいJSON構造であり、「タイプ」3が本当に意味するものであるかどうかはわかりません):
{
"hps": {
"msg": {
"action": {
"param": {
"appPkgName": "de.slova.huawei"
},
"type": 3
},
"type": 3,
"body": {
"title": "Alexander:+How+to+access+payload?",
"content": "Alexander:+How+to+access+payload?"
}
},
"ext": {
"gid": 86932
}
}
}
カスタムの整数「gid」値(アプリの「ゲームID」)を抽出する必要があります。
カスタムレシーバークラスで次のメソッドを定義していますが、それらは呼び出されません(onToken
メソッドを除く-アプリが起動し、非同期でHuaweiPush.HuaweiPushApi.getToken
メソッドを呼び出してHMSから「プッシュトークン」をリクエストした場合):
public class MyReceiver extends PushReceiver {
private final static String BELONG_ID = "belongId";
@Override
public void onToken(Context context, String token, Bundle extras) {
String belongId = extras.getString(BELONG_ID);
Log.d(TAG, "onToken belongId=" + belongId + ", token=" + token);
}
// this method is called for transparent Push messages only NOT CALLED
@Override
public boolean onPushMsg(Context context, byte[] msg, Bundle bundle) {
String content = new String(msg, "UTF-8");
Log.d(TAG, "onPushMsg content=" + content);
return true;
}
// this method is when a notification bar message is clicked NOT CALLED
@Override
public void onEvent(Context context, Event event, Bundle extras) {
if (Event.NOTIFICATION_OPENED.equals(event) || Event.NOTIFICATION_CLICK_BTN.equals(event)) {
int notifyId = extras.getInt(BOUND_KEY.pushNotifyId, 0);
Log.d(TAG, "onEvent notifyId=" + notifyId);
if (notifyId != 0) {
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(notifyId);
}
}
String msg = extras.getString(BOUND_KEY.pushMsgKey);
Log.d(TAG, "onEvent msg=" + msg);
super.onEvent(context, event, extras);
}
// this method is called when Push messages state changes
@Override
public void onPushState(Context context, boolean pushState) {
Log.d(TAG, "onPushState pushState=" + pushState);
}
}
HMSプッシュ通知を介してバックエンドからアプリにカスタム整数値を渡すのを手伝ってください。
(adb Shell setprop log.tag.hwpush VERBOSE
ログを送信した後)Huawei開発者から提供されたNiceヘルプのおかげで、すべてが解決されました-
AndroidManifest.xmlに、Googleのドキュメントで説明されているように、カスタムスキームapp
(任意の文字列にすることができます)を追加しました Create Deep Links to App内容 :
<activity Android:name="de.slova.MainActivity">
<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:scheme="app" Android:Host="slova.de" />
</intent-filter>
</activity>
MainActivity.Javaに、インテントを解析するためのコードを追加しました。
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
// getIntent() should always return the most recent intent
handleIntent(intent);
}
private boolean handleIntent(Intent intent) {
try {
String gidStr = intent.hasExtra("gid") ?
intent.getStringExtra("gid") : // FCM notification
intent.getData().getQueryParameter("gid"); // HMS notification
Log.d(TAG, "handleIntent gidStr=" + gidStr);
int gid = Integer.parseInt(gidStr);
// show the game when user has tapped a Push notification
showGame(gid);
return true;
} catch (Exception ex) {
Log.w(TAG, "handleIntent", ex);
}
return false;
}
ちなみに、アプリの起動時にプッシュ通知をクリアします。
@Override
public void onResume() {
super.onResume();
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancelAll();
}
最後に、ゲームバックエンドで最初にPOSTを実行してトークンを取得します https://login.cloud.huawei.com/oauth2/v2/token
grant_type=client_credentials&
client_secret=MY_APP_SECRET&
client_id=MY_APP_ID
そしてPOST通知 https://Push-api.cloud.huawei.com/v1/MY_APP_ID/messages:send ヘッダーを使用してAuthorization: Bearer MY_TOKEN
およびContent-Type: application/x-www-form-urlencoded
。JSON形式は HMS PushKit docで説明されています。
{
"message": {
"Android": {
"notification": {
"image": "https://slova.de/ws/board3?gid=108250",
"title": "Game 108250",
"body": "Alexander: Test chat msg",
"click_action": {
"type": 1,
"intent": "app://slova.de/?gid=108250"
}
}
},
"token": [
"1234567890123456789000000000DE01"
]
}
}
現在build.gradleで現在使用しているHMS SDKは次のとおりです。
implementation "com.huawei.hms:base:3.0.0.301"
implementation "com.huawei.hms:hwid:3.0.0.301"
implementation "com.huawei.hms:Push:3.0.0.301"
implementation "com.huawei.hms:iap:3.0.0.301"
これは my Word game に適しています。タイトル、本文、小さな画像を含むプッシュ通知が届きます。次に、ユーザーがタップすると、ゲーム#108250が私のアプリによって開かれます。
多分これは役立つでしょう、私はそれを huaweipushv3.html で見つけました、いくつかの理由で中国語バージョンのウェブページでのみです。
//Intent parameter generation mode:
// Scheme protocol(pushscheme://com.huawei.hms.hmsdemo/deeplink?)needs to be customized by developers
intent.setData(Uri.parse("pushscheme://com.huawei.hms.hmsdemo/deeplink?"));
//Add parameters to the intent as required, eg:"name","abc"
intent.putExtra("name", "abc");
intent.putExtra("age", 180);
//the "flag" must be carried
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
String intentUri = intent.toUri(Intent.URI_INTENT_SCHEME);
//The value of intentUri is the value of the intent field in the Push message
Log.d("intentUri", intentUri);
また、開発者は次のいずれかの方法を使用してパラメーターを転送できます。
//the parameters are connected by "&", for example
intent.setData(Uri.parse("pushscheme://com.huawei.hms.hmsdemo/deeplink?name=abc&age=180"));
//directly add parameters to the intent
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("name", "abc");
intent.putExtra("age", 180);
クライアントのAPP AndroidManifest.xmlファイルでユーザー定義アクティビティを宣言します(例:DeepLinkActivity)。
//the value must be consistent with the configuration of the preceding protocol. Otherwise, the specified interface cannot be displayed.
<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.hms.hmsdemo"
Android:path="/deeplink"
Android:scheme="pushscheme" />
</intent-filter>
</activity>
DeepLinkActivityクラスのパラメーターを受け取ります。
Intent intent = getIntent();
//name corresponds to the parameter abc
String name = intent.getStringExtra("name");
//the value of age corresponds to the value of 180
int age = intent.getIntExtra("age", -1);
新しい質問がある場合はメッセージを残してください:)
ペイロードにアクセスするには、HmsMessageServiceクラスを実装し、onMessageReceivedメソッドをオーバーライドする必要があります。 RemoteMessageオブジェクトからペイロードにアクセスできます。
トークンにアクセスするには、onNewTokenメソッドをオーバーライドします
Javaコード
import Android.util.Log;
import com.huawei.hms.Push.HmsMessageService;
import com.huawei.hms.Push.RemoteMessage;
public class HService extends HmsMessageService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if (remoteMessage != null) {
if (!remoteMessage.getData().isEmpty()) {
Log.d("HMS", "Payload" + remoteMessage.getData());
}
if (remoteMessage.getNotification() != null) {
Log.d("HMS", "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
}
}
コトリンコード
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
if (remoteMessage!!.data.isNotEmpty()) {
Log.i(TAG, "Message data payload: " + remoteMessage.data)
}
if (remoteMessage.notification != null) {
Log.i(TAG, "Message Notification Body: " + remoteMessage.notification.body)
}
}
マニフェストにサービスを登録してください。
<service
Android:name=".service.HService"
Android:enabled="true"
Android:exported="true"
Android:permission="${applicationId}.permission.PROCESS_Push_MSG"
Android:process=":HmsMessageService">
<intent-filter>
<action Android:name="com.huawei.Push.action.MESSAGING_EVENT" />
</intent-filter>
</service>
私はこれまでHuaweiのHMSプッシュ通知サービスを使用したことがないので、この答えを少し聞いてください。しかし、私はこの種の問題に遭遇し、何が問題を引き起こしているのかについて知識に基づいた推測をすることができます。
私のロジックが正しいと仮定すると、問題の核は、HuaweiのHMSプッシュ通知がJSONペイロードを使用して送信され、アプリがMyReceiver
クラスのメソッドを介してアクセスできないことです。
この質問 を見ると、JSONデータペイロードにnotification
タグの情報が含まれていると、クラスによって受信されますが、標準のバックグラウンドサービス。
ここでの要点は、データペイロードがバックグラウンドでアクセスをバイパスする構造を使用しているため、データにアクセスするための通常の方法が機能しないことです。そのため、Huaweiがペイロードの送信方法を変更するまで、標準的な方法ではペイロードにアクセスできません。
そうは言っても、次のようなサンプルコードを含む this one のようなガイドがあります。
if (intent.getData().getScheme().equals("rong") && intent.getData().getQueryParameter("isFromPush") != null) {
if (intent.getData().getQueryParameter("isFromPush").equals("true")) {
String options = getIntent().getStringExtra("options"); // 获取 intent 里携带的附加数据
NLog.d(TAG, "options:", options);
try{
JSONObject jsonObject = new JSONObject(options);
if(jsonObject.has("appData")) { // appData 对应的是客户端 sendMessage() 时的参数 pushData
NLog.d(TAG, "pushData:", jsonObject.getString("appData"));
}
...
...
これは、別の依存関係からではありますが、Huaweiがインテントパスを介してすでに採用している方法を使用してペイロードデータにアクセスする方法を概説していますが、これも経験に基づく推測です。