Android WebView: Exceptions are not caught - exception

I followed the approach of defining a Thread.setDefaultUncaughtExceptionHandler in the onCreate Method of my application. This application is also defined as such in the manifest. The handler is also created but its handler is never called although I do see a JavaScript error in the LogCat.
12-19 03:02:58.630: I/chromium(1569): [INFO:CONSOLE(45)] "Uncaught ReferenceError: $contactArea is not defined", source: file:///android_asset/DefaultPage.html (45)
The handler is defined in my app:
public class HPAWebView extends Application {
private static Context context;
#Override
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread thread, final Throwable ex) {
// Custom code here to handle the error.
Toast.makeText(HPAWebView.getAppContext(), "Oh no! " + ex.getMessage(), Toast.LENGTH_SHORT).show();
}
});
HPAWebView.context = getApplicationContext();
}
public static Context getAppContext() {
return HPAWebView.context;
}
}
...and this application is stated in the manifest:
<application
android:name="sap.com.prototype.webview.HPAWebView"

Your custom exception handler is not able to catch JavaScript exceptions. You could register a JavaScript interface in your WebView and then call it in response to the JavaScript error event. Let me know if this makes sense or I can clarify more.

Related

JavaFX application thread exits during JUnit test

I'm testing a JavaFX application with JUnit, In most cases I use the #Rule approach from Basic JUnit test for JavaFX 8. However there are a couple of situations where this approach does not work, so I setup the JavaFX platform manually, and call Platform.runLater() where necessary.
What appears to be happening is that at some point the JavaFX application thread is disappearing, this means subsequent tests lockup as the Platform.runLater() calls never return - that's why I've added timeouts in example. I've proved this with calls to Thread.getAllStackTraces()
Yes I'm aware of JemmyFX, and I'll likely move to it soon, but I'd still like to understand what's going on here...
Code
public class JavaFxThreadJUnit {
private static boolean setup;
private Stage stage;
#Before
public void before() throws Exception {
setupJavaFX();
Platform.setImplicitExit(true);
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
stage = new Stage();
stage.show();
latch.countDown();
});
latch.await(5, TimeUnit.SECONDS);
}
#After
public void after() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
Platform.runLater(() -> {
stage.hide();
latch.countDown();
});
latch.await(5, TimeUnit.SECONDS);
}
#Test
public void foo() throws Exception {
// test stuff...
System.out.println("foo test: "
+ Thread.getAllStackTraces().keySet().stream().map(Thread::getName).collect(Collectors.toList()));
}
#Test
public void bar() throws Exception {
// test stuff...
System.out.println("bar test: "
+ Thread.getAllStackTraces().keySet().stream().map(Thread::getName).collect(Collectors.toList()));
}
// https://gist.github.com/andytill/3835914
public static void setupJavaFX() throws InterruptedException {
if (setup) {
return;
}
long timeMillis = System.currentTimeMillis();
final CountDownLatch latch = new CountDownLatch(1);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// initializes JavaFX environment
new JFXPanel();
latch.countDown();
}
});
System.out.println("javafx initialising...");
latch.await();
System.out.println("javafx is initialised in " + (System.currentTimeMillis() - timeMillis) + "ms");
setup = true;
}
}
Output... JavaFX Application Thread was there, then it's gone...
javafx initialising...
javafx is initialised in 327ms
bar test: [Thread-3, ReaderThread, AWT-Shutdown, AWT-Windows, Thread-2, Finalizer, JavaFX Application Thread, Signal Dispatcher, Java2D Disposer, AWT-EventQueue-0, main, Attach Listener, Reference Handler, QuantumRenderer-0]
foo test: [Thread-3, ReaderThread, Java2D Disposer, AWT-Windows, Thread-2, main, Finalizer, Attach Listener, Reference Handler, Signal Dispatcher]
Looks like the stage closing is triggering an "implicit exit". I'd still be interested to know why this doesn't also affect tests using the #Rule approach...
Workaround:
Platform.setImplicitExit(false)

Error Hanling RemainingChargePercentChanged Event

I want to update a textblock whenever there is a change in battery percent. I found the event RemainingChargePercentChanged in the Windows.Phone.Devices.Power.Battery namespace. But whenever the eventhandler is called and i try to update the textblock, i struck with error.
the error is:
An exception of type System.UnauthorizedAccessException occurred in System.Windows.ni.dll but was not handled in user code.
Do I want to select any capabilities in AppManifest file??.. If so, what?
Any help will be appreciated.
Following is my code,
public partial class MainPage : PhoneApplicationPage
{
private readonly Battery _battery;
// Constructor
public MainPage()
{
InitializeComponent();
_battery = Battery.GetDefault();
_battery.RemainingChargePercentChanged += OnRemainingChargePercentChanged;
UpdateUI();
}
private void OnRemainingChargePercentChanged(object sender, object e)
{
UpdateUI();
}
private void UpdateUI()
{
sampletext.Text = string.Format("{0} %", _battery.RemainingChargePercent);
}
}
The problem is that the event handler is called on another thread, if you read the exception message it will say Invalid cross-thread access.
The solution is to change the Text property on the UI thread using the Dispatcher, like this:
Dispatcher.BeginInvoke(() => {
sampletext.Text = string.Format("{0} %", _battery.RemainingChargePercent);
});
Edit: or your whole UpdateUI function call:
private void OnRemainingChargePercentChanged(object sender, object e)
{
Dispatcher.BeginInvoke(() => {
UpdateUI();
});
}

Why is my app crashing in System.Windows.ni.dll on startup with no useful stack trace? (seemingly after adopting Caliburn.Micro)

Start with the default "empty" Windows Phone App project (Windows Phone 8). Let's call it BlackAdder for fun.
Add Caliburn.Micro from Nuget
Move MainPage.xaml to the Views subdirectory and create a matching ViewModel in ViewModels\MainPageViewModel.cs
Fix the namespace for MainPage to Blackadder.Views in both the .xaml and .xaml.cs files
Update App.xaml
<Application
x:Class="BlackAdder.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:local="clr-namespace:BlackAdder">
<Application.Resources>
<local:Bootstrapper x:Key="bootstrapper"/>
</Application.Resources>
</Application>
Update App.xaml.cs
public partial class App : Application
{
public static PhoneApplicationFrame RootFrame { get; private set; }
public App()
{
InitializeComponent();
// Show graphics profiling information while debugging.
if (Debugger.IsAttached)
{
...
}
}
}
Create Bootstrapper.cs
public class Bootstrapper : PhoneBootstrapper
{
private PhoneContainer container;
protected override void Configure()
{
container = new PhoneContainer();
container.RegisterPhoneServices(RootFrame);
container.PerRequest<MainPageViewModel>();
AddCustomConventions();
}
protected static void AddCustomConventions()
{
}
protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
}
When we run the app, it crashes in a very weird place.
An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in System.Windows.ni.dll
Additional information: Exception has been thrown by the target of an invocation.
There is no inner exception, and the stack trace is (seemingly) useless.
System.Windows.ni.dll!System.Windows.Threading.DispatcherOperation.Invoke()
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.Dispatch(System.Windows.Threading.DispatcherPriority priority)
System.Windows.ni.dll!System.Windows.Threading.Dispatcher.OnInvoke(object context)
System.Windows.ni.dll!System.Windows.Hosting.CallbackCookie.Invoke(object[] args)
System.Windows.RuntimeHost.ni.dll!System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(System.IntPtr pHandle, int nParamCount, System.Windows.Hosting.NativeMethods.ScriptParam* pParams, System.Windows.Hosting.NativeMethods.ScriptParam* pResult)
It turns out this has nothing to do with caliburn.micro at all. The problem lies in Properties\WMAppManifest.xaml.
After moving MainPage.xaml to the Views subdirectory, the Navigation Page setting (found on the first tab, Application UI) needs to be updated to Views\MainPage.xaml

Umbrella Exception during fire event in GWT

I have a Singleton Instance and when I am Firing the event whose handler uses Singleton instance it resulting in Umbrella Exception.
The code Snippets are
#UiHandler("panelButton")
void handleClick(ClickEvent e) {
AppUtils.eventBus.addHandler(PanelClickEvent.TYPE, new PanelClickEventHandler());
AppUtils.eventBus.fireEvent(new PanelClickEvent());
}
The Handler is
public class PanelClickEventHandler implements EventHandler{
#Inject
PanelDataHandler pdh;
public void displayPanelGrid() {
System.out.print(pdh.getPanelList().size());
}
}
The error is with the lines
#Inject
PanelDataHandler pdh;
My PanelDataHandler is
#Singleton
public class PanelDataHandler {
.......
#Inject
public PanelDataHandler(){
....
}
.......
}
Is there anything which I am missing?
shouln't I use #singleton object in my handler ?
PanelClickEventHandler won't be injected if you create it with new PanelClickEventHandler. It'll only be if GIN (or whatever you use for dependency injection) creates the instance, or if you explicitly inject its members afterwards.

Update UI thread from portable class library

I have an MVVM Cross application running on Windows Phone 8 which I recently ported across to using Portable Class Libraries.
The view models are within the portable class library and one of them exposes a property which enables and disables a PerformanceProgressBar from the Silverlight for WP toolkit through data binding.
When the user presses a button a RelayCommand kicks off a background process which sets the property to true which should enable the progress bar and does the background processing.
Before I ported it to a PCL I was able to invoke the change from the UI thread to ensure the progress bar got enabled, but the Dispatcher object isn't available in a PCL. How can I work around this?
Thanks
Dan
All the MvvmCross platforms require that UI-actions get marshalled back on to the UI Thread/Apartment - but each platform does this differently....
To work around this, MvvmCross provides a cross-platform way to do this - using an IMvxViewDispatcherProvider injected object.
For example, on WindowsPhone IMvxViewDispatcherProvider is provided ultimately by MvxMainThreadDispatcher in https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxMainThreadDispatcher.cs
This implements the InvokeOnMainThread using:
private bool InvokeOrBeginInvoke(Action action)
{
if (_uiDispatcher.CheckAccess())
action();
else
_uiDispatcher.BeginInvoke(action);
return true;
}
For code in ViewModels:
your ViewModel inherits from MvxViewModel
the MvxViewModel inherits from an MvxApplicationObject
the MvxApplicationObject inherits from an MvxNotifyPropertyChanged
the MvxNotifyPropertyChanged object inherits from an MvxMainThreadDispatchingObject
MvxMainThreadDispatchingObject is https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/ViewModels/MvxMainThreadDispatchingObject.cs
public abstract class MvxMainThreadDispatchingObject
: IMvxServiceConsumer<IMvxViewDispatcherProvider>
{
protected IMvxViewDispatcher ViewDispatcher
{
get { return this.GetService().Dispatcher; }
}
protected void InvokeOnMainThread(Action action)
{
if (ViewDispatcher != null)
ViewDispatcher.RequestMainThreadAction(action);
}
}
So... your ViewModel can just call InvokeOnMainThread(() => DoStuff());
One further point to note is that MvvmCross automatically does UI thread conversions for property updates which are signalled in a MvxViewModel (or indeed in any MvxNotifyPropertyChanged object) through the RaisePropertyChanged() methods - see:
protected void RaisePropertyChanged(string whichProperty)
{
// check for subscription before going multithreaded
if (PropertyChanged == null)
return;
InvokeOnMainThread(
() =>
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(whichProperty));
});
}
in https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/ViewModels/MvxNotifyPropertyChanged.cs
This automatic marshalling of RaisePropertyChanged() calls works well for most situations, but can be a bit inefficient if you Raise a lot of changed properties from a background thread - it can lead to a lot of thread context switching. It's not something you need to be aware of in most of your code - but if you ever do find it is a problem, then it can help to change code like:
MyProperty1 = newValue1;
MyProperty2 = newValue2;
// ...
MyProperty10 = newValue10;
to:
InvokeOnMainThread(() => {
MyProperty1 = newValue1;
MyProperty2 = newValue2;
// ...
MyProperty10 = newValue10;
});
If you ever use ObservableCollection, then please note that MvvmCross does not do any thread marshalling for the INotifyPropertyChanged or INotifyCollectionChanged events fired by these classes - so it's up to you as a developer to marshall these changes.
The reason: ObservableCollection exists in the MS and Mono code bases - so there is no easy way that MvvmCross can change these existing implementations.
If you don't have access to the Dispatcher, you can just pass a delegate of the BeginInvoke method to your class:
public class YourViewModel
{
public YourViewModel(Action<Action> beginInvoke)
{
this.BeginInvoke = beginInvoke;
}
protected Action<Action> BeginInvoke { get; private set; }
private void SomeMethod()
{
this.BeginInvoke(() => DoSomething());
}
}
Then to instanciate it (from a class that has access to the dispatcher):
var dispatcherDelegate = action => Dispatcher.BeginInvoke(action);
var viewModel = new YourViewModel(dispatcherDelegate);
Or you can also create a wrapper around your dispatcher.
First, define a IDispatcher interface in your portable class library:
public interface IDispatcher
{
void BeginInvoke(Action action);
}
Then, in the project who has access to the dispatcher, implement the interface:
public class DispatcherWrapper : IDispatcher
{
public DispatcherWrapper(Dispatcher dispatcher)
{
this.Dispatcher = dispatcher;
}
protected Dispatcher Dispatcher { get; private set; }
public void BeginInvoke(Action action)
{
this.Dispatcher.BeginInvoke(action);
}
}
Then you can just pass this object as a IDispatcher instance to your portable class library.
Another option that could be easier is to store a reference to SynchronizationContext.Current in your class's constructor. Then, later on, you can use _context.Post(() => ...) to invoke on the context -- which is the UI thread in WPF/WinRT/SL.
class MyViewModel
{
private readonly SynchronizationContext _context;
public MyViewModel()
{
_context = SynchronizationContext.Current.
}
private void MyCallbackOnAnotherThread()
{
_context.Post(() => UpdateTheUi());
}
}