Weather Awareness : A Journey Through HMS Awareness - Part 3 - Huawei Developers

More details about this article, 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"
}
Introduction:
Weather Awareness is being used to obtain current weather details such as humidity, temperature, wind direction, rain probability etc.
For calling Weather Awareness capability we have to assign the given permissions in the manifest file.
Code:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Here we are discussing about the following APIs
WeatherStatus
WeatherId
Let's go to the details.
1. WeatherStatus
public interface WeatherStatus
WeatherStatus carries complete weather information. This API provides five methods.
public abstract WeatherSituation getWeatherSituation() :- For current weather information.
public abstract Aqi getAqi() :- For obtaining the AQI
public abstract List<LiveInfo> getLiveInfo() - For living index in the next one to two days.
public abstract List<DailyWeather> getDailyWeather() :- For obtaining weather in the next seven days
public abstract List<HourlyWeather> getHourlyWeather() :- For obtaining weather in the next 24 hours
Let's go to the details.
public abstract WeatherSituation getWeatherSituation()
This method is used to obtain weather and city information. The weather information includes a weather ID, humidity, Celsius degree, Fahrenheit degree, a somatosensory temperature (°C), a somatosensory temperature (°F), a wind direction, a wind force level, a wind speed, atmospheric pressure, an ultraviolet light intensity, and update time. The city information includes the name, city code, province name, and time zone.
Code:
private void getWeatherSituation() {
Awareness.getCaptureClient(this).getWeatherByDevice()
.addOnSuccessListener(new OnSuccessListener<WeatherStatusResponse>() {
@Override
public void onSuccess(WeatherStatusResponse weatherStatusResponse) {
WeatherStatus weatherStatus = weatherStatusResponse.getWeatherStatus();
WeatherSituation weatherSituation = weatherStatus.getWeatherSituation();
Situation situation = weatherSituation.getSituation();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
String weatherInfoStr =
"Time Zone : " +(weatherSituation.getCity().getTimeZone()) + "\n\n" +
"Weather id : " + situation.getWeatherId() + "\n\n" +
"Temperature : " + situation.getTemperatureC() + "℃" +
"/" + situation.getTemperatureF() + "℉" + "\n\n" +
"Wind speed : " + situation.getWindSpeed() + "km/h" + "\n\n" +
"Wind direction : " + situation.getWindDir() + "\n\n" +
"Humidity : " + situation.getHumidity() + "%";
Log.i(TAG, weatherInfoStr);
weather_info_capture.setTextColor(getColor(R.color.green));
weather_info_capture.setText(weatherInfoStr);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "get weather failed");
weather_info_capture.setTextColor(getColor(R.color.red));
weather_info_capture.setText("get weather failed: "+e);
}
});
}
public abstract Aqi getAqi()
This method is used to obtain the AQI information, including data about carbon monoxide, nitrogen dioxide, ozone, PM10, PM2.5, and sulphur dioxide, and comprehensive weather index. Currently it is available only in China.
Code:
private void getAqi(){
Awareness.getCaptureClient(this).getWeatherByDevice()
.addOnSuccessListener(new OnSuccessListener<WeatherStatusResponse>() {
@Override
public void onSuccess(WeatherStatusResponse weatherStatusResponse) {
WeatherStatus weatherStatus = weatherStatusResponse.getWeatherStatus();
Aqi aqi = weatherStatus.getAqi();
String aqi_info="Ozone: "+aqi.getO3()+"\n"+
"Carbon Monoxide"+aqi.getCo()+"\n"+
"Nitrogen Dioxide"+aqi.getNo2()+"\n"+
"PM10"+aqi.getPm10()+"\n"+
"Suphur Dioxide"+aqi.getSo2()+"\n"+
"PM2.5"+aqi.getPm25()+"\n";
weather_info_capture.setText(aqi_info);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "getAqi failed");
weather_info_capture.setTextColor(getColor(R.color.red));
weather_info_capture.setText("get Aqi failed " + e);
}
});
}
public abstract List<LiveInfo> getLiveInfo()
This method is used to obtain the living index of the current day and the next one to two days, including the living index (code values), living level, and time information. Currently it is available only in china.
Code:
List<LiveInfo> liveInfo = weatherStatus.getLiveInfo();
public abstract List<DailyWeather> getDailyWeather()
This method is used to obtain weather information of the next seven days, including the moon phase, moonrise and moonset time, sunrise and sunset time, highest and lowest temperatures (°C), highest and lowest temperatures (°F), AQI value, date, weather IDs, wind direction, wind force, and wind speed in the daytime and at night.
Code:
private void getDailyWeather(){
Awareness.getCaptureClient(this).getWeatherByDevice()
.addOnSuccessListener(new OnSuccessListener<WeatherStatusResponse>() {
@Override
public void onSuccess(WeatherStatusResponse weatherStatusResponse) {
WeatherStatus weatherStatus = weatherStatusResponse.getWeatherStatus();
List<DailyWeather> dailyWeather = weatherStatus.getDailyWeather();
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
String daily_info="";
for(int i=0;i<7;i++) {
daily_info += "Date: " + dateFormat.format(dailyWeather.get(i).getDateTimeStamp()) + "\n" +
"Sun Rise: " + dateFormat.format(dailyWeather.get(i).getSunRise()) + "\n" +
"Sun Set: " + dateFormat.format(dailyWeather.get(i).getSunSet()) + "\n" +
"Moon Set: " + dateFormat.format(dailyWeather.get(i).getMoonSet()) + "\n" +
"Moon Rise: " + dateFormat.format(dailyWeather.get(i).getMoonRise()) + "\n" +
"Moon Phase: " + dailyWeather.get(i).getMoonphase() + "\n" +
"Aqi Value: " + dailyWeather.get(i).getAqiValue() + "\n" +
"Temperature Max: " + dailyWeather.get(i).getMaxTempC() + "°C / " + dailyWeather.get(i).getMaxTempF() + "°F \n" +
"Temperature Min: " + dailyWeather.get(i).getMinTempC() + "°C / " + dailyWeather.get(i).getMinTempF() + "°F \n" +
"Day Weather Id: " + dailyWeather.get(i).getSituationDay().getWeatherId() + "\n" +
"Night Weather Id: " + dailyWeather.get(i).getSituationNight().getWeatherId() + "\n" +
"Day Wind Direction: " + dailyWeather.get(i).getSituationDay().getWindDir() + "\n" +
"Night Wind Direction: " + dailyWeather.get(i).getSituationNight().getWindDir() + "\n" +
"Day Wind Level: " + dailyWeather.get(i).getSituationDay().getWindLevel() + "\n" +
"Night Wind Level: " + dailyWeather.get(i).getSituationNight().getWindLevel() + "\n" +
"Day Wind Speed: " + dailyWeather.get(i).getSituationDay().getWindSpeed() + "\n" +
"Night Wind Speed: " + dailyWeather.get(i).getSituationNight().getWindSpeed() + "\n\n";
}
weather_info_capture.setText(daily_info);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "get Hourly weather failed");
weather_info_capture.setTextColor(getColor(R.color.red));
weather_info_capture.setText("get dailyWeather failed " + e);
}
});
}
public abstract List<HourlyWeather> getHourlyWeather()
This method is used to obtains weather information in the next 24 hours. Weather information in the next 24 hours, including a weather ID, time information, Celsius degree, Fahrenheit degree, rainfall probability, and whether it is day/night.
Code:
private void getHourlyWeather() {
Awareness.getCaptureClient(this).getWeatherByDevice()
.addOnSuccessListener(new OnSuccessListener<WeatherStatusResponse>() {
@Override
public void onSuccess(WeatherStatusResponse weatherStatusResponse) {
WeatherStatus weatherStatus = weatherStatusResponse.getWeatherStatus();
List<HourlyWeather> hourlyWeather = weatherStatus.getHourlyWeather();
weather_info_capture.setTextColor(getColor(R.color.green));
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
String weather_info_hours="";
for(int i=0;i<=24;i++) {
weather_info_hours+= dateFormat.format(hourlyWeather.get(i).getDateTimeStamp()) +" - "+
(hourlyWeather.get(i).isDayNight() ? "Day" : "Night")+"\n"+
"Temperature: " + hourlyWeather.get(i).getTempC() + "°C / "+hourlyWeather.get(i).getTempF() +"°F \n"+
"Rain Probability: " + (hourlyWeather.get(i).getRainprobability()<50?"Low":(hourlyWeather.get(i).getRainprobability()<75?"Medium":"High"))+"\n"+
"Rain Probability: " + hourlyWeather.get(i).getRainprobability()+"\n"+
"Weather Id: " +hourlyWeather.get(i).getWeatherId()+"\n\n";
}
weather_info_capture.setText(weather_info_hours);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "get Hourly weather failed");
weather_info_capture.setTextColor(getColor(R.color.red));
weather_info_capture.setText("get Hourly weather failed " + e);
}
});
}
2. WeatherId
public interface WeatherId
Weather ID is a constant API, which describes the weather information corresponding to different values of weatherId.
References:
https://developer.huawei.com/consumer/en/doc/development/HMS-References/awareness-weatherstatus-4

Related

Android In-app Subscriptions: Facing issue to test the in-app subscription with trail

I have implemented in App subscription in my android application. But i'm unable to test in debug mode. We always need to generate an signed APK and check the next process - can anyone please suggest how to handle this scenario.
After installed signed APK, When I open my application it's showing my subscription product and play dialog with 3 days trial and one active subscription button. On the next day when I open the app, it again shows the same message and trial count is still showing as 3 days.
When I hit the subscription button it was processed to payment option. After full process it was cut the monthly subscription charge from my account and showing payment success method. - but I was still in trial mode then why it's cut the amount. It should be charged after 3 day's
Can anyone please suggest... find my code below
Code:
/*In-App BillingConfig*/
private void initBillingConfig() {
try {
mBillingClient = BillingClient.newBuilder(context).setListener(new PurchasesUpdatedListener() {
@override
public void onPurchasesUpdated(int responseCode, @nullable List<Purchase> purchases) {
try {
if (responseCode == BillingClient.BillingResponse.OK && purchases != null) {
for (Purchase purchase : purchases) {
if (purchase.getSku().equalsIgnoreCase(MONTHLY_2USD)) {
showToast("You have subscribed our product(" + MONTHLY_2USD + ") for next 1 month");
appendLog("You have subscribed our product(" + MONTHLY_2USD + ") for next 1 month");
}
}
} else if (responseCode == BillingClient.BillingResponse.ITEM_ALREADY_OWNED) {
showToast("onPurchasesUpdated: Item already purchased");
appendLog("onPurchasesUpdated: Item already purchased");
} else if (responseCode == BillingClient.BillingResponse.USER_CANCELED) {
showToast("You have canceled our subscription mode.");
appendLog("You have canceled our subscription mode.");
} else if (responseCode == BillingClient.BillingResponse.DEVELOPER_ERROR) {
showToast("BillingClient.BillingResponse.DEVELOPER_ERROR");
appendLog("BillingClient.BillingResponse.DEVELOPER_ERROR");
overridePendingTransition(0,0);
finish();
}
} catch (Exception e) {
e.printStackTrace();
showToast("onPurchasesUpdated: " + e.getMessage());
appendLog("onPurchasesUpdated: " + e.getMessage());
}
}
}).build();
mBillingClient.startConnection(new BillingClientStateListener() {
@override
public void onBillingSetupFinished(@BillingClient.BillingResponse int billingResponseCode) {
try {
if (billingResponseCode == BillingClient.BillingResponse.OK) {
// The billing client is ready. You can query purchases here.
checkBillingSKU();
} else if (billingResponseCode == BillingClient.BillingResponse.ITEM_ALREADY_OWNED) {
appendLog("onBillingSetupFinished: Item already purchased");
}
} catch (Exception e) {
e.printStackTrace();
showToast("onBillingSetupFinished: " + e.getMessage());
appendLog("onBillingSetupFinished: " + e.getMessage());
}
}
@override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
try {
mBillingClient.startConnection(this);
} catch (Exception e) {
e.printStackTrace();
showToast("onBillingServiceDisconnected: " + e.getMessage());
appendLog("onBillingServiceDisconnected: " + e.getMessage());
}
}
});
} catch (Exception e) {
e.printStackTrace();
showToast("initBillingConfig: " + e.getMessage());
appendLog("initBillingConfig: " + e.getMessage());
}
}
private void showToast(String msg) {
runOnUiThread(new Runnable() {
@override
public void run() {
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
});
}
private void checkBillingSKU() {
try {
List skuList = new ArrayList<>();
skuList.add(MONTHLY_2USD);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.SUBS);
mBillingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
@override
public void onSkuDetailsResponse(int responseCode, List<SkuDetails> skuDetailsList) {
// Process the result.
try {
if (responseCode == BillingClient.BillingResponse.OK && skuDetailsList != null) {
for (SkuDetails skuDetails : skuDetailsList) {
String sku = skuDetails.getSku();
String price = skuDetails.getPrice();
showToast(skuDetails.toString());
if (MONTHLY_2USD.equals(sku)) {
//mPremiumUpgradePrice = price;
purchaseProduct();
}
}
}
} catch (Exception e) {
e.printStackTrace();
showToast("onSkuDetailsResponse: " + e.getMessage());
appendLog("onSkuDetailsResponse: " + e.getMessage());
}
}
});
} catch (Exception e) {
e.printStackTrace();
showToast("checkBillingSKU: " + e.getMessage());
appendLog("checkBillingSKU: " + e.getMessage());
}
}
private void purchaseProduct() {
try {
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setSku(MONTHLY_2USD)
.setType(BillingClient.SkuType.SUBS) // SkuType.SUB for subscription
.build();
int responseCode = mBillingClient.launchBillingFlow(DashBoard.this, flowParams);
showToast("BillingFlowParams: " + responseCode);
appendLog("BillingFlowParams: " + responseCode);
} catch (Exception e) {
e.printStackTrace();
showToast("purchaseProduct: " + e.getMessage());
appendLog("purchaseProduct: " + e.getMessage());
}
}

Developing A Game for the Android Platform with Huawei Game service-Part 2

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"
}
Introduction:
In this tutorial we will work through the steps you need to take to add achievements to a simple Tic Tac Toe Android game. We will define an achievement in the App Gallery Connect and implement the achievement interaction in the game.
Why do we need to add achievement in the game?
Basically all developers’ wants engage their users. To make sure user uses application all the time, Achievement is the great way to increase user’s engagement in the game. Achievement will have the badges or some points based progress so that user can compare their progress with the other game players so that they will get motivation to play game. Achievement encourages the users to play the game.
Achievement
Attributes:
· Id: A unique achievement string id generated by AGC.
· Name: Achievement short name max 100 characters.
· Description: This attribute which explains user how to earn this achievement. Maximum 500 characters.
· Icon: Image of achievement where it will be displayed after earning the achievement. Maximum resolution is 512x512
· State: There are 3 types of states.
o Hidden: A hidden achievement means that details about the achievement are hidden from the player. Such achievements are equipped with a generic placeholder description and icon while in a hidden state. If an achievement contains a spoiler about your game that you would like not to reveal, you may configure the achievement as hidden and reveal it to the payer after the game reaches a certain stage.
o Revealed: A revealed achievement means that the player knows about the achievement, but has not yet earned it. If you wish to show the achievement to the player at the start of the game, you can configure it to this state.
o Unlocked: An unlocked achievement means that the player has successfully earned the achievement. This state is unconfigurable and must be earned by the player. After the player achieves this state, a pop-up will display at the top of the game page. HMS SDK allows for an achievement to be unlocked offline. When a game comes back online, it synchronizes with the Huawei game server to update the achievement's unlocked state.
· Steps: Achievements can be designated as standard or incremental. An incremental achievement involves a player completing a number of steps to unlock the achievement. These predefined number of steps are known as the achievement steps.
· List order: The order in which the current achievement appears among all of the achievements. It is designated during achievement configuration.
HMS SDK allows apps to perform the following operations for achievements:
1. Directly jump to the achievements page of Huawei AppAssistant. (Note only released app achievements will be shown in AppAssistant application. As of now AppAssistant app is not available in the App Gallery)
2. Initialize achievement client and get data. So that game application show the list of the achievements. Using the custom design.
Adding achievement in AGC.
On AGC navigate to operate->Game Achievement then click create button.
Fill all the fields like name, description, Icon, steps, initial state and list of order.
In the above image 2 achievements has already release and two more created and those can be released on clicking of release button which is marked in image. Another two achievements are testable. Using the sandbox test account game can be tested.
After releasing the achievements it will be waiting for review state. It takes some time to review from the Huawei reviewer. And then it will be approved.
If the achievements is under review state. Cannot add/modify the achievement. And achievement can delete only before release. And one more thing here is progress can be reset before release.
Now let’s come to android application. Please refer my previous article to android application set up and HMS game SDK configuration.
The above screen is sign in screen. Once sign is success achievement button will be enabled.
When user clicks on my achievement it will redirect achievement screen.
Code:
private AchievementsClient client; private void getAchievementData() {client = Games.getAchievementsClient(this, authHuaweiId);
Task<List<Achievement>> task = client.getAchievementList(forceReload);
task.addOnSuccessListener(new OnSuccessListener<List<Achievement>>() {
@Override
public void onSuccess(List<Achievement> data) {
if (data == null) {
showLog("achievement data is null");
return;
}
Iterator<Achievement> iterator = data.iterator();
achievements.clear();
//Log.e("achievement","data :"+new Gson().toJson(data));
while (iterator.hasNext()) {
Achievement achievement = iterator.next();
achievements.add(achievement);
Log.e("achievement", "Data: " + " Display name: " + achievement.getDisplayName() + " Id: " + achievement.getId()
+ " Description " + achievement.getDescInfo() + " Locale All steps: " + achievement.getLocaleAllSteps()
+ " LocaleReachedSteps: " + achievement.getLocaleReachedSteps() + " describeContents: " + achievement.describeContents()
+ " AllSteps: " + achievement.getAllSteps() + " getReachedSteps: " + achievement.getReachedSteps() + " Player Name :" + achievement.getGamePlayer().getDisplayName()
+ "getReachedThumbnailUri : " + achievement.getReachedThumbnailUri().toString() + " getState : " + achievement.getState() + " getVisualizedThumbnailUri :" + achievement.getVisualizedThumbnailUri().toString() + "\n"
);
//Log.e("achievement","data :"+new Gson().toJson(achievement));
}
adapter.setData(achievements);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
showLog(result);
}
}
});
}
Above code gets the achievement data. And set the recyclerview adapter.
Code:
@Override
public void Unlock(String achievementId, boolean isChecked) {
if (!isChecked) {
client.reach(achievementId);
} else {
performUnlockImmediate(client, achievementId);
}
}
@Override
public void reveal(String achievementId, boolean isChecked) {
if (!isChecked) {
client.visualize(achievementId);
} else {
performRevealImmediate(client, achievementId);
}
}
@Override
public void increment(String achievementId, boolean isChecked) {
if (!isChecked) {
client.grow(achievementId, 1);
} else {
performIncrementImmediate(client, achievementId, 1);
}
}
@Override
public void setStep(String achievementId, boolean isChecked) {
if (!isChecked) {
client.makeSteps(achievementId, 3);
} else {
performSetStepsImmediate(client, achievementId, 3);
}
}
private void performSetStepsImmediate(AchievementsClient client, String achievementId, int stepsNum) {
Task<Boolean> task = client.makeStepsWithResult(achievementId, stepsNum);
task.addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean isSucess) {
if (isSucess) {
Toast.makeText(AchievementListActivity.this, "setAchievementSteps is Success", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(AchievementListActivity.this, "achievement can not make steps", 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(AchievementListActivity.this, "step num is invalid " + result, Toast.LENGTH_SHORT).show();
}
}
});
}
private void performIncrementImmediate(AchievementsClient client, String achievementId, int stepsNum) {
Task<Boolean> task = client.growWithResult(achievementId, stepsNum);
task.addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean isSucess) {
if (isSucess) {
Toast.makeText(AchievementListActivity.this, "incrementAchievement is Success", Toast.LENGTH_SHORT).show();
getAchievementData();
} else {
Toast.makeText(AchievementListActivity.this, "achievement can not grow", 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(AchievementListActivity.this, "has bean already unlocked " + result, Toast.LENGTH_SHORT).show();
}
}
});
}
private void performRevealImmediate(AchievementsClient client, String achievementId) {
Task<Void> task = client.visualizeWithResult(achievementId);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void v) {
Toast.makeText(AchievementListActivity.this, "reveal Achievement is Success", Toast.LENGTH_SHORT).show();
getAchievementData();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
Toast.makeText(AchievementListActivity.this, "achievement is not hidden" + result, Toast.LENGTH_SHORT).show();
}
}
});
}
private void performUnlockImmediate(AchievementsClient client, String achievementId) {
Task<Void> task = client.reachWithResult(achievementId);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void v) {
Toast.makeText(AchievementListActivity.this, "Unlock Achievement is Success", Toast.LENGTH_SHORT).show();
getAchievementData();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
Toast.makeText(AchievementListActivity.this, "achievement has been already unlocked" + result, Toast.LENGTH_SHORT).show();
}
}
});
}
The above code does the Increment, Reveal, Unlock, SetStep. In the Tic Tac Toe game when user wins will increment step once step is reached the steps which is set while creating achievement, Then achievement will be unlocked. When user win the game achievement step will increment. Once the hidden achievement step is reached then achievement will be revealed. If you want to set increment manually setIncrement will be used.
Result:
This is to show the list of achievements.

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

Body Weight Exercise Application using Huawei Health Kit

More information like this, you can visit HUAWEI Developer Forum​
Original link: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201345979826040147&fid=0101187876626530001
In this article we will learn to use Huawei Health Kit in a workout app.
Huawei Health Kit
Health Kit based on users Huawei Id and authorization, provide best service by accessing their health and fitness data. Using this service, developers do not need to worry about capturing their user’s data from any Bluetooth device like fitness tracker watch or Fitbit and record them. It helps developers to create a hassle-free, effective and productive application to their users.
HMS Health Kit Services
1) DataController: Developers can use this API to insert, delete, update, and read data, as well as listen to data updates by registering a listener.
2) SensorsController: Developers can use this API to receiving data reported by the sensor like steps count.
3) AutoRecordController: Developers can use this API to automatically record sensor data, stop recording sensor data, and obtain the record information.
4) ActivityRecordsController: Developers can use this API to create and manage user activities.
Here in this article we will use two services provided by HMS Health Kit and that is SensorsController and ActivityRecordsController.
Use case
To lose weight, you can walk or run. When you walk or run will lose some calories from our body. So better to track our daily steps, if you track daily steps, then you can be active and also to avoid health problems like heart attacks or broken bones, a new study suggests.
Increasing our walking and maintaining the steps can reduce our risk of heart attacks, strokes and fractures over the next few years. Pedometers can be helpful for us to use, as they give us a clear idea of how much we are doing (self-monitoring) and can be used to set realistic goals for increasing our walking gradually.
HMS Health Kit works as a pedometer, count our steps and provide the information directly to us. We can also record our steps using HMS Health Kit and use it for self-monitoring.
Demo
{
"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"
}
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) Create a project in android studio.
2) Get the SHA Key. For getting the SHA key, refer this article.
3) Create an app in the Huawei AppGallery connect.
4) Click on Health kit in console.
5) Apply for Health Kit
6) Select Product Type as Mobile App, APK Name as your project package name and check the required permission required for your application to work, as shown below:
Finally click on submit button to apply for health kit.
7) Provide the SHA Key in App Information Section.
8) Provide storage location.
9) Add the app ID generated when the creating the app on HUAWEI Developers to the application section
Code:
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="YOUR_APP_ID" />
10) 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.
11) Enter the below maven url inside the repositories of buildscript and allprojects (project build.gradle file):
Code:
maven { url ‘http://developer.huawei.com/repo/’ }
12) Enter the below plugin in the app build.gradle file:
Code:
apply plugin: ‘com.huawei.agconnect’
13) Enter the below Health Kit, account kit and auth service dependencies in the dependencies section:
Code:
implementation 'com.huawei.agconnect:agconnect-core:1.4.0.300'
implementation 'com.huawei.agconnect:agconnect-auth:1.4.0.300'
implementation 'com.huawei.hms:hwid:4.0.4.300'
implementation 'com.huawei.hms:hihealth-base:5.0.0.300'
14) Enter the below permission in android manifest file
Code:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.BODY_SENSORS" />
15) Now Sync the gradle.
Huawei ID authentication
Sign in with Huawei ID authentication and apply for the scope to obtain the permissions to access the Health Kit APIs. Different scopes correspond to different permissions. Developers can apply for permissions based on service requirements.
Code:
public void doLogin(View view) {
Log.i(TAG, "begin sign in");
List<Scope> scopeList = new ArrayList<>();
scopeList.add(new Scope(Scopes.HEALTHKIT_STEP_BOTH));
scopeList.add(new Scope(Scopes.HEALTHKIT_HEIGHTWEIGHT_BOTH));
scopeList.add(new Scope(Scopes.HEALTHKIT_ACTIVITY_BOTH));
HuaweiIdAuthParamsHelper authParamsHelper = new HuaweiIdAuthParamsHelper(
HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM);
mHuaweiIdAuthParams = authParamsHelper.setIdToken()
.setAccessToken()
.setScopeList(scopeList)
.createParams();
mHuaweiIdAuthService = HuaweiIdAuthManager.getService(SplashActivity.this, mHuaweiIdAuthParams);
startActivityForResult(mHuaweiIdAuthService.getSignInIntent(), REQUEST_SIGN_IN_LOGIN);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_SIGN_IN_LOGIN) {
Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data);
if (authHuaweiIdTask.isSuccessful()) {
AuthHuaweiId huaweiAccount = authHuaweiIdTask.getResult();
Log.i("TAG", "accessToken:" + huaweiAccount.getAccessToken());
AGConnectAuthCredential credential = HwIdAuthProvider.credentialWithToken(huaweiAccount.getAccessToken());
AGConnectAuth.getInstance().signIn(credential).addOnSuccessListener(new OnSuccessListener<SignInResult>() {
@Override
public void onSuccess(SignInResult signInResult) {
mUser = AGConnectAuth.getInstance().getCurrentUser();
Intent intent = new Intent(SplashActivity.this,InstructionActivity.class);
startActivity(intent);
finish();
}
});
} else {
Log.e("TAG", "sign in failed : " + ((ApiException) authHuaweiIdTask.getException()).getStatusCode());
}
}
}
Below is the link to know more about the mapping between scopes and permissions:
https://developer.huawei.com/consumer/en/doc/HMSCore-References-V5/scopes-0000001050092713-V5
SensorController
As the name suggested it will gather information using sensor of android mobile device. Using SensorController of HMS Health Kit:
1) We can connect to a built-in sensor of the phone such as a pedometer to obtain data.
2) We can connect to an external BLE device such as heart rate strap to obtain data.
Here we will use SensorController to count the number of steps taken by our users. In order to that we need to directly call the register method of SensorsController to register a listener to obtain the data reported by the built-in sensor.
Obtain SensorController object
Code:
HiHealthOptions options = HiHealthOptions.builder().build();
AuthHuaweiId signInHuaweiId = HuaweiIdAuthManager.getExtendedAuthResult(options);
sensorsController = HuaweiHiHealth.getSensorsController(this, signInHuaweiId);
Register a listener to listen to the step count
Code:
private OnSamplePointListener onStepPointListener = new OnSamplePointListener() {
@Override
public void onSamplePoint(SamplePoint samplePoint) {
// The step count, time, and type data reported by the pedometer is called back to the app through
// samplePoint.
showSamplePoint();
mCurrentSamplePoint = samplePoint;
if (mLastSamplePoint == null) {
mLastSamplePoint = samplePoint;
}
}
};
public void registerSteps() {
if (sensorsController == null) {
Toast.makeText(StepsTrackerActivity.this, "SensorsController is null", Toast.LENGTH_LONG).show();
return;
}
DataCollector dataCollector = new DataCollector.Builder()
.setDataType(DataType.DT_CONTINUOUS_STEPS_TOTAL)
.setDataGenerateType(DataCollector.DATA_TYPE_RAW)
.setPackageName(StepsTrackerActivity.this)
.setDeviceInfo(new DeviceInfo("hw", "hw", "hw", 0))
.build();
SensorOptions.Builder builder = new SensorOptions.Builder();
builder.setDataType(DataType.DT_CONTINUOUS_STEPS_TOTAL);
builder.setDataCollector(dataCollector);
sensorsController.register(builder.build(), onStepPointListener)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Toast.makeText(StepsTrackerActivity.this, "Register Success", Toast.LENGTH_LONG).show();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Toast.makeText(StepsTrackerActivity.this, "Register Failed", Toast.LENGTH_LONG).show();
}
});
}
Show SamplePoint data
Code:
private void showSamplePoint() {
if (mLastSamplePoint != null && mCurrentSamplePoint != null) {
SamplePoint samplePoint = mCurrentSamplePoint;
System.out.println("STEPS >>>" + (samplePoint.getFieldValue(Field.FIELD_STEPS).asIntValue()
- mLastSamplePoint.getFieldValue(Field.FIELD_STEPS).asIntValue()));
runOnUiThread(new Runnable() {
@Override
public void run() {
txtSteps.setText(String.valueOf(Integer.parseInt(txtSteps.getText().toString()) + samplePoint.getFieldValue(Field.FIELD_STEPS).asIntValue()
- mLastSamplePoint.getFieldValue(Field.FIELD_STEPS).asIntValue()));
if(selectedWeight.equalsIgnoreCase("Kg")) {
txtCalorie.setText(String.format("%.2f", Integer.parseInt(weight.getText().toString()) * Long.parseLong(txtSteps.getText().toString()) * 0.4 * 0.001 * 1.036) + " Kcal");
}else{
txtCalorie.setText(String.format("%.2f", Integer.parseInt(weight.getText().toString()) * 2.2046226218 * Long.parseLong(txtSteps.getText().toString()) * 0.4 * 0.001 * 1.036) + " Kcal");
}
mLastSamplePoint = samplePoint;
}
});
}
}
Un-Register a listener to stop the step count
Code:
public void unregisterSteps() {
if (sensorsController == null) {
Toast.makeText(StepsTrackerActivity.this, "SensorsController is null", Toast.LENGTH_LONG).show();
return;
}
// Unregister the listener for the step count.
sensorsController.unregister(onStepPointListener).addOnSuccessListener(new OnSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean aBoolean) {
Toast.makeText(StepsTrackerActivity.this, "UnregisterSteps Succeed ...", Toast.LENGTH_LONG).show();
mLastSamplePoint = null;
mCurrentSamplePoint = null;
txtSteps.setText("0");
txtCalorie.setText("0");
btnStartStop.setText("Start Tracking");
isStartStop = true;
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Toast.makeText(StepsTrackerActivity.this, "UnregisterSteps Failed ...", Toast.LENGTH_LONG).show();
}
});
}
Result
ActivityRecordsController
As the name suggested it will record / insert the activity data of user. Here we will insert the steps count taken by user.
Start time and end time for ActivityRecords
We need start and end time to insert the user steps data as show below:
Code:
public static long getEndTime() {
Calendar cal = Calendar.getInstance();
Date now = new Date();
cal.setTime(now);
long endTime = cal.getTimeInMillis();
return endTime;
}
public static long getStartTime() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.HOUR_OF_DAY, -1);
long startTime = cal.getTimeInMillis();
return startTime;
}
Insert ActivityRecords
Using SamplePoint of HMS Health Kit we will insert the step count of user as shown below:
Code:
private void insertActivityRecords(){
HiHealthOptions hihealthOptions = HiHealthOptions.builder().build();
AuthHuaweiId signInHuaweiId = HuaweiIdAuthManager.getExtendedAuthResult(hihealthOptions);
ActivityRecordsController activityRecordsController = HuaweiHiHealth.getActivityRecordsController(StepsTrackerActivity.this, signInHuaweiId);
ActivityRecord activityRecord = new ActivityRecord.Builder()
.setName("AddStepsRecord")
.setDesc("This is Steps record")
.setId("StepId")
.setActivityTypeId(HiHealthActivities.ON_FOOT)
.setStartTime(startTime, TimeUnit.MILLISECONDS)
.setEndTime(endTime, TimeUnit.MILLISECONDS)
.build();
DataCollector dataCollector = new DataCollector.Builder()
.setDataType(DataType.DT_CONTINUOUS_STEPS_DELTA)
.setDataGenerateType(DataCollector.DATA_TYPE_RAW)
.setPackageName(getApplicationContext())
.setDataCollectorName("AddStepsRecord")
.build();
SampleSet sampleSet = SampleSet.create(dataCollector);
SamplePoint samplePoint = sampleSet.createSamplePoint().setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS);
samplePoint.getFieldValue(Field.FIELD_STEPS_DELTA).setIntValue(Integer.parseInt(txtSteps.getText().toString()));
sampleSet.addSample(samplePoint);
ActivityRecordInsertOptions insertOption =
new ActivityRecordInsertOptions.Builder().setActivityRecord(activityRecord).addSampleSet(sampleSet).build();
Task<Void> addTask = activityRecordsController.addActivityRecord(insertOption);
addTask.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
unregisterSteps();
Log.i("ActivityRecords","ActivityRecord add was successful!");
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
String errorCode = e.getMessage();
String errorMsg = HiHealthStatusCodes.getStatusCodeMessage(Integer.parseInt(errorCode));
Log.i("ActivityRecords",errorCode + ": " + errorMsg);
}
});
}
DatePicker
Code:
private void getDatePicker(EditText edtVal){
final Calendar c = Calendar.getInstance();
mYear = c.get(Calendar.YEAR);
mMonth = c.get(Calendar.MONTH);
mDay = c.get(Calendar.DAY_OF_MONTH);
datePickerVal = "";
DatePickerDialog datePickerDialog = new DatePickerDialog(GetRecords.this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year,
int monthOfYear, int dayOfMonth) {
// edtVal.setText(dayOfMonth + "-" + (monthOfYear + 1) + "-" + year);
edtVal.setText(year + "-" + (monthOfYear + 1) + "-" + dayOfMonth);
// datePickerVal = dayOfMonth + "-" + (monthOfYear + 1) + "-" + year;
}
}, mYear, mMonth, mDay);
datePickerDialog.show();
}
TimePicker
Code:
private void getTimePicker(EditText edtVal){
final Calendar c = Calendar.getInstance();
mHour = c.get(Calendar.HOUR_OF_DAY);
mMinute = c.get(Calendar.MINUTE);
// Launch Time Picker Dialog
TimePickerDialog timePickerDialog = new TimePickerDialog(GetRecords.this,
new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay,
int minute) {
edtVal.setText(hourOfDay + ":" + minute);
}
}, mHour, mMinute, false);
timePickerDialog.show();
}
Start & End Time milliseconds conversion
Code:
private long getDateTime(String dateval,String timeval) {
String dateStr = dateval+" "+timeval+":00";
long milliseconds = 0;
try {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date = dateFormat.parse(dateStr);
System.out.println("DATE TIME >>>"+date.getTime());
milliseconds = date.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
return milliseconds;
}
Reading ActivityRecords and Associated Data
Here we can obtain all ActivityRecords within a specific period of time for particular data, or obtain a specific ActivityRecord by name or ID as shown below:
Code:
private void readActivityRecords(){
HiHealthOptions hihealthOptions = HiHealthOptions.builder().build();
AuthHuaweiId signInHuaweiId = HuaweiIdAuthManager.getExtendedAuthResult(hihealthOptions);
ActivityRecordsController activityRecordsController = HuaweiHiHealth.getActivityRecordsController(getApplicationContext(), signInHuaweiId);
ActivityRecordReadOptions readOption =
new ActivityRecordReadOptions.Builder().setTimeInterval(startTime, endTime, TimeUnit.MILLISECONDS)
.readActivityRecordsFromAllApps()
.read(DataType.DT_CONTINUOUS_STEPS_DELTA)
.build();
Task<ActivityRecordReply> getTask = activityRecordsController.getActivityRecord(readOption);
getTask.addOnSuccessListener(new OnSuccessListener<ActivityRecordReply>() {
@Override
public void onSuccess(ActivityRecordReply activityRecordReply) {
Log.i("ActivityRecords","Get ActivityRecord was successful!");
//Print ActivityRecord and corresponding activity data in the result.
List<ActivityRecord> activityRecordList = activityRecordReply.getActivityRecords();
for (ActivityRecord activityRecord : activityRecordList) {
DateFormat dateFormat = DateFormat.getDateInstance();
DateFormat timeFormat = DateFormat.getTimeInstance();
for (SampleSet sampleSet : activityRecordReply.getSampleSet(activityRecord)) {
for (SamplePoint dp : sampleSet.getSamplePoints()) {
String values = "Start: " + dateFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS)) + " " + timeFormat.format(dp.getStartTime(TimeUnit.MILLISECONDS))+"\n"+
"End: " + dateFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS))+ " " + timeFormat.format(dp.getEndTime(TimeUnit.MILLISECONDS));
for (Field field : dp.getDataType().getFields()) {
/*Log.i("ActivityRecordSample",
"\tField: " + field.toString() + " Value: " + dp.getFieldValue(field));*/
values = values +"\n"+"Step Taken: " + dp.getFieldValue(field);
}
samplePointList.add(values);
}
}
}
showTheList();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
String errorCode = e.getMessage();
String errorMsg = HiHealthStatusCodes.getStatusCodeMessage(Integer.parseInt(errorCode));
Log.i("ActivityRecords",errorCode + ": " + errorMsg);
}
});
}
Result
What we learn?
We learn how to make the usage of two beautiful services provided by HMS Health Kit and also situation where we need the most, in this case fetching user steps and inserting/fetching the data when we need to show in the app.
GitHub
Very soon I am going to post the entire code on GitHub. So come back again to check it out.
For more reference
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/service-introduction-0000001050071661-V5
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/sensorscontroller-develop-0000001050069728-V5
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/activityrecord-develop-0000001050069730-V5

Displaying the Cellular (LTE) Connection Values Obtained by HMS Wireless Kit and the Location Information Obtained Using the Location Kit on the Map K

Displaying the Cellular (LTE) Connection Values Obtained by HMS Wireless Kit and the Location Information Obtained Using the Location Kit on the Map 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"
}
​
Hello everyone,
In this article, I will explain what the cellular data values obtained using the Wireless Kit are, how they are used and how the Wireless Kit values obtained based on location can be displayed on the map using the Huawei Map kit and Location kit. Let’s start with the use of the Wireless Kit first.
Wireless Kit Integration and Use of Wireless Kit Data
First we are creating our Application Gallery Connect website project and integrating the HMS core into our application. You can learn the detailed information required for these procedures from the link.
https://developer.huawei.com/consumer/en/hms/huawei-wirelesskit/
Then we create the buttons of the application, which we will do in three stages in MainActivity as below.
​We define the buttons we have created in the MainActivity class as below.
Java:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "<!!!> MainActivity";
private TextView resultTextView;
private int textCounter = 0;
private NetworkQoeService networkQoeService;
private LocationService locationService;
private String networkData = null, qoeLevel = null;
private Location locationData = null;
private AlertDialog progressDialog;
@Override
protected void onDestroy() {
super.onDestroy();
networkQoeService.DestroyService();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
networkQoeService = new NetworkQoeService(this);
locationService = new LocationService(this);
resultTextView = findViewById(R.id.resultext);
resultTextView.setMovementMethod(new ScrollingMovementMethod());
Button callbackButton = findViewById(R.id.callbackbtn);
Button realTimeDataButton = findViewById(R.id.getrealtimebtn);
Button openMapButton = findViewById(R.id.openMapButton);
callbackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getCallBackData();
}
});
realTimeDataButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getNetworkData();
}
});
openMapButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
progressDialog = showProgressAlertDialog();
getNetworkData();
getLocationData();
}
});
}
We enter the necessary permissions as in the manifest file below.
Code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.huawei.wirelesskit_codelab">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.huawei.permission.SECURITY_DIAGNOSE"/>
<application
android:name=".wirelesskit.MapKitApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.WirelessKitCodelab">
<activity android:name=".wirelesskit.activity.PermissionActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".wirelesskit.activity.MainActivity"
android:screenOrientation="portrait"/>
<activity android:name=".wirelesskit.activity.MapActivity"/>
<activity android:name=".wirelesskit.video.PlayActivity"
android:theme="@style/Theme.AppCompat.NoActionBar"
android:screenOrientation="landscape"/>
</application>
</manifest>
When we press the callbackButton, which is the first button we defined above, we call the getCallBackData method below and obtain your cellular (LTE) connection’s identifier, uplink latency, downlink latency, uplink bandwidth, downlink bandwidth, uplink rate, downlink rate, QoE level and uplink packet loss rate data respectively.
getCallBackData method can be viewed from the link below.
Java:
private void getCallBackData() {
Bundle data = NetworkQoeService.qoeInfo;
if(data != null)
{
int channelNum = 0;
if (data.containsKey("channelNum")) {
channelNum = data.getInt("channelNum");
}
String channelQoe = "channelNum: " + channelNum;
for (int i = 0; i < channelNum; i++) {
// channelQoe can be displayed on the user interface through EditText.
channelQoe += ",channelIndex: " + data.getInt("channelIndex" + i) + ",uLRtt: " + data.getInt("uLRtt" + i) + ",dLRtt: "
+ data.getInt("dLRtt" + i) + ",uLBandwidth: " + data.getInt("uLBandwidth" + i) + ",dLBandwidth: "
+ data.getInt("dLBandwidth" + i) + ",uLRate: " + data.getInt("uLRate" + i) + ",dLRate: "
+ data.getInt("dLRate" + i) + ",netQoeLevel: " + data.getInt("netQoeLevel" + i) + ",uLPkgLossRate: "
+ data.getInt("uLPkgLossRate" + i)+"\n";
}
updateText(channelQoe);
}else
{
Log.e(TAG, "callbackData else");
}
}
You can also look at the link below for detail information about the getCallBackData() method results.
https://developer.huawei.com/consum...eferences-V5/iqoecallback-0000001050986863-V5
Secondly, we call the getNetworkData() method using the realTimeDataButton button and get real-time NetworkQoe information of the application. In other words, we obtain the last second connection information.
​We do this process using the networkQoeService.GetRealTimeData () command as in the code section below.
Java:
private void getNetworkData() {
Bundle data = networkQoeService.GetRealTimeData();
if(data != null) {
int channelNum = 0;
if (data.containsKey("channelNum")) {
channelNum = data.getInt("channelNum");
}
int index = channelNum - 1;
networkData = "Channel Number : " + channelNum + "\n" +
"Channel Index : " + data.getInt("channelIndex" + index) + "\n" +
"UpLink Latency : " + data.getInt("uLRtt" + index) + "\n" +
"DownLink Latency : " + data.getInt("dLRtt" + index) + "\n" +
"UpLink Bandwidth : " + data.getInt("uLBandwidth" + index) + "\n" +
"DownLink Bandwidth : " + data.getInt("dLBandwidth" + index) + "\n" +
"UpLink Rate : " + data.getInt("uLRate" + index) + "\n" +
"DownLink Rate : " + data.getInt("dLRate" + index) + "\n" +
"QoE Level : " + data.getInt("netQoeLevel" + index) + "\n" +
"UpLink Package Loss Rate : " + data.getInt("uLPkgLossRate" + index) + "\n" +
"Download Speed in Mbps : " + data.getInt("dLBandwidth" + index) / 1000.0
;
qoeLevel = data.getInt("netQoeLevel" + index) + "";
updateText(networkData);
}
else {
Log.e(TAG, "realTimeData else");
}
}
Integration of Location and Map Kit and Displaying the Data Obtained on the Screen
We call the showProgressAlertDialog(), getNetworkData(), getLocationData() methods using the openMapButton button we created in our manifest. First, we use the showProgressAlertDialog() method to print the “loading” screen to indicate to the user that the screen should be waited until the other operations to be performed and the location and cellular connection information provided on the map are completed. We do this process using the code section below.
Java:
private AlertDialog showProgressAlertDialog(){
AlertDialog.Builder builder;
builder = new AlertDialog.Builder(this);
builder.setTitle("Loading...");
LayoutInflater factory = LayoutInflater.from(this);
View progressBar = factory.inflate(R.layout.progress_bar, null);
builder.setView(progressBar);
AlertDialog alertDialog = builder.create();
alertDialog.setCancelable(false);
alertDialog.show();
return alertDialog;
}
Secondly, we get real-time NetworkQoe information of the application by calling the getNetworkData() method. We will use the netQoeLevel data in the Wireless Kit results. The netQoeLevel variable takes one of the 4 and 5 values as in the pictures below, according to the connection quality. If the user has a smooth network performance, this value will return 4. However, if the user has poor network performance, this value will return 5.
Finally, we get the location information of the user calling the getLocationData() method, when the network connection quality is calculated. We do the process of obtaining location information as below.
Java:
private void getLocationData() {
locationService.getLocationUpdate(new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult != null) {
locationData = locationResult.getLastLocation();
openMapActivity();
locationService.stopLocationUpdates(this);
progressDialog.cancel();
}
}
});
}
As you see in the code section above, we use the getLocationUpdate method to get location information. Then we get the last location information using getLastLocation() method and we start our map operations using the openMapActivity() method. When we start this process, we stop the location service update process using stopLocationUpdates() because we have obtain the necessary location data. In addition, since the map opening process will start, we use progressDialog.cancel () to close the loading screen.
In the openMapActivity () method, we open the MapActivity using the necessary network information and location information as in the code section below.
Java:
private void openMapActivity() {
this.startActivity(MapActivity.newIntent(this, networkData, qoeLevel, locationData.getLatitude(), locationData.getLongitude()));
}
In the MapActivity’s onCreate() method we are directed here, we make the necessary assignments to the parameters, the width and length of our map, and the necessary definitions for the mapView.
Java:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
networkData = getIntent().getStringExtra(KEY_NETWORK_DATA);
qoeLevel = getIntent().getStringExtra(KEY_QOE_LEVEL);
double latitude = getIntent().getDoubleExtra(KEY_LATITUDE, 0);
double longitude = getIntent().getDoubleExtra(KEY_LONGITUDE, 0);
latLng = new LatLng(latitude, longitude);
mMapView = findViewById(R.id.mapView);
Bundle mapViewBundle = null;
if (savedInstanceState != null) {
mapViewBundle = savedInstanceState.getBundle(MAP_VIEW_BUNDLE_KEY);
}
MapsInitializer.setApiKey(API_KEY);
mMapView.onCreate(mapViewBundle);
mMapView.getMapAsync(this);
}
After completing the operations above, we will work on the onMapReady() method. In this method, we do our map configurations in the section we specified with the update camera view. Then we set the marker in If condition, which will show the user’s location on the map according to the qoeLevel value in the network data we receive from the Wireless Kit. As we explained above in our article, the netQoeLevel parameter will return 4 if the user has a smooth network connection, and in this case, we set the marker showing the user’s location to green. But if the user has poor network performance, this value will return as 5, and in this case, we set the location marker on the map to red to indicate the weak link. Then, when we click on these markers, we define InfoWindowAdapter on HuaweiMap to display network information on the screen. After these processes are finished, we create a LinearLayout to place the network connection data we receive from the Wireless Kit. Finally, we add the titles of the markers that indicate the network quality status that we have determined according to the netQoeLevel parameter to the LinearLayout we have created before, after adjusting the properties such as title text, background like below.
Java:
public void onMapReady(HuaweiMap huaweiMap) {
//update camera view
CameraUpdateParam cameraUpdateParam = new CameraUpdateParam();
cameraUpdateParam.setLatLng(latLng);
CameraUpdate cameraUpdate = new CameraUpdate(cameraUpdateParam);
huaweiMap.moveCamera(cameraUpdate);
//add marker
MarkerOptions markerOptions = new MarkerOptions()
.position(latLng)
.snippet(networkData);
if (GOOD_QOE_LEVEL.equals(qoeLevel)){
markerOptions.title("GOOD NETWORK CONNECTION");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
}
else if (BAD_QOE_LEVEL.equals(qoeLevel)) {
markerOptions.title("BAD NETWORK CONNECTION");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
}
huaweiMap.addMarker(markerOptions);
huaweiMap.setInfoWindowAdapter(new HuaweiMap.InfoWindowAdapter() {
@Override
public View getInfoContents(Marker marker) {
return null;
}
@Override
public View getInfoWindow(Marker marker) {
LinearLayout info = new LinearLayout(MapActivity.this);
info.setOrientation(LinearLayout.VERTICAL);
TextView title = new TextView(MapActivity.this);
title.setTextColor(Color.BLACK);
title.setBackgroundColor(Color.LTGRAY);
title.setTypeface(null, Typeface.BOLD);
title.setText(marker.getTitle());
TextView snippet = new TextView(MapActivity.this);
snippet.setTextColor(Color.BLACK);
snippet.setBackgroundColor(Color.LTGRAY);
snippet.setText(marker.getSnippet());
info.addView(title);
info.addView(snippet);
return info;
}
});
}
You can see the screenshots we created below. Thus, we complete our application.
​
You can visit the link below for detailed information about the Wireless Kit.
https://developer.huawei.com/consumer/en/hms/huawei-wirelesskit/
You can visit the link below for detailed information about the Map Kit.
https://developer.huawei.com/consumer/en/hms/huawei-MapKit/
You can visit the link below for detailed information about the Location Kit.
https://developer.huawei.com/consumer/en/hms/huawei-locationkit/
Thank you for taking your time and reading my article. Hope to see you in my next forum xda article.
​

Categories

Resources