Huawei Map as Popup using (Dialogs, Activities, Fragments) - Huawei Developers

Article Introduction
In this article we will show Huawei Map as popup in three different ways. By using Dialogs, separate Activity and separate Fragment. We can explore some of the restrictions and advantages of show Huawei Map as Popup in different methodologies.
Huawei Map Kit
Personalizing how your map displays and interacts with your users tailors their experience to them, not the other way around. Make location-based services work better for you so your app works better for your users.
1. Dialog
Using Dialog to show Huawei Map and mark user home address and return user coordinate and address for further processing.
Let’s begin with coding part without wasting more time.
Step 1: Dialog layout design
Design the layout for Huawei Map to display inside Dialog.
Code:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
android:alpha="0.4"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="450dp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:background="@color/white"
android:orientation="vertical">
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/mapFragment"
android:name="com.huawei.hms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:layout_weight="2"
map:cameraZoom="10"
map:cameraTargetLat="24.774265"
map:cameraTargetLng="46.738586"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginBottom="10dp"
android:orientation="horizontal">
<Button
android:id="@+id/btn_close_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="closeDialog"
android:text="Close" />
<Button
android:id="@+id/btn_save_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Save"
android:onClick="saveDialogMap"
/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
How layout look like
{
"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"
}
Step 2: Main Activity code to display Dialog
Implement OnMapReadyCallback and OnMapClickLisner
Code:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, HuaweiMap.OnMapClickListener {}
Define some variables which we use later in the code
Code:
Dialog dialog;
private HuaweiMap hmap;
private SupportMapFragment mSupportMapFragment;
private Marker mMarker;
private LatLng myLocation;
private String myAddress;
Check code for onMapRead, onMapClick for add Marker, addMarker method and finally getUserAddress.
Code:
@Override
public void onMapReady(HuaweiMap huaweiMap) {
hmap = huaweiMap;
hmap.setOnMapClickListener(this);
}
@Override
public void onMapClick(LatLng latLng) {
myLocation = latLng;
addMyMarker(myLocation);
}
public void addMyMarker(LatLng myMapPosition) {
myAddress = getMyAddress(myMapPosition);
if(mMarker != null) mMarker.remove();
mMarker = hmap.addMarker(new MarkerOptions()
.position(myMapPosition)
.draggable(true)
.icon(BitmapDescriptorFactory.defaultMarker
(BitmapDescriptorFactory.HUE_RED))
.title(myAddress));
}
public String getMyAddress(LatLng latLng) {
Geocoder geo = new Geocoder(this, Locale.getDefault());
String myAddress = "";
try {
List<Address> addresses = geo.getFromLocation(latLng.latitude, latLng.longitude, 1);
if (addresses.size() > 0) {
String cityName = addresses.get(0).getAdminArea();
String countryName = this.getResources().getConfiguration().locale.getDisplayCountry();
String address = addresses.get(0).getAddressLine(0);
myAddress = address;
Log.i("Site_Result", "countryName: " + countryName + ", CITY : " + cityName + ", Address: " + address);
}
} catch (IOException e) {
Log.i("Site_Result", "Error");
e.printStackTrace();
}
return myAddress;
}
Lastly we can show Dialog when user click on button, can close the dialog and save user location coordinates / address data for further processing.
Code:
public void showMyDailog(){
if(dialog == null){
dialog = new Dialog(this);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.dailog_map_popup);
dialog.show();
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.mapFragment);
if (fragment instanceof SupportMapFragment) {
mSupportMapFragment = (SupportMapFragment) fragment;
mSupportMapFragment.getMapAsync(this);
}
} else {
dialog.show();
}
}
public void closeDialog(View v) {
if(dialog != null){
dialog.dismiss();
}
}
public void saveDialogMap(View v) {
if(myLocation != null && myAddress != null && dialog != null){
String text = "PopupType: Dialog \nLatitude: " +myLocation.latitude + " \nLongitude: " +myLocation.longitude+ " \nAddress: " + myAddress;
textViewAddress.setText(text);
dialog.dismiss();
}
}
Step 3: Launch the Dialog
You can result of launching of Huawei Map popup using Dialog.
Note: You have notice one issue, once user open the Dialog second time Huawei Map is becoming empty and not showing any data. To solve this issue developer can either user Activity way or Fragment way. Currently Huawei Team is working to this issue for fix Huawei Map not to be Empty on Dialog.
2. Activity
You need to make separate activity and launch the activity with theme which behaves like dialog window without any title. And return some data to parent activity when we save some user location data and address for further processing.
Let’s begin with coding part without wasting more time.
Step 1: Make new Activity (HuaweiMapPopupActivity)
We need to make new Activity to show Huawei Map.
Code:
public class HuaweiMapPopupActivity extends AppCompatActivity implements OnMapReadyCallback,
HuaweiMap.OnCameraMoveStartedListener, HuaweiMap.OnCameraMoveListener, HuaweiMap.OnCameraIdleListener,
HuaweiMap.OnMyLocationButtonClickListener, HuaweiMap.OnMapClickListener {
}
Step 2: Make new theme for Huawei to show as Dialog
Define new theme for dialog in styles.xml file.
Code:
<!-- AppDialog Huawei theme. -->
<style name="AppDialogHuaweiTheme" parent="Theme.AppCompat.Light.Dialog">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:dialogTitle">false</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:background">@android:color/transparent</item>
</style>
Step 3: Assign theme to Activity
Go into AndroidManifest.xml file and define the newly created theme style.
Code:
<activity
android:name=".HuaweiMapPopupActivity"
android:theme="@style/AppDialogHuaweiTheme"
android:title="" />
Step 4: Design Layout for Activity of Huawei Map
Check layout design for our Activity.
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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="450dp"
android:layout_gravity="center_vertical"
android:orientation="vertical"
tools:context=".HuaweiMapPopupActivity">
<fragment
android:id="@+id/map"
android:name="com.huawei.hms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:layout_weight="2" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
android:layout_marginBottom="10dp"
>
<Button
android:id="@+id/btn_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Close" />
<Button
android:id="@+id/btn_save"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Save" />
</LinearLayout>
</LinearLayout>
More details, you can visit https://forums.developer.huawei.com/forumPortal/en/topic/0204395191834640053

Related

Example of Direction Steps - MAP KIT

Direction Steps
{
"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"
}
Overview
This article will guide to view the Directions steps for all types such as driving, by-cycling and walking.
In this, Used BottomSheet Layout for better user experience. For using BottomSheet, need to set app:layout_behavior attribute to NestedScrollView. Check the below code
Code:
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<androidx.core.widget.NestedScrollView
android:id="@+id/bottom_sheet_steps"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="@drawable/tool_gradient" />
<include layout="@layout/content_steps" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Check the below code for tool_gradient.xml drawable
Code:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="90"
android:startColor="#fff" />
</shape>
Check the below code for content_steps.xml layout
Code:
<?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:background="#fff"
android:orientation="vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/dimen_10">
<ImageView
android:id="@+id/img_time"
android:layout_width="@dimen/dimen_30"
android:layout_height="@dimen/dimen_30"
android:src="@drawable/time_pc" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_toEndOf="@id/img_time"
android:text="Distance"
android:textColor="#000"
android:textSize="14sp" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/dimen_10"
android:layout_marginTop="@dimen/dimen_10"
android:orientation="horizontal">
<TextView
android:id="@+id/txt_distance_steps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="15.34"
android:textColor="@color/red"
android:textSize="25sp"
android:textStyle="bold" />
<TextView
android:id="@+id/txtMKM"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" km" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="@dimen/dimen_10"
android:layout_height="@dimen/dimen_10"
android:layout_gravity="center_vertical"
android:layout_marginStart="@dimen/dimen_30"
android:src="@drawable/circular_marker" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen_50"
android:text="Your Location"
android:textColor="#000"
android:textSize="14sp" />
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_steps"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/dimen_10"
android:layout_marginTop="@dimen/dimen_10" />
</LinearLayout>
After that, Add below code in Activity onCreate. Here bottomSheetStepsView is View object and behaviourSteps is BottomSheetBehavior object
Code:
bottomSheetStepsView = findViewById(R.id.bottom_sheet_steps);
behaviourSteps = BottomSheetBehavior.from(bottomSheetStepsView);
behaviourSteps.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@SuppressLint("RestrictedApi")
@Override
public void onStateChanged(@NonNull View bottomSheet, int newState) {
switch (newState) {
case BottomSheetBehavior.STATE_EXPANDED:
myLocationFab.setVisibility(View.INVISIBLE);
imgBackDirections.setVisibility(View.INVISIBLE);
txtDirectionAddress.setVisibility(View.VISIBLE);
break;
case BottomSheetBehavior.STATE_DRAGGING:
myLocationFab.setVisibility(View.INVISIBLE);
break;
case BottomSheetBehavior.STATE_COLLAPSED:
myLocationFab.setVisibility(View.VISIBLE);
imgBackDirections.setVisibility(View.VISIBLE);
txtDirectionAddress.setVisibility(View.INVISIBLE);
behaviourSteps.setPeekHeight(900);
break;
}
}
@Override
public void onSlide(@NonNull View bottomSheet, float slideOffset) {
// React to dragging events
}
});
Initialize steps adapter
Code:
private void initStepsAdapter() {
stepsAdapter = new StepsAdapter(this);
stepsAdapter.type = 0;
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerViewSteps.setLayoutManager(linearLayoutManager);
recyclerViewSteps.setItemAnimator(new DefaultItemAnimator());
recyclerViewSteps.setAdapter(stepsAdapter);
}
In the Direction API response we will get steps response. Here directionType will be driving,bycycling or walking based on requirements. Check the below code
Code:
private void callDirectionsApi(final String directionType) {
if (!NetworkUtil.isNetworkConnected(this)) {
showNetworkDialog();
return;
}
Origin origin = new Origin();
origin.setLat(myLocation.getLatitude());
origin.setLng(myLocation.getLongitude());
Destination destination = new Destination();
destination.setLat(destinationLocation.getLat());
destination.setLng(destinationLocation.getLng());
DirectionsRequest request = new DirectionsRequest();
request.setOrigin(origin);
request.setDestination(destination);
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<DirectionsResponse> call = apiInterface.getDirections(directionType, request);
call.enqueue(new Callback<DirectionsResponse>() {
@Override
public void onResponse(@NotNull Call<DirectionsResponse> call, @NotNull Response<DirectionsResponse> response) {
if (response.isSuccessful()) {
DirectionsResponse directionsResponse = response.body();
assert directionsResponse != null;
Log.e(TAG + " Response", directionsResponse.toString());
List<RoutesItem> routesItemList = directionsResponse.getRoutes();
if (routesItemList.size() > 0) {
PathsItem pathsItem = (routesItemList.get(0).getPaths().get(0));
String distance, mORkm;
if (pathsItem.getDistance() < 1000) {
distance = String.valueOf((int) pathsItem.getDistance());
mORkm = " m";
} else {
distance = String.valueOf((int) pathsItem.getDistance() / 1000);
mORkm = " km";
}
txtMKMSteps.setText(mORkm);
txtDirectionTitle.setText(destinationName);
txtDistanceSteps.setText(distance);
txtDirectionAddress.setText(pathsItem.getEndAddress());
List<StepsItem> steps = routesItemList.get(0).getPaths().get(0).getSteps();
setStepsData(steps);
}
@Override
public void onFailure
(@NotNull Call<DirectionsResponse> call, @NotNull Throwable t) {
Log.e(TAG + " Response Error", Objects.requireNonNull(t.getMessage()));
}
});
}
Add the steps data to Steps Adapter
Code:
private void setStepsData(List<StepsItem> steps) {
stepsAdapter.addList(steps);
}
Steps item layout for adapter. Check the below code
Code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/lout_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/img_step_direction"
android:layout_width="@dimen/dimen_50"
android:layout_height="@dimen/dimen_50"
android:layout_gravity="center"
android:layout_margin="@dimen/dimen_10"
android:padding="7dp"
android:src="@drawable/turn_left" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen_10"
android:layout_marginTop="@dimen/dimen_10"
android:layout_marginEnd="@dimen/dimen_10"
android:orientation="vertical">
<TextView
android:id="@+id/txt_distance_top"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1.1 km"
android:textSize="14sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp">
<TextView
android:id="@+id/txt_step_instruction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Turn left and take Renigunta Road"
android:textColor="#000"
android:textSize="14sp" />
<TextView
android:id="@+id/txt_road_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/txt_step_instruction"
android:text="Renigunta Road"
android:layout_marginBottom="@dimen/dimen_10"
android:textSize="14sp" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txt_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2 min"
android:textColor="#000"
android:textSize="14sp" />
<TextView
android:id="@+id/txt_distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dimen_30"
android:layout_toEndOf="@id/txt_time"
android:text="1.1 km"
android:textColor="#000"
android:textSize="14sp" />
<View
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="0.1dp"
android:layout_marginStart="@dimen/dimen_20"
android:layout_marginTop="@dimen/dimen_15"
android:layout_marginEnd="@dimen/dimen_20"
android:layout_toEndOf="@id/txt_distance"
android:background="@color/grey" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
Check the below code for StepsAdapter
Code:
public class StepsAdapter extends RecyclerView.Adapter<StepsAdapter.MyHolder> {
private ArrayList<StepsItem> list = new ArrayList<>();
private Context context;
public int type = 0;
public void addList(List<StepsItem> stepsList) {
if (list != null) {
list.clear();
list.addAll(stepsList);
notifyDataSetChanged();
}
}
StepsAdapter(Context context) {
this.context = context;
}
public class MyHolder extends RecyclerView.ViewHolder {
LinearLayout loutRoot;
TextView txtInstruction, txtRoadName;
ImageView imgStepDirection;
TextView txtTime, txtDistance;
TextView txtDistanceTop;
View view;
public MyHolder(@NonNull View itemView) {
super(itemView);
txtInstruction = itemView.findViewById(R.id.txt_step_instruction);
txtRoadName = itemView.findViewById(R.id.txt_road_name);
imgStepDirection = itemView.findViewById(R.id.img_step_direction);
txtTime = itemView.findViewById(R.id.txt_time);
txtDistance = itemView.findViewById(R.id.txt_distance);
txtDistanceTop = itemView.findViewById(R.id.txt_distance_top);
view = itemView.findViewById(R.id.view);
loutRoot = itemView.findViewById(R.id.lout_root);
}
}
@NonNull
@Override
public StepsAdapter.MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.inflate_steps_item, parent, false);
return new StepsAdapter.MyHolder(view);
}
@Override
public void onBindViewHolder(@NonNull final StepsAdapter.MyHolder holder, final int position) {
if (type == 0) {
holder.txtDistanceTop.setVisibility(View.GONE);
} else {
holder.txtDistance.setVisibility(View.GONE);
holder.txtTime.setVisibility(View.GONE);
holder.view.setVisibility(View.GONE);
}
holder.txtInstruction.setText(list.get(position).getInstruction());
holder.txtDistance.setText(list.get(position).getDistanceText());
holder.txtDistanceTop.setText(list.get(position).getDistanceText());
holder.txtTime.setText(list.get(position).getDurationText());
holder.txtRoadName.setText(list.get(position).getRoadName());
int imageResource;
if (list.get(position).getAction().contains("left")) {
imageResource = R.drawable.turn_left;
} else if (list.get(position).getAction().contains("right")) {
imageResource = R.drawable.turn_right;
} else if (list.get(position).getAction().contains("straight")) {
imageResource = R.drawable.straight;
} else {
imageResource = 0;
}
Glide.with(context).load(imageResource).into(holder.imgStepDirection);
holder.loutRoot.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
StepsAdapter.MapStepClick placeClick = (StepsAdapter.MapStepClick) context;
placeClick.mapStepClick(list, position);
}
});
}
@Override
public int getItemCount() {
return list.size();
}
interface MapStepClick {
void mapStepClick(ArrayList<StepsItem> list, int position);
}
}
Find the output in below image
Conclusion
In this article we can learn about Direction Steps and BottomSheet Behaviour and it's callbacks. Based on these steps data we can develop preview routes.
Let’s wait for next article.
More information, you can visit https://forums.developer.huawei.com/forumPortal/en/home?tagId=0801188417594370004
Huawei map kit will support find nearest path?
sujith.e said:
Huawei map kit will support find nearest path?
Click to expand...
Click to collapse
Yep, it helps to find the nearest route and its condition. Believe it will facilitate our life in all aspects.

Intermediate: OneSignal Email APIs Integration in Xamarin (Android)

Overview
In this article, I will create a demo app along with the integration of OneSignal Email APIs which is based on Cross platform Technology Xamarin. It provides an easy-to-use email building interface that allow user to construct fantastic templates for all your emails.
OneSignal Service Introduction
OneSignal supports email as a messaging channel to provide you with more ways to reach users.
Single SDK- User won't need to manage separate SDKs for email and push, and it will be able to use the same familiar methods and syntax that already used for push.
Single API - User can use the same APIs, segments, and other features that may use for push notifications to send your emails as well.
Prerequisite
1. Xamarin Framework
2. Huawei phone
3. Visual Studio 2019
4. OneSignal Account
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 and download the configuration file.
3. Navigate to General Information, and then provide Data Storage location.
OneSignal SDK Integration process
1. Choose Huawei Android (HMS) and provide app name.
2. Choose Xamarin then click Next: Install and Test.
3. Copy your App Id.
4. Navigate to One Signal’s Dashboard > Messages > New Email.
5. Enter Email Details.
Installing the Huawei ML NuGet package
1. Navigate to Solution Explore > Project > Right Click > Manage NuGet Packages.
2. Search on Browser Com.OneSignal and Install the package.
Xamarin App Development
1. Open Visual Studio 2019 and Create A New Project.
2. Configure Manifest file and add following permissions and tags.
Code:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
package="com.hms.onesignalemail">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" ></uses-sdk>
<permission android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<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">
<receiver android:name="com.onesignal.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
3. Create Activity class with XML UI.
MainActivity.cs
This activity performs email send operation with help of OneSignal’s Email APIs.
Code:
using System;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Support.Design.Widget;
using Android.Support.V7.App;
using Android.Views;
using Android.Widget;
using Com.OneSignal;
using Com.OneSignal.Abstractions;
namespace OneSignalDemo
{
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
private Android.App.AlertDialog sendingDialog;
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);
Button button = FindViewById<Button>(Resource.Id.buttonSend);
button.Click += delegate {
ShowProgressBar("Sending Email");
};
}
public void sendEmail()
{
OneSignal.Current.SetEmail("[email protected]");
string email = "[email protected]";
string emailAuthHash = null; // Auth hash generated from your server
OneSignal.Current.SetEmail(email, emailAuthHash, () => {
//Successfully set email
}, (error) => {
//Encountered error setting email
});
}
public void logoutEmail()
{
OneSignal.Current.LogoutEmail();
// Optionally, you can also use callbacks
OneSignal.Current.LogoutEmail(() => {
//handle success
}, (error) => {
//handle failure
});
}
private void setUpOneSignal()
{
OneSignal.Current.SetLogLevel(LOG_LEVEL.VERBOSE, LOG_LEVEL.NONE);
OneSignal.Current.StartInit("83814abc-7aad-454a-9d20-34e3681efcd1")
.InFocusDisplaying(OSInFocusDisplayOption.Notification)
.EndInit();
}
public void ShowProgressBar(string message)
{
Android.App.AlertDialog.Builder dialogBuilder = new Android.App.AlertDialog.Builder(this);
var inflater = (LayoutInflater)GetSystemService(Context.LayoutInflaterService);
var dialogView = inflater.Inflate(Resource.Layout.dialog, null);
dialogBuilder.SetView(dialogView);
dialogBuilder.SetCancelable(false);
var tvMsg = dialogView.FindViewById<TextView>(Resource.Id.tvMessage);
tvMsg.Text = message;
sendingDialog = dialogBuilder.Create();
sendingDialog.Show();
}
public void HideProgressBar()
{
if (sendingDialog != null)
{
sendingDialog.Dismiss();
}
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.menu_main, menu);
return true;
}
public override bool OnOptionsItemSelected(IMenuItem item)
{
int id = item.ItemId;
if (id == Resource.Id.action_settings)
{
return true;
}
return base.OnOptionsItemSelected(item);
}
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);
}
}
}
email_activity.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/activity_main">
<TextView
android:text="Recipient Email"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editTextEmail" />
<TextView
android:text="Subject"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editTextSubject" />
<TextView
android:text="Message"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<EditText
android:lines="4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editTextMessage" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/buttonSend"
android:text="Send"/>
</LinearLayout>
sent_activity.xml
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"
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/activity_main">
<ImageView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerInParent="true"
android:src="@drawable/ok"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="30sp
"
android:gravity="center"
android:text="Email Sent Successfully" />
</LinearLayout>
progress_dialog.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<TableRow
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ProgressBar
android:id="@+id/progressbar"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<TextView
android:gravity="center|left"
android:id="@+id/tvMessage"
android:layout_width="match_parent"
android:text="Sending Email"
android:layout_height="match_parent"
android:layout_marginLeft="16dp" />
</TableRow>
</RelativeLayout>
Xamarin App Build Result
1. Navigate to Build > Build Solution.
2. Navigate to Solution Explore > Project > Right Click > Archive/View Archive to generate SHA-256 for build release and Click on Distribute.
3. Choose Archive > Distribute.
4. Choose Distribution Channel > Ad Hoc to sign apk.
5. Choose Demo keystore to release apk.
6. Build succeed and click Save.
7. Result.
Tips and Tricks
1. OneSignal does not act as its own email service provider, you will need to sign up for one.
2. Email and push subscribers will have separate OneSignal Player IDs. This is to manage the case where a user opts-out of one you can still send them messages to the other.
3. To configure email, you will need to modify your domain's DNS records. Different email service providers have different requirements for which records need modifying, which likely include MX, CNAME, and TXT types.
Conclusion
In this article, we have learned how to integrate OneSignal Push Notification in Xamarin based Android application. Developer can send OneSignal’s Push Message to users for new updates or any other information.
Thanks for reading this article. Be sure to like and comment to this article, if you found it helpful. It means a lot to me.
References
OneSignal Email API https://documentation.onesignal.com/docs/email-overview
Original Source

Integrating App Linking in a Xamarin app for Android

Xamarin is a popular cross platform framework to build mobile applications using .net
A number of AppGallery Connect services support many cross platform frameworks including Xamarin. Today we are going to take a look at how you can use one of these services, App Linking within your Xamarin project.
Enabling App Linking in AppGallery Connect​
Create an app or use an existing app in AppGallery Connect. Click My projects, go to Grow > App Linking, and click Use now on the displayed page.
On the displayed App Linking page, click the URL prefixes tab and then click New URL prefix to create a unique URL prefix.
{
"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"
}
Preparing the Xamarin Android Development Environment​Completing Android Setup​Download the JSON file from AppGallery Connect and copy the file to your project’s Assets directory.
Set a package name. Right-click your project and choose Properties. Click Android Manifest on the displayed page and set the same package name to that in the JSON file.
Implement LazyInputStream to read the agconnect-services.json file.
Right-click your project, and choose Add > New Item. In the displayed window, select Class and name the new class HmsLazyInputStream.cs.
Implement LazyInputStream to read the agconnect-services.json file.
Right-click your project, and choose Add > New Item. In the displayed window, select Class and name the new class HmsLazyInputStream.cs.
C-like:
using System;
using System.IO;
using Android.Content;
using Android.Util;
using Huawei.Agconnect.Config;
namespace AppLinking1
{
public class HmsLazyInputStream : LazyInputStream
{
public HmsLazyInputStream(Context context)
: base(context)
{
}
public override Stream Get(Context context)
{
try
{
return context.Assets.Open("agconnect-services.json");
}
catch (Exception e)
{
Log.Error("Hms", $"Failed to get input stream" + e.Message);
return null;
}
}
}
}
Create another new class as described in the preceding steps and read the agconnect-services.json file before your app is launched. You can name the new class CustomContentProvider.cs, which extends the ContentProvider class, and set the authorities and InitOrder attributes for the new class.
C-like:
using System;
using Android.Content;
using Android.Database;
using Huawei.Agconnect.Config;
namespace AppLinking1
{
[ContentProvider(new string[] { "com.huawei.applinkingdemo.CustomContentProvider" }, InitOrder = 99)]
class CustomContentProvider : ContentProvider
{
public override int Delete(Android.Net.Uri uri, string selection, string[] selectionArgs)
{
throw new NotImplementedException();
}
public override string GetType(Android.Net.Uri uri)
{
throw new NotImplementedException();
}
public override Android.Net.Uri Insert(Android.Net.Uri uri, ContentValues values)
{
throw new NotImplementedException();
}
public override bool OnCreate()
{
AGConnectServicesConfig config = AGConnectServicesConfig.FromContext(Context);
config.OverlayWith(new HmsLazyInputStream(Context));
return false; throw new NotImplementedException();
}
public override ICursor Query(Android.Net.Uri uri, string[] projection, string selection, string[] selectionArgs, string sortOrder)
{
throw new NotImplementedException();
}
public override int Update(Android.Net.Uri uri, ContentValues values, string selection, string[] selectionArgs)
{
throw new NotImplementedException();
}
}
}
Installing the Service SDK for Android​Right-click your project and choose Manage NuGet Packages.
Search for AppLinking on the Browse tab. Click Xamarin.Android bindings for AGC — Applinking in the search results and install it.
Agree to the service agreement as prompted.
Developing Your App​Creating an App Linking Link​To specify the layout of your app, open the activity_main file under Resources > layout. Sample code:
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:layout_margin="16dp"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/textDeepLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="DeepLink:"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/deepLink"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/create"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create Link" />
<TextView
android:id="@+id/ShortLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Short Link:"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textShortLink"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/LongLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Long Link:"
android:textSize="18sp"
android:textStyle="bold"
/>
<TextView
android:id="@+id/textLongLink"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/shareShort"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Share Short Link" />
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="80dp" />
</LinearLayout>
Open the MainActivity.cs file and import the following packages
C-like:
using Android.App;
using Android.OS;
using Android.Runtime;
using Android.Widget;
using AndroidX.AppCompat.App;
using System;
using Huawei.Agconnect.Applinking;
using Uri = Android.Net.Uri;
using Debug = System.Diagnostics.Debug;
using Android.Content;
Configure button actions in the onCreate method
C-like:
FindViewById<Button>(Resource.Id.create).Click += CreateAppLink;
FindViewById<Button>(Resource.Id.shareShort).Click += ShareShortAppLink;
Create an App Linking link and implement the method for sharing the link.
C-like:
private AppLinking.Builder builder;
public static string longLink = null;
public static string shortLink = null;
public static string UriPrefix = "https://applinkingtest.drcn.agconnect.link";
public static string OpenApp_Link = "https://open.androiddemoapp.com";
public static string OpenDetail_Link = "https://open.androiddemoapp.com/detail?id=358";
private async void CreateAppLink(object sender, EventArgs e)
{
builder = new AppLinking.Builder();
// Set a URL prefix.
builder.SetUriPrefix(UriPrefix);
// Set a deep link.
builder.SetDeepLink(Uri.Parse(OpenApp_Link));
//Set the link preview type. If this method is not called, the preview page with app information is displayed by default.
builder.SetPreviewType(AppLinking.LinkingPreviewType.AppInfo);
// (Optional) Set Android link behavior.
var behaviorBuilder = new AppLinking.AndroidLinkInfo.Builder();
// Set an earliest version. If a user's app version is earlier than the earliest version, your app will redirect the user to update the app on AppGallery.
behaviorBuilder.SetMinimumVersion(1);
builder.SetAndroidLinkInfo(behaviorBuilder.Build());
longLink = builder.BuildAppLinking().Uri.ToString();
FindViewById<TextView>(Resource.Id.textLongLink).Text = longLink;
}
private void ShareShortAppLink(object sender, EventArgs e)
{
string agcLink = FindViewById<TextView>(Resource.Id.textShortLink).Text;
Intent intent = new Intent(Intent.ActionSend);
intent.SetType("text/plain");
intent.PutExtra(Intent.ExtraText, agcLink);
intent.AddFlags(ActivityFlags.NewTask);
StartActivity(intent);
}
Receiving an App Linking Link​Configure the code of the activity for receiving an App Linking link.
Right-click the project, choose add > New Item, select Activity, and name it DetailActivity.
The sample code is as follows:
C-like:
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Huawei.Agconnect.Applinking;
namespace AppLinking1
{
//[Activity(Label = "DetailActivity")]
[Activity(Name = "com.company.app.DetailActivity", Label = "DetailActivity", Theme = "@style/AppTheme")]
public class DetailActivity : Activity
{
protected async override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.activity_detail);
// Create your app here.
try
{
//To receive links, initialize the AGConnectAppLinking instance.
AGConnectAppLinking appLinkInstance = AGConnectAppLinking.Instance;
//Call GetAppLinkingAsync() to check links of App Linking to be processed
ResolvedLinkData resolvedLinkData = await appLinkInstance.GetAppLinkingAsync(this);
String deepLink = null;
if (resolvedLinkData != null)
{
deepLink = resolvedLinkData.DeepLink.ToString();
FindViewById<TextView>(Resource.Id.deepLink).Text = deepLink;
}
}
catch (System.Exception ex)
{
FindViewById<TextView>(Resource.Id.message).Text = ex.Message;
}
}
}
}
Configure the layout for the page of receiving an App Linking link.
Right-click the project, choose add > New Item, select Android Layout, and name it activity_detail. The sample code is as follows:
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:layout_margin="16dp"
android:orientation="vertical"
tools:context=".DetailActivity">
<TextView
android:id="@+id/textDeepLink"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="DeepLink:"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/deepLink"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textMessage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="message:"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="80dp" />
</LinearLayout>
Configure the Manifest file. Find the Properties directory and open the AndroidManifest file in the directory. Configure the following content in the element.
XML:
<activity android:name="com.company.app.DetailActivity" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="open.androiddemoapp.com" android:scheme="https" />
<data android:host="open.androiddemoapp.com" android:scheme="http" />
</intent-filter>
<!--App Linking SDK reads content on the clipboard each time the app is launched.-->
<meta-data android:name="com.huawei.agconnect.applinking.READ_CLIPBOARD_PERMISSION" android:value="Available" />
</activity>
Testing Your App​Click Run to test your app.
References
Getting started with Xamarin
App Linking (Android)

Manage the Budget using Room Database in Money Management Android app (Kotlin) – Part 3

{
"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 manage your money using this Money Management app. User can add Income and Expenses in this app, so the data will be saved in room database, it can access in offline also. User can easily track their daily spending's and can take the preventive actions on the unnecessary expenses, so that they can save money and can invest in profitable return ways. In this app, user can add, update, delete and fetch operations.
So, I will provide the series of articles on this Money Management App, in upcoming articles I will integrate other Huawei Kits.
If you are new to this application, follow my previous articles.
Beginner: Find the introduction Sliders and Huawei Account Kit Integration in Money Management Android app (Kotlin) - Part 1
Beginner: Integration of Huawei Ads Kit and Analytics Kit in Money Management Android app (Kotlin) – Part 2
Components of Room DB
1. Entity
2. Dao
3. Database
1. Entity
Represents a table within the database. Room creates a table for each class that has @entity annotation, the fields in the class correspond to columns in the table. Therefore, the entity classes tend to be small model classes that does not contain any logic.
2. Dao
DAOs(Data Access Objects) are responsible for defining the methods that access the database. In the initial SQLite, we use the Cursor objects. With Room, we do not need all the Cursor related code and can simply define our queries using annotations in the Dao class.
3. Database
Contains the database holder and serves as the main access point for the underlying connection to your app's persisted, relational data.
To create a database, we need to define an abstract class that extends RoomDatabase. This class is annotated with @database, lists the entities contained in the database, and the DAOs which access them.
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. 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'
9. Add the below plugin and dependencies in build.gradle(Module) file.
Java:
apply plugin: id 'com.huawei.agconnect'
apply plugin: id 'kotlin-kapt'
// Huawei AGC
implementation 'com.huawei.agconnect:agconnect-core:1.6.0.300'
// Room Database
implementation "androidx.room:room-runtime:2.4.2"
kapt "androidx.room:room-compiler:2.4.2"
implementation "androidx.room:room-ktx:2.4.2"
androidTestImplementation "androidx.room:room-testing:2.4.2"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1"
// Recyclerview
implementation 'androidx.recyclerview:recyclerview:1.2.1'
10. Now Sync the gradle.
Let us move to development
I have created a project on Android studio with empty activity let us start coding.
Create a Transaction.kt class annotated with @entity to create a table for each class.
Java:
@Entity(tableName = "transactions")
data class Transaction(
@PrimaryKey(autoGenerate = true)
val id: Int,
val label: String,
val amount: Double,
val description: String): Serializable{}
Create a TransactionDao o.kt interface class annotated with @dao and responsible for defining the methods that access the database.
Java:
@Dao
interface TransactionDao {
@Query("SELECT * from transactions")
fun getAll(): List<Transaction>
@Insert
fun insertAll(vararg transaction: Transaction)
@Delete
fun delete(vararg transaction: Transaction)
@Update
fun update(vararg transaction: Transaction)
}
Create a AppDatabase.kt abstract class that extends RoomDatabase annotated with @database to lists the entities contained in the database, and the DAOs which access them.
Java:
@Database(entities = [Transaction::class], version = 2)
abstract class AppDatabase : RoomDatabase() {
abstract fun transactionDao(): TransactionDao
}
In the TransactionActivity.kt activity to find the business logic for entire dashboard.
Java:
class TransactionActivity : AppCompatActivity() {
private lateinit var deletedTransaction: Transaction
private lateinit var oldtransactions: List<Transaction>
private lateinit var transactions: List<Transaction>
private lateinit var transactionAdapter: TransactionAdapter
private lateinit var linearLayoutManager: LinearLayoutManager
private lateinit var db: AppDatabase
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_transcation)
transactions = arrayListOf()
transactionAdapter = TransactionAdapter(transactions)
linearLayoutManager = LinearLayoutManager(this)
trans_recycler_view.apply {
adapter = transactionAdapter
layoutManager = linearLayoutManager
}
// Swipe to remove
val itemTouchHelper = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT){
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
deleteTransaction(transactions[viewHolder.adapterPosition])
}
}
val swipeHelper = ItemTouchHelper(itemTouchHelper)
swipeHelper.attachToRecyclerView(trans_recycler_view)
btn_float.setOnClickListener {
val intent = Intent(this, AddTransactionActivity::class.java)
startActivity(intent)
}
// Room database
db = Room.databaseBuilder(this,AppDatabase::class.java,"transactions").build()
}
@SuppressLint("SetTextI18n")
private fun updateAmount(){
val totalAmount: Double = transactions.map {it.amount}.sum()
val budgetAmount: Double = transactions.filter {it.amount > 0}.map {it.amount}.sum()
val expenseAmount: Double = totalAmount - budgetAmount
balance.text = "RS %.2f".format(totalAmount)
budget.text = "RS %.2f".format(budgetAmount)
expense.text = "RS %.2f".format(expenseAmount)
}
// Fetch Transactions form Room Database
private fun fetchAll(){
GlobalScope.launch {
transactions = db.transactionDao().getAll()
runOnUiThread {
updateAmount()
transactionAdapter.setData(transactions)
}
}
}
private fun deleteTransaction(transaction: Transaction){
deletedTransaction = transaction
oldtransactions = transactions
GlobalScope.launch {
db.transactionDao().delete(transaction)
transactions = transactions.filter {it.id != transaction.id}
runOnUiThread {
updateAmount()
transactionAdapter.setData(transactions)
}
}
Toast.makeText(this, "Item Deleted", Toast.LENGTH_SHORT).show()
}
override fun onResume() {
super.onResume()
fetchAll()
}
}
Create a TransactionAdapter.kt adapter class to hold the list.
Java:
class TransactionAdapter(private var transactions: List<Transaction>):
RecyclerView.Adapter<TransactionAdapter.TransactionViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TransactionViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.transcation_list, parent, false)
return TransactionViewHolder(itemView)
}
override fun onBindViewHolder(holder: TransactionViewHolder, position: Int) {
val transaction: Transaction = transactions[position]
val context: Context = holder.amount.context
if(transaction.amount >= 0){
holder.amount.text = " RS %.2f".format(transaction.amount)
holder.amount.setTextColor(ContextCompat.getColor(context,R.color.Green))
} else {
holder.amount.text = " RS %.2f".format(transaction.amount)
holder.amount.setTextColor(ContextCompat.getColor(context,R.color.Red))
}
holder.label.text = transaction.label
holder.itemView.setOnClickListener {
val intent = Intent(context, DetailedActivity::class.java)
intent.putExtra("transaction", transaction)
context.startActivity(intent)
}
}
override fun getItemCount(): Int {
return transactions.size
}
inner class TransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val label: TextView = itemView.findViewById(R.id.txt_label)
val amount: TextView = itemView.findViewById(R.id.txt_amount)
}
fun setData(transactions: List<Transaction>){
this.transactions = transactions
notifyDataSetChanged()
}
}
In the AddTransactionActivity.kt activity to find the business logic to add items.
Java:
class AddTransactionActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_add_transaction)
btn_add.setOnClickListener {
val label = edt_label.text.toString()
val amount = edt_amount.text.toString().toDoubleOrNull()
val description = edt_desc.text.toString()
if(label.isBlank()) {
Toast.makeText(this, "Enter the label", Toast.LENGTH_SHORT).show()
}
else if(amount == null) {
Toast.makeText(this, "Enter the valid amount", Toast.LENGTH_SHORT).show()
}
else {
val transaction = Transaction(0, label, amount, description)
insert(transaction)
Toast.makeText(this, "Saved Content", Toast.LENGTH_SHORT).show()
}
}
}
private fun insert(transaction: Transaction) {
val db: AppDatabase = Room.databaseBuilder(this,AppDatabase::class.java,"transactions").build()
GlobalScope.launch {
db.transactionDao().insertAll(transaction)
finish()
}
}
}
In the DetailedActivity.kt activity to find the business logic for updating the items.
Java:
class DetailedActivity : AppCompatActivity() {
private lateinit var transaction: Transaction
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_detailed)
transaction = intent.getSerializableExtra("transaction") as Transaction
update_label.setText(transaction.label)
update_amount.setText(transaction.amount.toString())
btn_update.setOnClickListener {
val label = update_label.text.toString()
val amount = update_amount.text.toString().toDoubleOrNull()
val description = update_desc.text.toString()
if(label.isBlank()) {
Toast.makeText(this, "Enter the label", Toast.LENGTH_SHORT).show()
}
else if(amount == null) {
Toast.makeText(this, "Enter the valid amount", Toast.LENGTH_SHORT).show()
}
else {
val transaction = Transaction(transaction.id, label, amount, description)
update(transaction)
Toast.makeText(this, "Saved Content", Toast.LENGTH_SHORT).show()
}
}
}
private fun update(transaction: Transaction) {
val db: AppDatabase = Room.databaseBuilder(this,AppDatabase::class.java,"transactions").build()
GlobalScope.launch {
db.transactionDao().update(transaction)
finish()
}
}
}
In the activity_transcation.xml we can create the UI screen for Dashboard.
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"
tools:context=".room.TransactionActivity">
<LinearLayout
android:id="@+id/balance_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginStart="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Total Balance:"
android:textAllCaps="false"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/balance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="RS.xx"
android:textColor="@color/black"
android:textSize="20sp"
android:textStyle="bold" />
</LinearLayout>
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
app:cardCornerRadius="12dp"
android:layout_below="@+id/balance_layout">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="0.5"
android:layout_gravity="center">
<TextView
android:id="@+id/budget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="RS.xx"
android:textAllCaps="false"
android:textSize="24sp"
android:textColor="@color/Green"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Budget "
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="center"
android:layout_weight="0.5">
<TextView
android:id="@+id/expense"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="RS.xx"
android:textColor="@color/Red"
android:textAllCaps="false"
android:textSize="24sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Expense "
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Transcations"
android:textAllCaps="false"
android:textSize="18sp"
android:layout_marginTop="14dp"
android:layout_marginStart="10dp"
android:layout_below="@+id/cardview"
android:textStyle="bold" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/trans_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/title"
android:layout_marginTop="10dp"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/btn_float"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="10dp"
android:backgroundTint="@color/Red"
android:clickable="true"
android:contentDescription="TODO"
app:borderWidth="0dp"
app:srcCompat="@android:drawable/ic_input_add" />
</RelativeLayout>
In the activity_add_transaction.xml we can create the UI screen for adding items.
XML:
<?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=".room.AddTransactionActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<EditText
android:id="@+id/edt_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:hint="Label "
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/edt_amount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Amount: "
android:inputType="numberSigned"
app:layout_constraintTop_toBottomOf="@id/edt_label" />
<EditText
android:id="@+id/edt_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Description: "
app:layout_constraintTop_toBottomOf="@id/edt_amount" />
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:textSize="18sp"
android:layout_gravity="center"
android:text="Add"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/edt_desc" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
In the activity_detailed.xml we can create the UI screen for updating items.
XML:
<?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=".room.DetailedActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<EditText
android:id="@+id/update_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:hint="Label "
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/update_amount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Amount: "
android:inputType="numberSigned"
app:layout_constraintTop_toBottomOf="@id/edt_label" />
<EditText
android:id="@+id/update_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Description: "
app:layout_constraintTop_toBottomOf="@id/edt_amount" />
<Button
android:id="@+id/btn_update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:textSize="18sp"
android:layout_gravity="center"
android:text="Update"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/edt_desc" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
In the transcation_list.xml we can create the UI screen for customized items.
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="40dp"
android:layout_gravity="center_vertical">
<TextView
android:id="@+id/txt_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Food"
android:textAllCaps="false"
android:layout_marginStart="6dp"
android:textSize="20sp"
android:layout_weight="1"/>
<TextView
android:id="@+id/txt_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="RS.12"
android:layout_marginEnd="12dp"
android:textSize="20sp"/>
</LinearLayout>
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 the integration of Room database.
We, have learnt about the room database and its components such as DAO, Entity and Database. How to create, read, update and delete the content in room database and which helps the user to access the data when they are in offline.
I hope you have read this article. If you found it is helpful, please provide likes and comments.
Reference
Room Database
Find the Original document - https://forums.developer.huawei.com/forumPortal/en/topic/0202860048259200218?fid=0101187876626530001

Check the similar words using Text Embedding feature by Huawei ML Kit in Android (Kotlin)

{
"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 check similar words and sentences using Text Embedding feature of Huawei ML Kit. This Huawei ML Kit provides Text Embedding feature which helps to get matching vector value of words or sentences. Using this feature, we can improve our research based on the result. It provides similarity between two words or sentences and similar words of a particular word searched. We can also improve searching and browsing efficiency using after getting results related to search text.
Use Cases
This service can be used in text search scenarios. A user can enter a keyword in your news app to return hot news related to the word, improving the search and browsing efficiency.
Precautions
Text embedding depends on the on-cloud API for recognition. During commissioning and usage, ensure that the device can access the Internet.
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 21 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 ML 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.4.1.300'
10. Add the below plugin and dependencies in build.gradle(Module) file.
Java:
apply plugin: 'com.huawei.agconnect'
// Huawei AGC
implementation 'com.huawei.agconnect:agconnect-core:1.5.0.300'
// ML Kit Text Embedding
implementation 'com.huawei.hms:ml-nlp-textembedding:2.0.4.300'
11. Now Sync the gradle.
12. Add the required permission to the AndroidManifest.xml file.
Java:
<uses-permission android:name="android.permission.INTERNET" />
<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 for buttons.
Java:
class MainActivity : AppCompatActivity() {
var wordSimilar: Button? = null
var sentenceSimilar:Button? = null
var similarWords:Button? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
MLApplication.getInstance().apiKey = getString(R.string.api_key)
wordSimilar = findViewById(R.id.word_similar)
sentenceSimilar = findViewById(R.id.sentence_similar)
similarWords = findViewById(R.id.similar_words)
wordSimilar!!.setOnClickListener(View.OnClickListener {
startActivity(Intent([email protected], WordSimilarActivity::class.java)) })
sentenceSimilar!!.setOnClickListener(View.OnClickListener {
startActivity(Intent([email protected], SentenceSimilarActivity::class.java)) })
similarWords!!.setOnClickListener(View.OnClickListener {
startActivity(Intent([email protected], SimilarWordsActivity::class.java)) })
}
}
In the WordSimilarActivity.kt we can find the business logic for similar words.
Java:
class WordSimilarActivity : AppCompatActivity() {
private var analyzer: MLTextEmbeddingAnalyzer? = null
private var checkWordSimilarity: Button? = null
var resultTextView: TextView? = null
var similarWord1: EditText? = null
var similarWord2:EditText? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_word_similar)
resultTextView = findViewById(R.id.similar_word_value)
checkWordSimilarity = findViewById(R.id.check_word_similarity)
similarWord1 = findViewById(R.id.similar_word1)
similarWord2 = findViewById(R.id.similar_word2)
checkWordSimilarity!!.setOnClickListener(View.OnClickListener { getWordSimillarityApi() })
analyzer = UtilForAnalyzer.getAnalyzer()
}
private fun getWordSimillarityApi() {
val wordsSimilarityTask = analyzer!!.analyseWordsSimilarity(
similarWord1!!.text.toString(), similarWord2!!.text.toString() )
wordsSimilarityTask.addOnSuccessListener { wordsSimilarity ->
resultTextView!!.text = "The similarity value is $wordsSimilarity"
}.addOnFailureListener { e -> onFailure(e) }
}
private fun onFailure(e: Exception?) {
if (e is MLTextEmbeddingException) {
val embeddingException = e
embeddingException.errCode
embeddingException.message
} else {
}
}
}
Create a class for analyzer UtilForAnalyzer.kt.
Java:
class UtilForAnalyzer {
companion object{
private var analyzer: MLTextEmbeddingAnalyzer? = null
var setting: MLTextEmbeddingSetting? = null
fun getAnalyzer(): MLTextEmbeddingAnalyzer? {
if (analyzer == null) {
setting = MLTextEmbeddingSetting.Factory()
.setLanguage(MLTextEmbeddingSetting.LANGUAGE_EN)
.create()
analyzer = MLTextEmbeddingAnalyzerFactory.getInstance().getMLTextEmbeddingAnalyzer(setting)
}
return analyzer
}
}
}
In the SentenceSimilarActivity.kt we can find the business logic for similar sentence.
Java:
class SentenceSimilarActivity : AppCompatActivity() {
private var analyzer: MLTextEmbeddingAnalyzer? = null
private var checkSentenceSimilarity: Button? = null
private var sentence_1: EditText? = null
private var sentence_2: EditText? = null
var resultTextView: TextView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sentence_similar)
sentence_1 = findViewById(R.id.sentence1)
sentence_2 = findViewById(R.id.sentence2)
resultTextView = findViewById(R.id.similar_word_value)
checkSentenceSimilarity = findViewById(R.id.check_sentence_similarity)
checkSentenceSimilarity!!.setOnClickListener(View.OnClickListener { getSentenceSimilarityApi() })
analyzer = UtilForAnalyzer.getAnalyzer()
}
private fun getSentenceSimilarityApi() {
val sentencesSimilarityTask = analyzer!!.analyseSentencesSimilarity(
sentence_1!!.text.toString(), sentence_2!!.text.toString()
)
sentencesSimilarityTask.addOnSuccessListener { sentencesSimilarity ->
resultTextView!!.text = "The similarity value is $sentencesSimilarity"
}.addOnFailureListener { e -> onFailure(e) }
}
private fun onFailure(e: Exception?) {
if (e is MLTextEmbeddingException) {
val embeddingException = e
embeddingException.errCode
embeddingException.message
} else {
}
}
}
In the SimilarWordsActivity.kt we can find the business logic for similar words count.
Java:
class SimilarWordsActivity : AppCompatActivity() {
private var findSimilarWords: Button? = null
private var word_1: EditText? = null
private var word_2:EditText? = null
private var analyzer: MLTextEmbeddingAnalyzer? = null
var resultTextView: TextView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_similar_words)
word_1 = findViewById(R.id.word1)
word_2 = findViewById(R.id.word2)
resultTextView = findViewById(R.id.similar_word_value)
findSimilarWords = findViewById(R.id.check_word_similarity)
findSimilarWords!!.setOnClickListener(View.OnClickListener { noOfSimilarWords() })
analyzer = UtilForAnalyzer.getAnalyzer()
}
private fun noOfSimilarWords() {
val multipleSimilarityWordsTask = analyzer!!.analyseSimilarWords(
word_1!!.text.toString(), word_2!!.text.toString().toInt() )
multipleSimilarityWordsTask.addOnSuccessListener { words ->
val stringBuilder = StringBuilder()
for (word in words) {
stringBuilder.append(word)
stringBuilder.append("\t")
}
resultTextView!!.text = stringBuilder.toString()
}.addOnFailureListener { e -> onFailure(e) }
}
private fun onFailure(e: Exception?) {
if (e is MLTextEmbeddingException) {
val embeddingException = e
embeddingException.errCode
embeddingException.message
} else {
}
}
}
In the activity_main.xml we can create the UI screen.
XML:
<?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">
<Button
android:id="@+id/word_similar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Check Word Similarity"
android:textAllCaps="false"
android:textSize="17sp"
app:layout_constraintBottom_toTopOf="@+id/sentence_similar"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/sentence_similar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Check Sentence Similarity"
android:textAllCaps="false"
android:textSize="17sp"
app:layout_constraintBottom_toTopOf="@+id/similar_words"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/word_similar" />
<Button
android:id="@+id/similar_words"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get Similar Words"
android:textAllCaps="false"
android:textSize="17sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/word_similar" />
</androidx.constraintlayout.widget.ConstraintLayout>
In the activity_word_similar.xml we can create the UI screen for sentences.
Java:
<?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=".WordSimilarActivity">
<EditText
android:id="@+id/similar_word1"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="17sp"
app:layout_constraintBottom_toTopOf="@+id/similar_word2"
android:background="@drawable/edittext_bg"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/similar_word2"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="17sp"
android:background="@drawable/edittext_bg"
app:layout_constraintBottom_toTopOf="@+id/similar_word_value"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/similar_word1" />
<TextView
android:id="@+id/similar_word_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/check_word_similarity"
android:textColor="@color/black"
android:textSize="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/similar_word2" />
<Button
android:id="@+id/check_word_similarity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Check word Similarity"
android:textAllCaps="false"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/similar_word_value" />
</androidx.constraintlayout.widget.ConstraintLayout>
In the activity_sentence_similar.xml we can create the UI screen for sentences.
XML:
<?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=".SentenceSimilarActivity">
<EditText
android:id="@+id/sentence1"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@drawable/edittext_bg"
app:layout_constraintBottom_toTopOf="@+id/sentence2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/sentence2"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@drawable/edittext_bg"
app:layout_constraintBottom_toTopOf="@+id/similar_word_value"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/sentence1" />
<TextView
android:id="@+id/similar_word_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/check_sentence_similarity"
android:textColor="@color/purple_500"
android:textSize="20dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/sentence2" />
<Button
android:id="@+id/check_sentence_similarity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Check Sentence Similarity"
android:textSize="17sp"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/similar_word_value" />
</androidx.constraintlayout.widget.ConstraintLayout>
In the activity_similar_words.xml we can create the UI screen for words count.
XML:
<?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=".SimilarWordsActivity">
<EditText
android:id="@+id/word1"
android:gravity="center"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:textSize="17sp"
app:layout_constraintBottom_toTopOf="@+id/word2"
android:background="@drawable/edittext_bg"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/word2"
android:gravity="center"
android:layout_width="160dp"
android:layout_height="wrap_content"
android:hint="enter number"
android:textSize="17sp"
android:inputType="number"
android:background="@drawable/edittext_bg"
app:layout_constraintBottom_toTopOf="@+id/similar_word_value"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/word1" />
<TextView
android:id="@+id/similar_word_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
app:layout_constraintBottom_toTopOf="@+id/check_word_similarity"
android:textColor="@color/black"
android:textSize="15dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/word2" />
<Button
android:id="@+id/check_word_similarity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Check Similar Words"
android:textSize="17sp"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/similar_word_value" />
</androidx.constraintlayout.widget.ConstraintLayout>
Demo
Tips and Tricks
1. Make sure you are already registered as Huawei developer.
2. Set minSDK version to 21 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 can learn how to check similar words and sentences using Text Embedding feature of Huawei ML Kit. This Huawei ML Kit provides Text Embedding feature which helps to get matching vector value of words or sentences. Using this feature, we can improve our research based on the result. It provides similarity between two words or sentences and similar words of a particular word searched. We can also improve searching and browsing efficiency using after getting results related to search text.
I hope you have read this article. If you found it is helpful, please provide likes and comments.
Reference
ML Kit – Text Embedding
ML Kit – Training Video

Categories

Resources