精华内容
参与话题
问答
  • 混合 APP 开发(Hybrid App)

    万次阅读 2018-06-01 11:24:18
    混合 App Html5简介 UIWebView 和 WKWebView UIWebView 和 JS 交互 WKWebView 和 JS 交互 JS 调用 Native 相机 一. 混合 APP Hybrid Mobile App 可以理解为通过 Web 网络技术(如 HTML,CSS 和 JavaScript)...

    目录

    • 混合 App
    • Html5简介
    • UIWebView 和 WKWebView
    • UIWebView 和 JS 交互
    • WKWebView 和 JS 交互
    • JS 调用 Native 相机

     

    一. 混合 APP

    Hybrid Mobile App 可以理解为通过 Web 网络技术(如 HTML,CSS 和 JavaScript)与 Native 相结合的混合移动应用程序。

    H5用于大体界面的编写,如:需要一些基本的输入框、单选按钮、普通按钮、以及下拉选择框等。

    CSS3则是主要用于对整体界面细节化的修饰。比如:一个普通按钮,输入框边角默认是直角,那我们可以用CSS来改变其形状。

    还可以用来设置不同的样式。

    JS主要是要跟服务端打交道,实现数据交互。JS中的数据交互,主要以JSON格式跟XML格式这两种格式实现。

    总体来说,H5+CSS3负责界面的搭建,JS负责数据的交互。

     

     

    二. HTML5简介

     

    下面简述一下 Hybrid 的发展史:

     

    1.H5 发布

     

    Html5 是在 2014 年 9 月份正式发布的,这一次的发布做了一个最大的改变就是“从以前的 XML 子集升级成为一个独立集合”。

     

     

     

    2.H5 渗入 Mobile App 开发

     

    Native APP 开发中有一个 webview 的组件(Android 中是 webview,iOS 有 UIWebview和 WKWebview),这个组件可以加载 Html 文件。

    在 H5 大行其道之前,webview 加载的 web 页面很单调(因为只能加载一些静态资源),自从 H5 火了之后,前端猿们开发的 H5 页面在 webview 中的表现不俗使得 H5 开发慢慢渗透到了 Mobile App 开发中来。

     

     

    3.Hybrid 现状

     

    虽然目前已经出现了 RN 和 Weex 这些使用 JS 写 Native App 的技术,但是 Hybrid 仍然没有被淘汰,市面上大多数应用都不同程度的引入了 Web 页面。

     

    三. UIWebView 和 WKWebView

    做浏览器首先要选个好的基础。iOS8提供两类浏览组件:UIWebViewWKWebView

    UIWebView是iOS传统的浏览控件,绝大多数浏览器都采用这个控件作为基础, 如Chrome,Firefox,Safari。UIWebView比较封闭,很多API都不开放,但却一度是唯一的选择。好处是,这个控件使用时间比较长,有很多方案可以参考。

    WKWebView是苹果在iOS8和 OS X Yosemite 中新推出的WebKit中的一个组件。

    它代替了 UIKit 中的UIWebView和AppKit中的WebView,提供了统一的跨双平台 API。支持HTML5的特性, 占用内存可能只有UIWebView的1/3 ~ 1/4, 拥有 60fps 滚动刷新率、内置手势、高效的app和web信息交换通道、和Safari相同的JavaScript引擎, 增加了加载进度属性, 比UIWebView性能更加强大。

    但WKWebView也不是那么完美:如没有控制Cookie的API,  对读取本地html文件的支持也不好等。

     

    四. UIWebView 和 JS 交互

     

    JavaScriptCore介绍

     

    JavaScriptCore 这个库是 Apple 在 iOS 7 之后加入到标准库的,它对 iOS Native 与 JS 做交互调用产生了划时代的影响。

    JavaScriptCore 大体是由 4 个类以及 1 个协议组成的:

     

     

    • JSContext JS 执行上下文,你可以把它理解成 JavaScriptCore 包装出来的 JS 运行的环境。
    • JSValue 是对 JavaScript 值的引用,任何 JS 中的值都可以被包装为一个 JSValue
    • JSManagedValue 是对 JSValue 的包装,加入了“conditional retain”
    • JSVirtualMachine 可以理解为JS 虚拟机JSVirtualMachine中可以创建多个 JSContext 实例他们都是可以独立运行的 JavaScript 执行环境。
    • JSExport 协议:我们可以使用这个协议暴露原生对象,实例方法,类方法,和属性给JavaScript,这样JavaScript就可以调用相关暴露的方法和属性。

     

    Native 调用 JS:

     

    • WebView 直接注入 JS 并执行
    • JavaScriptCore 方法
    WebView 直接注入 JS 并执行
    
    self.webView.stringByEvaluatingJavaScript(from: “jsFuncName()”)
    
    注意:
    这个方法会返回运行 JS 的结果(nullable NSString *),它是一个同步方法,会阻塞当前线程!尽管此方法不被弃用,但最佳做法是使用 WKWebView 类的 evaluateJavaScript:completionHandler:method。注意:
    这个方法会返回运行 JS 的结果(nullable NSString *),它是一个同步方法,会阻塞当前线程!尽管此方法不被弃用,但最佳做法是使用 WKWebView 类的 evaluateJavaScript:completionHandler:method。

     

    JavaScriptCore 方法
    // 导入 JavaScriptCore 库
    
    JavaScriptCore 库提供的 JSValue 类,是对 JavaScript 值的引用。 您可以使用 JSValue 类来转换 JavaScript 和 Objective-C 或 Swift 之间的基本值(如数字和字符串),以便在本机代码和 JavaScript 代码之间传递数据。
    
    Native 代码: 
    self.context = webView.value(forKeyPath: “documentView.webView.mainFrame.javaScriptContext")
    
    let jsValue: JSValue = self.context.objectForKeyedSubscript(“jsFuncName()”)
            jsValue.call(withArguments: ["param1" ,"param2"])
    
    JS 代码: 
    function jsFuncName(param1, param2){
    
    }
    

     

     

     

    JS 调用 Native :

     

    • 拦截 URL 请求
    • Block 方法
    • 模型注入(JavaScriptCore 的 JSExport 协议)
    拦截 URL 请求
    
    用JS 发起一个假的 URL 请求, 然后在 shouldStartLoadWith 代理方法中拦截这次请求, 做出相应处理.
    注意: 
    这里在JS 中自定义一个loadURL 方法发起请求,而不是直接使用 window.location.href
    如果要传递参数, 可以拼接在 URL 上
    
    Native 代码:
    func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
            if request.url?.scheme == "haleyAction" {
                // to do something
                return false
            }
           return true
     }
            
    JS 代码:
    function loadURL(url) {
        var iFrame;
        iFrame = document.createElement("iframe");
                iFrame.setAttribute("src", url);
                iFrame.setAttribute("style", "display:none;");
                iFrame.setAttribute("height", "0px");
                iFrame.setAttribute("width", "0px");
                iFrame.setAttribute("frameborder", "0");
                document.body.appendChild(iFrame);
                // 发起请求后这个 iFrame 就没用了,所以把它从 dom 上移除掉
                iFrame.parentNode.removeChild(iFrame);
                iFrame = null;
            }
        
            function firstClick() {
                //要传递参数时, 可以拼接在url上
                loadURL("haleyAction://shareClick?title=测试分享的标题&content=测试分享的内容&url=http://www.baidu.com");
            }

     

    Block 方法
    
    使用 block 在js中运行原生代码, 将自动与JavaScript方法建立桥梁
    注意: 这种方法仅仅适用于 OC 的 block, 并不适用于swift中的闭包, 为了公开闭包,      
    我们将进行如下两步操作:
    (1)使用 @convention(block) 属性标记闭包,来建立桥梁成为 OC 中的 block
    (2)在映射 block 到 JavaScript方法调用之前,我们需要 unsafeBitCast 函数将block 转成为 AnyObject
    
    Native 代码:
    // JS调用了无参数swift方法
    let closure1: @convention(block) () ->() = {
                
    }
    self.context.setObject(unsafeBitCast(closure1, to: AnyObject.self),   
    forKeyedSubscript: "test1" as NSCopying & NSObjectProtocol)
    
    // JS调用了有参数swift方法
    let closure2: @convention(block) () ->() = {
                
    }
    self.context.setObject(unsafeBitCast(closure2, to: AnyObject.self), 
    forKeyedSubscript: "test2" as NSCopying & NSObjectProtocol)
    
    JS 代码:
    function JS_Swift1(){
        test1();
    }
    function JS_Swift2(){
        test2('oc','swift');
    }注意: 这种方法仅仅适用于 OC 的 block, 并不适用于swift中的闭包, 为了公开闭包,      
    我们将进行如下两步操作:
    (1)使用 @convention(block) 属性标记闭包,来建立桥梁成为 OC 中的 block
    (2)在映射 block 到 JavaScript方法调用之前,我们需要 unsafeBitCast 函数将block 转成为 AnyObject
    
    Native 代码:
    // JS调用了无参数swift方法
    let closure1: @convention(block) () ->() = {
                
    }
    self.context.setObject(unsafeBitCast(closure1, to: AnyObject.self),   
    forKeyedSubscript: "test1" as NSCopying & NSObjectProtocol)
    
    // JS调用了有参数swift方法
    let closure2: @convention(block) () ->() = {
                
    }
    self.context.setObject(unsafeBitCast(closure2, to: AnyObject.self), 
    forKeyedSubscript: "test2" as NSCopying & NSObjectProtocol)
    
    JS 代码:
    function JS_Swift1(){
        test1();
    }
    function JS_Swift2(){
        test2('oc','swift');
    }

     

     

    模型注入(JavaScriptCore  JSExport 协议)
    
    步骤一: 自定义协议服从 JSExport协议
    可以使用该协议暴露原生对象,实例方法,类方法,和属性给JavaScript,这样JavaScript就可以调用相关暴露的方法和属性。遵守JSExport协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来
    
    注意:
    如果js是多个参数的话  我们代理方法的所有变量前的名字连起来要和js的方法名字一样比如: js方法为  OCModel.showAlertMsg('js title', 'js message’),他有两个参数 那么我们的代理方法 就是把js的方法名 showAlertMsg 任意拆分成两段作为代理方法名
    
    第一个参数的 argumentLabel 用 "_" 隐藏
    @objc protocol JavaScriptSwiftDelegate: JSExport {
    
        func callNoParam()
        
        func showAlert(_ title: String, msg: String)
    }
    
    步骤二: 自定义模型服从自定义协议, 实现协议方法
    
    @objc class JSObjCModel: NSObject, JavaScriptSwiftDelegate {
        weak var controller: UIViewController?
        weak var jsContext: JSContext?
        
        func callNoParam() {
            let jsFunc = self.jsContext?.objectForKeyedSubscript("jsFunc");
            _ = jsFunc?.call(withArguments: []);
        }
        
        func showAlert(_ title: String, msg: String) {
            let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default, handler: nil))
            self.controller?.present(alert, animated: true, completion: nil)
        }
    }
    
    步骤三: 将模型对象注入 JS
    
    // 模型注入
    let model = JSObjCModel()
    model.controller = self
    model.jsContext = context
    // 这一步是将OCModel这个模型注入到JS中,在JS就可以通过OCModel调用我们暴露的方法了
    context.setObject(model, forKeyedSubscript: "OCModel" as NSCopying & NSObjectProtocol)
    let url = Bundle.main.url(forResource: "WebView", withExtension: "html")
    context.evaluateScript(try? String.init(contentsOf: url!, encoding: .utf8))
    context.exceptionHandler = { [unowned self](con, except) in
                self.context.exception = except
    }
    
    JS 代码:
    <div class='btn-button' onclick="OCModel.callNoParam()">JS调用Native方式三无参</div>
    <div class='btn-button' onclick="OCModel.showAlertMsg('js title', 'js message’)">JS调用Native方式三有参</div>(JavaScriptCore  JSExport 协议)
    
    步骤一: 自定义协议服从 JSExport协议
    可以使用该协议暴露原生对象,实例方法,类方法,和属性给JavaScript,这样JavaScript就可以调用相关暴露的方法和属性。遵守JSExport协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来
    
    注意:
    如果js是多个参数的话  我们代理方法的所有变量前的名字连起来要和js的方法名字一样比如: js方法为  OCModel.showAlertMsg('js title', 'js message’),他有两个参数 那么我们的代理方法 就是把js的方法名 showAlertMsg 任意拆分成两段作为代理方法名
    
    第一个参数的 argumentLabel 用 "_" 隐藏
    @objc protocol JavaScriptSwiftDelegate: JSExport {
    
        func callNoParam()
        
        func showAlert(_ title: String, msg: String)
    }
    
    步骤二: 自定义模型服从自定义协议, 实现协议方法
    
    @objc class JSObjCModel: NSObject, JavaScriptSwiftDelegate {
        weak var controller: UIViewController?
        weak var jsContext: JSContext?
        
        func callNoParam() {
            let jsFunc = self.jsContext?.objectForKeyedSubscript("jsFunc");
            _ = jsFunc?.call(withArguments: []);
        }
        
        func showAlert(_ title: String, msg: String) {
            let alert = UIAlertController(title: title, message: msg, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default, handler: nil))
            self.controller?.present(alert, animated: true, completion: nil)
        }
    }
    
    步骤三: 将模型对象注入 JS
    
    // 模型注入
    let model = JSObjCModel()
    model.controller = self
    model.jsContext = context
    // 这一步是将OCModel这个模型注入到JS中,在JS就可以通过OCModel调用我们暴露的方法了
    context.setObject(model, forKeyedSubscript: "OCModel" as NSCopying & NSObjectProtocol)
    let url = Bundle.main.url(forResource: "WebView", withExtension: "html")
    context.evaluateScript(try? String.init(contentsOf: url!, encoding: .utf8))
    context.exceptionHandler = { [unowned self](con, except) in
                self.context.exception = except
    }
    
    JS 代码:
    <div class='btn-button' οnclick="OCModel.callNoParam()">JS调用Native方式三无参</div>
    <div class='btn-button' οnclick="OCModel.showAlertMsg('js title', 'js message’)">JS调用Native方式三有参</div>

     

    五. WKWebView JS 交互

     

    WKWebView 的配置
    
    //导入 WebKit
    //创建配置类
    let confirgure = WKWebViewConfiguration()
                 
    //WKUserContentController: 内容交互控制器
    confirgure.userContentController = WKUserContentController()
            
    //创建WKWebView
    wkWebView = WKWebView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height), configuration: confirgure)
            
    //配置代理
    wkWebView.navigationDelegate = self as WKNavigationDelegate
    wkWebView.uiDelegate = self as WKUIDelegate

     

    Native 调用 JS

     

    • WebView 直接注入 JS 并执行

     

    不同于 UIWebView,WKWebView 注入并执行 JS 的方法不会阻塞当前线程。因为考虑到 webview 加载的 web content 内 JS 代码不一定经过验证,如果阻塞线程可能会挂起 App。
    
    self.wkWebView.evaluateJavaScript(“jsFuncName()") { (result, error) in
                print(result, error)
    }
    
    注意: 
    方法不会阻塞线程,而且它的回调代码块总是在主线程中运行。注意: 
    方法不会阻塞线程,而且它的回调代码块总是在主线程中运行。

     

    JS 调用 Native 

     

    • 拦截 URL 请求
    • Webkit 的 WKUIDelegate协议
    • 模型注入(Webkit 的 WKScriptMessageHandler协议)
       
    拦截 URL 请求
    拦截请求的代理方法为 WebKit 中 WKNavigationDelegate 协议的
    
     func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: ) 方法
    
    , 其它同 WebView

     

    Webkit 的 WKUIDelegate协议
    
    WKUIDelegate 协议包含一些函数用来监听 web JS 想要显示 alert 或 confirm 时触发。我们如果在 WKWebView 中加载一个 web 并且想要 web JS 的 alert 或 confirm 正常弹出,就需要实现对应的代理方法。
    
    以JS 弹出Confirm 为例, 下面是在 WKUIDelegate 监听 web 要显示 confirm 的代理方法中用 Native UIAlertController 替代 JS 中的 confirm 显示的 例子: 
    
    //通过 message 得到JS 端所传的数据,在 ios 端显示原生 alert 得到 true/false 后通过 completionHandler 回调给 JS
    
    Native 代码:
    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
            let alert = UIAlertController(title: "Confirm", message: message, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (_) -> Void in
                completionHandler(true)
            }))
            alert.addAction(UIAlertAction(title: "cancel", style: .cancel, handler: { (_) -> Void in
                completionHandler(false)
            }))
            self.present(alert, animated: true, completion: nil)
    }
    
    JS 代码:
    function callJsConfirm() {
            if (confirm('confirm', 'Objective-C call js to show confirm')) {
                d ocument.getElementById('jsParamFuncSpan').innerHTML = 'true';
            }else {
                 document.getElementById('jsParamFuncSpan').innerHTML = 'false';
            }
    }
    

     

    模型注入(Webkit 的 WKScriptMessageHandler协议)
    
    注意: 
    对象注入写在 viewWillAppear 中, 防止循环引用
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            //注入对象名称 APPModel, 当 JS 通过 APPModel 调用时, 可以在 WKScriptMessageHandler 代理方法中接收到
            wkWebView.configuration.userContentController.add(self, name: "APPModel")
        }
        
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            wkWebView.configuration.userContentController.removeScriptMessageHandler(forName: "APPModel")
              }
    
    JS 通过 AppModel 给 Native 发送数据,会在该方法中收到
    JS调用iOS的部分, 都只能在此处使用, 我们也可以注入多个名称(JS对象), 用于区分功能
    
        func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
            if message.name == "APPModel" {
                //传递的参数只支持NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull类型
                let alert = UIAlertController(title: "MessageHandler", message: message.name, preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (_) -> Void in
                    
                }))
                self.present(alert, animated: true, completion: nil)
            }
        }
    
    JS 代码:
    function messageHandlers() {
            //APPModel 是我们注入的对象
            window.webkit.messageHandlers.APPModel.postMessage({body: 'messageHandlers'});
    }
    注意: 
    对象注入写在 viewWillAppear 中, 防止循环引用
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            //注入对象名称 APPModel, 当 JS 通过 APPModel 调用时, 可以在 WKScriptMessageHandler 代理方法中接收到
            wkWebView.configuration.userContentController.add(self, name: "APPModel")
        }
        
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            wkWebView.configuration.userContentController.removeScriptMessageHandler(forName: "APPModel")
              }
    
    JS 通过 AppModel 给 Native 发送数据,会在该方法中收到
    JS调用iOS的部分, 都只能在此处使用, 我们也可以注入多个名称(JS对象), 用于区分功能
    
        func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
            if message.name == "APPModel" {
                //传递的参数只支持NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull类型
                let alert = UIAlertController(title: "MessageHandler", message: message.name, preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (_) -> Void in
                    
                }))
                self.present(alert, animated: true, completion: nil)
            }
        }
    
    JS 代码:
    function messageHandlers() {
            //APPModel 是我们注入的对象
            window.webkit.messageHandlers.APPModel.postMessage({body: 'messageHandlers'});
    }
    

     

    六. JS 通过 Native 调用iOS 硬件(相机)

    JS 调用 iOS 硬件, 本质上还是通过以上介绍的 JS 调用 Native 方法调用 Native接口,

    再由 Native 调用本地硬件, 具体实现看 demo , 这里不再赘述.

     

     

    参考链接:

     

    拦截 URL:

    https://www.jianshu.com/p/d19689e0ed83

    https://blog.csdn.net/wanglei0918/article/details/78141890

    WKWebView 和 JS 交互:

    https://github.com/marcuswestin/WebViewJavascriptBridge

    http://www.cocoachina.com/ios/20171024/20895.html

    https://blog.csdn.net/baihuaxiu123/article/details/51674726

    WebView 和 JS 交互:

    https://www.jianshu.com/p/c11f9766f8d5

    https://www.jianshu.com/p/8f3c47c24e29

    https://blog.csdn.net/longshihua/article/details/51645575

     

    Github地址: 点击打开链接

    https://github.com/LeeJoey77/WebView_H5Demo.git
    
     
    https://github.com/LeeJoey77/WebView_H5Demo.gi

     

     

     

     

     

     

     

     

    展开全文
  • Hybrid App 开发快速指南

    万次阅读 2018-08-14 00:42:57
    关于混合应用是什么、为什么使用的问题,相信大家都有自己的答案,但如何开发混合应用,从现有资料中却很难找到一个系统、全面的回答。 刚上手或准备上手混合应用的开发者,经常苦于没有一套经过验证的最佳实践来...

    课程背景

    混合应用相对于原生应用而言,是原生应用和 Web 应用的结合体。过去几年,混合应用开发的各种利弊已得到充分的讨论和验证。关于混合应用是什么、为什么使用的问题,相信大家都有自己的答案,但如何开发混合应用,从现有资料中却很难找到一个系统、全面的回答。

    刚上手或准备上手混合应用的开发者,经常苦于没有一套经过验证的最佳实践来指导开发,在开发的各个阶段往往遇到各种问题:

    • 如何选型?
    • 如何架构前端代码?
    • 如何做好体验?
    • 如何做好安全性?
    • 如何正确使用原生能力?

    如果对以上问题没有充分的理解,贸然开始一个混合项目就很容易掉进坑里。为了帮助大家解决这些问题,快速开展混合应用开发,特推出了本达人课。

    课程介绍

    本课程为混合应用开发入门课程,将带领读者快速掌握 Hybrid App 开发能力,内容涵盖混合应用原理、混合应用开发基础、混合应用开发进阶、混合应用开发最佳实践。

    课程主要分为两大部分:

    第一部分(第01-05课),理论篇,带大家明确了解混合应用开发与普通 Web 前端开发的差异,内容包括混合应用原理、混合应用界面开发、混合应用体验优化、性能优化、混合应用安全性等,属于混合应用开发基础理论内部。

    第二部分(第06-13课),实战篇,从技术选型开始,讲解如何基于 APICloud 平台开发混合应用,内容包括平台特性、前端项目工程规划、界面交互、数据交互、数据缓存等开发中的各个方面,并将遇到的所有需求一一封装,最终将带你从零搭建一套混合应用开发框架。

    课程以实战干货为主,在保证学习连贯性的前提下,尽量减少文档可查、引擎可搜的内容。通过认真学习本课程,读者将对混合应用开发有深入的理解,并有能力基于 APICloud 平台快速开发跨平台混合应用。

    作者介绍

    臧涛,五年前端从业者,从切图仔到架构师,练就一身丰富的踩坑经验。Flow-UI 组件化框架作者、HybridStart 混合应用框架作者。

    课程内容

    导读:七天开发一款 App 是怎样的体验?

    引言

    看到这个题目,很多人可能会下意识的想道:标题党!但我要说“七天开发 App”是我的亲身经历,严格来讲,前端开发实际所花费的时间可能还到不了七天。为什么可以做得这么快?首先,这是混合应用的魅力所在,投入一名前端,产出两个平台的 App,用 Web 技术做界面,比原生开发效率提升3-4倍已经是比较保守的估计了。

    当然,仅仅这样还不够,提高开发速度最行之有效的方法莫过于“封装”,混合应用开发更是如此。做混合应用,实际上就是做 Mobile 页面+原生功能调用,这个自带“胶水”属性的架构,产生了比普通 Web 项目更多的可封装点,比如 UI、交互组件、页面方法、常用页面、常用模块等,有的是 Web 页面,而有的要借助原生能力,为了统一开发体验和接口风格,必须毫不犹豫的封装它们。

    如果这些都做到位了,就可以很快完成项目界面开发,进入接口联调阶段。这时我们还需要一个封装良好的请求方法,为我们提供方便的调试、统一的异常处理、灵活的缓存能力、甚至加密传输能力。想让业务跑起来总少不了页面传参、数据存储、事件发布等能力,最后 App 还要能够在线升级,在线扩展。所有这些功能节点如果都封装到位,那开发速度想不快都难。

    那这些封装可以通用吗?这些林林总总的东西看起来很杂,其实通用性很强,绝大多数混合应用项目都跳不出这个圈子,因此该系列课程在讲到各个开发环节的同时,也会介绍相应的封装思路及实现,最后大家除了可以获得必须掌握的理论知识,还会实战完成一套封装好的开发框架,可以说这是一套面向封装的混合应用开发课

    课程特色

    “我为什么要为这套课程付费?”“这里有什么知识点是网上找不到的吗?”……在看到本达人课时,你心中可能会有些疑问。

    严谨得说,没有哪个知识点是网上找不到的,所有的经验也都可以自己习得。但是,以下这些东西可能需要你付出很多时间才能自己摸索得到,而通过本课程,你可以轻松立即获得它们。

    本课程的四大亮点:

    1. 从务实的角度,为你选择一条干货最多的学习路线。无论什么样的课程都无法满足每一个人,不同知识背景的读者会有不同的困惑,本课程会假定您有一定的前端开发经验,尽量过滤掉太基础的纯前端问题,将更多篇幅集中在混合应用开发本身上,保证读者的学习效率不会因为低权重内容而降低。对于前端基础薄弱的读者,网上有足够多的高质量免费学习资源,当然,如果您能善用搜索引擎的话,相信这些问题都不在话下。

    2. 大量的常见需求示例。初学者最常见的一种情况是,文档都看懂了,但还是写不出代码。简单得说,这是因为“键盘不会自己敲”,因此课程中的很多知识点会以实际需求的形式出现,通过一步一步的分析并实现这些需求,使读者对知识点的运用产生感性的认识,从而拉近知识与实践的距离,相信对初学者快速上手会有一定帮助。

    3. 排坑。每个环节涉及的常见坑,都为你提前排好,我踩过的坑,希望你不要再踩。比如做全包加密可能导致无法运行的问题,这八成是因为某些文件的写法不规范,导致加密后无法运行;只要是 Web 就免不了兼容问题,考验你前端 Debug 经验的时候到了;iOS 上架被拒也比较常见,我遇到最多的两个原因分别是在线更新和权限问题。还有一些我自己踩过的坑,都会在课程对应章节里分享。

    4. 一套非常好用的混合应用开发范式。混合应用从概念理解到上手实践可以说都非常简单,自己摸索文档三两个小时跑起来一个 Hello world 程序不是什么难事。做 Demo 不难但做实际项目却比较难,尤其是中型以上规模的项目。非难技术,而是很难找到一个好的开发范式。最开始,我从 Cordova 开始接触混合应用,后来转到国内 Appcan,再到 APICloud,截至目前已有四年以上混合应用开发经验,在开发和学习过程中逐渐提炼出一套做多页面混合应用的开发范式,相信对您一定有所帮助。

    如果以上内容让你觉得有兴趣,那么就可以正式开始后面的课程了。

    第01课:Hello Hybrid!

    什么是混合应用

    混合应用原理

    混合应用是指同时使用前端技术与原生技术开发的 App。通常由前端负责大部分界面开发和业务逻辑,原生负责封装原生功能供前端调用,二者以 WebView 作为媒介建立通信,从而既拥有 Web 开发的速度优势,又能拥有强大的原生能力。

    从前端开发者的角度,混合应用可以简单地理解为让前端页面跑在一个特殊的浏览器环境里,这个环境除了常规 Web API之外,还额外提供了很多可以直接调用手机原生能力的 API。

    从原生开发者的角度,混合应用其实就是一个原生开发的 App 外壳,这个外壳将原生功能封装成很多 API 并注入到 WebView 里,然后将前端页面打包进 App,App 启动时用 WebView 加载前端页面,剩下的就全交给前端了。

    混合应用原理

    混合应用框架

    混合应用框架的本质就是上面提到的那个原生 App 外壳,这个外壳重点实现三件事:

    1. 实现原生与前端(Javascript)的交互;
    2. 封装基本的原生功能,供前端调用;
    3. 实现原生插件机制,供原生开发者扩展功能。

    只要做到这三件事,基本上就可以被称为混合开发通用框架。

    混合应用框架

    Cordova

    最早出现也是最纯粹的混合应用方案是 Cordova/Phonegap,我们统称为 Cordova。Cordova 主要提供三种能力:

    1. 前端代码与原生代码通信的能力;
    2. 原生插件机制;
    3. 跨平台打包能力。

    之所以说这是“最纯粹”的混合应用方案,是因为该方案只为前端提供了一个 WebView,除此之外完全不干预展现层。其 App 外壳也只内置了极少数几个 API,其他原生功能都要靠插件实现。可以说 Cordova 只实现了混合应用框架的最小功能集合,从框架设计的角度,这样可以最大限度得做到不干扰业务,提高定制性。

    但 Cordova 的不足之处也非常明显。由于 Web 前端技术暂时还不足以开发出流畅的转场动画,而且可预见的未来手机操作系统恐怕都不会优化这一点,因此在前端只有一个 WebView 的情况下,转场动画将是绕不过去的一大问题。Cordova 的插件生态还算不错,但对于国内开发者来说难免有点水土不服,找插件经常要花不少时间,对于一些本土化服务的支持也没那么及时,遇到插件 Bug,就更是求助无门了。对于没有原生开发能力,英文水平又不是太好的国内开发者来说,Cordova只是一个“看上去很美”的方案。

    混合应用开发平台

    针对 Cordova 存在的问题,国内厂商给出了一种优化方案,那就是混合应用开发平台,平台的种类有很多,但他们的核心思路基本一致,都是在 Cordova 的基础上做了以下几点改进:

    1. 以云平台的方式管理项目,整个开发周期除了写代码以外都能在平台上实现;
    2. 丰富的内置原生能力,做到开箱可用;
    3. 打造本土化的插件生态;
    4. 多 WebView 机制,用原生转场解决流畅性问题,这是杀手级特性。

    结合以上特性,混合应用开发平台实际上已经将 Hybrid App 开发完全变成了前端开发者“一个人的事”,普通原生需求都内置了,扩展原生需求可以借助插件生态实现,前端转场不流畅可以用原生效果代替,甚至还提供 App 开发的全生命周期管理功能,包括 App 配置、项目管理、更新、统计等。可以说,混合应用开发平台这种模式的出现,将 Hybrid App 开发的技术门槛降到了最低,真正实现了只要一名前端就能开发跨平台 App 的目标,而且整个开发过程只需要用到 Web 前端技术,因此开发速度可以非常块,一个熟练的前端开发者完全可以在几天之内完成一个中小规模的 App 开发。

    混合应用开发平台

    市面上可选择的混合应用开发框架还有很多,例如 Ionic,原生部分仍然是 Cordova,UI 层使用 Angular 做了封装,相当于混合应用界的 Bootstrap;NativeScript,这个框架在理念上比 Cordova 更进一步,它为视图层封装了一套语法,前端使用这个语法开发界面和逻辑,最终打包后的 App 将全部使用原生绘制 UI,理念其实跟 RN/Weex 差不多。每一种的开发框架都有自己的优缺点,我们将在后面章节中对它们做一次详细的横向对比。

    为什么使用混合开发方式

    优缺点

    混合开发方式可以在只投入一名前端开发者的情况下,快速开发出兼容多个平台的 App,相比原生开发同时降低了开发的时间成本和人力成本,这是混合开发能够一直维持旺盛生命力的根源。

    但有得必有失,我们也必须正视混合开发的弊端,受限于 HTML5 的表现力,混合应用在 UI 层面很难达到原生界面的细腻程度;界面的载入速度也很容易受到手机运行速度和页面大小的影响。如果前端开发做的不够细致,就很容易给用户带来“网页感”,使 App 的用户体验大打折扣。

    应用场景

    结合上述优缺点分析,混合开发方式比较适合以下类型的项目:

    • 功能导向的项目,例如企业内部 App、面向特定用户的工具类 App;
    • 需要快速开发迭代的项目,例如新产品试水、外包项目;
    • 缺少原生开发团队的企业。

    总而言之,对体验要求不苛刻,且工期预算有限的 App 项目,都非常适合做成混合应用,尤其在外包领域,混合应用占据绝对领先的市场份额。另外很多中小型公司,在发展初期为了节省人力成本,往往不配置原生开发团队,也会采用混合开发方案。

    这里额外提醒一下,对于没有原生开发能力的团队,使用混合方案会有一个潜在的问题,就是原生需求完全受制于既定框架及其插件生态,因此在项目开始前,一定认真做技术选型,避免做到一半后无法继续做的情况。

    小结

    本文,我们简要讲解了混合应用开发的原理,并介绍了几种目前市面上常见的混合开发框架,及它们各自的特点。目的是让从未接触过混合应用开发的初学者,能够了解前端在混合开发中的分工和定位,有助于在后面的章节里快速进入角色。另外还简单分析了混合开发方式的优缺点,并结合优缺点列举了几种比较适合采用混合方案开发的项目类型,帮助读者更有针对性的选择学习方向。

    第02课:Hybrid App 界面开发
    第03课:Hybrid App 体验优化
    第04课:Hybrid App 的安全性
    第05课:Hybrid App 开发框架选型
    第06课:实战之 APICloud 核心概念
    第07课:实战之前端工程化
    第08课:实战之界面交互
    第09课:实战之前后端交互
    第10课:实战之数据缓存
    第11课:实战之使用模块
    第12课:实战之 APICloud 附加功能
    第13课:实战之插件机制

    阅读全文: http://gitbook.cn/gitchat/column/5b679a1d201ffa4ab88e7d5d

    展开全文
  • Hybrid APP混合开发的一些经验和总结

    万次阅读 多人点赞 2017-03-31 11:14:29
    由于业务需要,接触到一个Hybrid APP混合开发的项目。当时是第一次接触混合开发,有一些经验和总结,欢迎各位一起交流学习~ 1、混合开发概述 Hybrid App主要以JS+Native两者相互调用为主,从开发层面实现“一次...

    写在前面:

    由于业务需要,接触到一个Hybrid APP混合开发的项目。当时是第一次接触混合开发,有一些经验和总结,欢迎各位一起交流学习~

    1、混合开发概述

    Hybrid App主要以JS+Native两者相互调用为主,从开发层面实现一次开发,多处运行的机制,成为真正适合跨平台的开发。Hybrid App兼具了Native App良好用户体验的优势,也兼具了Web App使用HTML5跨平台开发低成本的优势。

    目前已经有众多Hybrid App开发成功应用,比如美团、爱奇艺、微信等知名移动应用,都是采用Hybrid App开发模式。

    2、移动应用开发的三种方式比较

    移动应用开发的方式,目前主要有三种:

    • Native App: 本地应用程序(原生App)
    • Web App:网页应用程序(移动web)
    • Hybrid App:混合应用程序(混合App)

     

    图1三种移动应用开发方式

    如图1所示,三种移动应用开发方式具体比较如表2所示

     

    表2三种移动应用开发方式比较

    3、混合开发应用场景

    (1)折中考虑——如果企业使用 Hybrid 开发方法,就能集Native 和web两者之所长。一方面,Native 让开发者可以充分利用现代移动设备所提供的全部不同的特性和功能。另一方面,使用 Web 语言编写的所有代码都可以在不同的移动平台之间共享,使得开发和日常维护过程变得集中式、更简短、更经济高效。

    (2)内部技能——许多企业都拥有Web 开发技能。如果选择 Hybrid 开发方法,在合适解决方案的支持下,Web 开发者只要仅仅运用 HTMLCSS 和 JavaScript 等 Web 技能,就能构建 App,同时提供 Native 用户体验。

    (3)考虑未来——HTML5的可用性和功能都在迅速改进。许多分析师预测,它可能会成为开发前端 App 的默认技术。如果用 HTML 来编写 App 的大部分代码,并且只有在需要时才使用 Native 代码,公司就能确保他们今天的投入在明天不会变得过时,因为 HTML 功能变得更丰富,可以满足现代企业一系列更广泛的移动要求。

    4、混合开发框架和层次结构图

    混合开发结构图

     

    1)移动终端web壳(以下简称“壳”):壳是使用操作系统的 API 来创建嵌入式 HTML的渲染引擎。壳主要功能是定义Android应用程序与网页之间的接口,允许网页中的JavaScript调用Android应用程序,提供基于web的应用程序的Android API,将Web嵌入到Android应用程序中。

    2)前端交互js:包括基础功能js和业务功能js

    3)前端适配器:适配不同的终端:Padandroidioswap

    混合开发层次结构图

     

    1) 页面加载

    1. 页面容器(XdjaWebView)类,是整个框架的核心和基础,主要用来实现页面的加载,以及对页面加载完成后的后续操作提供支持,例如:文件下载、js支持、文件上传,数据缓存、进度条等;
    2. 页面加载接口:对页面的加载过程进行跟踪;例如:页面加载进度百分比,页面开始加载、页面加载出错、页面加载完成等

    2) JS调用Android功能

    1. 网页:页面调用js接口中的具体方法;
    2. JS接口:调用android接口中一一对应的具体方法;
    3. android接口:直接调用框架中集成的功能,或者通过框架接口在应用系统中自定义功能(例如,退出、返回键响应等);其中升级功能的返回结果或者过程信息,可以在客户端中通过升级接口获取。
    4. XdjaClientHelper:如果需要将框架中的方法返回值通知给js方法,你们可以通过XdjaClientHelper类来实现;

    3)应用系统调用JS功能

    应用系统通过XdjaClientHelper来实现对js功能的调用;

    4) 应用系统调用HDF功能

    应用系统可以调用框架集成的工具类、消息提示框、升级模块以及手机上常见的打电话发短信等功能。

    5、性能优化

    1) 单个页面

    登录、首页以及共用代码(样式文件、JS文件、页面加载loading代码)等放在index页面里。页面展示前显示fake页面(过场页面),首屏加载完后,fake页面消失。

    页面虽然按照业务模块分为不同的页面,但是展示的时候会在同一个页面即index页面展示。具体的说,需要某个功能页面的时候将页面以AJAX的形式请求到index页面,使用完毕删除。

    使用一个页面,公共的CSSJS只会加载一次。

    2)CSSJavaScript

    在本次混合开发框架开发中,CSS全部写在一个文件里。

    CSSJquery Mobile的相关文件写在index页面头部,其余公用JS等写在index页面底部。防止JS阻塞页面加载。各业务逻辑JS写在各业务页面的底部。

    开发完成后,CSSJS需要进行压缩,减少用户使用时初次请求时间。

    3) @font-face

    本次混合开发中使用@font-face来实现图标字体化,统一控制图标的颜色和大小。

    使用@font-face优点:减少页面因使用图片而带来的流量,大大缩短页面响应时间;图标可以随意改变大小和颜色,而不会导致失真。

    使用时注意:所有的图标需要是矢量的SVG格式。

    使用限制:只适用于纯色扁平化的图标。背景图等比较复杂的图片仍然使用图片。

    4) 本地存储LocalStorage

    HTML5本地存储LocalStorage,在混合开发中主要用来存储最近查询记录等。

    拿首页最近查询来说,用户每次在综合查询中点击一个模块,通过LocalStorage将图标和对应的功能名字存储起来,如果用户不清除,LocalStorage中的数据是一直存在本地的。下次打开应用的时候从LocalStorage中读取最近查询记录等。

    使用LocalStorage的好处是,不进行后台交互,速度快。

    5)异步AJAX

    本次开发中多处实现都是通过使用AJAX首先,显示页面时,先显示框架,然后异步加载内容;其次,分页功能中,先显示部分简项列表,上拉获取更多内容。再次,每打开一个新功能,页面以AJAX的形式获取新页面的内容并展示出来。

    异步AJAX,交互体验更好。从性能的角度考虑,速度也更快。

     http://www.cnblogs.com/kingplus/p/5588339.html


    APP开发模式通常分为Web APP与Native APP原生模式两种,这两种模式均各自有自己的优势,到底是采用Native App开发还是采用Web App开发一直是业界争论的焦点,但是随着HTML5的发展及云服务普及,采用HTML5进行Web App开发正在成为一种趋势,用户可以根据应用特点和需求进行选择,亦可选择两者混合模式:
      Native App开发
      Native App开发即我们所称的传统APP开发模式(原生APP开发模式),该开发针对IOS、Android等不同的手机操作系统要采用不同的语言和框架进行开发,该模式通常是由“云服务器数据+APP应用客户端”两部份构成,APP应用所有的UI元素、数据内容、逻辑框架均安装在手机终端上。
      Web App开发
      Web App开发即是一种框架型APP开发模式(HTML5 APP 框架开发模式),该开发具有跨平台的优势,该模式通常由“HTML5云网站+APP应用客户端”两部份构成,APP应用客户端只需安装应用的框架部份,而应用的数据则是每次打开APP的时候,去云端取数据呈现给手机用户。
      原生APP开发及Web APP开发模式的区别
      Web APP需开发“html5云网站”和“APP客户端”,昆明天度网络公司总结这类型APP应用呈现以下特点:
      (1)每次打开APP,都要通过APP框架向云网站取UI及数据;
      (2)手机用户无法上网则无法访问APP应用中的数据。
      (3)框架型的APP无法调用手机终端的硬件设备(语音、摄像头、短信、GPS、蓝牙、重力感应等)
      (4)框架型APP的访问速度受手机终端上网的限制,每次使用均会消耗一定的手机上网流量;
      (5)框架型APP应用的安装包小巧,只包含框架文件,而大量的UI元素、数据内容刚存放在云端;
      (6)APP用户每次都可以访问到实时的最新的云端数据;
      (7)APP用户无须频繁更新APP应用,与云端实现的是实时数据交互;
      适用企业:电子商务、金融、新闻资讯、企业集团需经常更新内容的APP应用。
      Native App(原生型APP)需要开发“云服务器数据中心”和“APP客户端”,昆明天度网络公司总结这类型的APP应用呈现以下特点:
      (1)每次获取最新的APP功能,需要升级APP应用;
      (2)原生型APP应用的安装包相对较大,包含UI元素、数据内容、逻辑框架;
      (3)手机用户无法上网也可访问APP应用中以前下载的数据。
      (4)原生型的APP可以调用手机终端的硬件设备(语音、摄像头、短信、GPS、蓝牙、重力感应等)
      (5)APP应用更新新功能,涉及到每次要向各个应用商店进行提交审核。
      适用企业:游戏、电子杂志、管理应用、物联网等无需经常更新程序框架的APP应用。
      到底该如何选择Web App和Native App开发模式
      移动Web无所不在,移动Web是目前唯一的支持各种设备访问的平台,与桌面Web一样,移动Web支持各种标准的协议。移动Web也是唯一一个可供开发者发布移动应用的平台,它将各种移动交互与桌面任务有效地连接了起来;而开发Native App可以充分利用设备的特性,而这一点往往是Web浏览器做不到的,所以对一个产品本身而言,Native App是最佳的选择。下面几节将讨论一下Native App的一些主要功能。
      什么时候应该选择Native App
      1.为应用收费
      没有任何地方规定开发者不能对一个移动Web App收取使用费,但是由于某些原因,人们常常认为不能或是不应该对一个Web App收取费用。由于历史原因,导致移动设备上付费服务遭遇两大阻力:
      2.付款方式
      在移动设备上输入信用卡号相当麻烦,而且在许多老式设备上也没有安全保障。一种典型的方式是,如果你需要对你的应用收费,你可以与运营商达成协议,让运营商代为为你的服务收费。这也意味着,你需要和多个运营商达成合作。这通常是首选的方法,因为许多手机用户可能根本就没有信用卡,比如青少年。
      另一种方法是将用户的信用卡信息保存在一个安全的网站上。用户可以通过登录到该网站购买应用服务。这个过程不算特别理想,因为这意味着用户不能直接通过他们的移动设备购买服务了。
      3.强制分成
      移动运营商是会提成的。App无论是通过运营商还是通过移动设备发布,他们都为应用提供了一套收费机制。这些运营商和移动设备将会提取部分收益,然后将剩余的部分交给应用开发商,这也意味着,开发人员必须遵守他们的市场规则。适应运营商的市场规则通常是非常困难的,需要投入大量的人力资源。相比而言,移动设备的市场规则则简单许多,但是也存在不少的困难。
      妨碍运营商和移动设备开发商利益的应用以及服务都将受到阻扰。过去,那些不靠运营商和移动设备开发商运作的网站如果收入过于显眼的话,都逃脱不了被关闭的命运,但是最近,这样的事情鲜少发生了。
      如果你想为你的Native App收费,那么你就必须接受这个现实——你必须遵守别人的市场规则,还得放弃部分收益。
      4.开发游戏
      如果你是想开发一个移动游戏(移动游戏是移动市场上最大的一块),那么你需要开发一个Native App。游戏对资源的占用很大,并且需要使用许多设备API或平台API。虽然,现在有几款完全使用Web技术开发的游戏占有了一定的市场份额,但是和Native App市场的占有情况相比,还是微不足道的。游戏用户对应用的视觉和操作效果要求很高。移动Web虽然提供了一些仿真体验,但还远远不能满足用户的需求。
      在开发移动游戏时,你需要慎重考虑你的应用需要支持哪些平台。幸运的是,现在有许多工具能够帮助你将你的游戏推向多个平台,但是完成这些工作,还是需要花费大量的人力和物力。
      5.使用定位功能
      下一个功能就是定位功能,可以通过GPS或者是信号检测确定用户当前的位置信息。以前只能通过Native App的APIs查看用户的位置信息,但现在大多数主流移动浏览器上都嵌入了W3C Geolocation API。像iPhone或Android这样安装了WebKit的设备,或是配置了Opera或Mozilla浏览器的设备,都可以获取用户的位置信息。
      我相信定位功能会为Web技术带来许多全新的应用。如果能够合理利用Web浏览器,Web开发商就能使用用户的位置信息和其他内容开发出更加有趣的应用。虽然这在技术上没有太大的困难,但却受到隐私保护条例的限制。我们将Web浏览器当做是用户进入World Wide Web的入口。加入定位功能,意味着在网站中引入了一些敏感信息,这有可能导致严重的后果。但是位置感知应用中显示的位置信息必须经过用户的授权,用户当然有权禁止应用发布自己的位置信息。
      6.使用摄像头
      摄像头可以为你的应用提供丰富的可能性。以往移动MMS(Multimedia Messaging Service)被用于处理移动照片。换言之,你拍了一张照片后,需要使用MMS将它传送给一个服务器,服务器对照片做出相应的处理,并将处理完成的结果通知给你。这个过程是非常耗时的,而且相当复杂,也没有可靠性保障。
      通过访问摄像头,Native App开发者能够简化拍照的过程。用户可以直接在客户端对照片做一些简单的处理,只有在有需要的时候才将照片上传给服务器,而且是通过可靠的HTTP传输。W3C正在开发一个访问摄像头的API,但现在还没有将这部分工作正式整合到浏览器中。
      在许多类型的移动Apps中,摄像头是非常有用的,比如快拍应用、短片拍摄应用等等,摄像头可以用来捕捉许多重要的瞬间。不久的将来,我们可以看到——只要通过摄像头拍摄某个标识,应用程序就能自动完成对标识上的语言转换工作——这个技术在日本已经开始流行起来了。
      7.使用感应器
      现在越来越来越多的移动设备上都新增了感应器功能,该装置可以感知设备的物理速度以及重力,并将感知的数据结果传送给设备。这个装置常被用来感应设置是否被翻转,应用根据接受到的信息自动调节画面的方向。
      感应器可以用来帮助用户提升与设备交互时的真实感;大多数移动设备都是手持的,应用能够根据设备的方向调整内容画面,比如翻转屏幕,或是检测物理移动,并能据此猜测用户所处的环境。举一个简单的例子:比如用户正在走路,那么感应器能够检测到一个轻缓的移动或是速度,这时可以为用户提供一个大字体的用户界面,从而使得用户更容易看清屏幕上的内容。
      然而,开发者也不能过分依赖感应器,因为感应器无法区分究竟哪些交互是有意的,而哪些是没有意义的。每个移动交互都需要通过“传输测试”。设计你的交互时必须考虑用户在一个拥挤的汽车或是火车上的场景。考虑一下如果用户正身处拥挤的地铁或是正在驾车时,你的应用能否正确处理用户摇晃移动设备的动作。通常,大多数开发者都没有考虑这些因素。确保为每个任务设计一个备用方案以处理特殊场景中的移动交互。
      8.访问文件系统
      如果你的应用需要将数据保存在本地,那么你需要开发一个Native App。比如你要保存用户的地址簿、电话或E-mail信息,或是保存从其他设备上获取的数据。
      访问文件系统常常会涉及到安全和用户隐私保护的问题。恶意应用程序可能会修改或是删除你的移动设备上的数据。一个携带病毒的应用程序可以利用移动设备上的关系网将病毒扩散到许多其他的手机上,在采用移动应用认证机制以前,这种事情是常常发生的。
      另一方面,移动设备正变得越来越私人化,移动设备上保存了大量用户的个人信息,以及用户的朋友信息和商业信息。针对这些私人信息开发应用是一个不错的想法。但是这也存在一定的风险,使用保存在移动设备上的数据可以为用户提供更加有针对性的服务。
      开发者必须谨记,只有在获得用户的授权后才能访问用户的私人数据。我们看到许多应用在没有得到用户授权的情况下使用了大量的用户私人数据,而被误认为是垃圾信息或是钓鱼应用,即使这些应用原本是在提供一些非常有用的服务。人们对你的应用的误解将会影响到你的服务的推广,如果运营商收到过多关于你的应用的投诉,那么你的服务可能将被终止,甚至会牵连其他的应用。
      访问文件系统时至关重要的一点就是在没有获得用户授权的情况下,不要访问任何用户的私人数据。而这一点,往往被大多数应用忽略了。W3C正在为移动开发商开发相关的标准API,但目前该工作尚未完成。
      9.离线用户
      最后一个需要开发Native App的理由就是,用户有可能是离线的或者无法接入移动网络。这在城市可能很少发生,即使是在农村,网络的覆盖也已经逐步普及了。但是短暂的网络连接中断还是时常发生的,你的应用程序应该考虑如何处理这种情景。
      想想用户通常在什么时候,在哪里会使用你的App。如果是一个移动游戏,那么用户很可能在飞机上使用这个App。跟踪地图应用常在偏远且网络覆盖不佳的地方使用。移动旅游向导常在一个国外的网络中访问,往往需要支付漫游和国际网络费用。这时,应用程序最好能够为用户提供离线服务,保证用户在不接入网络的情况下,仍然能享受同等的服务。
      现在支持HTML5的浏览器也能实现脱机访问功能,但对用户来说可能不太明显。随着越来越多的浏览器都开始支持脱机访问,应用需要明确地告诉用户网络连接中断时,他们仍然可以访问移动Web Apps。
      Native Apps常常假设网络连接是可靠的。App通常只考虑了网络状况良好的情景,想当然地认为网络是封闭的,并且网速足够快。移动设备从网络良好的环境突然进入一个网络糟糕的环境并不少见。Native Apps应该在网络状况最差的情况下测试。比如用户启动任务时可能还是全信号覆盖,而在任务结束时可能已经完全没有网络信号了。
      用户在安装Native Apps时,根本不会考虑是在线访问还是离线访问——他们期望的是不管在任何状况下,Native Apps都能正常工作。而这也是开发者的职责。
      什么时候应该选择Web App
      只要你的应用程序不满足之前提到的Native App条件之一,那么你就没有必要开发一个Native App,而应该选择开发一个Web App。正如文章之前提到的,我是一个Native App的拥护者,我认为Native App有许多优秀的特质,并且具有很大的市场潜力,但是Web Apps是唯一一个经久不衰的移动内容、服务、应用开发平台。
      Native App并不能明显地为用户提供更好的服务;它反而会增加项目的成本,减少了应用发布的渠道,增加了App升级的复杂度,削弱了开发者对应用的控制和利润,并且可能会给设备带来麻烦。Native App可以为开发者带来短期的效益,但这是有一定风险的,甚至可能会影响到移动市场的可持久发展。
      移动Web App的优势在前文中已经提到过了。如果上一节提到的几点功能是促成你选择Native App的唯一原因,那么如果能够在移动浏览器上屏蔽这些障碍,你是否还会坚持选择Native App呢?Palm的webOS已经着手解决了上述的部分问题。他们基于WebKit构建了一个全移动操作系统,将手机变成了一个Web浏览器。所谓的“Native Apps”实际上就是一个Web Apps。
      PhoneGap也是一个类似的项目,这个开源项目用于帮助开发者在iPhone、Android以及BlackBerry设备上开发Native Apps,并且能够模拟设备上的功能(如定位功能和文件系统)供Web Apps调用。这些代码可以在各个设备的应用商店中发布并且出售,但是他们使用的通用代码和设计是可以共享的。由于开发的是一个Web App,开发者可以为低端的移动浏览器开发一个简化版的应用。只用开发一次,就可以部署在多个平台上了,
      对于那些有着丰富的移动开发经验的程序员来说,一提到“要开发一个功能丰富的应用”时,可能首先想到的就是Native App。虽然在很多设备上,这一想法仍然适用,但是现在移动Web Apps上也提供了足够丰富的功能接口供开发者调用。这使得Web App不仅可以像Native App一样被设计得功能丰富界面绚丽,而且还能在各个平台上迁移,甚至不用修改一行代码。
      现在在移动设备开发中,移动Web Apps的创新进入了前所未有的高潮时期。但更重要的是,这是有史以来第一次,移动设备开发商决定共同制定一个移动Web开发的标准,就像是桌面Web上的标准一样。不仅如此,那些支持移动Web App创新功能的设备或是支持第三方浏览器的移动设备都受到消费者的欢迎。



    展开全文
  • 混合APP开发-hybrid 升级流程

    千次阅读 2018-09-29 11:06:10
    本文来自网易云社区作者:王贝目前大多数APP已经应用hybrid进混合开发,这不,我们的gacha APP这个版本已经开始使用hybrid来开发了,hybrid的优势这里就不多说了,这里主要讲一下hybrid中模块包的升级流程。...

    本文来自网易云社区

    作者:王贝


    目前大多数APP已经应用hybrid进混合开发,这不,我们的gacha APP这个版本已经开始使用hybrid来开发了,hybrid的优势这里就不多说了,这里主要讲一下hybrid中模块包的升级流程。

    服务器要维护一份zip包的版本列表,

    201809291047366bf1a4f8-e8f7-451d-ae71-12ebbcbf2d4b.png

    apppid表示每个模块的id,唯一

    version表示对应模块的版本号,递增的

    url表示对应模块包最新版本号的下载地址

    MD5表示该包的md5值

    ps:每个模块对应一个appid,模块表示app混合html5的子元素,一个模块整合了一个app的一类页面功能,每个模块的目录结构如下:

    这里h10001里的资源文件表示一个模块的资源文件,在GACHA APP里这个代表跟帖详情页这个页面功能。

    首先要把前端的代码打包成zip包,写了一个自动化打包脚本(待完善),如下:

    20180929104756d925eae4-a67e-47ff-9a98-48e916575a19.png


    #切换到项目目录
    cd erciyuan_h5
    #更新最新代码
    git pull
    cd src
    var=$1
    var=${var//,/ }
    for element in $var
    do
    #切换到相应模块目录
    cd $element
    #执行前端webpack打包命令,在css目录和js目录里分别生成template.css template.js
    webpack -p
    #向服务器获取当前模块的最新版本号
    version=`curl "http://hostname/hybirdVersion?appid=$element"`
    echo $version
    #生成zip包名
    module={element}_version
    rm -rf $module
    #将前端资源文件打包
    mkdir $module
    cp -r image $module
    mkdir ${module}/js
    mkdir ${module}/css
    mv css/template.css ${module}/css
    mv js/template.js ${module}/js
    cp -r image $module
    cp template.html $module
    zip -r 
    module.zip
    {module}
    #获取zip包的md5值
    md5=`md5sum {module}.zip|awk -F ' ' '{print1}'`
    echo $md5
    #上传zip包至nos
    curl -X POST -F "zip=@
    module.zip""http://hostname/api/v1/upload/webpack/zip?zipId=
    {module}.zip"
    #更新服务器包管理列表
    curl "http://hostname/hybirdStore?appid=1&module={module}.zip&MD5={md5}&v={version}"
    #包备份
    cp ${module}.zip /home/hzwangbei/package
    #删除本地zip包相关文件
    rm -f ${module}.zip
    rm -rf ${module}
    echo -e "\nstop succeed\nDownload Url: http://acs.nos.netease.com/${module}.zip"
    done

    zip包生成上传后,app就要去更新了,更新协议如下:

    201809291048099374d8f5-910d-431f-be72-50e0d70da12a.png

    app 首先将本地维护的最新的模块及版本列表上传给服务器,服务器一一对比服务器的zip包版本号,检测到需要更新的zip包,reducer后返回给APP。

    app拿到需要更新的zip包模块列表后,下载对应zip包,校验zip包的md5值,校验通过后,解压覆盖掉本地旧的模块,同时更新本地维护的模块版本列表。

    大概流程如下:

    201809291048222b24da82-7840-42ff-859c-92a4746d6a42.png



    网易云免费体验馆,0成本体验20+款云产品! 

    更多网易研发、产品、运营经验分享请访问网易云社区




    相关文章:
    【推荐】 “网易有钱”sketch使用分享
    【推荐】 全局脚手架了解一下【fle-cli】
    【推荐】 GDB抓虫之旅(中篇)

    展开全文
  • 混合app开发

    2016-08-15 22:59:11
    app混合开发
  • 谈谈App混合开发

    千次阅读 2019-05-24 10:56:07
    混合开发的App(Hybrid App)就是在一个App中内嵌一个轻量级的浏览器,一部分原生的功能...下面来谈谈Hybrid App开发中的技术问题。iOS方面的我不太了解,我就主要谈谈Android开发中的,其中可能会有很多说错的,请...
  • 移动开发-混合App介绍

    万次阅读 2018-06-25 08:56:38
    什么是混合App(Hybrid App) Hybrid App是指介于web-app(网页APP,如京东web)、native-app(原生应用,如手机上面的APP应用)这两者之间的app,它虽然看上去是一个Native App,但只有一个WebView ( WebView,可以...
  • 什么是混合app开发

    千次阅读 2017-02-28 19:06:03
    到目前为止,比较流行的混合app开发主要有以下三种: 1、WebApp:就是在浏览器中运行的web应用 2、NativeApp:用android和Object-C等原生语言开发的应用 3、HybridApp:就是外面是原生的壳,里面是webapp应用,兼具2...
  • 混合app开发学习笔记

    千次阅读 2018-09-09 21:15:11
    什么是混合移动App开发【重点】 苹果上的软件是如何开发出来的:使用的是 OC、或者使用Swift这门语言 安卓平台上的软件又是如何开发出来的:使用安卓相关的语言开发的,Java,安卓的控件进行开发 苹果和安卓平台上...
  • 混合APP开发技术选型

    千次阅读 2019-02-26 17:29:33
    React Native https://reactnative.cn/ ionic https://ionicframework.com/docs/ weex https://weex.apache.org/zh/ Framework 7 http://framework7.taobao.org/ PhoneGap https://phonegap.com/ ...
  • 混合App开发原理

    千次阅读 2020-02-25 01:20:52
    前言 Hybrid App Hybrid App是指介于web-app(网页APP,如京东web)、native-app(原生应用,如手机上面的APP应用)这两者之间的app,它虽然看上去是一个Native App,但只有一个WebView ( WebView,...混合APP就是在...
  • 混合app开发 混合app开发介绍 application(应用)用前端的知识(html,css,js)开发出来手机App的方式就叫做混合App开发 App开发的三种类型 WebApp:跑在手机浏览器中运行的web应用(微信公众号,微信小程序)...
  • 混合app开发问题总结

    2017-04-08 21:42:29
    跨域访问 开发时用浏览器调试会存在跨域访问问题,使用真机调试或者打包成app后即不会存在此问题 ...混合app开发 css框架可以使用mui js框架mui mvvm框架使用avalon 这些框架都支持移动端。bootstrap样式不支持移动断
  • android开发以前干过,但是一直觉得比较麻烦,缺少分享功能,现在的app大多数是h5的混合开发app,需要用到原生的android API的时候需要去做兼容,如果是开发速度合并效率,还是混合的H5开发比较受企业的青睐。...
  • 这几天有空闲时间去网上找了找vue的相关的ui框架,看到有网友推荐quasar-framework,去它...仔细看了下支持的东西还挺多单页面应用、SSR服务器渲染、渐进式Web、混合app开发、Electron Apps开发(桌面应用),乖乖...
  • 第02节:Weex开发环境安装(1) 第03节:Weex开发环境安装(2) 第04节:weex常用命令和热更新 第05节:Android Studio 开发设置 第06节:weex和vue的爱恨情仇 第07节:Weex自定义组件和Text组件 第08节:Weex ...
  • MUI框架HTML5 APP开发之创建APP项目HTML5 APP开发之软件打包HTML5 APP开发之全量升级HTML5 APP开发之浏览器调试页面HTML5 APP开发之手机调试页面HTML5 APP开发之自动登录HTML5 APP开发之头部菜单HTML5 APP开发之底部...
  • var u = navigator.userAgent;var isAndroid = u.indexOf('Android') &gt; -1 || u.indexOf('Adr') &gt; -1;var isiOS = !!u.match(/\(i[^;]+;( U;)?...if (isiOS) { try { window.web...
  • 本文会详细的讲解什么是混合App开发混合App开发概念、原理、区别、为什么要学习混合App、混合App开发的几种方式以及具体的环境配置和踩坑指南等干货十足。 1-什么是混合移动App开发 苹果上的软件是如何开发出来...
  • 移动端app开发,原生开发与混合开发的区别

    万次阅读 多人点赞 2019-09-26 18:47:01
    目前市场上主流的APP分为三种:原生APP、Web APP(即HTML5)和混合APP三种,相...原生开发(Native App开发),是在Android、IOS等移动平台上利用提供的开发语言、开发类库、开发工具进行App软件开发。比如Android是...

空空如也

1 2 3 4 5 ... 20
收藏数 51,028
精华内容 20,411
关键字:

混合app开发