How to see what device is used? - flutter

I need to customize web app whether it is used on laptop or phone, found ios or android detection, so would it work if I just did:
if (android or ios) {return phone version} else {computer version} ?
SOLUTION
solutions below gave me an error, but this package helped me:
https://pub.dev/packages/universal_io
checkOS() {
if (Platform.isAndroid || Platform.isIOS) {
return PhoneVersion;
} else {
return ComputerVersion,
);
}
}
or
log('os: ${Platform.operatingSystem}');

You can use Platform class:
import 'dart:io';
bool isDesktop = (Platform.isWindows || Platform.isMacOS || Platform.isLinux);
bool isMobile = (Platform.isIOS || Platform.isAndroid);
also you can use kIsWeb:
import 'package:flutter/foundation.dart';
if (kIsWeb) {
// HORIZONTAL LAYOUT
} else {
// VERTICAL LAYOUT
}

if (Platform.isAndroid) {
// Do Android case
} else {
// Do other case
}
For retrieving more information about user's device, use packages like device_info.

Related

How do I properly use DI with IHttpClientFactory in .NET MAUI

I haven't found anything about HttpClient in .NET MAUI.
Does anyone know if the service:
builder.Services.AddHttpClient<IMyService, MyService>();
is possible in MAUI's startup MauiProgram.cs? And then inject HttpClient to where it's going to be used. I have tried everything and it does not seem to work. Only AddSingleton of HttpClient works for me, but it doesn't seem optimal.
PS.: I had to install nuget package Microsoft.Extensions.Http in order to use the AddHttpClient service.
UPDATES:
WORKING CODE:
MauiProgram.cs
builder.Services.AddTransient<Service<Display>, DisplayService>();
builder.Services.AddTransient<Service<Video>, VideoService>();
builder.Services.AddTransient<Service<Image>, ImageService>();
builder.Services.AddTransient<Service<Log>, LogService>();
builder.Services.AddSingleton(sp => new HttpClient() { BaseAddress = new Uri("https://api.myapi.com") });
Example of VideosViewModel.cs using a service
[INotifyPropertyChanged]
public partial class VideosViewModel
{
readonly Service<Video> videoService;
[ObservableProperty]
ObservableCollection<Video> videos;
[ObservableProperty]
bool isEmpty;
[ObservableProperty]
bool isRefreshing;
public VideosViewModel(Service<Video> videoService)
{
this.videoService = videoService;
}
[ICommand]
internal async Task LoadVideosAsync()
{
#if ANDROID || IOS || tvOS || Tizen
UserDialogs.Instance.ShowLoading("Henter videoer fra databasen...");
#endif
await Task.Delay(2000);
Videos = new();
try
{
await foreach (Video video in videoService.GetAllAsync().OrderBy(x => x.Id))
{
Videos.Add(video);
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
IsRefreshing = false;
#if ANDROID || IOS || tvOS
UserDialogs.Instance.HideLoading();
#endif
if (Videos.Count is 0)
{
IsEmpty = true;
}
else
{
IsEmpty = false;
}
}
}
[ICommand]
async Task UploadVideoAsync()
{
await Shell.Current.DisplayAlert("Upload en video", "Under opbygning - kommer senere!", "OK");
}
}
NOT WORKING CODE:
MauiProgram.cs
builder.Services.AddHttpClient<Service<Display>, DisplayService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
builder.Services.AddHttpClient<Service<Video>, VideoService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
builder.Services.AddHttpClient<Service<Image>, ImageService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
builder.Services.AddHttpClient<Service<Log>, LogService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
VideosViewModel.cs
Same as above working code.
What specifically doesn't work is that I get object reference exception on OrderBy(x => x.Id), specifically highlighted x.Id in ViewModel. Removing OrderBy method gives no longer exceptions, but the view shows no data except one random empty Frame.
Do not use builder.Services.AddHttpClient in MAUI.
Use one instance.

Flutter textfield on fireOS firetv/firestick on top of textfield

When calling textfield on flutter in fireOS in the fire tv devices, to do a search for example the fireOS virtual keyboard pops on top of textfield and doesnt work like on other android devices where the keyboard is on the bottom and textfield is visible.
On android legacy for example i can use edittext widget and the same keyboard pops on top but whatever i type with the controller updates on the virtual keyboard itself, because the keyboard has its own textfield or edittext. So my problem is how could i update the edittext on firetv virtual keyboard with flutter.
Okay, so I didnt find an answer anywhere so I had to do some hacky stuff heres how i got it to work since flutter is a no go.
Solution Overview:
1.- So first check is you are running on Android, you can do this with if (Platform.isAndroid) on flutter.
2.- If you are actually running on android you can then open a platform channel to native android to check the actual manufacturer(I will post how to code below).
3.- Check manufacturer or device name for "Amazon" or "Kindle" or whatever an if(string.contains("")) will do the trick.
4.- Open again a platform channel to Native Android and open an Alert Dialog with an Edittext, capture the resulting string and return it to flutter.
And thats how i got firetv's keyboard to work under flutter.
if (Platform.isAndroid){
checkOs().then((String osName){
print("Device running on: $osName");
if(osName.contains("Amazon") || osName.contains("AFTN")){
fireTvKeyboardInput().then((String result){
buscarTitulo(result);
});
}else{
_showDialog(); // Keyboard for NON FIREOS devices on Android.
}
});
}else{
//IF Device is not Android Eg. IOS
_showDialog();
}
Now theres two functions i used "checkOs" and "fireTvKeyboardInput" heres the code:
Future<String> checkOs() async {
String myResult = "";
try {
myResult = await platform.invokeMethod("checkOS", <String, dynamic>{
'param1': "hello",
});
}catch (e){
print ("exception: $e");
}
return myResult;
}
Future<String> fireTvKeyboardInput() async {
String myResult = "";
try {
myResult = await platform.invokeMethod("fireKeyBoard", <String, dynamic>{
'param1': "hello",
});
}catch (e){
print ("exception: $e");
}
return myResult;
}
On Native Android heres the code:
if(call.method == "checkOS"){
val operatingSystem = android.os.Build.MANUFACTURER + "- " + android.os.Build.MODEL
result.success(operatingSystem)
}
if(call.method == "fireKeyBoard"){
val alert = AlertDialog.Builder(this)
alert.setMessage("Search")
// Set an EditText view to get user input
val input = EditText(this)
input.hint = "Enter Text"
input.inputType = InputType.TYPE_CLASS_TEXT
alert.setView(input)
input.setOnKeyListener { view, keyCode, keyEvent ->
if (keyCode == 66) {
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(input.windowToken, 0)
}
false
}
alert.setPositiveButton("Ok") { dialog, whichButton ->
result.success(input.text.toString());
}
alert.setNegativeButton("Cancel") { dialog, whichButton ->
// Canceled.
}
alert.show()
}

How can I detect if my Flutter app is running in the web?

I know that I can detect the operating system with Platform.isAndroid, Platform.isIOS, etc. but there isn't something like Platform.isWeb so how can I detect this?
There is a global boolean kIsWeb which can tell you whether or not the app was compiled to run on the web.
Documentation: https://api.flutter.dev/flutter/foundation/kIsWeb-constant.html
import 'package:flutter/foundation.dart' show kIsWeb;
if (kIsWeb) {
// running on the web!
} else {
// NOT running on the web! You can check for additional platforms here.
}
If you want to know what your OS is on the web, you can use
String platform = "";
if (kIsWeb) {
platform = getOSInsideWeb();
}
String getOSInsideWeb() {
final userAgent = window.navigator.userAgent.toString().toLowerCase();
if( userAgent.contains("iphone")) return "ios";
if( userAgent.contains("ipad")) return "ios";
if( userAgent.contains("android")) return "Android";
return "Web";
}
There is a code written Below to get OS/web where flutter is running...
if(kIsWeb)
return Text("It's web");
else if(Platform.isAndroid){
return Text("it's Android"); }
you can use "kIsWeb" to do the job
if(kIsWeb){
// DO SOMETHING
}else{
// DO ANOTHER THING
}
Just use this package get: ^4.6.5
import 'package:get/get.dart';
You can use this to find web
bool isWeb = GetPlatform.isWeb;
For Others
bool isMobile = GetPlatform.isMobile;
bool isAndroid = GetPlatform.isAndroid;
bool isiOS = GetPlatform.isIOS;
bool isWeb = GetPlatform.isWeb;
bool isWindows = GetPlatform.isWindows;
bool isMac = GetPlatform.isMacOS;
bool isLinux = GetPlatform.isLinux;
bool isFusia = GetPlatform.isFuchsia;
bool isDesktop = GetPlatform.isDesktop;

UNITY (Android) NOT ASKING FOR PERMISSION

My app have some problem!
My app have three Scene , One of them using ARCore(ARScene), another one using camera device(CamScene). Problem is if i don't run ARScene , CamScene also does not work( NOT ASKING FOR PERMISSION)!
I create new app only use camera device, and it work (it ask for permission when begin run app)
public IEnumerator LoadAsync(SceneType levelNum)
{
yield return null;
StartOperation(levelNum);
yield return new WaitForSeconds(0.5f);
while (DoneLoading() == false)
{
Debug.Log("In while");
}
if (loadSceneMode == LoadSceneMode.Additive)
UnityEngine.SceneManagement.SceneManager.UnloadSceneAsync(currentScene.name);
else
operation.allowSceneActivation = true;
yield return new WaitForSeconds(0.2f);
//effect.Hiden();
}
private bool DoneLoading()
{
return (loadSceneMode == LoadSceneMode.Additive && operation.isDone) || (loadSceneMode == LoadSceneMode.Single && operation.progress >= 0.9f);
}
private void StartOperation(SceneType levelNum)
{
operation = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(levelNum.ToString(), loadSceneMode);
operation.allowSceneActivation = false;
}
public void LoadSceneAsync(SceneType sceneType)
{
effect.Show();
StartCoroutine(LoadAsync(sceneType));
}
This is my load scene, i build this app for android device, when i run with editor my app word normal, no error messages!!

Native sharing requires the Facebook for Android application

i have installed Facebook Android app,but my code
public void shareUsingNativeDialog() {
if (playerChoice == INVALID_CHOICE || computerChoice == INVALID_CHOICE) {
ShareContent content = getLinkContent();
// share the app
if (shareDialog.canShow(content, ShareDialog.Mode.NATIVE)) {
shareDialog.show(content, ShareDialog.Mode.NATIVE);
} else {
showError(R.string.native_share_error);
}
} else {
ShareContent content = getThrowActionContent();
if (shareDialog.canShow(content, ShareDialog.Mode.NATIVE)) {
shareDialog.show(content, ShareDialog.Mode.NATIVE);
} else {
showError(R.string.native_share_error);
}
}
}
it's tip Native sharing requires the Facebook for Android application.
so why??
No need, default mode of ShareDialog will be Mode.AUTOMATIC. It will check if the facebook app is installed.