Hi, as you know maps are used for different purposes in most apps. In this article, I would like to show you how to use Huawei map in Xamarin and make customizations on the map. First of all, we will follow what we need to do to add Hms Map kit to our project step by step.
Then we will focus on map customizations.
Of course, before that, we will talk about the problems you may encounter until you get to this step.
Integrating the HMS Map Kit Libraries to Xamarin Project
Let’s start. First of all, we need a Huawei developer account to use Huawei mobile services and configure our app with AppGallery Connect. Please follow the link for configuration.
How to configure app in AppGallery Connect
To use the HUAWEI Map Kit SDK for Xamarin, you need to create Xamarin Android bindings libraries from HMS Map Kit SDK for Android. After downloading the SDK files at the address below, we open a blank solution in visual studio and add these projects.
Map Kit SDK for Xamarin
{
"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"
}
Then please update the aar files in the projects.
Now we will add this solution to the our project as a reference where we will go and integrate the map kit.
We added our solution to our reference. Now we will be able to use related HMS classes in our project.
Manifest & Permissions
We have to update the application’s manifest file by declaring permissions. *Before starting this, please make sure the package name is correct since the project has been added to AppGallery Connect. Make sure that the Sha256 key is entered correctly for the respective build type and agconnect-services.json file is added to your project.
Code:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
AndroidManifest.xml
Also, we need to add a meta-data element to embed your app id in the application tag between <application> tag. It is required for this app to authenticate on the Huawei’s cloud server. You can find this id in agconnect-services.json file. If you don’t do that app couldn’t render the map.
Code:
<meta-data android:name="com.huawei.hms.client.appid" android:value="appid=YOUR_APPID"/>
Creating a Map
Currently, the HMS Core Map SDK supports two map containers: MapFragment and MapView.
MapFragment is a subclass of the Android Fragment class. You can use it to place a map within a fragment. It can also function as a map container and provide an entry for accessing a HuaweiMap object. In this article we will use a Map Fragment.
First off all please add following lines to your XML file to which one you want to show map.
Code:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/mapfragment_mapfragmentdemo"
class="com.huawei.hms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraTargetLat="41.019879"
map:cameraTargetLng="29.007822"
map:cameraZoom="12"
/>
In our activity’s OnCreate method, set the layout file as the content view, load AGConnectService. Get a handle to the map fragment by calling FragmentManager.FindFragmentById. Then use GetMapAsync to register for the map callback.
Also, implement the IOnMapReadyCallback interface to our Activity and override OnMapReady method which is triggered when the map is ready to use.
Code:
class NewActivty : AppCompatActivity, IOnMapReadyCallback
{
private MapView mMapView;
private HuaweiMap hMap;
private MapFragment mapFragment;
string[] permissions = {
Android.Manifest.Permission.AccessCoarseLocation,
Android.Manifest.Permission.AccessFineLocation,
Android.Manifest.Permission.Internet };
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_main);
mapFragment = FragmentManager.FindFragmentById<MapFragment>(Resource.Id.mapfragment_mapfragmentdemo);
mapFragment.GetMapAsync(this);
ActivityCompat.RequestPermissions(this, permissions, 100);
}
public void OnMapReady(HuaweiMap huaweiMap)
{
this.hMap = huaweiMap;
}
}
After adding the preceding information to the Manifest file, you need to dynamically apply for the permissions in the code (according to risky permission requirements in Android 6.0).
Show current location
To enable this function, set the MyLocationEnabled (true) of the HuaweiMap object
Code:
public void OnMapReady(HuaweiMap huaweiMap)
{
this.hMap = huaweiMap;
hMap.UiSettings.MyLocationButtonEnabled = true;
hMap.MyLocationEnabled = true;
}
Adding a Marker and Customization
I used more than one marker in my own project and I marked them on the map by customizing them.
You can do this directly in a method where you import the hmap object, but I created this function and I wanted to use this method by giving the necessary parameters externally.
Code:
private void addMarker(LatLng position, String title, String description)
{
Marker marker;
MarkerOptions marker3Options = new MarkerOptions()
.InvokePosition(position)
.InvokeTitle(title)
.InvokeSnippet(description);
Bitmap bitmap1 = ResourceBitmapDescriptor.DrawableToBitmap(this, ContextCompat.GetDrawable(this, Resource.Drawable.markerblue));
marker3Options.InvokeIcon(BitmapDescriptorFactory.FromBitmap(bitmap1));
marker = hMap.AddMarker(marker3Options);
hMap.MarkerDragStart += OnMarkerDragStart;
hMap.MarkerDrag += OnMarkerDrag;
hMap.MarkerDragEnd += OnMarkerDragEnd;
}
Now let’s see how our additions look on the map
Custom Information Window
When the markers are clicked, we can display custom information messages to inform. let’s see how to do this. First, create a layout for custom info.
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@color/colorPrimary"
android:orientation="horizontal">
<ImageView
android:id="@+id/customInfoImage"
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:adjustViewBounds="true" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/customInfoTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/customInfoDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:singleLine="false"
android:maxLines="2"
android:textColor="@android:color/white"
android:textSize="12sp" />
<RatingBar
android:id="@+id/customInfoRatingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:numStars="5"
android:outlineAmbientShadowColor="@android:color/white"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
</LinearLayout>
Then we add it to the class in which the click event of the marker is triggered.
Code:
hMap.SetInfoWindowAdapter(new CustomMapInfoWindow(this));
public void OnMarkerClick(object sender, HuaweiMap.MarkerClickEventArgs e)
{
Toast.MakeText(this, $"Marker Click Marker ID: {e.P0.Id}", ToastLength.Short).Show();
}
Now let’s see how it looks on map
Shape
With the HMS Core Map SDK, you can add different shapes to a map, including polylines, polygons, and circles. We can use these features for many purposes, such as creating a route between two points, expressing a specific region, or expressing the areas covered by certain regions. So the limit here is your imagination or coverage of your project.
Adding a Polyline
You can use the code block below to draw polyline. You can add as many points as you want for the route and you can give these points dynamically according to the setup of your project.
Code:
private void drawPolyline()
{
Polyline polyline;
PolylineOptions polylineOptions = new PolylineOptions()
.Add(new LatLng(41.03472222, 28.90027778), new LatLng(41.00166667, 28.97111111), new LatLng(41.00415, 29.012449), new LatLng(40.985996056, 29.035333192));
polylineOptions.InvokeColor(Color.Red);
polylineOptions.Clickable(true);
polyline = hMap.AddPolyline(polylineOptions);
}
Adding a Polygon
You can use the code block below to denote a specific region.
Code:
private void drawPolygone()
{
Polygon polygon;
PolygonOptions polygonOptions = new PolygonOptions()
.Add(new LatLng(41.01929, 28.967267), new LatLng(41.016785, 28.986971), new LatLng(41.014623, 28.999753), new LatLng(41.001917, 28.978743), new LatLng(41.002298, 28.954132));
polygonOptions.InvokeFillColor(Color.Argb(60, 255, 200, 0));
polygonOptions.InvokeStrokeColor(Color.Green);
polygonOptions.InvokeStrokeWidth(30);
polygonOptions.Clickable(true);
polygonOptions.InvokeZIndex(2);
polygon = hMap.AddPolygon(polygon1Options);
}
Adding a Circle
Whether a circle is solid or hollow can be controlled by amending the circle attributes. By default, a circle is solid. You can create your apartment by adding the code block below. You can customize many features such as scanning the inside of the circle thickness according to your purpose.
Code:
private void drawCircle()
{
Circle circle;
LatLng circleLatLng = new LatLng(40.985996056, 29.035333192);
CircleOptions circleOptions = new CircleOptions();
circle = hMap.AddCircle(circleOptions);
circleOptions.InvokeCenter(circleLatLng);
circleOptions.InvokeRadius(1800);
circleOptions.InvokeStrokeWidth(5);
circleOptions.InvokeStrokeColor(Color.Blue);
circleOptions.InvokeStrokeWidth(30);
circleOptions.Clickable(true);
circleOptions.InvokeZIndex(2);
circle = hMap.AddCircle(circleOptions);
circleOptions.Clickable(true);
hMap.CircleClick += OnCircleClick;
}
How it looks on map
Final
For any questions, please contact me. I hope this article helped you add Huawei map to your own project and learn how to use it.
Thanks for reading!
References:
Github Link
Docs
Related
{
"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"
}
Hi, as you know maps are used for different purposes in most apps. In this article, I would like to show you how to use Huawei map in Xamarin and make customizations on the map. First of all, we will follow what we need to do to add Hms Map kit to our project step by step.
Then we will focus on map customizations.
Of course, before that, we will talk about the problems you may encounter until you get to this step.
Integrating the HMS Map Kit Libraries to Xamarin Project
Let’s start. First of all, we need a Huawei developer account to use Huawei mobile services and configure our app with AppGallery Connect. Please follow the link for configuration.
How to configure app in AppGallery Connect <url>https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/config-agc-0000001050143025<url>
To use the HUAWEI Map Kit SDK for Xamarin, you need to create Xamarin Android bindings libraries from HMS Map Kit SDK for Android. After downloading the SDK files at the address below, we open a blank solution in visual studio and add these projects.
Map Kit SDK for Xamarin <url>https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/libbinding-0000001050143027<url>
Then please update the aar files in the projects.
Now we will add this solution to the our project as a reference where we will go and integrate the map kit.
We added our solution to our reference. Now we will be able to use related HMS classes in our project.
Manifest & Permissions
We have to update the application’s manifest file by declaring permissions. *Before starting this, please make sure the package name is correct since the project has been added to AppGallery Connect. Make sure that the Sha256 key is entered correctly for the respective build type and agconnect-services.json file is added to your project.
Code:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Also, we need to add a meta-data element to embed your app id in the application tag between <application> tag. It is required for this app to authenticate on the Huawei’s cloud server. You can find this id in agconnect-services.json file. If you don’t do that app couldn’t render the map.
Code:
<meta-data android:name="com.huawei.hms.client.appid" android:value="appid=YOUR_APPID"/>
Creating a Map
Currently, the HMS Core Map SDK supports two map containers: MapFragment and MapView.
MapFragment is a subclass of the Android Fragment class. You can use it to place a map within a fragment. It can also function as a map container and provide an entry for accessing a HuaweiMap object. In this article we will use a Map Fragment. First off all please add following lines to your XML file to which one you want to show map.
Code:
<fragment
android:id="@+id/mapfragment_mapfragmentdemo"
class="com.huawei.hms.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraTargetLat="41.019879"
map:cameraTargetLng="29.007822"
map:cameraZoom="12"
/>
In our activity’s OnCreate method, set the layout file as the content view, load AGConnectService. Get a handle to the map fragment by calling FragmentManager.FindFragmentById. Then use GetMapAsync to register for the map callback.
Also, implement the IOnMapReadyCallback interface to our Activity and override OnMapReady method which is triggered when the map is ready to use.
Code:
class NewActivty : AppCompatActivity, IOnMapReadyCallback
{
private MapView mMapView;
private HuaweiMap hMap;
private MapFragment mapFragment;
string[] permissions = {
Android.Manifest.Permission.AccessCoarseLocation,
Android.Manifest.Permission.AccessFineLocation,
Android.Manifest.Permission.Internet };
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
SetContentView(Resource.Layout.activity_main);
mapFragment = FragmentManager.FindFragmentById<MapFragment>(Resource.Id.mapfragment_mapfragmentdemo);
mapFragment.GetMapAsync(this);
ActivityCompat.RequestPermissions(this, permissions, 100);
}
public void OnMapReady(HuaweiMap huaweiMap)
{
this.hMap = huaweiMap;
}
}
Show current location
To enable this function, set the MyLocationEnabled (true) of the HuaweiMap object
Code:
public void OnMapReady(HuaweiMap huaweiMap)
{
this.hMap = huaweiMap;
hMap.UiSettings.MyLocationButtonEnabled = true;
hMap.MyLocationEnabled = true;
}
Adding a Marker and Customization
I used more than one marker in my own project and I marked them on the map by customizing them.
You can do this directly in a method where you import the hmap object, but I created this function and I wanted to use this method by giving the necessary parameters externally.
Code:
private void addMarker(LatLng position, String title, String description)
{
Marker marker;
MarkerOptions marker3Options = new MarkerOptions()
.InvokePosition(position)
.InvokeTitle(title)
.InvokeSnippet(description);
Bitmap bitmap1 = ResourceBitmapDescriptor.DrawableToBitmap(this, ContextCompat.GetDrawable(this, Resource.Drawable.markerblue));
marker3Options.InvokeIcon(BitmapDescriptorFactory.FromBitmap(bitmap1));
marker = hMap.AddMarker(marker3Options);
hMap.MarkerDragStart += OnMarkerDragStart;
hMap.MarkerDrag += OnMarkerDrag;
hMap.MarkerDragEnd += OnMarkerDragEnd;
}
Now let’s see how our additions look on the map.
Custom Information Window
When the markers are clicked, we can display custom information messages to inform. let’s see how to do this. First, create a layout for custom info.
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@color/colorPrimary"
android:orientation="horizontal">
<ImageView
android:id="@+id/customInfoImage"
android:layout_width="45dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:adjustViewBounds="true" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginRight="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/customInfoTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@android:color/white"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:id="@+id/customInfoDescription"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:singleLine="false"
android:maxLines="2"
android:textColor="@android:color/white"
android:textSize="12sp" />
<RatingBar
android:id="@+id/customInfoRatingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:numStars="5"
android:outlineAmbientShadowColor="@android:color/white"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
</LinearLayout>
We need to create a adapter class to be related to this layout. We are implementing HuaweiMap.IInfoWindowAdapter to this class.
Code:
class CustomMapInfoWindow : Java.Lang.Object, HuaweiMap.IInfoWindowAdapter
{
private Activity m_context;
private View m_View;
private Marker m_currentMarker;
public CustomMapInfoWindow(Activity activity)
{
m_context = activity;
m_View = m_context.LayoutInflater.Inflate(Resource.Layout.custom_info_contents, null);
}
public View GetInfoContents(Marker marker)
{
return null;
}
public View GetInfoWindow(Marker marker)
{
if (marker == null)
return null;
m_currentMarker = marker;
ImageView imageview = m_View.FindViewById<ImageView>(Resource.Id.customInfoImage);
TextView textviewTitle = m_View.FindViewById<TextView>(Resource.Id.customInfoTitle);
TextView textviewDescription = m_View.FindViewById<TextView>(Resource.Id.customInfoDescription);
RatingBar ratingBar = m_View.FindViewById<RatingBar>(Resource.Id.customInfoRatingBar);
if (marker.Title != null)
imageview.SetImageResource(Resource.Drawable.maplogo);
textviewTitle.Text = marker.Title;
textviewDescription.Text = marker.Snippet;
ratingBar.Rating = 5;
return m_View;
}
}
Then we add it to the class in which the click event of the marker is triggered.
Code:
hMap.SetInfoWindowAdapter(new CustomMapInfoWindow(this));
public void OnMarkerClick(object sender, HuaweiMap.MarkerClickEventArgs e)
{
Toast.MakeText(this, $"Marker Click Marker ID: {e.P0.Id}", ToastLength.Short).Show();
}
Now let’s see how it looks on map.
Shape
With the HMS Core Map SDK, you can add different shapes to a map, including polylines, polygons, and circles. We can use these features for many purposes, such as creating a route between two points, expressing a specific region, or expressing the areas covered by certain regions. So the limit here is your imagination or coverage of your project.
Adding a Polyline
You can use the code block below to draw polyline. You can add as many points as you want for the route and you can give these points dynamically according to the setup of your project.
Code:
private void drawPolyline()
{
Polyline polyline;
PolylineOptions polylineOptions = new PolylineOptions()
.Add(new LatLng(41.03472222, 28.90027778), new LatLng(41.00166667, 28.97111111), new LatLng(41.00415, 29.012449), new LatLng(40.985996056, 29.035333192));
polylineOptions.InvokeColor(Color.Red);
polylineOptions.Clickable(true);
polyline = hMap.AddPolyline(polylineOptions);
}
Adding a Polygon
You can use the code block below to denote a specific region.
Code:
private void drawPolygone()
{
Polygon polygon;
PolygonOptions polygonOptions = new PolygonOptions()
.Add(new LatLng(41.01929, 28.967267), new LatLng(41.016785, 28.986971), new LatLng(41.014623, 28.999753), new LatLng(41.001917, 28.978743), new LatLng(41.002298, 28.954132));
polygonOptions.InvokeFillColor(Color.Argb(60, 255, 200, 0));
polygonOptions.InvokeStrokeColor(Color.Green);
polygonOptions.InvokeStrokeWidth(30);
polygonOptions.Clickable(true);
polygonOptions.InvokeZIndex(2);
polygon = hMap.AddPolygon(polygon1Options);
}
Adding a Circle
Whether a circle is solid or hollow can be controlled by amending the circle attributes. By default, a circle is solid. You can create your apartment by adding the code block below. You can customize many features such as scanning the inside of the circle thickness according to your purpose.
Code:
private void drawCircle()
{
Circle circle;
LatLng circleLatLng = new LatLng(40.985996056, 29.035333192);
CircleOptions circleOptions = new CircleOptions();
circle = hMap.AddCircle(circleOptions);
circleOptions.InvokeCenter(circleLatLng);
circleOptions.InvokeRadius(1800);
circleOptions.InvokeStrokeWidth(5);
circleOptions.InvokeStrokeColor(Color.Blue);
circleOptions.InvokeStrokeWidth(30);
circleOptions.Clickable(true);
circleOptions.InvokeZIndex(2);
circle = hMap.AddCircle(circleOptions);
circleOptions.Clickable(true);
hMap.CircleClick += OnCircleClick;
}
How it looks on map
Final
For any questions, please contact me. I hope this article helped you add Huawei map to your own project and learn how to use it.
Thanks for reading!
References:
Github Link : <url>https://github.com/mbatuhanulper/Hms-Xamarin-Map-Demo<url>
Docs : <url>https://developer.huawei.com/consumer/en/doc/development/HMS-Plugin-Guides/drawmap-0000001050143035<url>
How can i draw dotted and dashed polyline?
In a previous post I´ve Shown you how to Sign In with Huawei without HMS, now we are going to use the credentials provided by the OAUTH APIs to access Drive kit and list the user's available files. By using the REST APIs of Drive kit, your app will be able to work without depending on the HMS Core APK, even in non-huawei devices.
Previous requirements
A developer account
Adding the required dependencies
As we have seen on the previous article, we will require the dependencies of the AppAuth library and the latest version of account kit to get access to the "Huawei Id Sign In button".
Code:
implementation 'net.openid:appauth:0.7.1'
implementation 'com.squareup.okio:okio:1.15.0'
implementation 'com.huawei.agconnect:agconnect-core:1.4.1.300'
implementation 'com.huawei.hms:hwid:5.0.1.301'
In order to get access to the user's Huawei Drive, we must use Account Kit to apply for the related scopes. You can use this link to check the complete list of Drive Scopes, use the gradle dependency for Drive Kit to quickly access to all the Drive Scopes.
Code:
implementation 'com.huawei.hms:drive:5.0.0.302'
We will not enter in details about the setup of the App Auth library, you can refer to this article to easily complete the library configuration.
Building the Auth Request
We wil use our Huawei Sign In button to trigger the Auth reques when is pressed. To achieve that we need to connect the onClick event of the button with our ViewModel.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
The data binding library can help us to directly connect the layout with the ViewModel, but this library must be enabled first on the app level buidl.gradle file.
Code:
android{
buildFeatures{
dataBinding true
viewBinding true
}
}
To use the data binding library with kotlin, we must also add the kapt plugin
Code:
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.huawei.agconnect'
id 'kotlin-kapt'
}
dependencies{
kapt 'com.android.databinding:compiler:3.1.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
}
Now is time to link the layout with the ViewModel
activity_main.xml
Code:
<?xml version="1.0" encoding="utf-8"?>
<layout
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">
<data>
<variable
name="mainVM"
type="com.hms.demo.appauthdrivekit.MainVM" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="15dp"
tools:context=".MainActivity">
<com.huawei.hms.support.hwid.ui.HuaweiIdAuthButton
android:id="@+id/hwidbtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="40dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
android:onClick="@{()->mainVM.onHwIdLogin(context)}"/>
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/welcome"
android:textSize="28sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="96dp"
android:text="@string/description"
android:textAlignment="center"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="28dp"
android:text="@string/instruction"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@+id/hwidbtn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
By using the variable tag we are preparing the ViewBinding object to receive and hold an instance of the ViewModel. To completly connect the ViewBinding with the ViewModel, we must obtain both from our activity and perform the assignation.
MainActivity.kt
Code:
class MainActivity : AppCompatActivity(), MainVM.LoginNavigator{
lateinit var viewModel:MainVM
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding=ActivityMainBinding.inflate(layoutInflater)
viewModel= ViewModelProviders.of(this).get(MainVM::class.java)
viewModel.navigator=this
setContentView(binding.root)
binding.mainVM=viewModel
}
}
Now the ViewModel is ready to listen the HwIdButton click events, when a click is detected, the Huawei OAuth request will be triggered.
MainVM.kt
Code:
class MainVM : ViewModel() {
var navigator:LoginNavigator?=null
fun onHwIdLogin(context: Context){
val appId = AGConnectServicesConfig.fromContext(context).getString(HuaweiUtils.KEY_APP_ID)
val params=HuaweiUtils.getParams(appId)
val authRequest=OAuthtils.buildRequest(params)
val authService = AuthorizationService(context)
val authIntent = authService.getAuthorizationRequestIntent(authRequest)
navigator?.navigateToHwLogin(authIntent)
authService.dispose()
}
interface LoginNavigator{
fun navigateToHwLogin(intent : Intent)
}
}
Tips & Tricks
If you want to use the App Auth library to sign in with other account systems, you can define a Data Class to hold all the required parameters by a given account system to build the auth request.
Code:
data class OAuthParams(var authEndpoint:String,
var tokenEndpoint:String,
var appId:String,
var responseTypeValues:String,
var redirectUri:Uri,
var scopes:List<String>)
object OAuthtils{
fun buildRequest(params:OAuthParams): AuthorizationRequest{
val serviceConfig = AuthorizationServiceConfiguration(
Uri.parse(params.authEndpoint), // authorization endpoint
Uri.parse(params.tokenEndpoint)// token endpoint
)
val authRequestBuilder = AuthorizationRequest.Builder(
serviceConfig, // the authorization service configuration
params.appId, // the client ID, typically pre-registered and static
params.responseTypeValues, //
params.redirectUri//The redirect URI
)
val stringBuilder= StringBuilder()
for(scope in params.scopes){
stringBuilder.append("$scope ")
}
authRequestBuilder.setScope(stringBuilder.toString())
return authRequestBuilder.build()
}
}
The related parameters for the Huawei Auth Request will be encapsulated on the HuaweiUtils object. Other objects can be defined to hold the params for other account systems which support OAuth.
Code:
object HuaweiUtils {
private const val AUTH_ENDPOINT = "https://oauth-login.cloud.huawei.com/oauth2/v3/authorize"
private const val TOKEN_ENDPOINT = "https://oauth-login.cloud.huawei.com/oauth2/v3/token"
private const val HW_REDIRECT_URI_PREFIX = "com.huawei.apps."
private const val HW_REDIRECT_URI_SUFFIX=":/oauth2redirect"
const val KEY_APP_ID="client/app_id"
const val HW_ID_CODE = 100
fun getParams(appId:String):OAuthParams{
val scopes= getHuaweiScopes()
val redirectUri=Uri.parse("${HW_REDIRECT_URI_PREFIX}appid${HW_REDIRECT_URI_SUFFIX}")
return OAuthParams(
AUTH_ENDPOINT,
TOKEN_ENDPOINT,
appId,
ResponseTypeValues.CODE,
redirectUri,
scopes
)
}
private fun getHuaweiScopes():List<String>{
return listOf("openid",
"email",
"profile",
DriveScopes.SCOPE_DRIVE,
DriveScopes.SCOPE_DRIVE_APPDATA,
DriveScopes.SCOPE_DRIVE_FILE,
DriveScopes.SCOPE_DRIVE_METADATA,
DriveScopes.SCOPE_DRIVE_METADATA_READONLY,
DriveScopes.SCOPE_DRIVE_READONLY
)
}
}
Connecting to Huawei Drive
We will use the Auth credentials obtained from the LoginActivity to connect with Huawei Drive. As you may know, the AccessToken obtaining via OAuth has an exiration time, the AppAuth library provides us an API to always use fresh tokens.
Code:
authState.performActionWithFreshTokens(service, new AuthStateAction() {
@Override public void execute(
String accessToken,
String idToken,
AuthorizationException ex) {
if (ex != null) { // negotiation for fresh tokens failed, check ex for more details
return;
} // use the access token to do something ...
}
});
Lets define the layout of our DriveActivity, we will need to know tthe identity of the user and the available space on Huawei Drive. The list of stored Items on Drive will be added later.
More details, you can visit
Drive kit supports India region ?
Interesting.
Introduction
Huawei provides various services for developers to make ease of development and provides best user experience to end users. In this article, we will cover integration of Huawei Enterprise Manager (HEM) Kit in Android.
Huawei Enterprise Manager (HEM) is a mobile device management solution provided for you based on the powerful platform and hardware of Huawei. The device deployment service in HEM helps install a Device Policy Controller (DPC) app automatically on enterprise devices in batches.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Development Overview
You need to install Android studio IDE and I assume that you have prior knowledge about the Android and java.
Hardware Requirements
A computer (desktop or laptop) running Windows 10.
A Huawei phone (with the USB cable), which is used for debugging.
An enterprise-oriented Huawei phone that has not been activated (running EMUI 11.0 or later). The bring your own device (BYOD) mode is not supported
Software Requirements
Java JDK installation package.
Android studio IDE installed.
HMS Core (APK) 5.X or later.
Follows the steps.
1. Create Android Project.
Open Android Studio.
Click NEW Project, select a Project Templet.
Enter project and Package Name and click on Finish:
2. Register as Huawei developer and complete identity verification in Huawei developer’s website, refer to register a Huawei ID.
3. To generate SHA-256 certificate fingerprint. On right-upper corner of android project click Gradle, choose Project Name > app > Tasks > android, and then click signingReport, as follows.
or
Also we can generate SHA-256 using command prompt.
To generating SHA-256 certificate fingerprint use below command.
4. Create an App in AppGallery Connect.
5. Download the agconnect-services.json file from AGC, copy and paste in android Project under app directory, as follows.
6. Add the below maven URL in build.gradle(Project level) file under the repositories of buildscript, , for more information refer Add Configuration.
Code:
maven { url 'https://developer.huawei.com/repo/' }
7. Add the below plugin and dependencies in build.gradle(App level).
Code:
apply plugin 'com.huawei.agconnect'
implementation "com.huawei.hms:hemsdk:1.0.0.303"
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
8. Open AndroidManifest file and add below permissions.
Code:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
9. Development Procedure.
1. Create a java class MainActivity.java inside your package.
MainActivity.java
Code:
package com.android.hemdemokit;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.huawei.hem.license.HemLicenseManager;
import com.huawei.hem.license.HemLicenseStatusListener;
public class MainActivity extends Activity {
private HemLicenseManager hemInstance;
private TextView resultCodeTV;
private TextView resultCodeDescTV;
private Button btnActive;
private Button btnDeActive;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hemInstance = HemLicenseManager.getInstance(this);
setButtonClickListener();
setStatusListener();
}
private void setButtonClickListener() {
btnActive = findViewById(R.id.active_btn);
btnDeActive = findViewById(R.id.de_active_btn);
esultCodeTV = findViewById(R.id.result_code_tv);
resultCodeDescTV = findViewById(R.id.result_code_desc_tv);
btnActive.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hemInstance.activeLicense();
}
});
btnDeActive.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hemInstance.deActiveLicense();
}
});
}
private void setStatusListener() {
hemInstance.setStatusListener(new MyHemLicenseStatusListener());
}
private class MyHemLicenseStatusListener implements HemLicenseStatusListener {
@Override
public void onStatus(final int errorCode, final String msg) {
resultCodeTV.post(new Runnable() {
@Override
public void run() {
resultCodeTV.setText(String.valueOf(errorCode));
}
});
resultCodeDescTV.post(new Runnable() {
@Override
public void run() {
resultCodeDescTV.setText(msg);
}
});
}
}
}
2. Create activity_main.xml layout file under app > main > res > layout folder.
activity_main.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="14dp"
android:orientation="horizontal">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="return code:"
android:textSize="16dp" />
<TextView
android:id="@+id/result_code_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@null"
android:drawablePadding="10dp"
android:padding="10dp"
android:text="" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="14dp"
android:orientation="horizontal">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="result description:"
android:textSize="16dp" />
<TextView
android:id="@+id/result_code_desc_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@null"
android:drawablePadding="10dp"
android:padding="10dp"
android:text="" />
</LinearLayout>
<Button
android:id="@+id/active_btn"
android:text="call active"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/de_active_btn"
android:text="call de_active"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
10. To build apk and run in device, choose Build > Generate Signed Bundle/APK > Build for apk or Build and Run into connected device follow the steps.
Result
1. Install application into device and click on app icon you can see below result.
2. If the EMUI device is less than targeted device, then you will get below errors.
Tips and Tricks
Always use the latest version of the library.
Add agconnect-services.json file without fail.
Add SHA-256 fingerprint without fail.
Make sure dependenciesadded in build files.
Make sure you have EMUI 11.0 and later versions.
Conclusion
In this article, we have learnt integration of Huawei HEM sdk. Also we learnt how to activate and deactivate an MDM license. HEM kit enables you to flexibly adapt your app to a wide range of device deployment scenarios for enterprises, to implement auto-deployment when they enroll a bunch of devices out of the box. This, in turn, dramatically reduces the required manual workload.
References
HEM Kit: https://developer.huawei.com/consumer/en/hms/huawei-hemkit/
Original Source
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Introduction
In this article, we can learn how to integrate the Huawei Account Kit in Book Reading app. So, I will provide the series of articles on this Book Reading App, in upcoming articles I will integrate other Huawei Kits.
Account Kit
Huawei Account Kit provides for developers with simple, secure, and quick sign-in and authorization functions. User is not required to enter accounts, passwords and waiting for authorization. User can click on Sign In with HUAWEI ID button to quickly and securely sign in to the app.
Requirements
1. Any operating system (MacOS, Linux and Windows).
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 and above installed.
4. Minimum API Level 24 is required.
5. Required EMUI 9.0.0 and later version devices.
How to integrate HMS Dependencies
1. First register as Huawei developer and complete identity verification in Huawei developers website, refer to register a Huawei ID.
2. Create a project in android studio, refer Creating an Android Studio Project.
3. Generate a SHA-256 certificate fingerprint.
4. To generate SHA-256 certificate fingerprint. On right-upper corner of android project click Gradle, choose Project Name > Tasks > android, and then click signingReport, as follows.
Note: Project Name depends on the user created name.
5. Create an App in AppGallery Connect.
6. Download the agconnect-services.json file from App information, copy and paste in android Project under app directory, as follows.
7. Enter SHA-256 certificate fingerprint and click Save button, as follows.
Note: Above steps from Step 1 to 7 is common for all Huawei Kits.
8. Click Manage APIs tab and enable Account Kit.
9. Add the below maven URL in build.gradle(Project) file under the repositories of buildscript, dependencies and allprojects, refer Add Configuration.
Java:
maven { url 'http://developer.huawei.com/repo/' }
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
[/CODE]
10. Add the below plugin and dependencies in build.gradle(Module) file.
Java:
apply plugin: id 'com.huawei.agconnect'
// Huawei AGC
implementation 'com.huawei.agconnect:agconnect-core:1.6.0.300'
// Huawei Account Kit
implementation 'com.huawei.hms:hwid:6.3.0.301'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
[/CODE]
11. Now Sync the gradle.
12. Add the required permission to the AndroidManifest.xml file.
XML:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
Let us move to development
I have created a project on Android studio with empty activity let us start coding.
In the MainActivity.kt we can find the business logic.
Java:
class MainActivity : AppCompatActivity() {
private var mAuthManager: AccountAuthService? = null
private var mAuthParam: AccountAuthParams? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sign_btn.setOnClickListener(mOnClickListener)
}
private fun signIn() {
mAuthParam = AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
.setIdToken()
.setAccessToken()
.setProfile()
.createParams()
mAuthManager = AccountAuthManager.getService([email protected], mAuthParam)
startActivityForResult(mAuthManager?.signInIntent, 1002)
}
private val mOnClickListener: View.OnClickListener = object : View.OnClickListener {
override fun onClick(v: View?) {
when (v?.id) {
R.id.sign_btn -> signIn()
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1002 ) {
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
if (authAccountTask.isSuccessful) {
Toast.makeText(this, "SigIn success", Toast.LENGTH_LONG).show()
val intent = Intent([email protected], Home::class.java)
startActivity(intent)
} else {
Toast.makeText(this, "SignIn failed: " + (authAccountTask.exception as ApiException).statusCode, Toast.LENGTH_LONG).show()
}
}
}
}
In the Home.kt we can find the business logic.
Java:
class Home : AppCompatActivity() {
lateinit var recyclerView: RecyclerView
var mBookAdapter: BookAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
recyclerView = findViewById(R.id.recycler_view)
mBookAdapter = BookAdapter()
recyclerView.adapter = mBookAdapter
}
}
Create BookAdapter.kt class for holding the list.
Java:
class BookAdapter(): RecyclerView.Adapter<BookAdapter.ViewHolder>() {
private var titles = arrayOf("Life", "Young Adult", "Comedy", "Women", "Tragedy", "Science Fiction",
"Horror Stories", "Drama", "Society", "Biography")
private var images = intArrayOf(R.drawable.life, R.drawable.youth, R.drawable.comedy, R.drawable.women,
R.drawable.tragedy, R.drawable.science, R.drawable.horror, R.drawable.drama,
R.drawable.society, R.drawable.biography)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookAdapter.ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.list_item, parent, false)
return BookAdapter.ViewHolder(view)
}
override fun onBindViewHolder(holder: BookAdapter.ViewHolder, position: Int) {
holder.itemTitle.text = titles[position]
holder.itemImage.setImageResource(images[position])
}
override fun getItemCount(): Int {
return titles.size
}
class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
var itemTitle: TextView = itemView.findViewById(R.id.titles)
var itemImage: ImageView = itemView.findViewById(R.id.images)
}
}
In the activity_main.xml we can create the UI screen.
Code:
<?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:orientation="vertical"
android:background="@drawable/book_fly"
tools:context=".MainActivity">
<TextView
android:id="@+id/act_main_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_marginLeft="20dp"
android:layout_marginTop="30dp"
android:text="Huawei E-Book Store"
android:textSize="32sp"
android:textColor="@color/hwid_auth_button_color_red"
android:textStyle="bold" />
<ImageButton
android:id="@+id/sign_btn"
android:layout_width="290dp"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:layout_margin="15dp"
android:paddingTop="10dp"
app:srcCompat="@drawable/huawei_id_buttons" />
</RelativeLayout>
In the activity_home.xml we can create the UI screen.
Java:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="8dp"
android:paddingRight="8dp"
tools:context=".Home">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_height="match_parent" />
</LinearLayout>
In the list_item.xml we can create the list of items.
Java:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/list_view"
android:layout_marginLeft="-3dp"
android:layout_marginRight="0dp"
android:layout_marginBottom="5dp"
app:cardBackgroundColor="@color/hwid_auth_button_color_border"
app:cardCornerRadius="8dp"
app:cardElevation="3dp"
app:contentPadding="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp">
<TextView
android:id="@+id/titles"
android:layout_width="160dp"
android:layout_height="50dp"
android:layout_marginStart="10dp"
android:layout_marginLeft="15dp"
android:text="Item"
android:textSize="20sp"
android:textAlignment="viewStart"
android:textColor="@color/black"
android:textStyle="bold" />
<ImageView
android:id="@+id/images"
android:layout_width="150dp"
android:layout_height="60dp"
android:layout_gravity="right"
android:layout_marginLeft="55dp" />
</LinearLayout>
</androidx.cardview.widget.CardView>
Demo
Tips and Tricks
1. Make sure you are already registered as Huawei developer.
2. Set minSDK version to 24 or later, otherwise you will get AndriodManifest merge issue.
3. Make sure you have added the agconnect-services.json file to app folder.
4. Make sure you have added SHA-256 fingerprint without fail.
5. Make sure all the dependencies are added properly.
Conclusion
In this article, we have learned how to integrate the Huawei Account Kit in Book Reading app. So, I will provide the series of articles on this Book Reading App, in upcoming articles will integrate other Huawei Kits.
I hope you have read this article. If you found it is helpful, please provide likes and comments.
Reference
Account 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
In this article, we can learn how to integrate the Huawei Analytics Kit and Ads Kit in Money Management app along with that will display the Income and Expense list of the users. The main intention of this app is to track the daily spending's of the user. Based on this tracking, users can plan their spending's on daily, monthly or yearly basis.
So, I will provide the series of articles on this Money Management App, in upcoming articles I will integrate other Huawei Kits.
Analytics Kit
HUAWEI Analytics Kit provides analysis models to understand user behaviour and gain in-depth insights into users, products and content. It helps you to gain insight about user behaviour on different platforms based on the user behaviour events and user attributes reported by through apps.
AppGallery Connect
Find the Analytics using AppGallery connect dashboard.
Choose My Projects > Huawei Analytics > Overview > Project overview.
Project overview displays the core indicators of current project, such as the number of new users, User activity, User acquisition, User revisit, New user retention, Active user retention, User characteristics and Popular pages etc. providing a quick overview of the users and how they are using your app.
Ads Kit
Huawei Ads provides to developers a wide-ranging capabilities to deliver good quality ads content to users. This is the best way to reach target audience easily and can measure user productivity. It is very useful when we publish a free app and want to earn some money from it.
HMS Ads Kit has 7 types of Ads kits. Now we can implement Rewarded Ads in this application.
Rewarded ads are full-screen video ads that allow users to view in exchange for in-app rewards.
Requirements
1. Any operating system (MacOS, Linux and Windows).
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 and above installed.
4. Minimum API Level 24 is required.
5. Required EMUI 9.0.0 and later version devices.
How to integrate HMS Dependencies
1. First register as Huawei developer and complete identity verification in Huawei developers website, refer to register a Huawei ID.
2. Create a project in android studio, refer Creating an Android Studio Project.
3. Generate a SHA-256 certificate fingerprint.
4. To generate SHA-256 certificate fingerprint. On right-upper corner of android project click Gradle, choose Project Name > Tasks > android, and then click signingReport, as follows.
Note: Project Name depends on the user created name.
5. Create an App in AppGallery Connect.
6. Download the agconnect-services.json file from App information, copy and paste in android Project under app directory, as follows.
7. Enter SHA-256 certificate fingerprint and click Save button, as follows.
Note: Above steps from Step 1 to 7 is common for all Huawei Kits.
8. Click Manage APIs tab and enable HUAWEI Analytics.
9. Add the below maven URL in build.gradle(Project) file under the repositories of buildscript, dependencies and allprojects, refer Add Configuration.
Java:
maven { url 'http://developer.huawei.com/repo/' }
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
10. Add the below plugin and dependencies in build.gradle(Module) file.
Java:
apply plugin: id 'com.huawei.agconnect'
// Huawei AGC
implementation 'com.huawei.agconnect:agconnect-core:1.6.0.300'
// // Huawei Analytics Kit
implementation 'com.huawei.hms:hianalytics:6.4.0.300'
// Huawei Ads Kit
implementation 'com.huawei.hms:ads-lite:13.4.51.300'301'
// Recycler View
implementation 'androidx.recyclerview:recyclerview:1.2.1'
11. Now Sync the gradle.
12. Add the required permission to the AndroidManifest.xml file.
XML:
// Analytics Kit
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.huawei.appmarket.service.commondata.permission.GET_COMMON_DATA" />
Let us move to development
I have created a project on Android studio with empty activity let us start coding.
In the MainActivity.kt we can find the business logic for Analytics.
Java:
class MainActivity : AppCompatActivity() {
// Initialize the Analytics
var mInstance: HiAnalyticsInstance? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_login.setOnClickListener(mOnClickListener)
// Initialize the Analytics function
initAna()
}
private fun initAna() {
// Enable Analytics Kit Log
HiAnalyticsTools.enableLog()
// Generate the Analytics Instance
mInstance = HiAnalytics.getInstance(this)
// Enable collection capability
mInstance?.setAnalyticsEnabled(true)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1002 ) {
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
if (authAccountTask.isSuccessful) {
// Analytics data to send custom events
val bundle = Bundle()
bundle.putString("email", data!!.extras!!.getString("email" ))
bundle.putString("name", data.extras!!.getString("name"))
bundle.putString("phone", data!!.extras!!.getInt("phone").toString())
bundle.putString("marks", data!!.extras!!.getFloat("86.5").toString())
mInstance!!.onEvent(HAEventType.SIGNIN, bundle)
Toast.makeText(this, "SigIn success", Toast.LENGTH_LONG).show()
} else {
Toast.makeText(this, "SignIn failed: " + (authAccountTask.exception as ApiException).statusCode, Toast.LENGTH_LONG).show()
}
}
}
}
In the Home.kt we can find the business logic for Rewarded Ads.
Java:
class Home : AppCompatActivity() {
private var rewardedAd: RewardAd? = null
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
btn_income.setOnClickListener {
rewardAdShow()
}
btn_expense.setOnClickListener {
val intent = Intent(this, ExpenseActivity::class.java)
startActivity(intent)
}
loadRewardAd()
}
private fun navigateToScreen(){
val intent = Intent(this, IncomeActivity::class.java)
startActivity(intent)
}
// Load a rewarded ad
private fun loadRewardAd() {
if (rewardedAd == null) {
rewardedAd = RewardAd(this, "testx9dtjwj8hp")
}
val rewardAdLoadListener: RewardAdLoadListener = object : RewardAdLoadListener() {
override fun onRewardedLoaded() {
showToast("onRewardedLoaded")
}
override fun onRewardAdFailedToLoad(errorCode: Int) {
navigateToScreen()
showToast("onRewardAdFailedToLoad errorCode is :$errorCode")
}
}
rewardedAd!!.loadAd(AdParam.Builder().build(), rewardAdLoadListener)
}
// Display a rewarded ad
private fun rewardAdShow() {
if (rewardedAd!!.isLoaded) {
rewardedAd!!.show(this, object : RewardAdStatusListener() {
override fun onRewardAdOpened() {
showToast("onReward Ad Opened")
}
override fun onRewardAdFailedToShow(errorCode: Int) {
showToast("onReward AdFailed ToShow errorCode is :$errorCode")
navigateToScreen()
}
override fun onRewardAdClosed() {
showToast("onReward Ad Closed")
navigateToScreen()
loadRewardAd()
}
override fun onRewarded(reward: Reward) {
loadRewardAd()
}
})
}
}
private fun showToast(text: String) {
runOnUiThread {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
}
}
}
In the IncomeActivity.kt we can find the business logic for Recycler View of Income List.
Java:
class IncomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_income)
val recyclerView = income_recycler_view
val adapter = IncomeAdapter(this)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
}
}
Create the IncomeAdapter.kt adapter class to hold the Income list.
Java:
class IncomeAdapter internal constructor (context: Context): RecyclerView.Adapter<IncomeAdapter.ViewHolder>(){
private val inflater: LayoutInflater = LayoutInflater.from(context)
private var prices = arrayOf(" +5000", " +1000", " +500", " +900", " +10000", " +700", " +4000", " +850")
private var images = intArrayOf(R.drawable.bank_deposit, R.drawable.crypto, R.drawable.mutual, R.drawable.post,
R.drawable.rainday, R.drawable.real, R.drawable.retirement_plan, R.drawable.stock)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): IncomeAdapter.ViewHolder {
val itemView = inflater.inflate(R.layout.income_list, parent, false)
return IncomeAdapter.ViewHolder(itemView)
}
override fun onBindViewHolder(holder: IncomeAdapter.ViewHolder, position: Int) {
holder.itemPrice.text = prices[position]
holder.itemImage.setImageResource(images[position])
}
override fun getItemCount(): Int {
return prices.size
}
class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
var itemPrice: TextView = itemView.findViewById(R.id.amount)
var itemImage: ImageView = itemView.findViewById(R.id.images)
}
}
In the ExpenseActivity.kt we can find the business logic for Recycler View of Expense List.
Java:
class ExpenseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_expense)
val recyclerView = expense_recycler_view
val adapter = ExpenseAdapter(this)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
}
}
Create the ExpenseAdapter.kt adapter class to hold the Expense list.
Java:
class ExpenseAdapter internal constructor (context: Context): RecyclerView.Adapter<ExpenseAdapter.ExpenseViewHolder>() {
private val inflater: LayoutInflater = LayoutInflater.from(context)
private var expenseprices = arrayOf(" -1000", " -2000", " -1500", " -500", " -2000", " -7000", " -2500", " -6500")
private var expenseimages = intArrayOf(R.drawable.clothes, R.drawable.food, R.drawable.grocery, R.drawable.icecream,
R.drawable.movie, R.drawable.resorts, R.drawable.shooping, R.drawable.trip)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExpenseAdapter.ExpenseViewHolder {
val itemView = inflater.inflate(R.layout.expense_list, parent, false)
return ExpenseAdapter.ExpenseViewHolder(itemView)
}
override fun onBindViewHolder(holder: ExpenseAdapter.ExpenseViewHolder, position: Int) {
holder.expensePrice.text = expenseprices[position]
holder.expenseImage.setImageResource(expenseimages[position])
}
override fun getItemCount(): Int {
return expenseprices.size
}
class ExpenseViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
var expensePrice: TextView = itemView.findViewById(R.id.expense_amount)
var expenseImage: ImageView = itemView.findViewById(R.id.expense_images)
}
}
In the activity_home.xml we can create the UI screen for buttons.
XML:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="10dp"
android:paddingBottom="10dp"
tools:context=".Home">
<Button
android:id="@+id/btn_income"
android:layout_width="220dp"
android:layout_height="wrap_content"
android:layout_marginTop="70dp"
android:textAlignment="center"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:textColor="@color/dot_dark_screen3"
android:padding="10dp"
android:textAllCaps="false"
android:text="Income" />
<Button
android:id="@+id/btn_expense"
android:layout_width="220dp"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:textAlignment="center"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:textColor="@color/dot_dark_screen4"
android:padding="8dp"
android:textAllCaps="false"
android:text="Expenses" />
<Button
android:id="@+id/btn_trans"
android:layout_width="220dp"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:textAlignment="center"
android:layout_gravity="center_horizontal"
android:textSize="20sp"
android:textColor="@color/dot_dark_screen5"
android:padding="8dp"
android:textAllCaps="false"
android:text="Transactions" />
</LinearLayout>
In the activity_income.xml we can create the UI screen Recycler Items.
XML:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="8dp"
android:paddingRight="8dp"
tools:context=".IncomeActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:layout_gravity="center_horizontal"
android:text="Income"
android:textStyle="bold"
android:textColor="#025022"
android:layout_marginBottom="20dp"
android:textSize="30sp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/income_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
In the activity_expense.xml we can create the UI screen Recycler Items.
XML:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="8dp"
android:paddingRight="8dp"
tools:context=".ExpenseActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:layout_gravity="center_horizontal"
android:text="Expenses"
android:textStyle="bold"
android:textColor="#F1066F"
android:layout_marginBottom="20dp"
android:textSize="30sp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/expense_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
In the income_list.xml we can create the custom view of Recycler UI Items.
XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="-3dp"
android:layout_marginTop="5dp"
android:layout_marginRight="0dp"
android:layout_marginBottom="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/images"
android:layout_width="130dp"
android:layout_height="80dp"
android:layout_gravity="left"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp" />
<TextView
android:id="@+id/amount"
android:layout_width="wrap_content"
android:layout_height="80dp"
android:layout_marginLeft="45dp"
android:text="Item"
android:textSize="36sp"
android:layout_gravity="end"
android:textAlignment="viewEnd"
android:textColor="@android:color/holo_green_light"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
In the expense_list.xml we can create the custom view of Recycler UI Items.
XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="-3dp"
android:layout_marginTop="5dp"
android:layout_marginRight="0dp"
android:layout_marginBottom="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/expense_images"
android:layout_width="130dp"
android:layout_height="80dp"
android:layout_gravity="left"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp" />
<TextView
android:id="@+id/expense_amount"
android:layout_width="wrap_content"
android:layout_height="80dp"
android:layout_marginLeft="45dp"
android:text="Item"
android:textSize="36sp"
android:layout_gravity="end"
android:textAlignment="viewEnd"
android:textColor="@color/purple_200"
android:textStyle="bold" />
</LinearLayout>
</androidx.cardview.widget.CardView>
Demo
Tips and Tricks
1. Make sure you are already registered as Huawei developer.
2. Set minSDK version to 24 or later, otherwise you will get AndriodManifest merge issue.
3. Make sure you have added the agconnect-services.json file to app folder.
4. Make sure you have added SHA-256 fingerprint without fail.
5. Make sure all the dependencies are added properly.
Conclusion
In this article, we have learned how to integrate the Huawei Analytics Kit and Ads Kit in Money Management app along with that will display the Income and Expense list of the users. The main intention of this app is to track the daily spending's of the user. Based on this tracking, users can plan their spending's on daily, monthly or yearly basis. So, I will provide the series of articles on this Money Management App, in upcoming articles will integrate other Huawei Kits.
I hope you have read this article. If you found it is helpful, please provide likes and comments.
Reference
Analytics Kit – Documentation
Analytics Kit – Training Video
Ads Kit - Documentation
Ads Kit – Training Video