Multiple local HMS ML Kit translator models in Flutter? - flutter

I've defined a class that wraps the HMS ML Kit in-device translator.
This class has two translator instances, with two different settings:
MLLocalTranslator translatorSend = new MLLocalTranslator();
MLLocalTranslator translatorReceive = new MLLocalTranslator();
MLTranslateSetting settingSend = new MLTranslateSetting();
MLTranslateSetting settingReceive = new MLTranslateSetting();
translatorSend translates request from a language (for example it) to English (en). translatorReceive translates the response of the request from en to it.
However, the prepare method only downloads the model for en_it translation and not the it_en model (if exists).
HMSTranslator(String languageCode) {
settingSend.sourceLangCode = languageCode;
settingSend.targetLangCode = "en";
settingReceive.sourceLangCode = "en";
settingReceive.targetLangCode = languageCode;
}
Future<bool> prepare() async {
if(settingSend.sourceLangCode != settingSend.targetLangCode) {
bool isSendPrepared = await translatorSend.prepareModel(setting: settingSend)
bool isReceivePrepared = await translatorReceive.prepareModel(setting: settingReceive);
isPrepared = isSendPrepared && isReceivePrepared;
}
else {
isPrepared = false;
}
return isPrepared;
}
The problem comes when I translate a string with translatorSend.
Future<String> translateString(String stringToTranslate) async {
if(settingSend.sourceLangCode != settingSend.targetLangCode) {
String result;
if (isPrepared) {
result = await translatorSend.asyncTranslate(sourceText: stringToTranslate);
}
else {
settingSend.sourceTextOnRemote = stringToTranslate;
result = await sendRemoteTranslator.asyncTranslate(setting: settingSend);
}
return result;
}
else {
return stringToTranslate;
}
}
This method should translate an it String to an en String. However, it seems to call the en_it model and fails the translation:
I/flutter (28228): TRANSLATOR: it to en
I/flutter (28228): TRANSLATOR: PREPARED
I/MLLocalTranslator(28228): translate sourceLanguage: en targetLanguage: it
WHAT: vestiti usati -> vestiti usati - WHERE applicazione -> applicazione
The translation of the response, from en to it works.
I've tested other languages and that happens also with fr.
Further testing showed that the process worked with es:
WHAT: ropa usada -> Used clothing - WHERE aplicación -> application

Pls check whether you are using the new version of the Flutter plug-in.
Language packs can be used in two-way. For example, en-it can be used for en to it or it to en.
The following are for your reference:
Modify based on the plugin Demo in the official website
The same instance is used for bidirectional translation by invoking multiple times.
//Entry function
_translationMake() async {
try {
await _prepareModel_run("it","en","vestiti usati");
await _prepareModel_run("en","it","application");
} on Exception catch (e) {
print(e.toString());
}
}
_prepareModel_run(String srcLang, String dstLang, String content) async {
setting.sourceLangCode = srcLang;
setting.targetLangCode = dstLang;
try {
final bool res = await translator.prepareModel(setting: setting);
if (res) {
final String s = await _localTranslate_run(content);
if (s != null) {
print("_prepareModel_run " + content + " translate to "+s);
}
}else {
print("_prepareModel_run res false");
}
} on Exception catch (e) {
print(e.toString());
}
}
Future<String> _localTranslate_run(String Content) async {
try {
final String s =
await translator.syncTranslate(sourceText: Content);
if (s != null) {
_stopLocalTranslate();
setState(() => _translateResult = s);
return s;
} else {
print("no Translation");
setState(() => _translateResult = "no translation");
return "no translation";
}
} on Exception catch (e) {
print(e.toString());
}
}
And the log print results are as follows:
_prepareModel_run vestiti usati translate to Used clothes
_prepareModel_run application translate to applicazione

We can use HMS ML kit to translate text into different languages. The following is the info. you can take reference for.
ML services can currently translate texts between 12 languages: Simplified Chinese, English, French, Arabic, Thai, Spanish, Turkish, Portuguese, Japanese, German, Italian, and Russian.
Step 1: Text is fetched from UI and provided to ML model
Step 2: Parameters are set before making API call to server
    · Source language code
    · Desired Language code
    · String which needs to be translated.
Step 3: Once API data reaches the server ML Model translates the text into desired output
Step 4: Server returns the translated output to application.
Step 5: Application shows output to UI.
Precautions: The machine learning model is stored on cloud. An Internet call is made so its permission is required.
Below are the changes you have to do in order to run build and run the project
Open App.gradle file and add this line on top.
apply plugin: 'com.huawei.agconnect'
To use Text Translation service add this dependency to pro
mplementation 'com.huawei.hms:ml-computer-translate:1.0.3.300'
MLRemoteTranslateSetting object is being created which takes Source Language as setSourceLangCode() and Output Language as setTargetLangCode()
MLRemoteTranslator object is created by passing previously created MLRemoteTranslateSetting object to it.
You can create a Task where mlRemoteTranslator will have an async call by asyncTranslate() and we will provide user string as the input to this method.
This task will yield to 2 callbacks
addOnSuccessListener
addOnFailureListener
As the name suggests you can add your code in success listener and can add notification/Log in failure listener.
For Flutter:
First:
create MlTranslatorSettings object and instance in initState
Second:
set the settings to the translator, for example, initial language and final language of the translation, see below example.
In the properties, you can customize the type of map, controls, camera position, initial position, etc.
Here are also some detailed info. regarding how to use HMS ML kit with Flutter:
Link Hope it will be helpful to you.

Related

Getting data from Realtime Database with a conditional statement

how I can show DeliveryBoys in a specific location, in my realtime database I have a value that I need to compare drivers with which is "City" I would like to have all DeliveryBoys that are in a specific city. How can I do that? Using flutter
Am only able to get all drivers without a conditional statement
**This is my Function that i want to modify **
retrieveOnlineDriversInformation(List onlineNearestDriversList) async {
DatabaseReference ref =
FirebaseDatabase.instance.ref().child("DeliveryBoys");
for (int i = 0; i < onlineNearestDriversList.length; i++) {
await ref
.child(onlineNearestDriversList[i].driverId.toString())
.once()
.then((dataSnapshot) {
var driverKeyInfo = dataSnapshot.snapshot.value;
dList.add(driverKeyInfo);
});
}
}
Database Structure
Based on your responses and as far as I can see, you don't need the loop where you have it. Therefore, I am going to ignore it and simply show you the code that will return the list of driver ids of all drivers for city 'Lusaka'.
Future<List<String>> retrieveOnlineDriversInformation() async {
final driverIds = <String>[];
DatabaseReference ref = FirebaseDatabase.instance.ref().child("drivers");
try {
await ref.orderByChild("city")
.equalTo("Lusaka")
.once()
.then(
(event) {
if (event.snapshot.value != null) {
final driverListData =
Map<String, dynamic>.from(event.snapshot.value! as Map);
driverListData.forEach((key, value) {
driverIds.add(key);
});
}
},
} on FirebaseException catch (error, stackTrace) {
// < Some code here to print database error details or otherwise deal with it >
} catch (error, stackTrace) {
// < Some code here to print other error details or otherwise deal with it >
}
return driverIds;
}
You could instead modify this to just return the Map 'driverListData' which contains each driver's id and associated driver data.
A couple of other points:
You don't stick to a standard naming convention for your database node and field names. I suggest that you always use lowerCamelCase as the standard (so for example, change DriverLicense to driverLicense) as it will match what you typically name the variables within the Flutter/Dart code.
You don't need to hold the driver id as a separate field in the driver node. It is a duplicate (and therefore wastes space on the database) of the driver record key, which is already accessible to you.
As you see, you should always wrap your database call logic in a try / catch clauses in order to handle any errors that the call to the database may return. There are specific exceptions that can be tested for with the on clause.

Can two ASP . NET Core 5.0 web api cause "The content may be already have been read by another component" errpr 400 if they accessed same db be4?

My API was as follows:
[HttpPut("{id}")]
public async Task<ActionResult<HomeContextModel>> EditHomeContext(int id, string title, string context, string subcontext, IFormFile imageFile)
{
HomeContextModel homeContextModel = await _context.HomeContext.Include(x => x.Image).Include(x => x.Button).Include(x => x.Logo).ThenInclude(y => y.Image)
.FirstOrDefaultAsync(m => m.Context_Id == id);
//HomeContextModel homeContextModel = await GetHomeContextModel(id);
if (homeContextModel == null)
{
return BadRequest("Context Id cannot be null");
}
if (imageFile != null)
{
ImageModel imageModel = homeContextModel.Image;
if (imageModel != null)
{
string cloudDomain = "https://privacy-web.conveyor.cloud";
string uploadPath = _webHostEnvironment.WebRootPath + "\\Images\\";
if (!Directory.Exists(uploadPath))
{
Directory.CreateDirectory(uploadPath);
}
string filePath = uploadPath + imageFile.FileName;
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await imageFile.CopyToAsync(fileStream);
await fileStream.FlushAsync();
}
using (var memoryStream = new MemoryStream())
{
await imageFile.CopyToAsync(memoryStream);
imageModel.Image_Byte = memoryStream.ToArray();
}
imageModel.ImagePath = cloudDomain + "/Images/" + imageFile.FileName;
imageModel.Modify_By = "CMS Admin";
imageModel.Modity_dt = DateTime.Now;
//_context.Update(imageModel);
}
}
homeContextModel.Title = title;
homeContextModel.Context = context;
homeContextModel.SubContext = subcontext;
_context.Entry(homeContextModel).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!HomeContextModelExists(homeContextModel.Context_Id))
{
return NotFound();
}
else
{
throw;
}
}
return Ok("Home Context Edit Successfully");
}
It's an API for the Content Management System (CMS) to change the content of the Homepage using a Flutter webpage that make put request onto this API.
Everything works fine. In the last few days, where I tested and tested again during the development. So before today, I've wrapped up them and submitted to the necessary place (It's a university FYP).
Until now it cause me this error when I was using this to prepare my presentation:
Error 400 failed to read the request form Unexpected end of stream ..."
After all the tested I tried:
Internet solutions
restore the database
repair Microsoft VS 2019 (As this issue was fixed before after I
updated my VS 2019 from 16.8. to the latest 16.11.7)
Use the ASP .NET file which didn't caused this issue before
Then I realized it may be because of I used another older ASP file to accessed the same database before. Does this really cause this matter?
If yes, then now how should I solved it, with the action I already done (listed as above)?
EDIT: Additional description to the situation
The above API I set breakpoint before, on the first line, using Swagger to test it.
It turns out that it didn't go into the API and straightaway return the error 400
REST API can have parameters in at least two ways:
As part of the URL-path
(i.e. /api/resource/parametervalue)
As a query argument
(i.e. /api/resource?parameter=value)
You are passing your parameters as a query instead of a path as indicated in your code. And that is why it is not executing your code and returning 400.

Get "handles" of characteristics using FlutterBlue?

Repeat of https://github.com/pauldemarco/flutter_blue/issues/868
On Windows, I have some code that looks like:
wclGattClient.ReadCharacteristicValue(errorchar, wclGattOperationFlag.goNone, out var Value);
foreach (uint16 handle in Value)
{
foreach(chars in service)
if(chars.handle == handle)
{
wclGattClient.ReadCharacteristicValue(errorchar, wclGattOperationFlag.goNone, out var Val2);
print("UUID %s is flagged : %s", chars.uuid, Val2.toString());
}
}
ie, the device is returning a list of Handles that are in an alert status (so I can read them and present the condition to the user), and I need to match that up with the Handle of the char in the discoverServices so I know which ones to get the data from...
How do I do this with flutter_blue?
The flutter_blue documentation on Github includes a part about reading and writing characteristics:
// Reads all characteristics
var characteristics = service.characteristics;
for(BluetoothCharacteristic c in characteristics) {
List<int> value = await c.read();
print(value);
}
// Writes to a characteristic
await c.write([0x12, 0x34])
In this example BluetoothCharacteristic cwould be your handle you can use to read and write values to.

Flutter: Search inside the List

I am trying to using the mobile_number plugin. Basically, I am fetching the SimCard number.
Here is the code.
String _mobileNumber = '';
List<SimCard> _simCard = <SimCard>[];
Future<void> initMobileNumberState() async {
if (!await MobileNumber.hasPhonePermission) {
await MobileNumber.requestPhonePermission;
return;
}
String mobileNumber = '';
// Platform messages may fail, so we use a try/catch PlatformException.
try {
mobileNumber = await MobileNumber.mobileNumber;
_simCard = await MobileNumber.getSimCards;
} on PlatformException catch (e) {
debugPrint("Failed to get mobile number because of '${e.message}'");
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_mobileNumber = mobileNumber;
});
}
Widget fillCards() {
List<Widget> widgets = _simCard
.map((SimCard sim) => Text(
'Sim Card Number: (${sim.countryPhonePrefix}) - ${sim.number}\nCarrier Name: ${sim.carrierName}\nCountry Iso: ${sim.countryIso}\nDisplay Name: ${sim.displayName}\nSim Slot Index: ${sim.slotIndex}\n\n'))
.toList();
return Column(children: widgets);
}
This is working fine I can see the mobile number.
But now I need to search the number inside the list.
I checked some of the questions on SO to get it done but I am not good with lists.
I tried using some of the examples and comes up with below. But this is incorrect with so many errors.
var comparenumber = _simCard.map((SimCard sim).where((sim.number) => sim.number.toLowerCase().contains(mobile.toLowerCase()).toList();
If you want to search if the list has a number or part of a number (say the result would be true searching for 641 in a list that has a number 641-819-xxxx)
you can use this code
bool searchNumber(String number) {
return _simCard.where((element) => element.number.contains(number)).isNotEmpty;
}
if you want to search for an exact number match replace element.number.contains(number) with element.number == number as in dart == for strings compare the string value, not pointers as in Java for example.
So, what is where?
where is a function in the abstract class Iterable (and lists in dart are iterable) that take a predicate or a test function and returns an iterable that has only elements that match the predicate.
returned iterable can be collected to a list or you can use some other functions or properties directly on it like isNotEmpty in our case

NullReferenceException occurs during offline sync to Azure Mobile Service

I am trying to make offline sync to table from azure mobile service. My Xamarin Form version is 1.4.2.6359.
I try to test my code in OnCreate method of MainActivity. All preparation steps such as MobileServiceClient initialization, MobileServiceSQLiteStore initialization, SyncTable creation, etc are ok.
When I try to call PullAsync, I am getting NullReferenceException. I capture the package using Package Capture App from mobile. The request goes to Azure Mobile service and it returns the correct json data successfully.
When I try the same code in Xamarin Android project (not Xamarin Form), it is working fine.
To reproduce the issue.
Just create Xamarin Form (Portable) project and use my code.
My Code
private async Task Test() {
const string applicationURL = #"https://xxxx.azure-mobile.net/";
const string applicationKey = #"xxxx";
CurrentPlatform.Init();
var client = new MobileServiceClient(applicationURL, applicationKey);
string path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "store.db");
if (!File.Exists(path)) {
File.Create(path).Dispose();
}
var store = new MobileServiceSQLiteStore(path);
store.DefineTable<Product>();
await client.SyncContext.InitializeAsync(store);
var productTable = client.GetSyncTable<Product>();
try {
await client.SyncContext.PushAsync();
await productTable.PullAsync("allProducts", productTable.CreateQuery());
var t = await productTable.ToListAsync();
Console.WriteLine("Product Count : " + t.Count);
}
catch (Java.Net.MalformedURLException ex) {
Console.WriteLine(ex.Message);
}
catch (Exception e) {
Console.WriteLine(e.Message);
}
}
References:
http://azure.microsoft.com/en-us/documentation/articles/mobile-services-xamarin-android-get-started-offline-data/
http://blogs.msdn.com/b/carlosfigueira/archive/2014/04/07/deep-dive-on-the-offline-support-in-the-azure-mobile-service-managed-client-sdk.aspx
I got the solution for this case.
As far as my understanding, this is what is happening. During the application is loading, I call PullAsync. It is async call and during this call, application keeps loading other components. The actual NullReferenceException is coming from OnPrepareOptionsMenu function (Xamarin.Forms.Platform.Android.AndroidActivity.OnPrepareOptionsMenu). The exception is happening on other thread and the thread simply dies. That's why I cannot get stack trace from my main thread.
This NullReferenceException issue is totally not related to Azure Mobile Service.
I override OnPrepareOptionsMenu in MainActivity and add try-catch block to base class function call. The problem is solved. Here is my code in MainActivity class.
public override bool OnPrepareOptionsMenu(IMenu menu) {
try {
// I am always getting menu.HasVisibleItems = false in my app
if (menu != null && menu.HasVisibleItems) {
// Exception is happening when the following code is executed
var result = base.OnPrepareOptionsMenu(menu);
return result;
}
}
catch{
}
return true;
}
I don't really understand why it is happening. Please point me out if you have better understanding of this case and better solution.
I think my issue is same as this : http://forums.xamarin.com/discussion/23579/exception-whilte-trying-to-open-activity-from-xamarin-forms-page