After resume sometimes show the Home Screen on Nativescript-Vue - nativescript

I have a problem with my application and his navigation.
My app have four screens but sometimes when tap the android home button in the second screen (or any other) and after resume the app, this show the home screen and not the last screen, any ideas to resolve this?
Update:
Sometimes after resume the app, this show the correct screen (the last showed) but I don't know how this happen (it's the same source code), I tested this in many versions of android simulator (4.4, 5.0, 7.0 y 8.0). Can this be a bug?
Screen Recording:
https://i.imgur.com/VhWFhWU.gifv
Code:
https://play.nativescript.org/?template=play-vue&id=wKkYCe&v=2
Thanks

It should be easy if you are using single frame in your application. You could listen to resume event of activity and call $navigateBack with a reference to first item in the back stack.
if (application.android) {
application.android.on(application.AndroidApplication.activityResumedEvent,
() => {
const backStack = frame.topmost().backStack[0];
if (backStack) {
setTimeout(() => {
this.$navigateBack({}, backStack);
}, 0);
}
}, this);
}
Playground Sample

Related

XamarinForms Shell OnResume - previous page is showing

I want to achieve lock mechanism in XF 4.5.0 Shell app.
I have static timer that counts how much seconds passed, and based on some logic present either screen that user was before put the app in behind (user went to instagram, but app is in the background running)
So, my OnResume() method looks like this:
private bool IsUserExists()
{
if (!string.IsNullOrWhiteSpace(GlobalAppSettings.Email) && !string.IsNullOrWhiteSpace(GlobalAppSettings.Password) && !string.IsNullOrWhiteSpace(GlobalAppSettings.Pin))
{
return true;
}
else
{
return false;
}
}
protected override void OnResume()
{
if ((!OnSleepOrPauseTime.HasValue || OnSleepOrPauseTime.Value.AddSeconds(5) <= DateTime.Now)
&&(IsUserExists()))
{
Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
{
await Shell.Current.GoToAsync(Routes.LoginPinPage, false);
});
}
}
The problem: user sees for a like half second the screen where he was before, and then it redirects to LoginPinPage.
The happy path: Should be that user doesnt see that flickering page that was before exiting form an app, just immediately lock screen.
Possible solution: That crossed on my mind, before leaving the app to somehow redirect in background app to login pin screen?
PushAsync has 2 overloads - docs
By default the PushAsync method pushes the new page with animation. I think that this is the so-called "flickering" that you are referring to.
You can try to use the second overload and pass false for the animated property and see if it makes any difference.
PushAsync(new LoginPinPage(), false);
If you want to redirect the user on app leave - you can use another of the Application's lifecycle methods - OnSleep and invoke your navigation there. But I suggest to try it without animations first.
Keep in mind that, should you choose to use the OnSleep method, you will also have to push the page without animations. I have just tested pushing with animations and I do indeed see the flickering that you are mentioning. Setting the animated flag to false, removed any flickering for me.

Access multiple renderers with spectron

I'm working on an Electron application. The main process opens a first renderer (browserWindow). When the user click on a button, this renderer sends an IPC message to the main process. When this message is received, the main process opens a second, different, renderer. Those two renderers live concurently. The application works fine.
Then, using Spectron to test this app, how to access both renderers ? The problem is app.rendererProcess always returns the first renderer.
This is the same problem with app.client which always contains the WebdriverIO browser object of the first renderer and never the second.
Is there a way to list all the process of a Spectron application in a test? Is it possible to access the browser object of the second renderer ?
With AVA:
test.(async t => {
// the application is open before the test
// at this point, the first renderer is open
// click on the button to open the second renderer
await t.context.app.client.click('#bt_openSecondRenderer');
// wait for the second renderer to open
// error: this element doesn't exist
await t.context.app.client.click('elt_of_the_scnd_renderer');
});
I'm using AVA but I don't think it is the problem. So if anyone know how to make this works with Mocha or anything else, it would be very helpfull.
Thanks !
Following the philosophy given by Tim answer, instead of using BrowserWindow, we can use WebDriverIO to focus the desired window:
test.(async t => {
// here, t.context.app.client handles the first window
await t.context.app.client.windowByIndex(1).then(() => {
// here, t.context.app.client handles the second window
});
});
Like a user, Specton can only interact with the focused window. This should work but I haven't tested it:
// The docs say that app.electron gives you access to all the Electron APIs
// This should get you a list of BrowserWindows
const windows = await t.context.app.electron.BrowserWindow.getAllWindows();
// Focus the window you want to interact with
windows[1].focus();
// Do your clicking
await t.context.app.client.click('elt_of_the_scnd_renderer');
it('Switch window', async () => {
await app.client.waitUntilWindowLoaded(100000)
.windowByIndex(0);
.windowByIndex(1);
})

Input.Touch not working on OSX

I'm a total beginner in Unity and created a function that simply sets the text of a text element when a touch is detected like this:
// Update is called once per frame
void Update () {
if (didTap ()) {
print ("did tap!");
tapText.text = "TAP!";
}
}
private bool didTap() {
print ("checking didtap");
if (Input.touchCount > 0) {
Touch initialTouch = Input.GetTouch (0);
return initialTouch.phase == TouchPhase.Began;
}
return false;
}
When I run this on an actual device (Android phone) it works perfectly, but when I 'click' in the unity editor when running the game nothing happens. I'm running OSX 10.12.2. Anything I need to configure to have the mouse mimic touch events?
You can duplicate Unity's play mode window onto your mobile device by using the UnityRemote app. This will allow you to interact with your phone's features, while still running Unity on your computer.
UnityRemote requires some setup in Unity along with downloading the app. Consider watching this video: Unity Remote Setup Tutorial
Alternatively, see the answer from Hellium in this question, in conjunction with getting the mouse clicks, to only compile code based on the device used.
There's an odd difference between "touch" input and "mouse" input in Unity. Input.touchCount will always return 0 while you're running in the Editor but Input.GetMouseButtonDown(0) works for both the Editor and the first touch of one or more touches while on a mobile build.
You have two options to solve this issue via code (your other option is the remote ryemoss mentioned):
If you're only ever using one touch, use Input.GetMouseButtonDown(0) and Input.GetMouseButtonUp(0).
Use #if UNITY_IOS, #if UNITY_ANDROID and #if UNITY_EDITOR tags to write separate input readers for your platforms and then have them all call into the same functionality.

Xcode7 | Xcode UI Tests | How to handle location service alert?

I am writing UI Test Cases for one one of my app using the XCUIApplication, XCUIElement and XCUIElementQuery introduced in Xcode7/iOS 9.
I have hit a road block. One of the screens in test case requires iOS's Location Services. As expected the user is prompted about allowing use of location service with alert titled: Allow “App name” to access your location while you use the app? with Allow & Don't Allow buttons.
Problem is or so it seems that since the alert is presented by OS itself it is not present in Application's element sub-tree.
I have logged following:
print("XYZ:\(app.alerts.count)")//0
var existence = app.staticTexts["Allow “App Name” to access your location while you use the app?"].exists
print("XYZ:\(existence)")//false
existence = app.buttons["Allow"].exists
print("XYZ:\(existence)") //false
Even UI recording generated similar code:
XCUIApplication().alerts["Allow “App Name” to access your location while you use the app?"].collectionViews.buttons["Allow"].tap()
I have not found any API that can get me past this problem. For example:
Tap at a position on the screen
Get alerts outside the app
So how can I get past this? Is there a way to configure Test Targets so that Location Service Authorization is not required.
Xcode 9
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let allowBtn = springboard.buttons["Allow"]
if allowBtn.exists {
allowBtn.tap()
}
Xcode 8.3.3
_ = addUIInterruptionMonitor(withDescription: "Location Dialog") { (alert) -> Bool in
alert.buttons["Allow"].tap()
return true
}
app.buttons["Request Location"].tap()
app.tap() // need to interact with the app for the handler to fire
Note that it is a bit different as the method name now is addUIInterruptionMonitor and takes withDescription as an argument
Xcode 7.1
Xcode 7.1 has finally fixed a issue with system alerts. There are, however, two small gotchas.
First, you need to set up a "UI Interuption Handler" before presenting the alert. This is our way of telling the framework how to handle an alert when it appears.
Second, after presenting the alert you must interact with the interface. Simply tapping the app works just fine, but is required.
addUIInterruptionMonitorWithDescription("Location Dialog") { (alert) -> Bool in
alert.buttons["Allow"].tap()
return true
}
app.buttons["Request Location"].tap()
app.tap() // need to interact with the app for the handler to fire
The "Location Dialog" is just a string to help the developer identify which handler was accessed, it is not specific to the type of alert.
Xcode 7.0
The following will dismiss a single "system alert" in Xcode 7 Beta 6:
let app = XCUIApplication()
app.launch()
// trigger location permission dialog
app.alerts.element.collectionViews.buttons["Allow"].tap()
Beta 6 introduced a slew of fixes for UI Testing and I believe this was one of them.
Also note that I am calling -element directly on -alerts. Calling -element on an XCUIElementQuery forces the framework to choose the "one and only" matching element on the screen. This works great for alerts where you can only have one visible at a time. However, if you try this for a label and have two labels the framework will raise an exception.
This was the only thing that worked for me. Using Xcode 9 fwiw.
Also probably relevant that I was already using addUIInterruptionMonitor for a different alert. I tried reordering them and it didn't make a difference. Could be that it's a problem in 9 when you have two, or could be I was using them wrong. In any event the code below worked. :)
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let allowBtn = springboard.buttons["Allow"]
if allowBtn.exists {
allowBtn.tap()
}
If you want to check if the alert is showing, just check for the existence of the button:
if (app.alerts.element.collectionViews.buttons["Dismiss"].exists)
{
app.alerts.element.collectionViews.buttons["Dismiss"].tap()
}
it checks if the alert is showing, and if it's showing it will tap it
I got it to work with this on Xcode 9.4.1, the trick was to wait for the popup to appear.
// wait for location service popup to appear
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let allowBtn = springboard.buttons["Allow"]
expectation(for: NSPredicate(format: "exists == true"), evaluatedWith: allowBtn, handler: nil)
waitForExpectations(timeout: 10, handler: nil)
//allow location service
if allowBtn.exists {
allowBtn.tap()
}
On xcode 9.1, alerts are only being handled if the test device has iOS 11. Doesn't work on older iOS versions e.g 10.3 etc. Reference: https://forums.developer.apple.com/thread/86989
To handle alerts use this:
//Use this before the alerts appear. I am doing it before app.launch()
let allowButtonPredicate = NSPredicate(format: "label == 'Always Allow' || label == 'Allow'")
//1st alert
_ = addUIInterruptionMonitor(withDescription: "Allow to access your location?") { (alert) -> Bool in
let alwaysAllowButton = alert.buttons.matching(allowButtonPredicate).element.firstMatch
if alwaysAllowButton.exists {
alwaysAllowButton.tap()
return true
}
return false
}
// One interruption monitor is sufficient for multiple alerts
This works for all languages:
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
let allowBtn = springboard.buttons.element(boundBy: 1)
if allowBtn.exists {
allowBtn.tap()
}
To tap allow on location alert you can call
element.tap() where element is any element on your screen.
So after calling tap, accessibility will tap Allow on alert and than tap on your element
Here's what I did to accept a notifications permission alert in any language by tapping the second button found in the (two button) dialog. The Allow button is on the right, therefore index 1.
let handler = addUIInterruptionMonitor(withDescription: "System Dialog") { (alert) -> Bool in
alert.buttons.element(boundBy: 1).tap()
return true
}
app.tap()

How to disable delay to detect single/double tap on List component to improve performance in Sencha Touch 2.2

I am using a list component and there seems to be a very noticeable delay when tapping a list item to open the next view. My understanding is that it is waiting to detect whether the tap is a single tap or a double tap. In the case of my app, all taps will always be single taps as there is no double tap action. Is there a way to disable this delay or prevent it so that the performance with which the app reacts to tap events is improved?
I use FastClick (Official Page) (GitHub). You end up having to add a block of about 500 lines of code to your app, which of course isn't ideal, but it works quite well and is super easy to implement.
If you don't use double taps in your app, then add this code to your app.js:
eventPublishers: {
touchGesture: {
recognizers: {
doubleTap: null,
}
}
},
This will prevent app/touch/src/event/recognizer/DoubleTap.js from loading. The maxDuration of 300 ms is set there.

Resources