How to Develop a Reward Ads in 10 Min ? - Huawei Developers

This article is originally from HUAWEI Developer Forum.
Forum link: https://forums.developer.huawei.com/forumPortal/en/home
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Huawei Ads provide developers an extensive data capabilities to deliver high quality ad content to their 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 mins. HMS ads kit currently offers five types of ad format:
v 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.
v Native Ad: Native ads fit seamlessly into the surrounding content to match our app design. Such ads can be customized as needed.
v Reward Ad: Rewarded ads are full-screen video ads that reward users for watching.
v Interstitial Ad: Interstitial ads are full-screen ads that cover the interface of an app. Such ads are displayed when a user starts, pauses, or exits an app, without disrupting the user's experience.
v Splash Ad: Splash ads are displayed immediately after an app is launched, even before the home screen of the app is displayed.
Today in this article we are going to learn how to integrate Reward Ad into our apps.
Prerequisite
1) Must have a Huawei Developer Account
2) Must have a Huawei phone with HMS 4.0.0.300 or later
3) Must have a laptop or desktop with Android Studio , Jdk 1.8, SDK platform 26 and Gradle 4.6 installed.
Things Need To Be Done
1) First we need to create a project in android studio.
2) Get the SHA Key. For getting the SHA key we can refer to this article.
3) Create an app in the Huawei app gallery connect.
4) Provide the SHA Key in App Information Section.
5) Provide storage location.
6) After completing all the above points we need to download the agconnect-services.json from App Information Section. Copy and paste the Json file in the app folder of the android project.
7) Copy and paste the below maven url inside the repositories of buildscript and allprojects ( project build.gradle file )
maven { url 'http://developer.huawei.com/repo/' }
8) Copy and paste the below plugin in the app build.gradle file dependencies section.
implementation 'com.huawei.hms:ads-lite:13.4.28.305'
9) If the project is using progaurd, copy and paste the below code in the progaurd-rules.pro file.
Code:
-keep class com.huawei.openalliance.ad.** { *; }
-keep class com.huawei.hms.ads.** { *; }
10) The HUAWEI Ads SDK requires the following permissions:
a) android.permission.ACCESS_NETWORK_STATE
b) android.permission.ACCESS_WIFI_STATE
11) Now sync the app.
There are two ways we can use Reward Ad in to our aps.
1. Showing Reward ad after splash screen.
2. Using Reward ad in a game.
Reward Ad after splash screen
In this scenario, we will show reward ad after displaying few seconds of splash screen.
STEPS
1) Create a RewardAd Object and use it call loadAd() method to load an Ad. Place it in onCreate() method.
Code:
private void loadRewardAd() {
if (rewardAd == null) {
rewardAd = new RewardAd(SplashActivity.this, AD_ID);
}
RewardAdLoadListener listener= new RewardAdLoadListener() {
@Override
public void onRewardedLoaded() {
// Rewarded ad loaded successfully...
}
@Override
public void onRewardAdFailedToLoad(int errorCode) {
// Failed to load the rewarded ad...
}
};
rewardAd.loadAd(new AdParam.Builder().build(),listener);
}
2) Call the isLoaded() method to confirm that an ad has finished loading, and call the show() method of the RewardAd object to display the ad.
Code:
private void rewardAdShow() {
if(rewardAd.isLoaded()) {
rewardAd.show(SplashActivity.this, new RewardAdStatusListener() {
@Override
public void onRewardAdClosed() {
super.onRewardAdClosed();
goToMainPage();
}
@Override
public void onRewardAdFailedToShow(int i) {
super.onRewardAdFailedToShow(i);
goToMainPage();
}
@Override
public void onRewardAdOpened() {
super.onRewardAdOpened();
}
@Override
public void onRewarded(Reward reward) {
super.onRewarded(reward);
goToMainPage();
}
});
}
else{
goToMainPage();
}
}
3) A handler to call rewardAdShow() method after few seconds. Place it in the onCreate() method after loadRewardAd() method.
Code:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
rewardAdShow();
}
}, 1000);
4) When testing rewarded ads, use the dedicated test ad slot ID to obtain test ads. This avoids invalid ad clicks during the test. The test ad slot ID is used only for function commissioning. Before releasing your app, apply for a formal ad slot ID and replace the test ad slot ID with the formal one.
THE RESULT
Reward Ad in a Game
In this scenario, we will show Reward Ad in a game and how user will get rewards after watching the ad. In real scenario user gets rewards in terms of extra coins, advance weapon, extra bullets for a weapon, extra life etc.
Here we will showcase how user gets extra life in a game after watching Reward Ad. The name of the game is Luck By Chance.
GAME RULES
· The game will generate a random number between 1 - 1000.
· The player needs to guess that number.
· Suppose the number is 200, the player guess the number as 190. Then the game will let the player know that the number is too low.
· If the player guess the number as 210. Then the game will let the player know that the number is too high.
· The player gets 3 life that means the player has 3 chance to guess the number right.
· If the player exhaust his / her 3 life then the game will give a chance to the player to watch Reward Ad video to get an extra life i.e. 1 life.
· After watching the Reward Ad video player can play one more chance and if the player guess it right then he / she wins the game.
· If the player wins the game, the player gets 5 score. The score gets added by 5 each time the player wins the game.
STEPS
1) Generate Random Number
Code:
public static final int MAX_NUMBER = 1000;
public static final Random RANDOM = new Random();
Code:
private void newGamePlay() {
findTheNumber = RANDOM.nextInt(MAX_NUMBER) + 5;
edtGuessNumber.setText("");
if (!blnScore) {
numScore = 0;
}
txtScore.setText("Score " + numScore);
numberTries = 3;
setLife(numberTries);
}
2) Create a method to play the game. Here we will check whether the guess number is too high or too low and if the user guess it right then we will show a win message to the user.
Code:
private void playTheGame() {
int guessNumber = Integer.parseInt(edtGuessNumber.getText().toString());
if (numberTries <= 0) {
showAdDialog();
} else {
if (guessNumber == findTheNumber) {
txtResult.setText("Congratulations ! You found the number " + findTheNumber);
numScore +=5;
blnScore = true;
newGamePlay();
} else if (guessNumber > findTheNumber) {
numberTries--;
setLife(numberTries);
if(numScore >0) {
numScore -= 1;
}
txtResult.setText(R.string.high);
} else {
numberTries--;
setLife(numberTries);
if(numScore >0) {
numScore -= 1;
}
txtResult.setText(R.string.low);
}
}
}
3) Create a RewardAd Object and use it call loadAd() method to load an Ad. Place it in onCreate() method.
Code:
private void loadRewardAd() {
if (rewardedAd == null) {
rewardedAd = new RewardAd(RewardActivity.this, AD_ID);
}
RewardAdLoadListener rewardAdLoadListener = new RewardAdLoadListener() {
@Override
public void onRewardAdFailedToLoad(int errorCode) {
Toast.makeText(RewardActivity.this,
"onRewardAdFailedToLoad "
+ "errorCode is :"
+ errorCode, Toast.LENGTH_SHORT).show();
}
@Override
public void onRewardedLoaded() {
}
};
rewardedAd.loadAd(new AdParam.Builder().build(), rewardAdLoadListener);
}
4) Call the isLoaded() method to confirm that an ad has finished loading, and call the show() method of the RewardAd object to display the ad. After user watch the entire Reward Ad video, he/she will get extra life i.e. 1.
Code:
private void rewardAdShow() {
if (rewardedAd.isLoaded()) {
rewardedAd.show(RewardActivity.this, new RewardAdStatusListener() {
@Override
public void onRewardAdClosed() {
loadRewardAd();
}
@Override
public void onRewardAdFailedToShow(int errorCode) {
Toast.makeText(RewardActivity.this,
"onRewardAdFailedToShow "
+ "errorCode is :"
+ errorCode,
Toast.LENGTH_SHORT).show();
}
@Override
public void onRewardAdOpened() {
Toast.makeText(RewardActivity.this,
"onRewardAdOpened",
Toast.LENGTH_SHORT).show();
}
@Override
public void onRewarded(Reward reward) {
numberTries ++; // HERE USER WILL GET REWARD AFTER WATCHING REWARD Ad VIDEO ...
setLife(numberTries);
}
});
}
}
5) A dialog to show the user that he/she needs to watch the video to get extra life. Here we will call rewardAdShow() method to show the reward video to the user for extra life if he/she accept to continue the game.
Code:
private void showAdDialog() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("GET EXTRA LIFE");
alertDialogBuilder
.setMessage("Watch video to get extra life")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
rewardAdShow();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
THE CODE
RewardActivity.java
Code:
public class RewardActivity extends AppCompatActivity implements View.OnClickListener {
public static final int MAX_NUMBER = 1000;
public static final Random RANDOM = new Random();
private static final String AD_ID = "testx9dtjwj8hp";
TextView txtHeader, txtScore, txtLife, txtResult;
EditText edtGuessNumber;
Button btnGuess;
boolean blnScore = false;
private int findTheNumber, numberTries, numScore = 1;
private RewardAd rewardedAd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reward);
txtHeader = findViewById(R.id.txtHeader);
txtHeader.setText("LUCK BY CHANCE");
txtLife = findViewById(R.id.txtLife);
txtScore = findViewById(R.id.txtScore);
txtResult = findViewById(R.id.txtStatus);
edtGuessNumber = findViewById(R.id.edtGuessNumber);
btnGuess = findViewById(R.id.btnGuess);
btnGuess.setOnClickListener(this);
newGamePlay();
loadRewardAd();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnGuess:
playTheGame();
break;
}
}
@SuppressLint("SetTextI18n")
private void playTheGame() {
int guessNumber = Integer.parseInt(edtGuessNumber.getText().toString());
if (numberTries <= 0) {
showAdDialog();
} else {
if (guessNumber == findTheNumber) {
txtResult.setText("Congratulations ! You found the number " + findTheNumber);
numScore +=5;
blnScore = true;
newGamePlay();
} else if (guessNumber > findTheNumber) {
numberTries--;
setLife(numberTries);
if(numScore >0) {
numScore -= 1;
}
txtResult.setText(R.string.high);
} else {
numberTries--;
setLife(numberTries);
if(numScore >0) {
numScore -= 1;
}
txtResult.setText(R.string.low);
}
}
}
private void showAdDialog() {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle("GET EXTRA LIFE");
alertDialogBuilder
.setMessage("Watch video to get extra life")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
rewardAdShow();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
@SuppressLint("SetTextI18n")
private void newGamePlay() {
findTheNumber = RANDOM.nextInt(MAX_NUMBER) + 5;
edtGuessNumber.setText("");
if (!blnScore) {
numScore = 0;
}
txtScore.setText("Score " + numScore);
numberTries = 3;
setLife(numberTries);
}
private void loadRewardAd() {
if (rewardedAd == null) {
rewardedAd = new RewardAd(RewardActivity.this, AD_ID);
}
RewardAdLoadListener rewardAdLoadListener = new RewardAdLoadListener() {
@Override
public void onRewardAdFailedToLoad(int errorCode) {
Toast.makeText(RewardActivity.this,
"onRewardAdFailedToLoad "
+ "errorCode is :"
+ errorCode, Toast.LENGTH_SHORT).show();
}
@Override
public void onRewardedLoaded() {
}
};
rewardedAd.loadAd(new AdParam.Builder().build(), rewardAdLoadListener);
}
private void rewardAdShow() {
if (rewardedAd.isLoaded()) {
rewardedAd.show(RewardActivity.this, new RewardAdStatusListener() {
@Override
public void onRewardAdClosed() {
loadRewardAd();
}
@Override
public void onRewardAdFailedToShow(int errorCode) {
Toast.makeText(RewardActivity.this,
"onRewardAdFailedToShow "
+ "errorCode is :"
+ errorCode,
Toast.LENGTH_SHORT).show();
}
@Override
public void onRewardAdOpened() {
Toast.makeText(RewardActivity.this,
"onRewardAdOpened",
Toast.LENGTH_SHORT).show();
}
@Override
public void onRewarded(Reward reward) {
numberTries ++;
setLife(numberTries);
}
});
}
}
private void setLife(int life) {
txtLife.setText("Life " + life);
}
}
activity_reward.xml
Code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".RewardActivity">
<include
android:id="@+id/include"
layout="@layout/layout_bar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/edtGuessNumber"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginStart="32dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="32dp"
android:background="@drawable/edittext_style"
android:ems="10"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:inputType="number|none"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="@+id/txtLife"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginEnd="24dp"
android:textColor="#0B400F"
android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@+id/textView3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/include"
app:layout_constraintVertical_bias="0.00999999" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="200dp"
android:text="Guess The Number ?"
android:textColor="#3040E4"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/include"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="@+id/btnGuess"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginStart="32dp"
android:layout_marginTop="70dp"
android:layout_marginEnd="32dp"
android:background="#F57F17"
android:text="@string/play"
android:textColor="#FFFFFF"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edtGuessNumber"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="@+id/txtStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:textColor="#1B5E20"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/edtGuessNumber"
app:layout_constraintVertical_bias="0.0" />
<TextView
android:id="@+id/txtScore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="32dp"
android:text="Score 0"
android:textColor="#B71C1C"
android:textSize="24sp"
app:layout_constraintBottom_toTopOf="@+id/textView3"
app:layout_constraintEnd_toStartOf="@+id/txtLife"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/include"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
THE RESULT

About the reward ad in the game.. is there a way to skip the ad but still end up getting the reward?

thanks for sharing very easy to implement

Related

Huawei Share Kit Facilitates to Acquire Skill in Enforcement - Part 2

More articles like this, you can visit HUAWEI Developer Forum and Medium.
​https://forums.developer.huawei.com/forumPortal/en/home
In this article, We will implement the Huawei Share Kit SDK and complete our demo application.
In the previous article, we have learned about Share Kit introduction and created project. So let’s start our implementation.
I will represent the functionality of Share Kit in a simple way with a working application and give a demo.
Before start developing the application we must have the following requirement.
Hardware Requirements
1. A computer (desktop or laptop) that runs Windows 7 or Windows 10
2. A Huawei phone (with the USB cable), which is used for debugging
3. A third-party Android device, which is used for debugging
Software Requirements
1. JDK 1.8 or later
2. Android API (level 26 or higher)
3. EMUI 10.0 or later
Let’s start the development:
{
"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"
}
1. Add Share Kit SDK in project:
2. We need to add the code repository to the project root directory gradle.
Code:
maven {
url 'http://developer.huawei.com/repo/'
}
3. We need to add the following dependencies in our app gradle.
Code:
dependencies {
implementation files('libs/sharekit-1.0.1.300.aar')
implementation 'com.android.support:support-annotations:28.0.0'
implementation 'com.android.support:localbroadcastmanager:28.0.0'
implementation 'com.android.support:support-compat:28.0.0'
implementation 'com.google.guava:guava:24.1-android'
}
Note: You need to raise a ticket to get Share Kit SDK “sharekit-1.0.300.aar” file
Click on the below link and raise your ticket.
https://developer.huawei.com/consumer/en/support/feedback/#/
4. I have created following package and resource file:
5. I have mentioned all activities in manifest file:
Code:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hms.myshare">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".SplashScreen"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SearchingActivity"
android:configChanges="orientation|keyboardHidden|screenSize"/>
<activity
android:name=".ReceiveActivity"
android:configChanges="orientation|keyboardHidden|screenSize"/>
</application>
</manifest>
Let’s create an awesome User Interface:
1. I have created a wave ripple effect which will help to find the device from a UI perspective.
I have created a SearchingView.java class:
Code:
public class SearchingView extends RelativeLayout {
private static final int DEFAULT_RIPPLE_COUNT=6;
private static final int DEFAULT_DURATION_TIME=3000;
private static final float DEFAULT_SCALE=6.0f;
private static final int DEFAULT_FILL_TYPE=0;
private int rippleColor;
private float rippleStrokeWidth;
private float rippleRadius;
private int rippleDurationTime;
private int rippleAmount;
private int rippleDelay;
private float rippleScale;
private int rippleType;
private Paint paint;
private boolean animationRunning=false;
private AnimatorSet animatorSet;
private ArrayList<Animator> animatorList;
private LayoutParams rippleParams;
private ArrayList<RippleView> rippleViewList=new ArrayList<RippleView>();
public SearchingView(Context context) {
super(context);
}
public SearchingView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public SearchingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(final Context context, final AttributeSet attrs) {
if (isInEditMode())
return;
if (null == attrs) {
throw new IllegalArgumentException("Attributes should be provided to this view,");
}
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RippleBackground);
rippleColor=typedArray.getColor(R.styleable.RippleBackground_rb_color, getResources().getColor(R.color.rippelColor));
rippleStrokeWidth=typedArray.getDimension(R.styleable.RippleBackground_rb_strokeWidth, getResources().getDimension(R.dimen.rippleStrokeWidth));
rippleRadius=typedArray.getDimension(R.styleable.RippleBackground_rb_radius,getResources().getDimension(R.dimen.rippleRadius));
rippleDurationTime=typedArray.getInt(R.styleable.RippleBackground_rb_duration,DEFAULT_DURATION_TIME);
rippleAmount=typedArray.getInt(R.styleable.RippleBackground_rb_rippleAmount,DEFAULT_RIPPLE_COUNT);
rippleScale=typedArray.getFloat(R.styleable.RippleBackground_rb_scale,DEFAULT_SCALE);
rippleType=typedArray.getInt(R.styleable.RippleBackground_rb_type,DEFAULT_FILL_TYPE);
typedArray.recycle();
rippleDelay=rippleDurationTime/rippleAmount;
paint = new Paint();
paint.setAntiAlias(true);
if(rippleType==DEFAULT_FILL_TYPE){
rippleStrokeWidth=0;
paint.setStyle(Paint.Style.FILL);
}else
paint.setStyle(Paint.Style.STROKE);
paint.setColor(rippleColor);
rippleParams=new LayoutParams((int)(2*(rippleRadius+rippleStrokeWidth)),(int)(2*(rippleRadius+rippleStrokeWidth)));
rippleParams.addRule(CENTER_IN_PARENT, TRUE);
animatorSet = new AnimatorSet();
animatorSet.setInterpolator(new AccelerateDecelerateInterpolator());
animatorList=new ArrayList<Animator>();
for(int i=0;i<rippleAmount;i++){
RippleView rippleView=new RippleView(getContext());
addView(rippleView,rippleParams);
rippleViewList.add(rippleView);
final ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(rippleView, "ScaleX", 1.0f, rippleScale);
scaleXAnimator.setRepeatCount(ObjectAnimator.INFINITE);
scaleXAnimator.setRepeatMode(ObjectAnimator.RESTART);
scaleXAnimator.setStartDelay(i * rippleDelay);
scaleXAnimator.setDuration(rippleDurationTime);
animatorList.add(scaleXAnimator);
final ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(rippleView, "ScaleY", 1.0f, rippleScale);
scaleYAnimator.setRepeatCount(ObjectAnimator.INFINITE);
scaleYAnimator.setRepeatMode(ObjectAnimator.RESTART);
scaleYAnimator.setStartDelay(i * rippleDelay);
scaleYAnimator.setDuration(rippleDurationTime);
animatorList.add(scaleYAnimator);
final ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(rippleView, "Alpha", 1.0f, 0f);
alphaAnimator.setRepeatCount(ObjectAnimator.INFINITE);
alphaAnimator.setRepeatMode(ObjectAnimator.RESTART);
alphaAnimator.setStartDelay(i * rippleDelay);
alphaAnimator.setDuration(rippleDurationTime);
animatorList.add(alphaAnimator);
}
animatorSet.playTogether(animatorList);
}
private class RippleView extends View {
public RippleView(Context context) {
super(context);
this.setVisibility(View.INVISIBLE);
}
@Override
protected void onDraw(Canvas canvas) {
int radius=(Math.min(getWidth(),getHeight()))/2;
canvas.drawCircle(radius,radius,radius-rippleStrokeWidth,paint);
}
}
public void startRippleAnimation(){
if(!isRippleAnimationRunning()){
for(RippleView rippleView:rippleViewList){
rippleView.setVisibility(VISIBLE);
}
animatorSet.start();
animationRunning=true;
}
}
public void stopRippleAnimation(){
if(isRippleAnimationRunning()){
animatorSet.end();
animationRunning=false;
}
}
public boolean isRippleAnimationRunning(){
return animationRunning;
}
Let’s see the implementation of this custom view inside xml layout:
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:background="@drawable/background"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center">
<com.hms.myshare.view.SearchingView
android:id="@+id/searching"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:rb_color="@android:color/white"
app:rb_duration="3000"
app:rb_radius="40dp"
app:rb_rippleAmount="6"
app:rb_scale="5">
<ImageView
android:id="@+id/img_logo"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:src="@drawable/log" />
</com.hms.myshare.view.SearchingView>
</RelativeLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:textColor="@android:color/white"
android:textSize="28sp"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Huawei Share Kit"
android:id="@+id/appCompatTextView2" />
</LinearLayout>
Let’ see the output of this view:
Let’s implement Search device and Send Data:
· We have implemented this functionality inside SearchingActivity class.
We need to perform the following operation in order to implement sending data to found device.
1. We need to instantiate SDK manager class i.e. ShareKitManager with current context of Activity inside the oncreate method.
Code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.searching_activity);
shareKitManager = new ShareKitManager(this);
2. Add callback IShareKitInitCallback to initialize the ShareKitManager class.
Code:
IShareKitInitCallback initCallback = isSuccess -> {
Log.i(TAG, "share kit init result:" + isSuccess);
if (isSuccess) {
binding.txtError.setText(getString(R.string.sharekit_init_finish));
} else {
binding.txtError.setText(getString(R.string.sharekit_init_failed));
}
};
shareKitManager.init(initCallback);
3. Register the ShareKitManager with IWidgetCallback:
Code:
private IWidgetCallback callback = new IWidgetCallback.Stub() {
@Override
public synchronized void onDeviceFound(NearByDeviceEx nearByDeviceEx) {
String deviceId = nearByDeviceEx.getCommonDeviceId();
if (deviceId == null) {
Log.e(TAG, "onDeviceFound: deviceId is null");
return;
}
Log.i(TAG, "onDeviceFound: " + deviceId + ", btName: " + nearByDeviceEx.getBtName());
synchronized (lock) {
deviceMap.put(deviceId, nearByDeviceEx);
foundTimeMap.put(deviceId, format.format(new Date()));
updateDeviceList();
}
}
@Override
public void onDeviceDisappeared(NearByDeviceEx nearByDeviceEx) {
String deviceId = nearByDeviceEx.getCommonDeviceId();
if (deviceId == null) {
Log.e(TAG, "onDeviceDisappeared: deviceId is null");
return;
}
Log.i(TAG, "onDeviceDisappeared: " + deviceId + ", btName: " + nearByDeviceEx.getBtName());
synchronized (lock) {
deviceMap.remove(deviceId);
foundTimeMap.remove(deviceId);
updateDeviceList();
}
}
@Override
public void onTransStateChange(NearByDeviceEx nearByDeviceEx, int state, int stateValue) {
Log.i(TAG, "trans state:" + state + " value:" + stateValue);
String stateDesc = "";
switch (state) {
case STATE_PROGRESS:
stateDesc = getString(R.string.sharekit_send_progress, stateValue);
break;
case STATE_SUCCESS:
stateDesc = getString(R.string.sharekit_send_finish);
break;
case STATE_STATUS:
stateDesc = getString(R.string.sharekit_state_chg, translateStateValue(stateValue));
break;
case STATE_ERROR:
stateDesc = getString(R.string.sharekit_send_error, translateErrorValue(stateValue));
showError(getString(R.string.sharekit_send_error, translateErrorValue(stateValue)));
break;
default:
break;
}
// showToast(stateDesc);
}
@Override
public void onEnableStatusChanged() {
int status = shareKitManager.getShareStatus();
Log.i(TAG, "sharekit ability current status:" + status);
}
};
We need to pass this callback to Register api.
Code:
shareKitManager.registerCallback(callback);
4. Start searching device using Discorvey api.
Code:
shareKitManager.startDiscovery();
5. If you found the device successfully we need to call the ShareBean api for send the data.
Code:
private void doSendText() {
String text = binding.sharetext.getText().toString();
ShareBean shareBean = new ShareBean(text);
doSend(destDevice, shareBean);
}
Followed by doSend() method:
Code:
private void doSend(String deviceName, ShareBean shareBean) {
List<NearByDeviceEx> processingDevices = shareKitManager.getDeviceList();
for (NearByDeviceEx device : processingDevices) {
if (deviceName.equals(device.getBtName())) {
return;
}
}
synchronized (lock) {
for (NearByDeviceEx device : deviceMap.values()) {
if (deviceName.equals(device.getBtName())) {
shareKitManager.doSend(device, shareBean);
}
}
}
}
Let’s implement Receive data functionality:
· We have implemented this functionality inside ReceivingActivity.
· We need to enable wifi in Huawei device which receive the socket connection request from sender device.
· So we need to initialize the ShareKitManager inside this activity oncreate method.
Code:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.receiver_activity);
binding.searching.startRippleAnimation();
shareKitManager = new ShareKitManager(this);
IShareKitInitCallback initCallback = isSuccess -> {
Log.i(TAG, "share kit init result:" + isSuccess);
};
shareKitManager.init(initCallback);
shareKitManager.enable();
}
Android device (Sender):
Huawei device (Receiver):
If you have any doubts or queries. Please leave your valuable comment or post your doubts in HUAWEI Developer Forum.

AD kit collections: Huawei vs AdMob

More information like this, you can visit HUAWEI Developer Forum​
What is Ad Kit
Ad kit service makes it 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 article we will integrate banner ad and reward video ad provided by Google Admob and Huawei Ad kit in single application.
Banner Ad
{
"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"
}
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.
Reward Ad
Ads which reward users for watching short videos, interacting with ads and surveys that are playable. Perfect for free-to-play players to monetize.
Usecase
1. We will develop small application “Wheel of fortune”. User can spin wheel to earn coins.
2. We will show banner ad at the bottom of app
3. User will spin the wheel of fortune, if coins earned are 6 or less ,he can earn additional coin by watching reward ads.
4. If device supports HMS, we will show Huawei ads.
5. If device supports GMS, we will show Google AdMob ads.
Initial Setup
Huawei Ad kit
1) Create a project in android studio
2) Get the SHA Key. For getting the SHA key we can refer to this article.
3) Create an app in the Huawei app gallery connect.
4) Provide the SHA Key in App Information Section.
5) Provide storage location.
6) After completing all the above points we need to download the agconnect-services.json from App Information Section. Copy and paste the Json file in the app folder of the android project.
7) Enter the below maven url inside the repositories of buildscript and allprojects ( project build.gradle file )
Code:
maven { url 'http://developer.huawei.com/repo/' }
8) 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'
9) Provide following permissions in manifest.
Code:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Google Admob
1. Create a Google AdMob account and register an app.
2. Open app-level gradle file, and add following dependencies.
Code:
dependencies {
implementation 'com.google.android.gms:play-services-ads:19.2.0'
}
3. Create APP ID in admob dashboard. Refer this to create APP ID.
4. Add APP ID in Android manifest.
Code:
<manifest>
<application>
<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
</application>
</manifest>
Development for Huawei device supporting HMS
Integrating Huawei Banner AD
1. Add bannerview in activity_main.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.
2. 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");
}
};
Integrating Huawei Reward Video AD
1. To show Huawei reward Ads
Code:
if (Utility.isHuaweiMobileServicesAvailable(MainActivity.this) && Utility.isDeviceHuaweiManufacturer()) {
showHuaweiRewardAds();
}
Code:
private void showHuaweiRewardAds() {
// Test ad slot ID
final String AD_ID = "testx9dtjwj8hp";
final RewardAd rewardAd;
rewardAd = new RewardAd(this, AD_ID);
RewardAdLoadListener listener= new RewardAdLoadListener() {
@Override
public void onRewardedLoaded() {
// Rewarded ad loaded successfully.
if (rewardAd.isLoaded()) {
rewardAd.show(MainActivity.this, new RewardAdStatusListener() {
@Override
public void onRewardAdOpened() {
// Rewarded ad opened.
Log.d(TAG , "rewardAd loaded");
}
@Override
public void onRewardAdFailedToShow(int errorCode) {
// Failed to display the rewarded ad.
Log.d(TAG , "rewardAd failed error : " + errorCode);
}
@Override
public void onRewardAdClosed() {
// Rewarded ad closed.
}
@Override
public void onRewarded(Reward reward){
showRewardAdAlertDialog( "You have been rewarded " +
String.valueOf(reward.getAmount()) +" "+ reward.getName() + " for watching Ad");
}
});
}
}
@Override
public void onRewardAdFailedToLoad(int errorCode) {
// Failed to load the rewarded ad.
}
};
rewardAd.loadAd(new AdParam.Builder().build(), listener);
}
2. The reward object is passed in the onRewarded method. Call the reward.getAmount() method to obtain the reward amount and the reward.getName() method to obtain the name of the reward.
Code:
public void onRewarded(Reward reward){
// Reward earned by the user.
// TODO: Reward the user.
// Toast.makeText(MainActivity.this , reward.getName() +", "+ reward.getAmount() , Toast.LENGTH_LONG).show();
showRewardAdAlertDialog( "You have been rewarded " +
String.valueOf(reward.getAmount()) +" "+ reward.getName() + " for watching Ad");
}
Development for Non Huawei device supporting GMS
Integrating AdMob Banner AD
Before loading ads, we have to initialize the Mobile Ads SDK by calling MobileAds.initialize() which initializes the SDK and calls back a completion listener once initialization is complete (or after a 30-second timeout). This needs to be done only once, ideally at app launch.
Code:
MobileAds.initialize(this, new OnInitializationCompleteListener() {
@Override
public void onInitializationComplete(InitializationStatus initializationStatus) {
}
});
2. Add the banner AdView in activity_main.xml
Code:
<com.google.android.gms.ads.AdView
xmlns:ads="http://schemas.android.com/apk/res-auto"
android:id="@+id/google_banner_adView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:visibility="gone"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
ads:adSize="BANNER"
ads:adUnitId="ca-app-pub-3940256099942544/6300978111">
</com.google.android.gms.ads.AdView>
Note: Here we are using test adUnitId. When building and testing your apps, make sure you use test ads rather than live, production ads
3. To load the banner Ad view
Code:
if(Utility.isGooglePlayServicesAvailable(this)) {
mGoogleAdView = findViewById(R.id.google_banner_adView);
mGoogleAdView.setVisibility(View.VISIBLE);
AdRequest adRequest = new AdRequest.Builder().build();
mGoogleAdView.loadAd(adRequest);
mGoogleAdView.setAdListener(new com.google.android.gms.ads.AdListener()
{
@Override
public void onAdLoaded() {
// Code to be executed when an ad finishes loading.
Log.d(TAG, "onAdLoaded");
}
@Override
public void onAdFailedToLoad(int errorCode) {
// Code to be executed when an ad request fails.
Log.d(TAG, "onAdFailedToLoad " + errorCode);
}
@Override
public void onAdOpened() {
// Code to be executed when an ad opens an overlay that
// covers the screen.
}
@Override
public void onAdClicked() {
// Code to be executed when the user clicks on an ad.
}
@Override
public void onAdLeftApplication() {
// Code to be executed when the user has left the app.
}
@Override
public void onAdClosed() {
// Code to be executed when the user is about to return
// to the app after tapping on an ad.
}
}
);
}
Integrating AdMob Reward Video AD
1. To show Admob Reward Video ad.
Code:
if (Utility.isGooglePlayServicesAvailable(MainActivity.this)) {
showGoogleRewardAds();
}
Code:
private void showGoogleRewardAds() {
RewardedVideoAd mRewardedVideoAd;
MobileAds.initialize(this, "ca-app-pub-3940256099942544~3347511713");
// Use an activity context to get the rewarded video instance.
mRewardedVideoAd = MobileAds.getRewardedVideoAdInstance(this);
mRewardedVideoAd.setRewardedVideoAdListener(new RewardedVideoAdListener() {
@Override
public void onRewardedVideoAdLoaded() {
if (mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.show();
}
}
@Override
public void onRewardedVideoAdOpened() {
}
@Override
public void onRewardedVideoStarted() {
}
@Override
public void onRewardedVideoAdClosed() {
}
@Override
public void onRewarded(RewardItem rewardItem) {
showRewardAdAlertDialog("You have been rewarded " + rewardItem.getAmount() + " "+ rewardItem.getType() + " for watching ad");
}
@Override
public void onRewardedVideoAdLeftApplication() {
}
@Override
public void onRewardedVideoAdFailedToLoad(int i) {
}
@Override
public void onRewardedVideoCompleted() {
}
});
mRewardedVideoAd.loadAd("ca-app-pub-3940256099942544/5224354917",
new AdRequest.Builder().build());
}
"ca-app-pub-3940256099942544/5224354917" is test Ad id for Admob reward AD.
To check if device has HMS or GMS installed
Code:
public class Utility {
public static boolean isGooglePlayServicesAvailable(Activity activity) {
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
int status = googleApiAvailability.isGooglePlayServicesAvailable(activity);
if(status != ConnectionResult.SUCCESS) {
if(googleApiAvailability.isUserResolvableError(status)) {
googleApiAvailability.getErrorDialog(activity, status, 2404).show();
}
return false;
}
return true;
}
public static boolean isHuaweiMobileServicesAvailable(Context context) {
if (HuaweiApiAvailability.getInstance().isHuaweiMobileServicesAvailable(context) == ConnectionResult.SUCCESS){
return true;
}
return false;
}
public static boolean isDeviceHuaweiManufacturer () {
String manufacturer = Build.MANUFACTURER;
Log.d("Device : " , manufacturer);
if (manufacturer.toLowerCase().contains("huawei")) {
return true;
}
return false;
}
}
Links:
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/publisher-service-introduction-0000001050064960-V5
https://developers.google.com/admob/android/quick-start

HMS Game Service - How to create a Sign In / Get User Info [Java]

More information like this, you can visit HUAWEI Developer Forum​
Introduction
In this article I would like to address the Game Service topic by doing a practical example in which we will implement the kit. The goal is to achieve a simple application where our user has the possibility to log in with his Huawei ID and obtain information regarding his player on Game Service. In the Huawei repositories we can find projects with all the implementation but in my opinion it is better to create a new project where we have the opportunity to do our own development.
Steps:
1. Create an App in AGC
2. Add the necessary libraries and repositories
3. Permissions in our Application
4. Building the user interface
5. Create the Signing class
6. Write the code in our MainActity
7. Test the App
Create an App in AGC
If you already have experience implementing HMS you will have noticed that the creation of an App in the AGC console is regularly required. If you are in this case, I recommend that you skip this step and go to step 3.
In this link you can find a detailed guide on how to create an App in AGC, generate your finger print and download the json services.
https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#0
In case you do not have Android Studio Configured on your device, I also share a guide with the requirements.
https://developer.huawei.com/consumer/en/codelab/HMSAccounts-Kotlin/index.html#1
Once your App is created in AGC, it is important that you activate the Game Service, Account Kit and In App purchases services in case you require it. We can go to the Apis Management tab
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
What have we accomplished so far?
We have an App in AGC connected to our project and with activated services.
Add the necessary libraries and repositories
Once our project is created in Android Studio it will be necessary to add the following lines of code
Let's add the following lines to the project gradle
Code:
buildscript {
repositories {
google()
jcenter()
//Esta linea
maven { url 'http://developer.huawei.com/repo/' }
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.0"
//Tambien esta esta linea
classpath 'com.huawei.agconnect:agcp:1.3.1.300'
}
}
allprojects {
repositories {
google()
jcenter()
//Repositorio de Maven
maven {url 'http://developer.huawei.com/repo/'}
}
}
Now let's add the necessary dependencies in the app gradle.
Code:
implementation'com.huawei.agconnect:agconnect-core:1.3.1.300' //HMSCore
implementation 'com.huawei.hms:hwid:4.0.4.300' //Huawei Id
implementation 'com.huawei.hms:game:4.0.3.301' //Game Service
implementation 'com.huawei.hms:base:4.0.4.301'
implementation 'com.squareup.picasso:picasso:2.71828'
Do not forget to add the plugin.
Code:
apply plugin:'com.huawei.agconnect'
Permissions in our Application
Now let's add the permissions of our Application because we want to use the Game Service services. So in the Android Manifest File, let's add the necessary permissions.
Code:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Building the user interface
The time has come to build the user interface, what we will do is use the powerful tool that Android Studio from Constraint offers us, basically what we are looking for is to achieve something like this. Where we will place the elements that we want to show when obtaining the data of our user. Of course you can create the interface that you like the most, but if you want to use this simple distribution of elements this is the code
Code:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="68dp"
android:text="Welcome"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/avatarImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="36dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="28dp"
android:text="Player Id"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/idtv" />
<TextView
android:id="@+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginEnd="51dp"
android:text="Player Level"
app:layout_constraintEnd_toStartOf="@+id/leveltv"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="@+id/textView9"
app:layout_constraintTop_toBottomOf="@+id/textView9" />
<TextView
android:id="@+id/idtv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginTop="24dp"
android:text="TextView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.082"
app:layout_constraintStart_toEndOf="@+id/textView9"
app:layout_constraintTop_toBottomOf="@+id/avatarImg" />
<TextView
android:id="@+id/leveltv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="TextView"
app:layout_constraintStart_toStartOf="@+id/idtv"
app:layout_constraintTop_toBottomOf="@+id/idtv" />
<Button
android:id="@+id/loginButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:text="Login"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_editor_absoluteX="0dp" />
<Button
android:id="@+id/btnInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="88dp"
android:text="PlayerInfo"
app:layout_constraintBottom_toTopOf="@+id/loginButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.475"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView10"
app:layout_constraintVertical_bias="0.178" />
</androidx.constraintlayout.widget.ConstraintLayout>
Create the SignInCenter class
In this class we will make the instance of the class and we will be able to manage the Huawei of Authentication
Code:
public class SignInCenter {
private static SignInCenter INS = new SignInCenter();
private static AuthHuaweiId currentAuthHuaweiId;
public static SignInCenter get() {
return INS;
}
public void updateAuthHuaweiId(AuthHuaweiId AuthHuaweiId) {
currentAuthHuaweiId = AuthHuaweiId;
}
public AuthHuaweiId getAuthHuaweiId() {
return currentAuthHuaweiId;
}
}
Write the code in our MainActity
Let's work on our Main Activity is the time to get our hands dirty, I will put the source code and within the add comments to each method this for reading is easier
Code:
/**
*Variable Declarations
* Buttons, TextViews
* AuthHuaweiId to store retrived elements
* ImageView to show avatar
* Handler to use a service
*/
private Button loginButton;
private Button infoButton;
private TextView welcomeTv,idtv,leveltv;
private AuthHuaweiId mAuthid;
private final static int SIGN_IN_INTENT = 3000;
private String playerId;
private String sessionId = null;
private ImageView avatar;
private Handler handler;
private final static int HEARTBEAT_TIME = 15 * 60 * 1000;
private static final String TAG = "TAG1";
private boolean hasInit = false;
//---------------------------------------------------------------------------------------------
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Call UI elements we can use Butterknife or if you are using Kotlin use the extensions to get rid of this part
loginButton = findViewById(R.id.loginButton);
loginButton.setOnClickListener(this);
welcomeTv = findViewById(R.id.textView);
avatar = findViewById(R.id.avatarImg);
infoButton = findViewById(R.id.btnInfo);
infoButton.setOnClickListener(this);
idtv = findViewById(R.id.idtv);
leveltv = findViewById(R.id.leveltv);
}
//---------------------------------------------------------------------------------------------
/*
* Overide onclick method and by using elements id call the proper methods, dont forget to
* implement View.Onclick Listener Interface
*/
//---------------------------------------------------------------------------------------------
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.loginButton:
signIn();
break;
case R.id.btnInfo:
init();
getCurrentPlayer();
break;
}
}
//---------------------------------------------------------------------------------------------
/*
* This is the method where we will initialize the service by passing the Authentification ID
* if the user has logged in correctly
*/
//---------------------------------------------------------------------------------------------
public void init() {
JosAppsClient appsClient = JosApps.getJosAppsClient(this,mAuthid);
appsClient.init();
Log.d(TAG,"init success");
hasInit = true;
}
//---------------------------------------------------------------------------------------------
/*
*Get the current player by using the ID there are many ways to achive this but for this example
* we will keep it simple
**/
//---------------------------------------------------------------------------------------------
private void getCurrentPlayer() {
PlayersClientImpl client = (PlayersClientImpl) Games.getPlayersClient(this,mAuthid);
//Create a Task to get the Player
Task<Player> task = client.getCurrentPlayer();
task.addOnSuccessListener(new OnSuccessListener<Player>() {
@Override
public void onSuccess(Player player) {
String result = "display:" + player.getDisplayName() + "\n" + "playerId:" + player.getPlayerId() + "\n"
+ "playerLevel:" + player.getLevel() + "\n" + "timestamp:" + player.getSignTs() + "\n"
+ "playerSign:" + player.getPlayerSign();
Log.d("TAG1",result);
idtv.setText(player.getPlayerId());
leveltv.setText(player.getLevel() + "");
playerId = player.getPlayerId();
gameBegin();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//gamePlayExtra();
}
};
new Timer().schedule(new TimerTask() {
@Override
public void run() {
Message message = new Message();
handler.sendMessage(message);
}
}, HEARTBEAT_TIME, HEARTBEAT_TIME);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
Log.d("TAG1",result);
}
}
});
}
//---------------------------------------------------------------------------------------------
/*
*On this method the Game will begin with the obtained ID
*/
//---------------------------------------------------------------------------------------------
public void gameBegin() {
if (TextUtils.isEmpty(playerId)) {
Log.d("TAG1","GetCurrentPlayer first.");
return;
}
String uid = UUID.randomUUID().toString();
PlayersClient client = Games.getPlayersClient(this,mAuthid);
Task<String> task = client.submitPlayerEvent(playerId, uid, "GAMEBEGIN");
task.addOnSuccessListener(new OnSuccessListener<String>() {
@Override
public void onSuccess(String jsonRequest) {
if (jsonRequest == null) {
Log.d("TAG1","jsonRequest is null");
return;
}
try {
JSONObject data = new JSONObject(jsonRequest);
sessionId = data.getString("transactionId");
} catch (JSONException e) {
Log.d("TAG1","parse jsonArray meet json exception");
return;
}
Log.d("TAG1","submitPlayerEvent traceId: " + jsonRequest);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
String result = "rtnCode:" + ((ApiException) e).getStatusCode();
Log.d("TAG1",result);
}
}
});
}
//---------------------------------------------------------------------------------------------
/*
* This is the method to sign in i have commented most of the lines to understa what we have been doing
*/
//---------------------------------------------------------------------------------------------
private void signIn() {
//Create a task with the Type of AuthHuaweiId
Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.getService(this, getHuaweiIdParams()).silentSignIn();
//Add the proper Listener so we can track the response of the Task
authHuaweiIdTask.addOnSuccessListener(new OnSuccessListener<AuthHuaweiId>() {
//Must overide the Osuccess Method which will return an AuthHuaweiId Object
@Override
public void onSuccess(AuthHuaweiId authHuaweiId) {
//Logs to track the information
Log.d("TAG1","signIn success");
Log.d("TAG1","Id" + authHuaweiId.getDisplayName());
Log.d("TAG1", "Picture" + authHuaweiId.getAvatarUriString());
//Handle the user interface
welcomeTv.setVisibility(View.VISIBLE);
welcomeTv.setText("Welcome back " + authHuaweiId.getDisplayName());
Picasso.get().load(authHuaweiId.getAvatarUriString()).into(avatar);
loginButton.setVisibility(View.INVISIBLE);
Log.d("TAG1","AT:" + authHuaweiId.getAccessToken());
mAuthid = authHuaweiId;
//Sign in Center update
SignInCenter.get().updateAuthHuaweiId(authHuaweiId);
infoButton.setVisibility(View.VISIBLE);
}
}).addOnFailureListener(new OnFailureListener() {
//Something went wrong, use this method to inform your users
@Override
public void onFailure(Exception e) {
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
Log.d("TAG1","signIn failed:" + apiException.getStatusCode());
Log.d("TAG1","start getSignInIntent");
signInNewWay();
}
}
});
}
//---------------------------------------------------------------------------------------------
private void signInNewWay() {
Intent intent = HuaweiIdAuthManager.getService(MainActivity.this, getHuaweiIdParams()).getSignInIntent();
startActivityForResult(intent, SIGN_IN_INTENT);
}
//---------------------------------------------------------------------------------------------
/*
*Create the HuaweiIdParams so we can send it to the service
*/
//---------------------------------------------------------------------------------------------
public HuaweiIdAuthParams getHuaweiIdParams() {
return new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM_GAME).createParams();
}
//---------------------------------------------------------------------------------------------
/*
*Dont Forget to overide onActivity Result otherwise we wont have any functionality working
* */
//---------------------------------------------------------------------------------------------
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (SIGN_IN_INTENT == requestCode) {
handleSignInResult(data);
} else {
Log.d("TAG1","unknown requestCode in onActivityResult");
}
}
//---------------------------------------------------------------------------------------------
/*
*Handle the result of signin we can take some desicion here
* */
//---------------------------------------------------------------------------------------------
private void handleSignInResult(Intent data) {
if (null == data) {
Log.d("TAG1","signIn inetnt is null");
return;
}
// HuaweiIdSignIn.getSignedInAccountFromIntent(data);
String jsonSignInResult = data.getStringExtra("HUAWEIID_SIGNIN_RESULT");
if (TextUtils.isEmpty(jsonSignInResult)) {
Log.d("TAG1","SignIn result is empty");
return;
}
try {
HuaweiIdAuthResult signInResult = new HuaweiIdAuthResult().fromJson(jsonSignInResult);
if (0 == signInResult.getStatus().getStatusCode()) {
Log.d("TAG1","Sign in success.");
Log.d("TAG1","Sign in result: " + signInResult.toJson());
SignInCenter.get().updateAuthHuaweiId(signInResult.getHuaweiId());
// getCurrentPlayer();
} else {
Log.d("TAG1","Sign in failed: " + signInResult.getStatus().getStatusCode());
}
} catch (JSONException var7) {
Log.d("TAG1","Failed to convert json from signInResult.");
}
}
Conclusion
Well! Well we have achieved it we have a small implementation of a simple Game Service but that we could add to our video games. Game Service has many very useful methods, check the documentation if you would like to go deeper into this topic.
https://developer.huawei.com/consumer/en/hms/huawei-game

Expert: Xamarin Android Online Book Store App Using In-App Purchase and Login with Huawei Id

Overview
In this article, I will create a demo app that highlights an online book store with In-App Purchases. User can easily buy book and make a payment online. I have integrated HMS Account and IAP Kit which is based on Cross-platform Technology Xamarin.
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.
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.
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 and Add SHA-256 key.
3. Navigate to General Information > Data Storage location.
4. Navigate to Manage APIs > enable APIs to require by an application.
5. Navigate to In-App Purchases and Copy Public Key.
6. Navigate to My apps > Operate, and then enter details in Add Product.
7. Click View and Edit in the above screenshot, enter Product price details, and then click Save.
8. Click Activate for product activation.
Xamarin Account Kit Setup Process
1. Download Xamarin Plugin all the aar and zip files from below URL:
https://developer.huawei.com/consum...y-V1/xamarin-sdk-download-0000001050768441-V1
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:
https://developer.huawei.com/consum...y-V1/xamarin-sdk-download-0000001051011015-V1
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.
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.
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 BookStore
{
[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);
CheckIfIAPAvailable();
// 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);
};
/*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();
}
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();
}
}
}
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();
Intent intent = new Intent(context, typeof(BookStoreActivity));
context.StartActivity(intent);
}
}
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.
}
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.
}
}
}
}
}
}
content_main.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:hwads="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:background="#FFA500">
<TextView
android:id="@+id/txt_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:clickable="true"
android:gravity="bottom"
android:padding="20dp"
android:text="Online Book Store"
android:textColor="#fff"
android:textSize="25dp"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical"
android:gravity="center_horizontal"
android:padding="10dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:gravity="center_horizontal"
android:text="Sign in"
android:textSize="30dp"
android:textColor="#fff" />
<Button
android:id="@+id/btn_huawei_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#dd4b39"
android:text="Huawei Id"
android:textColor="#fff" />
<Button
android:id="@+id/btn_email_phone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:background="#dd4b39"
android:text="Login with Phone/Email"
android:textColor="#fff" />
</LinearLayout>
<!--<com.huawei.hms.ads.banner.BannerView
android:id="@+id/hw_banner_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
hwads:adId="@string/banner_ad_id"
hwads:bannerSize="BANNER_SIZE_320_50"/>-->
</RelativeLayout>
BookStoreActivity.cs
This activity performs all the operation regarding In-App purchasing and display list of books.
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 BookStore
{
[Activity(Label = "BookStoreActivity", Theme = "@style/AppTheme")]
public class BookStoreActivity : AppCompatActivity, BuyProduct
{
private static String TAG = "BookStoreActivity";
private RecyclerView recyclerView;
private BookStoreAdapter storeAdapter;
IList<ProductInfo> productList;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_store);
recyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerview);
recyclerView.SetLayoutManager(new LinearLayoutManager(this));
recyclerView.SetItemAnimator(new DefaultItemAnimator());
//ADAPTER
storeAdapter = new BookStoreAdapter(this);
storeAdapter.SetData(productList);
recyclerView.SetAdapter(storeAdapter);
GetProducts();
}
private void GetProducts()
{
List<String> productIdList = new List<String>();
productIdList.Add("Book101");
productIdList.Add("Book102");
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 BookStoreActivity storeActivity;
public QueryProductListenerImp(BookStoreActivity storeActivity)
{
this.storeActivity = storeActivity;
}
public void OnSuccess(Java.Lang.Object result)
{
// Obtain the result
ProductInfoResult productlistwrapper = (ProductInfoResult)result;
IList<ProductInfo> productList = productlistwrapper.ProductInfoList;
storeActivity.storeAdapter.SetData(productList);
storeActivity.storeAdapter.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 BookStoreActivity storeActivity;
public BuyListenerImp(BookStoreActivity storeActivity)
{
this.storeActivity = storeActivity;
}
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(storeActivity, 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();
}
}
}
}
activity_store.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:background="#ADD8E6">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
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. User can easily log in and purchase an online book with easy and hassle-free payment.
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
Account Kit
In-App Purchase
Read In Forum

Intermediate: Huawei Activity Identification Service | HMS location kit

{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Introduction
Nowadays, everybody is using smartphones to do daily tasks like taking photos, looking up movie times, making calls etc. The best part of Android apps on mobile phones is that they are trying more and more to get to know their users. Many applications today take users' locations to provide users with locational feeds. One common example is a normal news app, where the app takes your current location and shows the news by location.
If you're a developer, you need to understand users better to give users a better experience of the application. You should know at any time what your users do. The more you know about your users, the better application for your users can build. For example, a distance calculator app lunches by itself when you start driving yourcar or bike and stops when you stop driving. Health and fitness app also uses this service to determine how many meters/kilometers you have covered on particular day.
What is Activity Identification Service?
Activity Identification Service does the heavy lifting using acceleration sensor, cellular network information and magnetometer from device to identify user’s current activity. Your app receives a list of detected activities, each of which includes possibility and identity properties.
The Activity Identification Service can detect following activities:
STILL: When the mobile device will be still, that is, the user is either sitting at someplace or the mobile device is having no motion, then the Activity Recognition Client will detect the STILL activity.
FOOT: When the mobile device is moving at a normal speed , that is, the user carrying the mobile device is either walking or running then the Activity Identification Service will detect the FOOT activity.
WALKING: This is a sub-activity of the FOOT activity which is detected by the Activity Identification Service when the user carrying the mobile device is walking.
RUNNING: This is also a sub-activity of FOOT activity which is detected by the Activity Recognition Client when the user carrying the mobile device is running.
VEHICLE: This activity detected when the mobile device is on the bus or car or some other kind of vehicle or the user holding the mobile device is present in the vehicle.
OTHERS: The Activity Identification service will show this result when the device is unable to detect any activity on the mobile device.
In this article, we will create a sample application to show user activity. When user clicks start button, we will identify user activity status along with possibility level and display the status in Textview and Imageview. And when user clicks on stop button, we will stop requesting activity identification updates.
Development Overview
Prerequisite
1. Must have a Huawei Developer Account.
2. Must have Android Studio 3.0 or later.
3. Must have Huawei phone running EMUI 5.0 or later.
4. EMUI 5.0 or later.
Software Requirements
1. Java SDK 1.7 or later.
2. Android 5.0 or later.
Preparation
1. Create an app or project in the Huawei App Gallery Connect.
2. Provide the SHA Key and App Package name of the project in App Information Section and enable the Location Kit API.
3. Download the agconnect-services.json file.
4. Create an Android project.
Integration
1. Add below to build.gradle (project) file under buildscript/repositories and allprojects/repositories.
Code:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"
classpath 'com.huawei.agconnect:agcp:1.4.2.300'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
2. Add below to build.gradle (app) file, under dependencies to use the Location kit SDK.
Code:
apply plugin: 'com.huawei.agconnect'
dependencies {
implementation 'com.huawei.hms:location:5.0.5.300'
}
Tip: Minimum android version supported for these kits is 19.
3. Add below permissions to manifest file.
For version earlier than android Q
Code:
<uses-permission android:name="com.huawei.hms.permission.ACTIVITY_RECOGNITION"/>
For version Android Q and later
Code:
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
Note: The above permissions are dangerous permission and need to be requested dynamically. Requesting permission dynamically is not covered in this article.
Development
We need to register static broadcast receiver in AndroidManifest.xmlto listen to activity status update identified by Activity Identification Service.
Code:
<receiver
android:name=".LocationReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.huawei.hmssample.location.LocationBroadcastReceiver.ACTION_PROCESS_LOCATION" />
</intent-filter>
</receiver>
Now the next step is to add the UI for our Main Activity. In our application, we will be having one TextView to display the name of the current activity and display corresponding image on ImageView and one TextView to display the possibility of Activity. We will have two Buttons to start and stop activity identification tracking. So, the activity_main.xml file looks something like this:
XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FAF0E6"
tools:context=".MainActivity">
<ImageView
android:id="@+id/ivDisplay"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_centerInParent="true"
android:scaleType="centerInside"
android:src="@drawable/ic_still" />
<TextView
android:id="@+id/tvidentity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/ivDisplay"
android:layout_marginTop="5dp"
android:textStyle="bold"
android:textColor="#192841"
android:textSize="25sp"
android:layout_centerHorizontal="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tvpossiblity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tvidentity"
android:textSize="20sp"
android:textColor="#192841"
android:layout_centerHorizontal="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/bStart"
android:layout_weight="1"
android:layout_margin="5dp"
android:text="Start Tracking"
android:textColor="@color/upsdk_white"
android:background="#192841"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/bStop"
android:layout_margin="5dp"
android:layout_weight="1"
android:text="Stop Tracking"
android:textColor="@color/upsdk_white"
android:background="#192841"/>
</LinearLayout>
</RelativeLayout>
Now let’s create instance of ActivityIdentificationService in onCreate() method of MainActivity.java
Java:
private PendingIntent mPendingIntent;
private ActivityIdentificationService identificationService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); intializeTracker(); }
private void intializeTracker() {
identificationService = ActivityIdentification.getService(this);
mPendingIntent = obtainPendingIntent();
}
To obtain PendingIntent object
Java:
private PendingIntent obtainPendingIntent() {
Intent intent = new Intent(this, LocationReceiver.class);
intent.setAction(LocationReceiver.ACTION_NAME);
return PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
When user clicks on Start Tracking Button, we will request activity identification updates by calling createActivityIdentificationUpdates() method.
identificationService.createActivityIdentificationUpdates(5000, mPendingIntent)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@override
public void onSuccess(Void aVoid) {
Log.i(TAG, "createActivityIdentificationUpdates onSuccess");
}
})
// Define callback for request failure.
.addOnFailureListener(new OnFailureListener() {
@override
public void onFailure(Exception e) {
Log.e(TAG, "createActivityIdentificationUpdates onFailure:" + e.getMessage());
}
});
This method has two parameters: detectionIntervalMillis and pendingIntent, which indicate the detection interval (in milliseconds) and action to perform, respectively.
On click of Stop Tracking Button, we will stop activity identification updates.
Java:
identificationService.deleteActivityIdentificationUpdates(mPendingIntent)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i(TAG, "deleteActivityIdentificationUpdates onSuccess");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "deleteActivityIdentificationUpdates onFailure:" + e.getMessage());
}
});
Finally, We can get activity identification result (containing identity and possibility) from intent received by the broadcast receiver.
Java:
public class LocationReceiver extends BroadcastReceiver {
public static final String ACTION_NAME = "com.huawei.hms.location.ACTION_PROCESS_LOCATION";
@Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_NAME.equals(action)) {
// Obtains ActivityIdentificationResponse from extras of the intent sent by the activity identification service.
ActivityIdentificationResponse activityIdentificationResponse = ActivityIdentificationResponse.getDataFromIntent(intent);
if(activityIdentificationResponse!= null) {
List<ActivityIdentificationData> list = activityIdentificationResponse.getActivityIdentificationDatas();
ActivityIdentificationData identificationData = list.get(list.size() -1);
int identificationIdentity = identificationData.getIdentificationActivity();
int possibility = identificationData.getPossibility();
Intent i = new Intent("activityIdentificationReceiver");
i.putExtra("identity", identificationIdentity);
i.putExtra("possibility", possibility);
context.sendBroadcast(i);
}
}
}
}
}
getActivityIdentificationDatas() API is used to obtain the list of activitiy identification list. The activity identifications are sorted by most probable activity first.
We have created Utils.java class to obtain activity status from identity code obtained from LocationReceiver
Java:
public class Utils {
public static String getActivityIdentityName(int code) {
switch(code) {
case ActivityIdentificationData.VEHICLE:
return "VEHICLE";
case ActivityIdentificationData.BIKE:
return "BIKE";
case ActivityIdentificationData.FOOT:
return "FOOT";
case ActivityIdentificationData.STILL:
return "STILL";
case ActivityIdentificationData.OTHERS:
return "OTHERS";
case ActivityIdentificationData.WALKING:
return "WALKING";
case ActivityIdentificationData.RUNNING:
return "RUNNING";
default:
return "No Data Available";
}
}
public static int getActivityIdentityDrawableID(int code) {
switch(code) {
case ActivityIdentificationData.VEHICLE:
return R.drawable.ic_driving;
case ActivityIdentificationData.BIKE:
return R.drawable.ic_on_bicycle;
case ActivityIdentificationData.FOOT:
return R.drawable.ic_still;
case ActivityIdentificationData.STILL:
return R.drawable.ic_still;
case ActivityIdentificationData.OTHERS:
return R.drawable.ic_unknown;
case ActivityIdentificationData.WALKING:
return R.drawable.ic_walking;
case ActivityIdentificationData.RUNNING:
return R.drawable.ic_running;
default:
return R.drawable.ic_unknown;
}
}
}
Code snippet of MainActivity.java
Java:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private ActivityConversionRequest request;
private Button bStart, bStop;
private TextView tvPossiblity, tvIdentity;
private ImageView ivDisplay;
private PendingIntent mPendingIntent;
private ActivityIdentificationService identificationService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intializeTracker();
bStart = findViewById(R.id.bStart);
bStop = findViewById(R.id.bStop);
tvIdentity = findViewById(R.id.tvidentity);
tvPossiblity = findViewById(R.id.tvpossiblity);
ivDisplay = findViewById(R.id.ivDisplay);
bStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
identificationService.createActivityIdentificationUpdates(5000, mPendingIntent)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i(TAG, "createActivityIdentificationUpdates onSuccess");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "createActivityIdentificationUpdates onFailure:" + e.getMessage());
}
});
}
});
bStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
identificationService.deleteActivityIdentificationUpdates(mPendingIntent)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i(TAG, "deleteActivityIdentificationUpdates onSuccess");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.e(TAG, "deleteActivityIdentificationUpdates onFailure:" + e.getMessage());
}
});
}
});
}
private void intializeTracker() {
identificationService = ActivityIdentification.getService(this);
mPendingIntent = obtainPendingIntent();
}
// Get PendingIntent associated with the custom static broadcast class LocationBroadcastReceiver.
private PendingIntent obtainPendingIntent() {
Intent intent = new Intent(this, LocationReceiver.class);
intent.setAction(LocationReceiver.ACTION_NAME);
return PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("activityIdentificationReceiver");
registerReceiver(mIdentificationReceiver , filter);
}
@Override
protected void onPause() {
super.onPause();
try {
if(mIdentificationReceiver != null){
unregisterReceiver(mIdentificationReceiver);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private BroadcastReceiver mIdentificationReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
int possibility = intent.getIntExtra("possibility", 0);
int identity = intent.getIntExtra("identity", 103);
tvIdentity.setText(Utils.getActivityIdentityName(identity));
tvPossiblity.setText("Possibility : " + String.valueOf(possibility));
ivDisplay.setImageResource(Utils.getActivityIdentityDrawableID(identity));
}
};
}
Tips and Tricks
1.During writing of this article, the activity identification service cannot identify the cycling and riding activities on devices outside the Chinese mainland.
2. ACTIVITY_RECOGNITION is dangerous permission and should be requested dynamically.
Conclusion
In this article, we have learnt how to use the Activity Identification Service in our application to determine the activities that users are doing at any given time. The Activity Identification Service determines the ongoing activities based on a possibility value that tells you which activity is currently taking place.
Hope you found this story useful and interesting.
Happy coding!
References
https://developer.huawei.com/consum...troduction-0000001050706106-V5?ha_source=hms1

Categories

Resources