cordova-plugin-file 从 extSD 播放视频文件

cordova-plugin-file to play video file from extSD

我需要包装我的 cordova html 显示图片和 运行 位于外部 SD 根目录之外的视频文件。在 cordova-plugin-file.

的 git 集线器上似乎没有可以提出这些问题的地方

A) 如果文件位于根以外的那两个子目录中,我不确定我是否理解在下面的 2 B&C 中使用什么路径来完成此操作?

B) 如果我只需要访问分机 SD,那么 3 B 中的所有这些值都是必需的吗?

到目前为止,这是我从文档中了解到的...但显然我没有完全正确,因为我收到了错误(见下文)

1) 从 CMD 行设置环境

    cordova create MyApp
    cd /MyApp
    cordova platform add android@latest
    cordova plugin add cordova-plugin-whitelist
    cordova plugin add cordova-plugin-file
    corddova build android (after step 3 below)

2) 将这些添加到 index.html

A) cdvfile: scheme to Content-Security-Policy meta tag of the index page, e.g.:

 <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap:cdvfile:https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src 

B) <img src="cdvfile:///img/logo.png" />

C) <p><a href="cdvfile://video/MyVideo.mp4">Play video</a></p>

3) 将这些添加到 config.xml

A) <access origin="cdvfile://*" />

B) <preference name="AndroidExtraFilesystems" value="files,files-external,documents,sdcard,cache,cache-external,assets,root" />

我在 Android 上点击视频 link 时出现的错误是 ...

 net::ERR_UNKNOWN_URL_SCHEME (cdvfile:video/0001_a1.mp4)

=========== 编辑 #1

现在正在尝试@DaveAlden 的推荐...使用名为 [cordova.plugins.diagnostic][2] 的插件和此配置来定位 ExtSD 上的根路径以播放视频但出现错误(见下文)...

config.xml

 <preference name="android-minSdkVersion" value="14" />

 <preference name="android-targetSdkVersion" value="14" />

 <preference name="android-maxSdkVersion" value="25" />
 <plugin name="cordova-plugin-whitelist" spec="1" />

 <plugin name="cordova.plugins.diagnostic" />

Index.html

<body>

<!-- Set up path to ExtSD on Android -->
<script>
function getSdRefAndEmbed(){
    cordova.plugins.diagnostic.getExternalSdCardDetails(function(details){
    details.forEach(function(detail){
        if(detail.type === "root"){
        cordova.file.externalSdCardRoot = detail.filePath;
        embedMedia();
        }
    });
    }, function(error){
    console.error(error);
    });
}

function embedMedia(){
    $('.extSdVideo').each(function(){
        $(this).attr('href', cordova.file.externalSdCardRoot + $(this).attr('href'));
    });
}

$(document).on('deviceready', getSdRefAndEmbed);
$(document).on('pageinit', embedMedia);
</script>

<!-- Play video file -->
<a class="extSdVideo" href="video/0001_a1.mp4" id="0001_a1"> a1 </a>

</body>

应用程序错误

net::ERR_FILE_NOT_FOUND (file:///android_assest/www/HHR/hhr-cm_cameroon-cm1-fra-spa/‌​‌​hhr/hhr-cm_cameroo‌​n-‌​cm1-fra-spa/vide‌​o/00‌​01_a1.mp4

尝试将 0001_a1.mp4 放在这两个目录中的任何一个...

extSDRoot/video/0001_a1.mp4

and/or

extSDRoot/www/HHR/hhr-cm_cameroon-cm1-fra-spa/‌​‌​hhr/hhr-cm_cameroo‌​n-‌​cm1-fra-spa/vide‌​o/00‌​01_a1.mp4

=================== 编辑#2

@DaveAlden 建议尝试这三件事...

1) 将 console.dir(details) 放入 getExternalSdCardDetails() 以查看插件找到的本地路径。

结果:它在错误消息中给出了相同的路径

Application Error
net::ERR_FILE_NOT_FOUND
(file:///android_asset/www/hhr/cm_cameroon-cm1-fra-spa/0001_a1.mp4) 

2) 在同一台设备上尝试 example project (https://github.com/dpa99c/cordova-diagnostic-plugin-example) 以查看 ext SD 示例是否有效。

结果 1:示例项目的构建失败...

BUILD FAILED Total time: 47.426 secs Error: cmd: Command failed with exit code 1 Error output: F:\DIAGNOSTIC_WORKING\cordova-diagnostic-plugin-example\plat‌​forms\android\build\ intermediates\res\merged\debug\values-v24\values-v24.xml:3: AAPT: Error retrievi ng parent for item: No resource found that matches the given name 'android:TextA ppearance.Material.Widget.Button.Borderless.Colored'.

@DaveAlden 对构建失败的回应...

You have missing/outdated Android SDK components in your build environment and/or are using an outdated version of cordova-android platform. See documentation (https://github.com/dpa99c/cordova-diagnostic-plugin#building-for-android) and this issue (https://github.com/dpa99c/cordova-diagnostic-plugin/issues/161).

我的操作:

我检查了 Android SDK 管理器,通过 运行 执行此命令

查看所需产品的所有 API 级别都在同一级别
C:> Android -v

Android SDK Tool 25.2.5
SDK platform 25
Android Support Repository 46
Google Play services 39
Google Repository 45

我运行这个命令...

cordova platform check android

得到这个结果...

F:\DIAGNOSTIC_WORKING\cordova-diagnostic-plugin-example>cordova platform check android
Subproject Path: CordovaLib
android @ 6.1.2; current did not install, and thus its version cannot be determined

为什么我得到这个"current did not install"?这可能是诊断插件找不到 extSD 正确路径的问题吗?

我运行这个命令...

cordova platform rm android && cordova platform add android@latest && cordova build android

示例项目构建成功!

查看显示 extSD 路径的示例诊断应用程序的屏幕截图。这条路径看起来与我 运行 我的应用程序中的诊断插件时得到的路径非常不同。

请注意按钮 "Write External SD File" 在按下时没有写入任何内容。我检查了我的文件管理器。

为示例项目提供的路径与诊断插件为我的应用程序提供的路径非常不同(见下文)。这些结果来自同一个 Galaxy S7。

net::ERR_FILE_NOT_FOUND (file:///android_assest/www/HHR/hhr-cm_cameroon-cm1-fra-spa/‌​‌​hhr/hhr-cm_cameroo‌​n-‌​cm1-fra-spa/vide‌​o/00‌​01_a1.mp4

我 运行 这个命令适用于我的应用程序但没有改变...

cordova platform rm android && cordova platform add android@latest && cordova build android

3) @DaveAlden 建议 运行 使用 Chrome 进行调试...接下来我会这样做。

找到这个...

============= 编辑 3 使用 cordova-diagnostic-plugin

成功地从 extSD 播放视频

方法如下...

最后的障碍是因为我有 Android 6+ phone 我还必须添加一个函数来检查 运行 读取 extSD 的时间权限。代码在编辑#2(见上文)中不断显示错误,就像它试图查看内部路径一样。一旦我添加了检查 运行 时间许可的功能,它终于给出了正确的外部路径。提示……仅在清单中提供许可是不够的。你可以在这里读到它。感谢@DaveAlden 的示例项目!

https://github.com/dpa99c/cordova-diagnostic-plugin-android-runtime-example

Android runtime permissions

Android 6 / API 23 introduces the concept of runtime permissions. Similar to >iOS, certain "dangerous" permissions must be requested at runtime in addition >to being listed in the Android manifest.

Runtime permissions only apply if the device/emulator the app is running on has >Android 6.0 or above AND the app is built using API 23 or higher. For Cordova, >this means using the Cordova Android platform version 5.0.0 or above. If the >app is built with version 4.x or below (API 22 or below), runtime permissions >do not apply - all permissions are granted at installation time.

添加到 Config.xml

<access origin="*" />
<plugin name="cordova-plugin-whitelist" version="*" />
<plugin name="cordova.plugins.diagnostic" version="*" />
<plugin name="cordova-plugin-file" version="*" />
<preference name="android-minSdkVersion" value="21" />
<preference name="android-targetSdkVersion" value="23" />


<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

感谢@DaveAlden 提供此代码...我只添加了检查 运行 时间读取权限的功能。戴夫,您应该将这段用于从 extSD 读取媒体文件的代码添加到您的项目示例中,这样您就不必像帮助我那样帮助下一个人。 :)

添加到Index.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src * gap://ready file:; style-src 'self' 'unsafe-inline'; img-src * 'self' data:; script-src * 'unsafe-inline' 'unsafe-eval'">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">

<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="js/index.js"></script>

<h3>Play video and img file</h3>

<img class="extSdImg" src="img/image1.png"/>
<img class="extSdImg" src="img/image2.png"/>

<p>
<a class="extSdVideo" href="video/video1.mp4">Play video</a>
</p>

<p>
<a class="extSdVideo" href="video/video2.mp4">Play video</a>
</p>
</body>
</html>

添加到Index.js

function authorizerequestExtSD() {
cordova.plugins.diagnostic.requestExternalStorageAuthorization(function(status){
    console.log("Successfully requested external storage authorization: authorization was " + status);
    checkState();
    getSdRefAndEmbed();
               }, function(error){
     console.error(error);
    });
}

function getSdRefAndEmbed(){
    cordova.plugins.diagnostic.getExternalSdCardDetails(function(details){
    details.forEach(function(detail){
           if(detail.type === "root"){
          cordova.file.externalSdCardRoot = detail.filePath;
          embedMedia();
          }
    });
        }, function(error){
            console.error(error);
    });
}

function embedMedia(){
    $('.extSdImg').each(function(){
           $(this).attr('src', cordova.file.externalSdCardRoot + $(this).attr('src'));
    });
    $('.extSdVideo').each(function(){
            $(this).attr('href', cordova.file.externalSdCardRoot + $(this).attr('href'));
    });
}

$(document).on('deviceready', authorizerequestExtSD);
$(document).on('pageinit', embedMedia);

添加 jQuery 的本地文件副本(在本项目 https://github.com/dpa99c/cordova-diagnostic-plugin-example 中找到一个):

jquery-2.1.3.min.js 

您的方法行不通:cdvfile:// 是由 cordova 定义的内部伪协议,其中路径的第一部分定义了一个内部参考点 (cdvfile://localhost/persistent|temporary|another-fs-root*/path/to/file),而 2B 和 2C正在定义路径,就好像是相对于外部 SD 卡根目录的路径。

请注意,cordova-plugin-media 对您没有帮助,因为它仅用于播放音频,本身并不解析文件位置。

如果您的媒体文件位于外部可移动 SD 卡上(例如在 Samsung Galaxy 设备中),cordova-plugin-file 不提供访问此位置的参考。 cordova-plugin-file 使用的 "external" 引用(例如 cordova.file.externalRootDirectory)实际上指向一个内部内存位置 - /scard/。这是因为并非所有设备都有可移动的外部 SD 卡(例如 Google Nexus),因此 /sdcard 是一个 "emulated" 存储位置,它保证存在于所有 Android 设备上。

如果您希望从外部 可移动 SD 卡读取文件,您可以使用 cordova-diagnostic-plugin 获取对外部 SD 卡根目录的有效文件路径引用.请注意,这需要在 JS 中动态完成,而不是在 HTML:

中硬编码静态路径

index.html

<body>
    <img class="extSdImg" src="img/image1.png"/>
    <img class="extSdImg" src="img/image2.png"/>
    <p><a class="extSdVideo" href="video/video1.mp4">Play video</a></p>
    <p><a class="extSdVideo" href="video/video2.mp4">Play video</a></p>
</body>

index.js

function getSdRefAndEmbed(){
    cordova.plugins.diagnostic.getExternalSdCardDetails(function(details){
    details.forEach(function(detail){
        if(detail.type === "root"){
        cordova.file.externalSdCardRoot = detail.filePath;
        embedMedia();
        }
    });
    }, function(error){
    console.error(error);
    });
}

function embedMedia(){
    $('.extSdImg').each(function(){
        $(this).attr('src', cordova.file.externalSdCardRoot + $(this).attr('src'));
    });
    $('.extSdVideo').each(function(){
        $(this).attr('href', cordova.file.externalSdCardRoot + $(this).attr('href'));
    });
}

$(document).on('deviceready', getSdRefAndEmbed);
$(document).on('pageinit', embedMedia);