HTML5 Quick App Website Internationalization - Huawei Developers

Background
I needed to develop a function for dynamically loading HTML5 websites that matched the system language. The website internationalization in my project was implemented by dynamically loading URLs. For example, if the system language of a mobile phone is Japanese, the URLs of web pages in Japanese are loaded. For simplified Chinese, those in simplified Chinese are loaded, and for English, those in English are loaded, and so on. Here, I have listed the steps for your reference.
{
"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"
}
Solution
Step 1: Bind a variable.
Bind a variable to the src attribute of the web component, to ensure that the attribute will not have a fixed value. In the following code, loadUrl in {{}} is a bound variable. It is defined under script in the UX file. You can skip this step if your project was created using the HTML5 template in Huawei Quick App IDE, downloaded from https://developer.huawei.com/consumer/en/doc/development/quickApp-Guides/quickapp-installtool, because the variable will be bound by the template code.
JavaScript:
<!-- template -->
<web src="{{loadUrl}}"
</web>
<!-- script -->
export default {
data: {
loadUrl: "https://transit.navitime.com/en",
},
Step 2: Initialize the variable.
Use the onInit() method in the quick app’s lifecycle to call the device API to obtain the system language and load the HTML5 page in the obtained language.
JavaScript:
onInit: function () {
const device = require("@system.device")
const res = device.getInfoSync();
let local = res.language; //system language
let region = res.region; //system region
console.info('onInit :localole= ' + local + ", region=" + region);
if (local === 'zh') {
if (region === "CN") {
this.loadUrl = "https://transit.navitime.com/zh-cn/";
} else if (region === "TW") {
this.loadUrl = "https://transit.navitime.com/zh-tw/";
}
} else if (local === 'ja') {
this.loadUrl = "https://transit.navitime.com/ja/?from=huawei.quickapp";
} else {
// For other languages, the HTML5 page in the default language is used.
this.loadUrl = "https://transit.navitime.com/en";
}
},
Step 3: Add a listener for system language switch.
Perform this step if you want the language on the HTML5 page to change accordingly, as the user changes the system language when the HTML5 quick app is running. You can skip this step if you don’t need to implement this function. The user can simply exit the app and re-enter it.
The code for adding a listener to listen to the system language switch is as follows:
JavaScript:
onConfigurationChanged(object) {
console.log("onConfigurationChanged object=" + JSON.stringify(object));
if (object.type === "locale") {
const configuration=require("@system.configuration")
var localeObject = configuration.getLocale();
let local= localeObject.language;
let region= localeObject.countryOrRegion;
console.info(onConfigurationChanged(object :localole= ' + local + ", region=" + region);
if (local === 'zh') {
if (region === "CN") {
this.loadUrl = "https://transit.navitime.com/zh-cn/";
} else if (region === "TW") {
this.loadUrl = "https://transit.navitime.com/zh-tw/";
}
} else if (local === 'ja') {
this.loadUrl = "https://transit.navitime.com/ja/?from=huawei.quickapp";
} else {
// For other languages, the HTML5 page in the default language is used.
this.loadUrl = "https://transit.navitime.com/en";
}
}
},
Summary
I hope you’ll find this post helpful, when planning the global release of your HTML5 quick app. Feel free to leave a question or comment below, to share your own experiences.

It's an easy and useful code.

Rebis said:
It's an easy and useful code.
Click to expand...
Click to collapse
Thanks to your liking.

Related

Great way to test android apps[HMS and GMS], A/B Testing

More information about this, you can visit HUAWEI Developer Forum
​Introduction
This article will guide you to use A/B testing in android project. It will provide details to use HMS and GMS.
Steps
1. Create App in Android
2. Configure App in AGC
3. Integrate the SDK in our new Android project
4. Integrate the dependencies
5. Sync project
Procedure
Step1: Create application in android studio.
HMS related dependencies, Add below dependencies in app directory
Code:
implementation 'com.huawei.agconnect:agconnect-remoteconfig:1.3.1.300'
apply plugin:'com.huawei.agconnect'
Add below dependencies in root directory
Code:
maven { url 'http://developer.huawei.com/repo/' }
classpath 'com.huawei.agconnect:agcp:1.2.1.301'
GMS related dependencies, Add below dependencies in app directory
Code:
implementation 'com.google.android.gms:play-services-analytics:17.0.0'
implementation 'com.google.firebase:firebase-config:19.2.0'
Add below dependencies into root directory
Code:
classpath 'com.google.gms:google-services:4.3.3'
Step2: Create MobileCheckService class, using this class you can identify whether the device has HMS or GMS.
Code:
class MobileCheckService {
fun isGMSAvailable(context: Context?): Boolean {
if (null != context) {
val result: Int = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
if (com.google.android.gms.common.ConnectionResult.SUCCESS === result) {
return true
}
}
return false
}
fun isHMSAvailable(context: Context?): Boolean {
if (null != context) {
val result: Int = HuaweiApiAvailability.getInstance().isHuaweiMobileServicesAvailable(context)
if (com.huawei.hms.api.ConnectionResult.SUCCESS == result) {
return true
}
}
return false
}
}
Step3: Create instance for Mobilecheckservice inside activity class. Inside OnCreate() call checkAvailableMobileService().This method return whether the device has HMS or GMS.
Code:
private fun checkAvailableMobileService() {
if (mCheckService.isHMSAvailable(this)) {
Toast.makeText(baseContext, "HMS Mobile", Toast.LENGTH_LONG).show()
configHmsTest()
} else
if (mCheckService.isGMSAvailable(this)) {
Toast.makeText(baseContext, "GMS Mobile", Toast.LENGTH_LONG).show()
configGmsTest()
} else {
Toast.makeText(baseContext, "NO Service", Toast.LENGTH_LONG).show()
}
}
Step4: If the device support HMS, then use AGConnectConfig.
Code:
private fun configHmsTest() {
val config = AGConnectConfig.getInstance()
config.applyDefault(R.xml.remote_config_defaults)
config.clearAll()
config.fetch().addOnSuccessListener { configValues ->
config.apply(configValues)
config.mergedAll
var sampleTest = config.getValueAsString("Festive_coupon")
Toast.makeText(baseContext, sampleTest, Toast.LENGTH_LONG).show()
}.addOnFailureListener { Toast.makeText(baseContext, "Fetch Fail", Toast.LENGTH_LONG).show() }
}
Step5: If the device support GMS, then use FirebaseRemoteConfig.
Code:
private fun configGmsTest() {
val firebase = FirebaseRemoteConfig.getInstance();
val configSettings = FirebaseRemoteConfigSettings.Builder().build()
firebase.setConfigSettingsAsync(configSettings)
firebase.setDefaultsAsync(R.xml.remote_config_defaults)
firebase.fetch().addOnCompleteListener { configValues ->
if (configValues.isSuccessful) {
firebase.fetchAndActivate()
var name = firebase.getString("Festive_coupon")
Toast.makeText(baseContext, name, Toast.LENGTH_LONG).show()
} else {
Toast.makeText(baseContext, "Failed", Toast.LENGTH_LONG).show()
}
}
}
App Configuration in Firebase:
Note: A/B test is using HMS configuration, refer
https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201248355275100167&fid=0101187876626530001
Step1: To configure app into firebase Open firebase https://console.firebase.google.com/u/0/?pli=1
{
"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"
}
Step2: Click Add Project and add required information like App Name, package name, SHA-1.
Step3: After configuration is successful, then click A/B Testing in Grow menu.
To Start A/b testing experiment Click Create experiment button, It will show you list of supported experiments. Using Firebase you can do three experiments.
· Notifications
· Remote Config
· In-App Messaging
Notification: This experiment will use for sending messages to engage the right users at the right moment.
Remote Config: This experiment will use to change app-behavior dynamically and also using server-side configuration parameters.
In-App Messaging: This experiment will use to send different In-App Messages.
Step4: Choose AbTesting > Remote Config > Create a Remote Config experiment, provide the required information to test, as follows
Step5: Choose AbTesting > Remote Config > App_Behaviour, following page will display.
Step6: Click Start experiment, then start A/B test based on the experiment conditions it will trigger
Step7: After successful completion of experiment, we can get report.
Conclusion:
Using A/B test, you can control the entire experiment from HMS or GMS dashboard, this form of testing will be highly effective for the developers.
Reference:
To know more about firebase console, follow the URL https://firebase.google.com/docs/ab-testing
Share your thoughts on this article, if you are already worked with A/B tests, then you can share your experience on separation between them with us

Integrate [Site kit + Map Kit] to Double Users' Convenience

More information like this, you can visit HUAWEI Developer Forum​
Introduction
Customers of Huawei maps are people who use maps API like Ecommerce, real estate portals, travel portals etc. and end users who use the Huawei maps application through different devices. End users also experience the maps interface through different search experiences like the local business searches, hotel searches, flight searches.
Let’s Start how to Integrate Map:
Step1: create a new project in Android studio.
Step 2: Configure your app into AGC.
Step 3: Enable required Api & add SHA-256.
Step 4: Download the agconnect-services.json from AGC. Paste into app directory.
Step 5: Add the below dependency in app.gradle file.
Code:
implementation 'com.huawei.hms:maps:4.0.0.301'
implementation 'com.huawei.hms:site:4.0.3.300'
Step 6: Add the below dependency in root.gradle file
Code:
maven { url 'http://developer.huawei.com/repo/' }
Step 7: Add appId & permissions in AndoridManifest.xml file
Code:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="appid=*********" />
Step 8: Sync your Project
Use Cases:
Huawei site kit supports below capabilities.
· Keyword Search: It will display list based on user input.
· Nearby Place Search: It will display nearby places based on the current location of the user's device.
· Place Detail Search: Searches for details about a place.
· Place Search Suggestion: Returns a list of suggested places.
Let’s Discuss how to integrate Site Kit:
Declare SearchService create Instance for SearchService.
Code:
SearchService searchService = SearchServiceFactory.create(this,URLEncoder.encode("API_KEY", "utf-8"));
Create TextSearchRequest, which is the place to search request. below are the parameters.
query: search keyword.
location: longitude and latitude to which search results need to be biased.
radius: search radius, in meters. The value ranges from 1 to 50000. The default value is 50000.
poiType: POI type. The value range is the same as that of LocationType.
HwPoiType: Huawei POI type. his parameter is recommended. The value range is the same as that of HwLocationType.
countrycode: code of the country where places are searched. The country code must comply with the ISO 3166-1 alpha-2 standard.
language: language in which search results are displayed. For details about the value range, please refer to language codes in LanguageMapping
If this parameter is not passed, the language of the query field is used in priority. If the field language is unavailable, the local language will be used.
pageSize: number of records on each page. The value ranges from 1 to 20. The default value is 20.
pageIndex: current page number. The value ranges from 1 to 60. The default value is 1.
Code:
autoCompleteTextView.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (timer != null) {
timer.cancel();
}
}
@Override
public void afterTextChanged(final Editable text) {
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
if (text.length() > 3) {
list.clear();
final TextSearchRequest textSearchRequest = new TextSearchRequest();
textSearchRequest.setQuery(text.toString());
searchService.textSearch(textSearchRequest, new SearchResultListener<TextSearchResponse>() {
@Override
public void onSearchResult(TextSearchResponse response) {
for (Site site : response.getSites()) {
LatLng latLng = new LatLng(site.getLocation().getLat(), site.getLocation().getLng());
SearchResult searchResult = new SearchResult(latLng, site.getAddress().getLocality(), site.getName());
String result = site.getName() + "," + site.getAddress().getSubAdminArea() + "\n" +
site.getAddress().getAdminArea() + "," +
site.getAddress().getLocality() + "\n" +
site.getAddress().getCountry() + "\n" +
site.getAddress().getPostalCode() + "\n";
list.add(result);
searchList.add(searchResult);
}
mAutoCompleteAdapter.clear();
mAutoCompleteAdapter.addAll(list);
mAutoCompleteAdapter.notifyDataSetChanged();
autoCompleteTextView.setAdapter(mAutoCompleteAdapter);
Toast.makeText(MainActivity.this, String.valueOf(response.getTotalCount()), Toast.LENGTH_SHORT).show();
}
@Override
public void onSearchError(SearchStatus searchStatus) {
Toast.makeText(MainActivity.this, searchStatus.getErrorCode(), Toast.LENGTH_SHORT).show();
}
});
}
}
}, 200);
autoCompleteTextView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mAutoCompleteAdapter.getItem(position);
selectedPostion = searchList.get(position);
try {
createMarker(new LatLng(selectedPostion.latLng.latitude, selectedPostion.latLng.longitude));
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
});
Output:
{
"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"
}
Reference:
https://developer.huawei.com/consumer/en/doc/development/HMS-References/hms-map-cameraupdate
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/android-sdk-introduction-0000001050158571

How to quickly add Sign In with Email to your Android App

Certain kind of apps require user registration to provide relevant information or save user's generated content/preferences in a server. If you are building an app with this feature, you may be interested in Huawei Auth Service to quickly develop your Log In screen with support of the most popular Third-party accounts. I've talked about how to set up the Auth Service in a previous post, so now will show you how to add the Sign In with Email to your Huawei Auth Service implementation.
Previous requirements
A developer account
An app project on AGC with Auth Service integrated
Note: Auth service requires a Data Storage Location, be careful when selecting this, because your app will be only available to certain countries per location.
Enabling the service
You must enable the account types to be supported by Auth Service one by one. Enable the Email support by going to AGC > My projects > "Your Project" > Auth Service.
{
"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"
}
Auth Service configurtion panel
Layout
Add a button and an EditText to your Login screen to get the user's email.
Layout editor
Adding the logic
Add the onClickListener to your login button
Code:
mailBtn.setOnClickListener(this)
override fun onClick(v: View?) {
loadingDialog.show()
when (v?.id) {
R.id.hw -> signInWithHWID()
R.id.google_sign_in_button -> signInWithGoogle()
R.id.anon -> signInAnonymously()
R.id.mailBtn -> signInWithMail()
}
}
I suggest you using a regular expression to check if the given email has a proper format. If everything is ok, you can send a verification code to the email address
Code:
private fun signInWithMail() {
val input = mail.text.toString()
val regex = Regex("^[\\w-\\.][email protected]([\\w-]+\\.)+[\\w-]{2,4}\$")
if (!regex.matches(input)) {
Snackbar.make(mailBtn, "Please use a valid email", Snackbar.LENGTH_SHORT).show()
return
}
val settings = VerifyCodeSettings.newBuilder()
.action(ACTION_REGISTER_LOGIN) //ACTION_REGISTER_LOGIN/ACTION_RESET_PASSWORD
.sendInterval(30) // Minimum sending interval, ranging from 30s to 120s.
.build()
val task: Task<VerifyCodeResult> = EmailAuthProvider.requestVerifyCode(
input,
settings
)
task.addOnSuccessListener {
//The verification code application is successful.
Snackbar.make(
mailBtn,
"Verification code sent to your mailbox",
Snackbar.LENGTH_SHORT
).show()
Log.e("EmailAuth", "success")
//Display dialog
val dialog = VerifyDialog(this, input)
dialog.listener = this
dialog.show()
}
.addOnFailureListener {
Log.e("EmailAuth", it.toString())
}
}
In my case, I've chosen to show a dialog, waiting for the verification code.
Dialog layout
Then the dialog will report the given code and password to the Fragment / Activity
Code:
class VerifyDialog(val context: Context,val email: String):DialogInterface.OnClickListener{
lateinit var view:View
var listener:VerificationListener?=null
var alertDialog: AlertDialog
init{
val inflater=LayoutInflater.from(context)
view=inflater.inflate(R.layout.dialog_verify,null)
val builder=AlertDialog.Builder(context)
builder.setTitle("Email Verification")
.setView(view)
.setPositiveButton("ok",this)
.setNegativeButton("Cancel",this)
.setCancelable(false)
alertDialog=builder.create()
}
public fun show(){
alertDialog.show()
}
override fun onClick(dialog: DialogInterface?, which: Int) {
when(which){
DialogInterface.BUTTON_POSITIVE ->{
val code=view.inputCode.text.toString()
if(code==""){
Snackbar.make(view,"Please input the code",Snackbar.LENGTH_SHORT).show()
return
}
val pass=view.inputPass.text.toString()
val vPass=view.confirmPass.text.toString()
if(pass.isEmpty()||pass!=vPass){
Snackbar.make(view,"Passwords doesn't match",Snackbar.LENGTH_SHORT).show()
return
}
listener?.onVerification(code,email,pass)
}
DialogInterface.BUTTON_NEGATIVE ->{
dialog?.dismiss()
listener?.onCancel()
}
}
}
public interface VerificationListener{
fun onVerification(code:String,email:String,password:String)
fun onCancel()
}
}
Report the code and password to AGC, so the user can use the password to sign in the next time.
Note: Setting the password is not mandatory.
Code:
override fun onVerification(code: String, email: String, password: String) {
val emailUser = EmailUser.Builder()
.setEmail(email)
.setVerifyCode(code)
.setPassword(password) // Optional. If this parameter is set, the current user has created a password and can use the password to sign in.
// If this parameter is not set, the user can only sign in using a verification code.
.build()
AGConnectAuth.getInstance().createUser(emailUser)
.addOnSuccessListener {
// After an account is created, the user is signed in by default.
startNavDrawer(it.user)
}
.addOnFailureListener {
Log.e("AuthSevice","Email Sign In failed $it")
}
}
Conclusion
Now your users can Sign In with their email adress. You can check the full example here: DummyApp
Reference
Official document:https://developer.huawei.com/consum...-connect-Guides/agc-auth-service-introduction
Hi am trying to implement email login but am getting email null do we need to anything.
Hi Is there any ways to use Huawei Auth Service as one like firebase UI ?

How to add or delete record to/from table in Huawei Cloud DB ?

Hello everyone, in this story, I will try to show you basic usage of HMS Cloud Db executeUpsert() and executeDelete() functions.
First, please be sure that having a project on cloud db up and running. If it is your first Cloud Db project and don’t know what to do, feel free to visit here.
For our scenario, we will have two tables named BookmarkStatus and LikeStatus. BookmarkStatus and LikeStatus tables holds a record for each user’s bookmark/like for the specified object and deletes the record when user remove his/her like or bookmark.
Let’s start with initializing our cloud db object. I will initialize cloud db object once when application started (in SplashScreen) and use it through the application.
Note : Make sure you have initialized your cloud db object before any of your cloud db operations.
Click to expand...
Click to collapse
Code:
companion object {
fun initDb() {
AGConnectCloudDB.initialize(ContextProvider.getApplicationContext())
}
}
fun dbGetInstance(){
mCloudDb = AGConnectCloudDB.getInstance()
}
Then, create a base viewModel to call certain functions of cloud db instead of calling them in every viewModel.
Code:
open class BaseViewModel : ViewModel() {
var mCloudDbZoneWrapper: CloudDbRepository =
CloudDbRepository()
init {
mCloudDbZoneWrapper.createObjectType()
mCloudDbZoneWrapper.openCloudDbZone()
}
}
Here is what createObjectType() and openCloudDbZone() functions do.
Code:
/*
Create object type
*/
fun createObjectType() {
dbGetInstance()
try {
mCloudDb!!.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo())
} catch (exception: AGConnectCloudDBException) {
Log.w("CloudDbRepository", exception.errMsg)
}
}
/*
Following method opens cloud db zone with given configs.
*/
fun openCloudDbZone() {
val mConfig: CloudDBZoneConfig = CloudDBZoneConfig(
"YOUR_CLOUD_DB_NAME", CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE,
CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC
)
mConfig.persistenceEnabled = true
try {
mCloudDbZone = mCloudDb!!.openCloudDBZone(mConfig, true)
} catch (exception: AGConnectCloudDBException) {
Log.w("CloudDbRepository", exception.errMsg)
}
}
Now we have all settings done. All we need to do is calling executeUpsert() and executeDelete() functions properly in related repositories.
Note: Please make sure that all needed permissions are granted to add or delete to/from table.
Click to expand...
Click to collapse
Code:
private fun bookmarkResult(
snapshot: CloudDBZoneSnapshot<BookmarkStatus>,
bookmark: BookmarkStatus,
triggered: Boolean
) {
val bookmarkStatsCursor: CloudDBZoneObjectList<BookmarkStatus> = snapshot.snapshotObjects
try {
if (bookmarkStatsCursor.hasNext()) {
val bookmarkStats = bookmarkStatsCursor.next()
if (bookmarkStats != null && bookmarkStats.object != null) {
if (triggered) {
//deleteBookmark
val deleteTask = mCloudDBZone.executeDelete(bookmarkStats)
deleteTask.addOnSuccessListener {
Log.w(TAG, "BookmarkDelete success")
bookmarkStatus.postValue(false)
}.addOnFailureListener {
Log.w(TAG, "BookmarkDelete fail" + it.message)
}
} else {
bookmarkStatus.postValue(true)
}
}
} else {
if (triggered) {
//add bookmark
val upsertTask = mCloudDBZone.executeUpsert(bookmark)
upsertTask.addOnSuccessListener {
Log.w(TAG, "BookmarkAdd success")
bookmarkStatus.postValue(true)
}.addOnFailureListener {
Log.w(TAG, "BookmarkDelete fail" + it.message)
}
} else {
bookmarkStatus.postValue(false)
}
}
} catch (exception: Exception) {
}
snapshot.release()
}
In this function, triggered parameter is for if user clicked bookmark button or not if clicked then value is true.
Here is the logic;
If user bookmarked the given object (which is queried in another method and passed as a parameter to this method as snapshot) then bookmarkStatsCursor.hasNext() returns true and if not triggered , this means user bookmarked the object and is trying to display bookmark status and all we need to do is using postValue() of the observable property bookmarkStatus and pass the value as true. Let’s say user has a record on BookmarkStatus table and triggered is true then we can say user is trying to remove bookmark of the object. So we need to use executeDelete(bookmark) to delete bookmark from table. With the help of addOnSuccessListener we will post value as false which means user does not have a bookmark on the given object anymore.
If user does not have a bookmark in given object and triggered is false, this means user did not bookmark object and trying to display bookmark status. We will post value as false. If triggered is true then, user is trying to add bookmark to that object. In this situation, we will add a record to the bookmark table using executeUpsert(bookmark) method.
{
"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"
}
Note that you can use addOnFailureListener to catch errors occurred during adding or deleting functions.
To add or delete records to/from LikeStatus table, you can use same logic with BookmarkStatus table given above.
So, as you can see, it is very simple to implement cloud db in your project and you can apply all CRUD functions simply as demonstrated above
References
https://developer.huawei.com/consum...llery-connect-Guides/agc-clouddb-introduction

Implementing SMS Verification with Huawei SMS Retriever

Hi everyone! Today I will briefly walkthrough you about how to implement an SMS Retriever system using Huawei’s SMSRetriever service.
{
"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"
}
First of all, let’s start with why do we need this service in our apps. Applications that involve user verification usually do this with an SMS code, and this SMS code is entered to a field in the app to verify user account. These sms codes are named as One-Time-Password, OTP for short. OTP’s can be used for verification of real user or increasing account security. Our purpose here is to retrieve this code and automatically enter it to the necessary field in our app. So let’s begin!
Our steps through the guide will be as:
Complete HMS Service implementation
1 — Require SMS read permission
2 — Initiate ReadSmsManager
3 — Register broadcast receiver for SMS
4 — Send SMS for user
5 — Register broadcast receiver for OTP — to extract code from SMS —
6 — Create SMSBroadcastReceiver class
1 — We begin by adding our required permission to the AndroidManifest.xml
XML:
<uses-permission android:name="android.permission.SEND_SMS" />
Note: Don’t forget to check if user has given permission.
Code:
val permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.SEND_SMS)
if (permissionCheck == PackageManager.PERMISSION_GRANTED)
// Send sms
else
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.SEND_SMS), SEND_SMS_REQUEST_CODE)
2 — Then we add the ReadSmsManager to initiate our SMS service.
Before ReadSmsManager code snippet, we have to add Huawei Account Kit implementation.
Code:
implementation 'com.huawei.hms:hwid:5.1.0.301'
After Gradle sync, we can add the SMS manager to our class.
Code:
val task = ReadSmsManager.startConsent([email protected], mobileNumber)
task.addOnCompleteListener {
if (task.isSuccessful) {
Toast.makeText(this, "Verification code sent successfully", Toast.LENGTH_LONG).show()
} else
Toast.makeText(this, "Task failed.", Toast.LENGTH_LONG).show()
}
3 — For SMS broadcast receiver, we need to add this little code block.
Code:
val intentFilter = IntentFilter(READ_SMS_BROADCAST_ACTION)
registerReceiver(SmsBroadcastReceiver(), intentFilter)
Note: After you add this code block, you will get an error saying SmsBroadcastReceiver cannot be found, because we didn’t define it yet. We are just getting our SmsActivity ready. We will be adding it once we are done here.
4 — After we register our receiver, we can send the SMS to our user.
Code:
val smsManager = SmsManager.getDefault()
smsManager.sendTextMessage(
mobileNumber,
null,
"Your verification code is $otp",
null,
null
)
Note: here otp will cause an error as it is not defined anywhere yet. You should implement a random OTP generator fitting your likings and assign the value to otp .
5 — Now that we sent an SMS to user, we should register the broadcast receiver to be able to retrieve the code from it.
Code:
val filter = IntentFilter()
filter.addAction("service.to.activity.transfer")
val otpReceiver = object : BroadcastReceiver() {
override fun onReceive(
context: Context,
intent: Intent
) {
intent.getStringExtra("sms")?.let { data ->
// You should find your otp code here in `data`
}
}
}
registerReceiver(otpReceiver, filter)
Note: Once we complete our classes, you should be setting your otp value to your view. This part is left out in the code snippet as view bindings and data bindings may vary on projects.
6 —Finally, where we get to read the messages and find our code.
Code:
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import com.huawei.hms.common.api.CommonStatusCodes
import com.huawei.hms.support.api.client.Status
import com.huawei.hms.support.sms.common.ReadSmsConstant
class SmsBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val bundle = intent!!.extras
if (bundle != null) {
val status: Status? = bundle.getParcelable(ReadSmsConstant.EXTRA_STATUS)
if (status?.statusCode == CommonStatusCodes.TIMEOUT) {
// Process system timeout
} else if (status?.statusCode == CommonStatusCodes.SUCCESS) {
if (bundle.containsKey(ReadSmsConstant.EXTRA_SMS_MESSAGE)) {
bundle.getString(ReadSmsConstant.EXTRA_SMS_MESSAGE)?.let {
val local = Intent()
local.action = "service.to.activity.transfer"
local.putExtra("sms", it)
context!!.sendBroadcast(local)
}
}
}
}
}
}
So that’s it. You should be able to successfully register for SMS sending and retrieving, then read OTP from content and use in whatever way you like.
Thanks for reading through the guide and I hope it is simple and useful for you. Let me know if you have any suggestions or problems.
References
https://developer.huawei.com/consum...upport-sms-readsmsmanager-0000001050050553-V5
https://developer.huawei.com/consum...Guides/authotize-to-read-sms-0000001061481826
https://medium.com/huawei-developers/android-integrating-your-apps-with-huawei-hms-core-1f1e2a090e98

Categories

Resources