Websocket performance issue on iOS 11 - ios

I have a websocket server and I run in a html page the following code:
<!DOCTYPE html><head>
<title>In/Out: Test</title>
<script type="text/javascript">
var socket;
function onLoad() {
socket = new WebSocket("ws://10.10.10.1:80", "inout");
socket.onopen = function() {
socket.send("update");
}
var previous = 0;
socket.onmessage = function got_packet(msg) {
var now = Date.now();
var st = "" + (now - previous) + " ms";
previous = now;
console.log(st);
document.getElementById("debug").innerHTML = st;
}
}
</script>
</head>
<body onload="onLoad();">
<span id="debug" name="debug" style="font-size:300%"></span></body></html>
The server sends messages at least every 100ms.
Everywhere (Windows, Linux, Android, even MacOS), it's working very well, I receive messages at the same rate.
On iOS 11 (iPod touch, iPhone), with ANY browser (Safari, Chrome) it's extremely slow and I receive messages at best every 1200ms.
Here are two devices (Android phone and iPod touch 6th gen):
This report (here) seems to be similar to my problem.
Any idea what could be the issue? Anyone experiencing the same problem?

Related

get content of webview in nativescript

Is there a way I can read the content of webview after the page is loaded ?
The reason is redirect (like window.location.replace or window.location.href ) is not working in IOS in my case, works fine in Android.
https://docs.nativescript.org/cookbook/ui/web-view
I can access url, error. but how to access content ?
Narayan
I was only looking for IOS. I found the answer and sharing it here. For Android I would like to point some leads.
if (webView.ios) {
var webHeader = webView.ios.stringByEvaluatingJavaScriptFromString("document.head.innerHTML").trim();
console.log(webHeader);
var webBody = webView.ios.stringByEvaluatingJavaScriptFromString("document.body.innerHTML").trim();
console.log(webBody);
} else if (webView.android) {
webTitle = webView.android.getTitle(); //getting the title title
console.log(webTitle)
}
Some stack overflow lead for Android
You could look at this post. installs a library that allows communication with the webview through observables. Right now I'm using it myself and it's great for both iOS and Android
1- install:
tns plugin add nativescript-webview-interface
2- in web project copy plugin file
cp node_modules/nativescript-webview-interface/www/nativescript-webview-interface.js app/www/lib/
3- code:
xml:
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
loaded="pageLoaded">
<web-view id="webView"></web-view>
</Page>
var webViewInterfaceModule = require('nativescript-webview-
interface');
var oWebViewInterface;
function pageLoaded(args){
page = args.object;
setupWebViewInterface(page)
}
function setupWebViewInterface(page){
var webView = page.getViewById('webView');
oWebViewInterface = new
webViewInterfaceModule.WebViewInterface(webView, '~/www/index.html');
}
function handleEventFromWebView(){
oWebViewInterface.on('anyEvent', function(eventData){
// perform action on event
});
}
function emitEventToWebView(){
oWebViewInterface.emit('anyEvent', eventData);
}
function callJSFunction(){
oWebViewInterface.callJSFunction('functionName', args, function(result){
});
}
web-view:
<html>
<head></head>
<body>
<script src="path/to/nativescript-webview-interface.js"></script>
<script src="path/to/your-custom-script.js"></script>
</body>
web-view js:
var oWebViewInterface = window.nsWebViewInterface;
// register listener for any event from native app
oWebViewInterface.on('anyEvent', function(eventData){
});
// emit event to native app
oWebViewInterface.emit('anyEvent', eventData);
// function which can be called by native app
window.functionCalledByNative = function(arg1, arg2){
// do any processing
return dataOrPromise;
}
More Info:
https://www.npmjs.com/package/nativescript-webview-interface
http://shripalsoni.com/blog/nativescript-webview-native-bi-directional-communication/
This will work for IOS
if (webview.ios){
url = args.url;
}

ActionScript's File.upload does not work on Air SDK for iOS devices

I am trying to use ActionScript's File.upload to upload a file on Air SDK for iOS environment, but the File.upload does not work properly. No handler about the file upload is executed after File.upload is invoked, and no exception is caught. When I check the network traffic of the server side, I found that no http request even hit the server after executing File.upload. The code is below.
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="HomeView">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
<fx:Script>
<![CDATA[
private var file:File;
private var dir:File;
//This method is executed to create a file and upload it when the Upload Button is pressed.
protected function OnUploadButtonPressed(event:MouseEvent):void{
trace("upload button clicked");
var urlReq:URLRequest = new URLRequest("http://10.60.99.31/MyPath/fileUploadTest.do");
urlReq.method = URLRequestMethod.POST;
var str:String = 'This is test';
var imageBytes:ByteArray = new ByteArray();
for ( var i:int = 0; i < str.length; i++ ) {
imageBytes.writeByte( str.charCodeAt(i) );
}
trace("size = " + imageBytes.length);
try{
dir = File.applicationStorageDirectory
//I also tested in several different directories
//dir = File.createTempDirectory();
//dir = File.documentsDirectory;
var now:Date = new Date();
var filename:String = "IMG" + now.fullYear + now.month + now.day + now.hours + now.minutes + now.seconds + now.milliseconds + ".txt";
file = dir.resolvePath( filename );
var stream:FileStream = new FileStream();
stream.open( file, FileMode.WRITE );
stream.writeBytes( imageBytes );
stream.close();
//Read back the file contents to check whether the file is written successfully.
var readStream:FileStream = new FileStream();
readStream.open(file, FileMode.READ);
var result:String = readStream.readUTFBytes(readStream.bytesAvailable);
trace("read back result = " + result);//The result is shown here as expected.
file.addEventListener( Event.COMPLETE, uploadComplete );
file.addEventListener( IOErrorEvent.IO_ERROR, ioError );
file.addEventListener( SecurityErrorEvent.SECURITY_ERROR, securityError );
file.addEventListener(ErrorEvent.ERROR, someError);
file.addEventListener(ProgressEvent.PROGRESS, onProgress);
file.upload( urlReq );//This line does not work. No handler is executed. No http request hit the server side.
trace("after file upload test");
}
catch( e:Error )
{
trace( e );
}
}
//Complete Handler
private function uploadComplete( event:Event ):void
{
trace( "Upload successful." );
}
//IOError handler
private function ioError( error:IOErrorEvent ):void
{
trace( "Upload failed: " + error.text );
}
//SecurityError handler
private function securityError(error:SecurityErrorEvent):void{
trace( "Security error:" + error.text );
}
//Other handler
private function someError(error:ErrorEvent):void{
trace("some error" + error.text);
}
//Progress handler
private function onProgress(event:ProgressEvent):void{
trace("progressHandler");
}
//This method is executed to invoke the URLLoader.load when the Tricky Button is pressed.
protected function OnTrickyButtonPressed(event:MouseEvent):void{
var urlReq:URLRequest = new URLRequest("http://200.60.99.31/");//This points to a non-existed server
urlReq.method = URLRequestMethod.POST;
urlReq.data = new ByteArray();
var loader:URLLoader = new URLLoader();
try{
loader.load(urlReq);//This line seems very important in iOS7. It decides whether the latter file.upload can work.
//But in iOS8, file.upload does not work even if this line is executed.
trace("after urlloader load");
}catch(e:Error){
trace(e);
}
}
]]>
</fx:Script>
<s:Button x="200" y="200" width="400" height="200" label="Upload" click="OnUploadButtonPressed(event)" />
<s:Button x="200" y="500" width="400" height="200" label="Tricky" click="OnTrickyButtonPressed(event)" />
</s:View>
When executed on Air Simulator, it works fine as expected, and the file is successfully uploaded to the server. But When executed on iOS devices(in my case, iPad), as I explain early, no handler about the file upload is executed, and no the http request event hit the server. So I think the problem may be in the client side.
During my try to solve the problem, I found something tricky about this problem on iOS7. That is, if you invoke the URLLoader.load method (even if the URLLoader.load points to a non-existed address) before invoking the File.upload method, the File.upload will work as expected on iOS7. More specifically, when method OnTrickyButtonPressed above is executed before method OnUploadButtonPressed, File.upload will succeed on iOS7. But this only happens on iOS7. On iOS8, File.upload always refuses to work, regardless of whether the URLLoader.load is executed before.
I think in my case the problem is not the Sandbox problem or Firefox session problem described in the two links below, because not even any http request hit the server side. It seems that the Air SDK for iOS just failed to send the http request for some reason.
Flex 4 FileReference Issues With Firefox
How do I make Flex file upload work on firefox and safari?
To make my problem more clear, I list my environment below:
Develoment Environment: Windows7 (64bit) / Mac os 10.9.4 (Tested on
two OS platforms.)
IDE: Flash Builder 4.7
Air SDK: 3.8 / 16.0.0 (After I updated to the lastest Air SDK 16.0.0
, the problem still exists.)
Application Server: Tomcat7 + Spring
Finally, I would like to mention that uploading file using URLLoader.load is not an option in my case because I want to upload large files in the future, which can not be handled with the URLLoader.load.
I have been struggling for this for days. So I really appreciate it if anyone has any idea about this.
Thanks in advance.
Finally I found that the real problem is not about the code I provided, it is about the http proxy Auto configuration, and this problem happened on iOS7 and iOS8. I described the problem and a workaround in detail in the following link. Hope this will help some of you.
https://forums.adobe.com/thread/1716036

phonegap app connected to node server by socket.io works on browser but not in app

i setted up a node server, this sends data via socket.io to the clients and use that in a phonegap projekt,
it works fine when i test it in browsers & mobile browsers but it does not work when i build a ios app which i run in the emulator,
part of node server code:
define(['node-static','http'],function (Static,Http) {
return FileServer = function (server) {
var httpFileServer = new Static.Server('./phonegap/www');
Http.createServer(function (request, response) {
request.addListener('end', function () {
httpFileServer.serve(request, response);
}).resume();
}).listen(server.fileServerHTTPport,"0.0.0.0");
return {
// exampleVariable : function() {return exampleVariable},
// exampleFunction : exampleFunction
}
} });
index.html phonegap
... <script src="js/socket.io.js"></script>
<script src="js/jquery-2.0.3.min.js"></script>
<script>
var socket = io.connect('http://'+document.location.hostname+':54321');
socket.on('display', function (data) {
console.log(data.color);
$("h1").text( data.color.h );
});
</script></head>
<body><h1> hello world</h1> ...
I figured out, i have to use the devices default localhost ip,
so for example in ios: 127.0.0.1
var socket = io.connect('http://127.0.0.1:54321');

Google geolocation doesn´t work in mobile browsers

the standard geolocation code from google does not work in mobile browsers (Android Chrome, standard Android browser):
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Reverse Geocoding</title>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var geocoder;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(successFunction, errorFunction, {enableHighAccuracy: true});
}
//Get the latitude and the longitude;
function successFunction(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
codeLatLng(lat, lng)
}
function errorFunction(){
alert("Geocoder failed");
}
function initialize() {
geocoder = new google.maps.Geocoder();
}
function codeLatLng(lat, lng) {
var latlng = new google.maps.LatLng(lat, lng);
geocoder.geocode({'latLng': latlng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
console.log(results)
if (results[1]) {
//formatted address
alert(results[2].address_components[0].long_name)
} else {
alert("No results found");
}
} else {
alert("Geocoder failed due to: " + status);
}
});
}
</script>
</head>
<body onload="initialize()">
</body>
</html>
But in Desktop Browser it works fine... Why? I´m sure the code has worked a few days ago. I didn´t change anything. is it possible that google has changed something in their code?
EDIT: it´s important for me to get the location with GPS, WLAN AND! mobile network
Try changing the sensor parameter to true like below.
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=true"></script>
Go through Geolocation documentation of Google maps API.
Specifying the Sensor Parameter
Use of the Google Maps API requires that you indicate whether your
application is using a sensor (such as a GPS locator) to determine the
user's location. This is especially important for mobile devices.
Applications must pass a required sensor parameter to the tag
when including the Maps API javascript code, indicating whether or not
your application is using a sensor device.
Applications that determine the user's location via a sensor must pass
sensor=true when loading the Maps API JavaScript.
Hope you understand.

Trouble using Titanium's webview to fire an API event

I'm trying to fire an event from an external HTML page opened inside of Titanium's webview.
app.js file...
var group, now, tab, view, window;
now = new Date();
view = Titanium.UI.createWebView({url: 'http://MYWEBSITE.com/index.htm?time=' + now.getTime()});
window = Titanium.UI.createWindow({tabBarHidden: true, navBarHidden: true});
window.add(view);
Titanium.App.addEventListener('browse', function(e) {
Ti.API.info("I received " + e.something + " from the webview.");
});
group = Titanium.UI.createTabGroup();
tab = Titanium.UI.createTab({title: 'window', window: window});
group.addTab(tab);
group.open(tab);
js excerpt from web page...
$("#testButton").mousedown(function() {
alert ("I got clicked.");
Ti.App.fireEvent('browse', {something:'stuff'});
});
(I include the time in the URL to ensure the page is always fresh.)
Adding the event listener as shown above, or using view.addEventListener, compiles but ultimately doesn't work.
Using Titanium.UI.WebView.addEventListener produces an error message that the object doesn't exist.
Do I need to open the URL/webview in a different manner?
Also, since Titanium.App.fireEvent is not a recognized function, except to Titanium, how does one prevent a JavaScript error?
Thanks.
// from web page
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id='testButton'>TEST BUTTON</div>
</body>
<script>
var _button = document.getElementById ("testButton");
_button.onmousedown = function () {
alert (this.id);
Ti.App.fireEvent('fromwebview', {name:this.id});
return false;
};
</script>
</html>
from apps.js
Ti.App.addEventListener('fromwebview', function(data)
{
Titanium.API.info("--> " + data.name);
});
Just to warn you all - I don't think this works with remote pages anymore for security reasons. Spent ages trying fruitlessly!
You can make this work on your remote html page by including the Titanium Injection code. For sdk 1.8.3 it's the following. Now your remote html page can talk to the device.
var Ti = {_event_listeners:[],createEventListener:function(listener ){ var newListener={ listener:listener ,systemId:-1 ,index:this._event_listeners.length };this._event_listeners.push(newListener);return newListener;},getEventListenerByKey:function(key,arg){for(var i=0;i<this._event_listeners.length;i++){if(this._event_listeners[i][key]==arg){return this._event_listeners[i];}} return null;},API:TiAPI,App:{addEventListener:function(eventName,listener) {var newListener=Ti.createEventListener(listener);newListener.systemId=TiApp.addEventListener(eventName,newListener.index);return newListener.systemId;},removeEventListener:function(eventName,listener) {if(typeof listener=='number'){TiApp.removeEventListener(eventName,listener);var l=Ti.getEventListenerByKey('systemId',listener);if(l!==null){Ti._event_listeners.splice(l.index,1);}}else{l=Ti.getEventListenerByKey('listener',listener);if(l!==null){TiApp.removeEventListener(eventName,l.systemId);Ti._event_listeners.splice(l.index,1);}}},fireEvent:function(eventName,data) {TiApp.fireEvent(eventName,JSON.stringify(data));}},executeListener:function(id,data) {var listener=this.getEventListenerByKey('index',id);if(listener!==null){listener.listener.call(listener.listener,data);}}};var Titanium=Ti;

Resources