Overview
In this article, I will create a demo app along with the integration of HMS Ads and Analytics Kit which is based on Cross-platform Technology Xamarin. I have implemented Ads Kit and Analytics Kit. So the developer can easily monetise their efforts using Banner, Splash, Reward and Interstitial Ads also to track the user’s behaviour through the Analytics kit.
Ads Kit Service Introduction
HMS Ads kit is powered by Huawei which allows the developer to monetization services such as Banner, Splash, Reward and Interstitial Ads. HUAWEI Ads Publisher Service is a monetization service that leverages Huawei's extensive data capabilities to display targeted, high-quality ad content in your application to the vast user base of Huawei devices.
Analytics Kit Service Introduction
Analytics kit is powered by Huawei which allows rich analytics models to help you clearly understand user behaviour and gain in-depth insights into users, products, and content. As such, you can carry out data-driven operations and make strategic decisions about app marketing and product optimization.
Analytics Kit implements the following functions using data collected from apps:
1. Provides data collection and reporting APIs for collection and reporting custom events.
2. Sets up to 25 user attributes.
3. Supports automatic event collection and session calculation as well as predefined event IDs and parameters.
Prerequisite
1. Xamarin Framework
2. Huawei phone
3. Visual Studio 2019
App Gallery Integration process
1. Sign In and Create or Choose a project on AppGallery Connect portal.
{
"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"
}
2. Add SHA-256 key.
3. Navigate to Project settings and download the configuration file.
4. Navigate to General Information, and then provide Data Storage location.
5. Navigate to Manage APIs and enable APIs to require by application.
6. Navigate to Huawei Analytics > Overview > Custom dashboard > Enable Analytics
Xamarin Analytics Kit Setup Process
1. Download Xamarin Plugin of all the aar and zip files from below URL:
https://developer.huawei.com/consum...ibrary-V1/xamarin-android-0000001061360985-V1
2. Open the XHiAnalytics-5.0.5.300.sln solution in Visual Studio.
3. Navigate to Solution Explorer and right-click on jar Add > Existing Item and choose aar file which download in Step 1.
4. Choose aar file from download location.
5. Right-click on added aar file, then choose Properties > Build Action > LibraryProjectZip.
Note: Repeat Step 3 and 4 for all aar file.
6. Build the Library and make DLL files.
Xamarin Ads Kit Setup Process
1. Download Xamarin Plugin of all the aar and zip files from below URL:
https://developer.huawei.com/consum..._TOPIC_0000001050175494__section1134316505481
2. Open the XAdsIdentifier-3.4.35.300.sln solution in Visual Studio.
3. Navigate to Solution Explorer and right-click on jar Add > Existing Item and choose aar file which download in Step 1.
4. Choose aar file from download location.
5. Right-click on added aar file, then choose Properties > Build Action > LibraryProjectZip.
Note: Repeat Step 3 and 4 for all aar file.
6. Build the Library and make DLL files.
Xamarin App Development
1. Open Visual Studio 2019 and Create A New Project.
2. Navigate to Solution Explore > Project > Add > Add New Folder.
3. Navigate to Folder(created) > Add > Add Existing and add all DLL files.
Read full article in forum
Ads Kit Integration
Banner Ads Integration Procedure
Kindly refer to the below link:
https://developer.huawei.com/consum...in-Guides/xamarin-banner-ads-0000001050418457
Reward Ads Integration Procedure
Kindly refer to the below link:
https://developer.huawei.com/consum...-Guides/xamarin-rewarded-ads-0000001050178541
Interstitial Ads Integration Procedure
Kindly refer to the below link:
https://developer.huawei.com/consum...ugin-Guides/interstitial-ads-0000001050176486
Splash Ads Integration Procedure
Kindly refer to the below link:
https://developer.huawei.com/consum...in-Guides/xamarin-splash-ads-0000001050418461
Analytics Kit Integration
Initializing Analytics Kit Procedure
Kindly refer to the below link:
https://developer.huawei.com/consum...-Plugin-Guides/initanalytics-0000001050141599
LoginActivity.cs
This activity performs all the operation regarding login with Huawei Id along with display banner ads at bottom of the screen along with track analytics events.
C#:
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
using Android.Support.V4.App;
using Android.Support.V4.Content;
using Android.Support.V7.App;
using Android.Util;
using Android.Views;
using Android.Widget;
using Com.Huawei.Agconnect.Config;
using Com.Huawei.Hmf.Tasks;
using Com.Huawei.Hms.Ads;
using Com.Huawei.Hms.Ads.Banner;
using Com.Huawei.Hms.Ads.Nativead;
using Com.Huawei.Hms.Analytics;
using Com.Huawei.Hms.Common;
using Com.Huawei.Hms.Support.Hwid;
using Com.Huawei.Hms.Support.Hwid.Request;
using Com.Huawei.Hms.Support.Hwid.Result;
using Com.Huawei.Hms.Support.Hwid.Service;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WeatherAppDemo
{
[Activity(Label = "LoginActivity", Theme = "@style/AppTheme", MainLauncher = true)]
public class LoginActivity : AppCompatActivity
{
private static String TAG = "LoginActivity";
private HuaweiIdAuthParams mAuthParam;
public static IHuaweiIdAuthService mAuthManager;
// private NativeAd nativeAd;
private Button btnLoginWithHuaweiId;
HiAnalyticsInstance instance;
InterstitialAd interstitialAd;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.login_activity);
loadBannerAds();
HiAnalyticsTools.EnableLog();
// Generate the Analytics Instance
instance = HiAnalytics.GetInstance(this);
// You can also use Context initialization
// Context context = ApplicationContext;
// instance = HiAnalytics.GetInstance(context);
// Enable collection capability
instance.SetAnalyticsEnabled(true);
btnLoginWithHuaweiId = FindViewById<Button>(Resource.Id.btn_huawei_id);
btnLoginWithHuaweiId.Click += delegate
{
// Write code for Huawei id button click
mAuthParam = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DefaultAuthRequestParam)
.SetIdToken().SetEmail()
.SetAccessToken()
.CreateParams();
mAuthManager = HuaweiIdAuthManager.GetService(this, mAuthParam);
StartActivityForResult(mAuthManager.SignInIntent, 1011);
string text = "Login Clicked";
Toast.MakeText(Android.App.Application.Context, text, ToastLength.Short).Show();
// Initiate Parameters
Bundle bundle = new Bundle();
bundle.PutString("text", text);
instance.OnEvent("ButtonClickEvent", bundle);
navigateToHomeScreen();
};
checkPermission(new string[] { Android.Manifest.Permission.Internet,
Android.Manifest.Permission.AccessNetworkState,
Android.Manifest.Permission.ReadSms,
Android.Manifest.Permission.ReceiveSms,
Android.Manifest.Permission.SendSms,
Android.Manifest.Permission.BroadcastSms}, 100);
}
private void loadBannerAds()
{
// Obtain BannerView based on the configuration in layout
BannerView bottomBannerView = FindViewById<BannerView>(Resource.Id.hw_banner_view);
bottomBannerView.AdListener = new AdsListener();
AdParam adParam = new AdParam.Builder().Build();
bottomBannerView.LoadAd(adParam);
// Obtain BannerView using coding
BannerView topBannerview = new BannerView(this);
topBannerview.AdId = "testw6vs28auh3";
topBannerview.BannerAdSize = BannerAdSize.BannerSize32050;
topBannerview.LoadAd(adParam);
}
private void LoadInterstitialAd()
{
InterstitialAd interstitialAd = new InterstitialAd(this);
interstitialAd.AdId = "testb4znbuh3n2"; //testb4znbuh3n2 is a dedicated test ad slot ID.
AdParam adParam = new AdParam.Builder().Build();
interstitialAd.LoadAd(adParam);
}
private void ShowInterstitial()
{
interstitialAd.AdListener = new AdsListenerInterstitial(this);
// Display an interstitial ad.
if (interstitialAd != null && interstitialAd.IsLoaded)
{
interstitialAd.Show();
}
else
{
// The ad was not loaded.
}
}
private class AdsListenerInterstitial : AdListener
{
LoginActivity interstitialActivity;
public AdsListenerInterstitial(LoginActivity interstitialActivity)
{
this.interstitialActivity = interstitialActivity;
}
public override void OnAdClicked()
{
// Called when an ad is clicked.
}
public override void OnAdClosed()
{
// Called when an ad is closed.
}
public override void OnAdFailed(int errorCode)
{
// Called when an ad fails to be loaded.
}
public override void OnAdLeave()
{
// Called when a user leaves an ad.
}
public override void OnAdLoaded()
{
// Called when an ad is loaded successfully.
// Display an interstitial ad.
interstitialActivity.ShowInterstitial();
}
public override void OnAdOpened()
{
// Called when an ad is opened.
}
}
public void checkPermission(string[] permissions, int requestCode)
{
foreach (string permission in permissions)
{
if (ContextCompat.CheckSelfPermission(this, permission) == Permission.Denied)
{
ActivityCompat.RequestPermissions(this, permissions, requestCode);
}
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected override void AttachBaseContext(Context context)
{
base.AttachBaseContext(context);
AGConnectServicesConfig config = AGConnectServicesConfig.FromContext(context);
config.OverlayWith(new HmsLazyInputStream(context));
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 1011 || requestCode == 1022)
{
//login success
Task authHuaweiIdTask = HuaweiIdAuthManager.ParseAuthResultFromIntent(data);
if (authHuaweiIdTask.IsSuccessful)
{
AuthHuaweiId huaweiAccount = (AuthHuaweiId)authHuaweiIdTask.TaskResult();
Log.Info(TAG, "signIn get code success.");
Log.Info(TAG, "ServerAuthCode: " + huaweiAccount.AuthorizationCode);
Toast.MakeText(Android.App.Application.Context, "SignIn Success", ToastLength.Short).Show();
// navigateToHomeScreen(huaweiAccount);
}
else
{
Log.Info(TAG, "signIn failed: " + ((ApiException)authHuaweiIdTask.Exception).StatusCode);
Toast.MakeText(Android.App.Application.Context, ((ApiException)authHuaweiIdTask.Exception).StatusCode.ToString(), ToastLength.Short).Show();
Toast.MakeText(Android.App.Application.Context, "SignIn Failed", ToastLength.Short).Show();
}
}
}
private void showLogoutButton()
{
/*logout.Visibility = Android.Views.ViewStates.Visible;*/
}
private void hideLogoutButton()
{
/*logout.Visibility = Android.Views.ViewStates.Gone;*/
}
private void navigateToHomeScreen(/*AuthHuaweiId data*/)
{
Intent intent = new Intent(this, typeof(MainActivity));
/*intent.PutExtra("name", data.DisplayName.ToString());
intent.PutExtra("email", data.Email.ToString());
intent.PutExtra("image", data.PhotoUriString.ToString());*/
StartActivity(intent);
Finish();
}
private class AdsListener : AdListener
{
public override void OnAdClicked()
{
// Called when a user taps an ad.
Log.Info(TAG, "Ad Clicked");
Toast.MakeText(Application.Context, "Ad Clicked", ToastLength.Short).Show();
}
public override void OnAdClosed()
{
// Called when an ad is closed.
Log.Info(TAG, "Ad Closed");
Toast.MakeText(Application.Context, "Ad Closed", ToastLength.Short).Show();
}
public override void OnAdFailed(int errorCode)
{
// Called when an ad fails to be loaded.
Log.Info(TAG, "Ad Failed");
Toast.MakeText(Application.Context, "Ad Failed", ToastLength.Short).Show();
}
public override void OnAdLeave()
{
// Called when a user has left the app.
Log.Info(TAG, "Ad Leave");
/*Toast.MakeText(Android.App.Application.Context, "Ad Leave", ToastLength.Short).Show();*/
}
public override void OnAdOpened()
{
// Called when an ad is opened.
Log.Info(TAG, "Ad Opened");
/*Toast.MakeText(Android.App.Application.Context, "Ad Opened", ToastLength.Short).Show();*/
}
public override void OnAdLoaded()
{
// Called when an ad is loaded successfully.
Log.Info(TAG, "Ad Loaded");
Toast.MakeText(Application.Context, "Ad Loaded", ToastLength.Short).Show();
}
}
}
}
Tips and Tricks
1. On mobile phones whose value of targetSdkVersion is 28 or later, ad video assets may fail to be downloaded. In this case, you need to configure the app to allow HTTP network requests. For details, please refer to Configuring Network Permissions.
2. Xamarin requires the ADB daemon to be started over port 5037. If the ADB daemon runs on a different port, Visual Studio will not be able to detect your device.
Conclusion
In this article, we have learned how to integrate HMS Ads and Analytics Kit in Xamarin based Android application. We can display ads and track the user’s event in the application.
Thanks for reading this article.
Be sure to like and comments on this article, if you found it helpful. It means a lot to me.
References
https://developer.huawei.com/consum...-Guides/service-introduction-0000001050178531
https://developer.huawei.com/consum..._TOPIC_0000001050175494__section1134316505481
https://developer.huawei.com/consum...S-Plugin-Guides/introduction-0000001050139636
https://forums.developer.huawei.com/forumPortal/en/topic/0204485009808440045
Read full article in forum
Related
More information like this, you can visit HUAWEI Developer Forum
Introduction
Huawei Flight booking application is to explore HMS kits in real time scenario. This app can be used as reference to CP during HMS integration.
Prerequisite
1) You must have Huawei developer account.
2) Huawei phone with HMS 4.0.0.300 or later
3) Android Studio, JDK 1.8, SDK platform 26 and Gradle 4.6 installed.
Permissions
Provide following permissions in manifest.
Code:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
User Sign in
HUAWEI Account Kit offers easy, stable and fast login, and authorization functions to developers. Instead of entering accounts and passwords, you can simply tap the sign-in button with HUAWEI ID to log in your application easily and safely.
Setup:
1) Create a project in android studio.
2) Get the SHA-256 Key.
3) Create an app in the Huawei app gallery connect.
4) Enable account kit setting in Manage APIs Section.
5) Provide the SHA-256 Key in App Information Section.
6) Provide storage location.
7) Enable Huawei account under Auth Service in AGC.
{
"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"
}
8) After completing all the above points we need to download the agconnect-services.json from App Information Section. Place the json file in the app folder of the android project.
9) Enter the below maven URL inside the repositories of buildscript and allprojects respectively (project build.gradle file).
Code:
maven { url 'http://developer.huawei.com/repo/' }
10) Enter the below plugin in the app build.gradle file.
Code:
apply plugin: 'com.huawei.agconnect'
dependencies {
implementation 'com.huawei.hms:hwid:4.0.0.300'
11) Now Sync the gradle.
Implementation
1) In this app, we can implement Authorization code method.
Code:
HuaweiIdAuthParams authParams = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode().createParams();
huaweiservice = HuaweiIdAuthManager.getService(MainActivity.this, authParams);
startActivityForResult(huaweiservice.getSignInIntent(), HUAWEI_SIGNIN);
2) To Process the sign-in result after the authorization is complete.
Code:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == HUAWEI_SIGNIN) {
com.huawei.hmf.tasks.Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data);
if (authHuaweiIdTask.isSuccessful()) {
//The sign-in is successful, and the user's HUAWEI ID information and authorization code are obtained.
AuthHuaweiId huaweiAccount = authHuaweiIdTask.getResult();
Log.i(TAG, "Authorization code:" + huaweiAccount.getAuthorizationCode());
Log.d(TAG, "name: " + huaweiAccount.getDisplayName());
Log.d(TAG, "email: " + huaweiAccount.getEmail());
Log.d(TAG , "avatar : "+huaweiAccount.getAvatarUriString());
launchLoggedinActivity(huaweiAccount.getFamilyName() , huaweiAccount.getGivenName() , huaweiAccount.getAvatarUriString(),"huawei");
} else {
// The sign-in failed.
Log.e(TAG, "sign in failed : " + ((com.huawei.hms.common.ApiException) authHuaweiIdTask.getException()).getStatusCode());
}
}
}
3) To handle silent Sign-in
The authorization is required only for first registration with the HUAWEI ID. Then no approval is required for subsequent registrations with the same HUAWEI ID.
Code:
private void handleHuaweiSilentSignIn() {
HuaweiIdAuthParams authParams = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM).createParams();
HuaweiIdAuthService service = HuaweiIdAuthManager.getService(MainActivity.this, authParams);
com.huawei.hmf.tasks.Task<AuthHuaweiId> task = service.silentSignIn();
task.addOnSuccessListener(new OnSuccessListener<AuthHuaweiId>() {
@Override
public void onSuccess(AuthHuaweiId authHuaweiId) {
// Obtain the user's HUAWEI ID information.
Log.i(TAG, "displayName:" + authHuaweiId.getDisplayName());
launchLoggedinActivity(authHuaweiId.getFamilyName() , authHuaweiId.getGivenName() , authHuaweiId.getAvatarUriString(),"huawei");
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// The sign-in failed. Try to sign in explicitly using getSignInIntent().
if (e instanceof ApiException) {
ApiException apiException = (ApiException)e;
Log.i(TAG, "sign failed status:" + apiException.getStatusCode());
}
}
});
}
4) To sign out from Huawei account.
Code:
Task<Void> signOutTask = service.signOut();
signOutTask.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
Log.i(TAG, "signOut complete");
}
});
5) To revoke authorization
Code:
service.cancelAuthorization().addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
// Processing after a successful authorization revoking.
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);
}
}
}
Integrating Huawei Banner Ads
Ad kit service makes easy for developers to raise money with high-quality advertising from mobile devices. It maximizes the value of every impression by combining global advertiser demand, innovative ad formats, and advanced app monetization technology.
Showing ads to app users helps you to create a reliable revenue stream to help your company grow while concentrating on creating and improving quality apps. Advertisers can attract new consumers and users can discover related goods and services while enjoying free apps. So it is a win for developers, users, and advertisers.
In this app, we will integrate Huawei banner ad. It is a Rectangular advertising on the top or bottom of the screen show. When users interact with the app, banner ads remain on the screen and it can be refreshed periodically for a period of time.
Usecase
We will show banner ad at the bottom of flight search screen.
Implementation
1) Enter the below maven URL inside the repositories of buildscript and allprojects (project build.gradle file).
Code:
implementation 'com.huawei.hms:ads-lite:13.4.30.307'
2) To integrate Huawei banner ad, add BannerView in xml.
Code:
<RelativeLayout xmlns:hwads="http://schemas.android.com/apk/res-auto" >
<com.huawei.hms.ads.banner.BannerView
android:id="@+id/huawei_banner_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:visibility="gone"
hwads:adId="testw6vs28auh3"
hwads:bannerSize="BANNER_SIZE_360_57"/>
Note: We are using test ad ID. "testw6vs28auh3" is a dedicated test ad slot ID.
3) To show Banner Ad.
Code:
if(Utility.isDeviceHuaweiManufacturer() && Utility.isHuaweiMobileServicesAvailable(this)) {
hwBannerView = findViewById(R.id.huawei_banner_view);
hwBannerView.setVisibility(View.VISIBLE);
// Create an ad request to load an ad.
AdParam adParam = new AdParam.Builder().build();
hwBannerView.loadAd(adParam);
hwBannerView.setAdListener(adListener);
} private AdListener adListener = new AdListener() {
@Override
public void onAdLoaded() {
// Called when an ad is loaded successfully.
Log.d(TAG , "onAdLoaded");
}
@Override
public void onAdFailed(int errorCode) {
// Called when an ad fails to be loaded.
Log.d(TAG , "onAdFailed");
}
@Override
public void onAdOpened() {
// Called when an ad is opened.
Log.d(TAG , "onAdOpened");
}
@Override
public void onAdClicked() {
// Called when a user taps an ad.
Log.d(TAG , "onAdClicked");
}
@Override
public void onAdLeave() {
// Called when a user has left the app.
Log.d(TAG , "onAdLeave");
}
@Override
public void onAdClosed() {
// Called when an ad is closed.
Log.d(TAG , "onAdClosed");
}
};
Conclusion:
We have learnt how easy it is to integrate Huawei account and ads kit in the flight booking application.
Stay tune for next article to see more Huawei kit integration in flight booking app.
Links:
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/introduction-0000001050048870
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/publisher-service-introduction-0000001050064960
does huawei mobile services provide flight booking api?
More information like this, you can visit HUAWEI Developer Forum
Introduction
Huawei Cab Application is to explore more about HMS Kits in real time scenario, we can use this app as reference to CP during HMS integration, and they can understand easily how HMS works in real time scenario, refer previous article.
Dashboard Module
The Dashboard page allows a user to book a cab with help of Huawei location, map and site kits, as follows:
Location kit provides to get the current location and location updates, and it provides flexible location based services globally to the users.
Huawei Map kit is to display maps, it covers map data of more than 200 countries and regions for searching any location address.
Site kit provides with convenient and secure access to diverse, place-related services to users.
Kits covered in Dashboard Module:
1. Location kit
2. Map kit
3. Site kit
4. Ads kit
Third Party API’s:
1. TomTom for Directions API
App Screenshots:
Auto fetch current location and also customize current location button in huawei map.
{
"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"
}
Pick destination you want to travel with marker in the huawei map view.
Pick destination using HMS Site Kit.
Draw route between start and end location.
Huawei Location Kit
HUAWEI Location Kit combines the GPS, Wi-Fi, and base station location functionalities in your app to build up global positioning capabilities, allowing you to provide flexible location-based services targeted at users around globally. Currently, it provides three main capabilities: fused location, activity identification, and geo-fence. You can call one or more of these capabilities as needed.
Huawei Map Kit
The HMS Core Map SDK is a set of APIs for map development in Android. The map data covers most countries outside China and supports multiple languages. The Map SDK uses the WGS 84 GPS coordinate system, which can meet most requirements of map development outside China. You can easily add map-related functions in your Android app, including:
Map display: Displays buildings, roads, water systems, and Points of Interest (POIs).
Map interaction: Controls the interaction gestures and buttons on the map.
Map drawing: Adds location markers, map layers, overlays, and various shapes.
Site Kit
HUAWEI Site Kit provide to users with convenient and secure access to diverse, place-related services.
Ads Kit
Huawei Ads provide developers extensive data capabilities to deliver high quality ad content to users. By integrating HMS ads kit we can start earning right away. It is very useful particularly when we are publishing a free app and want to earn some money from it.
Integrating HMS ads kit does not take more than 10 minuts HMS ads kit currently offers five types of ad format like Banner, Native, Rewarded, Interstitial and Splash ads.
In this article, we will see banner ad also.
Banner Ad: Banner ads are rectangular images that occupy a spot at the top, middle, or bottom within an app's layout. Banner ads refresh automatically at regular intervals. When a user taps a banner ad, the user is redirected to the advertiser's page in most cases.
TomTom for Direction API
TomTom Technology for a moving world. Meet the leading independent location, navigation and map technology specialist.
Follow the steps for TomTom Direction API.
Step1: Visit TomTom Developer Portal. https://developer.tomtom.com/
Step2: Login/Signup.
Step3: Click PRODUCTS and select Directions API
Step 4: Route API, as follows: https://developer.tomtom.com/routing-api/routing-api-documentation-routing/calculate-route
Step5: Click MY DASHBOARD and Copy Key and Use it in your application.
Integration Preparations
To integrate HUAWEI Map, Site, Location and Ads Kit, you must complete the following preparations:
Create an app in AppGallery Connect.
Create a project in Android Studio.
Generate a signing certificate.
Generate a signing certificate fingerprint.
Configure the signing certificate fingerprint.
Add the app package name and save the configuration file.
Add the AppGallery Connect plug-in and the Maven repository in the project-level build.gradle file.
Configure the signature file in Android Studio.
Configuring the Development Environment
Enabling HUAWEI Map, Site, Location and Ads Kit.
1. Sign in to AppGallery Connect, select My apps, click an app, and navigate to Develop > Overview > Manage APIs.
2. Click agconnect-services.json to download the configuration file.
3. Copy the agconnect-services.json file to the app's root directory.
4. Open the build.gradle file in the root directory of your Android Studio project.
5. Configure the following information in the build.gradle file.
Code:
buildscript {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
classpath 'com.huawei.agconnect:agcp:1.3.2.301'
}
}
allprojects {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
}
6. Open the build.gradle file in the app directory.
7. Add Dependencies in app level build.gradle.
Code:
apply plugin: 'com.huawei.agconnect'dependencies {
implementation 'com.huawei.hms:maps:5.0.1.300'
implementation 'com.huawei.hms:location:5.0.0.302'
implementation 'com.huawei.hms:site:5.0.0.300'
implementation 'com.huawei.hms:ads-lite:13.4.30.307'
}
8. Apply for relevant permissions in sections at the same level as the application section in the AndroidManifest.xml file.
Code:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
9. Add Huawei MapView and Banner Ad in layout file: activity_maview.xml
Code:
<!--MapView-->
<com.huawei.hms.maps.MapView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mapview"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraTargetLat="51"
map:cameraTargetLng="10"
map:cameraZoom="8.5"
map:mapType="normal"
map:uiCompass="true"
map:uiZoomControls="true" />
<!--BannerView-->
<com.huawei.hms.ads.banner.BannerView
android:id="@+id/hw_banner_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
hwads:adId="@string/banner_ad_id"
android:layout_alignParentTop="true"
hwads:bannerSize="BANNER_SIZE_360_57" />
10. Add the configuration for calling the MapView to the activity.
Code:
class DashboardFragment : Fragment(), OnMapReadyCallback, ReverseGeoCodeListener {private var hMap: HuaweiMap? = null
private var mMapView: MapView? = null
private var pickupLat: Double = 0.0
private var pickupLng: Double = 0.0
private var dropLat: Double = 0.0
private var dropLng: Double = 0.0
private var mPolyline: Polyline? = null
private var mMarkerDestination: Marker? = nulloverride fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) // create fusedLocationProviderClient
mFusedLocationProviderClient = LocationServices.getFusedLocation ProviderClient(activity) mapView?.onCreate(savedInstanceState)
mapView?.onResume()
mapView?.getMapAsync(this)}
fun initBannerAds() {
// Obtain BannerView based on the configuration in layout.
val adParam: AdParam = AdParam.Builder().build()
hw_banner_view.loadAd(adParam)
}
override fun onMapReady(map: HuaweiMap) {
Log.d(TAG, "onMapReady: ")
hMap = map hMap?.isMyLocationEnabled = true
hMap?.uiSettings?.isMyLocationButtonEnabled = false
getLastLocation()
hMap?.setOnCameraMoveStartedListener {
when (it) {
HuaweiMap.OnCameraMoveStartedListener.REASON_GESTURE -> {
Log.d(TAG, "The user gestured on the map.")
val midLatLng: LatLng = hMap?.cameraPosition!!.target
Log.d("Moving_LatLng ", "" + midLatLng)
dropLat = midLatLng.latitude
dropLng = midLatLng.longitude
val task = MyAsyncTask(this, false)
task.execute(midLatLng.latitude, midLatLng.longitude) }
HuaweiMap.OnCameraMoveStartedListener
.REASON_API_ANIMATION -> {
Log.d(TAG, "The user tapped something on the map.")
}
HuaweiMap.OnCameraMoveStartedListener
.REASON_DEVELOPER_ANIMATION -> {
Log.d(TAG, "The app moved the camera.")
}
}
}
}
11. Add the life cycle method of the MapView
Code:
override fun onStart() {
super.onStart()
mMapView?.onStart()
}
override fun onStop() {
super.onStop()
mMapView?.onStop()
}
override fun onDestroy() {
super.onDestroy()
mMapView?.onDestroy()
}
override fun onPause() {
mMapView?.onPause()
super.onPause()
}
override fun onResume() {
super.onResume()
mMapView?.onResume()
}
override fun onLowMemory() {
super.onLowMemory()
mMapView?.onLowMemory()
}
12. Check permissions to let the user allow App to access user location from android 6.0
Code:
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Log.i(TAG, "sdk < 28 Q")
if (checkSelfPermission(
this,
ACCESS_FINE_LOCATION
) != PERMISSION_GRANTED && checkSelfPermission(
this,
ACCESS_COARSE_LOCATION
) != PERMISSION_GRANTED
) {
val strings = arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION)
requestPermissions(this, strings, 1)
}
} else {
if (checkSelfPermission(
[email protected],
ACCESS_FINE_LOCATION
) != PERMISSION_GRANTED && checkSelfPermission(
[email protected], ACCESS_COARSE_LOCATION
) != PERMISSION_GRANTED && checkSelfPermission(
[email protected],
"android.permission.ACCESS_BACKGROUND_LOCATION"
) != PERMISSION_GRANTED
) {
val strings = arrayOf(
ACCESS_FINE_LOCATION,
ACCESS_COARSE_LOCATION,
"android.permission.ACCESS_BACKGROUND_LOCATION"
)
requestPermissions(this, strings, 2)
}
}
13. In you activity you need to handle the response by this way.
Code:
Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == 1) {
if (grantResults.size > 1 && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED) {
Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSION successful")
} else {
Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSSION failed")
}
}
if (requestCode == 2) {
if (grantResults.size > 2 && grantResults[2] == PERMISSION_GRANTED && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED) { override fun onRequestPermissionsResult(requestCode: Int, permissions: Log.i(TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION successful")
} else {
Log.i(TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION failed")
}
}
}
You can perform subsequent steps by referring to the RequestLocationUpdatesWithCallbackActivity.kt file.
14. Create a location provider client and device setting client.
Code:
// create fusedLocationProviderClient
fusedLocationProviderClient=LocationServices.getFusedLocationProviderClient(this)
// create settingsClient
settingsClient = LocationServices.getSettingsClient(this)
15. Create a location request.
Code:
mLocationRequest = LocationRequest().apply {
// set the interval for location updates, in milliseconds
interval = 1000
needAddress = true
// set the priority of the request
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
16. Create a result callback.
Code:
mLocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
if (locationResult != null) {
val locations: List<Location> =
locationResult.locations
if (locations.isNotEmpty()) {
for (location in locations) {
LocationLog.i(TAG,"onLocationResult location[Longitude,Latitude,Accuracy]:${location.longitude} , ${location.latitude} , ${location.accuracy}")
}
}
}
}
override fun onLocationAvailability(locationAvailability: LocationAvailability?) {
locationAvailability?.let {
val flag: Boolean = locationAvailability.isLocationAvailable
LocationLog.i(TAG, "onLocationAvailability isLocationAvailable:$flag")
}
}
}
17. Request location updates.
Code:
private fun requestLocationUpdatesWithCallback() {
try {
val builder = LocationSettingsRequest.Builder()
builder.addLocationRequest(mLocationRequest)
val locationSettingsRequest = builder.build()
// check devices settings before request location updates.
//Before requesting location update, invoke checkLocationSettings to check device settings.
val locationSettingsResponseTask: Task<LocationSettingsResponse> = settingsClient.checkLocationSettings(locationSettingsRequest)
locationSettingsResponseTask.addOnSuccessListener { locationSettingsResponse: LocationSettingsResponse? ->
Log.i(TAG, "check location settings success {$locationSettingsResponse}")
// request location updates
fusedLocationProviderClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper())
.addOnSuccessListener {
LocationLog.i(TAG, "requestLocationUpdatesWithCallback onSuccess")
}
.addOnFailureListener { e ->
LocationLog.e(TAG, "requestLocationUpdatesWithCallback onFailure:${e.message}")
}
}
.addOnFailureListener { e: Exception ->
LocationLog.e(TAG, "checkLocationSetting onFailure:${e.message}")
when ((e as ApiException).statusCode) {
LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try {
val rae = e as ResolvableApiException
rae.startResolutionForResult(
[email protected]uestLocationUpdatesWithCallbackActivity, 0
)
} catch (sie: SendIntentException) {
Log.e(TAG, "PendingIntent unable to execute request.")
}
}
}
} catch (e: Exception) {
LocationLog.e(TAG, "requestLocationUpdatesWithCallback exception:${e.message}")
}
}
18. Remove location updates.
Code:
private fun removeLocationUpdatesWithCallback() {
try {
fusedLocationProviderClient.removeLocationUpdates(mLocationCallback)
.addOnSuccessListener {
LocationLog.i(
TAG,
"removeLocationUpdatesWithCallback onSuccess"
)
}
.addOnFailureListener { e ->
LocationLog.e(
TAG,
"removeLocationUpdatesWithCallback onFailure:${e.message}"
)
}
} catch (e: Exception) {
LocationLog.e(
TAG,
"removeLocationUpdatesWithCallback exception:${e.message}"
)
}
}
19. Reverse Geocoding
Code:
companion object {
private const val TAG = "MapViewDemoActivity"
private const val MAPVIEW_BUNDLE_KEY = "MapViewBundleKey"
class MyAsyncTask internal constructor(
private val context: DashboardFragment,
private val isStartPos: Boolean
) : AsyncTask<Double, Double, String?>() {
private var resp: String? = null
lateinit var geocoding: Geocoding
override fun onPreExecute() {
}
override fun doInBackground(vararg params: Double?): String? {
try {
geocoding = Geocoding()
geocoding.reverseGeoCodeListener = context
geocoding.reverseGeocoding(
"reverseGeocode",
"YOUR_API_KEY",
params[0],
params[1],
isStartPos
)
} catch (e: InterruptedException) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
return resp
} override fun onPostExecute(result: String?) {
}
override fun onProgressUpdate(vararg values: Double?) {
}
}
}
20. Geocoding class for converting latlng into Address
Code:
class Geocoding {
var reverseGeoCodeListener: ReverseGeoCodeListener? = null
val ROOT_URL = "https://siteapi.cloud.huawei.com/mapApi/v1/siteService/"
val conection =
"?key="
val JSON = MediaType.parse("application/json; charset=utf-8")
open fun reverseGeocoding(serviceName: String, apiKey: String?, lat: Double?, lng: Double?, isStartPos: Boolean) {
var sites: String = ""
val json = JSONObject()
val location = JSONObject()
try {
location.put("lng", lng)
location.put("lat", lat)
json.put("location", location)
json.put("language", "en")
json.put("politicalView", "CN")
json.put("returnPoi", true)
Log.d("MapViewDemoActivity",json.toString())
} catch (e: JSONException) {
Log.e("error", e.message)
}
val body : RequestBody = RequestBody.create(JSON, json.toString())
val client = OkHttpClient()
val request = Request.Builder()
.url(ROOT_URL + serviceName + conection + URLEncoder.encode(apiKey, "UTF-8"))
.post(body)
.build()
client.newCall(request).enqueue(object : Callback {
@Throws(IOException::class)
override fun onResponse(call: Call, response: Response) {
var str_response = response.body()!!.string()
val json_response:JSONObject = JSONObject(str_response)
val responseCode:String = json_response.getString("returnCode")
if (responseCode.contentEquals("0")) {
Log.d("ReverseGeocoding", str_response)
var jsonarray_sites: JSONArray = json_response.getJSONArray("sites")
var i:Int = 0
var size:Int = jsonarray_sites.length()
var json_objectdetail:JSONObject=jsonarray_sites.getJSONObject(0)
sites = json_objectdetail.getString("formatAddress")
Log.d("formatAddress", sites)
reverseGeoCodeListener?.getAddress(sites, isStartPos)
} else{
sites = "No Result"
Log.d("formatAddress", "")
reverseGeoCodeListener?.onAdddressError(sites)
}
}
override fun onFailure(call: Call, e: IOException) {
sites = "No Result"
Log.e("ReverseGeocoding", e.toString())
reverseGeoCodeListener?.onAdddressError(sites)
}
})
}
}
This is not the end. For full content, you can visit https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201352135916100198&fid=0101187876626530001
When am integrating site getting error code 6? can you explain why
sujith.e said:
When am integrating site getting error code 6? can you explain why
Click to expand...
Click to collapse
Hi, Sujith.e. The possible cause is that the API key contains special characters. You need to encode the special characters using encodeURI.
Overview
In this article, I will create a demo app along with the integration of HMS ML Kit which based on Cross-platform Technology Xamarin. User can easily scan any items from this application with camera Product Vision Search ML Kit technique and choose best price and details of product.
{
"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"
}
Service Introduction
HMS ML Kit allows your apps to easily leverage Huawei's long-term proven expertise in machine learning to support diverse artificial intelligence (AI) applications throughout a wide range of industries.
A user can take a photo of a product. Then the Product Visual Search service searches for the same or similar products in the pre-established product image library and returns the IDs of those products and related information. In addition, to better manage products in real-time, this service supports offline product import, online product addition, deletion, modification, query, and product distribution.
We can capture any kind of image for products to buy or check the price of a product using Machine Learning. It will give the other options so that you can improve your buying skills.
Prerequisite
1. Xamarin Framework
2. Huawei phone
3. Visual Studio 2019
App Gallery Integration process
1. Sign In and Create or Choose a project on AppGallery Connect portal.
2. Add SHA-256 key.
3. Navigate to Project settings and download the configuration file.
4. Navigate to General Information, and then provide Data Storage location.
5. Navigate to Manage APIs and enable APIs which require by application.
Xamarin ML Kit Setup Process
1. Download Xamarin Plugin all the aar and zip files from below url:
https://developer.huawei.com/consum...Library-V1/xamarin-plugin-0000001053510381-V1
2. Open the XHms-ML-Kit-Library-Project.sln solution in Visual Studio.
3. Navigate to Solution Explore and right-click on jar Add > Exsiting Item and choose aar file which download in Step 1.
4. Right click on added aar file then choose Properties > Build Action > LibraryProjectZip
Note: Repeat Step 3 & 4 for all aar file.
5. Build the Library and make dll files.
Xamarin App Development
1. Open Visual Studio 2019 and Create A New Project.
2. Navigate to Solution Explore > Project > Assets > Add Json file.
3. Navigate to Solution Explore > Project > Add > Add New Folder.
4. Navigate to Folder(created) > Add > Add Existing and add all DLL files.
5. Select all DLL files.
6. Right-click on Properties, choose Build Action > None.
7. Navigate to Solution Explore > Project > Reference > Right Click > Add References, then navigate to Browse and add all DLL files from recently added folder.
8. Added reference, then click OK.
ML Product Visual Search API Integration
1. Create an analyzer for product visual search. You can create the analyzer using the MLRemoteProductVisionSearchAnalyzerSetting class.
C#:
// Method 1: Use default parameter settings.
MLRemoteProductVisionSearchAnalyzer analyzer = MLAnalyzerFactory.Instance.RemoteProductVisionSearchAnalyzer;
// Method 2: Use customized parameter settings.
MLRemoteProductVisionSearchAnalyzerSetting settings = new MLRemoteProductVisionSearchAnalyzerSetting.Factory()
// Set the maximum number of products that can be returned.
.SetLargestNumOfReturns(16)
.Create();
MLRemoteProductVisionSearchAnalyzer analyzer = MLAnalyzerFactory.Instance.GetRemoteProductVisionSearchAnalyzer(settings);
2. Create an MLFrame object by using Android.Graphics.Bitmap. JPG, JPEG, PNG, and BMP images are supported.
C#:
// Create an MLFrame object using the bitmap, which is the image data in bitmap format.
MLFrame frame = MLFrame.FromBitmap(bitmap);
3. Implement image detection.
Code:
Task<IList<MLProductVisionSearch>> task = this.analyzer.AnalyseFrameAsync(frame);
await task;
if (task.IsCompleted && task.Result != null)
{
// Analyze success.
var productVisionSearchList = task.Result;
if (productVisionSearchList.Count != 0)
{
//Product detected successfully
}
else
{
//Product not found
}
}
4. After the recognition is complete, stop the analyzer to release recognition resources.
if (analyzer != null) {
analyzer.Stop();
}
ProductVisionSearchAnalyseActivity.cs
This activity performs all the operation regarding product search with camera.
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Android;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using AndroidX.AppCompat.App;
using AndroidX.Core.App;
using AndroidX.Core.Content;
using Com.Huawei.Hms.Mlplugin.Productvisionsearch;
using Com.Huawei.Hms.Mlsdk;
using Com.Huawei.Hms.Mlsdk.Common;
using Com.Huawei.Hms.Mlsdk.Productvisionsearch;
using Com.Huawei.Hms.Mlsdk.Productvisionsearch.Cloud;
using Java.Lang;
namespace HmsXamarinMLDemo.MLKitActivities.ImageRelated.ProductVisionSearch
{
[Activity(Label = "ProductVisionSearchAnalyseActivity")]
public class ProductVisionSearchAnalyseActivity : AppCompatActivity, View.IOnClickListener
{
private const string Tag = "ProductVisionSearchTestActivity";
private static readonly int PermissionRequest = 0x1000;
private int CameraPermissionCode = 1;
private static readonly int MaxResults = 1;
private TextView mTextView;
private ImageView productResult;
private Bitmap bitmap;
private MLRemoteProductVisionSearchAnalyzer analyzer;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
this.SetContentView(Resource.Layout.activity_image_product_vision_search_analyse);
this.mTextView = (TextView)this.FindViewById(Resource.Id.result);
this.productResult = (ImageView)this.FindViewById(Resource.Id.image_product);
this.bitmap = BitmapFactory.DecodeResource(this.Resources, Resource.Drawable.custom_model_image);
this.productResult.SetImageResource(Resource.Drawable.custom_model_image);
this.FindViewById(Resource.Id.product_detect_plugin).SetOnClickListener(this);
this.FindViewById(Resource.Id.product_detect).SetOnClickListener(this);
// Checking Camera Permissions
if (!(ActivityCompat.CheckSelfPermission(this, Manifest.Permission.Camera) == Permission.Granted))
{
this.RequestCameraPermission();
}
}
private void RequestCameraPermission()
{
string[] permissions = new string[] { Manifest.Permission.Camera };
if (!ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.Camera))
{
ActivityCompat.RequestPermissions(this, permissions, this.CameraPermissionCode);
return;
}
}
private void CheckPermissions(string[] permissions)
{
bool shouldRequestPermission = false;
foreach (string permission in permissions)
{
if (ContextCompat.CheckSelfPermission(this, permission) != Permission.Granted)
{
shouldRequestPermission = true;
}
}
if (shouldRequestPermission)
{
ActivityCompat.RequestPermissions(this, permissions, PermissionRequest);
return;
}
StartVisionSearchPluginCapture();
}
private async void RemoteAnalyze()
{
// Use customized parameter settings for cloud-based recognition.
MLRemoteProductVisionSearchAnalyzerSetting setting =
new MLRemoteProductVisionSearchAnalyzerSetting.Factory()
// Set the maximum number of products that can be returned.
.SetLargestNumOfReturns(MaxResults)
.SetProductSetId("vmall")
.SetRegion(MLRemoteProductVisionSearchAnalyzerSetting.RegionDrChina)
.Create();
this.analyzer = MLAnalyzerFactory.Instance.GetRemoteProductVisionSearchAnalyzer(setting);
// Create an MLFrame by using the bitmap.
MLFrame frame = MLFrame.FromBitmap(bitmap);
Task<IList<MLProductVisionSearch>> task = this.analyzer.AnalyseFrameAsync(frame);
try
{
await task;
if (task.IsCompleted && task.Result != null)
{
// Analyze success.
var productVisionSearchList = task.Result;
if(productVisionSearchList.Count != 0)
{
Toast.MakeText(this, "Product detected successfully", ToastLength.Long).Show();
this.DisplaySuccess(productVisionSearchList);
}
else
{
Toast.MakeText(this, "Product not found", ToastLength.Long);
}
}
else
{
// Analyze failure.
Log.Debug(Tag, " remote analyze failed");
}
}
catch (System.Exception e)
{
// Operation failure.
this.DisplayFailure(e);
}
}
private void StartVisionSearchPluginCapture()
{
// Set the config params.
MLProductVisionSearchCaptureConfig config = new MLProductVisionSearchCaptureConfig.Factory()
//Set the largest OM detect Result,default is 20,values in 1-100
.SetLargestNumOfReturns(16)
//Set the fragment you created (the fragment should implement AbstractUIExtendProxy)
.SetProductFragment(new ProductFragment())
//Set region,current values:RegionDrChina,RegionDrSiangapore,RegionDrGerman,RegionDrRussia
.SetRegion(MLProductVisionSearchCaptureConfig.RegionDrChina)
//设set product id,you can get the value by AGC
//.SetProductSetId("xxxxx")
.Create();
MLProductVisionSearchCapture capture = MLProductVisionSearchCaptureFactory.Instance.Create(config);
//Start plugin
capture.StartCapture(this);
}
private void DisplayFailure(System.Exception exception)
{
string error = "Failure. ";
try
{
MLException mlException = (MLException)exception;
error += "error code: " + mlException.ErrCode + "\n" + "error message: " + mlException.Message;
}
catch (System.Exception e)
{
error += e.Message;
}
this.mTextView.Text = error;
}
private void DrawBitmap(ImageView imageView, Rect rect, string product)
{
Paint boxPaint = new Paint();
boxPaint.Color = Color.White;
boxPaint.SetStyle(Paint.Style.Stroke);
boxPaint.StrokeWidth = (4.0f);
Paint textPaint = new Paint();
textPaint = new Paint();
textPaint.Color = Color.White;
textPaint.TextSize = 100.0f;
imageView.DrawingCacheEnabled = true;
Bitmap bitmapDraw = Bitmap.CreateBitmap(this.bitmap.Copy(Bitmap.Config.Argb8888, true));
Canvas canvas = new Canvas(bitmapDraw);
canvas.DrawRect(rect, boxPaint);
canvas.DrawText("product type: " + product, rect.Left, rect.Top, textPaint);
this.productResult.SetImageBitmap(bitmapDraw);
}
private void DisplaySuccess(IList<MLProductVisionSearch> productVisionSearchList)
{
List<MLVisionSearchProductImage> productImageList = new List<MLVisionSearchProductImage>();
foreach (MLProductVisionSearch productVisionSearch in productVisionSearchList)
{
this.DrawBitmap(this.productResult, productVisionSearch.Border, productVisionSearch.Type);
foreach (MLVisionSearchProduct product in productVisionSearch.ProductList)
{
productImageList.AddRange(product.ImageList);
}
}
StringBuffer buffer = new StringBuffer();
foreach (MLVisionSearchProductImage productImage in productImageList)
{
string str = "ProductID: " + productImage.ProductId + "\nImageID: " + productImage.ImageId + "\nPossibility: " + productImage.Possibility;
buffer.Append(str);
buffer.Append("\n");
}
this.mTextView.Text = buffer.ToString();
this.bitmap = BitmapFactory.DecodeResource(this.Resources, Resource.Drawable.custom_model_image);
this.productResult.SetImageResource(Resource.Drawable.custom_model_image);
}
public void OnClick(View v)
{
switch (v.Id)
{
case Resource.Id.product_detect:
this.RemoteAnalyze();
break;
case Resource.Id.product_detect_plugin:
CheckPermissions(new string[]{Manifest.Permission.Camera, Manifest.Permission.ReadExternalStorage,
Manifest.Permission.WriteExternalStorage, Manifest.Permission.AccessNetworkState});
break;
default:
break;
}
}
protected override void OnDestroy()
{
base.OnDestroy();
if (this.analyzer == null)
{
return;
}
this.analyzer.Stop();
}
}
}
Xamarin App Build
1. Navigate to Solution Explore > Project > Right Click > Archive/View Archive to generate SHA-256 for build release and Click on Distribute.
2. Choose Distribution Channel > Ad Hoc to sign apk.
3. Choose Demo Keystore to release apk.
4. Finally here is the Result.
Tips and Tricks
1. HUAWEI ML Kit complies with GDPR requirements for data processing.
2. HUAWEI ML Kit does not support the recognition of the object distance and colour.
3. Images in PNG, JPG, JPEG, and BMP formats are supported. GIF images are not supported.
Conclusion
In this article, we have learned how to integrate HMS ML Kit in Xamarin based Android application. User can easily search items online with the help of product visual search API in this application.
Thanks for reading this article. Be sure to like and comments to this article, if you found it helpful. It means a lot to me.
References
https://developer.huawei.com/consum...-Plugin-Guides/about-service-0000001052602130
Overview
In this article, I will create a College Campus Placement Centre Demo App which highlights ongoing college placement with all listed companies and their details. Student can easily apply and redeem points through IAP. I have integrated HMS Account and IAP Kit which is based on Cross-platform Technology Xamarin.
HMS IAP Service Introduction
HMS In-App Purchase Kit allows purchasing any product from the application with highly secure payment. Users can purchase a variety of products or services, including common virtual products and subscriptions, directly within your app. It also provides a product management system (PMS) for managing the prices and languages of in-app products (including games) in multiple locations.
These are the following 3 types of in-app products supported by the IAP:
1. Consumable: Consumables are used once, are depleted, and can be purchased again.
2. Non-consumable: Non-consumables are purchased once and do not expire.
3. Auto-renewable subscriptions: Users can purchase access to value-added functions or content in a specified period of time. The subscriptions are automatically renewed on a recurring basis until users decide to cancel.
Account Kit Service Introduction
HMS Account Kit allows you to connect to the Huawei ecosystem using your HUAWEI ID from a range of devices, such as mobile phones, tablets, and smart screens.
It’s a simple, secure, and quick sign-in and authorization functions. Instead of entering accounts and passwords and waiting for authentication.
Complies with international standards and protocols such as OAuth2.0 and OpenID Connect, and supports two-factor authentication (password authentication and mobile number authentication) to ensure high security.
Prerequisite
1. Xamarin Framework
2. Huawei phone
3. Visual Studio 2019
App Gallery Integration process
1. Sign In and Create or Choose a project on AppGallery Connect portal.
{
"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"
}
2. Navigate to Project settings > download the configuration file.
3. Navigate to General Information > Data Storage location.
4. Navigate to Manage APIs > enable APIs to require by an application.
5. Navigate to My apps > Operate, and then enter details in Add Product.
6. Click View and Edit in the above screenshot, enter Product price details, and then click Save.
7. Click Activate for product activation.
Xamarin Account Kit Setup Process
1. Download Xamarin Plugin all the aar and zip files from below URL:
Document
developer.huawei.com
2. Open the XHwid-5.03.302.sln solution in Visual Studio.
Xamarin IAP Kit Setup Process
1. Download Xamarin Plugin all the aar and zip files from below URL:
Document
developer.huawei.com
2. Open the XIAP-5.0.2.300.sln solution in Visual Studio.
3. Navigate to Solution Explorer and Right-click on jar Add > Existing Item and choose aar file which downloads in Step 1.
4. Right-click on added aar file then choose Properties > Build Action > LibraryProjectZip.
Note: Repeat Step 3 & 4 for all aar file.
5. Build the Library and make dll files.
Xamarin App Development
1. Open Visual Studio 2019 and Create a new project.
2. Navigate to Solution Explore > Project > Assets > Add JSON file.
3. Navigate to Solution Explore > Project > Add > Add New Folder.
4. Navigate to Folder(created) > Add > Add Existing and add all DLL files.
5. Right click > Properties > Build Action > None.
6. Navigate to Solution Explore > Project > Reference > Right Click > Add References then Navigate to Browse and add all DLL files from the recently added Folder.
7. Added reference then click Ok.
MainActivity.cs
This activity performs all the operation regarding login with Huawei Id.
Java:
using System;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Support.V4.App;
using Android.Support.V4.Content;
using Android.Support.V7.App;
using Android.Util;
using Android.Views;
using Android.Widget;
using Com.Huawei.Agconnect.Config;
using Com.Huawei.Hmf.Tasks;
using Com.Huawei.Hms.Common;
using Com.Huawei.Hms.Iap;
using Com.Huawei.Hms.Iap.Entity;
using Com.Huawei.Hms.Support.Hwid;
using Com.Huawei.Hms.Support.Hwid.Request;
using Com.Huawei.Hms.Support.Hwid.Result;
using Com.Huawei.Hms.Support.Hwid.Service;
namespace PlacementApp
{
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
private Button btnLoginWithHuaweiId;
private HuaweiIdAuthParams mAuthParam;
public static IHuaweiIdAuthService mAuthManager;
private static String TAG = "MainActivity";
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_main);
Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
btnLoginWithHuaweiId = FindViewById<Button>(Resource.Id.btn_huawei_id);
// Write code for Huawei id button click
mAuthParam = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DefaultAuthRequestParam)
.SetIdToken().SetEmail()
.SetAccessToken()
.CreateParams();
mAuthManager = HuaweiIdAuthManager.GetService(this, mAuthParam);
// Click listener for each button
btnLoginWithHuaweiId.Click += delegate
{
StartActivityForResult(mAuthManager.SignInIntent, 1011);
};
CheckIfIAPAvailable();
/*FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab);
fab.Click += FabOnClick;*/
//check permissions
checkPermission(new string[] { Android.Manifest.Permission.Internet,
Android.Manifest.Permission.AccessNetworkState,
Android.Manifest.Permission.ReadSms,
Android.Manifest.Permission.ReceiveSms,
Android.Manifest.Permission.SendSms,
Android.Manifest.Permission.BroadcastSms}, 100);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 1011)
{
//login success
Task authHuaweiIdTask = HuaweiIdAuthManager.ParseAuthResultFromIntent(data);
if (authHuaweiIdTask.IsSuccessful)
{
AuthHuaweiId huaweiAccount = (AuthHuaweiId)authHuaweiIdTask.TaskResult();
Log.Info(TAG, "signIn get code success.");
Log.Info(TAG, "ServerAuthCode: " + huaweiAccount.AuthorizationCode);
Toast.MakeText(Android.App.Application.Context, "SignIn Success", ToastLength.Short).Show();
ManageHomeScreen(huaweiAccount, true);
}
else
{
Log.Info(TAG, "signIn failed: " + ((ApiException)authHuaweiIdTask.Exception).StatusCode);
Toast.MakeText(Android.App.Application.Context, ((ApiException)authHuaweiIdTask.Exception).StatusCode.ToString(), ToastLength.Short).Show();
Toast.MakeText(Android.App.Application.Context, "SignIn Failed", ToastLength.Short).Show();
ManageHomeScreen(null, false);
}
}
}
public void ManageHomeScreen(AuthHuaweiId data, Boolean loginStatus)
{
if (loginStatus)
{
btnLoginWithHuaweiId.Visibility = ViewStates.Gone;
}
else
{
btnLoginWithHuaweiId.Visibility = ViewStates.Visible;
}
}
public void checkPermission(string[] permissions, int requestCode)
{
foreach (string permission in permissions)
{
if (ContextCompat.CheckSelfPermission(this, permission) == Permission.Denied)
{
ActivityCompat.RequestPermissions(this, permissions, requestCode);
}
}
}
/*private void FabOnClick(object sender, EventArgs eventArgs)
{
View view = (View) sender;
Snackbar.Make(view, "Replace with your own action", Snackbar.LengthLong)
.SetAction("Action", (Android.Views.View.IOnClickListener)null).Show();
}*/
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected override void AttachBaseContext(Context context)
{
base.AttachBaseContext(context);
AGConnectServicesConfig config = AGConnectServicesConfig.FromContext(context);
config.OverlayWith(new HmsLazyInputStream(context));
}
private void CancelAuthorisation()
{
Task cancelAuthorizationTask = mAuthManager.CancelAuthorization();
Log.Info(TAG, "Cancel Authorisation");
cancelAuthorizationTask.AddOnCompleteListener(
new OnCompleteListener
(
this, "Cancel Authorization Success",
"Cancel Authorization Failed"
)
);
}
public void SignOut()
{
Task signOutTask = mAuthManager.SignOut();
signOutTask.AddOnSuccessListener(new OnSuccessListener(this, "SignOut Success"))
.AddOnFailureListener(new OnFailureListener("SignOut Failed"));
}
public class OnCompleteListener : Java.Lang.Object, IOnCompleteListener
{
//Message when task is successful
private string successMessage;
//Message when task is failed
private string failureMessage;
MainActivity context;
public OnCompleteListener(MainActivity context, string SuccessMessage, string FailureMessage)
{
this.context = context;
this.successMessage = SuccessMessage;
this.failureMessage = FailureMessage;
}
public void OnComplete(Task task)
{
if (task.IsSuccessful)
{
//do some thing while cancel success
Log.Info(TAG, successMessage);
//context.SignOut();
}
else
{
//do some thing while cancel failed
Exception exception = task.Exception;
if (exception is ApiException)
{
int statusCode = ((ApiException)exception).StatusCode;
Log.Info(TAG, failureMessage + ": " + statusCode);
}
//context.ManageHomeScreen(null, true);
}
}
}
public class OnSuccessListener : Java.Lang.Object, Com.Huawei.Hmf.Tasks.IOnSuccessListener
{
//Message when task is successful
private string successMessage;
MainActivity context;
public OnSuccessListener(MainActivity context, string SuccessMessage)
{
this.successMessage = SuccessMessage;
this.context = context;
}
public void OnSuccess(Java.Lang.Object p0)
{
Log.Info(TAG, successMessage);
Toast.MakeText(Android.App.Application.Context, successMessage, ToastLength.Short).Show();
context.ManageHomeScreen(null, false);
}
}
public class OnFailureListener : Java.Lang.Object, Com.Huawei.Hmf.Tasks.IOnFailureListener
{
//Message when task is failed
private string failureMessage;
public OnFailureListener(string FailureMessage)
{
this.failureMessage = FailureMessage;
}
public void OnFailure(Java.Lang.Exception p0)
{
Log.Info(TAG, failureMessage);
Toast.MakeText(Android.App.Application.Context, failureMessage, ToastLength.Short).Show();
}
}
public void CheckIfIAPAvailable()
{
IIapClient mClient = Iap.GetIapClient(this);
Task isEnvReady = mClient.IsEnvReady();
isEnvReady.AddOnSuccessListener(new ListenerImp(this)).AddOnFailureListener(new ListenerImp(this));
}
class ListenerImp : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
private MainActivity mainActivity;
public ListenerImp(MainActivity mainActivity)
{
this.mainActivity = mainActivity;
}
public void OnSuccess(Java.Lang.Object IsEnvReadyResult)
{
// Obtain the execution result.
Intent intent = new Intent(mainActivity, typeof(ComapnyActivity));
mainActivity.StartActivity(intent);
}
public void OnFailure(Java.Lang.Exception e)
{
Toast.MakeText(Android.App.Application.Context, "Feature Not available for your country", ToastLength.Short).Show();
if (e.GetType() == typeof(IapApiException))
{
IapApiException apiException = (IapApiException)e;
if (apiException.Status.StatusCode == OrderStatusCode.OrderHwidNotLogin)
{
// Not logged in.
//Call StartResolutionForResult to bring up the login page
}
else if (apiException.Status.StatusCode == OrderStatusCode.OrderAccountAreaNotSupported)
{
// The current region does not support HUAWEI IAP.
}
}
}
}
}
}
CompanyActivity.cs
This activity performs all the operation In-App purchasing and display list of company with package details.
Java:
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.App;
using Android.Support.V7.Widget;
using Android.Util;
using Android.Views;
using Android.Widget;
using Com.Huawei.Hmf.Tasks;
using Com.Huawei.Hms.Iap;
using Com.Huawei.Hms.Iap.Entity;
using Org.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PlacementApp
{
[Activity(Label = "ComapnyActivity", Theme = "@style/AppTheme")]
public class ComapnyActivity : AppCompatActivity, BuyProduct
{
private static String TAG = "ComapnyActivity";
private RecyclerView recyclerView;
private CompanyAdapter adapter;
IList<ProductInfo> productList;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_company);
recyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerview);
recyclerView.SetLayoutManager(new LinearLayoutManager(this));
recyclerView.SetItemAnimator(new DefaultItemAnimator());
//ADAPTER
adapter = new CompanyAdapter(this);
adapter.SetData(productList);
recyclerView.SetAdapter(adapter);
GetProducts();
}
private void GetProducts()
{
List<String> productIdList = new List<String>();
productIdList.Add("Nokia");
productIdList.Add("Hyperlink");
productIdList.Add("Tata");
productIdList.Add("Infosys");
productIdList.Add("Wipro");
ProductInfoReq req = new ProductInfoReq();
// PriceType: 0: consumable; 1: non-consumable; 2: auto-renewable subscription
req.PriceType = 0;
req.ProductIds = productIdList;
//"this" in the code is a reference to the current activity
Task task = Iap.GetIapClient(this).ObtainProductInfo(req);
task.AddOnSuccessListener(new QueryProductListenerImp(this)).AddOnFailureListener(new QueryProductListenerImp(this));
}
class QueryProductListenerImp : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
private ComapnyActivity activity;
public QueryProductListenerImp(ComapnyActivity activity)
{
this.activity = activity;
}
public void OnSuccess(Java.Lang.Object result)
{
// Obtain the result
ProductInfoResult productlistwrapper = (ProductInfoResult)result;
IList<ProductInfo> productList = productlistwrapper.ProductInfoList;
activity.adapter.SetData(productList);
activity.adapter.NotifyDataSetChanged();
}
public void OnFailure(Java.Lang.Exception e)
{
//get the status code and handle the error
}
}
public void OnBuyProduct(ProductInfo pInfo)
{
//Toast.MakeText(Android.App.Application.Context, pInfo.ProductName, ToastLength.Short).Show();
CreatePurchaseRequest(pInfo);
}
private void CreatePurchaseRequest(ProductInfo pInfo)
{
// Constructs a PurchaseIntentReq object.
PurchaseIntentReq req = new PurchaseIntentReq();
// The product ID is the same as that set by a developer when configuring product information in AppGallery Connect.
// PriceType: 0: consumable; 1: non-consumable; 2: auto-renewable subscription
req.PriceType = pInfo.PriceType;
req.ProductId = pInfo.ProductId;
//"this" in the code is a reference to the current activity
Task task = Iap.GetIapClient(this).CreatePurchaseIntent(req);
task.AddOnSuccessListener(new BuyListenerImp(this)).AddOnFailureListener(new BuyListenerImp(this));
}
protected override void OnActivityResult(int requestCode, Android.App.Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 6666)
{
if (data == null)
{
Log.Error(TAG, "data is null");
return;
}
//"this" in the code is a reference to the current activity
PurchaseResultInfo purchaseIntentResult = Iap.GetIapClient(this).ParsePurchaseResultInfoFromIntent(data);
switch (purchaseIntentResult.ReturnCode)
{
case OrderStatusCode.OrderStateCancel:
// User cancel payment.
Toast.MakeText(Android.App.Application.Context, "Payment Cancelled", ToastLength.Short).Show();
break;
case OrderStatusCode.OrderStateFailed:
Toast.MakeText(Android.App.Application.Context, "Order Failed", ToastLength.Short).Show();
break;
case OrderStatusCode.OrderProductOwned:
// check if there exists undelivered products.
Toast.MakeText(Android.App.Application.Context, "Undelivered Products", ToastLength.Short).Show();
break;
case OrderStatusCode.OrderStateSuccess:
// pay success.
Toast.MakeText(Android.App.Application.Context, "Payment Success", ToastLength.Short).Show();
// use the public key of your app to verify the signature.
// If ok, you can deliver your products.
// If the user purchased a consumable product, call the ConsumeOwnedPurchase API to consume it after successfully delivering the product.
String inAppPurchaseDataStr = purchaseIntentResult.InAppPurchaseData;
MakeProductReconsumeable(inAppPurchaseDataStr);
break;
default:
break;
}
return;
}
}
private void MakeProductReconsumeable(String InAppPurchaseDataStr)
{
String purchaseToken = null;
try
{
InAppPurchaseData InAppPurchaseDataBean = new InAppPurchaseData(InAppPurchaseDataStr);
if (InAppPurchaseDataBean.PurchaseStatus != InAppPurchaseData.PurchaseState.Purchased)
{
return;
}
purchaseToken = InAppPurchaseDataBean.PurchaseToken;
}
catch (JSONException e) { }
ConsumeOwnedPurchaseReq req = new ConsumeOwnedPurchaseReq();
req.PurchaseToken = purchaseToken;
//"this" in the code is a reference to the current activity
Task task = Iap.GetIapClient(this).ConsumeOwnedPurchase(req);
task.AddOnSuccessListener(new ConsumListenerImp()).AddOnFailureListener(new ConsumListenerImp());
}
class ConsumListenerImp : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
public void OnSuccess(Java.Lang.Object result)
{
// Obtain the result
Log.Info(TAG, "Product available for purchase");
}
public void OnFailure(Java.Lang.Exception e)
{
//get the status code and handle the error
Log.Info(TAG, "Product available for purchase API Failed");
}
}
class BuyListenerImp : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
private ComapnyActivity activity;
public BuyListenerImp(ComapnyActivity activity)
{
this.activity = activity;
}
public void OnSuccess(Java.Lang.Object result)
{
// Obtain the payment result.
PurchaseIntentResult InResult = (PurchaseIntentResult)result;
if (InResult.Status != null)
{
// 6666 is an int constant defined by the developer.
InResult.Status.StartResolutionForResult(activity, 6666);
}
}
public void OnFailure(Java.Lang.Exception e)
{
//get the status code and handle the error
Toast.MakeText(Android.App.Application.Context, "Purchase Request Failed !", ToastLength.Short).Show();
}
}
}
}
Xamarin App Build Result
1. Navigate to Solution Explore > Project > Right Click > Archive/View Archive to generate SHA-256 for build release and Click on Distribute.
2. Choose Distribution Channel > Ad Hoc to sign apk.
3. Choose Demo Keystore to release apk.
4. Build succeed and Save apk file.
5. Finally here is the result.
Tips and Tricks
1. It is recommended that the app obtains the public payment key from your server in real-time. Do not store it on the app to prevent app version incompatibility caused by the subsequent key upgrade.
2. The sandbox testing function can be used only when the following conditions are met: A sandbox testing account is successfully added, and the value of versionCode of the test package is greater than that of the released package. In the HMS Core IAP SDK 4.0.2, the isSandboxActivated API is added to check whether the current sandbox testing environment is available. If not, the API returns the reason why the environment is unavailable.
Conclusion
In this article, we have learned how to integrate HMS In-App Purchase and Account Kit in Xamarin based Android application. Student can easily apply in a listed company which offers campus placement.
Be sure to like and comments on this article, if you found it helpful. It means a lot to me.
References
Document
developer.huawei.com
Document
developer.huawei.com
Read In Forum
Overview
In this article, I will create a College Campus Placement Centre Demo App which highlights ongoing pool college placement with all listed companies and their details. Student can easily apply and register with available food facility on the campus through IAP. I have integrated HMS Account, Ads, Analytics and IAP Kit which is based on Cross-platform Technology Xamarin.
Ads Kit Service Introduction
HMS Ads kit is powered by Huawei which allows the developer to monetize services such as Banner, Splash, Reward and Interstitial Ads. HUAWEI Ads Publisher Service is a monetization service that leverages Huawei's extensive data capabilities to display targeted, high-quality ad content in your application to the vast user base of Huawei devices.
Analytics Kit Service Introduction
Analytics kit is powered by Huawei which allows rich analytics models to help you clearly understand user behavior and gain in-depth insights into users, products, and content. As such, you can carry out data-driven operations and make strategic decisions about app marketing and product optimization.
Analytics Kit implements the following functions using data collected from apps:
1. Provides data collection and reporting APIs for collection and reporting custom events.
2. Sets up to 25 user attributes.
3. Supports automatic event collection and session calculation as well as predefined event IDs and parameters.
HMS IAP Service Introduction
HMS In-App Purchase Kit allows purchasing any product from the application with highly secure payment. Users can purchase a variety of products or services, including common virtual products and subscriptions, directly within your app. It also provides a product management system (PMS) for managing the prices and languages of in-app products (including games) in multiple locations.
These are the following 3 types of in-app products supported by the IAP:
1. Consumable: Consumables are used once, are depleted, and can be purchased again.
2. Non-consumable: Non-consumables are purchased once and do not expire.
3. Auto-renewable subscriptions: Users can purchase access to value-added functions or content in a specified period of time. The subscriptions are automatically renewed on a recurring basis until users decide to cancel.
Account Kit Service Introduction
HMS Account Kit allows you to connect to the Huawei ecosystem using your HUAWEI ID from a range of devices, such as mobile phones, tablets, and smart screens.
It’s a simple, secure, and quick sign-in and authorization functions. Instead of entering accounts and passwords and waiting for authentication.
Complies with international standards and protocols such as OAuth2.0 and OpenID Connect, and supports two-factor authentication (password authentication and mobile number authentication) to ensure high security.
Prerequisite
1. Xamarin Framework
2. Huawei phone
3. Visual Studio 2019
App Gallery Integration process
1. Sign In and Create or Choose a project on AppGallery Connect portal.
{
"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"
}
2. Navigate to Project settings > download the configuration file.
3. Navigate to General Information > Data Storage location.
4. Navigate to Manage APIs > enable APIs to require by an application.
5. Navigate to My apps > Operate, and then enter details in Add Product.
6. Click Activate for product activation.
7. Navigate to Huawei Analytics > Overview > Custom dashboard > Enable Analytics.
Xamarin Ads Kit Setup Process
1. Download Xamarin Plugin of all the aar and zip files from the URL:
2. Open the XAdsIdentifier-3.4.35.300.sln solution in Visual Studio.
3. Navigate to Solution Explorer and right-click on jar Add > Existing Item and choose aar file which download in Step 1.
4. Choose aar file from download location.
5. Right-click on added aar file, then choose Properties > Build Action > LibraryProjectZip.
Note: Repeat Step 3 and 4 for all aar file.
6. Build the Library and make DLL files.
Xamarin Analytics Kit Setup Process
1. Download Xamarin Plugin of all the aar and zip files from the URL, see the similar image in Ads kit setup Step 1:
2. Open the XHiAnalytics-5.0.5.300.sln solution in Visual Studio, see the similar image in Ads kit setup Step 2.
3. Navigate to Solution Explorer and right-click on jar Add > Existing Item and choose aar file which download in Step 1.
4. Choose aar file from download location.
5. Right-click on added aar file, then choose Properties > Build Action > LibraryProjectZip.
Note: Repeat Step 3 and 4 for all aar file.
6. Build the Library and make DLL files.
Xamarin Account Kit Setup Process
1. Download Xamarin Plugin all the aar and zip files from the URL, see the similar image in Ads kit setup Step 1:
2. Open the XHwid-5.03.302.sln solution in Visual Studio, see the similar image in Ads kit setup Step 2.
Xamarin IAP Kit Setup Process
1. Download Xamarin Plugin all the aar and zip files from the URL, see the similar image in Ads kit setup Step 1:
2. Open the XIAP-5.0.2.300.sln solution in Visual Studio, see the similar image in Ads kit setup Step 2.
3. Navigate to Solution Explorer and Right-click on jar Add > Existing Item and choose aar file which downloads in Step 1.
4. Right-click on added aar file then choose Properties > Build Action > LibraryProjectZip.
Note: Repeat Step 3 and 4 for all aar file.
5. Build the Library and make dll files.
Xamarin App Development
1. Open Visual Studio 2019 and Create a new project.
2. Navigate to Solution Explore > Project > Assets > Add JSON file.
3. Navigate to Solution Explore > Project > Add > Add New Folder.
4. Navigate to Folder(created) > Add > Add Existing and add all DLL files.
5. Right click > Properties > Build Action > None.
6. Navigate to Solution Explore > Project > Reference > Right Click > Add References, then Navigate to Browse and add all DLL files from the recently added Folder.
7. Added reference then click Ok.
MainActivity.cs
This activity performs all the operation regarding login with Huawei Id.
Java:
using System;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Support.V4.App;
using Android.Support.V4.Content;
using Android.Support.V7.App;
using Android.Util;
using Android.Views;
using Android.Widget;
using Com.Huawei.Agconnect.Config;
using Com.Huawei.Hmf.Tasks;
using Com.Huawei.Hms.Common;
using Com.Huawei.Hms.Ads.Banner;
using Com.Huawei.Hms.Analytics;
using Com.Huawei.Hms.Iap;
using Com.Huawei.Hms.Iap.Entity;
using Com.Huawei.Hms.Support.Hwid;
using Com.Huawei.Hms.Support.Hwid.Request;
using Com.Huawei.Hms.Support.Hwid.Result;
using Com.Huawei.Hms.Support.Hwid.Service;
namespace PlacementApp
{
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
private Button btnLoginWithHuaweiId;
private HuaweiIdAuthParams mAuthParam;
public static IHuaweiIdAuthService mAuthManager;
private static String TAG = "MainActivity";
public static String name, email;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_main);
Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
btnLoginWithHuaweiId = FindViewById<Button>(Resource.Id.btn_huawei_id);
// Write code for Huawei id button click
mAuthParam = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DefaultAuthRequestParam)
.SetIdToken().SetEmail()
.SetAccessToken()
.CreateParams();
mAuthManager = HuaweiIdAuthManager.GetService(this, mAuthParam);
HiAnalyticsTools.EnableLog();
instance = HiAnalytics.GetInstance(this);
instance.SetAnalyticsEnabled(true);
// Click listener for each button
btnLoginWithHuaweiId.Click += delegate
{
StartActivityForResult(mAuthManager.SignInIntent, 1011);
string text = "Login Clicked";
Toast.MakeText(Android.App.Application.Context, text, ToastLength.Short).Show();
// Initiate Parameters
Bundle bundle = new Bundle();
bundle.PutString("text", text);
instance.OnEvent("ButtonClickEvent", bundle);
};
CheckIfIAPAvailable();
/*FloatingActionButton fab = FindViewById<FloatingActionButton>(Resource.Id.fab);
fab.Click += FabOnClick;*/
//check permissions
checkPermission(new string[] { Android.Manifest.Permission.Internet,
Android.Manifest.Permission.AccessNetworkState,
Android.Manifest.Permission.ReadSms,
Android.Manifest.Permission.ReceiveSms,
Android.Manifest.Permission.SendSms,
Android.Manifest.Permission.BroadcastSms}, 100);
}
private void loadBannerAds()
{
// Obtain BannerView based on the configuration in layout
BannerView bottomBannerView = FindViewById<BannerView>(Resource.Id.hw_banner_view);
bottomBannerView.AdListener = new AdsListener();
AdParam adParam = new AdParam.Builder().Build();
bottomBannerView.LoadAd(adParam);
// Obtain BannerView using coding
BannerView topBannerview = new BannerView(this);
topBannerview.AdId = "testw6vs28auh3";
topBannerview.BannerAdSize = BannerAdSize.BannerSize32050;
topBannerview.LoadAd(adParam);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 1011)
{
//login success
Task authHuaweiIdTask = HuaweiIdAuthManager.ParseAuthResultFromIntent(data);
if (authHuaweiIdTask.IsSuccessful)
{
AuthHuaweiId huaweiAccount = (AuthHuaweiId)authHuaweiIdTask.TaskResult();
Log.Info(TAG, "signIn get code success.");
Log.Info(TAG, "ServerAuthCode: " + huaweiAccount.AuthorizationCode);
Toast.MakeText(Android.App.Application.Context, "SignIn Success", ToastLength.Short).Show();
ManageHomeScreen(huaweiAccount, true);
}
else
{
Log.Info(TAG, "signIn failed: " + ((ApiException)authHuaweiIdTask.Exception).StatusCode);
Toast.MakeText(Android.App.Application.Context, ((ApiException)authHuaweiIdTask.Exception).StatusCode.ToString(), ToastLength.Short).Show();
Toast.MakeText(Android.App.Application.Context, "SignIn Failed", ToastLength.Short).Show();
ManageHomeScreen(null, false);
}
}
}
public void ManageHomeScreen(AuthHuaweiId data, Boolean loginStatus)
{
if (loginStatus)
{
btnLoginWithHuaweiId.Visibility = ViewStates.Gone;
name = data.DisplayName;
email = data.Email;
}
else
{
btnLoginWithHuaweiId.Visibility = ViewStates.Visible;
}
}
public void checkPermission(string[] permissions, int requestCode)
{
foreach (string permission in permissions)
{
if (ContextCompat.CheckSelfPermission(this, permission) == Permission.Denied)
{
ActivityCompat.RequestPermissions(this, permissions, requestCode);
}
}
}
/*private void FabOnClick(object sender, EventArgs eventArgs)
{
View view = (View) sender;
Snackbar.Make(view, "Replace with your own action", Snackbar.LengthLong)
.SetAction("Action", (Android.Views.View.IOnClickListener)null).Show();
}*/
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
protected override void AttachBaseContext(Context context)
{
base.AttachBaseContext(context);
AGConnectServicesConfig config = AGConnectServicesConfig.FromContext(context);
config.OverlayWith(new HmsLazyInputStream(context));
}
private void CancelAuthorisation()
{
Task cancelAuthorizationTask = mAuthManager.CancelAuthorization();
Log.Info(TAG, "Cancel Authorisation");
cancelAuthorizationTask.AddOnCompleteListener(
new OnCompleteListener
(
this, "Cancel Authorization Success",
"Cancel Authorization Failed"
)
);
}
public void SignOut()
{
Task signOutTask = mAuthManager.SignOut();
signOutTask.AddOnSuccessListener(new OnSuccessListener(this, "SignOut Success"))
.AddOnFailureListener(new OnFailureListener("SignOut Failed"));
}
public class OnCompleteListener : Java.Lang.Object, IOnCompleteListener
{
//Message when task is successful
private string successMessage;
//Message when task is failed
private string failureMessage;
MainActivity context;
public OnCompleteListener(MainActivity context, string SuccessMessage, string FailureMessage)
{
this.context = context;
this.successMessage = SuccessMessage;
this.failureMessage = FailureMessage;
}
public void OnComplete(Task task)
{
if (task.IsSuccessful)
{
//do some thing while cancel success
Log.Info(TAG, successMessage);
//context.SignOut();
}
else
{
//do some thing while cancel failed
Exception exception = task.Exception;
if (exception is ApiException)
{
int statusCode = ((ApiException)exception).StatusCode;
Log.Info(TAG, failureMessage + ": " + statusCode);
}
//context.ManageHomeScreen(null, true);
}
}
}
public class OnSuccessListener : Java.Lang.Object, Com.Huawei.Hmf.Tasks.IOnSuccessListener
{
//Message when task is successful
private string successMessage;
MainActivity context;
public OnSuccessListener(MainActivity context, string SuccessMessage)
{
this.successMessage = SuccessMessage;
this.context = context;
}
public void OnSuccess(Java.Lang.Object p0)
{
Log.Info(TAG, successMessage);
Toast.MakeText(Android.App.Application.Context, successMessage, ToastLength.Short).Show();
context.ManageHomeScreen(null, false);
}
}
public class OnFailureListener : Java.Lang.Object, Com.Huawei.Hmf.Tasks.IOnFailureListener
{
//Message when task is failed
private string failureMessage;
public OnFailureListener(string FailureMessage)
{
this.failureMessage = FailureMessage;
}
public void OnFailure(Java.Lang.Exception p0)
{
Log.Info(TAG, failureMessage);
Toast.MakeText(Android.App.Application.Context, failureMessage, ToastLength.Short).Show();
}
}
public void CheckIfIAPAvailable()
{
IIapClient mClient = Iap.GetIapClient(this);
Task isEnvReady = mClient.IsEnvReady();
isEnvReady.AddOnSuccessListener(new ListenerImp(this)).AddOnFailureListener(new ListenerImp(this));
}
class ListenerImp : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
private MainActivity mainActivity;
public ListenerImp(MainActivity mainActivity)
{
this.mainActivity = mainActivity;
}
public void OnSuccess(Java.Lang.Object IsEnvReadyResult)
{
// Obtain the execution result.
Intent intent = new Intent(mainActivity, typeof(ComapnyActivity));
mainActivity.StartActivity(intent);
}
public void OnFailure(Java.Lang.Exception e)
{
Toast.MakeText(Android.App.Application.Context, "Feature Not available for your country", ToastLength.Short).Show();
if (e.GetType() == typeof(IapApiException))
{
IapApiException apiException = (IapApiException)e;
if (apiException.Status.StatusCode == OrderStatusCode.OrderHwidNotLogin)
{
// Not logged in.
//Call StartResolutionForResult to bring up the login page
}
else if (apiException.Status.StatusCode == OrderStatusCode.OrderAccountAreaNotSupported)
{
// The current region does not support HUAWEI IAP.
}
}
}
}
}
CompanyActivity.cs
This activity performs all the operation In-App purchasing and display list of company with package details.
Java:
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.App;
using Android.Support.V7.Widget;
using Android.Util;
using Android.Views;
using Android.Widget;
using Com.Huawei.Hmf.Tasks;
using Com.Huawei.Hms.Iap;
using Com.Huawei.Hms.Iap.Entity;
using Org.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PlacementApp
{
[Activity(Label = "ComapnyActivity", Theme = "@style/AppTheme")]
public class ComapnyActivity : AppCompatActivity, BuyProduct
{
private static String TAG = "ComapnyActivity";
private RecyclerView recyclerView;
private CompanyAdapter adapter;
IList<ProductInfo> productList;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_company);
recyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerview);
recyclerView.SetLayoutManager(new LinearLayoutManager(this));
recyclerView.SetItemAnimator(new DefaultItemAnimator());
//ADAPTER
adapter = new CompanyAdapter(this);
adapter.SetData(productList);
recyclerView.SetAdapter(adapter);
GetProducts();
}
private void GetProducts()
{
List<String> productIdList = new List<String>();
productIdList.Add("Nokia");
productIdList.Add("Hyperlink");
productIdList.Add("Tata");
productIdList.Add("Infosys");
productIdList.Add("Wipro");
ProductInfoReq req = new ProductInfoReq();
// PriceType: 0: consumable; 1: non-consumable; 2: auto-renewable subscription
req.PriceType = 0;
req.ProductIds = productIdList;
//"this" in the code is a reference to the current activity
Task task = Iap.GetIapClient(this).ObtainProductInfo(req);
task.AddOnSuccessListener(new QueryProductListenerImp(this)).AddOnFailureListener(new QueryProductListenerImp(this));
}
class QueryProductListenerImp : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
private ComapnyActivity activity;
public QueryProductListenerImp(ComapnyActivity activity)
{
this.activity = activity;
}
public void OnSuccess(Java.Lang.Object result)
{
// Obtain the result
ProductInfoResult productlistwrapper = (ProductInfoResult)result;
IList<ProductInfo> productList = productlistwrapper.ProductInfoList;
activity.adapter.SetData(productList);
activity.adapter.NotifyDataSetChanged();
}
public void OnFailure(Java.Lang.Exception e)
{
//get the status code and handle the error
}
}
public void OnBuyProduct(ProductInfo pInfo)
{
//Toast.MakeText(Android.App.Application.Context, pInfo.ProductName, ToastLength.Short).Show();
CreatePurchaseRequest(pInfo);
}
private void CreatePurchaseRequest(ProductInfo pInfo)
{
// Constructs a PurchaseIntentReq object.
PurchaseIntentReq req = new PurchaseIntentReq();
// The product ID is the same as that set by a developer when configuring product information in AppGallery Connect.
// PriceType: 0: consumable; 1: non-consumable; 2: auto-renewable subscription
req.PriceType = pInfo.PriceType;
req.ProductId = pInfo.ProductId;
//"this" in the code is a reference to the current activity
Task task = Iap.GetIapClient(this).CreatePurchaseIntent(req);
task.AddOnSuccessListener(new BuyListenerImp(this)).AddOnFailureListener(new BuyListenerImp(this));
}
protected override void OnActivityResult(int requestCode, Android.App.Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 6666)
{
if (data == null)
{
Log.Error(TAG, "data is null");
return;
}
//"this" in the code is a reference to the current activity
PurchaseResultInfo purchaseIntentResult = Iap.GetIapClient(this).ParsePurchaseResultInfoFromIntent(data);
switch (purchaseIntentResult.ReturnCode)
{
case OrderStatusCode.OrderStateCancel:
// User cancel payment.
Toast.MakeText(Android.App.Application.Context, "Payment Cancelled", ToastLength.Short).Show();
break;
case OrderStatusCode.OrderStateFailed:
Toast.MakeText(Android.App.Application.Context, "Order Failed", ToastLength.Short).Show();
break;
case OrderStatusCode.OrderProductOwned:
// check if there exists undelivered products.
Toast.MakeText(Android.App.Application.Context, "Undelivered Products", ToastLength.Short).Show();
break;
case OrderStatusCode.OrderStateSuccess:
// pay success.
Toast.MakeText(Android.App.Application.Context, "Payment Success", ToastLength.Short).Show();
// use the public key of your app to verify the signature.
// If ok, you can deliver your products.
// If the user purchased a consumable product, call the ConsumeOwnedPurchase API to consume it after successfully delivering the product.
String inAppPurchaseDataStr = purchaseIntentResult.InAppPurchaseData;
MakeProductReconsumeable(inAppPurchaseDataStr);
break;
default:
break;
}
return;
}
}
private void MakeProductReconsumeable(String InAppPurchaseDataStr)
{
String purchaseToken = null;
try
{
InAppPurchaseData InAppPurchaseDataBean = new InAppPurchaseData(InAppPurchaseDataStr);
if (InAppPurchaseDataBean.PurchaseStatus != InAppPurchaseData.PurchaseState.Purchased)
{
return;
}
purchaseToken = InAppPurchaseDataBean.PurchaseToken;
}
catch (JSONException e) { }
ConsumeOwnedPurchaseReq req = new ConsumeOwnedPurchaseReq();
req.PurchaseToken = purchaseToken;
//"this" in the code is a reference to the current activity
Task task = Iap.GetIapClient(this).ConsumeOwnedPurchase(req);
task.AddOnSuccessListener(new ConsumListenerImp()).AddOnFailureListener(new ConsumListenerImp());
}
class ConsumListenerImp : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
public void OnSuccess(Java.Lang.Object result)
{
// Obtain the result
Log.Info(TAG, "Product available for purchase");
}
public void OnFailure(Java.Lang.Exception e)
{
//get the status code and handle the error
Log.Info(TAG, "Product available for purchase API Failed");
}
}
class BuyListenerImp : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
private ComapnyActivity activity;
public BuyListenerImp(ComapnyActivity activity)
{
this.activity = activity;
}
public void OnSuccess(Java.Lang.Object result)
{
// Obtain the payment result.
PurchaseIntentResult InResult = (PurchaseIntentResult)result;
if (InResult.Status != null)
{
// 6666 is an int constant defined by the developer.
InResult.Status.StartResolutionForResult(activity, 6666);
}
}
public void OnFailure(Java.Lang.Exception e)
{
//get the status code and handle the error
Toast.MakeText(Android.App.Application.Context, "Purchase Request Failed !", ToastLength.Short).Show();
}
}
public void OnRegister(int position)
{
//Toast.MakeText(Android.App.Application.Context, "Position is :" + position, ToastLength.Short).Show();
Intent intent = new Intent(this, typeof(RegistrationActivity));
ProductInfo pInfo = productList[position];
intent.PutExtra("price_type", pInfo.PriceType);
intent.PutExtra("product_id", pInfo.ProductId);
intent.PutExtra("price", pInfo.Price);
StartActivity(intent);
}
}
}
RegistrationActivity.cs
This activity performs register student data then redirect to the payment screen through In-App purchasing.
Java:
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.V7.App;
using Android.Util;
using Android.Views;
using Android.Widget;
using Com.Huawei.Hmf.Tasks;
using Com.Huawei.Hms.Iap;
using Com.Huawei.Hms.Iap.Entity;
using Org.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PlacementApp
{
[Activity(Label = "Registration", Theme = "@style/AppTheme")]
class RegistrationActivity : AppCompatActivity
{
private int priceType;
private String productId, price;
private EditText stdName, stdEmail, phoneNo, place;
private TextView regFee;
private Button btnRegister;
private static String TAG = "RegistrationActivity";
private Spinner spinner, spinnerGender;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_registration);
productId = Intent.GetStringExtra("product_id");
priceType = Intent.GetIntExtra("price_type", 0);
price = Intent.GetStringExtra("price");
stdName = FindViewById<EditText>(Resource.Id.name);
stdEmail = FindViewById<EditText>(Resource.Id.email);
phoneNo = FindViewById<EditText>(Resource.Id.phone);
place = FindViewById<EditText>(Resource.Id.place);
regFee = FindViewById<TextView>(Resource.Id.reg_fee);
btnRegister = FindViewById<Button>(Resource.Id.register);
spinner = FindViewById<Spinner>(Resource.Id.branch);
spinner.ItemSelected += SpinnerItemSelected;
spinnerGender = FindViewById<Spinner>(Resource.Id.year);
ArrayAdapter yearAdapter = ArrayAdapter.CreateFromResource(this, Resource.Array.year_array, Android.Resource.Layout.SimpleSpinnerItem);
yearAdapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);
spinnerGender.Adapter = yearAdapter;
ArrayAdapter adapter = ArrayAdapter.CreateFromResource(this, Resource.Array.branch_array, Android.Resource.Layout.SimpleSpinnerItem);
adapter.SetDropDownViewResource(Android.Resource.Layout.SimpleSpinnerDropDownItem);
spinner.Adapter = adapter;
stdName.Text = MainActivity.name;
stdEmail.Text = MainActivity.email;
regFee.Text = "Breakfast Fee : " + price;
btnRegister.Click += delegate
{
CreateRegisterRequest();
};
}
private void SpinnerItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
{
if (e.Position != 0)
{
Spinner spinner = (Spinner)sender;
string name = spinner.GetItemAtPosition(e.Position).ToString();
Toast.MakeText(Android.App.Application.Context, name, ToastLength.Short).Show();
}
}
private void CreateRegisterRequest()
{
// Constructs a PurchaseIntentReq object.
PurchaseIntentReq req = new PurchaseIntentReq();
// The product ID is the same as that set by a developer when configuring product information in AppGallery Connect.
// PriceType: 0: consumable; 1: non-consumable; 2: auto-renewable subscription
req.PriceType = priceType;
req.ProductId = productId;
//"this" in the code is a reference to the current activity
Task task = Iap.GetIapClient(this).CreatePurchaseIntent(req);
task.AddOnSuccessListener(new BuyListenerImp(this)).AddOnFailureListener(new BuyListenerImp(this));
}
class BuyListenerImp : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
private RegistrationActivity regActivity;
public BuyListenerImp(RegistrationActivity regActivity)
{
this.regActivity = regActivity;
}
public void OnSuccess(Java.Lang.Object result)
{
// Obtain the payment result.
PurchaseIntentResult InResult = (PurchaseIntentResult)result;
if (InResult.Status != null)
{
// 6666 is an int constant defined by the developer.
InResult.Status.StartResolutionForResult(regActivity, 6666);
}
}
public void OnFailure(Java.Lang.Exception e)
{
//get the status code and handle the error
Toast.MakeText(Android.App.Application.Context, "Purchase Request Failed !", ToastLength.Short).Show();
}
}
protected override void OnActivityResult(int requestCode, Android.App.Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (requestCode == 6666)
{
if (data == null)
{
Log.Error(TAG, "data is null");
return;
}
//"this" in the code is a reference to the current activity
PurchaseResultInfo purchaseIntentResult = Iap.GetIapClient(this).ParsePurchaseResultInfoFromIntent(data);
switch (purchaseIntentResult.ReturnCode)
{
case OrderStatusCode.OrderStateCancel:
// User cancel payment.
Toast.MakeText(Android.App.Application.Context, "Registration Cancelled", ToastLength.Short).Show();
break;
case OrderStatusCode.OrderStateFailed:
Toast.MakeText(Android.App.Application.Context, "Registration Failed", ToastLength.Short).Show();
break;
case OrderStatusCode.OrderProductOwned:
// check if there exists undelivered products.
Toast.MakeText(Android.App.Application.Context, "Undelivered Products", ToastLength.Short).Show();
break;
case OrderStatusCode.OrderStateSuccess:
// pay success.
Toast.MakeText(Android.App.Application.Context, "Registration Success", ToastLength.Short).Show();
// use the public key of your app to verify the signature.
// If ok, you can deliver your products.
// If the user purchased a consumable product, call the ConsumeOwnedPurchase API to consume it after successfully delivering the product.
String inAppPurchaseDataStr = purchaseIntentResult.InAppPurchaseData;
MakeProductReconsumeable(inAppPurchaseDataStr);
break;
default:
break;
}
return;
}
}
private void MakeProductReconsumeable(String InAppPurchaseDataStr)
{
String purchaseToken = null;
try
{
InAppPurchaseData InAppPurchaseDataBean = new InAppPurchaseData(InAppPurchaseDataStr);
if (InAppPurchaseDataBean.PurchaseStatus != InAppPurchaseData.PurchaseState.Purchased)
{
return;
}
purchaseToken = InAppPurchaseDataBean.PurchaseToken;
}
catch (JSONException e) { }
ConsumeOwnedPurchaseReq req = new ConsumeOwnedPurchaseReq();
req.PurchaseToken = purchaseToken;
//"this" in the code is a reference to the current activity
Task task = Iap.GetIapClient(this).ConsumeOwnedPurchase(req);
task.AddOnSuccessListener(new ConsumListenerImp(this)).AddOnFailureListener(new ConsumListenerImp(this));
}
class ConsumListenerImp : Java.Lang.Object, IOnSuccessListener, IOnFailureListener
{
private RegistrationActivity registrationActivity;
public ConsumListenerImp(RegistrationActivity registrationActivity)
{
this.registrationActivity = registrationActivity;
}
public void OnSuccess(Java.Lang.Object result)
{
// Obtain the result
Log.Info(TAG, "Product available for purchase");
registrationActivity.Finish();
}
public void OnFailure(Java.Lang.Exception e)
{
//get the status code and handle the error
Log.Info(TAG, "Product available for purchase API Failed");
}
}
}
}
Xamarin App Build Result
1. Navigate to Solution Explore > Project > Right Click > Archive/View Archive to generate SHA-256 for build release and Click on Distribute.
2. Choose Distribution Channel > Ad Hoc to sign apk.
3. Choose Demo Keystore to release apk.
4. Build succeed and Save apk file.
5. Final result.
Analytics Report
1. Navigate to Huawei Analytics > Overview > Real-time Overview.
2. Navigate to Huawei Analytics > Overview > Real-time Overview, then check Event analysis.
3. Navigate to App debugging, then track your events.
Tips and Tricks
1. It is recommended that the app obtains the public payment key from your server in real-time. Do not store it on the app to prevent app version incompatibility caused by the subsequent key upgrade.
2. The sandbox testing function can be used only when the following conditions are met: A sandbox testing account is successfully added, and the value of versionCode of the test package is greater than that of the released package. In the HMS Core IAP SDK 4.0.2, the isSandboxActivated API is added to check whether the current sandbox testing environment is available. If not, the API returns the reason why the environment is unavailable.
3. On mobile phones whose value of targetSdkVersion is 28 or later, ad video assets may fail to be downloaded. In this case, you need to configure the app to allow HTTP network requests. For details, please refer to Configuring Network Permissions.
4. Xamarin requires the ADB daemon to be started over port 5037. If the ADB daemon runs on a different port, Visual Studio will not be able to detect your device.
Conclusion
In this article, we have learned how to integrate HMS In-App Purchase, Ads, Analytics and Account Kit in Xamarin based Android application. Student can easily apply in a listed company which offers campus placement.
Be sure to like and comments on this article, if you found it helpful. It means a lot to me.
References
1. Banner Ads Integration Procedure
2. Reward Ads Integration Procedure
3. Interstitial Ads Integration Procedure
4. Initializing Analytics Kit Procedure
Original Source