I want my app to navigate every five minutes to a certain webpage while the display is off. Therefore i created an AlarmReceiver:
[BroadcastReceiver]
public class BackgroundAlarmReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
MainActivity.Current.RunOnUiThread(() =>
{
FMain.WV.LoadUrl("http://127.0.0.1/");
});
}
}
WV is attached to the layout of the fragment 'FMain' and a static parameter of it.
This works fine while the screen is on, but when I turn my screen off and turn it on a few minutes later, most of the times I get to see "Webpage not available, ERR_NAME_NOT_RESOLVED" (but sometimes it loads even while the screen is of).
The webview has DomStorage and JavaScript enabled and a standard WebViewClient:
public class MyWebViewClient : WebViewClient
{
public override bool ShouldOverrideUrlLoading(WebView view, IWebResourceRequest request)
{
view.LoadUrl(request.Url.ToString());
return false;
}
}
It happens, because android system kills your web view. Do you really need to render some page every 5 minutes in background, or you just want to send request?
Related
I'm currently working on the POM of a web app, that allows to open modals from the navigation bar. The navigation bar stays the same for every page you're on. Each modal can be opened from every page.
I have defined a page object for each modal. Also the navigation bar is a pageobject,
What would be the best way to return to the page, that the modal was opened from?
So for example, you are on the Page FooPage and open modal AboutModal. What is the best way to return to FooPage? It should also work for BarPage and other Pages.
My first approach was, that i define a BasePage Object, which only includes the webdriver and navigationbar. i extend every Page on the web app from this BasePage. Then i could do something like this:
Code for FooPage:
public class FooPage: BasePage
{
private NavigationBar NavBar;
public FooPage(IWebDriver driver): base(driver)
{
...
this.NavBar = new NavigationBar(driver);
}
public NavigationBar Navigate()
{
return NavBar;
}
...
}
public class NavigationBar
{
...
public openAboutModal(BasePage currentPage)
{
log.Info("Open About Modal");
Action.Click(NavigationBarElements.AboutButton);
return new AboutModal(Driver, currentPage);
}
}
public class AboutModal
{
...
protected BasePage ReturnPage;
public AboutModal(IWebDriver driver, BasePage returnPage)
{
...
this.ReturnPage = returnPage;
}
public BasePage CloseAboutModal()
{
return this.ReturnPage;
}
...
}
This is not practical and not intuitive, because we have to remember on which pageobject we currently are, when writing tests. Also only the methods from BasePage are available, which means we have to additionaly navigate back to the page we wanted to be on.
So instead of writing
public class ModalTests
{
[Test]
public void CheckAboutModal()
{
Login() // FooPage
.Navigate() //NavigationBar
.openAboutModal() // AboutModal
.doSomeStuff() //AboutModal
.CloseAboutModal(); //FooPage
}
}
we have to do
public void CheckAboutModal()
{
Login() // FooPage
.Navigate() //NavigationBar
.openAboutModal(new FooPage(Driver)) // AboutModal
.doSomeStuff() // AboutModal
.CloseAboutModal() // BasePage
.Navigate() //NavigationBar
.ToFooPage(); // FooPage
}
}
How can I return to the calling Page of the modal, without making Testwriting to complicated?
Rather than write your test as one giant method-chaining call, use variables whenever you need to refer back to a certain page model. Your test can simply become:
var foo = Login();
foo.Navigate()
.openAboutModal()
.doSomeStuff()
.CloseAboutModal();
// Continue your test after closing the modal
foo.SomeOtherOperation();
In cases like this, the modal doesn't need to return anything. The CloseAboutModal() method can be a void return type. Your test should understand the larger context in which the modal is being used, and create local variables appropriately in order to "return" back to the main page.
I am not sure how to handle this behavior, this is the Feature I have:
public class HolderFeature : Feature<HolderState>
{
public override string GetName() => "HolderState";
protected override HolderState GetInitialState() => new(holder: new ProductHolder(), persons: string.Empty);
}
And, everything works fine until a page is refreshed (pressing f5), the state is wiped out, I have this to handle the error:
protected override void OnInitialized()
{
if (HolderState.Value.QuotedProduct.Quotes != null)
{
//do the logic
}
else
{
//show error screen
PressedF5 = true;
}
}
What I expect is that even when the page is refreshed it shouldn't wipe out the state. how can I do that?
The state is stored in memory. When you refresh the page you are unloading it and starting from scratch, so all the memory is lost if it isn't persisted somewhere.
I'm working on a Xamarin.Forms project that supports iOS and Android devices, and I'm using the MVVM design pattern.
I have navigation root page that consists of a ListView, when item is selected on this ListView, I execute the following command to Navigate to item details view.
Page DetailsPage = new View.DetailsView(SelectedItemData);
await Navigation.PushAsync(DetailsPage);
Once this Details Page is opened, I start running a background task.
private void StartBackgroundTask(){
TimerBackgroundTask = new Timer((o) => {
Device.BeginInvokeOnMainThread(() => Update()); }, null, 0, 1000);
}
}
Which is based on this class
public class Timer : CancellationTokenSource
{
public bool IsDisposed { get; set; }
public Timer(Action<object> callback, object state, int dueTime, int period)
{
System.Threading.Tasks.Task.Delay(dueTime, Token).ContinueWith(async (t, s) =>
{
Tuple<Action<object>, object> tuple = (Tuple<Action<object>, object>)s;
while (!IsCancellationRequested)
{
await System.Threading.Tasks.Task.Run(() => tuple.Item1(tuple.Item2));
await System.Threading.Tasks.Task.Delay(period);
}
},
Tuple.Create(callback, state), CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.Default);
}
protected override void Dispose(bool disposing)
{
IsDisposed = true;
if (disposing)
{
Cancel();
}
base.Dispose(disposing);
}
}
Update function updates UI every 1 second.
Everything works fine and as it should, no issues here, however problems start to occur once I navigate back to root page, and back to details page - doing so twice causes the following error:
System.ArgumentException'jobject' must not be IntPtr.Zero. Parameter name: jobject
The problem stops occurring once the StartBackgroundTask gets disabled entirely from the code, so I believe that it is the one responsible for the error. Furthermore, I'm fairly convinced that this background task keeps on running somewhere in the thread even though I navigate back to the root page and I believe that if I could somehow dispose of the background task OnDissapearing event / navigation back button pressed, the error would no longer persist.
Unfortunately I have no idea how I how or even if its possible to somehow bind command to navigation back pressed event given my Views are bound to ViewModel.
Any tips would be greatly appreciated.
You can detect that a page is being dismissed by overriding OnDisappearing. In your DetailPage you could have something like this:
protected override void OnDisappearing()
{
TimerBackgroundTask?.Dispose();
base.OnDisappearing();
}
I writing android app on Xamarin(C#)
I need to Show alert with "Yes" and "No" variantes when I tap back button on Activity.
How can I realize this?
I know how to show alert. How I can make it when i press back button
try this , add to your activity
#Override
public void onBackPressed() {
AlertDialog.Builder builder =
new AlertDialog.Builder(this, R.style.AppCompatAlertDialogStyle);
builder.setTitle(getResources().getString(R.string.app_name));
builder.setMessage("" + Message);
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//write your code
}
});
builder.setNegativeButton("No", null);
builder.setCancelable(false);
builder.show();
}
Xamarin provides wrappers to the native Android Activity classes. So you probably have a MainActivity and maybe other Activity classes in your Xamarin Android project.
In these classes you can override the OnBackPressed method inherited from FormsApplicationActivity and then create and show your Alert from there.
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity
{
public override void OnBackPressed()
{
// show Alert or pass call on to base.OnBackPressed()
}
}
Since Xamarin Forms 1.3.0 pre3, there is a new method:
protected bool OnBackButtonPressed();
You need to override this on your page.
protected override bool OnBackButtonPressed()
{
// If you want to stop the back button and show alert
return true;
// If you want to continue going back
base.OnBackButtonPressed();
return false;
}
Thanks to Xamarin Forums. Refer this link for more info.
I have function which reads Data out of an Webservice. With that Data i create Bitmaps. I send the Bitmaps to Panels (Displays) which displays the created Bitmaps. Manually its working like charm. What i need now is, that my Application run this function every 5 min automtically in the Backround.
My Application is running under IIS. How can i do that? Can someone help me with that?
You don't have to be depended on asp.net project, but you can use Cache Callback to do it.
I have found a nice approach, to do it.
actually i don't remember the link so i'll give you a code that i use:
public abstract class Job
{
protected Job()
{
Run();
}
protected abstract void Execute();
protected abstract TimeSpan Interval { get; }
private void Callback(string key, object value, CacheItemRemovedReason reason)
{
if (reason == CacheItemRemovedReason.Expired)
{
Execute();
Run();
}
}
protected void Run()
{
HttpRuntime.Cache.Add(GetType().ToString(), this, null,
Cache.NoAbsoluteExpiration, Interval, CacheItemPriority.Normal, Callback);
}
}
Here is the implementation
public class EmailJob : Job
{
protected override void Execute()
{
// TODO: send email to whole users that are registered
}
protected override TimeSpan Interval
{
get { return new TimeSpan(0, 10, 0); }
}
}
An Asp.Net application is not the correct framework for a task like this.
You should probably create a dedicated service for this type of tasks.
Another option is to create a scheduled task that will run every X minutes
On a side note, if you must do this through your asp.net application, I recommend reading on how to Simulate a Windows Service using ASP.NET to run scheduled jobs