The Principle of Hybrid App.

4,868 views

Published on

The Principle of Hybrid App.
This slide is shown by musart in GTUG(Google Technology User Group) seoul 6th Seminar.

Published in: Technology
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,868
On SlideShare
0
From Embeds
0
Number of Embeds
2,499
Actions
Shares
0
Downloads
0
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • The Principle of Hybrid App.

    1. 1. The Principle of Hybrid App. @musart
    2. 2. The solutions is Hybrid App...
    3. 3. What is Hybrid App.? ? : http://www.phonegap.com/
    4. 4. The type of Hybrid App.• Run-time Hybrid App. • phonegap • appspresso• Build-time Hybrid App. • titanium
    5. 5. Build-time vs. Run-timeJavaScript JavaScript, CSS, html App. WebView Graphic Graphic Context Context
    6. 6. Build-time vs. Run-time JavaScript JavaScript, CSS, htmlConvert JS to Java, Obj-C Package App. App. WebView Graphic Graphic Context Context
    7. 7. Build-time vs. Run-time JavaScript JavaScript, CSS, htmlConvert JS to Java, Obj-C Connect JS and Java, Obj-C Package App. Package App. App. WebView Graphic Graphic Context Context
    8. 8. Magic Point in Android
    9. 9. Magic Point in Android<!DOCTYPE html> <head> <script> function changeText() { document.getElementById(‘myDiv’).innerHTML = MyHybrid.hello(); } </script> </head> <body> <b id=‘myDiv’>Hello world.</b><br/> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/> </body></html>public class HybirdApp extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WebView webView = findResourceById(R.id.WebView); webView.loadUrl(“file:///android_asset/www/index.html”); webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new MyHybrid(), “MyHybrid”); } class MyHybrid { public String hello() { return “Hello hybrid App.”; } }}
    10. 10. Magic Point in Android<!DOCTYPE html> <head> <script> function changeText() { document.getElementById(‘myDiv’).innerHTML = MyHybrid.hello(); } </script> </head> <body> <b id=‘myDiv’>Hello world.</b><br/> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/> </body></html>public class HybirdApp extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WebView webView = findResourceById(R.id.WebView); webView.loadUrl(“file:///android_asset/www/index.html”); webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new MyHybrid(), “MyHybrid”); } class MyHybrid { public String hello() { return “Hello hybrid App.”; } }}
    11. 11. Magic Point in Android<!DOCTYPE html> <head> <script> function changeText() { document.getElementById(‘myDiv’).innerHTML = MyHybrid.hello(); } </script> </head> <body> <b id=‘myDiv’>Hello world.</b><br/> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/> </body></html>public class HybirdApp extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WebView webView = findResourceById(R.id.WebView); webView.loadUrl(“file:///android_asset/www/index.html”); webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new MyHybrid(), “MyHybrid”); } class MyHybrid { public String hello() { return “Hello hybrid App.”; } }}
    12. 12. 1. parameter type• Which type of parameter in JavaScript is suitable for Java? • numeric, boolean, string • object, array, function
    13. 13. 1. parameter type<script> function changeText() { var str = MyHybrid.setInt(20) + “<br/>”; str += MyHybrid.setFloat(20.5) + “<br/>”; str += MyHybrid.setBoolean(true) + “<br/>”; str += MyHybrid.setString(“hello”) + “<br/>”; document.getElementById(‘paramTest’).innerHTML = str; }</script><body> <div id=‘paramTest’></div></body>class MyHybrid { public String setInt(int data) { return “setInt:” + Integer.toString(data); } public String setFloat(float data) { return “setFloat:” + Float.toString(data); } public String setBoolean(boolean data) { return “setBoolean:” + Boolean.toString(data); } public String setString(String data) { return “setString:” + data; }}
    14. 14. 1. parameter type<script> function changeText() { var str = MyHybrid.setInt(20) + “<br/>”; str += MyHybrid.setFloat(20.5) + “<br/>”; str += MyHybrid.setBoolean(true) + “<br/>”; str += MyHybrid.setString(“hello”) + “<br/>”; document.getElementById(‘paramTest’).innerHTML = str; }</script><body> <div id=‘paramTest’></div></body>class MyHybrid { public String setInt(int data) { return “setInt:” + Integer.toString(data); } public String setFloat(float data) { return “setFloat:” + Float.toString(data); } public String setBoolean(boolean data) { return “setBoolean:” + Boolean.toString(data); } public String setString(String data) { return “setString:” + data; }}
    15. 15. 1. parameter type<script> function changeText() { var str = MyHybrid.setObject({}) + “<br/>”; str += MyHybrid.setArray([]) + “<br/>”; str += MyHybrid.setFunction(func1) + “<br/>”; document.getElementById(‘paramTest’).innerHTML = str; } function func1() { var value1=0; }</script><body> <div id=‘paramTest’></div></body>class MyHybrid { public String setObject(String data) { return “setObject:” + data; } public String setArray(String data) { return “setArray:” + data; } public String setFunction(String data) { return “setFunction:” + data; }}
    16. 16. 1. parameter type<script> function changeText() { var str = MyHybrid.setObject({}) + “<br/>”; str += MyHybrid.setArray([]) + “<br/>”; str += MyHybrid.setFunction(func1) + “<br/>”; document.getElementById(‘paramTest’).innerHTML = str; } function func1() { var value1=0; }</script><body> <div id=‘paramTest’></div></body>class MyHybrid { public String setObject(String data) { return “setObject:” + data; } public String setArray(String data) { return “setArray:” + data; } public String setFunction(String data) { return “setFunction:” + data; }}
    17. 17. 1. parameter type<script> function changeText() { var str = MyHybrid.setObject( JSON.stringify({}) ) + “<br/>”; str += MyHybrid.setArray( JSON.stringify([]) ) + “<br/>”; str += MyHybrid.setFunction( func1.toString() ) + “<br/>”; document.getElementById(‘paramTest’).innerHTML = str; } function func1() { var value1=0; }</script><body> <div id=‘paramTest’></div></body>class MyHybrid { public String setObject(String data) { return “setObject:” + data; } public String setArray(String data) { return “setArray:” + data; } public String setFunction(String data) { return “setFunction:” + data; }}
    18. 18. 1. parameter type<script> function changeText() { var str = MyHybrid.setObject( JSON.stringify({}) ) + “<br/>”; str += MyHybrid.setArray( JSON.stringify([]) ) + “<br/>”; str += MyHybrid.setFunction( func1.toString() ) + “<br/>”; document.getElementById(‘paramTest’).innerHTML = str; } function func1() { var value1=0; }</script><body> <div id=‘paramTest’></div></body>class MyHybrid { public String setObject(String data) { return “setObject:” + data; } public String setArray(String data) { return “setArray:” + data; } public String setFunction(String data) { return “setFunction:” + data; }}
    19. 19. 2. asynchronous function in Java• If JavaScript is stuck ? • OMG!! • ANR!!
    20. 20. 2. asynchronous function in Java<script> var start = new Date().getTime(); setInterval(function() { document.getElementById(‘tTest’).innerHTML+=(new Date().getTime()-start)+“msec<br/>”; }, 1000); function changeText() { document.getElementById(‘tTest’).innerHTML += “call MyHybrid.hang()<br/>”; MyHybrid.hang(5); document.getElementById(‘tTest’).innerHTML += “hang 5secs<br/>”; }</script><body> <div id=‘tTest’></div> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/></body>class MyHybrid { public void hang(int time) { try { Thread.sleep(time*1000); } catch (InterruptedException e) { e.printStackTrace(); } }}
    21. 21. 2. asynchronous function in Java<script> var start = new Date().getTime(); setInterval(function() { document.getElementById(‘tTest’).innerHTML+=(new Date().getTime()-start)+“msec<br/>”; }, 1000); function changeText() { document.getElementById(‘tTest’).innerHTML += “call MyHybrid.hang()<br/>”; MyHybrid.hang(5); document.getElementById(‘tTest’).innerHTML += “hang 5secs<br/>”; }</script><body> <div id=‘tTest’></div> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/></body>class MyHybrid { public void hang(int time) { try { Thread.sleep(time*1000); } catch (InterruptedException e) { e.printStackTrace(); } }}
    22. 22. 2. asynchronous function in Java<script> var start = new Date().getTime(); setInterval(function() { document.getElementById(‘tTest’).innerHTML+=(new Date().getTime()-start)+“msec<br/>”; }, 1000); function changeText() { document.getElementById(‘tTest’).innerHTML += “call MyHybrid.asyncJob()<br/>”; MyHybrid.asyncJob(5); document.getElementById(‘tTest’).innerHTML += “hang 5secs<br/>”; }</script><body> <div id=‘tTest’></div> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/></body>class MyHybrid { public void asyncJob(final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }}
    23. 23. 2. asynchronous function in Java<script> var start = new Date().getTime(); setInterval(function() { document.getElementById(‘tTest’).innerHTML+=(new Date().getTime()-start)+“msec<br/>”; }, 1000); function changeText() { document.getElementById(‘tTest’).innerHTML += “call MyHybrid.asyncJob()<br/>”; MyHybrid.asyncJob(5); document.getElementById(‘tTest’).innerHTML += “hang 5secs<br/>”; }</script><body> <div id=‘tTest’></div> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/></body>class MyHybrid { public void asyncJob(final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }}
    24. 24. 3. return value & callback function• When functions are changed asynchronously, how to return results to the caller exactly?
    25. 25. 3. return value & callback function<script> var start = new Date().getTime(); setInterval(function() { document.getElementById(‘tTest’).innerHTML+=(new Date().getTime()-start)+“msec<br/>”; }, 1000); function changeText() { document.getElementById(‘tTest’).innerHTML += “call MyHybrid.asyncJob()<br/>”; MyHybrid.asyncJob(5); document.getElementById(‘tTest’).innerHTML += “hang 5secs<br/>”; }</script><body> <div id=‘tTest’></div> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/></body>class MyHybrid { public void asyncJob(final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); // how to return results? } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }}
    26. 26. 3. return value & callback function<script> var start = new Date().getTime(); setInterval(function() { document.getElementById(‘tTest’).innerHTML+=(new Date().getTime()-start)+“msec<br/>”; }, 1000); function changeText() { document.getElementById(‘tTest’).innerHTML += “call MyHybrid.asyncJob()<br/>”; MyHybrid.asyncJob(5); document.getElementById(‘tTest’).innerHTML += “hang 5secs<br/>”; }</script><body> <div id=‘tTest’></div> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/></body>class MyHybrid { public void asyncJob(final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); // how to return results? } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }}
    27. 27. 3. return value & callback function<script> var start = new Date().getTime(); setInterval(function() { document.getElementById(‘tTest’).innerHTML+=(new Date().getTime()-start)+“msec<br/>”; }, 1000); function changeText() { document.getElementById(‘tTest’).innerHTML += “call MyHybrid.asyncJob()<br/>”; MyHybrid.asyncJob(5); document.getElementById(‘tTest’).innerHTML += “hang 5secs<br/>”; }</script><body> <div id=‘tTest’></div> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/></body>class MyHybrid { public void asyncJob(final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); mWebView.loadUrl(“javascript:document.getElementById(‘tTest’).innerHTML +=”finish asyncJob()<br/>””); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }
    28. 28. 3. return value & callback function<script> var start = new Date().getTime(); setInterval(function() { document.getElementById(‘tTest’).innerHTML+=(new Date().getTime()-start)+“msec<br/>”; }, 1000); function changeText() { document.getElementById(‘tTest’).innerHTML += “call MyHybrid.asyncJob()<br/>”; MyHybrid.asyncJob(5); document.getElementById(‘tTest’).innerHTML += “hang 5secs<br/>”; }</script><body> <div id=‘tTest’></div> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/></body>class MyHybrid { public void asyncJob(final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); mWebView.loadUrl(“javascript:document.getElementById(‘tTest’).innerHTML +=”finish asyncJob()<br/>””); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }
    29. 29. 3. return value & callback function<script> var start = new Date().getTime(); setInterval(function() { document.getElementById(‘tTest’).innerHTML+=(new Date().getTime()-start)+“msec<br/>”; }, 1000); function changeText() { document.getElementById(‘tTest’).innerHTML += “call MyHybrid.aFuncJob()<br/>”; MyHybrid.aFuncJob(asyncFunction.toString().match(/^s*functions+([^s(]+)/)[1], 5); document.getElementById(‘tTest’).innerHTML += “aFuncJob 5secs<br/>”; } function asyncFunction(str) { document.getElementById(‘tTest’).innerHTML += “asyncFunction:” + str + “<br/>”; }</script><body>class MyHybrid { public String aFuncJob(final String strFunc, final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); mWebView.loadUrl(“javascript:” + strFunc + “(”finish aFuncJob()<br/>”)”); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }}
    30. 30. 3. return value & callback function<script> var start = new Date().getTime(); setInterval(function() { document.getElementById(‘tTest’).innerHTML+=(new Date().getTime()-start)+“msec<br/>”; }, 1000); function changeText() { document.getElementById(‘tTest’).innerHTML += “call MyHybrid.aFuncJob()<br/>”; MyHybrid.aFuncJob(asyncFunction.toString().match(/^s*functions+([^s(]+)/)[1], 5); document.getElementById(‘tTest’).innerHTML += “aFuncJob 5secs<br/>”; } function asyncFunction(str) { document.getElementById(‘tTest’).innerHTML += “asyncFunction:” + str + “<br/>”; }</script><body>class MyHybrid { public String aFuncJob(final String strFunc, final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); mWebView.loadUrl(“javascript:” + strFunc + “(”finish aFuncJob()<br/>”)”); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }}
    31. 31. 4. anonymous callback function• We use anonymous callback functions in JavaScript, normally. setInterval(function() { alert(“hello”); }, 1000);• Let’s make it possible!
    32. 32. 4. anonymous callback function<script> function changeText() { var str = MyHybrid.setFunction( func1.toString() ) + “<br/>”; str += MyHybrid.setFunction((function func2() {var value2=0;}).toString()) + “<br/>”; str += MyHybrid.setFunction((function() {var value3=0;}).toString()) + “<br/>”; document.getElementById(‘paramTest’).innerHTML = str; } function func1() { var value1=0; }</script><body> <div id=‘paramTest’></div></body>class MyHybrid { public String setFunction(String data) { return “setFunction:” + data; }}
    33. 33. 4. anonymous callback function<script> function changeText() { var str = MyHybrid.setFunction( func1.toString() ) + “<br/>”; str += MyHybrid.setFunction((function func2() {var value2=0;}).toString()) + “<br/>”; str += MyHybrid.setFunction((function() {var value3=0;}).toString()) + “<br/>”; document.getElementById(‘paramTest’).innerHTML = str; } function func1() { var value1=0; }</script><body> <div id=‘paramTest’></div></body>class MyHybrid { public String setFunction(String data) { return “setFunction:” + data; }}
    34. 34. 4. anonymous callback function<script> function changeText() { document.getElementById(‘tTest’).innerHTML += “call HybridFunc()<br/>”; HybridFunc(function(str) { document.getElementById(‘tTest’).innerHTML += “callbackFunc:” + str + “<br/>” }, 5); } function HybridFunc(cb, arg) { CbMgr.callCbFunc(cb, arg); } var CbMgr = {}; CbMgr.cbId = 0; CbMgr.cbs = {}; CbMgr.callCbFunc = function(func, arg) { var id = “CbMgr” + CbMgr.cbId++; if(!CbMgr.cbs[id]) { CbMgr.cbs[id] = func; MyHybrid.aFuncJobWithId(id, arg); } }; CbMgr.fireCbFunc = function(id, args) { if(CbMgr.cbs[id]) { CbMgr.cbs[id](args); delete CbMgr.cbs[id]; } };</script><body> <div id=‘tTest’></div> <input type=‘button’ onclick=‘changeText()’ value=‘Change Text’/></body>
    35. 35. 4. anonymous callback function<script> function changeText() { document.getElementById(‘tTest’).innerHTML += “call HybridFunc()<br/>”; HybridFunc(function(str) { document.getElementById(‘tTest’).innerHTML += “callbackFunc:” + str + “<br/>” }, 5); } function HybridFunc(cb, arg) { CbMgr.callCbFunc(cb, arg); } ...</script>public String aFuncJobWithId(final String strId, final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); mWebView.loadUrl(“javascript:CbMgr.fireCbFunc(”” + strId + “”, ”finishaFuncJobWithId()<br/>”)”); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }
    36. 36. 4. anonymous callback function<script> function changeText() { document.getElementById(‘tTest’).innerHTML += “call HybridFunc()<br/>”; HybridFunc(function(str) { document.getElementById(‘tTest’).innerHTML += “callbackFunc:” + str + “<br/>” }, 5); } function HybridFunc(cb, arg) { CbMgr.callCbFunc(cb, arg); } ...</script>public String aFuncJobWithId(final String strId, final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); mWebView.loadUrl(“javascript:CbMgr.fireCbFunc(”” + strId + “”, ”finishaFuncJobWithId()<br/>”)”); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }
    37. 37. To use generally<script src=”MyHybrid.js”></script><script> function changeText() { document.getElementById(‘tTest’).innerHTML += “call HybridFunc()<br/>”; HybridFunc(function(str) { document.getElementById(‘tTest’).innerHTML += “callbackFunc:” + str + “<br/>” }, 5); HybridFunc(function(str) { alert(str); }, 1); HybridFunc(function(str) { if(str == “handsome guy”) alert(“”); }, {age : 20, name : “musart”); }</script>class MyHybrid { public String aFuncJobWithId(final String strId, final int time) { Thread thread = new Thread(new Runnable() { public void run() { try { Thread.sleep(time*1000); mWebView.loadUrl(“javascript:CbMgr.fireCbFunc(”” +strId+ “”, ” +time+ ”)”); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); }}
    38. 38. Simple Hybrid App.• If you draw 10 dots, get results from Java.
    39. 39. Simple Hybird App.<!DOCTYPE html><head> <script> /* MyHybrid.js */ function HybridFunc(action, cb, arg) { CbMgr.callCbFunc(action, cb, arg); } var CbMgr = {}; CbMgr.cbId = 0; CbMgr.cbs = {}; CbMgr.callCbFunc = function(action, cb, arg) { var id = "CbMgr" + CbMgr.cbId++; if(!CbMgr.cbs[id]) { CbMgr.cbs[id] = cb; MyHybrid.HybridFunc(action, id, arg); } }; CbMgr.fireCbFunc = function(id, args) { if(CbMgr.cbs[id]) { CbMgr.cbs[id](args); delete CbMgr.cbs[id]; } } </script> ...</head><body> ...</body></html>
    40. 40. Simple Hybird App.<script>function startDotGame() { var canvas = document.getElementById("canvas1"); ctx = canvas.getContext("2d"); canvas.addEventListener("touchstart", function(event) { ctx.beginPath(); ctx.lineWidth = 10; ctx.moveTo(event.touches[0].pageX, event.touches[0].pageY); ctx.lineTo(event.touches[0].pageX+1, event.touches[0].pageY+1); ctx.stroke(); }); canvas.addEventListener("touchmove", function(event) {}); canvas.addEventListener("touchend", function(event) { ctx.stroke(); ctx.closePath(); ctx.save(); HybridFunc("addDot", function() {}); }); HybridFunc("startDot", function(value) { ctx.beginPath(); ctx.fillText(value, 50, 50); ctx.stroke(); ctx.closePath(); ctx.save(); }); document.getElementById(btn).value = "stop";}</script>
    41. 41. Simple Hybird App.<!DOCTYPE html><head> ...</head><body> <canvas id="canvas1" width=300 height=300 style="position: relative; border: 1pxsolid #000;"></canvas> <input id="btn" type=button onclick=startDotGame() value=start/></body></html>
    42. 42. Simple Hybird App.package com.HybridApp;import android.app.Activity;import android.os.Bundle;import android.view.ViewGroup.LayoutParams;import android.webkit.WebChromeClient;import android.webkit.WebView;import android.widget.LinearLayout;import com.HybridApp.R;public class HybridAppActivity extends Activity { /** Called when the activity is first created. */ private WebView mWebView = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //mWebView = (WebView) findViewById(R.id.webView); mWebView = new WebView(this); mWebView.setLayoutParams(new LinearLayout.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); setContentView(mWebView); mWebView.loadUrl("file:///android_asset/www/index2.html"); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.addJavascriptInterface(new MyHybrid(), "MyHybrid"); } ...}
    43. 43. Simple Hybird App. class MyHybrid { public int dotNum = 0; public void addDot(final String cbId, final String arg) { dotNum++; } public void startDot(final String cbId, final String arg) { dotNum = 0; final Thread thread = new Thread(new Runnable() { public void run() { while(true) { if(dotNum == 10) { mWebView.loadUrl("javascript:CbMgr.fireCbFunc("" + cbId + "", "finish1")"); break; } else { try { Thread.sleep(500); } catch (InterruptedException e) {} } } }}); thread.start(); } public void HybridFunc(final String strFunc, final String cbId, final String arg) { if("addDot".equals(strFunc)) { addDot(cbId, arg); } else if("startDot".equals(strFunc)) { startDot(cbId, arg); } }}
    44. 44. Thank you @musart all source codes are in github.https://github.com/musart/HybridApplication

    ×