Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Local media does not work on Android #200

Open
scottopolis opened this issue Oct 21, 2019 · 2 comments
Open

Local media does not work on Android #200

scottopolis opened this issue Oct 21, 2019 · 2 comments

Comments

@scottopolis
Copy link

scottopolis commented Oct 21, 2019

Thank you for this great plugin! I would love to use it, but I think I have found a bug.

What version of Streaming-Meda-Cordova-Plugin are you using?

latest

What version of Cordova are you using?

8.0.0

What devices are affected?

Android

Please describe the issue in detail, with relevant code samples

I have all audio and video working on iOS and Android when using full paths, such as https://mysite.com/file.mp3. Local files (in the application directory) work on iOS, but not Android.

On Android, when I attempt to play a local file, such as www/assets/file.mp3, a blank player opens and nothing happens. No errors, no controls, no sound, nothing.

I am using streamingMedia.playAudio( cordova.file.applicationDirectory + 'www/assets/file.mp3' ) for the filepath, and I have confirmed that the path is correct, and the correct file exists at this path. I can play it using HTML5 audio at this exact path, it also works on iOS.

I have tried relative urls, and every local path imaginable, no local files work on Android. I have tested on a device and using the emulator, the behavior is the same.

Any help would be amazing. Thanks!

@nettopuis
Copy link

I had the same problem recently. I have not seen any documentation on this, but it seems like local playback (from asset folder bundled in app) does not work with this plugin on Android. It's probably a security issue causing the plugin to not be able to get the file in the bundled file structure. I used a workaround on Android, but it's far from perfect. Please see the two approaches for iOS and Android below.

Setup:

In Ionic/Cordova the File plugin is needed:

import { File } from '@ionic-native/file/ngx';

With Ionic/Cordova I also needed to reference cordova.js in my project index.html file:
<script src="cordova.js"></script>

To be honest, I'm not sure if needed, but I also add the Cordova File plugin in my config.xml along with the straming media plugin:
<plugin name="cordova-plugin-file" spec="6.0.2" source="npm"/>
<plugin name="cordova-plugin-streaming-media" spec="2.2.0" source="npm" />

Again, I am not sure if needed, but I also have the Cordova Whitelist plugin added:
<plugin name="cordova-plugin-whitelist" spec="1.3.3" />

..with a bunch of paths allowed:
<access origin="*" />
<access origin="cdvfile://*" />
<access origin="file://*" />
<access origin="cdvfile:///*" />
<access origin="file:///*" />
<access origin="cdvfile:///storage/*" />
<access origin="file:///storage/*" />
<access origin="content:///*" />
<access origin="files/*" />

I also add these permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Playback on iOS is quite straight forward:

playIosVideo(){
    let path:string = "www/assets/videos/video.mp4";
    let targetPath:any = this.file.applicationDirectory + path;
    let options = {            
      shouldAutoClose: true
    }
    window["plugins"].streamingMedia.playVideo(targetPath, options); 
}

I used a workaround on Android, but it's far from perfect. My approach is to copy the file from the applicationDirectory (in the bundled file structure) to the dataDirectory (storage available to the app):

playAndroidVideo(){
    let path:string = "www/assets/videos/";
    let targetPath:any = this.file.applicationDirectory + path;
      
    //first - resolve target path in bundled file structure:
    this.file.resolveLocalFilesystemUrl(targetPath)
    .then((entry: any)=>{

      let dirPath = entry.toNativeURL();
      //alert('target entry: '+entry + ", - dirPath: "+dirPath);

      //then - resolve save folder in dataDirectory:
      this.file.resolveLocalFilesystemUrl(this.file.dataDirectory)
      .then((entry: any)=>{        
        let savePath = entry.toNativeURL();
        //alert('save entry: '+entry + ", - savePath: "+savePath);
        
        //then - copy file to saveFolder
        this.file.copyFile(dirPath, "video.mp4", savePath, "video.mp4")
        .then((entry: any)=>{
          
          let newPath = entry.toNativeURL();
          //alert("File copied, entry.toNativeURL(): "+newPath);
          let options = { 
            successCallback: function() {
              //alert("Video playback OK.");              
            },
            errorCallback: function(errMsg) {
              alert("Error playing video file! " + errMsg);
            },           
            shouldAutoClose: true
          }
          window["plugins"].streamingMedia.playVideo(newPath, options);
                         

        }).catch((error)=>{
          alert("error copyFile: "+error);
        }); 
      
      }).catch((error)=>{
        alert("error resolveLocalFilesystemUrl (save folder): "+error);
      }); 

    }).catch((error)=>{
      alert("error resolveLocalFilesystemUrl (target): "+error);
    });     
    
  }

This is definitely a workaround to get it to work on Android and absolutely not a perfect solution. Main drawbacks:

  • The copy takes a little while depending on the size of the file. My 55 MB file takes about 1-2 seconds to copy before playback is ready. A larger file will take several seconds to copy, also depending on the device.
  • Copying the file actually makes the app take up more space on the device as the file is copied to the dataDirectory. A solution is to add a function which deletes the copied file when closing the app or navigating to another view in the app.

I tried to get the Ionic native video player to work (com.moust.cordova.videoplayer), but without success. Maybe this plugin allows playback from the asset folder?

@scottopolis
Copy link
Author

@nettopuis thank you for this, copying the file to the data directory does work on Android. I had to modify your code a bit to work, specifically file.copyFile I used file.applicationDirectory + "www/" as the first argument.

I would still consider this a "bug" in this plugin, but this is a valid workaround. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants