SCMLife.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 2966|回复: 1

[推荐] 使用 IBM Worklight 开发跨平台的 HTML5 视频播放混合应用程序

[复制链接]
发表于 2013-2-17 15:18:54 | 显示全部楼层 |阅读模式
本帖最后由 技术狂人 于 2013-2-17 15:22 编辑
3 w7 Z5 H# f$ f) f3 G/ c' x+ ?& @4 Q. Y& W% P
简介
( j4 e0 \) ?9 u( h! d移动混合应用程序将原生的操作系统功能与 Web 技术相结合。通常,混合应用程序在一个嵌入式 Web 浏览器中呈现内容,该方法增强了跨平台功能,因为大部分代码都可使用 HTML5 技术编写,同时支持在必要时访问原生设备功能。IBM Worklight 是一个移动应用程序平台,支持开发跨平台混合应用程序,提供了在 Web 视图与原生视图之间导航的机制,还提供了一个可使混合应用程序更接近 “一次编写,随处运行” 目标的开发和运行时环境。
- N3 Z9 r7 _' L0 J. n' y应用程序中的视频播放是一个很难实现跨平台功能的领域。HTML5 的 <video> 标记用于实现跨平台视频播放,但功能支持上的不一致导致它无法实现此目标。
$ B% r2 [' H$ ?$ o9 @) z  X( y本文将重点介绍如何在跨平台 HTML5 混合应用程序中开发视频播放,解释 IBM Worklight 开发平台如何帮助解决无法在任何特定平台上支持 HTML5 的视频功能时遇见的问题。  X) O2 |( V0 |  S


3 T0 K  o2 Z+ i- T* d9 b6 X! C5 h6 ]- J# ~# r7 {4 a$ l! P
视频播放挑战
) A' s, r9 Z9 ^计算机和移动设备上的视频播放长久以来一直是开发人员面临的挑战,因为开发视频功能需要理解复杂的技术和术语。在深入介绍之前,让我们来了解一些术语。" Z* L, ~  v. x0 a0 v. D
视频是一个视频(或图片)流和一个或多个音频流的组合,它们都封装在一个压缩文件中。在常见的视频用语中:) ^6 D( a% \: J9 i
  • 视频容器将音频和视频文件封装在单个压缩文件中。有许多视频容器格式,一些流行的格式包括 MPEG4、Flash Video、Ogg、WebM 和 Audio Video Interleave。容器格式使用文件扩展名表示,比如 mp4、flv、ogv、webm 和 avi 等。
  • 视频编解码器识别用于编码和解码(压缩和解压)视频流的软件算法。视频播放器需要知道使用何种编解码器来解码和播放视频流。
  • 音频编解码器类似于视频编解码器,但用于音频流。9 S1 z, h4 U# E( e3 y' y
通向 HTML5 之路1 N* l+ D! u  d, _
视频播放的主要挑战来源于计算机和移动设备中的视频播放机制的演化。在 HTML5 规范诞生之前,没有在浏览器中播放视频的标准方式,而且视频几乎始终是通过第三方插件(比如 RealPlayer、Apple QuickTime 和 Adobe Flash)进行传输的。HTML5 的视频播放功能从一定程度上解决了对插件的依赖性,甚至在 YouTube 播放视频的广受欢迎导致 Flash 成为桌面上的实时标准时也是如此。随着 Apple 拒绝 Flash,转而青睐于使用 HTML5 在 iOS 设备上播放视频,使用 Flash 的跨领域视频播放就变得不可能了,而且开发人员开始关注创建使用 HTML5 播放视频的网站了。' E9 ]( k$ K4 W* L6 M9 ]+ Z
HTML5 添加了一个新 video 标记用于将视频内容直接嵌入到网页中,以不使用插件播放视频。清单 1 给出了添加一个 video 标记来在浏览器窗口中播放 mp4 视频的示例。它指定嵌入到浏览器窗口中的视频播放器的宽度和高度,分配给它的空间量,启用了自动播放,所以视频无需用户操作即可播放,还启用了屏幕视频控件(播放、暂停和音量)。最重要的是,它指定了要播放的视频源压缩文件。
# ~# {# i! R, M1 B% A7 G, q- ~" C$ c' a* `  C
清单 1. 用于将视频嵌入网页中的 HTML5 video 标记
! |8 w6 i8 V6 c  S$ O' ^3 d! @* O
<video width="320px" height="480px" autoplay="autoplay" controls="controls">
1 h9 O, y# e; J/ R$ E/ j$ K        <source src="dir/video.mp4" type="video/mp4"/>3 u" L- `+ K8 W
</video>

) N4 P+ {& @) W3 F; y2 uHTML5 video 标记的采用已得到广泛支持。最初,在起草 HTML5 时,Safari 是惟一提供了 HTML5 视频支持的浏览器,但现在所有现代浏览器都支持它。网络上的流视频正在快速从 Flash 插件过渡到 HTML5 标准,即使 HTML5 规范仍然为草案格式(预计将于 2014 年完成)。
+ s" G- F- f! z& U( EHTML5 视频播放的不足之处
- V% ]% v/ h; k( \7 M$ L. w% C! w/ j不幸的是,对 HTML5 video 标记的浏览器支持仅是故事的一部分,因为视频播放需要的不仅仅是标记支持。对视频容器格式、视频和音频编解码器,以及传输协议的支持都在跨浏览器的网页互操作性中发挥着重要的作用。例如,对 H.264 和 WebM 等编解码器的浏览器支持是可选择的,一些浏览器支持一种编解码器,而不支持另一种编解码器。HTML5 没有指定编解码器,因为标准小组未对使用哪种编解码器达成一致意见,这意味着考虑使用 HTML5 video 的 Web 开发人员必须考虑浏览器兼容性问题。
9 c+ f8 v; {1 v; c由于移动设备的多样性和它们不同的屏幕分辨率和处理器,移动视频播放还带来了其他挑战。例如,移动市场上有数百个 Android 变体版本,它们都需要播放音频和视频。
, g4 w! U2 w: \# r7 F& ~) F, X

0 O: c' @; Y8 h4 {$ d5 F6 F
. \* V) W9 c7 x7 s/ x& g& O0 L试验、苦恼和解决方案9 y0 w( E" h2 {4 `+ l6 ~0 }- e
我们的 SmarterTVApp 项目涉及到一个具有视频播放功能的跨平台移动混合应用程序的开发,似乎只有使用 HTML5 video 播放视频才是自然而然的事。我们使用经过 Worklight Studio 4.2 Eclipse 插件扩展的 Eclipse、在 Red Hat Linux® 上运行 Worklight Server 的服务器硬件,以及一个填充了 MPEG4 视频文件的视频存储服务器组建了一个开发环境。然后使用多个运行 Android 4.0 Ice Cream Sandwich 和 Apple iOS 5 的移动设备来测试它,它们从一个视频存储服务器接收视频,该服务器使用 HTTP Level Streaming (HLS) 协议传输视频。
! q+ \& N/ |; G/ W4 n  r3 层混合应用程序模型* S- y  Q. D6 F% s! s. M& D& ?
Worklight 开发的应用程序使用一种 3 层跨平台应用程序模型,如图 1 所示。最底层包含原生操作系统 API 库提供的原生操作系统功能。对于我们的 SmarterTVApp,这包括内置于应用程序中的 Android 或 iOS 操作系统 API 调用点。
* E9 v; G- W* z- r* b& w+ A3 V& A: T4 w; q- s  d  b" i
图 1. 3 层应用程序模型
7 I4 \5 m1 z# K; ~# J9 h# q, x- g% ?0 z: e
中间层包含 Worklight 和它提供的 Apache Cordova 组件,它们将 HTML5 应用程序代码与原生的设备操作系统功能衔接起来。Apache Cordova(以前称为 PhoneGap)是一个开源移动开发框架,支持通过 JavaScript™ 访问原生操作系统功能来开发混合应用程序。这一层中的 Worklight 组件提供了客户端功能,比如设备皮肤、加密存储、推送通知、服务器集成框架和许多其他功能。
- Q! V9 y7 B0 J% c0 n, Y顶层包含应用程序组件。在 SmarterTVApp 中,顶层包含我们的自定义应用程序 JavaScript、HTML 和 CSS 代码,以及我们为了支持应用程序而导入的组件 IBM Dojo Toolkit 1.7.2 版,以及我们的应用程序用来演示和视图间过渡的 IBM issw.mobile 应用程序框架。1 c& T( [2 {1 z: n8 q
开发环境) C* M, N  u! l
当在 Eclipse 中创建一个 Worklight 项目时,Worklight Studio 插件创建一个初始目录结构,其中填充了一组针对应用程序和运行时环境的文件夹。SmarterTVApp 的目录结构如图 2 所示。common 文件夹包含所有设备部署环境中通用的 JavaScript、HTML 和 CSS 文件,而 android、ipad 和 mobilewebapp 文件夹包含特定于设备的优化文件。
" ]& Y1 S, c0 _! T7 r在 common 文件夹中,我们还添加了与 Dojo 相关的文件夹(dijit、dojo 和 dojox)来保存应用程序使用的 Dojo 文件,并为组成 issw.mobile application 框架的文件添加了一个 issw 文件夹。1 t; a6 D2 `# Z8 i3 M% x
* e2 q" A% S- m0 I! n& j& B4 H& m
图 2. Worklight 项目文件夹
5 h$ W& v! U2 _) ^$ v; ~3 t2 E! Q
开发测试环境的一个简单演示如图 3 所示。Android 和 iOS 设备与一个在 Worklight Server 上运行的服务器应用程序交互,该应用程序然后会发起从 Video Storage Server 到设备的视频传输。+ ~1 o! n' B2 Q/ @

5 J* B. z* y' m) B* a图 3. 开发测试环境" x3 F3 X& M3 Z$ i0 G
! G0 c3 S$ I2 B6 x! k. Q) n9 y
使用 HTML5 video 的初始实现
0 G' z! e9 f( B  O我们的初始设计使用了 HTML5 video 来实现跨平台视频播放,所以我们使用两个 source 元素来实现 video 元素,如清单 2 所示。当遇到多个 source 元素时,浏览器将会使用第一个识别的格式,我们希望 MP4 和 OGV 格式将会提供足够多的跨浏览器功能。3 o* C  g! |, N9 ?

/ T9 I  q! p  h9 ?7 w清单 2. 指定一种多格式的视频的 HTML5 video 标记' v% t) O. r: e9 R) Y* j: Q
<video width="320px" height="480px" autoplay="autoplay" controls="controls">
' K6 F9 e3 O; c/ c+ H0 H        <source src="dir/video.mp4" type="video/mp4/">/ v0 g$ U0 m- b$ o0 G  y
        <source src="dir/video.webm" type="video/webm/">( L- E# j# _7 C* b
</video>

  q8 D6 |  H' B1 q在我们开始测试第一个原型时,我们对通过使用 HTML5 video 快速实现跨平台视频播放的高期望破灭了。通过一些调整,我们成功地在 iOS 设备上运行的应用程序之上实现了视频播放,但在 Android 上运行它时就没有这么幸运。因此,要在开发过程中执行一个试用和错误阶段。" _* y; K5 D- h8 a
努力实现解决方案' h' F/ P2 t7 l0 `; ]+ z5 a% @7 M% r
这里的一个重要的考虑因素是,用于 Android 的移动混合方法(由 Cordova 实现)基于用于显示网页的 Android WebView 类。一个基于 Cordova 的混合应用程序使用一个 WebView 显示应用程序的 HTML5 内容部分。在我们的测试中,我们发现尽管 HTML5 视频内容能在 Android 浏览器中成功播放,但在通过混合应用程序的 WebView 对象显示 HTML5 视频内容时,无法播放该视频。
4 d8 ~# {( O# S2 x4 P. j% c我们自然会从网络上寻找信息,一次快速搜索证实了我们的担忧:技术论坛上的许多帖子来自在 Android 4.0 上面临类似 WebView HTML5 视频播放问题的痛苦的开发人员。根据我们查阅到的建议,我们尝试了各种视频格式,尝试过更改 video 标记参数,还尝试过更改创建 video 元素及其属性的许多动态 (JavaScript) 和静态 (HTML) 方面,但都没有成功。
- {1 C' D9 H# J9 Y4 z$ S, G) B+ k所以是采用 B 计划的时候了:在将应用程序构建为在 Android 上运行时,放弃使用 HTML5 video 标记的跨平台视频播放,改用 Android 原生视频播放功能。当构建来在 iOS 上运行时,应用程序将按最初的计划使用 HTML5 视频播放。! f5 s3 N" Y& g  K9 O% [
使用 Worklight 开发的一个好处是,它提供了一种将原生页面合并到混合应用程序中的简单机制。Worklight 的混合编码功能支持应用程序在 Web 与原生页面之间导航,以及在这些页面间共享数据。通过使用此功能,我们的混合应用程序能够切换到使用 Android 的 Java API 集播放视频的原生页面,然后在播放完视频时切换回对 iOS 和 Android 通用的 JavaScript 代码。- n  S% g, t" ^
有了此知识,我们开始实现一个原生页面,它使用 VideoView 对象创建一个 Android 活动来播放视频,最后我们取得了成功:在 Android 上运行的时候播放视频。
2 ?; X) X8 b( a) b1 ?
" C# v5 ^' P9 v3 b7 O3 ^
' h9 E% T! A9 a# g3 N6 G
解决方案细节
/ K) C! @7 l3 w& H# G) u解决方案同时包含 Android 原生 Java 代码和 JavaScript 代码。JavaScript 代码使用 Worklight 的功能调用 Android Java 代码来播放视频。+ ]2 L  w5 \# E& G! b, t0 u5 c
播放视频的 Android 原生 Java 代码0 Z1 A0 [6 b: i: T5 h
为了实现 Java 视频功能,我们首先在特定于 Android 的项目结构位置下创建了一个新 StreamingVideoActivity.java 类,如图 4 所示。Worklight 项目结构(将特定于设备的优化文件分离到独立的文件夹中)简化了我们的解决方案需要的 Android 原生代码的添加。
! O6 R3 B. h3 D" D5 m  x+ U: y/ p; N# U" ]: t* E
图 4. 包含 Android 原生 Java 代码的 Worklight 项目文件夹' x1 Q% \9 k, g, c  q, k
0 {" o$ N8 N7 T
StreamingVideoActivity 被实现为 Android 活动的一个扩展,使用 VideoView 和 MediaController 来播放视频。此实现的大纲如清单 3 所示。完成的解决方案将实现处理视频终止和完成事件的回调,以将控制权返回到 Worklight 的基于 Web 的屏幕视图。
+ I: J( A4 L4 D( n
; ^( p. q% _$ c( S清单 3. StreamingVideoActivity.java 实现
3 l2 i% T8 i# h+ O
public class StreamingVideoActivity extends Activity {: K2 q( L0 V" O% K2 P  Q
        ) E$ G* ^8 `! h. |/ _" n
    /** Called when the activity is first created. *// q2 J+ X! n6 A! g9 A
    @Override6 B: h) l2 E' ~) c
    public void onCreate(Bundle savedInstanceState) {( I3 W! Q9 w+ w3 K+ M% M' V$ q3 ]! p
            ) i  `/ c( M$ c7 d6 f* J6 k$ Y
        super.onCreate(savedInstanceState);
5 a6 e$ g5 i3 A6 h+ r        Log.d("StreamingVideoActivity", "Entering onCreate");                       
2 [( ]1 n% k4 j5 c6 x+ O8 X' Y% l6 c% ~$ h
        // Extract the URL from the Intent4 B! Q4 V( W- n/ n  A3 i& x
        String url = getIntent().getStringExtra("urlParam");
6 u8 C1 K4 B* E3 Q: W4 x" a2 m                0 o3 ~' _0 j- Q% j
        Log.d("StreamingVideoActivity", "About to play URL: url");                        ' P" Y' ^9 T: B3 P8 @4 E
        VideoView videoView = new VideoView(this);( h# |, z7 M  _8 `2 ~" Y+ v) ?! ~# \
        videoView.setVideoPath(url);
- B+ G1 ^& g- X, {                2 z; M+ g; m7 n9 H
        MediaController ctlr = new MediaController(this);5 [% t* C1 B% A
        ctlr.setMediaPlayer(videoView);
. ]( S) W- d# b( \        videoView.setMediaController(ctlr);$ B+ z# a' M" S: g
      
) n) W9 a- n! J$ ~0 u' T  E' }+ N7 _        setContentView(videoView);
  u$ s$ j- f- @, c0 s2 R# ~        videoView.requestFocus();7 t, U% d  f2 z  K/ S
        Log.d("StreamingVideoActivity", "Leaving onCreate");                       
5 Y0 a) O& l4 J' w$ B1 e! n! @    }2 O# v/ p  g6 D& b& G8 _
}

4 t8 _4 n' [" R% v6 o5 z: ~从 Web 应用程序调用 Android 代码
* {: j" `; v# j6 ]- p( UAndroid 工作完成后,剩余的工作只是创建一个 JavaScript 函数,它使用 Worklight WL.NativePage.show API 函数从基于 Web 的活动切换到新的原生 Android 活动。实现此功能的 JavaScript 文件 SmarterTVApp.js 放在特定于 Android 的项目结构位置中,如图 5 所示。
  ?+ [) E" j9 S$ h6 z, a: e* j- p; Y# ^! b" J' F/ d, j% M; v3 _' E
图 5. 包含特定于 Android 的 JavaScript 文件的 Worklight 项目文件夹
* L& Z4 z0 G* @$ Q- \$ D
3 W4 ?3 R+ N6 F/ i清单 4 中的代码摘自 SmarterTVApp.js,显示了调用 Worklight WL.NativePage.show 函数来运行 StreamingVideoActivity 活动的 openNativePage 函数的实现。4 P5 C2 ^3 {0 w

: M  v7 p. h0 z! p6 \清单 4. SmarterTVApp.js 代码摘录( }! r. A% D! j7 A0 m# }) |
/**
: @6 ]% D3 w0 G7 V * Plays the specified video in an Android native page& _& L/ G9 q  ]
* @param url  The video URL
$ ~& X( e4 D' o/ k4 O. f */! i( g, S' @3 z. l/ n
function openNativePage (url) {7 N4 ~+ g4 W% M" F
        WL.Logger.debug("Switching to SmarterTVApp.StreamingVideoActivity to play " +url);
+ P4 }1 e% M% I0 |, i8 V# w4 i/ k
7 E7 o( j* ?  o0 b' J2 X        // Create an object to hold the URL.  The field name, urlParam, must match9 j. A5 B6 M$ p
        // the name used in the native Android Java code for extracting the URL
) N$ @% G/ n/ B0 D; S7 c2 z- ]        var params = {urlParam : url};
& _! J  C  e% \* ]2 J8 Q
6 @4 `' Q: D7 R0 |# j5 V        // Show the Android native page3 i$ e$ f* \( i6 V) |7 n+ l
        WL.NativePage.show('com.SmarterTVApp.StreamingVideoActivity', & D9 T. X+ v2 T" s4 V" Z
                backFromNativePage, params);
# A" e$ l- O- `2 z( A* r9 I  R. Q}0 H; E( r5 F$ K8 R7 R: b
, `  k, L$ }- p; y8 T9 B9 i2 W
/**
8 b' Z3 j6 T; [% R' v8 r3 a * Invoked as a call-back on return from the Android native page. g  u% l: h0 ]' q' S1 l/ O# h
* @param data
; w/ P) V. y* ] */7 \, N+ U' F2 Q
function backFromNativePage(data) {
8 y( r5 C( L. C9 D8 k        WL.Logger.debug("Back from StreamingVideoActivity");
. a9 F8 `( |  K; ]; T& K}

4 u% }# t; h7 Q! F/ g最后,我们需要在混合应用程序在一个 Android 设备上运行时有条件地调用 openNativePage,Worklight Studio 开发环境也可在这里提供帮助。无需检测设备类型并添加 if-then-else JavaScript 逻辑,Worklight 项目结构会自动处理此任务。在我们的应用程序视频中,播放在 StreamingView.js 文件中执行。通过创建该文件的两个版本,如图 6 所示,一个存储在启动 HTML5 视频播放的 common 文件夹中,另一个存储在调用 Worklight openNativePage 函数来启动 Android 原生视频播放的 android 文件夹中,Worklight Studio 自动处理了包含适合运行时环境的文件版本的过程。3 I" L0 D% E7 E, N6 P
& z% a! ^  H0 f& v. F
图 6. 视频流的双重实现& e  @1 ^6 N# u, D- Y, C
% ]  u: [5 O7 E  W& i' I$ h1 H

8 z2 I& x% p- Y& [& m$ m# i
) T# f( q- c; M
结束语
7 k; E/ t1 D) s9 J- q* m* v从这个项目,我们了解到,跨平台视频播放可能很难实现,并且解决方案可能需要使用原生设备功能。Worklight 通过使用它组合原生和基于 Web 的功能的能力,简化了开发。
  s  K% r; Y% _0 p; p  D# P/ \2 y& Q. i$ `: e6 ]( ^

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
 楼主| 发表于 2013-2-17 15:23:08 | 显示全部楼层
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|无图版|SCMLife.com ( 京ICP备06056490号-1 )

GMT+8, 2018-1-18 00:12 , Processed in 0.074797 second(s), 8 queries , Gzip On, MemCache On.

Powered by SCMLife X3.4 Licensed

© 2001-2017 JoyShare.

快速回复 返回顶部 返回列表