Why is Ionic 3 ion-loader throwing removeView error / not showing when dismiss/present checks in place - view

I am using an ion-loading component which works fine the first time the view is accessed and the loader is presented and dismissed.
import { AlertController, LoadingController } from 'ionic-angular';
constructor(
public zone: NgZone,
public loadingCtrl: LoadingController,
public alertCtrl: AlertController,
private storage: Storage,
public navCtrl: NavController
) {
this.loading = this.loadingCtrl.create();
}
tryGeolocation() {
this.loading.present();
//misc code
this.markers.push(marker);
this.map.setCenter(pos);
//if(this.loading){
this.loading.dismiss();
}
However when I navigate back to the view and the loader is again presented I get a error:
Error: Uncaught (in promise): removeView was not found
I have tried to followe the advice here and introduced checks to see if loader has been dismissed but now the loader never comes into view:
if (this.loading == null){
console.log("Map.ts: Presenting loader.");
this.loading.present();
}
if (this.loading != null){
console.log("Map.ts: Dismissing loader.");
this.loading.dismiss();
}
I am using ionic 3.9.9, angular 5.2.11
Any input appreciated.

Seems to be allot of different solutions out there depending on the context, for me the solution was to move the loader create call from the module constructor to the method calling present and dismiss:
tryGeolocation() {...
this.loading = this.loadingCtrl.create();
this.loading.present();
//some code
this.loading.dismiss();
}

Related

Windows 10 version 1903 update (NET Framework 4.8) breaking Prism 6.3

First off, we are well aware that this isn't strictly speaking a Prism 6.3 issue; what we're looking for (in case a solution isn't straightforward) are pointers to a solution to the problem -thanks in advance btw-, which is:
Windows 10 version 1903, via .NET Framework 4.8 inclusion, breaks our otherwise perfectly functioning, tried-and-true, production-deployed Prism 6.3-based commercial software. We're using Prism (Core), Prism.WPF, and Prism.MEF (all v6.3). What we get (source code later) is the following runtime error whenever we try to instantiate a registered View:
Prism.Regions.RegionNavigationService.CreateNewRegionItem(String candidateTargetContract) throws an InvalidOperationException: Cannot create navigation target 'xyzView'. Activation error ocurred while tring to get instance of type Object, key 'xyzView'.
Inner exception stems from Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key), which throws an ActivationException: Activation error ocurred while tring to get instance of type Object, key 'xyzView'.
Devil's in the details so here's some relevant code (xyzView = ExpedicionView or ExpedicionMaestroView, both trigger the Exception):
[ModuleExport(typeof(ExpedicionModulo))]
[Export(typeof(IMenu))]
public class ExpedicionModulo : IModule, IMenu
{
[Import]
public IRegionManager RegionManager;
[Import]
public ILoggerFacade Logger;
[ImportingConstructor]
public ExpedicionModulo(IRegionManager regionManager, ILoggerFacade logger)
{
Logger = logger;
RegionManager = regionManager;
// irrelevant (for our purposes) code omitted here
}
public void Initialize()
{
// Here's how we register views for main region
RegionManager.RegisterViewWithRegion(RegionNames.MainContentRegion, typeof(ExpedicionView));
RegionManager.RegisterViewWithRegion(RegionNames.MainContentRegion, typeof(MaestroExpedicionView));
// Some more registering for our dialog region
RegionManager.RegisterViewWithRegion(RegionNames.DialogRegion, typeof(ExpedicionDetalleView));
// other views registered in the very same fashion
Logger.Log("Expedition Module initialized", Category.Info, Priority.None);
}
We invoke RequestNavigate in this bit of code here:
[Export]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ShellViewModel : BaseViewModel
{
public IRibbonPrincipal RibbonPrincipal { get; set; }
private readonly InteractionRequest<Confirmation> _confirmationInteractionRequest;
private readonly InteractionRequest<Notification> _notificationInteractionRequest;
private string _seccionActiva;
private string _subseccionActiva;
private IRegionManager _regionManager;
[ImportingConstructor]
public ShellViewModel(IRegionManager regionManager, IEventAggregator eventAggregator, ILoggerFacade logger)
: this(eventAggregator, logger)
{
try
{
_regionManager = regionManager;
_regionManager.RegisterViewWithRegion(RegionNames.MainContentRegion, typeof(PrincipalView));
}
catch (Exception ex)
{
this.LoggerError(ex.Message);
}
}
public ShellViewModel(IEventAggregator eventAggregator, ILoggerFacade logger)
: base(eventAggregator, logger)
{
try
{
// Some irrelevant (to our purposes) initialization code omitted here
New = new DelegateCommand(() => { }, () => { return false; }); // etc.
_confirmationInteractionRequest = new InteractionRequest<Confirmation>();
_notificationInteractionRequest = new InteractionRequest<Notification>();
// Events code omitted for brevity sake
EventAggregator.GetEvent<MessageBoxEvent>().Subscribe(ShowMessageBox, ThreadOption.PublisherThread, false); // etc.
// View loading wireup
CambioSeccion = new DelegateCommand<object>(OnCambioSeccion);
CambioSubseccion = new DelegateCommand<object[]>(OnCambioSubseccion);
// some more irrelevant (to our purposes) code omitted here.
}
catch (Exception ex)
{
this.LoggerError(ex.Message);
}
}
/// <summary>
/// This is where we instantiate the View (WAI in .NET Framework <=4.7.2)
/// </summary>
/// <param name="objeto"></param>
private void OnCambioSeccion(object objeto)
{
// Ribbon menu handling here
RibbonPrincipal.ResetRibbon();
IIdentifyViewModel ivm = null;
// We are passing the View's name via clicked TreeViewItem in this case (param objeto)
TreeViewItem treeViewItem = (TreeViewItem)objeto;
if (treeViewItem != null && !string.IsNullOrEmpty(treeViewItem.Name))
{
_seccionActiva = treeViewItem.Name;
// Now we build the actual RequestNavigate invoke
// In our case, _seccionActiva would equal "Expedicion" or "MaestroExpedicion"
_regionManager.RequestNavigate(RegionNames.MainContentRegion, new Uri("/" + _seccionActiva + "View", UriKind.Relative), (r) =>
{
if (!r.Result.HasValue || !r.Result.Value)
{
// error handling code here
}
else
{
ivm = ((FrameworkElement)_regionManager.Regions[RegionNames.MainContentRegion].ActiveViews.First()).DataContext as IIdentifyViewModel;
}
});
// Some event triggering here
if (ivm != null)
{
Seccion.Cambio(EventAggregator, ivm.ID);
}
}
}
Sorry for the long winded post, and thanks in advance.
#mcandal thanks for the write-up. This looks like a recent issue introduced in .NET Framework 4.8 that we have seen with the patterns and practices activation code. The underlying issue is that in 4.8 the constructors for types were returned in a different order resulting in the patterns and practices choice of the first (eg. ctors[0]) sometimes no longer being correct.
There are a few workarounds as we work through a fix in an upcoming release.
This issue only impacts assemlbies that are ngen'd.
Workarounds:
1) Disable ngen for the assembly containing the type:
<configuration>
<runtime>
<disableNativeImageLoad>
<assemblyIdentity name="assembly_name" />
</disableNativeImageLoad>
</runtime>
</configuration>
2) For the type that is being activated only have 1 ctor (the documentation for the patterns and practices assumes there is only 1 ctor)
3) Choose the other provided activation models where you pass in the types of the parameters, to avoid the ambiguity.
As I mentioned, we are working on a fix and if you would like to discuss further you can submit a VS Feedback item and link to this post and we can continue the discussion there.

Rendering the Google Recaptcha in Android Studio 3

I am using Android Studio 3
I am following this article to learn how to use Google Recaptcha in Android Studio.
Installed the package using this: implementation 'com.google.android.gms:play-services-safetynet:12.0.1'
API keys are also registered.
I saw there is onClick event handler but where is it mentioned about rendering the recaptcha?
Update 1
When I wrote the button click code as mentioned in the link...I got a complication error: inconvertible types cannot cast anonymous android.view.view.onclicklistener to java.util.concurrent.executor
Code as asked in comment
btn_Login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
SafetyNet.getClient(this).verifyWithRecaptcha("")
.addOnSuccessListener((Executor) this,
new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
#Override
public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
// Indicates communication with reCAPTCHA service was
// successful.
String userResponseToken = response.getTokenResult();
if (!userResponseToken.isEmpty()) {
// Validate the user response token using the
// reCAPTCHA siteverify API.
}
}
})
.addOnFailureListener((Executor) this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ApiException) {
// An error occurred when communicating with the
// reCAPTCHA service. Refer to the status code to
// handle the error appropriately.
ApiException apiException = (ApiException) e;
int statusCode = apiException.getStatusCode();
} else {
}
}
});
}
});
I used below code and everything is work fine now.
Make sure to implement Executor in the activity
btn_Login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
SafetyNet.getClient(Activity.this).verifyWithRecaptcha("")
.addOnSuccessListener((Activity) MyActivity.this,
new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
#Override
public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
// Indicates communication with reCAPTCHA service was
// successful.
String userResponseToken = response.getTokenResult();
if (!userResponseToken.isEmpty()) {
// Validate the user response token using the
// reCAPTCHA siteverify API.
}
}
})
.addOnFailureListener((Activity) MyActivity.this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ApiException) {
// An error occurred when communicating with the
// reCAPTCHA service. Refer to the status code to
// handle the error appropriately.
ApiException apiException = (ApiException) e;
int statusCode = apiException.getStatusCode();
} else {
}
}
});
}
});
According to the article, in your button click handler you must call the method SafetyNet.getClient(this).verifyWithRecaptcha(...) to show reCAPTCHA and handle success or error. Passing this, you give the SDK handle to your current view which should be shown after solving reCAPTCHA. Most probably the rendering will be done by the SDK itself given that it’s a part of the OS. And most probably it will be full-screen in a separate top-level view blocking access to your app before solving the riddle.
You should try to implement it in your app as described in the article and see how it goes. Then you can ask a more specific question.
EDIT: You combined 2 techniques in your code: copy-pasting the code from Google and implementing anonymous class from it. So the problem you asked in the comment is that using (Executor) this in line 5 refers now not to your View (as it was there in the original tutorial) but to the instance of the anonymous interface implementation new View.OnClickListener() that you created. Ypu can refer to this answer to see how it can be implemented not interfering with already complex reCAPTCHA code.

Angular 4: Using Custom RouteReuseStrategy causes Cannot read property 'prototype' of undefined

The custom Route reuse strategy is as follows,
import { RouteReuseStrategy,ActivatedRouteSnapshot,DetachedRouteHandler} from '#angular/router';
export class CustomRouteReuseStrategy extends RouteReuseStrategy {
shouldDetach(route: ActivatedRouteSnapshot): boolean { return false; }
store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void {}
shouldAttach(route: ActivatedRouteSnapshot): boolean { return false; }
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { return null ; }
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
console.log("inside shouldReuseRoute...");
return future.routeConfig === curr.routeConfig ;
}
}
I get this below error
Error: TypeError: Cannot read property 'prototype' of undefined
at __extends (http://localhost:8000/app/UMSClient/com/ipc/ums/modules/shared/CustomRouteReuse.service.js:7:73)
I read through stack overflow posts and couldn't locate a solution. Once this works I want to ensure one of my child component gets reloaded instead of Re-use and then attach component going forward in the project.
I provided in AppModule
{
provide: RouteReuseStrategy,
useClass: CustomRouteReuseStrategy
},
I change extends to implements and the error goes away but the custom route re-use does not work.
i am using angular 4.3.1
The issue was my workspace structure. Angular 2 version was picked up by build wrongly when angular 4 was intended. When I corrected this, it started working fine.

LoginPage and MasterDetail Issue

So I'm trying to implement a login with OAuth and the Xamarin.Auth plugin (I'm working in Xamarin.Forms, building for ios and android). I successfully followed this tutorial... on a dummy example. Now I'm try to go for "the real deal" but I'm kind of stuck:
My app has a resource dictionary in the App.xaml file which doesn't seem to be loaded: In App.xaml.cs, I have
public static Action SuccessfulLoginAction
{
get
{
return new Action(() =>
{
_NavPage.Navigation.PushModalAsync(new SampleWithAppResources());
});
}
}
Which his invoke in a custom Renderer (android one here, but there is another one for ios):
public class LoginPageRenderer : PageRenderer
{
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
var auth = new OAuth2Authenticator([...]);
auth.Completed += (sender, eventArgs) =>
{
App.SuccessfulLoginAction.Invoke();
if (eventArgs.IsAuthenticated)
{
// The user is authenticated
}
else
{
// The user cancelled
}
};
PresentViewController(auth.GetUI(), true, null);
}
}
SampleWithAppResources is not empty, but appears as a blank page when used in this flow...
2nd problem, my app uses a MasterDetailPage. I made the code evolve so it resemble to this:
static Root _RootPage;
public App()
{
InitializeComponent();
_RootPage = new Root(){Detail = new NavigationPage(new LoginPage())};
MainPage = _RootPage;
}
public static Action SuccessfulLoginAction
{
get
{
return new Action(() =>
{
_RootPage.Detail = new NavigationPage(new SampleWithAppResources());
});
}
}
Which results (once successfully logged in) in:
Unhandled Exception:
Java.Lang.IllegalStateException: Can not perform this action after onSaveInstanceState occurred
Fundamentally here what I'm trying to do:
Redirect to the LoginPage if the user is not logged in
Display a "HomePage" (here SampleWithAppResources) once the user is logged in.
By the way, I've the exact same error in the Action when trying to present first the LoginPage, then replacing the App.Current.MainPage
If any of you have a clue on how to do this, it would be really helpful.

Xamarin iOS Google Sign-in component : App crashes due to error uiDelegate must either be a |UIViewController| or implement

I'm trying to implement google sign in using this component for xamarin.ios: Google Sign-in for iOS
It works great on emulator but when it comes to actual device it's crashing once i tap signin button. (iOS 10.2 - emulator is also using same OS)
I have a custom button which calls SignInUser method on SignIn.SharedInstance
It's crashing with below error (only when the app is deployed on device)
Objective-C exception thrown. Name: NSInvalidArgumentException Reason: uiDelegate must either be a |UIViewController| or implement the |signIn:presentViewController:| and |signIn:dismissViewController:| methods from |GIDSignInUIDelegate|.
I'm calling function below to initialize GoogleSignIn on FinishedLaunching method of AppDelegate.cs
public void Configure()
{
NSError configureError;
Context.SharedInstance.Configure(out configureError);
if (configureError != null)
{
// If something went wrong, assign the clientID manually
Console.WriteLine("Error configuring the Google context: {0}", configureError);
SignIn.SharedInstance.ClientID = googleClientId;
}
SignIn.SharedInstance.Delegate = this;
SignIn.SharedInstance.UIDelegate = new GoogleSignInUIDelegate();
}
Here's my implementation of ISignInUIDelegate():
class GoogleSignInUIDelegate : SignInUIDelegate
{
public override void WillDispatch(SignIn signIn, NSError error)
{
}
public override void PresentViewController(SignIn signIn, UIViewController viewController)
{
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(viewController, true, null);
}
public override void DismissViewController(SignIn signIn, UIViewController viewController)
{
UIApplication.SharedApplication.KeyWindow.RootViewController.DismissViewController(true, null);
}
}
So the emulator seems to know the methods are implemented, but not the device. Any idea what i am doing wrong here?
After some debugging i found where the actual issue was.
Somehow, the UIDelegate i assigned during initialization was lost when i was calling my login method. So i moved the line below from my initialization step to login
SignIn.SharedInstance.UIDelegate = new GoogleSignInUIDelegate();
Here's how my login method looks like now:
public void Login()
{
SignIn.SharedInstance.UIDelegate = new GoogleSignInUIDelegate(); //moved this here from Configure
SignIn.SharedInstance.SignInUser();
}
This took care of the issue for me but i am still not sure why this is only an issue on the device and not the emulator. Any Ideas?
Add a PreserveAttribute to your GoogleSignInUIDelegate class to prevent the Linker from removing the methods that can not be determined via static analysis.
Add the following class to your project:
public sealed class PreserveAttribute : System.Attribute {
public bool AllMembers;
public bool Conditional;
}
Apply the class attribute:
[Preserve (AllMembers = true)]
class GoogleSignInUIDelegate : SignInUIDelegate
{
~~~~
}
Re: https://developer.xamarin.com/guides/ios/advanced_topics/linker/
Setting PresentingViewController helped me to resolve the issue.
SignIn.SharedInstance.PresentingViewController = this;
Have found such fix here:
https://github.com/googlesamples/google-signin-unity/issues/169#issuecomment-791305225

Resources