我已经设法使用以下方法加载和播放 vimeo 视频。但是,如 vimeo oembed doc 中所示,autoplay=1 s 不会在加载时自动播放。任何人都找到了自动播放的方法(还需要在视频结束时捕捉事件)
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setAppCacheEnabled(true);
mWebView.getSettings().setDomStorageEnabled(true);
// how plugin is enabled change in API 8
if (Build.VERSION.SDK_INT < 8) {
mWebView.getSettings().setPluginsEnabled(true);
} else {
mWebView.getSettings().setPluginState(PluginState.ON);
}
mWebView.loadUrl("http://player.vimeo.com/video/24577973?player_id=player&autoplay=1&title=0&byline=0&portrait=0&api=1&maxheight=480&maxwidth=800");
最佳答案
此答案仅针对 Vimeo。在大约十几次失败的尝试之后,这就是我的工作。也许它会帮助别人。向其他 SO 答案的原作者道歉一千次。我在下面“借用”了一些模式——只是认为将所有这些放在一个地方会很方便,并且不要为我自己的代码声明它们。
首先,我还没有找到解决嵌入 Vimeo 播放器的方法(即你不能直接访问 mp4 流——至少不容易或不可靠——我很确定这是故意的)。其次,Vimeo 提供了一个 javascript 库来检测他们的播放器,并且使用它是相当不可避免的。当心,它需要消息传递,这是一种较新的浏览器功能。这记录在他们的 API 页面上。第三,正如 SO 的其他地方所记录的那样,您需要非常小心地等待部分堆栈准备就绪,并且不要跳枪。第四,Vimeo 播放器包含一个特别无用的背景图像,旨在传达插件丢失或损坏(一小帧电影,这是常见的图标)。真正的意思是你的 javascript 在某个地方被轰炸了,什么都没有运行。如果您在空白屏幕上看到一小段电影,请检查您的 javascript。
第 1 步。设置 WebView。你上面有这个正确的。作为引用,这是我使用的。
mWebView = new WebView((Context) this);
mWebView.setLayoutParams(new LayoutParams(windowWidth, windowHeight));
mWebView.getSettings().setJavaScriptEnabled(true);
// Watch the sdk level here, < 12 requires 'false
// Wanted to force HTML5/264/mp4, you may want flash
// where still available
mWebView.getSettings().setPluginState(PluginState.OFF);
mWebView.getSettings().setLoadWithOverviewMode(true);
mWebView.getSettings().setUseWideViewPort(true);
mWebView.getSettings().setUserAgentString("Android Mozilla/5.0 AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30");
wcc = new MyWebChromeClient();
mWebView.setWebChromeClient(wcc);
wvc = new MyWebViewClient();
mWebView.setWebViewClient(wvc);
第 2 步。如果您希望视频在 WebView 上工作,则需要 WebChromeClient。此处记录:http://developer.android.com/reference/android/webkit/WebView.html (请参阅 HTML 视频支持)。
再一次,我用的是引用。
private class MyWebChromeClient extends WebChromeClient {
@Override
public void onProgressChanged(WebView view, int progress) {
if(progress == 100) {
// Your page is loaded, but not visible,
// add whatever navigation elements you plan to use here.
// N.B. these are JAVA, not JS nav elements
}
}
@Override
public boolean onConsoleMessage(ConsoleMessage cm) {
// I like to watch in the console. And, since it was
// a very convenient way to monitor the javascript, I
// use it for that too. Purists will object, no doubt
if(cm.message().equalsIgnoreCase("EVENT -- Finish")) {
Log.i(TAG, "---> Finishing . . .");
// Depart the activity
finish();
} else {
Log.d(TAG, " **Console ["+cm.sourceId()+"] ("+cm.lineNumber()+") ["+cm.message()+"]");
}
return(true);
}
@Override
public View getVideoLoadingProgressView() {
// Something entertaining while the bytes arrive
Log.i(TAG, " -------------> Loading Progress . . . ");
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
return(inflater.inflate(R.layout.loading_video, null));
}
@Override
public void onShowCustomView(View v, WebChromeClient.CustomViewCallback callback) {
// With great sadness, I report that this never fires.
// Neither does the 'hide'.
}
@Override
public void onHideCustomView() {
}
}
WebViewClient 看起来像这样:
private class MyWebViewClient extends WebViewClient {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
String injection = injectPageMonitor();
if(injection != null) {
Log.d(TAG, " ---------------> Page Loaded . . .");
Log.d(TAG, " Injecting . . . ["+injection+"]");
view.loadUrl(injection);
}
}
}
第 3 步。您需要构建一点点 Javascript 来触发播放器。我用过这个:
public String injectPageMonitor() {
return( "javascript:" +
"jQuery(document).ready( function() { " +
"console.log(' === Page Ready ===> Setting up');" +
"console.log(' ==== Sending PLAY Command ===');" +
"var froogaloop = $f('froog');" +
"setTimeout(function() { froogaloop.api('play'); }, 3000);" +
"});");
}
快速解释。 . .我在我的 JS 中使用 jQuery,它在下面。那只是为了方便,如果你想减轻负担,你可以直接做JS。请注意,在其他一切准备就绪之后,脚本会再等待 3 秒才能真正触发。在我软弱的时候,我想象 Vimeo 的好心人有一个 splinter 的“准备好”回调。 3 秒似乎可以做到。
第 4 步。页面上需要一些 HTML 和 JavaScript。我将它放在资源 (raw/vimeo_frame.html) 内的文本文件中。该文件如下所示:
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script type="text/javascript">jQuery.noConflict();</script>
<script src="http://a.vimeocdn.com/js/froogaloop2.min.js"></script>
<script type="text/javascript">
jQuery(document).ready( function() {
var showing_player = false;
var froogaloop = $f('froog');
console.log(' === Page Ready ===> Setting up');
jQuery('.froog_container_class').hide();
jQuery('.console').css('height', '100%');
froogaloop.addEvent('ready', function() {
console.log('==== PLAYER READY ====> Setting Play Callback');
froogaloop.addEvent('play', function(data) {
console.log('EVENT -- Play');
/* No idea why, but if the player isn't displayed, it goes
straight to 'pause'. Probably a feature. So I give it 4x4px
to do it's thing during setup */
jQuery('.froog_container_class').show();
jQuery('.froog_container_class').css('height', '4px');
jQuery('.froog_container_class').css('width', '4px');
jQuery('.froog_container_class').css('overflow', 'hidden');
});
/* I don't want to reveal the video until it is actually
playing. So I do that here */
var showingPlayer = false;
froogaloop.addEvent('playProgress', function(data) {
if(!showingPlayer && data.percent > 0) {
showingPlayer = true;
jQuery('.froog_container_class').show();
jQuery('.froog_container_class').css('height', '_windowHeight');
jQuery('.froog_container_class').css('width', '_windowWidth');
/* Most tablets I tested aren't quick enough to make this work
but one can still hope */
jQuery('#loading').fadeOut('slow');
}
});
});
});
</script>
</head>
<body>
<style>
body {
background-image: url('http://<SomethingEntertainingToWatch>.png');
background-size: contain;
}
.mask {
float: left;
height: _windowHeight;
width: _windowWidth;
z-index: 100;
background: transparent;
display: inline;
position: absolute;
top: 0;
left: 0;
}
.froog_container_class {
position: absolute;
height: _windowHeight;
width: _windowWidth;
left: 0;
top: 0;
display: inline;
z-index: 1;
}
#froog {
display: inline;
height: _windowHeight;
width: _windowWidth;
postion: absolute;
top: 0;
left: 0;
}
</style>
<div id="loading" class="loading"><h1>Loading</h1><img class="loading_anim" src="http://foo.bar.com/assets/global/loading.gif"/>
</div>
<!-- Completely optional, I put a div in front of the player to block controls -->
<div id="mask" class="mask">
</div>
<div id="froog_container" class="froog_container_class">
<iframe id="froog" src="_targetUrl?api=1&title=0&byline=0&portrait=0&player_id=froog" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen>
</iframe>
</div>
</body>
</html>
然后我像这样加载这个 html 文件:
public String genMainHTML() {
String code = null;
try {
Resources res = getResources();
InputStream in_s = res.openRawResource(R.raw.vimeo_frame);
byte[] b = new byte[in_s.available()];
in_s.read(b);
code = new String(b);
} catch (Exception e) {
e.printStackTrace();
}
if(code != null) {
code = code.replaceAll("_windowHeight", "" + windowHeight + "px");
code = code.replaceAll("_windowWidth", "" + windowWidth + "px");
code = code.replaceAll("_targetUrl", targetUrl);
return(code);
} else {
return(null);
}
}
然后像这样注入(inject):
mDomain = "http://player.vimeo.com";
mWebView.requestFocus(View.FOCUS_DOWN);
targetUrl = extras.getString("URL");
String meat = genMainHTML();
mWebView.loadDataWithBaseURL(mDomain, meat, "text/html", "utf-8", null);
setContentView(mWebView);
哇!当 WebView 准备就绪时,html 和 js 就会进入,包括带有 Vimeo 播放器的 iframe。加载文档后,我们等待播放器准备就绪。当播放器准备就绪时,我们添加一些监听器。 3 秒后,我们触发 api“播放”方法。
观众中那些爱吹毛求疵的人可能想知道,为了完整起见,如何停止视频?两位。首先,当它结束时,我通过观察控制台输出中显示的消息来停止它。因此:
public String injectPageFinisher() {
return( "javascript:" +
"jQuery(document).ready( function() { " +
"console.log(' === Page Ready ===> Tearing down');" +
"console.log(' ==== Sending PAUSE Command ===');" +
"var froogaloop = $f('froog');" +
"froogaloop.api('pause');" +
"jQuery('#froog_container').html('');" +
"});");
}
可以这样插入:
@Override
public void onPause() {
super.onPause();
if(isFinishing()){
// Unload the page
if(mWebView != null) {
Log.i(TAG, " ------> Destroying WebView");
mWebView.destroy();
}
}
finish();
}
第二部分是视频完成它的小 self 的地方。因此,在上面的 vimeo_frame.html 中,就在“播放”回调之后,我输入:
froogaloop.addEvent('finish', function(data) {
console.log('EVENT -- Finish');
});
在 Activity 中,我做了一些观察 - 请参阅上面的 onConsoleMessage 覆盖。
但是——在撰写本文时,我仍然没有解决一个棘手的问题。 MediaPlayer 在 WebView 及其所有后代消失后继续存在。我确信这会产生一些问题,但我还没有发现它们。
关于android - 在 Android webview 中自动播放 vimeo 视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9030524/
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty
动漫制作技巧是很多新人想了解的问题,今天小编就来解答与大家分享一下动漫制作流程,为了帮助有兴趣的同学理解,大多数人会选择动漫培训机构,那么今天小编就带大家来看看动漫制作要掌握哪些技巧?一、动漫作品首先完成草图设计和原型制作。设计草图要有目的、有对象、有步骤、要形象、要简单、符合实际。设计图要一致性,以保证制作的顺利进行。二、原型制作是根据设计图纸和制作材料,可以是手绘也可以是3d软件创建。在此步骤中,要注意的问题是色彩和平面布局。三、动漫制作制作完成后,加工成型。完成不同的表现形式后,就要对设计稿进行加工处理,使加工的难易度降低,并得到一些基本准确的概念,以便于后续的大样、准确的尺寸制定。四、
2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p
Transformers开始在视频识别领域的“猪突猛进”,各种改进和魔改层出不穷。由此作者将开启VideoTransformer系列的讲解,本篇主要介绍了FBAI团队的TimeSformer,这也是第一篇使用纯Transformer结构在视频识别上的文章。如果觉得有用,就请点赞、收藏、关注!paper:https://arxiv.org/abs/2102.05095code(offical):https://github.com/facebookresearch/TimeSformeraccept:ICML2021author:FacebookAI一、前言Transformers(VIT)在图
最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路
我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功
我想知道是否可以通过自动创建数组来插入数组,如果数组不存在的话,就像在PHP中一样:$toto[]='titi';如果尚未定义$toto,它将创建数组并将“titi”压入。如果已经存在,它只会推送。在Ruby中我必须这样做:toto||=[]toto.push('titi')可以一行完成吗?因为如果我有一个循环,它会测试“||=”,除了第一次:Person.all.eachdo|person|toto||=[]#with1billionofperson,thislineisuseless999999999times...toto.push(person.name)你有更好的解决方案吗?
目前我正在使用这个正则表达式从YoutubeURL中提取视频ID:url.match(/v=([^&]*)/)[1]我怎样才能改变它,以便它也可以从这个没有v参数的YoutubeURL获取视频ID:http://www.youtube.com/user/SHAYTARDS#p/u/9/Xc81AajGUMU感谢阅读。编辑:我正在使用ruby1.8.7 最佳答案 对于Ruby1.8.7,这就可以了。url_1='http://www.youtube.com/watch?v=8WVTOUh53QY&feature=feedf'url