Huawei Flight Booking Application (Crash Service and Push kit) – Part 3 - Huawei Developers

Introduction
Flight booking app allows user to search and book flight. In this article, we will integrate app messaging and analytics into demo flight booking application.
For prerequisite, permission and set up, refer to part 1.
Usecase
1. We will integrate Huawei Crash analytics to monitors and captures your crashes, also it analyzes them, and then groups into manageable issues. And it does this through lightweight SDK that won’t bloat your app. You can integrate Huawei crash analytics SDK with a single line of code before you publish.
2. We will send push notification which establishes communication between cloud and devices. Using HMS push kit, developers can send message to user.
Crash Analytics
1. In order to use Crash service, we need to integrate Analytics kit by adding following code in app-level build.gradle.
Code:
implementation 'com.huawei.hms:hianalytics:5.0.1.301'
2. Enable Analytics in ACG. Refer Service Enabling.
3. Integrate Crash SDK by adding following code in app-level build.gradle.
Code:
implementation 'com.huawei.agconnect:agconnect-crash:1.4.1.300'
4. In onCreate() of MainActivity class, enable crash analytics.
Code:
AGConnectCrash.getInstance().enableCrashCollection(true);
5. To trigger a crash
Code:
AGConnectCrash.getInstance().testIt(this);
Note: Please comment the above code before releasing or publishing the app. It deliberately causes app to crash and just used for testing HMS crash service.
6. To monitor a crash report inApp Gallery Connect, select your app from MyProjects. Select Quality -> Crash on left panel of the screen. Click on Problems.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
7. Setting screen has been designed to enable crash service.
Push Kit
1. Enable push kit in AGC. Refer Service Enabling.
2. Integrate Push kit SDK by adding following code in app-level build.gradle.
Code:
implementation 'com.huawei.hms:push:5.0.1.300'
3. Call getToken() method in onCreate() of MainActivity class. Generated token will be used later in AGC to send notification.
Code:
private void getToken() {
new Thread() {
@Override
public void run() {
try {
// read from agconnect-services.json
String appId = AGConnectServicesConfig.fromContext(MainActivity.this).getString("client/app_id");
String token = HmsInstanceId.getInstance(MainActivity.this).getToken(appId, "HCM");
Log.i(TAG, "get token:" + token);
if(!TextUtils.isEmpty(token)) {
sendRegTokenToServer(token);
}
} catch (ApiException e) {
Log.e(TAG, "get token failed, " + e);
}
}
}.start();
}
private void sendRegTokenToServer(String token) {
Log.i(TAG, "sending token to server. token:" + token);
}
4. To deregister the token.
Code:
new Thread() {
@Override
public void run() {
try {
// read from agconnect-services.json
String appId = AGConnectServicesConfig.fromContext(this).getString("client/app_id");
HmsInstanceId.getInstance(this).deleteToken(appId, "HCM");
Log.i(TAG, "deleteToken success.");
} catch (ApiException e) {
Log.e(TAG, "deleteToken failed." + e);
}
}
}.start();
5. Create a Service which extends HmsMessageService class. Declare it in Manifest.
Code:
<service
android:name=".service.FLightHmsMessageService"
android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT"/>
</intent-filter>
</service>
6. Override onMessageReceivedMethod() to obtain the message data.
Code:
@Override
public void onMessageReceived(RemoteMessage message) {
super.onMessageReceived(message);
Log.i(TAG, "getCollapseKey: " + message.getCollapseKey()
+ "\n getData: " + message.getData()
+ "\n getFrom: " + message.getFrom()
+ "\n getTo: " + message.getTo()
+ "\n getMessageId: " + message.getMessageId()
+ "\n getSendTime: " + message.getSentTime()
+ "\n getMessageType: " + message.getMessageType()
+ "\n getTtl: " + message.getTtl());
RemoteMessage.Notification notification = message.getNotification();
if (notification != null) {
Log.i(TAG, "\n getImageUrl: " + notification.getImageUrl()
+ "\n getTitle: " + notification.getTitle()
+ "\n getTitleLocalizationKey: " + notification.getTitleLocalizationKey()
+ "\n getTitleLocalizationArgs: " + Arrays.toString(notification.getTitleLocalizationArgs())
+ "\n getBody: " + notification.getBody()
+ "\n getBodyLocalizationKey: " + notification.getBodyLocalizationKey()
+ "\n getBodyLocalizationArgs: " + Arrays.toString(notification.getBodyLocalizationArgs())
+ "\n getIcon: " + notification.getIcon()
+ "\n getSound: " + notification.getSound()
+ "\n getTag: " + notification.getTag()
+ "\n getColor: " + notification.getColor()
+ "\n getClickAction: " + notification.getClickAction()
+ "\n getChannelId: " + notification.getChannelId()
+ "\n getLink: " + notification.getLink()
+ "\n getNotifyId: " + notification.getNotifyId());
}
}
7. Log in to AGC, select your project and navigate to Growing -> Push kit. And compose the message for notification. Provide the token which was earlier generated from getToken() method.
Image
Conclusion:
In this article, we learnt how to integrate Huawei crash service and HMS push kit to in application.
For detailed guide, refer to
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/service-introduction-0000001050040060
https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-crash-introduction

Related

How to know more about the client with Huawei Push Kit?

{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Huawei Push Kit is a messaging service provided by Huawei for developers. It establishes a communication channel between the cloud and devices. By using Huawei Push Kit, developers can send the latest messages to users. This helps developers maintain closer ties with users and increases user awareness and activity. User can tap the message displayed in the notification bar of the device and can open the corresponding app and view more details. Huawei Push Kit is already available more than 200+ countries and regions. It offers the capacity of sending 10 million messages per second from the server, delivering 99% of them and providing real time push reports ultimately helping improve the DAU of your apps.
Today in this article we are going to see how to integrate HMS core Push kit into your apps.
Prerequisite
1) Must have a Huawei Developer Account.
2) Must have a Huawei phone with HMS 4.0.0.300 or later
3) Must have a laptop or desktop with Android Studio , Jdk 1.8, SDK platform 26 and Gradle 4.6 installed.
Things Need To Be Done
1) First we need to create a project in android studio.
2) Get the SHA Key. For getting the SHA key we can refer to this article.
3) Create an app in the Huawei app gallery connect.
4) Enable push kit setting in Manage APIs section.
5) Provide the SHA Key in App Information Section.
6) Provide storage location.
7) Under Develop tab, go to Growing > Push and select service status Enable.
8) After completing all the above points we need to download the agconnect-services.json from App Information Section. Copy and paste the Json file in the app folder of the android project.
9) Copy and paste the below maven url inside the repositories of buildscript and allprojects ( project build.gradle file )
maven { url 'http://developer.huawei.com/repo/' }
10) Copy and paste the below plugin in the app build.gradle file
apply plugin: 'com.huawei.agconnect'
11) Now Sync the gradle.
Let’s Code
Service Class
First we need to configure app AndroidManifest.xml file. Before we go ahead and providing configuration to the AndroidManifest.xml file, we need to create a Push service class which will extend HmsMessageService class.
This service class will provide us with two callback methods i.e. onNewToken() and onMessageReceived(). In onNewToken() method we will receive the token here and onMessageReceived() method we will receive the data messages sent by Huawei Push.
Code:
public class MyPushService extends HmsMessageService {
private static final String TAG = "PushDemoLog";
@Override
public void onNewToken(String token) {
super.onNewToken(token);
Log.i(TAG, "receive token:" + token);
}
@Override
public void onMessageReceived(RemoteMessage message) {
super.onMessageReceived(message);
Log.i(TAG, "getCollapseKey: " + message.getCollapseKey()
+ "\n getData: " + message.getData()
+ "\n getFrom: " + message.getFrom()
+ "\n getTo: " + message.getTo()
+ "\n getMessageId: " + message.getMessageId()
+ "\n getSendTime: " + message.getSentTime()
+ "\n getMessageType: " + message.getMessageType()
+ "\n getTtl: " + message.getTtl());
RemoteMessage.Notification notification = message.getNotification();
if (notification != null) {
Log.i(TAG, "\n getImageUrl: " + notification.getImageUrl()
+ "\n getTitle: " + notification.getTitle()
+ "\n getTitleLocalizationKey: " + notification.getTitleLocalizationKey()
+ "\n getTitleLocalizationArgs: " + Arrays.toString(notification.getTitleLocalizationArgs())
+ "\n getBody: " + notification.getBody()
+ "\n getBodyLocalizationKey: " + notification.getBodyLocalizationKey()
+ "\n getBodyLocalizationArgs: " + Arrays.toString(notification.getBodyLocalizationArgs())
+ "\n getIcon: " + notification.getIcon()
+ "\n getSound: " + notification.getSound()
+ "\n getTag: " + notification.getTag()
+ "\n getColor: " + notification.getColor()
+ "\n getClickAction: " + notification.getClickAction()
+ "\n getChannelId: " + notification.getChannelId()
+ "\n getLink: " + notification.getLink()
+ "\n getNotifyId: " + notification.getNotifyId());
}
}
}
This service need to be mention or configure in the AndroidManifest.xml file. Copy and paste the below code after </activity> tag and before </application> tag.
Code:
<service
android:name=".MyPushService"
android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT" />
</intent-filter>
</service>
To get the token from the HMS Push kit we need to write the following code in the Activity class (it could be any activity class example MainActivity).
Code:
private void getToken(){
new Thread() {
@Override
public void run() {
try {
String appId = AGConnectServicesConfig.fromContext(MainActivity.this).getString("client/app_id");
pushtoken = HmsInstanceId.getInstance(MainActivity.this).getToken(appId, "HCM");
if(!TextUtils.isEmpty(pushtoken)) {
Log.i(TAG, "get token:" + pushtoken);
showLog(pushtoken);
}
} catch (Exception e) {
Log.i(TAG,"getToken failed, " + e);
}
}
}.start();
}
On the log we will be able to see the token as shown below
Turn Off / On Notification
Suppose user doesn’t want any notification from your app, we can achieve this functionality by simply calling HmsMessaging class. This class contain two methods turnOnPush() and turnOffPush(). Below you will find the code to turn off / on notification. By default the notification message is enable.
Code:
private void turnOnNotification(){
HmsMessaging.getInstance(this).turnOnPush().addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
Log.i(TAG, "turnOnPush Complete");
} else {
Log.e(TAG, "turnOnPush failed: ret=" + task.getException().getMessage());
}
}
});
}
private void turnOffNotification(){
HmsMessaging.getInstance(this).turnOffPush().addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
Log.i(TAG, "turnOnPush Complete");
} else {
Log.e(TAG, "turnOnPush failed: ret=" + task.getException().getMessage());
}
}
});
}
Sending Notification
To send notification message we need to go to AGC and select My apps. Under My apps we will find the app which we have created to get notification. Select the app go to Operate > Promotion > Push. Select Add Notification button. Provide details as shown below and click Test effect button which will ask for token. Put the token and select okay.
We have a second part of this article i.e. HMS PUSH KIT SERVER SIDE ( PART 2 ). I would recommend you to go for it. It will help you to have a clear picture of HMS Push Kit.
That’s it
For more information like this, you can visit https://forums.developer.huawei.com/forumPortal/en/home

HUAWEI Game Service Implementation : Leaderboard

More information like this, you can visit HUAWEI Developer Forum​
Introduction
Huawei Game service provides a centralized place for you to manage game services and configure metadata for authorizing and authenticating your game. Using Huawei game service, developer can access range of capabilities to help develop your games more efficiently.
Features
1. Developers can promote their game efficiently and quickly.
2. Developers can easily build the foundation of game by implementing features like achievements and events.
3. Developers can perform in-depth operations tailored to their game and their users.
In this article, we will implement leaderboard feature provided by Huawei game service in Tic tac toe game.
To understand event feature provided by Huawei game service, please refer my last article.
Prerequisites
1. Developer has created an application on App Gallery Connect. Follow Creating an App.
2. Integrating app gallery connect SDK. Please refer to AppGallery Connect Service Getting Started.
3. Developer has integrated Huawei Account kit. Follow this tutorial to integrate account kit.
4. HUAWEI mobile phone with HMS Core 4.0.0.300 or later installed.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Setup:
1. Enable Huawei Game service in Manage APIS. Please refer to Service Enabling.
2. Add appgallery connect plug-in in app-level build.gradle
Code:
apply plugin: 'com.huawei.agconnect'
3. Add following dependencies in app-level build.gradle and click on Sync Now and wait till synchronization is done.
Code:
dependencies {
implementation 'com.huawei.hms:base:4.0.4.301'
implementation 'com.huawei.hms:hwid:4.0.4.300'
implementation 'com.huawei.hms:iap:4.0.4.300'
implementation 'com.huawei.hms:game:4.0.3.301'
}
Initialization
Once Initial set up is done, let’s implement Huawei game service in Tic tac toe game
1. Add the following code in onCreate() method of Application class.
Code:
public class GameServiceApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HuaweiMobileServicesUtil.setApplication(this);
}
@Override
public void onTerminate() {
super.onTerminate();
}
}
2. To initialize the game
Code:
private void init() {
JosAppsClient appsClient = JosApps.getJosAppsClient(this, null);
appsClient.init();
Log.i(TAG, "initialization success");
}
Sign in
1. When app is launched, Huawei sign-in page is displayed.
2. User enters Huawei Huawei ID and password to sign in.
3. After a successful sign in, the app obtains player information corresponding to Huawei ID.
Please refer to this article for sign in implementation.
Game Leaderboards
The term Leaderboard is often used in gaming platform to signify rank among people who play various titles. Players can be ranked against other players based on their skills. Overall, leaderboards can provide an incentive for players to improve as they give many a sense of superiority or accomplishment.
Creating a Leaderboard in AppGallery Connect
1. Sign in to AppGallery Connect and select My apps.
2. Select an app from the app list to create an event.
3. Click the Operate tab and go to Products > Leaderboard. Click Create.
4. Configure the leaderboard information and click Save.
5. Check your leaderboard ID on the event list and properly save the ID for development.
Development
To initialize leaderboard , we need to obtain instance of RankingsClient
Code:
RankingsClient client = Games.getRankingsClient(this, mAuthHuaweiId);
mAuthHuaweiId is obtained during sign in.
2. To allow player's score to be displayed on leaderboard, call setRankingSwitchStauts() method, and pass 1 as parameter. the player's leaderboard switch is set to 0
Code:
private void enableRankingSwitchStatus (int status) {
Task<Integer> task = rankingsClient.setRankingSwitchStatus(status);
task.addOnSuccessListener(new OnSuccessListener<Integer>() {
@Override
public void onSuccess(Integer statusValue) {
// success to set the value,the server will reponse the latest value.
Log.d(TAG, "setRankingSwitchStatus success : " +statusValue) ;
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// errCode information
if (e instanceof ApiException) {
String result = "Err Code:" + ((ApiException) e).getStatusCode();
Log.e(TAG , "setRankingSwitchStatus error : " + result);
}
}
});
}
3. To check the leaderboard switch settings
Code:
Task<Integer> task = rankingsClient.getRankingSwitchStatus();
task.addOnSuccessListener(new OnSuccessListener<Integer>() {
@Override
public void onSuccess(Integer statusValue) {
//success to get the latest value
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// errCode information
if (e instanceof ApiException) {
String result = "err :" + ((ApiException) e).getStatusCode();
}
}
});
onSuccess() will return either 0 or 1. 0 indicates leaderboard is not enabled for players. If 1 is returned, your game submits the updated score of the player.
4. To submit the score
Code:
private void submitRanking(int score) {
rankingsClient.submitRankingScore(LEADERBOARD_ID, score);
}
LEADERBOARD_ID indicates the ID of the leaderboard which is generated while defining the event in AppGallery connect.
5. To obtain leaderboard, we need to call getCurrentRankingSummary(id, isRealTime)
Code:
Task<Ranking> task = rankingsClient.getRankingSummary(id, isRealTime);
task.addOnSuccessListener(new OnSuccessListener<Ranking>() {
@Override
public void onSuccess(Ranking s) {
showLog( " success. ");
if (task.getResult() == null) {
Log.d(TAG, "Ranking result is null");
tvLeaderboard.setText("Ranking result is null");
return;
}
Ranking ranking = task.getResult();
StringBuffer buffer = new StringBuffer();
buffer.append("-------Ranking-------\n");
if (ranking == null) {
buffer.append("ranking is null");
} else {
buffer.append("\n DisplayName:" + ranking.getRankingDisplayName());
iv.setVisibility(View.VISIBLE);
Glide.with(this).load(ranking.getRankingImageUri()).into(iv);
buffer.append("\n ScoreOrder:" + ranking.getRankingScoreOrder());
if (ranking.getRankingVariants() != null) {
buffer.append("\n Variants.size:" + ranking.getRankingVariants().size());
if (ranking.getRankingVariants().size() > 0) {
showRankingVariant(ranking.getRankingVariants() , buffer);
}
}
}
}
});
isRealTime is a Boolean which indicates whether to obtain result from huawei server (true) or local cache.
id indicates the ID of the leaderboard which is generated while defining the event in AppGallery connect.
6. To display only specified number of top rankings, we need to call getRankingTopScores(id, timeDimension, maxResult, offsetPlayerRank, pageDirection)
Code:
Task<RankingsClient.RankingScores> task
= rankingsClient.getRankingTopScores(id, timeDimension, maxResults, offsetPlayerRank, pageDirection);
task.addOnSuccessListener(new OnSuccessListener<RankingsClient.RankingScores>() {
@Override
public void onSuccess(RankingsClient.RankingScores s) {
showLog(" success. ");
Ranking ranking = task.getResult().getRanking();
List<RankingScore> scoresBuffer = task.getResult().getRankingScores();
for (int i = 0; i < scoresBuffer.size(); i++) {
printRankingScore(scoresBuffer.get(i), i);
}
}
});
private void printRankingScore(RankingScore s, int index) {
StringBuffer buffer = new StringBuffer();
buffer.append("------RankingScore " + index + "------\n");
if (s == null) {
buffer.append("rankingScore is null\n");
return;
}
String displayScore = s.getRankingDisplayScore();
buffer.append(" DisplayScore: " + displayScore).append("\n");
buffer.append(" TimeDimension: " + s.getTimeDimension()).append("\n");
buffer.append(" RawPlayerScore: " + s.getPlayerRawScore()).append("\n");
buffer.append(" PlayerRank: " + s.getPlayerRank()).append("\n");
String displayRank = s.getDisplayRank();
buffer.append(" getDisplayRank: " + displayRank).append("\n");
buffer.append(" ScoreTag: " + s.getScoreTips()).append("\n");
buffer.append(" updateTime: " + s.getScoreTimestamp()).append("\n");
String playerDisplayName = s.getScoreOwnerDisplayName();
buffer.append(" PlayerDisplayName: " + playerDisplayName).append("\n");
buffer.append(" PlayerHiResImageUri: " + s.getScoreOwnerHiIconUri()).append("\n");
buffer.append(" PlayerIconImageUri: " + s.getScoreOwnerIconUri()).append("\n\n");
Log.d(TAG , buffer.toString());
tvLeaderboard.setText(buffer.toString());
}
id indicates the ID of the leaderboard which is generated while defining the event in AppGallery connect.
timeDimension indicates time frame. Provide 0 for daily, 1 for weekly, 2 for all time .
maxResults indicates maximum number of records on each page. The value is an integer ranging from 1 to 21.
offsetPlayerRank specifies rank by offsetPlayerRank.For example, if offsetPlayerRank is set to 5 and pageDirection is set to 0, one additional page of scores starting from the fifth rank downwards will be loaded.
pageDirection indicates data obtaing direction. Currently 0 is supported, indicating data of next page is obtained.
7. To display the score of current player , we need to call getCurrentPlayerRankingScore(id, timeDimension)
Code:
Task<RankingScore> task = rankingsClient.getCurrentPlayerRankingScore(id, timeDimension);
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
showLog(" failure. exception: " + e);
}
});
task.addOnSuccessListener(new OnSuccessListener<RankingScore>() {
@Override
public void onSuccess(RankingScore s) {
showLog(" success. ");
StringBuffer buffer = new StringBuffer();
if (task.getResult() == null) {
buffer.append("RankingScore result is null");
return;
}
buffer.append("=======RankingScore=======\n");
RankingScore s = task.getResult();
printRankingScore(s, 0);
}
});
task.addOnCanceledListener(new OnCanceledListener() {
@Override
public void onCanceled() {
showLog(method + " canceled. ");
}
});
private void printRankingScore(RankingScore s, int index) {
StringBuffer buffer = new StringBuffer();
buffer.append("------RankingScore " + index + "------\n");
if (s == null) {
buffer.append("rankingScore is null\n");
return;
}
String displayScore = s.getRankingDisplayScore();
buffer.append(" DisplayScore: " + displayScore).append("\n");
buffer.append(" TimeDimension: " + s.getTimeDimension()).append("\n");
buffer.append(" RawPlayerScore: " + s.getPlayerRawScore()).append("\n");
buffer.append(" PlayerRank: " + s.getPlayerRank()).append("\n");
String displayRank = s.getDisplayRank();
buffer.append(" getDisplayRank: " + displayRank).append("\n");
buffer.append(" ScoreTag: " + s.getScoreTips()).append("\n");
buffer.append(" updateTime: " + s.getScoreTimestamp()).append("\n");
String playerDisplayName = s.getScoreOwnerDisplayName();
buffer.append(" PlayerDisplayName: " + playerDisplayName).append("\n");
buffer.append(" PlayerHiResImageUri: " + s.getScoreOwnerHiIconUri()).append("\n");
buffer.append(" PlayerIconImageUri: " + s.getScoreOwnerIconUri()).append("\n\n");
Log.d(TAG , buffer.toString());
tvLeaderboard.setText(buffer.toString());
}
id indicates the ID of the leaderboard which is generated while defining the event in AppGallery connect.
timeDimension indicates time frame. Provide 0 for daily, 1 for weekly, 2 for all time .
Screenshots
Thank you so much for such a nice information. I think, that will be very helpful for developers who are going to use Huawei Game Service

Huawei In App Purchase integration in Unity app using Unity UDP Package

The purpose of this article is how to use Huawei in App Purchase integration in Unity app using Unity UDP. Here we are going to create a sample project in Unity with the help of UDP Package.
In this section, following are covered:
1. How to create new project in UDP Console?
2. How to Import UDP Package?
3. How to link UDP Console Project in unity editor and how to create IAP Products?
4. How to Implement UDP IAP in Client Side?
5. How to Configure IAP in Huawei AGC Console?
6. How to Link UDP Console with Huawei AGC Console?
1. How to create new project in UDP Console?
a) Navigate to below URL and click to sign in to access UDP console
https://distribute.dashboard.unity.com/
b) To create new game, navigate to My Games > Create New Game (You can create a game on the UDP console first, and later link it to an actual UDP project in unity)
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
c) Enter required fields in Edit Game Information and click SAVE.
d) Copy the client id from the Integration Information panel of the Game Info section, in the UDP console.
2. How to Import UDP Package?
a) Navigate to the unity editor and import Unity Distribution Portal (UDP) from asset store.
b) Once it is imported you can see the sample IAP Client side code which contains all the basic modules like initialization, purchase, query, consume etc.
3. How to link UDP Console Project in unity editor and How to create IAP Products?
a) Now we need to link UDP project with Unity (Window > Unity Distribution Portal > Settings). Paste the client id which you copied from UDP console and link it to UDP Client.
b) Once your Unity project is linked to a UDP client, the UDP Settings inspector loads more settings (like IAP Catalog, UDP Sandbox test account, push, pull).
c) Now you can add and define IAP products in the IAP Catalog section of the UDP Settings. The Pull and Push buttons in the top section of the UDP Settings window sync your IAP Catalog with the UDP server. You can add sandbox test account in UDP Sandbox Test Accounts.
d) Once IAP details are configured and pushed. You can see the IAP details in Udp Console.
4. How to Implement UDP IAP in Client Side?
a) Now it’s time to implement client side logic.
Please refer the below link and sample code in Unity Editor (Projects > Assets > UDP > Sample > Scripts > UDPSampleScript.cs) which I referred for the implementation.
URL: https://docs.unity3d.com/Packages/[email protected]/manual/Implementing-UDP-IAP-on-the-client-side.html
b) Now create buttons and script file in unity editor.
c) Add the below code to the Script and link the above buttons to the correct On Click listeners in Script.
Code:
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using UnityEngine.UDP;
public class NewBehaviourScript : MonoBehaviour
{
int n;
public Text myText1;
InitListener m_InitListener;
PurchaseListener m_PurchaseListener;
private static bool m_ConsumeOnPurchase;
private static bool m_ConsumeOnQuery;
private static bool m_Initialized;
public void OnInit()
{
Debug.Log("Oninitialize");
m_InitListener = new InitListener();
m_PurchaseListener = new PurchaseListener();
m_Initialized = false;
StoreService.Initialize(m_InitListener);
}
public void OnPurchase()
{
if (!m_Initialized)
{
Debug.Log("Please Initialize first");
return;
}
string prodcutId = "test_1";
Debug.Log("Buy button is clicked.");
m_ConsumeOnPurchase = false;
Debug.Log("test_1 will be bought");
StoreService.Purchase(prodcutId, "payload", m_PurchaseListener);
}
public void OnPurchaseNonConsumable()
{
if (!m_Initialized)
{
Debug.Log("Please Initialize first");
return;
}
string prodcutId = "test_2";
Debug.Log("Buy button is clicked.");
m_ConsumeOnPurchase = false;
Debug.Log("test_2 will be bought");
StoreService.Purchase(prodcutId, "payload", m_PurchaseListener);
}
public void OnBuyConsume()
{
if (!m_Initialized)
{
Debug.Log("Please Initialize first");
return;
}
string prodcutId = "test_1";
Debug.Log("Buy&Consume button is clicked.");
m_ConsumeOnPurchase = true;
StoreService.Purchase(prodcutId, "payload2", m_PurchaseListener);
}
List<string> productIds = new List<string> { "test_1", "test_2" };
public void OnQueryButton()
{
if (!m_Initialized)
{
Debug.Log("Please Initialize first");
return;
}
m_ConsumeOnQuery = false;
Debug.Log("Query button is clicked.");
StoreService.QueryInventory(productIds, m_PurchaseListener);
}
public void OnQueryConsumeButton()
{
if (!m_Initialized)
{
Debug.Log("Please Initialize first");
return;
}
m_ConsumeOnQuery = true;
Debug.Log("QueryConsume button is clicked.");
StoreService.QueryInventory(productIds, m_PurchaseListener);
}
public class InitListener : IInitListener
{
public void OnInitialized(UserInfo userInfo)
{
Debug.Log("[Game]On Initialized suceeded");
m_Initialized = true;
}
public void OnInitializeFailed(string message)
{
Debug.Log("[Game]OnInitializeFailed: " + message);
}
}
public class PurchaseListener : IPurchaseListener
{
public void OnPurchase(PurchaseInfo purchaseInfo)
{
string message = string.Format(
"[Game] Purchase Succeeded, productId: {0}, cpOrderId: {1}, developerPayload: {2}, storeJson: {3}",
purchaseInfo.ProductId, purchaseInfo.GameOrderId, purchaseInfo.DeveloperPayload,
purchaseInfo.StorePurchaseJsonString);
Debug.Log(message);
// Show(message);
/*
* If the product is consumable, consume it and deliver the product in OnPurchaseConsume().
* Otherwise, deliver the product here.
*/
if (m_ConsumeOnPurchase)
{
Debug.Log("Consuming");
StoreService.ConsumePurchase(purchaseInfo, this);
}
}
public void OnPurchaseFailed(string message, PurchaseInfo purchaseInfo)
{
Debug.Log("Purchase Failed: " + message);
}
public void OnPurchaseRepeated(string productCode)
{
throw new System.NotImplementedException();
}
public void OnPurchaseConsume(PurchaseInfo purchaseInfo)
{
Debug.Log("Consume success: " + purchaseInfo.ProductId);
}
public void OnPurchaseConsumeFailed(string message, PurchaseInfo purchaseInfo)
{
Debug.Log("Consume Failed: " + message);
}
public void OnQueryInventory(Inventory inventory)
{
Debug.Log("OnQueryInventory");
Debug.Log("[Game] Product List: ");
string message = "Product List: \n";
foreach (KeyValuePair<string, ProductInfo> productInfo in inventory.GetProductDictionary())
{
Debug.Log("[Game] Returned product: " + productInfo.Key + " " + productInfo.Value.ProductId);
message += string.Format("{0}:\n" +
"\tTitle: {1}\n" +
"\tDescription: {2}\n" +
"\tConsumable: {3}\n" +
"\tPrice: {4}\n" +
"\tCurrency: {5}\n" +
"\tPriceAmountMicros: {6}\n" +
"\tItemType: {7}\n",
productInfo.Key,
productInfo.Value.Title,
productInfo.Value.Description,
productInfo.Value.Consumable,
productInfo.Value.Price,
productInfo.Value.Currency,
productInfo.Value.PriceAmountMicros,
productInfo.Value.ItemType
);
}
message += "\nPurchase List: \n";
foreach (KeyValuePair<string, PurchaseInfo> purchaseInfo in inventory.GetPurchaseDictionary())
{
Debug.Log("[Game] Returned purchase: " + purchaseInfo.Key);
message += string.Format("{0}\n", purchaseInfo.Value.ProductId);
}
if (m_ConsumeOnQuery)
{
StoreService.ConsumePurchase(inventory.GetPurchaseList(), this);
}
}
public void OnQueryInventoryFailed(string message)
{
Debug.Log("OnQueryInventory Failed: " + message);
}
}
}
For more information, you can visit https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201366685963750355&fid=0101187876626530001

Expert: Courier App MVVM Jetpack (HMS Push Kit) in Android using Kotlin- Part-2

Overview
In this article, I will create a Courier android application using Kotlin in which I will integrate HMS Core kits such as HMS Account and AuthService Kit.
We have integrated HMS Account and AuthService Kit in part-1 of this series. Kindly go through the link below-
// pls add part-1 link
App will make use of android MVVM clean architecture using Jetpack components such as DataBinding, AndroidViewModel, Observer, LiveData and much more.
In this article, we are going to implement DataBinding using Observable pattern.
Huawei Push Kit Introduction
Push Kit is a messaging service provided by Huawei for developers. Push Kit establishes a messaging channel from the cloud to devices. By integrating HUAWEI Push Kit, developers can send messages to apps on users’ devices in real time. Push Kit helps developers rapidly to reach the target audience. Push notification can be sent to everyone or to a specific person individually. For send notification, user’s token is required. You can send messages to a device group or specific user. Push Kit has two different notification type. Text only style (Shows longer text messages) and big picture style (Shows large text and image messages).
Prerequisite
Huawei Phone EMUI 3.0 or later.
Non-Huawei phones Android 4.4 or later (API level 19 or higher).
HMS Core APK 4.0.0.300 or later
Android Studio
AppGallery Account
App Gallery Integration process
Sign In and Create or Choose a project on AppGallery Connect portal.
Navigate to Project settings and download the configuration file.
Navigate to General Information, and then provide Data Storage location.
App Development
Add Required Dependencies:
Launch Android studio and create a new project. Once the project is ready.
Navigate to the Gradle scripts folder and open build.gradle (module: app).
In the same build.gradle file, add the lifecycle library to your dependencies. This library helps to connect the UI to a ViewModel and LiveData.
Add following dependency for HMS Push Kits
Navigate to the Gradle scripts folder and open build.gradle (project: app).
Code Implementation
Created following package model, push, viewmodel.
Model: In your primary folder, create a new package and name it model.
Java:
package com.hms.corrierapp.push
import android.util.Log
import com.huawei.hms.push.HmsMessageService
import com.huawei.hms.push.RemoteMessage
import java.util.*
class PushService : HmsMessageService() {
private val TAG = "PushService"
override fun onNewToken(token: String?) {
super.onNewToken(token)
Log.i(TAG, "Receive Token : $token");
}
override fun onMessageReceived(message: RemoteMessage?) {
super.onMessageReceived(message)
Log.i(
TAG, "getCollapseKey: " + message?.collapseKey
+ "\n getData: " + message?.data
+ "\n getFrom: " + message?.from
+ "\n getTo: " + message?.to
+ "\n getMessageId: " + message?.messageId
+ "\n getSendTime: " + message?.sentTime
+ "\n getMessageType: " + message?.messageType
+ "\n getTtl: " + message?.ttl
)
val notification: RemoteMessage.Notification = message!!.notification
Log.i(
TAG, "\n getImageUrl: " + notification.imageUrl
+ "\n getTitle: " + notification.title
+ "\n getTitleLocalizationKey: " + notification.titleLocalizationKey
+ "\n getTitleLocalizationArgs: " + Arrays.toString(notification.titleLocalizationArgs)
+ "\n getBody: " + notification.body
+ "\n getBodyLocalizationKey: " + notification.bodyLocalizationKey
+ "\n getBodyLocalizationArgs: " + Arrays.toString(notification.bodyLocalizationArgs)
+ "\n getIcon: " + notification.icon
+ "\n getSound: " + notification.sound
+ "\n getTag: " + notification.tag
+ "\n getColor: " + notification.color
+ "\n getClickAction: " + notification.clickAction
+ "\n getChannelId: " + notification.channelId
+ "\n getLink: " + notification.link
+ "\n getNotifyId: " + notification.notifyId
)
}
}
Java:
package com.hms.corrierapp.push
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
class AccessTokenClient {
companion object{
private const val TIMEOUT: Long = 500000
fun getClient() : Retrofit {
val logginInterceptor = HttpLoggingInterceptor()
logginInterceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.connectTimeout(TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(TIMEOUT,TimeUnit.MICROSECONDS)
.readTimeout(TIMEOUT, TimeUnit.SECONDS)
.addInterceptor(logginInterceptor).build()
return Retrofit.Builder()
.baseUrl("https://oauth-login.cloud.huawei.com/").client(client)
.addConverterFactory(GsonConverterFactory.create()).build()
}
}
}
Java:
package com.hms.corrierapp.push
import retrofit2.Call
import retrofit2.http.Field
import retrofit2.http.FormUrlEncoded
import retrofit2.http.Headers
import retrofit2.http.POST
interface AccessTokenInterface {
@FormUrlEncoded
@Headers("Content-Type:application/x-www-form-urlencoded; charset=UTF-8")
@POST("oauth2/v3/token")
fun createAccessToken(
@Field("grant_type") grant_type : String,
@Field("client_secret") client_secret : String,
@Field("client_id") client_id : String) : Call<AccessTokenModel>
}
App Build Result
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Tips and Tricks
Identity Kit displays the HUAWEI ID registration or sign-in page first. The user can use the functions provided by Identity Kit only after signing in using a registered HUAWEI ID.
Push Kit supports cross-region messaging, but the messaging performance may be affected. To minimize cross-region messaging, it is recommended that you deploy servers in regions where users gather.
Conclusion
In this article, we have learned how to integrate Huawei ID and Push Kit in Android application. After completely read this article user can easily implement Huawei ID and Client Side Push Notification in the Courier android application using Kotlin.
Thanks for reading this article. Be sure to like and comment to this article, if you found it helpful. It means a lot to me.
References
HMS Docs:
https://developer.huawei.com/consum.../HMSCore-Guides/introduction-0000001050048870
Document
developer.huawei.com
Push Kit Training Video:
https://developer.huawei.com/consumer/en/training/course/video/101583005582480166

Practice on Pushing Messages to Devices of Different Manufacturers

Push messaging, with the proliferation of mobile Internet, has become a very effective way for mobile apps to achieve business success. It improves user engagement and stickiness by allowing developers to send messages to a wide range of users in a wide range of scenarios: taking the subway or bus, having a meal in a restaurant, having a chat... you name it. No matter what the scenario is, a push message is always a great helper for you to directly "talk" to your users, and for your users to know something informative.
Such great benefits brought by push messages, however, can be dampened by a challenge: the variety of mobile phone manufacturers. This is because usually each manufacturer has their own push messaging channels, which increases the difficulty for uniformly sending your app's push messages to mobile phones of different manufacturers. Of course there is an easy solution for this: sending your push messages to mobile phones of only one manufacturer, but this can limit your user base and prevent you from obtaining your desired messaging effects.
Then this well explains why we developers usually need to find a solution for our apps to be able to push their messages to devices of different brands.
I don't know about you, but the solution I found for my app is HMS Core Push Kit. Going on, I will demonstrate how I have integrated this kit and used its ability to aggregate third-party push messaging channels to implement push messaging on mobile phones made by different manufacturers, expecting greater user engagement and stickiness. Let's move on to the implementation.
Preparations​Before integrating the SDK, make the following preparations:
1. Sign in to the push messaging platform of a specific manufacturer, create a project and app on the platform, and save the JSON key file of the project. (The requirements may vary depending on the manufacturer, so refer to the specific manufacturer's documentation to learn about their requirements.)
2. Configure app information in AppGallery Connet, but use the following build dependency instead when configuring the build dependencies:
Code:
dependencies {
implementation 'com.huawei.hms:push-fcm:6.3.0.304'
}
3. On the platform mentioned in the previous step, click My projects, find the app in the project, and go to Grow > Push Kit > Settings. On the page displayed, click Enable next to Configure other Android-based push, and then copy the key in the saved JSON key file and paste it in the Authentication parameters text box.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
​Development Procedure​Now, let's go through the development procedure.
1. Disable the automatic initialization of the SDK.
To do so, open the AndroidManifest.xml file, and add the <meta-data> element to the <application> element. Note that in the element, the name parameter has a fixed value of push_kit_auto_init_enabled. As for the value parameter, you can set it to false, indicating that the automatic initialization is disabled.
Code:
<manifest ...>
...
<application ...>
<meta-data
android:name="push_kit_auto_init_enabled"
android:value="false"/>
...
</application>
...
</manifest>
2. Initialize the push capability in either of the following ways:
Set value corresponding to push_kit_proxy_init_enabled in the <meta-data> element to true.
Code:
<application>
<meta-data
android:name="push_kit_proxy_init_enabled"
android:value="true" />
</application>
Explicitly call FcmPushProxy.init in the onCreate method of the Application class.
3. Call the getToken method to apply for a token.
Code:
private void getToken() {
// Create a thread.
new Thread() {
@Override
public void run() {
try {
// Obtain the app ID from the agconnect-services.json file.
String appId = "your APP_ID";
// Set tokenScope to HCM.
String tokenScope = "HCM";
String token = HmsInstanceId.getInstance(MainActivity.this).getToken(appId, tokenScope);
Log.i(TAG, "get token: " + token);
// Check whether the token is empty.
if(!TextUtils.isEmpty(token)) {
sendRegTokenToServer(token);
}
} catch (ApiException e) {
Log.e(TAG, "get token failed, " + e);
}
}
}.start();
}
private void sendRegTokenToServer(String token) {
Log.i(TAG, "sending token to server. token:" + token);
}
4. Override the onNewToken method.
After the SDK is integrated and initialized, the getToken method will not return a token. Instead, you'll need to obtain a token by using the onNewToken method.
Code:
@Override
public void onNewToken(String token, Bundle bundle) {
Log.i(TAG, "onSubjectToken called, token:" + token );
}
5. Override the onTokenError method.
This method will be called if the token fails to be obtained.
Code:
@Override
public void onTokenError(Exception e, Bundle bundle) {
int errCode = ((BaseException) e).getErrorCode();
String errInfo = e.getMessage();
Log.i(TAG, "onTokenError called, errCode:" + errCode + ",errInfo=" + errInfo );
}
6. Override the onMessageReceived method to receive data messages.
Code:
@Override
public void onMessageReceived(RemoteMessage message) {
Log.i(TAG, "onMessageReceived is called");
// Check whether the message is empty.
if (message == null) {
Log.e(TAG, "Received message entity is null!");
return;
}
// Obtain the message content.
Log.i(TAG, "get Data: " + message.getData()
+ "\n getFrom: " + message.getFrom()
+ "\n getTo: " + message.getTo()
+ "\n getMessageId: " + message.getMessageId()
+ "\n getSentTime: " + message.getSentTime()
+ "\n getDataMap: " + message.getDataOfMap()
+ "\n getMessageType: " + message.getMessageType()
+ "\n getTtl: " + message.getTtl()
+ "\n getToken: " + message.getToken());
Boolean judgeWhetherIn10s = false;
// Create a job to process a message if the message is not processed within 10 seconds.
if (judgeWhetherIn10s) {
startWorkManagerJob(message);
} else {
// Process the message within 10 seconds.
processWithin10s(message);
}
}
private void startWorkManagerJob(RemoteMessage message) {
Log.d(TAG, "Start new job processing.");
}
private void processWithin10s(RemoteMessage message) {
Log.d(TAG, "Processing now.");
}
7. Send downlink messages.
Currently, you can only use REST APIs on the server to send downlink messages through a third-party manufacturer's push messaging channel.
The following is the URL for calling the API using HTTPS POST:
Code:
POST https://push-api.cloud.huawei.com/v1/[appId]/messages:send
The request header looks like the following:
Code:
Content-Type: application/json; charset=UTF-8
Authorization: Bearer CF3Xl2XV6jMKZgqYSZFws9IPlgDvxqOfFSmrlmtkTRupbU2VklvhX9kC9JCnKVSDX2VrDgAPuzvNm3WccUIaDg==
An example of the notification message body is as follows:
Code:
{
"validate_only": false,
"message": {
"android": {
"notification": {
"title": "test title",
"body": "test body",
"click_action": {
"type": 3
}
}
},
"token": ["pushtoken1"]
}
}
And just like that, my app has got the ability to send its push messages to mobile phones of different manufacturers — without any other configurations. Easy-peasy, right?
Conclusion​Today's highly developed mobile Internet has made push messaging an important and effective way for mobile apps to improve user engagement and stickiness. A great obstacle for push messaging to effectively play its role is the highly diversified mobile phone market that is inundated with various manufacturers.
In this article, I demonstrated my solution to aggregate the push channels of different manufacturers, which allowed my app to push messages in a unified way to devices made by those manufacturers. As proven, the whole implementation process is both straightforward and cost-effective, delivering a better messaging effect of push messages by ensuring that they can reach a bigger user base supported by various manufacturers.

Categories

Resources