I want to call a C# class/method from within the HTML loaded in my WebView.
I have defined a class JS2CS which contains a single method to show a Toast, as follows:
using Android.Content;
using Android.Widget;
using Java.Interop;
namespace CrossPlatformApp_Android
{
public class JS2CS : Java.Lang.Object
{
private Context context;
public JS2CS (Context context)
{
this.context = context;
}
[Export ("run")]
public void Run ()
{
Toast.MakeText (context, "Hello from C#", ToastLength.Short).Show ();
}
}
}
I have defined a button in my HomePage.html file as follows:
<button type="button" onclick="JS2CS.run()" >Call C#</button>
HomePage.html is saved in the Assets folder of my project and I load it into my WebView as follows:
myWebView.Settings.JavaScriptEnabled = true;
myWebView.SetWebChromeClient (new CustomWebChromeClient());
myWebView.LoadUrl ("file:///android_asset/Content/HomePage.html");
CustomWebChromeClient is a simple extension of WebChromeClient which offers no additional functionality over its parent.
Lastly, I inject my JS2CS object into my WebView after calling LoadUrl(...), as follows:
myWebView.AddJavascriptInterface (new JS2CS (this), "JS2CS");
Unfortunately this does not do the job. When I launch my application and click the html button, I get the following message:
[Web Console] Uncaught ReferenceError: JS2CS is not defined at
file:///android_asset/Content/HomePage.html:22
If I call the AddJavascriptInterface(...) method before LoadUrl(...) instead, I get the following error message:
[Web Console] Uncaught TypeError: Object [object Object] has no method
'run' at file:///android_asset/Content/HomePage.html:22
Any ideas anybody??!!
The above implementation is based on the following two urls:
Call C# from JavaScript
Monodroid Javascript Call-back
Hmm, after trying all kinds of things... I stumbled across this sentence in the Android WebView.addJavascriptInterface(Object, String) documentation:
...For applications targeted to API level JELLY_BEAN_MR1 and above, only
public methods that are annotated with JavascriptInterface can be
accessed from JavaScript...
And I lowered my Android Application's Target Version from API 19 to API 14 and made no other changes to the code in the question and it now works! Hurrah! That does now pose the question however of how to inject a JavaScript interface into a WebView for app's targeting API 17+ but that's another question for another thread...
Edit: To get it to work for an app targeting API 17+, all you have to do is add the [JavascriptInterface] annotation to the method being
exported.
Related
Is there a way to achieve method binding in iOS with MVVMCross ?
I cannot see an example of such a binding in the vids or tutorials...
ImageNavigationViewModel:
public void NavigateLeft()
{
if (!this.HasLeftSisters.Value)
{
return;
}
this.currentNodeIndex--;
this.Update();
}
ImageNavigationView:
private UIButton navigateLeftButton;
...
var set = this.CreateBindingSet<ImageNavigationView, ImageNavigationViewModel>();
set.Bind(this.navigateLeftButton).To(vm => vm.NavigateLeft);
I have a compile-time error since it's expecting an object (ICommand).
I tried this too:
set.Bind(this.navigateLeftButton).To("NavigateLeft");
And have runtime error: Failed to create target binding for binding TouchUpInside for NavigateLeft.
I ended up adding a ICommand to my view model, which is a bit disappointing since I "method bind" just find in Android.
Rio Method binding is available in iOS
It's demonstrated in https://www.youtube.com/watch?v=8-5XQlcVj2Y with sample cod ein https://github.com/MvvmCross/NPlus1DaysOfMvvmCross/blob/master/N-36-Rio/BindMe.Touch/Views/FirstView.cs#L58
Your line:
set.Bind(this.navigateLeftButton).To("NavigateLeft");
should work - but you will need the method binding plugin added to the Touch UI project to enable this extension.
I'm trying to write a library that will make it easer for dartisans to use the SoundCloud JavaScript SDK (http://developers.soundcloud.com/docs/api/sdks#javascript).
I'm using the 'dart:js' library, and
I'm only using one class to handle the proxy.
class SCproxy {
JsObject proxy = context['SC'];
String client_id;
SCproxy(this.client_id) {}
initialize() {
proxy.callMethod('initialize', [client_id]);
}
stream(String track_id){
var track = new JsObject(proxy.callMethod('stream',[track_id]));
print(track); // track should be the soundmanager2 object that we can call '.play' on.
}
The repo I'm hosting this from is (https://github.com/darkkiero/scproxy)
My problem occurs when I try to run my 'stream' method.
main() {
SCproxy SC = new SCproxy('Your SoundCloud API client_ID');
SC.initialize();
SC.stream('/tracks/111477464');
}
When I try to grab and use the soundmanager2 object returned by the javascript 'SC.stream' method, the dart editor gives me this exception :
Breaking on exception: type 'ScriptElement' is not a subtype of type 'JsFunction' of 'constructor'.
I am under the impression that I should be able to get the dart JsObject for the soundmanager2 object by collecting the callback of the 'SC.stream', But I'm not sure how.However I could be completely misusing 'dart:js' and that would be helpful information as well.
You don't seem to follow the SoundCloud JavaScript SDK documentation. Particularly for the stream method that takes a callback as parameter and doesn't return.
The following Dart code :
context['SC'].callMethod('stream', ['/tracks/293', (sound) {
sound.callMethod('play');
}]);
will do the same as this JS code :
SC.stream("/tracks/293", function(sound){
sound.play();
});
You can have a look at Using JavaScript from Dart for more explanations.
I have a quick question here. Can any one please help me to sort out this problem.
I'm new to windows Phone. I'm developing an Application where i can change my Font styles for the entire application . I have three different Resource file to set three different types of font styles. The resource file are set to application in App.xaml.cs file. Now i need to support to change the styles in Application run time from Application Changestyles page. So i need to call the method in app.xaml.cs from changestyles.xaml.cs page.
private void LoadResourceDictionary()
{
var dictionaries = new ResourceDictionary();
string source = String.Format("/Testapp;component/Large.xaml");
var themeStyles = new ResourceDictionary { Source = new Uri(source, UriKind.Relative) };
dictionaries.MergedDictionaries.Add(themeStyles);
App.Current.Resources = dictionaries;
ResourceDictionary appResources = App.Current.Resources;
}
I need to call this method to set the another resource to my application in run time.
Is it possible to resolve this issue?
Make this method public static and you can call it from everywhere: App.LoadResourceDictionary();
Here is a generic how to based on the code I needed for an app I am writing. I know the circumstances are slightly different, but it may help someone else who is after a similar solution:
In MainPage.xaml you create a method as follows:
public static void InMainPage()
{
System.Diagnostics.Debug.WriteLine("Hi I am a method in MainPage.xaml.cs");
}
Now in App.xaml.cs you can call it in any method as such:
MainPage.InMainPage();
AND IT WORKS FOR YOU CIRCUMSTANCE IN THE REVERSE DIRECTION
In App.xaml.cs you create a method as follows:
public static void InAppXaml()
{
System.Diagnostics.Debug.WriteLine("Hi I am a method in App.xaml.cs");
}
Now in Mainpage.xaml.cs you can call it in any method as such:
App.InAppXaml();
Tested and works well. Hope it helps!
First of all I would like to remark I am new with the concept of prism, DI and containers. I am looking on one of the code samples provided with the Prism Library:
The code simply injects a view with the "Hello World" string (in a TextBlock element) to a region in the shell.
When the application starts-up, it creates a new BootStrapper instance, which creates and initializes the shell:
public class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
return Container.Resolve<Shell>();
}
protected override void InitializeShell()
{
base.InitializeShell();
Application.Current.RootVisual = (UIElement)this.Shell;
}
protected override void ConfigureModuleCatalog()
{
base.ConfigureModuleCatalog();
ModuleCatalog moduleCatalog = (ModuleCatalog)this.ModuleCatalog;
moduleCatalog.AddModule(typeof(HelloWorldModule.HelloWorldModule));
}
}
My question refers to the method CreateShell(). I couldnt find nowhere in the supplied code (including not in a configuration file or any xaml file...) where do they register the type Shell, and even if it was registered - the supplies Shell class doesnt implement any interface... what is the meaning of resolving a specific type?
the Shell implementation:
public partial class Shell : UserControl
{
public Shell()
{
InitializeComponent();
}
}
This looks like a magic to me, so I tried to create my own type (MyType) and resolve it the same way:
Container.Resolve<MyType>();
By setting a breakepoint inside MyType constructor, I saw that it DID resolved MyType. Can somebody please explain to me how does it work?
These couple of threads should answer your question:
http://compositewpf.codeplex.com/Thread/View.aspx?ThreadId=230051
Does unity just make clasess with out needing anything registered?
Additionally, if you are eager to get more detail into how Unity can do this, simple download Unity 2.0 and open the source code that is provided with the installer.
I hope this helps.
Thanks,
Damian
You do not need to register a type you want to resolve. You need to register the dependencies of a type, that you want to resolve. In this case, the Shell doesn't need any dependencies, so you can resolve it simply. But for an example (not really), if your shell getting an interface IService as a parameter, then you must register IService, before you resolve Shell.
Otherwise you will get Dependency Resolution Failed Exception. In Prism 4.1 it will be swallowed silently due to TryResolve.
I have the following two projects in in Flex Builder 3:
One AS3 library project (generates a SWC file)
One Flex application project (MXML Application)
The MXML Application references to the AS3 library project (Flex build path). So far, so good. I now want to run code automatically when an application uses the AS3 library. The [mixin] tag should do exactly what I need.
I followed the instructions from http://nondocs.blogspot.com/2007/04/metadatamixin.html and checked out the AutoQuick project. The latter is an example project by Adobe showing the use of the automation framework. In this project they are using the [mixin] tag (class AQAdapter).
I followed the examples but my code is not working. The static init method is not called. I added the library to the compiler arguments list that didn't work either.
How do I get this to work?
/* class to be automatically loaded */
package {
/* includes */
[mixin]
public class TestApp extends Sprite {
/* additional members */
private static var mContainer:DisplayObjectContainer;
private static var mInstance:TestApp;
/**
* #private
*/
public static function init(root:DisplayObject):void
{
if(!mInstance)
{
mContainer = root as DisplayObjectContainer;
mContainer.addEventListener(FlexEvent.APPLICATION_COMPLETE, applicationCompleteHandler);
}
}
}
}
With the [Mixin] tag, the static init() method will be called at application start-up, as long as the class is referenced directly or indirectly from the main application.
Also, you have to remember that this method is run in a static context, so you shouldn't reference methods or attributes that require an instance (non-static), without creating the instance first.
Link: http://adamflater.blogspot.com/2007/03/static-code-blocks.html