i got a java project about floating view from web. i try to translate it to monodroid, but i fail, because on function ,i don't know how to write in monodroid .
java code is in http://www.xsmile.net/file/FloatViewDemo.rar
namespace MonoFloatView
{
[Activity(Label = "MonoFloatView", MainLauncher = true, Icon = "#drawable/icon")]
public class MyFloatViewActivity : Activity
{
private IWindowManager wm = null;
private WindowManagerLayoutParams wmParams = null;
private MyFloatView myFV = null;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
createView();
// Create your application here
}
private void createView()
{
//myFV = new MyFloatView(getApplicationContext()); //java
myFV = new MyFloatView(ApplicationContext);
myFV.SetImageResource(Resource.Drawable.Icon);
//wm = (WindowManager)getApplicationContext().getSystemService("window");
//http://stackoverflow.com/questions/13634835/monodroid-screen-dimensions
//i get some tip from url above.
wm = GetSystemService(Activity.WindowService).JavaCast<IWindowManager>();
//i don't know the getApplication, how to write in monodroid?
wmParams = ((MyApplication)getApplication()).getMywmParams();
wmParams.Type = LayoutParams.TYPE_PHONE;
wmParams.Format = PixelFormat.RGBA_8888;
wmParams.Flags = LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE;
wmParams.Gravity = Gravity.LEFT | Gravity.TOP;
wmParams.X = 0;
wmParams.Y = 0;
wmParams.Width = 40;
wmParams.Height = 40;
wm.AddView(myFV, wmParams);
}
public override void onDestroy()
{
base.OnDestroy();
wm.RemoveView(myFV);
}
}
}
If you're in an Activity, you should be able to use:
this.Application
Related
I updated Xamarin.Forms to the latest version 4.8.0.1560. I managed to bind the timepicker on both Android and iOS. The only discrepancy with my application is when the user use 24 time setting in their phone the time picker "stuck" in 12 hour format.
In order to do that I created a custom renderer in iOS
[assembly: ExportRenderer(typeof(TimePicker), typeof(TimeRenderer))]
namespace TabsApp.iOS.custom.renderers
{
public class TimeRenderer : TimePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
{
base.OnElementChanged(e);
int hours = Element.Time.Hours;
int minutes = Element.Time.Minutes;
if (!Is12Hours())
{
var timePicker = (UIDatePicker)Control.InputView;
timePicker.Locale = new NSLocale("no_nb");
}
string format = Is12Hours()?"hh:mm tt":"HH:mm";
DateTime currTime = DateTime.Now;
currTime = new DateTime(currTime.Year,currTime.Month,currTime.Day,hours,minutes,0);
Control.Text = currTime.ToString(format);
}
private bool Is12Hours()
{
var dateFormatter = new NSDateFormatter();
dateFormatter.DateStyle = NSDateFormatterStyle.None;
dateFormatter.TimeStyle = NSDateFormatterStyle.Short;
var dateString = dateFormatter.ToString(NSDate.Now);
var isTwelveHourFormat =
dateString.Contains(dateFormatter.AMSymbol) ||
dateString.Contains(dateFormatter.PMSymbol);
return isTwelveHourFormat;
}
}
}
OnElementChanged is being called once the application is loaded, and it will show the correct time format. When you change the time, this callback is not being called. Do I need to override other functions?
At the end I found the answer from xamarin forms. You will need to change/add custom timepicker renderer.
This is the code
[assembly: ExportRenderer(typeof(TimePicker), typeof(TimeRenderer))]
namespace TabsApp.iOS.custom.renderers
{
public class TimeRenderer : TimePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
{
base.OnElementChanged(e);
if (Is12Hours())
{
Element.Format = "hh:mm tt";
}
else
{
var timePicker = (UIDatePicker)Control.InputView;
timePicker.Locale = new NSLocale("no_nb");
Element.Format = "HH:mm";
}
}
private bool Is12Hours()
{
var dateFormatter = new NSDateFormatter();
dateFormatter.DateStyle = NSDateFormatterStyle.None;
dateFormatter.TimeStyle = NSDateFormatterStyle.Short;
var dateString = dateFormatter.ToString(NSDate.Now);
var isTwelveHourFormat =
dateString.Contains(dateFormatter.AMSymbol) ||
dateString.Contains(dateFormatter.PMSymbol);
return isTwelveHourFormat;
}
}
}
I have a WebView that contains an iframe (an HTML element). this iframe has a Peertube video plyaer, I pass &autoplay=1 to that iframe and it works good on android, iPad and browser, but on iPhone the video can not be autoplayed.
I tried custom render with WKWebView with this code:
class FullScreenEnabledWebViewRenderer : WkWebViewRenderer
{
WKUserContentController userController;
public FullScreenEnabledWebViewRenderer() : this(new WKWebViewConfiguration() { MediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypes.None, AllowsInlineMediaPlayback = true, MediaPlaybackRequiresUserAction = false, RequiresUserActionForMediaPlayback = false })
{
}
public FullScreenEnabledWebViewRenderer(WKWebViewConfiguration config) : base(config)
{
config.AllowsInlineMediaPlayback = true;
config.AllowsAirPlayForMediaPlayback = true;
config.AllowsPictureInPictureMediaPlayback = true;
config.MediaPlaybackAllowsAirPlay = true;
config.MediaPlaybackRequiresUserAction = false;
config.RequiresUserActionForMediaPlayback = false;
config.MediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypes.None;
}
}
and still does not work.
Can you help me with that please.
Webview in iOS couldn't support iframe very well . So it could better to use <video> like
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = #"<html><body><video width='300' height='500' muted='muted' controls autoplay='autoplay'><source src='https://ia800201.us.archive.org/12/items/BigBuckBunny_328/BigBuckBunny_512kb.mp4' type='video/mp4'></video></body></html>";
webview.Source = htmlSource;
If it still could not auto play in iOS , we could invoked JS to play it .
using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using App4;
using App4.iOS;
using WebKit;
using ObjCRuntime;
[assembly: ExportRenderer(typeof(WebView), typeof(FullScreenEnabledWebViewRenderer))]
namespace App4.iOS
{
public class FullScreenEnabledWebViewRenderer: ViewRenderer<WebView, WKWebView>
{
WKWebView wkWebView;
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
var config = new WKWebViewConfiguration();
config.AllowsInlineMediaPlayback = true;
config.AllowsAirPlayForMediaPlayback = true;
config.AllowsPictureInPictureMediaPlayback = true;
config.MediaPlaybackAllowsAirPlay = true;
config.MediaPlaybackRequiresUserAction = false;
config.RequiresUserActionForMediaPlayback = false;
config.MediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypes.None;
wkWebView = new WKWebView(Frame, config);
wkWebView.NavigationDelegate = new WkWebviewPolicy();
SetNativeControl(wkWebView);
}
}
}
public class WkWebviewPolicy : WKNavigationDelegate
{
public override void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, WKWebpagePreferences preferences, [BlockProxy(typeof(NIDActionArity2V120))] Action<WKNavigationActionPolicy, WKWebpagePreferences> decisionHandler)
{
decisionHandler.Invoke(WKNavigationActionPolicy.Allow, preferences);
//base.DecidePolicy(webView, navigationAction, preferences, decisionHandler);
}
public override void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
base.DidFinishNavigation(webView, navigation);
var JSstr = #"var videos = document.querySelectorAll('video'); for (var i = videos.length - 1; i >= 0; i--) { var ivideo = videos[i]; ivideo.setAttribute('webkit-playsinline','\'); ivideo.play(); };";
webView.EvaluateJavaScript(JSstr,null);
}
}
}
I want to binding a variable to a label which as a children in a grid.
the variable changed with a timer event.pls check my code help me found out where i am wrong.I can see the label init value is 0,but it won't update when the variable do.
public class DevicePage : ContentPage
{
IDevice device;
Label testLb = new Label();
System.Timers.Timer testtimer;
Grid gridView;
byte testt { get; set; } = 0;
GetSendData communicate;
private byte _maintext;
public byte MainText
{
get
{
return _maintext;
}
set
{
_maintext = value;
OnPropertyChanged();
}
}
public DevicePage(IDevice currDevice)
{
device = currDevice;
this.Title = "Status";
testtimer = new System.Timers.Timer();
testtimer.Interval = 1000;
testtimer.Elapsed += OnTimedEvent;
testtimer.Enabled = true;
gridView = new Grid();
testLb.Text = testt.ToString();
testLb.SetBinding(Label.TextProperty, ".");
testLb.BindingContext = MainText;
gridView.Children.Add(testLb, 0, 0);
this.Content = gridView;
}
private void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs e)
{
MainText += 1;
}
after I implement INotifyPropertyChanged,testLb won't update either.But I change testLb.SetBinding(Label.TextProperty, "."); testLb.BindingContext = MainText; to testLb.SetBinding(Label.TextProperty, "MainText"); testLb.BindingContext = this; It works!
I am developing an application with MVVM Cross, Mvvm Cross Forms, Xamarin Forms and Grail KIT. In IOS it works perfectly. But when I start it on Android I get an error without trace and I do not know how to solve it.
After the OnStart method is executed. This exception occurs:
The step-by-step execution of the debugger does not allow me to go beyond this method.
This is the code of the MvxFormsApplication.
public partial class App : MvxFormsApplication
{
private void ConfigLocale()
{
if (Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.Android )
{
Debug.WriteLine("Get Culture Info ...");
var ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();
Debug.WriteLine(ci.ToString());
AppResources.Culture = ci; // set the RESX for resource localization
DependencyService.Get<ILocalize>().SetLocale(ci); // set the Thread for locale-aware methods
}
}
public App()
{
ConfigLocale();
InitializeComponent();
}
void OnAuthenticatedUserMessage(AuthenticatedUserMessage authenticatedUserMessage)
{
Debug.WriteLine("OnAuthenticatedUserMessage ...");
var deviceGroupsService = Mvx.Resolve<IDeviceGroupsService>();
// save token
deviceGroupsService.saveDevice(CrossDeviceInfo.Current.Id, Settings.FcmToken).Subscribe(device => {
Debug.WriteLine(String.Format("Device Saved: {0}", device.ToString()));
});
}
void OnExceptionOcurredMessage(ExceptionOcurredMessage exceptionOcurredMessage)
{
Debug.WriteLine("OnExceptionOcurredMessage ...");
var userDialogs = Mvx.Resolve<IUserDialogs>();
userDialogs.ShowError(AppResources.Global_ErrorOcurred);
if (exceptionOcurredMessage.Ex != null)
exceptionOcurredMessage.Ex.Track();
}
protected override void OnStart()
{
Debug.WriteLine("Forms App OnStart ...");
var messenger = Mvx.Resolve<IMvxMessenger>();
// subscribe to Authenticated User Message
messenger.Subscribe<AuthenticatedUserMessage>(OnAuthenticatedUserMessage);
// subscribe to Exception Ocurred Message
messenger.Subscribe<ExceptionOcurredMessage>(OnExceptionOcurredMessage);
//Handling FCM Token
CrossFirebasePushNotification.Current.OnTokenRefresh += (s, p) =>
{
Debug.WriteLine($"TOKEN REC: {p.Token}");
Settings.FcmToken = p.Token;
};
Debug.WriteLine($"TOKEN: {CrossFirebasePushNotification.Current.Token}");
Settings.FcmToken = CrossFirebasePushNotification.Current.Token;
}
}
}
The application starts with a SplashScreen that I expose below:
using System;
using Android.App;
using Android.Content.PM;
using MvvmCross.Droid.Views;
using MvvmCross.Forms.Droid;
using Xamarin.Forms;
namespace Bullytect.Droid
{
[Activity(
Name = "com.usal.bisite.bulltect.SplashScreen",
Label = "Bulltect"
, MainLauncher = true
, Icon = "#mipmap/ic_launcher"
, Theme = "#style/Theme.Splash"
, NoHistory = true
, ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreen : MvxSplashScreenActivity
{
public override void InitializationComplete()
{
StartActivity(typeof(MvxFormsApplicationActivity));
}
protected override void OnCreate(Android.OS.Bundle bundle)
{
Forms.Init(this, bundle);
// Leverage controls' StyleId attrib. to Xamarin.UITest
Forms.ViewInitialized += (object sender, ViewInitializedEventArgs e) => {
if (!string.IsNullOrWhiteSpace(e.View.StyleId))
{
e.NativeView.ContentDescription = e.View.StyleId;
}
};
base.OnCreate(bundle);
}
}
}
The Activity MvxFormsApplicationActivity is then executed by the Application Application
namespace Bullytect.Droid
{
[Activity(
Name = "com.usal.bisite.bulltect.MvxFormsApplicationActivity",
Label = "bulltect",
Icon = "#mipmap/ic_launcher",
Theme = "#style/AppTheme",
MainLauncher = false,
LaunchMode = LaunchMode.SingleTask,
ScreenOrientation = ScreenOrientation.Portrait
)]
public class MvxFormsApplicationActivity : FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
try
{
ToolbarResource = Resource.Layout.Toolbar;
TabLayoutResource = Resource.Layout.Tabs;
base.OnCreate(bundle);
Forms.Init(this, bundle);
PullToRefreshLayoutRenderer.Init();
XFGloss.Droid.Library.Init(this, bundle);
//Initializing FFImageLoading
CachedImageRenderer.Init();
UserDialogs.Init(this);
GrialKit.Init(this, "Bullytect.Droid.GrialLicense");
FormsHelper.ForceLoadingAssemblyContainingType(typeof(UXDivers.Effects.Effects));
var formsPresenter = (MvxFormsPagePresenter)Mvx.Resolve<IMvxAndroidViewPresenter>();
LoadApplication(formsPresenter.FormsApplication);
//FirebasePushNotificationManager.ProcessIntent(Intent);
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine("**BullTect LAUNCH EXCEPTION**\n\n" + e);
}
}
public override void OnConfigurationChanged(Android.Content.Res.Configuration newConfig)
{
base.OnConfigurationChanged(newConfig);
DeviceOrientationLocator.NotifyOrientationChanged();
}
}
}
These are all the packages I have installed:
Hope someone can help me.
I am working on an app that creates a mock location. Now, after I start it - everything seems to work here - and then go into maps, I always get set right to where I actually am - not where my fake coordinates are. So im thinking, this is due to my program immediately stopping as soon as i push it into the background of the android phone im debugging with.
1) Would u say so too?
2) So, how do I get my program to continue mocking the location, even though its in the background? I already set up a timer, that mocks a new location every 5 seconds. Here is my main activity (which happens to be a bit long, excuse me..)
Any help would be AWESOME!
public static double GlobalLongitude = 0.0; // global, cause i need to pull string from void method
public static double GlobalLatitude = 0.0;
static readonly string TAG = "X:" + typeof(Activity1).Name;
Location _currentLocation;
LocationManager _locationManager;
string _locationProvider;
TextView _locationText;
static TextView txtAdded;
static Button btnMain;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
_locationText = FindViewById<TextView>(Resource.Id.GpsTest);
txtAdded = FindViewById<TextView>(Resource.Id.AddedCoordinates);
btnMain = FindViewById<Button>(Resource.Id.startbutton);
CountDown();
InitializeLocationManager();
} // start here! :D
private void CountDown()
{
System.Timers.Timer timer = new System.Timers.Timer();
timer.Interval = 5000;
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}
private void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs e) // txt.Added is here!
{
txtAdded.Text = SetMockLocation();
}
public void OnLocationChanged(Location location)
{
string test = "Null";
string test2 = "Null";
bool waitforresult = false;
_currentLocation = location;
if (_currentLocation == null)
{
_locationText.Text = "Unable to determine your location. Try again in a short while.";
}
else
{
_locationText.Text = string.Format("Unchanged: {0:f5} {1:f5}", _currentLocation.Latitude, _currentLocation.Longitude);// hh: 53, 10
//das her wird ausgegeben bei button.click
test = string.Format("{0:f5}", _currentLocation.Latitude); // to format
test2 = string.Format("{0:f5}", _currentLocation.Longitude);
double.TryParse(test, out GlobalLatitude);
double.TryParse(test2, out GlobalLongitude);
if (test != "Null")
{
waitforresult = true;
}
if (waitforresult == true)
{
Add700ToCoordinates();
}
}
} // ausgabe der koordinaten
void InitializeLocationManager()
{
_locationManager = (LocationManager)GetSystemService(LocationService);
Criteria criteriaForLocationService = new Criteria
{
Accuracy = Accuracy.Fine
};
IList<string> acceptableLocationProviders = _locationManager.GetProviders(criteriaForLocationService, true);
if (acceptableLocationProviders.Any())
{
_locationProvider = acceptableLocationProviders.First();
}
else
{
_locationProvider = string.Empty;
}
Log.Debug(TAG, "Using " + _locationProvider + ".");
}
protected override void OnResume()
{
base.OnResume();
_locationManager.RequestLocationUpdates(_locationProvider, 0, 0, this);
Log.Debug(TAG, "Listening for location updates using " + _locationProvider + ".");
}
protected override void OnPause()
{
base.OnPause();
_locationManager.RemoveUpdates(this);
Log.Debug(TAG, "No longer listening for location updates.");
}
public static double Add700ToCoordinates()
{
string xy = "Null";
double FinalCoordinates = (GlobalLatitude + 0.01065);
btnMain.Click += (sender, e) =>
{
xy = FinalCoordinates.ToString();
xy = xy + " " + GlobalLongitude.ToString();
};
return FinalCoordinates;
}
public static string SetMockLocation()
{
var context = Android.App.Application.Context;
var locationManager = context.GetSystemService(LocationService) as LocationManager;
locationManager.AddTestProvider("Test09", false, false, false, false, false, false, false, Power.Low, Android.Hardware.SensorStatus.AccuracyHigh);
locationManager.SetTestProviderEnabled("Test09", true);
var location = new Location("Test09");
location.Latitude = Add700ToCoordinates();
location.Longitude = GlobalLongitude;
location.Accuracy = 0; // ob das geht?... ja, aber was beduetet es?
location.Time = DateTime.Now.Ticks;
location.ElapsedRealtimeNanos = 100; // hier das gleiche... was hießt es? :D
locationManager.SetTestProviderLocation("Test09", location);
//Check if your event reacted the right way
locationManager.RemoveTestProvider("Test09");
return location.Latitude.ToString();
}
}
}
There are probably two things at play here - service and background processing.
You can set the mock locations, probably, as a service that runs in the background. You can do this in the native code.
And if you are using Xamarin or Xamarin Forms you can utilize the MessagingCenter feature to talk/access the service.
You can have native code running services in the background and your PCL/shared code can access from native code information that you need.
You can check on this link for some very helpful example and walkthrough.
First you need to create native implementation for services for each platform.
For Android:
You need to wrap your service into Android Service to have capability work in background. Please see this references https://developer.android.com/guide/components/services.html
https://developer.xamarin.com/guides/android/application_fundamentals/services/
For iOS:
It's little beat harder. First read this reference, especially "Declaring Your App’s Supported Background Tasks" part.(https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html)
So you can use "Location updates" background mode and inject your mock-generator service into "locations updates" service.
Below example for xamarin iOS:
private void StartAccelerometerUpdates()
{
if (_motionManager.AccelerometerAvailable)
_motionManager.AccelerometerUpdateInterval = ACCEL_UPDATE_INTERVAL;
_motionManager.StartAccelerometerUpdates (NSOperationQueue.MainQueue, AccelerometerDataUpdatedHandler);
}
public void AccelerometerDataUpdatedHandler(CMAccelerometerData data, NSError error)
{ //your mock-generator code }