Introduction
Safety Detect builds robust security capabilities, including system integrity check (SysIntegrity), app security check (AppsCheck), malicious URL check (URLCheck), fake user detection (UserDetect), and malicious Wi-Fi detection (WifiDetect), into your app, effectively protecting it against security threats.
SysIntegrity API: Checks whether the device running your app is secure, for example, whether it is rooted.
AppsCheck API: Checks for malicious apps and provides you with a list of malicious apps.
URLCheck API: Determines the threat type of a specific URL.
UserDetect API: Checks whether your app is interacting with a fake user.
WifiDetect API: Checks whether the Wi-Fi to be connected is secure.
Regions and Languages
For details, please refer to supported regions and languages.
UserDetect is only available outside of the Chinese mainland.
WiFi Detect is only available inside of the Chinese mainland.
Implementation
Before you get started, you must register as a HUAWEI developer and complete identity verification on the HUAWEI Developer website. For details, please refer to Register a HUAWEI ID.
Integration HMS Core Sdk
After that, follow the steps in the link below to integrate HMS Core Sdk into the project and for more details about creating a new project on AppGallery Connect . Follow the link below.
https://medium.com/huawei-developers/android-integrating-your-apps-with-huawei-hms-core-1f1e2a090e98
Enable Safety Detect
Enable the Safety Detect in the Manage API section and add the Safety Detect sdk to build.gradle in the app directory from Android Studio.
Code:
implementation 'com.huawei.hms:safetydetect:5.0.2.300'
Finally, On the Project Setting page, click agconnect-services.json to download the configuration file and copy the agconnect-services.json file to the app root directory. We have completed the necessary preparations to use the safety detect. Let’s see how to use the functions.
Importing SysIntegrity API
The SysIntegrity API is called to check the system integrity of a device. If the device is not safe, appropriate measures are taken. The API evaluates the system integrity in the secure boot process in the Trusted Execution Environment (TEE) and will dynamically evaluate the system integrity. The check results are high reliable. For example, whether the phone has root access can be checked with this API.
Code:
public void invoke() {
byte[] nonce = new byte[24];
try {
SecureRandom random;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
random = SecureRandom.getInstanceStrong();
} else {
random = SecureRandom.getInstance("SHA1PRNG");
}
random.nextBytes(nonce);
} catch (
NoSuchAlgorithmException e) {
Log.e(TAG, e.getMessage());
}
// TODO(developer): Change your app ID. You can obtain your app ID in AppGallery Connect.
Task task = client.sysIntegrity(nonce, APP_ID);
task.addOnSuccessListener(new OnSuccessListener<SysIntegrityResp>() {
@Override
public void onSuccess(SysIntegrityResp response) {
// Indicates communication with the service was successful.
// Use response.getResult() to get the result data.
String jwsStr = response.getResult();
String[] jwsSplit = jwsStr.split("\\.");
String jwsPayloadStr = jwsSplit[1];
String payloadDetail = new String(Base64.decode(jwsPayloadStr.getBytes(StandardCharsets.UTF_8), Base64.URL_SAFE), StandardCharsets.UTF_8);
try {
final JSONObject jsonObject = new JSONObject(payloadDetail);
final boolean basicIntegrity = jsonObject.getBoolean("basicIntegrity");
String isBasicIntegrity = String.valueOf(basicIntegrity);
String basicIntegrityResult = "Basic Integrity: " + isBasicIntegrity;
Log.i(TAG, basicIntegrityResult);
if (!basicIntegrity) {
String advice = "Advice: " + jsonObject.getString("advice");
Log.i("Advice log", advice);
}
} catch (JSONException e) {
String errorMsg = e.getMessage();
Log.e(TAG, errorMsg != null ? errorMsg : "unknown error");
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// An error occurred while communicating with the service.
if (e instanceof ApiException) {
// An error with the HMS API contains some
// additional details.
ApiException apiException = (ApiException) e;
// You can retrieve the status code using
// the apiException.getStatusCode() method.
Log.e(TAG, "Error: " + SafetyDetectStatusCodes.getStatusCodeString(apiException.getStatusCode()) + ": " + apiException.getMessage());
} else {
// A different, unknown type of error occurred.
Log.e(TAG, "ERROR:" + e.getMessage());
}
}
});
}
When calling the SysIntegrity API of Safety Detect, you must transfer a nonce value that will be contained in the check result. You can check the nonce value to determine whether the returned result corresponds to your request and does not encounter replay attacks.
{
"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"
}
The SysIntegrity API has two input parameters. The first one is the nonce value, and the other is appId. Huawei Mobile Services (APK) sends the check result to the Huawei server to verify the certificate and sends the result to you via the SysIntegrityResp object. With the getResult () method, we can get the response in JSON Web Signature (JWS) format. After doing the parse operations, we get the value of basicIntegrity.
If the value of basicIntegrity is false in the check result, you can decide whether to remind users of the risks based on your security requirements.
Importing AppsCheck
You can obtain a list of malicious applications and evaluate whether you can restrict the behavior of your application based on the risk. AppsCheck API provide developer apps with a list of malicious apps on HUAWEI mobile phones.
Code:
public void invokeGetMaliciousApps() {
Task task = client.getMaliciousAppsList();
task.addOnSuccessListener(new OnSuccessListener<MaliciousAppsListResp>() {
@Override
public void onSuccess(MaliciousAppsListResp maliciousAppsListResp) {
// Indicates communication with the service was successful.
// Use resp.getMaliciousApps() to get malicious apps data.
List<MaliciousAppsData> appsDataList = maliciousAppsListResp.getMaliciousAppsList();
// Indicates get malicious apps was successful.
if (maliciousAppsListResp.getRtnCode() == CommonCode.OK) {
if (appsDataList.isEmpty()) {
// Indicates there are no known malicious apps.
Log.i(TAG, "There are no known potentially malicious apps installed.");
} else {
Log.i(TAG, "Potentially malicious apps are installed!");
for (MaliciousAppsData maliciousApp : appsDataList) {
Log.i(TAG, "Information about a malicious app:");
// Use getApkPackageName() to get APK name of malicious app.
Log.i(TAG, "APK: " + maliciousApp.getApkPackageName());
// Use getApkSha256() to get APK sha256 of malicious app.
Log.i(TAG, "SHA-256: " + maliciousApp.getApkSha256());
// Use getApkCategory() to get category of malicious app.
// Categories are defined in AppsCheckConstants
Log.i(TAG, "Category: " + maliciousApp.getApkCategory());
}
}
} else {
Log.e(TAG, "getMaliciousAppsList fialed: " + maliciousAppsListResp.getErrorReason());
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// An error occurred while communicating with the service.
if (e instanceof ApiException) {
// An error with the HMS API contains some
// additional details.
ApiException apiException = (ApiException) e;
// You can retrieve the status code using the apiException.getStatusCode() method.
Log.e(TAG, "Error: " + SafetyDetectStatusCodes.getStatusCodeString(apiException.getStatusCode()) + ": " + apiException.getStatusMessage());
} else {
// A different, unknown type of error occurred.
Log.e(TAG, "ERROR: " + e.getMessage());
}
}
});
}
You can directly call getMaliciousAppsList() of the SafetyDetectClient to obtain a list of malicious apps. If you have no malicious apps, the log “There are no known potentially malicious apps installed” is shown .
Importing User Detect
This API can help your app prevent batch registration, credential stuffing attacks, activity bonus hunting, and content crawling.If a user is a suspicious one or risky one, a verification code is sent to the user for secondary verification.
Working principles :
(1) Your app integrates the HMS SDK to call HMS Core Safety Detect.
(2) Safety Detect evaluates risks in the device environment. If the risk level is medium or high, Safety Detect requires captcha and returns a response token to your app.
(3) Your app sends the response token to the app server.
(4) The app server sends the response token to the Safety Detect server to request the detection results.
To initiate a detection request, you need to call the userDetection method. Generally, this method is triggered when a user touches a UI control (such as a button). To call the userDetection() method, perform the following steps:
Code:
public void detect() {
Log.i(TAG, "User detection start.");
SafetyDetect.getClient(context)
.userDetection(APP_ID)
.addOnSuccessListener(new OnSuccessListener<UserDetectResponse>() {
@Override
public void onSuccess(UserDetectResponse userDetectResponse) {
Log.i(TAG, "User detection succeed, response = " + userDetectResponse);
boolean verifySucceed = verify(userDetectResponse.getResponseToken());
if (verifySucceed) {
Toast.makeText(context.getApplicationContext(),
"User detection succeed and verify succeed",
Toast.LENGTH_SHORT)
.show();
} else {
Toast.makeText(context.getApplicationContext(),
"User detection succeed but verify fail,"
+ "please replace verify url with your's server address",
Toast.LENGTH_SHORT)
.show();
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
String errorMsg;
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
errorMsg = SafetyDetectStatusCodes.getStatusCodeString(apiException.getStatusCode())
+ ": " + apiException.getMessage();
} else {
errorMsg = e.getMessage();
}
Log.i(TAG, "User detection fail. Error info: " + errorMsg);
Toast.makeText(context.getApplicationContext(), errorMsg, Toast.LENGTH_SHORT).show();
}
});
}
If the OnSuccess () method is run in the UserDetect API, the user has completed human-machine authentication. However, you still need to validate the user’s response token on the background server. To obtaining the Detection Result , You need to get an access token and call the cloud-side API to obtain the detection result. You can see the details below.
Code:
private static boolean verify(final String responseToken) {
try {
return new AsyncTask<String, Void, Boolean>() {
@Override
protected Boolean doInBackground(String... strings) {
String input = strings[0];
JSONObject jsonObject = new JSONObject();
try {
// TODO(developer): Replace the baseUrl with your own server address,better not hard code.
String baseUrl = "https://www.example.com/userdetect/verify";
jsonObject.put("response", input);
String result = sendPost(baseUrl, jsonObject);
JSONObject resultJson = new JSONObject(result);
boolean success = resultJson.getBoolean("success");
// if success is true that means the user is real human instead of a robot.
Log.i(TAG, "verify: result = " + success);
return success;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}.execute(responseToken).get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
return false;
}
}
Importing Wifi detect
Your app can detect ARP attacks, man-in-the-middle attacks, DNS hijacking attacks, and other attacks on the Wi-Fi to be connected with Wifi Detect Api. If attacks are detected, your app can interrupt the user operation or ask users to confirm whether to continue the operation.
Code:
public void invokeGetWifiDetectStatus() {
Log.i(TAG, "Start to getWifiDetectStatus!");
Task task = client.getWifiDetectStatus();
task.addOnSuccessListener(new OnSuccessListener<WifiDetectResponse>() {
@Override
public void onSuccess(WifiDetectResponse wifiDetectResponse) {
int wifiDetectStatus = wifiDetectResponse.getWifiDetectStatus();
Log.i(TAG, "\n-1: Failed to obtain the Wi-Fi status. \n" + "0: No Wi-Fi is connected. \n" + "1: The connected Wi-Fi is secure. \n" + "2: The connected Wi-Fi is insecure.");
Log.i(TAG, "wifiDetectStatus is: " + wifiDetectStatus);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
Log.e(TAG,
"Error: " + apiException.getStatusCode() + ":"
+ SafetyDetectStatusCodes.getStatusCodeString(apiException.getStatusCode()) + ": "
+ apiException.getStatusMessage());
} else {
Log.e(TAG, "ERROR! " + e.getMessage());
}
}
});
}
Wifi Detect Status:
1: Failed to obtain the Wi-Fi status.
0: No Wi-Fi is connected.
1: The connected Wi-Fi is secure.
2: The connected Wi-Fi is insecure.
Importing Url Check
When you visit a URL ,this API checks whether the URL is a malicious one. If so, you can evaluate the risk and alert the user about the risk or block the URL.
Main steps:
Initialize the URLCheck API.
Request URL check.
Close the URL check session.
Process the result code.
Code:
public void callUrlCheckApi() {
client.urlCheck("https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/SafetyDetectWiFiDetectAPIDevelopment", APP_ID,
// Specify url threat type
UrlCheckThreat.MALWARE,
UrlCheckThreat.PHISHING)
.addOnSuccessListener(new OnSuccessListener<UrlCheckResponse>() {
/**
* Called after successfully communicating with the SafetyDetect API.
* The #onSuccess callback receives an
* {@link com.huawei.hms.support.api.entity.safetydetect.UrlCheckResponse} that contains a
* list of UrlCheckThreat that contains the threat type of the Url.
*/
@Override
public void onSuccess(UrlCheckResponse urlCheckResponse) {
// Indicates communication with the service was successful.
// Identify any detected threats.
// Call getUrlCheckResponse method of UrlCheckResponse then you can get List<UrlCheckThreat> .
// If List<UrlCheckThreat> is empty , that means no threats found , else that means threats found.
List<UrlCheckThreat> list = urlCheckResponse.getUrlCheckResponse();
if (list.isEmpty()) {
// No threats found.
Log.i(TAG,"No Threats found!");
} else {
// Threats found!
Log.i(TAG,"Threats found!");
}
}
})
.addOnFailureListener(new OnFailureListener() {
/**
* Called when an error occurred when communicating with the SafetyDetect API.
*/
@Override
public void onFailure(Exception e) {
// An error with the Huawei Mobile Service API contains some additional details.
String errorMsg;
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
errorMsg = "Error: " +
SafetyDetectStatusCodes.getStatusCodeString(apiException.getStatusCode()) + ": " +
e.getMessage();
// You can use the apiException.getStatusCode() method to get the status code.
// Note: If the status code is SafetyDetectStatusCodes.CHECK_WITHOUT_INIT, you need to call initUrlCheck().
} else {
// Unknown type of error has occurred.
errorMsg = e.getMessage();
}
Log.d(TAG, errorMsg);
Toast.makeText(context.getApplicationContext(), errorMsg, Toast.LENGTH_SHORT).show();
}
});
}
You need to call the getUrlCheckResponse() method of the URLCheckResponse object to obtain the URL check response. The method returns List<UrlCheckThreat> which contains a list of all detected URL threat types. If the list is empty, no threat has been detected. Otherwise, you can call the getUrlCheckResult () method of UrlCheckThreat to obtain the specific threat code. For more detail follow this link.
Resources:
Github link : https://github.com/simgekeser/Hms-Safety-Detect-Example
Official Document : https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/SafetyDetect_AbouttheService
Can you please tell me a real time scenario of using safety detect in application.
Related
Before using HUAWEI IAP on your app, send an isEnvReady request from your app to HUAWEI IAP to check whether the currently signed-in HUAWEI ID is located in a country or region where HUAWEI IAP is available.
If your app does not connect to the HUAWEI ID sign-in API, connect to this API to sign in.
Perform the following steps for your development:
Send an isEnvReady request and set two callback listeners to receive the request result.
● If the request result is Succeeded, your app will obtain an IsEnvReadyResult instance, indicating that the country or region where the currently signed-in HUAWEI ID is located supports HUAWEI IAP.
● If the request result is Failed, HUAWEI IAP will return an Exception object. If the object is IapApiException, use its getStatusCode() method to obtain the result code of the request.
If the result code is OrderStatusCode.ORDER_HWID_NOT_LOGIN (no HUAWEI ID signed in), use status in the IapApiException object to bring up the HUAWEI ID sign-in screen. Then, obtain the result in the onActivityResult method of Activity. Parse returnCode from the intent returned by onActivityResult. If returnCode is OrderStatusCode.SUCCESS, the country or region where the currently signed-in HUAWEI ID is located supports HUAWEI IAP. If returnCode is not OrderStatusCode.SUCCESS, an exception occurs.
Code:
// To get the Activity instance that calls this API.
Activity activity = getActivity();
Task<IsEnvReadyResult> task = Iap.getIapClient(activity).isEnvReady();
task.addOnSuccessListener(new OnSuccessListener<IsEnvReadyResult>() {
@Override
public void onSuccess(IsEnvReadyResult result) {
// Obtain the execution result.
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof IapApiException) {
IapApiException apiException = (IapApiException) e;
Status status = apiException.getStatus();
if (status.getStatusCode() == OrderStatusCode.ORDER_HWID_NOT_LOGIN) {
// Not logged in.
if (status.hasResolution()) {
try {
// 6666 is an int constant defined by the developer.
status.startResolutionForResult(getActivity(), 6666);
} catch (IntentSender.SendIntentException exp) {
}
}
} else if (status.getStatusCode() == OrderStatusCode.ORDER_ACCOUNT_AREA_NOT_SUPPORTED) {
// The current region does not support HUAWEI IAP.
}
}
}
});
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 6666) {
if (data != null) {
// Obtain the execution result.
int returnCode = data.getIntExtra("returnCode", 1);
}
}
}
More information like this, you can visit HUAWEI Developer Forum
{
"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"
}
What is it?
Huawei Games is a group of APIs from Huawei to simplify some games basic features like leaderboards, achievements, Events and online matches.
Gaming technologies are constantly evolving. Nevertheless, a lot of core gameplay elements have remained unchanged for decades. High scores, leaderboards, quests, achievements, and multiplayer support are examples. If you are developing a game for the Android platform, you don't have to implement any of those elements manually. You can simply use the Huawei Game services APIs instead.
Features of Huawei Game services
· HUAWEI ID sign-in
· Real-name authentication
· Bulletins
· Achievements
· Events
· Leaderboard
· Saved games
· Player statistics
Let’s start!
You should follow the steps
1) Create an android project in android studio.
2) Get the SHA Key. Create SHA key
3) Create a Game App in the Huawei app galley connect (AGC)
4) Provide the SHA key in the information section.
5) Provide storage location.
6) Enable Game service.
7) After all the steps need to download the agconnect-services.json from the app information section. Copy and paste the json file in the app folder of the android project.
8) 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/'
Add the classpath in the dependencies path
classpath 'com.huawei.agconnect:agcp:1.2.1.300'
9) Copy and paste the below plugin in the app build.gradle file dependencies section.
apply plugin: 'com.huawei.agconnect'
Add the below 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'
Note: if you are not using the In-App purchase then no need add the following dependency.
1. implementation 'com.huawei.hms:iap:4.0.4.300'
10) Sync App.
In this series of article we will build Tic Tac Toe game. In this article will see the following features.
· Sign In.
· Initialization.
· Getting player info.
· Saving player info.
Sign In
User can sign-in with Huawei account. They can play game.
Code:
public void signIn() {
Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.getService(this, getHuaweiIdParams()).silentSignIn();
authHuaweiIdTask.addOnSuccessListener(new OnSuccessListener<AuthHuaweiId>() {
@Override
public void onSuccess(AuthHuaweiId authHuaweiId) {
showLog("signIn success");
showLog("display:" + authHuaweiId.getDisplayName());
welcomeTv.setVisibility(View.VISIBLE);
welcomeTv.setText("Welcome back " + authHuaweiId.getDisplayName());
signIn.setVisibility(View.INVISIBLE);
showLog("AT:" + authHuaweiId.getAccessToken());
mAuthid = authHuaweiId;
SignInCenter.get().updateAuthHuaweiId(authHuaweiId);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
signIn.setVisibility(View.VISIBLE);
welcomeTv.setVisibility(View.INVISIBLE);
ApiException apiException = (ApiException) e;
showLog("signIn failed:" + apiException.getStatusCode());
showLog("start getSignInIntent");
signInNewWay();
}
}
});
}
public HuaweiIdAuthParams getHuaweiIdParams() {
return new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM_GAME).createParams();
}
public void signInNewWay() {
Intent intent = HuaweiIdAuthManager.getService(SignInActivity.this, getHuaweiIdParams()).getSignInIntent();
startActivityForResult(intent, SIGN_IN_INTENT);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (SIGN_IN_INTENT == requestCode) {
handleSignInResult(data);
} else {
showLog("unknown requestCode in onActivityResult");
}
}
private void handleSignInResult(Intent data) {
if (null == data) {
showLog("signIn inetnt is null");
return;
}
// HuaweiIdSignIn.getSignedInAccountFromIntent(data);
String jsonSignInResult = data.getStringExtra("HUAWEIID_SIGNIN_RESULT");
if (TextUtils.isEmpty(jsonSignInResult)) {
showLog("SignIn result is empty");
return;
}
try {
HuaweiIdAuthResult signInResult = new HuaweiIdAuthResult().fromJson(jsonSignInResult);
if (0 == signInResult.getStatus().getStatusCode()) {
showLog("Sign in success.");
showLog("Sign in result: " + signInResult.toJson());
SignInCenter.get().updateAuthHuaweiId(signInResult.getHuaweiId());
} else {
showLog("Sign in failed: " + signInResult.getStatus().getStatusCode());
}
} catch (JSONException var7) {
showLog("Failed to convert json from signInResult.");
}
}
The above show the sign in with Huawei account.
Initialization
Key steps to launch the game
Add the following code to the onCreate method of the Application to register the callback listening function of the activity.
Code:
package com.android.huawei.tictactoe;
import android.app.Application;
import com.huawei.hms.api.HuaweiMobileServicesUtil;
public class TicTacToeApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HuaweiMobileServicesUtil.setApplication(this);
}
}
Call JosApps.getJosAppsClient to initialize the JosAppsClient object and JosAppsClient.init to initialize the game.
Code:
private void init() {
JosAppsClient appsClient = JosApps.getJosAppsClient(this, null);
appsClient.init();
Log.i(TAG, "init success");
}
Getting player info
Code:
public void getCurrentPlayer() {
PlayersClientImpl client = (PlayersClientImpl) Games.getPlayersClient(this, getAuthHuaweiId());
Task<Player> task = client.getCurrentPlayer();
task.addOnSuccessListener(new OnSuccessListener<Player>() {
@Override
public void onSuccess(Player player) {
String result = "display:" + player.getDisplayName() + "\n"
+ "playerId:" + player.getPlayerId() + "\n"
+ "playerLevel:" + player.getLevel() + "\n"
+ "timestamp:" + player.getSignTs() + "\n"
+ "playerSign:" + player.getPlayerSign();
showLog(result);
playerId = player.getPlayerId();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
showLog(result);
}
}
});
}
The above code gives the player info like playerId, Player name, player level, in which level he/she is playing.
Saving player info.
Player info can be updated using AppPlayerInfo. Player level, role, rank etc. The following code show the saving player info.
To save player info playerId is mandatory.
Code:
public void savePlayerInfo() {
if (TextUtils.isEmpty(playerId)) {
Toast.makeText(this, "Get the current user first", Toast.LENGTH_SHORT).show();
return;
}
PlayersClient client = Games.getPlayersClient(this, getAuthHuaweiId());
AppPlayerInfo appPlayerInfo = new AppPlayerInfo();
appPlayerInfo.area = "2";
appPlayerInfo.rank = "56";
appPlayerInfo.role = "Pro";
appPlayerInfo.sociaty = "Red Cliff III";
appPlayerInfo.playerId = playerId;
Task<Void> task = client.savePlayerInfo(appPlayerInfo);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void v) {
Toast.makeText(SignInActivity.this, "Player info saved successfully ", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
Toast.makeText(SignInActivity.this, result, Toast.LENGTH_SHORT).show();
}
}
});
}
Result
Nice, thank you
Can be useful for online games.
Freemind R said:
More information like this, you can visit HUAWEI Developer Forum
What is it?
Huawei Games is a group of APIs from Huawei to simplify some games basic features like leaderboards, achievements, Events and online matches.
Gaming technologies are constantly evolving. Nevertheless, a lot of core gameplay elements have remained unchanged for decades. High scores, leaderboards, quests, achievements, and multiplayer support are examples. If you are developing a game for the Android platform, you don't have to implement any of those elements manually. You can simply use the Huawei Game services APIs instead.
Features of Huawei Game services
· HUAWEI ID sign-in
· Real-name authentication
· Bulletins
· Achievements
· Events
· Leaderboard
· Saved games
· Player statistics
Let’s start!
You should follow the steps
1) Create an android project in android studio.
2) Get the SHA Key. Create SHA key
3) Create a Game App in the Huawei app galley connect (AGC)
4) Provide the SHA key in the information section.
5) Provide storage location.
6) Enable Game service.
7) After all the steps need to download the agconnect-services.json from the app information section. Copy and paste the json file in the app folder of the android project.
8) 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/'
Add the classpath in the dependencies path
classpath 'com.huawei.agconnect:agcp:1.2.1.300'
9) Copy and paste the below plugin in the app build.gradle file dependencies section.
apply plugin: 'com.huawei.agconnect'
Add the below 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'
Note: if you are not using the In-App purchase then no need add the following dependency.
1. implementation 'com.huawei.hms:iap:4.0.4.300'
10) Sync App.
In this series of article we will build Tic Tac Toe game. In this article will see the following features.
· Sign In.
· Initialization.
· Getting player info.
· Saving player info.
Sign In
User can sign-in with Huawei account. They can play game.
Code:
public void signIn() {
Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.getService(this, getHuaweiIdParams()).silentSignIn();
authHuaweiIdTask.addOnSuccessListener(new OnSuccessListener<AuthHuaweiId>() {
@Override
public void onSuccess(AuthHuaweiId authHuaweiId) {
showLog("signIn success");
showLog("display:" + authHuaweiId.getDisplayName());
welcomeTv.setVisibility(View.VISIBLE);
welcomeTv.setText("Welcome back " + authHuaweiId.getDisplayName());
signIn.setVisibility(View.INVISIBLE);
showLog("AT:" + authHuaweiId.getAccessToken());
mAuthid = authHuaweiId;
SignInCenter.get().updateAuthHuaweiId(authHuaweiId);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
signIn.setVisibility(View.VISIBLE);
welcomeTv.setVisibility(View.INVISIBLE);
ApiException apiException = (ApiException) e;
showLog("signIn failed:" + apiException.getStatusCode());
showLog("start getSignInIntent");
signInNewWay();
}
}
});
}
public HuaweiIdAuthParams getHuaweiIdParams() {
return new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM_GAME).createParams();
}
public void signInNewWay() {
Intent intent = HuaweiIdAuthManager.getService(SignInActivity.this, getHuaweiIdParams()).getSignInIntent();
startActivityForResult(intent, SIGN_IN_INTENT);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (SIGN_IN_INTENT == requestCode) {
handleSignInResult(data);
} else {
showLog("unknown requestCode in onActivityResult");
}
}
private void handleSignInResult(Intent data) {
if (null == data) {
showLog("signIn inetnt is null");
return;
}
// HuaweiIdSignIn.getSignedInAccountFromIntent(data);
String jsonSignInResult = data.getStringExtra("HUAWEIID_SIGNIN_RESULT");
if (TextUtils.isEmpty(jsonSignInResult)) {
showLog("SignIn result is empty");
return;
}
try {
HuaweiIdAuthResult signInResult = new HuaweiIdAuthResult().fromJson(jsonSignInResult);
if (0 == signInResult.getStatus().getStatusCode()) {
showLog("Sign in success.");
showLog("Sign in result: " + signInResult.toJson());
SignInCenter.get().updateAuthHuaweiId(signInResult.getHuaweiId());
} else {
showLog("Sign in failed: " + signInResult.getStatus().getStatusCode());
}
} catch (JSONException var7) {
showLog("Failed to convert json from signInResult.");
}
}
The above show the sign in with Huawei account.
Initialization
Key steps to launch the game
Add the following code to the onCreate method of the Application to register the callback listening function of the activity.
Code:
package com.android.huawei.tictactoe;
import android.app.Application;
import com.huawei.hms.api.HuaweiMobileServicesUtil;
public class TicTacToeApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HuaweiMobileServicesUtil.setApplication(this);
}
}
Call JosApps.getJosAppsClient to initialize the JosAppsClient object and JosAppsClient.init to initialize the game.
Code:
private void init() {
JosAppsClient appsClient = JosApps.getJosAppsClient(this, null);
appsClient.init();
Log.i(TAG, "init success");
}
Getting player info
Code:
public void getCurrentPlayer() {
PlayersClientImpl client = (PlayersClientImpl) Games.getPlayersClient(this, getAuthHuaweiId());
Task<Player> task = client.getCurrentPlayer();
task.addOnSuccessListener(new OnSuccessListener<Player>() {
@Override
public void onSuccess(Player player) {
String result = "display:" + player.getDisplayName() + "\n"
+ "playerId:" + player.getPlayerId() + "\n"
+ "playerLevel:" + player.getLevel() + "\n"
+ "timestamp:" + player.getSignTs() + "\n"
+ "playerSign:" + player.getPlayerSign();
showLog(result);
playerId = player.getPlayerId();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
showLog(result);
}
}
});
}
The above code gives the player info like playerId, Player name, player level, in which level he/she is playing.
Saving player info.
Player info can be updated using AppPlayerInfo. Player level, role, rank etc. The following code show the saving player info.
To save player info playerId is mandatory.
Code:
public void savePlayerInfo() {
if (TextUtils.isEmpty(playerId)) {
Toast.makeText(this, "Get the current user first", Toast.LENGTH_SHORT).show();
return;
}
PlayersClient client = Games.getPlayersClient(this, getAuthHuaweiId());
AppPlayerInfo appPlayerInfo = new AppPlayerInfo();
appPlayerInfo.area = "2";
appPlayerInfo.rank = "56";
appPlayerInfo.role = "Pro";
appPlayerInfo.sociaty = "Red Cliff III";
appPlayerInfo.playerId = playerId;
Task<Void> task = client.savePlayerInfo(appPlayerInfo);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void v) {
Toast.makeText(SignInActivity.this, "Player info saved successfully ", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
Toast.makeText(SignInActivity.this, result, Toast.LENGTH_SHORT).show();
}
}
});
}
Result
Click to expand...
Click to collapse
Whtat is the difference between sign in and Silent Sign in
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
More information like this, you can visit HUAWEI Developer Forum
Introduction
HMS ML kit service searches in pre-established product image library for the same or similar products based on a product image taken by a customer, and returns the IDs of those products and related information.
{
"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"
}
Use Case
We will capture the product image using device camera from our developed shopping application.
We will show the returned products list in recycle view.
Prerequisite
Java JDK 1.8 or higher is recommended.
Android Studio is recommended.
Huawei android device with HMS core 4.0.0.300 or higher.
Before developing an app, you will need to register as a HUAWEI developer. Refer to Register a HUAWEI ID.
Integrating app gallery connect SDK. Refer to AppGallery Connect Service Getting Started.
Implementation
Enable ML kit in Manage APIs. Refer to Service Enabling.
Integrate following dependencies in app-level build.gradle.
Code:
// Import the product visual search SDK.
implementation 'com.huawei.hms:ml-computer-vision-cloud:2.0.1.300'
3. Add agc plugin in the top of app.gradle file.
Code:
apply plugin: 'com.huawei.agconnect'
4. Add the following permission in manifest.
Camera permission android.permission.CAMERA: Obtains real-time images or videos from a camera.
Internet access permission android.permission.INTERNET: Accesses cloud services on the Internet.
Storage write permission android.permission.WRITE_EXTERNAL_STORAGE: Upgrades the algorithm version.
Storage read permission android.permission.READ_EXTERNAL_STORAGE: Reads photos stored on a device.
5. To request camera permission in realtime.
Code:
private void requestCameraPermission() {
final String[] permissions = new String[] {Manifest.permission.CAMERA};
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
ActivityCompat.requestPermissions(this, permissions, this.CAMERA_PERMISSION_CODE);
return;
}
}
6. Add following code in Application class
Code:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
MLApplication.getInstance().setApiKey("API KEY");
}
}
API key can be obtained either from AGC or integrated agcconnect-services.json.
7. To create an analyzer for product visual search.
Code:
private void initializeProductVisionSearch() {
MLRemoteProductVisionSearchAnalyzerSetting settings = new MLRemoteProductVisionSearchAnalyzerSetting.Factory()
// Set the maximum number of products that can be returned.
.setLargestNumOfReturns(16)
// Set the product set ID. (Contact [email protected] to obtain the configuration guide.)
// .setProductSetId(productSetId)
// Set the region.
.setRegion(MLRemoteProductVisionSearchAnalyzerSetting.REGION_DR_CHINA)
.create();
analyzer
= MLAnalyzerFactory.getInstance().getRemoteProductVisionSearchAnalyzer(settings);
}
8. To capture image from camera.
Code:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQ_CAMERA_CODE);
9. Once image has been captured, onActivityResult() method will be executed.
Code:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult");
if(requestCode == 101) {
if (resultCode == RESULT_OK) {
Bitmap bitmap = (Bitmap) data.getExtras().get("data");
if (bitmap != null) {
// Create an MLFrame object using the bitmap, which is the image data in bitmap format.
MLFrame mlFrame = new MLFrame.Creator().setBitmap(bitmap).create();
mlImageDetection(mlFrame);
}
}
}
}
private void mlImageDetection(MLFrame mlFrame) {
Task> task = analyzer.asyncAnalyseFrame(mlFrame);
task.addOnSuccessListener(new OnSuccessListener>() {
public void onSuccess(List products) {
// Processing logic for detection success.
displaySuccess(products);
}})
.addOnFailureListener(new OnFailureListener() {
public void onFailure(Exception e) {
// Processing logic for detection failure.
// Recognition failure.
try {
MLException mlException = (MLException)e;
// Obtain the result code. You can process the result code and customize respective messages displayed to users.
int errorCode = mlException.getErrCode();
// Obtain the error information. You can quickly locate the fault based on the result code.
String errorMessage = mlException.getMessage();
} catch (Exception error) {
// Handle the conversion error.
}
}
});
}
private void displaySuccess(List productVisionSearchList) {
List productImageList = new ArrayList();
String prodcutType = "";
for (MLProductVisionSearch productVisionSearch : productVisionSearchList) {
Log.d(TAG, "type: " + productVisionSearch.getType() );
prodcutType = productVisionSearch.getType();
for (MLVisionSearchProduct product : productVisionSearch.getProductList()) {
productImageList.addAll(product.getImageList());
Log.d(TAG, "custom content: " + product.getCustomContent() );
}
}
StringBuffer buffer = new StringBuffer();
for (MLVisionSearchProductImage productImage : productImageList) {
String str = "ProductID: " + productImage.getProductId() + "
ImageID: " + productImage.getImageId() + "
Possibility: " + productImage.getPossibility();
buffer.append(str);
buffer.append("
");
}
Log.d(TAG , "display success: " + buffer.toString());
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.main_fragment_container, new SearchResultFragment(productImageList, prodcutType ));
transaction.commit();
}
onSuccess() callback will give us list of MLProductVisionSearch objects, which can be used to get product id and image URL of each product. Also we can get the product type using productVisionSearch.getType(). getType() returns number which can be mapped.
10. We can achieve the product type mapping with following code.
Code:
private String getProductType(String type) {
switch(type) {
case "0":
return "Others";
case "1":
return "Clothing";
case "2":
return "Shoes";
case "3":
return "Bags";
case "4":
return "Digital & Home appliances";
case "5":
return "Household Products";
case "6":
return "Toys";
case "7":
return "Cosmetics";
case "8":
return "Accessories";
case "9":
return "Food";
}
return "Others";
}
11. To get product id and image URL from MLVisionSearchProductImage.
Code:
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
final MLVisionSearchProductImage mlProductVisionSearch = productVisionSearchList.get(position);
holder.tvTitle.setText(mlProductVisionSearch.getProductId());
Glide.with(context)
.load(mlProductVisionSearch.getImageId())
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(holder.imageView);
}
Images
Reference
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/sdk-data-security-0000001050040129-V5
{
"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"
}
Introduction
In this article, we will learn how to integrate Huawei ML kit in Android application. ML Kit provides many text service, you can check these services in the link provided in the reference section , in this sample we will be integrating one of its text service I.e. On-device translation, it translates text from the source language into the target language with the support of an on-device model, even when no Internet service is available.
Supported Devices
Development Overview
You need to install Android Studio IDE and I assume that you have prior knowledge of Android application development.
Hardware Requirements
A computer (desktop or laptop) running Windows 10.
Android phone (with the USB cable), which is used for debugging.
Software Requirements
Java JDK 1.8 or later.
Android Studio software installed.
HMS Core (APK) 4.X or later
Integration steps
Step 1. Huawei developer account and complete identity verification in Huawei developer website, refer to register Huawei ID.
Step 2. Create project in AppGallery Connect
Step 3. Adding HMS Core SDK
Let's start coding
How do I call sign in method?
Java:
private void signInWithHuaweiID() {
AccountAuthParams authParams = new AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode().createParams();
service = AccountAuthManager.getService(ClientActivity.this, authParams);
startActivityForResult(service.getSignInIntent(), 1212);
}
How do I get sign in result?
Java:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
// Process the authorization result to obtain the authorization code from AuthAccount.
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1212) {
Task<AuthAccount> authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data);
if (authAccountTask.isSuccessful()) {
// The sign-in is successful, and the user's ID information and authorization code are obtained.
AuthAccount authAccount = authAccountTask.getResult();
Log.i("TAG", "serverAuthCode:" + authAccount.getAuthorizationCode());
userName = authAccount.getDisplayName();
makeConnect();
} else {
// The sign-in failed.
Log.e("TAG", "sign in failed:" + ((ApiException) authAccountTask.getException()).getStatusCode());
}
}
}
How do I start server?
Java:
wManager = (WifiManager) getSystemService(WIFI_SERVICE);
serverIP = Formatter.formatIpAddress(wManager.getConnectionInfo().getIpAddress());
ip_txt.setText(serverIP);
class ServerThread implements Runnable {
@Override
public void run() {
try {
while (true) {
serverSocket = new ServerSocket(POST_NUMBER);
socket = serverSocket.accept();
output = new PrintWriter(socket.getOutputStream());
input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.d("TAG", " here ");
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_status.setText("Waiting for conn at " + POST_NUMBER);
}
});
handler.post(new Runnable() {
@Override
public void run() {
tv_status.setText("Connected");
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
How do I send message using socket?
Java:
class SendMessage implements Runnable {
private String message;
SendMessage(String message) {
this.message = message;
}
@Override
public void run() {
output.write(message+"\r");
output.flush();
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_chat.append("\n New Message: " + message);
ed_message.setText("");
}
});
Thread.interrupted();
}
}
How do I receive message using socket?
Java:
private class ReadMessage implements Runnable {
@Override
public void run() {
while (true) {
try {
// Log.d("TAG","Server: Listening for message");
if(input!=null){
final String message = input.readLine();
if (message != null) {
handler.post(new Runnable() {
@Override
public void run() {
tv_chat.append("\n" + message );
}
});
}
}
} catch (IOException e) {
// Log.e("TAG","Error while receiving message");
e.printStackTrace();
}
}
}
}
Close the Socket and other connections
Java:
@Override
protected void onPause() {
super.onPause();
if (socket != null) {
try {
output.close();
input.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
How do I revoke auth permission?
Java:
if(service!=null){
// service indicates the AccountAuthService instance generated using the getService method during the sign-in authorization.
service.cancelAuthorization().addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
// Processing after a successful authorization cancellation.
Log.i("TAG", "onSuccess: ");
} else {
// Handle the exception.
Exception exception = task.getException();
if (exception instanceof ApiException){
int statusCode = ((ApiException) exception).getStatusCode();
Log.i("TAG", "onFailure: " + statusCode);
}
}
}
});
}
How do I translate message using ML Text Service?
Java:
private void translateMessage(String text) {
MLApplication.getInstance().setApiKey(API_KEY);
// create an offline translator.
MLLocalTranslateSetting setting = new MLLocalTranslateSetting.Factory()
// Set the source language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
.setSourceLangCode("en")
// Set the target language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
.setTargetLangCode("hi")
.create();
myLocalTranslator = MLTranslatorFactory.getInstance().getLocalTranslator(setting);
// Set the model download policy.
MLModelDownloadStrategy downloadStrategy = new MLModelDownloadStrategy.Factory()
.needWifi()// It is recommended that you download the package in a Wi-Fi environment.
.create();
// Create a download progress listener.
MLModelDownloadListener modelDownloadListener = new MLModelDownloadListener() {
@Override
public void onProcess(long alreadyDownLength, long totalLength) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// Display the download progress or perform other operations.
}
});
}
};
myLocalTranslator.preparedModel(downloadStrategy, modelDownloadListener).
addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Called when the model package is successfully downloaded.
// input is a string of less than 5000 characters.
final Task<String> task = myLocalTranslator.asyncTranslate(text);
// Before translation, ensure that the models have been successfully downloaded.
task.addOnSuccessListener(new OnSuccessListener<String>() {
@Override
public void onSuccess(String translated) {
// Processing logic for detection success.
Log.d("TAG", "Text : " + translated);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
e.printStackTrace();
}
});
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
e.printStackTrace();
}
});
}
Result
Tricks and Tips
Makes sure that agconnect-services.json file added.
Make sure required dependencies are added
Make sure that service is enabled in AGC
Make sure that languages are supported
Conclusion
In this article, we have learnt how to integrate Huawei ML kit service i.e. text translation(message) in Client Server messaging using Socket in Android application. You can check the desired result in the result section. Hoping Huawei ML kit capabilities are helpful to you as well, like this sample, you can make use of ML services as per your requirement.
Thank you so much for reading. I hope this article helps you to understand the integration of Huawei ML kit in Android application.
Reference
Huawei ML Kit – Training video
Checkout in forum