HTML5 Quick App Internationalization
At present, more and more HTML5 apps are released globally on HUAWEI AppGallery as HTML5 quick apps. Apps need to be internationalized to open pages in languages set by users, and this improves user experience. For some websites, their languages are adapted based on dynamic URLs. In this way, you need to implement dynamic loading of URLs in different languages.
1. Bind a variable.
The value of the src attribute on the web component needs to be bound with a variable and cannot be fixed. The variable to be bound is loadUrl in {{}}, and the variable is defined under the script tag in the .ux file. If you create the project with the IDE H5 App template, you can ignore this step because this step has been completed based on IDE template code.
<!—template part->
<web src="{{loadUrl}}"
</web>
<!—script part -->
export default {
data: {
loadUrl: "https://transit.navitime.com/en",
},
2. Initialize the variable value.
In the onInit() method about the quick app's lifecycle, the system language is obtained through a device API, and the corresponding HTML5 URL is loaded after the language is determined.
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, use the HTML5 page of the default language.
this.loadUrl = "https://transit.navitime.com/en";
}
},
3. (Optional) Make quick app languages be updated with system settings.
It is applicable to the scenario where the HTML5 quick app has been started and is running. If the user changes the language in system settings at this time, you can use the settings here to update the language on HTML5 pages. You can also ignore this step, in this way, the user can exit the app and re-enter.
The quick app provides an API for monitoring language configuration changes during runtime. The code for adaptation is as follows:
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, use the HTML5 page of the default language.
this.loadUrl = "https://transit.navitime.com/en";
}
}
},
Thanks for this guide.
Freemind R said:
Thanks for this guide.
Click to expand...
Click to collapse
Thank you for your love and hope to get more attention from you.
Related
More information like this, you can visit HUAWEI Developer Forum
Original link: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0202330537081990041&fid=0101187876626530001
{
"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"
}
Article Introduction
In this article we are going to cover HUAWEI Map Kit JavaScript API introduction. Next we going to implementing HUAWEI Map in Ionic/Cordova project. Lastly we will implement HUAWEI Map Kit JavaScript into Native Application.
Technology Introduction
HUAWEI Map Kit provides JavaScript APIs for you to easily build map apps applicable to browsers.
It provides the basic map display, map interaction, route planning, place search, geocoding, and other functions to meet requirements of most developers.
Restriction
Before using the service, you need to apply for an API key on the HUAWEI Developers website. For details, please refer to "Creating an API Key" in API Console Operation Guide. To enhance the API key security, you are advised to restrict the API key. You can configure restrictions by app and API on the API key editing page.
Generating API Key
Go to HMS API Services > Credentials and click Create credential.
Click API key to generate new API Key.
In the dialog box that is displayed, click Restrict to set restrictions on the key to prevent unauthorized use or quota theft. This step is optional.
The restrictions include App restrictions and API restriction.
App restrictions: control which websites or apps can use your key. Set up to one app restriction per key.
API restrictions: specify the enabled APIs that this key can call.
After setup App restriction and API restriction API key will generate.
The API key is successfully created. Copy API Key to use in your project.
Huawei Web Map API introduction
1. Make a Basic Map
Code:
function loadMapScript() {
const apiKey = encodeURIComponent(
"API_KEY"
);
const src = `https://mapapi.cloud.huawei.com/mapjs/v1/api/js?callback=initMap&key=${apiKey}`;
const mapScript = document.createElement("script");
mapScript.setAttribute("src", src);
document.head.appendChild(mapScript);
}
function initMap() { }
function initMap() {
const mapOptions = {};
mapOptions.center = { lat: 48.856613, lng: 2.352222 };
mapOptions.zoom = 8;
mapOptions.language = "ENG";
const map = new HWMapJsSDK.HWMap(
document.getElementById("map"),
mapOptions
);
}
loadMapScript();
Note: Please update API_KEY with the key which you have generated. In script url we are declaring callback function, which will automatically initiate once Huawei Map Api loaded successfully.
2. Map Interactions
Map Controls
Code:
var mapOptions = {};
mapOptions.center = {lat: 48.856613, lng: 2.352222};
mapOptions.zoom = 10;
scaleControl
mapOptions.scaleControl = true; // Set to display the scale.
mapOptions.scaleControlOptions = {
units: "imperial" // Set the scale unit to inch.
};
zoomSlider
Code:
mapOptions.zoomSlider = true ; // Set to display the zoom slider.
zoomControl
Code:
mapOptions.zoomControl = false; // Set not to display the zoom button.
rotateControl (Manage Compass)
Code:
mapOptions.rotateControl = true; // Set to display the compass.
navigationControl
Code:
mapOptions.navigationControl = true; // Set to display the pan button.
copyrightControl
Code:
mapOptions.copyrightControl = true; // Set to display the copyright information.
mapOptions.copyrightControlOptions = {value: "HUAWEI",} // Set the copyright information.
locationControl
Code:
mapOptions.locationControl= true; // Set to display the current location.
Camera
Map moving: You can call the map.panTo(latLng)
Map shift: You can call the map.panBy(x, y)
Zoom: You can use the map.setZoom(zoom) method to set the zoom level of a map.
Area control: You can use map.fitBounds(bounds) to set the map display scope.
Map Events
Map click event:
Code:
map.on('click', () => {
map.zoomIn();
});
Map center change event:
Code:
map.onCenterChanged(centerChangePost);
function centerChangePost() {
var center = map.getCenter();
alert( 'Lng:'+map.getCenter().lng+'
'+'Lat:'+map.getCenter().lat);
}
Map heading change event:
Code:
map.onHeadingChanged(headingChangePost);
function headingChangePost() {
alert('Heading Changed!');
}
Map zoom level change event:
Code:
map.onZoomChanged(zoomChangePost);
function zoomChangePost() {
alert('Zoom Changed!')
}
3. Drawing on Map
Marker:
You can add markers to a map to identify locations such as stores and buildings, and provide additional information with information windows.
Code:
var map;
var mMarker;
function initMap() {
var mapOptions = {};
mapOptions.center = {lat: 48.856613, lng: 2.352222};
mapOptions.zoom = 8;
map = new HWMapJsSDK.HWMap(document.getElementById('map'), mapOptions);
mMarker = new HWMapJsSDK.HWMarker({
map: map,
position: {lat: 48.85, lng: 2.35},
zIndex: 10,
label: 'A',
icon: {
opacity: 0.5
}
});
}
Marker Result:
Marker Clustering:
The HMS Core Map SDK allows you to cluster markers to effectively manage them on the map at different zoom levels. When a user zooms in on the map to a high level, all markers are displayed on the map. When the user zooms out, the markers are clustered on the map for orderly display.
Code:
var map;
var markers = [];
var markerCluster;
var locations = [
{lat: 51.5145160, lng: -0.1270060},
{ lat : 51.5064490, lng : -0.1244260 },
{ lat : 51.5097080, lng : -0.1200450 },
{ lat : 51.5090680, lng : -0.1421420 },
{ lat : 51.4976080, lng : -0.1456320 },
···
{ lat : 51.5061590, lng : -0.140280 },
{ lat : 51.5047420, lng : -0.1470490 },
{ lat : 51.5126760, lng : -0.1189760 },
{ lat : 51.5108480, lng : -0.1208480 }
];
function initMap() {
var mapOptions = {};
mapOptions.center = {lat: 48.856613, lng: 2.352222};
mapOptions.zoom = 3;
map = new HWMapJsSDK.HWMap(document.getElementById('map'), mapOptions);
generateMarkers(locations);
markerCluster = new HWMapJsSDK.HWMarkerCluster(map, markers);
}
function generateMarkers(locations) {
for (let i = 0; i < locations.length; i++) {
var opts = {
position: locations[i]
};
markers.push(new HWMapJsSDK.HWMarker(opts));
}
}
Cluster markers Result:
Information Window:
The HMS Core Map SDK supports the display of information windows on the map. There are two types of information windows: One is to display text or image independently, and the other is to display text or image in a popup above a marker. The information window provides details about a marker.
Code:
var infoWindow;
function initMap() {
var mapOptions = {};
mapOptions.center = {lat: 48.856613, lng: 2.352222};
mapOptions.zoom = 8;
var map = new HWMapJsSDK.HWMap(document.getElementById('map'), mapOptions);
infoWindow = new HWMapJsSDK.HWInfoWindow({
map,
position: {lat: 48.856613, lng: 2.352222},
content: 'This is to show mouse event of another marker',
offset: [0, -40],
});
}
Info window Result:
Ground Overlay
The builder function of GroundOverlay uses the URL, LatLngBounds, and GroundOverlayOptions of an image as the parameters to display the image in a specified area on the map. The sample code is as follows:
Code:
var map;
var mGroundOverlay;
function initMap() {
var mapOptions = {};
mapOptions.center = {lat: 48.856613, lng: 2.352222};
mapOptions.zoom = 8;
map = new HWMapJsSDK.HWMap(document.getElementById('map'), mapOptions);
var imageBounds = {
north: 49,
south: 48.5,
east: 2.5,
west: 1.5,
};
mGroundOverlay = new HWMapJsSDK.HWGroundOverlay(
// Path to a local image or URL of an image.
'huawei_logo.png',
imageBounds,
{
map: map,
opacity: 1,
zIndex: 1
}
);
}
Marker Result:
Ionic / Cordova Map Implementation
In this part of article we are supposed to add Huawei Map Javascript API’s.
Update Index.html to implment Huawei Map JS scripts:
You need to update src/index.html and include Huawei map javacript cloud script url.
Code:
function loadMapScript() {
const apiKey = encodeURIComponent(
"API_KEY"
);
const src = `https://mapapi.cloud.huawei.com/mapjs/v1/api/js?callback=initMap&key=${apiKey}`;
const mapScript = document.createElement("script");
mapScript.setAttribute("src", src);
document.head.appendChild(mapScript);
}
function initMap() { }
loadMapScript();
Make new Map page:
Code:
ionic g page maps
Update maps.page.ts file and update typescript:
Code:
import { Component, OnInit, ChangeDetectorRef } from "@angular/core";
import { Observable } from "rxjs";
declare var HWMapJsSDK: any;
declare var cordova: any;
@Component({
selector: "app-maps",
templateUrl: "./maps.page.html",
styleUrls: ["./maps.page.scss"],
})
export class MapsPage implements OnInit {
map: any;
baseLat = 24.713552;
baseLng = 46.675297;
ngOnInit() {
this.showMap(his.baseLat, this.baseLng);
}
ionViewWillEnter() {
}
ionViewDidEnter() {
}
showMap(lat = this.baseLat, lng = this.baseLng) {
const mapOptions: any = {};
mapOptions.center = { lat: lat, lng: lng };
mapOptions.zoom = 10;
mapOptions.language = "ENG";
this.map = new HWMapJsSDK.HWMap(document.getElementById("map"), mapOptions);
this.map.setCenter({ lat: lat, lng: lng });
}
}
Ionic / Cordova App Result:
Native Application Huawei JS API Implementation
In this part of article we are supposed to add javascript based Huawei Map html version into our Native through webview. This part of implementation will be helpful for developer who required very minimal implementation of map.
Make assets/www/map.html file
Add the following HTML code inside map.html file:
Code:
var map;
var mMarker;
var infoWindow;
function initMap() {
const LatLng = { lat: 24.713552, lng: 46.675297 };
const mapOptions = {};
mapOptions.center = LatLng;
mapOptions.zoom = 10;
mapOptions.scaleControl = true;
mapOptions.locationControl= true;
mapOptions.language = "ENG";
map = new HWMapJsSDK.HWMap(
document.getElementById("map"),
mapOptions
);
map.setCenter(LatLng);
mMarker = new HWMapJsSDK.HWMarker({
map: map,
position: LatLng,
zIndex: 10,
label: 'A',
icon: {
opacity: 0.5
}
});
mMarker.addListener('click', () => {
infoWindow.open();
});
infoWindow = new HWMapJsSDK.HWInfoWindow({
map,
position: LatLng,
content: 'This is to info window of marker',
offset: [0, -40],
});
infoWindow.close();
}
Add the webview in your layout:
Code:
< WebView
android:id="@+id/webView_map"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Update your Activity class to call html file
Code:
class MainActivity : AppCompatActivity() {
lateinit var context: Context
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
context = this
val mWebview = findViewById(R.id.webView_map)
mWebview.webChromeClient = WebChromeClient()
mWebview.webViewClient = WebViewClient()
mWebview.settings.javaScriptEnabled = true
mWebview.settings.setAppCacheEnabled(true)
mWebview.settings.mediaPlaybackRequiresUserGesture = true
mWebview.settings.domStorageEnabled = true
mWebview.loadUrl("file:///android_asset/www/map.html")
}
}
Internet permission:
Don’t forget to add internet permissions in androidmanifest.xml file.
Code:
< 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" />
Native app Result:
References:
Huawei Map JavaScript API:
https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/javascript-api-introduction-0000001050164063
Complete Ionic JS Map Project:
https://github.com/salmanyaqoob/Ionic-All-HMS-Kits
Conclusion
Huawei Map JavaSript Api will be helpful for JavaScript developers to implement Huawei Map on cross platforms like “Cordova, Ionic, React-Native” and also helpful for the Native developers to implement under his projects. Developers can also able to implement Huawei Maps on websites.
Thank you very much, very helpful.
Introduction
This article is based on Huawei ML Kit to create a new sample application for Online Shopping Store to buy real products.
In this application, we can capture any kind of image for products to buy or check the price of a product using Machine Learning. It will give the other options so that you can improve your buying skills.
Huawei ML Kit allows your apps to easily leverage Huawei's long-term proven expertise in machine learning to support diverse artificial intelligence (AI) applications throughout a wide range of industries. ML Kit provides diversified leading machine learning capabilities that are easy to use and help you develop various AI apps.
Service Introduction
A user can take a photo of a product. Then the Product Visual Search service searches for the same or similar products in the pre-established product image library and returns the IDs of those products and related information. In addition, to better manage products in real-time, this service supports offline product import, online product addition, deletion, modification, query, and product distribution. For example, you can use this service to create shopping apps where users can quickly search for the things they want and compare products.
Prerequisite
1. A computer (desktop or laptop).
2. A Huawei phone used for running the app with HMS Core (APK) 3.0.0.300 or later.
3. A data cable used for connecting the computer to the Huawei phone.
4. Android Studio 3.0 or later.
5. Java SDK 1.7 or later.
6. HMS Core SDK 4.0.0.300 or later.
7. Must have Huawei Developer Account.
Things Need To Be Done
1. Create an app in AppGallery Connect and enable the service.
2. Create an Android Studio project.
3. Start development with kit integration inside the application.
4. Launch the application.
Create a project on AppGalleryConnect portal
1. Navigate to AppGalleryConnect, create a new project
2. Enter all details regarding your application, enable ML Kit API, after that download configuration JSON file, and then add into your android studio project.
Create a project in Android Studio
Navigate to android studio and create a new android project, provide all details of your project, and then add AGC and ML kit based dependencies.
1. Add the following AppGalleryConnect classpath.
Code:
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.1'
classpath 'com.huawei.agconnect:agcp:1.0.0.300'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
2. Add the following dependencies in app module based Gradle file, then sync your project.
Code:
implementation 'com.huawei.hms:ml-computer-vision-cloud:2.0.1.300'
Start development with kit integration inside the application
We have created the following package inside the project.
You need to initialize the ML kit in our application class.
Code:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
MLApplication.getInstance().setApiKey("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
}
}
We have implemented ML kit functionality in HomeActivity and BuyScanProductActivity
HomeActivity: I have implemented all basic functions such as initialize the Product Vision Search Service open camera, then create a bitmap followed by MLframe.
Code:
public class HomeActivity extends BaseActivity {
private static final String TAG = HomeActivity.class.getName();
private static final int CAMERA_PERMISSION_CODE = 100;
MLRemoteProductVisionSearchAnalyzer analyzer;
private ActivityHomeBinding homeBinding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
homeBinding = DataBindingUtil.setContentView(this, R.layout.activity_home);
init();
initializeProductVisionSearch();
}
private void init() {
setToolbar(homeBinding.tbWidget.findViewById(R.id.toolbar),
false, "My Online Store", homeBinding.tbWidget.findViewById(R.id.tv_toolbar_title));
homeBinding.btnBuyFromStore.setOnClickListener(v -> StoreActivity.start(this));
homeBinding.btnViewYourPurchases.setOnClickListener(v -> ViewPurchasesActivity.start(this));
homeBinding.btnBuyScanProduct.setOnClickListener(v->{
if (!(ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
== PackageManager.PERMISSION_GRANTED)) {
this.requestCameraPermission();
}
initializeProductVisionSearch();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 101);
});
}
private void requestCameraPermission() {
final String[] permissions = new String[] {Manifest.permission.CAMERA};
if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
ActivityCompat.requestPermissions(this, permissions, this.CAMERA_PERMISSION_CODE);
return;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 101) {
if (resultCode == RESULT_OK) {
Bitmap bitmap = (Bitmap) data.getExtras().get("data");
if (bitmap != null) {
MLFrame mlFrame = new MLFrame.Creator().setBitmap(bitmap).create();
mlImageDetection(mlFrame);
}
}
}
}
private void mlImageDetection(MLFrame mlFrame) {
Task<List<MLProductVisionSearch>> task = analyzer.asyncAnalyseFrame(mlFrame);
task.addOnSuccessListener(products -> {
Log.d(TAG, "success");
displaySuccess(products); })
.addOnFailureListener(e -> {
try {
MLException mlException = (MLException) e;
int errorCode = mlException.getErrCode();
String errorMessage = mlException.getMessage();
} catch (Exception error) {
// Handle the conversion error.
}
});
}
private void initializeProductVisionSearch() {
MLRemoteProductVisionSearchAnalyzerSetting settings = new MLRemoteProductVisionSearchAnalyzerSetting.Factory()
.setLargestNumOfReturns(16)
.setRegion(MLRemoteProductVisionSearchAnalyzerSetting.REGION_DR_CHINA)
.create();
analyzer
= MLAnalyzerFactory.getInstance().getRemoteProductVisionSearchAnalyzer(settings);
}
private void displaySuccess(List<MLProductVisionSearch> productVisionSearchList) {
List<MLVisionSearchProductImage> productImageList = new ArrayList<>();
String prodcutType = "";
for (MLProductVisionSearch productVisionSearch : productVisionSearchList) {
Log.d(TAG, "type: " + productVisionSearch.getType());
prodcutType = productVisionSearch.getType();
for (MLVisionSearchProduct product : productVisionSearch.getProductList()) {
productImageList.addAll(product.getImageList());
Log.d(TAG, "custom content: " + product.getCustomContent());
}
}
StringBuffer buffer = new StringBuffer();
for (MLVisionSearchProductImage productImage : productImageList) {
String str = "ProductID: " + productImage.getProductId() + "\nImageID: " + productImage.getImageId() + "\nPossibility: " + productImage.getPossibility();
buffer.append(str);
buffer.append("\n");
}
Log.d(TAG, "display success: " + buffer.toString());
BuyScanProductActivity.start(this,productImageList);
}
Product Visual Search
1. Create an analyzer for product visual search. You can create the analyzer using the MLRemoteProductVisionSearchAnalyzerSetting class.
Code:
MLRemoteProductVisionSearchAnalyzer analyzer
= MLAnalyzerFactory.getInstance().getRemoteProductVisionSearchAnalyzer();
2. Create an MLFrame object using android.graphics.Bitmap. JPG, JPEG, PNG, and BMP images are supported.
Code:
MLFrame mlFrame = new MLFrame.Creator().setBitmap(bitmap).create();
3. Implement image detection. For details about the result codes, refer to MLException.
Task<List<MLProductVisionSearch>> task = analyzer.asyncAnalyseFrame(mlFrame);
task.addOnSuccessListener(products -> {
Log.d(TAG, "success");
displaySuccess(products); })
.addOnFailureListener(e -> {
try {
MLException mlException = (MLException) e;
int errorCode = mlException.getErrCode();
String errorMessage = mlException.getMessage();
} catch (Exception error) {
// Handle the conversion error.
}
});<strong> </strong>
BuyScanProductActivity: We have displayed all the items in the recycler view list in which all products found by the result.
Code:
public class BuyScanProductActivity extends BaseActivity {
private static List<Item> items;
private ActivityStoreBinding storeBinding;
private StoreAdapter storeAdapter;
public static void start(@NonNull Context context, List<MLVisionSearchProductImage> products) {
if (context instanceof AppCompatActivity) {
Intent intent = new Intent(context, BuyScanProductActivity.class);
context.startActivity(intent);
startActivityAnimation(context);
items = new ArrayList<>();
for (MLVisionSearchProductImage product : products) {
Item item = new Item();
item.setFruitName(product.getProductId());
item.setImageUrl(product.getImageId());
item.setPrice(8500);
items.add(item);
}
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
storeBinding = DataBindingUtil.setContentView(this, R.layout.activity_store);
init();
}
private void init() {
setToolbar(storeBinding.tbWidget.findViewById(R.id.toolbar),
true,
getString(R.string.store),
storeBinding.tbWidget.findViewById(R.id.tv_toolbar_title));
storeAdapter = new StoreAdapter(this, items, item4 -> {
BillingPremiumDialog.show(this);
});
storeBinding.rvStore.setAdapter(storeAdapter);
}
}
Launch the application
If you have any doubts or queries. Leave your valuable comment in the comment section and do not forget to like and follow me.
At present, more and more HTML5 apps are released globally on HUAWEI AppGallery as HTML5 quick apps. Apps need to be internationalized to open pages in languages set by users, and this improves user experience. For some websites, their languages are adapted based on dynamic URLs. In this way, you need to implement dynamic loading of URLs in different languages.
1. Bind a variable.
The value of the src attribute on the web component needs to be bound with a variable and cannot be fixed. The variable to be bound is loadUrl in {{}}, and the variable is defined under the script tag in the .ux file. If you create the project with the IDE H5 App template, you can ignore this step because this step has been completed based on IDE template code.
HTML:
[HTML] {{loadUrl}}"
export default {
data: {
loadUrl: "https://transit.navitime.com/en",
},
[/HTML]
2. Initialize the variable value.
In the onInit() method about the quick app's lifecycle, the system language is obtained through a device API, and the corresponding HTML5 URL is loaded after the language is determined.
HTML:
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, use the HTML5 page of the default language.
this.loadUrl = "https://transit.navitime.com/en";
}
},
3. (Optional) Make quick app languages be updated with system settings.
It is applicable to the scenario where the HTML5 quick app has been started and is running. If the user changes the language in system settings at this time, you can use the settings here to update the language on HTML5 pages. You can also ignore this step, in this way, the user can exit the app and re-enter.
The quick app provides an API for monitoring language configuration changes during runtime. The code for adaptation is as follows:
HTML:
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, use the HTML5 page of the default language.
this.loadUrl = "https://transit.navitime.com/en";
}
}
},
For details about Huawei developers and HMS, visit the website.
https://forums.developer.huawei.com/forumPortal/en/home?fid=0101246461018590361
how many types binding we can do using Quick App ?
Some quick app APIs, such as service.share, cannot be used outside the Chinese mainland. How can I shield the code that is not supported outside the Chinese mainland without affecting its use in the Chinese mainland?
Call the device.getCountryCode API to check the value of countryCode of the current HUAWEI ID in the Quick App Center. If the value is CN, the corresponding API can be used. The following takes service.share as an example.
The code in the app.ux file is as follows:
data: {
localeObject: ''
},
test() {
device.getServiceCountryCode({
success: function (ret) {
this.localeObject = ret.serviceCountryCode
console.log(ret.serviceCountryCode);
},
fail: function (erromsg, errocode) {
this.localeObject = 'errocode:' + errocode + ',erromsg:' + erromsg
console.log(erromsg, errocode);
},
complete: function () {
}
})
return this.localeObject
}
The code for calling the service.share API in the UX file is as follows:
fastAppShare() {
if (this.$app.$def.test()==='CN') {
share.share({
// This content is shared by three parties.
})
}
}
Q: Is multi-language syntax supported in value assignment under data?
No. You need to use it in a method. You are advised to assign a value during page initialization to achieve the same effect.
Negative example:
data: {
AppData: "{{ $t('message.takePhotoAndPick') }}",
},
Positive example:
data: {
AppData: ""
},
onInit: function () {
this.AppData = this.$t('message.takePhotoAndPick')
}
For details about Huawei developers and HMS, visit the website.
HUAWEI Developer Forum | HUAWEI Developer
forums.developer.huawei.com
Overview
In this article, I will create a demo app along with the integration of HMS ML Kit which based on Cross-platform Technology Xamarin. User can easily scan any items from this application with camera Product Vision Search ML Kit technique and choose best price and details of product.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Service Introduction
HMS ML Kit allows your apps to easily leverage Huawei's long-term proven expertise in machine learning to support diverse artificial intelligence (AI) applications throughout a wide range of industries.
A user can take a photo of a product. Then the Product Visual Search service searches for the same or similar products in the pre-established product image library and returns the IDs of those products and related information. In addition, to better manage products in real-time, this service supports offline product import, online product addition, deletion, modification, query, and product distribution.
We can capture any kind of image for products to buy or check the price of a product using Machine Learning. It will give the other options so that you can improve your buying skills.
Prerequisite
1. Xamarin Framework
2. Huawei phone
3. Visual Studio 2019
App Gallery Integration process
1. Sign In and Create or Choose a project on AppGallery Connect portal.
2. Add SHA-256 key.
3. Navigate to Project settings and download the configuration file.
4. Navigate to General Information, and then provide Data Storage location.
5. Navigate to Manage APIs and enable APIs which require by application.
Xamarin ML Kit Setup Process
1. Download Xamarin Plugin all the aar and zip files from below url:
https://developer.huawei.com/consum...Library-V1/xamarin-plugin-0000001053510381-V1
2. Open the XHms-ML-Kit-Library-Project.sln solution in Visual Studio.
3. Navigate to Solution Explore and right-click on jar Add > Exsiting Item and choose aar file which download in Step 1.
4. Right click on added aar file then choose Properties > Build Action > LibraryProjectZip
Note: Repeat Step 3 & 4 for all aar file.
5. Build the Library and make dll files.
Xamarin App Development
1. Open Visual Studio 2019 and Create A New Project.
2. Navigate to Solution Explore > Project > Assets > Add Json file.
3. Navigate to Solution Explore > Project > Add > Add New Folder.
4. Navigate to Folder(created) > Add > Add Existing and add all DLL files.
5. Select all DLL files.
6. Right-click on Properties, choose Build Action > None.
7. Navigate to Solution Explore > Project > Reference > Right Click > Add References, then navigate to Browse and add all DLL files from recently added folder.
8. Added reference, then click OK.
ML Product Visual Search API Integration
1. Create an analyzer for product visual search. You can create the analyzer using the MLRemoteProductVisionSearchAnalyzerSetting class.
C#:
// Method 1: Use default parameter settings.
MLRemoteProductVisionSearchAnalyzer analyzer = MLAnalyzerFactory.Instance.RemoteProductVisionSearchAnalyzer;
// Method 2: Use customized parameter settings.
MLRemoteProductVisionSearchAnalyzerSetting settings = new MLRemoteProductVisionSearchAnalyzerSetting.Factory()
// Set the maximum number of products that can be returned.
.SetLargestNumOfReturns(16)
.Create();
MLRemoteProductVisionSearchAnalyzer analyzer = MLAnalyzerFactory.Instance.GetRemoteProductVisionSearchAnalyzer(settings);
2. Create an MLFrame object by using Android.Graphics.Bitmap. JPG, JPEG, PNG, and BMP images are supported.
C#:
// Create an MLFrame object using the bitmap, which is the image data in bitmap format.
MLFrame frame = MLFrame.FromBitmap(bitmap);
3. Implement image detection.
Code:
Task<IList<MLProductVisionSearch>> task = this.analyzer.AnalyseFrameAsync(frame);
await task;
if (task.IsCompleted && task.Result != null)
{
// Analyze success.
var productVisionSearchList = task.Result;
if (productVisionSearchList.Count != 0)
{
//Product detected successfully
}
else
{
//Product not found
}
}
4. After the recognition is complete, stop the analyzer to release recognition resources.
if (analyzer != null) {
analyzer.Stop();
}
ProductVisionSearchAnalyseActivity.cs
This activity performs all the operation regarding product search with camera.
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Android;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Graphics;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using AndroidX.AppCompat.App;
using AndroidX.Core.App;
using AndroidX.Core.Content;
using Com.Huawei.Hms.Mlplugin.Productvisionsearch;
using Com.Huawei.Hms.Mlsdk;
using Com.Huawei.Hms.Mlsdk.Common;
using Com.Huawei.Hms.Mlsdk.Productvisionsearch;
using Com.Huawei.Hms.Mlsdk.Productvisionsearch.Cloud;
using Java.Lang;
namespace HmsXamarinMLDemo.MLKitActivities.ImageRelated.ProductVisionSearch
{
[Activity(Label = "ProductVisionSearchAnalyseActivity")]
public class ProductVisionSearchAnalyseActivity : AppCompatActivity, View.IOnClickListener
{
private const string Tag = "ProductVisionSearchTestActivity";
private static readonly int PermissionRequest = 0x1000;
private int CameraPermissionCode = 1;
private static readonly int MaxResults = 1;
private TextView mTextView;
private ImageView productResult;
private Bitmap bitmap;
private MLRemoteProductVisionSearchAnalyzer analyzer;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
this.SetContentView(Resource.Layout.activity_image_product_vision_search_analyse);
this.mTextView = (TextView)this.FindViewById(Resource.Id.result);
this.productResult = (ImageView)this.FindViewById(Resource.Id.image_product);
this.bitmap = BitmapFactory.DecodeResource(this.Resources, Resource.Drawable.custom_model_image);
this.productResult.SetImageResource(Resource.Drawable.custom_model_image);
this.FindViewById(Resource.Id.product_detect_plugin).SetOnClickListener(this);
this.FindViewById(Resource.Id.product_detect).SetOnClickListener(this);
// Checking Camera Permissions
if (!(ActivityCompat.CheckSelfPermission(this, Manifest.Permission.Camera) == Permission.Granted))
{
this.RequestCameraPermission();
}
}
private void RequestCameraPermission()
{
string[] permissions = new string[] { Manifest.Permission.Camera };
if (!ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.Camera))
{
ActivityCompat.RequestPermissions(this, permissions, this.CameraPermissionCode);
return;
}
}
private void CheckPermissions(string[] permissions)
{
bool shouldRequestPermission = false;
foreach (string permission in permissions)
{
if (ContextCompat.CheckSelfPermission(this, permission) != Permission.Granted)
{
shouldRequestPermission = true;
}
}
if (shouldRequestPermission)
{
ActivityCompat.RequestPermissions(this, permissions, PermissionRequest);
return;
}
StartVisionSearchPluginCapture();
}
private async void RemoteAnalyze()
{
// Use customized parameter settings for cloud-based recognition.
MLRemoteProductVisionSearchAnalyzerSetting setting =
new MLRemoteProductVisionSearchAnalyzerSetting.Factory()
// Set the maximum number of products that can be returned.
.SetLargestNumOfReturns(MaxResults)
.SetProductSetId("vmall")
.SetRegion(MLRemoteProductVisionSearchAnalyzerSetting.RegionDrChina)
.Create();
this.analyzer = MLAnalyzerFactory.Instance.GetRemoteProductVisionSearchAnalyzer(setting);
// Create an MLFrame by using the bitmap.
MLFrame frame = MLFrame.FromBitmap(bitmap);
Task<IList<MLProductVisionSearch>> task = this.analyzer.AnalyseFrameAsync(frame);
try
{
await task;
if (task.IsCompleted && task.Result != null)
{
// Analyze success.
var productVisionSearchList = task.Result;
if(productVisionSearchList.Count != 0)
{
Toast.MakeText(this, "Product detected successfully", ToastLength.Long).Show();
this.DisplaySuccess(productVisionSearchList);
}
else
{
Toast.MakeText(this, "Product not found", ToastLength.Long);
}
}
else
{
// Analyze failure.
Log.Debug(Tag, " remote analyze failed");
}
}
catch (System.Exception e)
{
// Operation failure.
this.DisplayFailure(e);
}
}
private void StartVisionSearchPluginCapture()
{
// Set the config params.
MLProductVisionSearchCaptureConfig config = new MLProductVisionSearchCaptureConfig.Factory()
//Set the largest OM detect Result,default is 20,values in 1-100
.SetLargestNumOfReturns(16)
//Set the fragment you created (the fragment should implement AbstractUIExtendProxy)
.SetProductFragment(new ProductFragment())
//Set region,current values:RegionDrChina,RegionDrSiangapore,RegionDrGerman,RegionDrRussia
.SetRegion(MLProductVisionSearchCaptureConfig.RegionDrChina)
//设set product id,you can get the value by AGC
//.SetProductSetId("xxxxx")
.Create();
MLProductVisionSearchCapture capture = MLProductVisionSearchCaptureFactory.Instance.Create(config);
//Start plugin
capture.StartCapture(this);
}
private void DisplayFailure(System.Exception exception)
{
string error = "Failure. ";
try
{
MLException mlException = (MLException)exception;
error += "error code: " + mlException.ErrCode + "\n" + "error message: " + mlException.Message;
}
catch (System.Exception e)
{
error += e.Message;
}
this.mTextView.Text = error;
}
private void DrawBitmap(ImageView imageView, Rect rect, string product)
{
Paint boxPaint = new Paint();
boxPaint.Color = Color.White;
boxPaint.SetStyle(Paint.Style.Stroke);
boxPaint.StrokeWidth = (4.0f);
Paint textPaint = new Paint();
textPaint = new Paint();
textPaint.Color = Color.White;
textPaint.TextSize = 100.0f;
imageView.DrawingCacheEnabled = true;
Bitmap bitmapDraw = Bitmap.CreateBitmap(this.bitmap.Copy(Bitmap.Config.Argb8888, true));
Canvas canvas = new Canvas(bitmapDraw);
canvas.DrawRect(rect, boxPaint);
canvas.DrawText("product type: " + product, rect.Left, rect.Top, textPaint);
this.productResult.SetImageBitmap(bitmapDraw);
}
private void DisplaySuccess(IList<MLProductVisionSearch> productVisionSearchList)
{
List<MLVisionSearchProductImage> productImageList = new List<MLVisionSearchProductImage>();
foreach (MLProductVisionSearch productVisionSearch in productVisionSearchList)
{
this.DrawBitmap(this.productResult, productVisionSearch.Border, productVisionSearch.Type);
foreach (MLVisionSearchProduct product in productVisionSearch.ProductList)
{
productImageList.AddRange(product.ImageList);
}
}
StringBuffer buffer = new StringBuffer();
foreach (MLVisionSearchProductImage productImage in productImageList)
{
string str = "ProductID: " + productImage.ProductId + "\nImageID: " + productImage.ImageId + "\nPossibility: " + productImage.Possibility;
buffer.Append(str);
buffer.Append("\n");
}
this.mTextView.Text = buffer.ToString();
this.bitmap = BitmapFactory.DecodeResource(this.Resources, Resource.Drawable.custom_model_image);
this.productResult.SetImageResource(Resource.Drawable.custom_model_image);
}
public void OnClick(View v)
{
switch (v.Id)
{
case Resource.Id.product_detect:
this.RemoteAnalyze();
break;
case Resource.Id.product_detect_plugin:
CheckPermissions(new string[]{Manifest.Permission.Camera, Manifest.Permission.ReadExternalStorage,
Manifest.Permission.WriteExternalStorage, Manifest.Permission.AccessNetworkState});
break;
default:
break;
}
}
protected override void OnDestroy()
{
base.OnDestroy();
if (this.analyzer == null)
{
return;
}
this.analyzer.Stop();
}
}
}
Xamarin App Build
1. Navigate to Solution Explore > Project > Right Click > Archive/View Archive to generate SHA-256 for build release and Click on Distribute.
2. Choose Distribution Channel > Ad Hoc to sign apk.
3. Choose Demo Keystore to release apk.
4. Finally here is the Result.
Tips and Tricks
1. HUAWEI ML Kit complies with GDPR requirements for data processing.
2. HUAWEI ML Kit does not support the recognition of the object distance and colour.
3. Images in PNG, JPG, JPEG, and BMP formats are supported. GIF images are not supported.
Conclusion
In this article, we have learned how to integrate HMS ML Kit in Xamarin based Android application. User can easily search items online with the help of product visual search API in this application.
Thanks for reading this article. Be sure to like and comments to this article, if you found it helpful. It means a lot to me.
References
https://developer.huawei.com/consum...-Plugin-Guides/about-service-0000001052602130