Detect App idle time period for iOS in Xamarin forms - ios

I recently started working in Xamarin forms and quite happy to be part of Xamarin community. I've a requirement to kick out the loggedIn User if he is idle on app for 10 mins. I got through of it in Android part using usual Life Cycle methods (combination of OnResume/OnPause) but not yet succeeded in iOS app.
I've hard time trying to find a solution over the internet but not able to find the one so far. I also tried with using Some Life cycle methods like WillEnterForeground/DidEnterbackground but due to some reason these method are not invoked on desired actions.
FYI, I am from the Android background so not expertise in iOS.
Any help would be highly appreciated or let me know If I am missing anything.

in App class
DateTime sleepTime;
protected override void OnSleep()
{
base.OnSleep();
sleepTime = DateTime.Now;
}
protected override void OnResume()
{
base.OnResume();
var sleepDuration = DateTime.Now - sleepTime;
}

Related

Xamarin iOS App check if GPS is enabled or prompt the user

Hi I am looking into an app which is written in Xamarin iOS. The feature I am trying to implement is
GPS must be enabled when app is running, if gps is not enabled prompt the user to enable. If the answer is yes enable the gps and continue otherwise exit app.
I am really new Xamarin and mobile development in general. After research i have found this link which shows the lifecycle of Xamarin iOS app.
Xamarin Lifecycle
The question I have is
1) Will I be able to show an alert to user from App Delegate to enable GPS when app returns from background or launched in the overrides (See link)
2) If a dialog is not possible from app delegate will it be better to create a new screen and show the dialog to enable gps instead of adding gps check in all screens.
3) Is this the correct way of checking if GPS is enabled
e.g., when app returns from background
public override void WillEnterForeground(UIApplication application)
{
Console.WriteLine("App will enter foreground");
if(CLLocationManager.Status == CLAuthorizationStatus.Denied)
{
}
}
Welcome #Abe you are on the right path!
Yes, you will be. You just have to place it in the overrides as you mentioned.
You can place the check in the AppDelegate, but it may not be the best thing to do. You might want to just place it in the Appear override of your page.
Yes using AppDelegate lifecycle overrides, is one way of checking for GPS if you need the it when your app is in the background.
Tips:
If you are using Xamarin Native, inside the ViewController, you could instead use the ViewDidLoad override to perform the check for GPS
You could instead just also just look into the Xamarin Essentials examples for a simplified way of dealing with GPS

indexedDB.open() takes around 10sec on iOS Safari

I have an indexedDB database used in a web app on my iPhone.
Lately it started to take more time to start. After diagnosing this case for some time I've found that it happens because of indexedDB.open() running for 10+ seconds.
Here is a little code example
var db;
var promise = utils.promise();
var openRequest = indexedDB.open(this.dbName, this.version);
openRequest.onsuccess = function(evt) {
db = openRequest.result;
promise.resolve();
};
openRequest.onerror = function(evt) {
promise.reject();
onError(evt, 'Database open');
};
Database itself didn't change lately so much. Also I don't have lots of data. It has around 300 records.
Any idea how to diagnose such an issue?
UPD may be related https://bugs.chromium.org/p/chromium/issues/detail?id=402980
Apparently it was a result of iOS update (from 11.1.* to 11.2.*).
I have my web app added to the Home Screen. And as far as I understand when you do iOS updates the web app container is moved to a new iOS environment but conserves some features from the original iOS version (probably something related to WebView used for web app but I am not sure).
So I have added my web app to Home Screen again and it starts without delays.

Ti.Facebook doesn't open authorize with FB app installed

EDIT: DEAR PEOPLE FROM THE FUTURE, trey-jones has fixed this issue by implementing setLoginBehavior, FBSDKLoginNative seems to have issues on FB's end not with the module.
Environment:
MacOS X 10.10.5
Ti SDK 5.1.1.GA - 5.1.2.GA
iOS 9.2
Ti.Facebook 5.0.0 - 5.0.1
My project settings (tiapp.xml) are fine (it works on every other case on both iOS and Android).
Code I'm using to invoke the login:
var fb = require('facebook');
fb.initialize();
fb.authorize();
If the Facebook app is installed to the device the fb.authorize() doesn't open up. I did not see any iOS system level messages when this happened either.
Has anyone else had luck using fb.authorize with the new sdk on iOS devices WITH the app installed. With no fb app on the system it correctly opens the browser based view.
EDIT: I have managed a workaround for this (it is not pretty) based on the fact that login works with AppC's KitchenSink.
The workaround is to add a Ti.FB loginButton to the code, doesn't matter if its not visible, initializing this will fix whatever is causing custom login's .authorize() to not work.
//Workaround button:
if(OS_IOS){
var fbHaxBtn = fb.createLoginButton({
readPermissions: ['email'],
visible: false
});
}
//It needs to be added to the window/doesn't need to be visible though
$.login_window.add(fbHaxBtn);
//Then in our custom button's code, we can fire as normal:
function doLoginClick{
fb.initialize(); //I was having unexpected issues dropping this line on Android, although the docs say its deprecated.
fb.authorize();
}
Will keep this ticket updated if/when this thing gets a formal fix.
This is my second answer on this question. I believe that my original answer offers some value to the conversation and that is why I am leaving it, but it still did not consistently solve the problem of the facebook authorization not working.
The consistent solution turned out to be modifying the official Ti.Facebook module. I will submit a pull request for this change (1 line), but for now, you can get the working module here:
Source
Pre-built
This consistently allows users to authorize by explicitly setting the login behavior to use the browser, rather than the native facebook app through fast app-switching. This is actually the intent of Facebook's developers.
I was unable to determine what is causing it to fizzle when trying to use the native app to login - it should try the next option, which is the browser - but this works, and doesn't require a TiFacebookButton either.
I hope it helps someone else!
EDIT: This answer does not solve the original question. I have left it here in case it helps with related difficulties using the Ti.Facebook module. See my other answer, to actually solve the problem. END EDIT
I commented above, but after doing so encountered some more strange behavior, with the result being that I could not reliably use the workaround given (fbHaxButton). I want to explain what was happening in my case, and show my own workaround (which is also not pretty). It's possible that the root cause is the same for both of us.
I have not bothered with Android yet, so this answer is specific to iOS.
When I started this process, I came to the conclusion that authorize was correctly opening the facebook website in safari to allow authorization, but was not firing the login event upon returning. To handle this I had already implemented the following:
facebook = require('facebook');
Ti.App.addEventListener('resumed', function (e) {
var launchOptions = Ti.App.getArguments();
if(!launchOptions.url) {
return console.warn('Ignoring resume event with no url argument.');
}
// this lib = https://github.com/garycourt/uri-js
var URI = require('vendor/uri'),
uriComponents = URI.parse(launchOptions.url),
expectedScheme = 'fb',
expectedHost = 'authorize';
// I would like to be more specific about the uri, but we are limited
// in Titanium, and this will allow us to pretty certain
// that FB is sending us back to our app
if(uriComponents.scheme.search(expectedScheme) < 0 || uriComponents.host !== expectedHost) {
return console.warn('Resume event received, but scheme is incorrect. Ignoring.');
}
// synthesize login event
facebook.fireEvent('myapp:login', {
success: 1,
token: facebook.getAccessToken(),
uid: result.id
});
});
facebook.addEventListener('myapp:login', function onFacebookAuth(e) {
facebook.removeEventListener('myapp:login', onFacebookAuth);
if(!e.success) {
// do fail action
}
// do success action
});
facebook.initialize();
facebook.authorize();
So, originally I was firing and listening for an event called 'login', which the facebook module supposedly (according to the docs) will fire after authorization is complete.
In my case, this event was being fired while my app was in the background, after authorize was called, but before the user actually clicked 'OK' in facebook. My listener would respond to this event (logging, etc), but seemed to occur in a separate thread, or somehow otherwise become disconnected from my app, as it never passed its result along to the UI. I am using Q.js (kriw-kowal) and I belive this is where the disconnect is occuring.
Ceasing to listen to 'login', and simply handling my own synthesized event has fixed my issue.
I felt that this was very difficult to explain. If you have feedback about that, and how I can be more clear about what I believe is happening, or if you believe that I have reached wrong or incomplete conclusion, let me know - I'll try to update this answer to be better.

Xamarin MvvmCross iOS state restoration issues

I am currently unable to get state save/restore working for an iOS (target iOS 8) Xamarin solution using MvvmCross. The core view model implements save/restore as specified here https://github.com/MvvmCross/MvvmCross/wiki/View-Model-Lifecycle
The state is saved and restored correctly in the Android version of the solution, but is not working for the iOS version.
I have set a Restoration ID on the associated view controllers, and added the “opt in” methods to the app delegate class…
public override bool ShouldSaveApplicationState(UIApplication application, NSCoder coder)
{
return true;
}
public override bool ShouldRestoreApplicationState(UIApplication application, NSCoder coder)
{
return true;
}
If I create a basic single view iOS Xamarin app then I do see a call to the view controller’s EncodeRestorableState override method when the app goes into the background. However, for a similar simple MvvmCross implementation, this overridden method is no longer called (and neither is the SaveState method of the view model).
I have been unable to find anything to help, and only seem to find many people asking similar questions, but currently with no answers (e.g. SaveState in MvvmCross is not being called in an iOS application).
I would be very grateful for any information that could help point me in the right direction with this. Thanks.

UiApplication.activate() method called post app install on some BlackBerry Bolds. Why?

I'm having troubles with the UiApplication.activate() method firing post-app-installation (OTA install).
I have:
public class PlayerApp extends UiApplication
public PlayerApp() {
new Thread(this).start();
}
public void run() { ... }
public void activate() { ... }
I'm having troubles with the activate() method. It's firing to early, it's firing post--installation when it shouldn't (I thought it should fire when the application is selected by the user from the menu). What makes it worse it's not occuring on all Bolds. The BB is meant to ask for a reboot, but activate() is firing before this point and plays hell with the UI.
Questions. When does activate() really fire? Should activate() be firing post-install anyway? Is there a way to handle activate() firing post-installation? Is this a bug in the rim apis?
Note: The problem appears on BB Bold 4.6.0.144/4.0.0.143 and thus far I've not been able to replicate the issue on 4.6.0.282/4.0.0.235.
Edit: Installation flow: OTA link > Download > Install > 'Yes' to 'Trust application status' > AutoStart app > Trouble starts here.
According to the API docs activate():
The system invokes this method when it brings this application to the foreground. By default, this method does nothing. Override this method to perform additional processing when being brought to the foreground.
So, I suspect after OTA install the user is given the option of running the app which, when accepted, brings the app to the foreground. It is difficult to be certain without seeing your startup code. If your app is configured to autostart, then it will be "autostarted" after install. If this casues the UI to be instantiated and brought to the foreground, the activate will be called at that time.

Resources