I want to use a timer in my C# monodroid program for android 2.2, but it doesnt work.
here is my code:
using System;
using System.Timers;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Util;
namespace MonoAndroidApplication1
{
[Activity(Label = "MonoAndroidApplication1", MainLauncher = true, Icon=drawable/icon")]
public class Activity1 : Activity
{
int count = 1;
TextView txv1;
System.Timers.Timer t1;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
txv1 = FindViewById<TextView>(Resource.Id.txv1);
DateTime dt = DateTime.Now;
txv1.Text = dt.ToShortTimeString();
t1 = new System.Timers.Timer(200);
t1.Elapsed += new ElapsedEventHandler(OnTimeEvent);
t1.Interval = 200;
t1.Enabled = true;
t1.Start();
}
private void OnTimeEvent(object source, ElapsedEventArgs e)
{
txv1.Text = count.ToString();
count++;
}
}
}
please help me.
System.Timers.Timer will be running on a separate (non-UI) thread. Consequently, your OnTimeEvent() method is incorrect, as it will be updating a UI instance (txv1) from a non-UI thread.
You need to use Activity.RunOnUiThread() to update the UI from a background thread:
private void OnTimeEvent(object source, ElapsedEventArgs e)
{
RunOnUiThread(delegate {
txv1.Text = count.ToString ();
count++;
});
}
Related
###################################
# MainActivity.cs
###################################
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Content;
using System.Collections.Generic;
using Android.Net.Wifi;
using System.Text;
using Java.Lang;
using Xamarin.Forms;
using StringBuilder = System.Text.StringBuilder;
using Menu = Android.Views.Menu;
using System.Threading.Tasks;
using System.Threading;
[assembly: Xamarin.Forms.Dependency(typeof(App1.Droid.Wifi))]
namespace App1.Droid
{
[Activity(Label = "App1", Icon = "#mipmap/icon", Theme = "#style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize )]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
public class Wifi : IWifi
{
private Context context = null;
public Wifi()
{
this.context = Android.App.Application.Context;
}
public async Task<IEnumerable<string>> GetAvailableNetworksAsync()
{
IEnumerable<string> availableNetworks = null;
// Get a handle to the Wifi
var wifiMgr = (WifiManager)context.GetSystemService(Context.WifiService);
var wifiReceiver = new WifiReceiver(wifiMgr);
await Task.Run(() =>
{
// Start a scan and register the Broadcast receiver to get the list of Wifi Networks
context.RegisterReceiver(wifiReceiver, new IntentFilter(WifiManager.ScanResultsAvailableAction));
availableNetworks = wifiReceiver.Scan();
});
return availableNetworks;
}
[BroadcastReceiver(Enabled = true, Exported = false)]
class WifiReceiver : BroadcastReceiver
{
private WifiManager wifi;
private List<string> wifiNetworks;
private AutoResetEvent receiverARE;
private Timer tmr;
private const int TIMEOUT_MILLIS = 10000; // 20 seconds timeout
public WifiReceiver()
{
}
public WifiReceiver(WifiManager wifi)
{
this.wifi = wifi;
wifiNetworks = new List<string>();
receiverARE = new AutoResetEvent(false);
}
public IEnumerable<string> Scan()
{
tmr = new Timer(Timeout, null, TIMEOUT_MILLIS, System.Threading.Timeout.Infinite);
wifi.StartScan();
receiverARE.WaitOne();
return wifiNetworks;
}
public override void OnReceive(Context context, Intent intent)
{
IList<ScanResult> scanwifinetworks = wifi.ScanResults;
foreach (ScanResult wifinetwork in scanwifinetworks)
{
wifiNetworks.Add(wifinetwork.Ssid);
}
receiverARE.Set();
}
private void Timeout(object sender)
{
// NOTE release scan, which we are using now, or we throw an error?
receiverARE.Set();
}
}
}
}
###################################
# MainPage.xaml.cs
###################################
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace App1
{
public interface IWifi
{
Task<IEnumerable<string>> GetAvailableNetworksAsync();
}
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private async void btn1_Clicked(object sender, EventArgs e)
{
IEnumerable<string> _wifiService = null;
_wifiService = await DependencyService.Get<IWifi>().GetAvailableNetworksAsync();
txtlog.Text = _wifiService.Count().ToString();
wifilist.ItemsSource = _wifiService;
//Device.StartTimer(new TimeSpan(0, 0, 60), () =>
//{
// // do something every 60 seconds
// Device.BeginInvokeOnMainThread(async () =>
// {
// IEnumerable<string> _wifiService = null;
// _wifiService = await DependencyService.Get<IWifi>().GetAvailableNetworksAsync();
// wifilist.ItemsSource = _wifiService;
// //txtlog.Text = _wifiService.Count<int>();
// //editLog.add
// });
// return true; // runs again, or false to stop
//});
//IEnumerable<string> test1 = new IEnumerable<string>;
//wifilist.
//ListView listview = FindViewByID<ListView>(Resources.Id)
//listview.setAdapter(adapter);
//List<string> lstItems;
//for (int i = 0; i < 10; i ++)
//{
//}
//wifilist.ItemsSource = lstItems;
}
}
}
###################################
# MainPage.xaml.cs
###################################
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.app1" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
<application android:label="App1.Android" android:theme="#style/MainTheme"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>
I tried following the example, but I can't get the wifi list. What am I doing wrong?
Here is a link to the example I referenced.
referenced example
I plan to use Android 10 or higher.
And I'm going to test it by putting Android OS on the Raspberry Pi board in the development environment.
From the code, I understood that you are trying to get the list of available wifi connections.
I have tried your code and I am able to get the wifi list.
Please check whether you have done below things, if not please do
enable device location
allow location permission for your app (either from your code or from device settings)
Hope this helps!
I would like to override the On/Off text of a switch using an Effect rather than a custom renderer.
In Android, I have the following code:
protected override void OnAttached()
{
try
{
if (Control is Android.Widget.Switch control)
{
control.TextOn = "Yes";
control.TextOff = "No";
}
}
OnAttached executes as expected but 'Control' is not an Android.Widget.Switch control but of a related type, e.g. 'android.support.v7.widget.SwitchCompat'. How can I make the code recognize that it should update the text in this case?
Do you want to achieve the result like following effect?
You can achieve it like following code.
using Android.Runtime;
using Android.Support.V7.Widget;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(SwitchDemo.Droid.ClickEffect), nameof(SwitchDemo.Droid.ClickEffect))]
namespace SwitchDemo.Droid
{
public class ClickEffect : PlatformEffect
{
protected override void OnAttached()
{
// throw new NotImplementedException();
if (Control is SwitchCompat control)
{
control.ShowText = true;
control.TextOn = "Yes";
control.TextOff = "No";
}
}
protected override void OnDetached()
{
//throw new NotImplementedException();
}
}
}
Here is PCL code.
ClickEffect.cs
public class ClickEffect: RoutingEffect
{
public ClickEffect() : base($"MyCompany.{nameof(ClickEffect)}")
{
}
}
Use it in xaml.
<Switch>
<Switch.Effects>
<local:ClickEffect/>
</Switch.Effects>
</Switch>
I have AlertDialog. Bu default the alertDialog is like this:
I want to change the color of OK button and add border color. Is there a solution for this customization .
This is my code:
await Application.Current.MainPage.DisplayAlert("Alert!", " This is DisplayAlert", "OK");
You could use [DependencyService] to call native AlerDialog and change it in specific platforms,here is a simple sample that change the color of the action button .
in Forms ,create the interface:
public interface IPopUp
{
void Popup(string title, string message,Color titleColor,Color messageColor,Color OKButtonColor ,EventHandler handler);
}
in iOS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App10.iOS;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using App10;
[assembly: Dependency(typeof(PopupImplemention))]
namespace App10.iOS
{
public class PopupImplemention : IPopUp
{
public void Popup(string title, string message, Color titleColor, Color messageColor, Color OKButtonColor, EventHandler handler)
{
UIAlertController alertController = UIAlertController.Create(title,message,UIAlertControllerStyle.Alert);
var firstAttributes = new UIStringAttributes
{
ForegroundColor =titleColor.ToUIColor(),
};
var secondAttributes = new UIStringAttributes
{
ForegroundColor =messageColor.ToUIColor(),
};
alertController.SetValueForKey(new NSAttributedString(title, firstAttributes), new NSString("attributedTitle"));
alertController.SetValueForKey(new NSAttributedString(message, secondAttributes), new NSString("attributedMessage"));
UIAlertAction cancelAction = UIAlertAction.Create("Cancel",UIAlertActionStyle.Cancel,null);
UIAlertAction okAction = UIAlertAction.Create("OK", UIAlertActionStyle.Default,(sender)=> { handler?.Invoke(sender, new EventArgs()) ; });
okAction.SetValueForKey(OKButtonColor.ToUIColor(), new NSString("_titleTextColor"));
alertController.AddAction(cancelAction);
alertController.AddAction(okAction);
var currentViewController = topViewControllerWithRootViewController(UIApplication.SharedApplication.Delegate.GetWindow().RootViewController);
currentViewController.PresentViewController(alertController,true,null);
}
UIViewController topViewControllerWithRootViewController(UIViewController rootViewController)
{
if (rootViewController is UITabBarController)
{
UITabBarController tabBarController = (UITabBarController)rootViewController;
return topViewControllerWithRootViewController(tabBarController.SelectedViewController);
}
else if (rootViewController is UINavigationController)
{
UINavigationController navigationController = (UINavigationController)rootViewController;
return topViewControllerWithRootViewController(navigationController.VisibleViewController);
}
else if (rootViewController.PresentedViewController != null)
{
UIViewController presentedViewController = rootViewController.PresentedViewController;
return topViewControllerWithRootViewController(presentedViewController);
}
else
{
return rootViewController;
}
}
}
}
in Android
in MainActivity
public static MainActivity Intance;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Intance = this;
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
using Xamarin.Forms;
using xxx;
using xxx.Droid;
using Android;
using System;
using Xamarin.Forms.Platform.Android;
using Android.Support.V7.App;
using Android.Text;
[assembly: Dependency(typeof(PopupImplemention))]
namespace xxx.Droid
{
public class PopupImplemention : IPopUp
{
public void Popup(string title, string message, Color titleColor, Color messageColor, EventHandler handler)
{
// because html.string could not support format string , so you need to set the color directly in the string with a static value
Android.Support.V7.App.AlertDialog.Builder alert = new Android.Support.V7.App.AlertDialog.Builder(MainActivity.Intance);
alert.SetTitle(title);
alert.SetMessage(message);
alert.SetPositiveButton(Html.FromHtml("<font color='#0000ff'>OK</font>"), (senderAlert, args) =>
{
handler?.Invoke(senderAlert, args);
});
Android.Support.V7.App.AlertDialog dialog = alert.Create();
dialog.Show();
}
}
}
And call it in forms
DependencyService.Get<IPopUp>().Popup("Title","xxxxxxxxxxxx",Color.Red,Color.Blue,Color.Green,(sen,args)=> {
// handle the logic when clikc the OK button
});
You can use cross platform libraries like this one: https://github.com/aritchie/userdialogs
You will need to create a styles.xml and configure it for Android that way. There is currently no way to customize that native control through any of the Xamarin.Forms API's as far as I am aware.
Example:
<style name="AppCompatAlertDialogStyle" parent="Theme.AppCompat.Dialog.Alert">
<item name="colorAccent">#c7ac56</item>
<item name="android:textColor">#c7ac56</item>
<item name="android:background">#5c8487</item>
</style>
Here is a good tutorial on an example on how to do this: http://gmariotti.blogspot.com/2015/04/a-material-styled-alertdialog.html
If you are using Xamarin Android you probably could also hook into the AlertDialog.Builder and set the proprieties pro grammatically: https://developer.android.com/reference/android/app/AlertDialog.Builder
Is there anything possible to customize the radius of Entry to having a slightly rounded corner?
You can use Custom Renderer in xamarin.forms
in iOS
//...
using App11;
using App11.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyiOSEntry))]
namespace App11.iOS
{
public class MyiOSEntry:EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Layer.MasksToBounds = true;
Control.Layer.CornerRadius = 10; //set the rounded corner
Control.Layer.BorderColor = UIColor.Red.CGColor;
Control.Layer.BorderWidth = 3;
}
}
}
}
in Android
creat a xml file in the folder Resource->drawable edit_text_style.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:shape="rectangle">
<solid
android:color="#ffffff" />
<corners
android:radius="10dp" />
<stroke
android:width="2dp"
android:color="#3bbdfa" />
</shape>
</item>
in Custom Renderer
using Android.Support.V4.Content.Res;
using App11;
using App11.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyAndriodEntry))]
namespace App11.Droid
{
public class MyAndriodEntry:EntryRenderer
{
public MyAndriodEntry(Context context):base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
Control.SetBackground(ResourcesCompat.GetDrawable(Resources, Resource.Drawable.edit_text_style, null) );
}
}
}
}
in UWP
create a folder named Styles and add a new item as type Resource Dictionary and name it Dictionary1.xaml
in Dictionary1.xaml put this code for a rounded Textbox .
in Custom Renderer
using App11;
using App11.UWP;
using Windows.UI.Xaml.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;
[assembly: ExportRenderer(typeof(MyEntry), typeof(MyUWPEntry))]
namespace App11.UWP
{
public class MyUWPEntry:EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if(Control!=null)
{
Control.Style = (Windows.UI.Xaml.Style)App11.UWP.App.Current.Resources["StyleRoundedTextBox"];
}
}
}
}
how do I changed this style and how do I create this code ?
It's simple , in msdn.com search for "objectName" default style in uwp then you will find default style for the object you need . change it in the way you want and add it to application resources directly or link it (like what I did here) then load your style in CustomRenderer
for more detail about UWP yo can refer here
in Forms
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace App11
{
public class MyEntry : Entry
{
public MyEntry()
{
}
}
}
in xxx.cs file
Content = new StackLayout
{
Children = {
new MyEntry {Text = "In Shared Code",}
},
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
For Windows app you can customize an entry using a renderer.
public class CustomEntryRenderer : ViewRenderer<CustomEntry, TextBox>
{
protected override void OnElementChanged(ElementChangedEventArgs<CustomEntry> e)
{
base.OnElementChanged(e);
var textBox = new TextBox();
textBox.BorderThickness = new Windows.UI.Xaml.Thickness(1);
textBox.BorderBrush = new SolidColorBrush(GetSolidColorBrush("#444444").Color);
textBox.CornerRadius = new Windows.UI.Xaml.CornerRadius(10);
this.SetNativeControl(textBox);
}
public SolidColorBrush GetSolidColorBrush(string hex)
{
hex = hex.Replace("#", string.Empty);
byte r = (byte)(Convert.ToUInt32(hex.Substring(0, 2), 16));
byte g = (byte)(Convert.ToUInt32(hex.Substring(2, 2), 16));
byte b = (byte)(Convert.ToUInt32(hex.Substring(4, 2), 16));
SolidColorBrush myBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(255, r, g, b));
return myBrush;
}
}
Holy shmoley it's not that hard.
Unless I'm missing something, just wrap it in a Frame that has IsClippedToBounds set to true and then put a corner radius on the frame.
Maybe there's some reason that's not a good solution, I guess, but it's one I use a lot.
I just want to know about the banner advertisements supported with Xamarin.Forms without any patch or loophole. Is there any advertisement provider who are providing their SDKs with the Xamarin.Forms?
Thanks in advance.
There are both SDK and step-by-step examples for Google AdMob for Xamarin.Android. You are going to need the Xamarin.GooglePlaySerives.Ads nuget.
I use it to show ads in my Xamarin.Forms app published at Google Play.
Here is the sample code for the android part of your application:
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Android.Support.V7.App;
using Android.Gms.Ads;
using Android;
namespace AdMobExample
{
[Activity (Label = "#string/app_name", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
protected AdView mAdView;
protected InterstitialAd mInterstitialAd;
protected Button mLoadInterstitialButton;
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
SetContentView (Resource.Layout.activity_main);
mAdView = FindViewById<AdView> (Resource.Id.adView);
var adRequest = new AdRequest.Builder ().Build ();
mAdView.LoadAd (adRequest);
mInterstitialAd = new InterstitialAd (this);
mInterstitialAd.AdUnitId = GetString (Resource.String.test_interstitial_ad_unit_id);
mInterstitialAd.AdListener = new AdListener (this);
mLoadInterstitialButton = FindViewById<Button> (Resource.Id.load_interstitial_button);
mLoadInterstitialButton.SetOnClickListener (new OnClickListener (this));
}
protected void RequestNewInterstitial ()
{
var adRequest = new AdRequest.Builder ().Build ();
mInterstitialAd.LoadAd (adRequest);
}
protected void BeginSecondActivity ()
{
var intent = new Intent (this, typeof(SecondActivity));
StartActivity (intent);
}
protected override void OnPause ()
{
if (mAdView != null) {
mAdView.Pause ();
}
base.OnPause ();
}
protected override void OnResume ()
{
base.OnResume ();
if (mAdView != null) {
mAdView.Resume ();
}
if (!mInterstitialAd.IsLoaded) {
RequestNewInterstitial ();
}
}
protected override void OnDestroy ()
{
if (mAdView != null) {
mAdView.Destroy ();
}
base.OnDestroy ();
}
class AdListener : Android.Gms.Ads.AdListener
{
MainActivity that;
public AdListener (MainActivity t)
{
that = t;
}
public override void OnAdClosed ()
{
that.RequestNewInterstitial ();
that.BeginSecondActivity ();
}
}
class OnClickListener : Java.Lang.Object, View.IOnClickListener
{
MainActivity that;
public OnClickListener (MainActivity t)
{
that = t;
}
public void OnClick (View v)
{
if (that.mInterstitialAd.IsLoaded) {
that.mInterstitialAd.Show ();
} else {
that.BeginSecondActivity ();
}
}
}
}
}
There is also a ste-by-step guide for AdMob ads for Xamarin.iOS:
using Google.MobileAds;
...
const string intersitialId = "<Get your ID at google.com/ads/admob>";
Interstitial adInterstitial;
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
CreateAndRequestInterstitial ();
}
public void AfterSomeTime ()
{
if (adInterstitial.IsReady)
adInterstitial.PresentFromRootViewController (navController);
}
void CreateAndRequestInterstitial ()
{
adInterstitial = new Interstitial (intersitialId);
adInterstitial.ScreenDismissed += (sender, e) => {
// Interstitial is a one time use object. That means once an interstitial is shown, HasBeenUsed
// returns true and the interstitial can't be used to load another ad.
// To request another interstitial, you'll need to create a new Interstitial object.
adInterstitial.Dispose ();
adInterstitial = null;
CreateAndRequestInterstitial ();
};
var request = Request.GetDefaultRequest ();
// Requests test ads on devices you specify. Your test device ID is printed to the console when
// an ad request is made. GADBannerView automatically returns test ads when running on a
// simulator. After you get your device ID, add it here
request.TestDevices = new [] { Request.SimulatorId.ToString () };
adInterstitial.LoadRequest (request);
}