We're coding an app for Android. It's a WebView that contains Html5 pages. We're using loadUrl() webview's method, in order to push some native OS variables to html, such as:
webview.loadUrl("javascript:myJavascriptFunc('" + myAndroidOSVar + "');");
It works pretty fine. But if we are typing on an input from page while loadUrl() is called, we lose focus of our input fields, even if javascript function called just changes a flag on cache.
Do you know other way to call a Javascript function from WebView instead of loadUrl()?
This is the closest you can get to avoiding the issue: WebView hides soft keyboard during loadUrl(), which means a keyboard cannot stay open while calling javascript
Basically you are avoiding the loadUrl call by queuing up commands on the native side and at an interval letting the JS bridge get the commands and execute using JS eval() or something.
I'm not sure exactly how it will respond if you have multiple fields in the webview, but I came up with a workaround to keep the keyboard shown: https://stackoverflow.com/a/18776064/513038. It may be worth trying.
yes, there is a way by adding a JavaScriptInterface to your WebView , refer this tutorial for more explanation and details
Related
I am working on creating an app and am a relatively new Objective C programmer. On a page, "test.php", I have a javascript variable. Here is a simplified version.
<script>
var idx = 45;
document.write(idx);
</script>
I would like to be able to view the value of the variable "idx" in my IOS app, which I have created using Xcode. What would be the optimal way to connect to the page, test.php, and transfer my Javascript variable to Objective C so I could use it as part of my IOS App?
Any help would be greatly appreciated. Thank you.
You will need to communicate between the webview and the native code using a combination of two pieces. First, you will need to "trigger" the webview into returning some value by calling stringByEvaluatingJavaScriptFromString: on the webview. When the webview tries to navigate because of the javascript call, you can intercept it on the native side with the WebView's shouldStartLoadWithRequest: method.
For details, see the specifics here Invoke method in objective c code from HTML code using UIWebView
That is only if you need some activity in the webview to trigger the fetch (or notify the native code that the value has been set). If the value is always available via JS, you can simply use stringByEvaluatingJavaScriptFromString: as follows:
NSString *returnvalue = [self.webviewForHtml stringByEvaluatingJavaScriptFromString:#"var idx = "return_value";return idx;"];
I'm working on an iOS app in which I'm trying to use UIWebView to display a variety of websites. Recently I finished logic to inject Javascript into the UIWebView to catch instances of window.open, window.close, and window.opener.focus. In short, to do so, I inject JS that overrides the aforementioned JS functions, which includes creating an iframe with a specific scheme that I can catch in the app's webView:shouldStartLoadWithRequest:navigationType method. This is all working OK for now, including window.open creating a new UIWebView rather than loading in the same window.
Now though, the issue has come up where there's no feasible solution for JS communication between windows. If the child window tries to call to window.opener or window.parent, it's always returning a null value, and thus, it can't communicate back to the original web view.
In an effort to see what iOS browsers are able to effectively perform window-to-window communication, I found that of the 9 browsers I have on my iPhone, only Safari was able to effectively perform this communication successfully. This leads me to believe that there's something with UIWebView that prevents full JS window-to-window communication from being possible.
Has anyone had any success with getting UIWebView to fully integrate with all JS logic, namely window-to-window communication? Or have proof that JS window-to-window communication isn't possible? Any direction or advice is appreciated. Thanks!
Found possible solution.
Add JavaScriptCore.framework to Linked Frameworks and in your webViewDidFinishLoad:
JSContext *parentCtx = [self.parentWebView valueForKeyPath:#"documentView.webView.mainFrame.javaScriptContext"];
JSContext *childCtx = [self.childWebView valueForKeyPath:#"documentView.webView.mainFrame.javaScriptContext"];
childCtx[#"window"][#"opener"] = parentCtx[#"window"];
Now when you call window.opener.test() from childWebView, it will fire test function in parentWebView!
I'm not sure about private API.
Works on iOS 7 only
Swift version
import JavaScriptCore
let jsContextA = webA.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext")
let jsContextB = webB.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext")
//Original objc code : jsContextB[#"window"][#"opener"] = jsContextA[#"window"];
jsContextB!.setObject("opener", forKeyedSubscript: "window")
jsContextB!.setObject(jsContextA!.objectForKeyedSubscript("window"), forKeyedSubscript: "opener")
This is my first post so I am sorry for any mistakes I made :)
I know the title is confusing, but i will try to explain what I want.
I got this website, on the website there is a schedule, this schedule change when you change different values so that it consist with the appropriate person. When you change a value a JavaScript function is called. Is there any way for me to do this JavaScript (on a site I don't own) from objective-C.
So, what I want is this (in a very plain description):
do JavaScript call change() on website: "My website" (I know this is not valid, but this is what I want)
Also I would like to be able to change the different values and pass the function with parameters.
Thanks
Kristian
The website is here (Norwegian):
http://www.novasoftware.se/webviewer/(S(mfq2npum0th2lxb0g5oy3045))/design1.aspx?schoolid=60810&code=545354&type=3&id=1559)
Edit:
Hello I found another way to solve my problem.
The website is automatically generating an image for each of the students. The url of an image is similar to this link
(had some problems posting the URL)
Where you got &week=42 (you can change this to whatever you want and it works perfect). So I got it working for the MAC (in Safari 5).
But when I try to use this URL in the iPhone simulator I only get a white screen.
this is the code i use:
[webView loadRequest:[NSURLRequest
requestWithURL:[NSURL
URLWithString:#"http://www.novasoftware.se/ImgGen/schedulegenerator.aspx?format=png&schoolid=60810/nb-no&type=3&id={76C567C0-161E-42C3-B054-8941DDD04F52}&period=&week=42&mode=0&printer=0&colors=32&head=0&clock=0&foot=0&day=0&width=1405&height=683&maxwidth=1405&maxheight=683"]]];
It works if I use a simpler URL like "http://www.google.com" :S Does the iPhone not support for aspx?
I only know this in the context of iPhone APIs...
Assuming you have the page loaded in a UIWebView inside your app...
You can call UIWebView method stringByEvaluatingJavaScriptFromString: to send javascript to the page.
If the calling function returns anything, it will be typecast as a NSString and returned to your app, but in your case it looks like you can just ignore the return value. You might need to make your Javascript look something like:
(function(){
change();
return "hello world";
})();
because I'm not sure how well it handles void return values.
I'm trying to figure out why something with Javascript isn't working inside of a UIWebView. To my knowledge, there is no way to set a breakpoint inside of XCode for a js file. No problemo, I'll just go back to 2004 and use alert statemen-- oh wait they don't seem to work inside of a UIWebView either!
The only thing I could think of is by exporting my HTML And JS files to my desktop and then just doing my debugging inside of Safari. And that works! But of course, the bug I'm fighting with in the UIWebView doesn't occur in Safari.
Are there any other ways for debugging inside of a UIWebView, or any tricks that I can use akin to using the old-school alert method?
If you're using iOS >= 6 and you have mountain lion (10.8) or Safari >= 6, you can just:
Open the application in the simulator (or your device in XCode >= 4.5.x).
Open Safari (go to Preferences -> Advanced and make sure "Show Develop Menu in Menubar" is on.
From the Menu-bar (of Safari) select Develop -> iPhone Simulator -> [your webview page].
That's it !
This query tops google, so worth linking to the remoteInspector hidden in iOS5 - by far the best way found so far to debug your UIWebViews - just conditional compile out before you send to Apple.
alert() certainly works for me.
However, you can also do lots of other things, like make your own DHTML alert that pops up in a layer. This can be nice because you can do multiple alerts to a single div, without stopping your app. You should also be able to write a stack trace to it (the stack trace is in the exception object, and you can always throw your own exceptions).
Alternatively, if running on the simulator your custom "alert()" could call into objective C, and display the string in the iPhone simulator's console window:
document.location.href = "http://debugger/" +
encodeURIComponent(outputString);
and on the objective C side:
//--------------------------------------------------------------------
- (BOOL)webView:(UIWebView*)webView
shouldStartLoadWithRequest: (NSURLRequest*)req
navigationType:(UIWebViewNavigationType)navigationType {
if ([[[req URL] host] isEqualToString:#"debugger"]){
// do stuff with [[req URL] path]
}
}
That said, I have an app that is heavy on the UiWebView / javascript stuff, and I tend to do most javascript dev in Chrome (simulating what is necessary from the iPhone environment)
I get the awesome way to debug UIWebView Or
SFSafariViewController.
I hope It will Help.
Step 1:
Open Safari VC In Your Mac (hahaha Don't make your face, If I am saying in your Macbook just follow this my steps)
Step2: Go at Safari preferences And Click on Advance.
You will Get this setting on your MacBook Screen.
Now enable the Show to develop menu in menu bar.
Now Your All work is done.
Are you thinking I am kidding :P :P no man...
Step3: Run your application in Device or Simulator. (Don’t Think Just run )
And go in your application where you are opening your Webview or SFSafariViewController.
Till now you did not understand I know. Be cool and see my next step.
Step4: Open Safari In your MacBook and Click on Develop Option from the Menu bar.
Did you get something your MacBook, iPad/ iPhone is Displaying Right?????
Step5: Its Done. click your device and click on URL New popup will come out like This.
Step6: what are you looking now its over here all the steps.
Now debug your Webpage on this console.
Be happy and enjoy your day while doing coding With a cup of tea or
Coffee.
IMP: Don't forget to enable See Below Image
I haven't tried this yet, but take a look at this Weinre
Looks very promising.
This is an old question. But I'll still like to share my two cents.
I have been using jsconsole.com for remote debugging. It's easy. Just include a script tag and use console logs to debug by printing. This can also be used for debugging on a real device.
Old question, but I think I found the best solution, in my case you need to debug uiwebview, but I had no access to the IOS app and only to the html content and I had to view some JS logs, I added the following code to load the light firebug JS and show it automatically:
calling it from JS
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://getfirebug.com/firebug-lite-debug.js';
document.head.appendChild(script);
or load it from html
<script type="text/javascript" src="https://getfirebug.com/firebug-lite-debug.js"></script>
You can set up a system like that used in PhoneGap to send messages from JavaScript to Objective-C and log from there. In a nutshell, they are setting document.location with a custom scheme and blocking that scheme in the delegate callback.
You can take advantage of the fact that a UIWebView is most of the delegates for a WebView. WebKit is technically undocumented for iPhone, but mostly the same as specified in the desktop WebKit headers, possibly including the WebScriptObject. I use this for debugging, but be sure to strip this code out before submitting to Apple.
To get a WebView from a UIWebView, implement a delegate method like -(void) webView:(id)inWebView didFinishLoadForFrame:(id)inWebFrame in a subclass of UIWebView. Call super if you use that one.
I'm trying to call a function in a Silverlight 4 component to open a file dialog and upload a file to the server. Everything works well within Silverlight but I'd like to call the component from JavaScript. So I call the button click handler from a C#-function which is [ScriptableMember]. I get the following error when calling the function:
System.Security.SecurityException: Dialogs must be user-initiated.
at System.Windows.Browser.ManagedObjectInfo.Invoke(ManagedObject obj, InvokeType
invokeType, String memberName, ScriptParam[] args) at
System.Windows.Hosting.ManagedHost.InvokeScriptableMember(IntPtr pHandle, Int32 nMemberID,
Int32 nInvokeType, Int32 nArgCount, ScriptParam[] pArgs, ScriptParam& pResult,
ExceptionInfo& pExcepInfo)
I based my code on the tutorial by Tim Heuer that can be found here: http://www.silverlight.net/learn/videos/silverlight-videos/openfiledialog-and-file-upload/
I understand why the error is thrown, sort of, the 'click' from the user is done in JavaScript and probably is not going through to Silverlight. For Silverlight this is merely a function call.
Is this new policy from Silverlight 4? Is it still possible to only use Silverlight behind to screens to upload a file? Any help is appreciated.
I believe in Silverlight 2 this may have been permitted, but ever since it has not. This was a breaking behavior change, requiring the action to be "user initiated" through a user action -in- Silverlight: something like a key press or mouse click on a button with a click event handler.
There isn't a way to pop up and open the file dialog any other way.