How can I get Locale and Language from the device, with Kotlinmultiplatform - kotlin-multiplatform

I am creating my first app on kotlin multi-platform, and a need to get some device's information like language and maybe country.
I am looking for a way to get on both devices, android and iOS, using Kotlin multi-plataform.
It is possible? Or it's only possible make this on native way on both devices?

Something like the following.
Common
expect val myLang:String?
expect val myCountry:String?
iOS
actual val myLang:String?
get() = NSLocale.currentLocale.languageCode
actual val myCountry:String?
get() = NSLocale.currentLocale.countryCode
Android
actual val myLang:String?
get() = Locale.getDefault().language
actual val myCountry:String?
get() = Locale.getDefault().country

Related

F# non-static methods in modules

I am an absolute newbie to coding, but I need to modify a F# script. It always gives me the error "Method or object constructor 'x' is not static". I read that this might be due to the fact that I try to call a non-static method within a module, which is by default static. For example 'x' = Get.Axis():
module Primitives =
let axis1 = Zaber.Motion.Ascii.Device.GetAxis(1)
The manual only provides code in C#: var axis1 = device.GetAxis(1);
If I use static member instead of let, I'll get a 'unexpected keyword static in definition' error, although I checked the indentation as suggested in another question.
Assuming you're using the Zaber Motion Library, I think what you need to do is get an instance of a device first, instead of trying to access the class in a static context.
Their documentation includes an example of how to get a list of devices by opening a serial port:
open Zaber.Motion.Ascii
use connection = Connection.OpenSerialPort("COM3")
let deviceList = connection.DetectDevices()
match deviceList |> Seq.tryHead with // See if we got at least one device
| Some device ->
let axis = device.GetAxis(1)
// TODO: Do whatever you want with the axis here
| None ->
failwith "No Devices Found on COM3"

How to use Akka.Streams.*.ConcatMany in F#?

I want to create a flow that creates a new source (it will be a persistence query) out of incoming elements, and then flattens the results. Something like this simplified example:
var z = Source.Single(1).ConcatMany(i => Source.Single(i));
this code compiles and works as expected. My problem is that when I translate it to F#:
let z = Source.Single(1).ConcatMany(fun i -> Source.Single(i))
I get an error saying
This expression was expected to have type
'IGraph<SourceShape<'a>,Akka.NotUsed>'
but here has type
'Source<int,Akka.NotUsed>'
I think that the cause of that is that F# handles co/contravariance differently than C# and cannot simply convert these generic specializations (https://github.com/fsharp/fslang-suggestions/issues/162), but I cannot figure out a way to make a convertion between an int and a SourceShape<int>. Is it possible to convert this example to F#?
Looking at the code on GitHub, it appears that Source<TOut, TMat> is a direct implementation of IGraph, so you should just be able to cast it:
public sealed class Source<TOut, TMat> : IFlow<TOut, TMat>, IGraph<SourceShape<TOut>, TMat>
let z = Source.Single(1).ConcatMany(fun i -> Source.Single(i) :> IGraph<SourceShape<int>,Akka.NotUsed>)
I think the biggest difference between the C# and F# usage is that C# will automatically do the upcast for you.
One workaround that I found is to use Akkling.Streams wrapper library:
open Akkling.Streams
let x =
Source.singleton 1
|> Source.collectMap(fun x -> Source.singleton x)
the question how to do this without Akkling remains open.

#iOSFindBy is displayed as deprecated, what can I use instead (using pagefactory for Hybrid usage of Android and iOS device))

I have no experience with iOS, but I am trying to redesign my Android Project for the iOS Guys to use it as well for iOS.
After search in internet I find out that this can happens by using the page factory and locating elements by #iOSFindBy,
After trying to use #iOSFindby for locating element using the page factory method, the compiler indicate that it is deprecated.
#iOSFindBy (Accessibility = "button_login")
#AndroidFindBy(id = "net.myApp.int:id/loginBtn")
private MobileElement login_Button2;
what Can I use instead of this?
I saw also in Appium java client (https://static.javadoc.io/io.appium/java-client/7.0.0/index.html?deprecated-list.html) :
*io.appium.java_client.pagefactory
Annotation Type iOSFindBy
Deprecated.
UIAutomation is going to get deprecated. Use iOSXCUITFindBy instead It is recommended to use XCUITest
#Retention(value=RUNTIME) #Target(value={FIELD,TYPE})
#Repeatable(value=iOSFindBySet.class) public #interface iOSFindBy
Used to mark a field on a Page Object to indicate an alternative mechanism for locating the element or a list of elements. Used in conjunction with PageFactory this allows users to quickly and easily create PageObjects. using iOS UI selectors, accessibility, id, name, class name, tag and xpath*
but I dont know if this is the solution and how to use
If I use it in my Code also get Error:
#iOSXCUITFindBy Accessibility = "button_login"
#AndroidFindBy(id = "net.myApp.int:id/loginBtn")
private MobileElement login_Button1;
Annotation are not allowed here.
Thanks for any Tip in advance
The best way to know how things work is to check related tests in appium-java-client repository on github:
#iOSXCUITFindBy(accessibility = "IntegerB")
private MobileElement textField2;
So in your case, it should be:
#iOSXCUITFindBy(accessibility = "button_login")
#AndroidFindBy(id = "net.myApp.int:id/loginBtn")
private MobileElement login_Button1;

Can I use System.Timers.Timer in an F# PCL library?

I need to use System.Timers.Timer in an F# PCL library.
I'm currently targeting framework 4.5 and using Profile7 (I used the VS template) and it doesn't allow access to System.Timer.
According to this SO answer it's a known issue and is solved in 4.5.1.
I created a 4.5.1 C# PCL and checked its .csproj. It targets framework 4.6 and uses Profile32.
Is there a way to target the same in an F# project? I naively tried to update the .fsproj with the C# values, but it broke everything. :)
Thanks very much!
The System.Timers.Timer (and System.Threading.Timer) classes don't work in the main F# PCL profiles. Given that normal F# async is supported, you can easily work around this by writing your own "timer" type. For example, the following (while a bit ugly) should mimic the Timer class functionality reasonably well:
type PclTimer(interval, callback) =
let mb = new MailboxProcessor<bool>(fun inbox ->
async {
let stop = ref false
while not !stop do
// Sleep for our interval time
do! Async.Sleep interval
// Timers raise on threadpool threads - mimic that behavior here
do! Async.SwitchToThreadPool()
callback()
// Check for our stop message
let! msg = inbox.TryReceive(1)
stop := defaultArg msg false
})
member __.Start() = mb.Start()
member __.Stop() = mb.Post true

Is it possible to use the HttpClient class in MonoDroid?

I'm trying to use the HttpClient class on a MonoDroid project but it looks like the System.Net.http namespace it's not valid.
I try to add a reference in the project to System.Net.http.dll but it doesn't seem to be available in the references list.
Any idea?
Thks
HttpClient is a .NET 4.5 class, which is not available yet in Mono for Android. Mono itself added supported for it in version 3.0, but Mono for Android is still based on Mono 2.10. I know Xamarin is working on updating Mono for Android (and MonoTouch) to Mono 3.0 now, but as far as I know there's no release date set yet.
I know it is an old thread but I just saw that Xamarin has finally given System.Net.Http in Xamarin.Android 4.8, so thought to share it with you too.
Thanks.
You can't use HttpClient (yet!), but you can still use the System.Net.HttpWebRequest object, which does actually do what HttpClient can provide convenient wrappers for (especially when hitting up a Web API controller).
Here's a sample from a current project I'm working on (it's using the monodroid port of NewtonSoft.Json, not the standard System.Runtime.Serialization.Json) :
private void AddARecord()
{
var cartesian = new Cartesian()
{
Description = "next item blah",
X = 5,
Y = 10,
Z = 15,
};
string json = JsonConvert.SerializeObject(cartesian);
var request = new HttpWebRequest(new Uri(_url)) {ContentType = "application/json", Method = "POST"};
var sw = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
sw.Write(json);
sw.Close();
request.BeginGetResponse(ProcessJsonResponseForSingleResult, request);
}
...the Web API controller I'm hitting does something arbitrary, saves the object I just sent, and then tweaks the description so I know it works. Then it sends the tweaked object back...
And then the callback ProcessJsonResponseForSingleResult looks like
private void ProcessJsonResponseForSingleResult(IAsyncResult ar)
{
var request = (HttpWebRequest)ar.AsyncState;
var response = request.EndGetResponse(ar);
using (var outputStream = new StreamReader(response.GetResponseStream(), System.Text.Encoding.ASCII))
{
var jsonString = outputStream.ReadToEnd();
Log.Info("PJRFSR", string.Format("JSON string: {0} - deserialising...", jsonString));
var cartesian = JsonConvert.DeserializeObject<Cartesian>(jsonString);
RunOnUiThread(() => UpdateUiTextView(cartesian.Description));
}
}
Yeah, I know, it uses the BeginAsync/EndAsync pattern which I don't like any more either, but it does work if you just need to get something done.

Resources