Ionic media plugin is not working

Hi Folks,

Trying to create a simple player by passing a local .mp3 file path. Below is my code -

import { Component } from '@angular/core';
import { PlaylistPage } from '../playlist/playlist';
import { NavController, ModalController, reorderArray, ViewController, IonicApp, IonicModule, IonicErrorHandler, Platform } from 'ionic-angular';
import { Media, MediaObject } from '@ionic-native/media';


@Component({
  templateUrl: 'tabs.html'
})
export class TabsPage {
  visible = false;
  shuffle= false;
  url:string='assets/audio/1001.mp3';
  file: MediaObject = this.media.create(this.url);
  constructor(private viewCtrl: ViewController,private media: Media, private platform:Platform,
    public navCtrl: NavController, private modalCtrl: ModalController, private files:File) {
      this.platform.ready().then(() => { 
        this.file.onStatusUpdate.subscribe(status => console.log('Satish', status)); // fires when file status changes
        this.file.onSuccess.subscribe(() => console.log('Action is successful'));
        this.file.onError.subscribe(error => console.log('Error!', error));
      })
  }
  play() {
    this.file.play();
  } 

}

Erro -

core.js:1350 ERROR Error: Uncaught (in promise): TypeError: Cannot set property 'statusCallback' of undefined
TypeError: Cannot set property 'statusCallback' of undefined
    at MediaObject.set [as statusCallback] (decorators.js:195)
    at Observable._subscribe (index.js:39)
    at Observable._trySubscribe (Observable.js:172)
    at Observable.subscribe (Observable.js:160)
    at tabs.ts:18
    at t.invoke (polyfills.js:3)
    at Object.onInvoke (core.js:4629)
    at t.invoke (polyfills.js:3)
    at r.run (polyfills.js:3)
    at polyfills.js:3
    at MediaObject.set [as statusCallback] (decorators.js:195)
    at Observable._subscribe (index.js:39)
    at Observable._trySubscribe (Observable.js:172)
    at Observable.subscribe (Observable.js:160)
    at tabs.ts:18
    at t.invoke (polyfills.js:3)
    at Object.onInvoke (core.js:4629)
    at t.invoke (polyfills.js:3)
    at r.run (polyfills.js:3)
    at polyfills.js:3
    at c (polyfills.js:3)
    at polyfills.js:3
    at t.invokeTask (polyfills.js:3)
    at Object.onInvokeTask (core.js:4620)
    at t.invokeTask (polyfills.js:3)
    at r.runTask (polyfills.js:3)
    at o (polyfills.js:3)
    at e.invokeTask [as invoke] (polyfills.js:3)
    at p (polyfills.js:2)
    at HTMLDocument.v (polyfills.js:2)

Where i am doing it wrong ??

Hi Champion007,

i’m going to assume that the error may be coming from the fact you are calling the plugin before the device is ready. I would advise putting the code above such that it replicates the following:

file: MediaObject = null; //consider changing this to musicfile and all further instances to avoid conflict in the future

this.platform.ready().then(() => {
  //code here such that:
  file = this.media.create(this.url);
});

then only allowing the play() function if the ‘file’ variable is not null:

play() {
  if (!file) {
    console.log('not yet ready'); return;
  }
  this.file.play();
}

Hope this helps!

EDIT: also make sure that the variable ‘file’ isn’t used else where for example from the ‘cordova-file’ plugin, maybe call the variable ‘musicfile’ instead for predicting later code.

1 Like

Thank you for your reply @HeyItsMatty i did what you have mentioned but i don’t know where i am going wrong.

Plugin events are not firing getting same error.

`file: MediaObject = null; //consider changing this to musicfile and all further instances to avoid conflict in the future
  url:string='assets/audio/1001.mp3';
  visible = false;
  shuffle= false;  
 
  constructor(private viewCtrl: ViewController,private media: Media, private platform:Platform,
    public navCtrl: NavController, private modalCtrl: ModalController) {
      this.platform.ready().then(() => { 
        this.file = this.media.create(this.url);
        this.file.onStatusUpdate.subscribe(status => console.log('status>>>>>>>>>', status)); // fires when file status changes
        this.file.onSuccess.subscribe(() => console.log('Action is successful'));
        this.file.onError.subscribe(error => console.log('Error!', error));        
      })
  }
  play() {
    console.log('file>>>>>>>>>>>>>>', this.file);
    if (!this.file) {
      console.log('not yet ready'); return;
    }
    this.file.play();
  }`

Hmm, not fully sure. I haven’t really dabbled about with the media plugin at all, Just for debugging purposes would you try commenting out everything bar the this.file = this.media.create(this.url); to see which of the callbacks is causing the error. Breaking down the error you are receiving, typescript is throwing a hissy fit that something is undefined and therefore it can’t make a callback for one of the promises (or subscribes).

Also double check that the mp3 is in a reachable place by the plugin. Coming from fileOpener2 it was vital to have a file in the native app folder instead.

may i ask what is calling the play() function?

finally i have just noticed now, but you are declaring the type MediaObject on the file variable before defining it in the constructor. Try setting the file variable as follows:

file: any = null;

or better still reference it as a constant, so you can negate the this part.

const file:any = null

let me know if anything solves this.

  • Matt

Thanks @HeyItsMatty media in local directory is not readable for some reason, below is the log i am getting -

Here is modified code -

constructor(private viewCtrl: ViewController,private media: Media, private platform:Platform) {
      this.platform.ready().then(() => { 
        this.playEvents();
      })
  }

  playEvents(){
    const file: MediaObject = this.media.create('assets/audio/1001.mp3');
    console.log('file>>>>>>>>>>>>', file);
    file.play();
  }
MediaObject {_objectInstance: undefined, onSuccess: Observable, onError: Observable, onStatusUpdate: Observable}
errorCallback
:
(...)
onError
:
Observable {_isScalar: false, _subscribe: ƒ}
onStatusUpdate
:
Observable {_isScalar: false, _subscribe: ƒ}
onSuccess
:
Observable {_isScalar: false, _subscribe: ƒ}
statusCallback
:
(...)
successCallback
:
(...)
_objectInstance
:
undefined
__proto__
:
Object

I am waiting for platform ready , then calling a method here I’m checking for native media events, i am getting object as undefined.

Where this example works for me - https://arielfaur.github.io/ionic-audio-demo/

Hi @champion007,

Apologies for the delay in the response, been very busy with other projects.

It seems you may have figured out the problem, audio files not placed inside of a native folder will result in the audio not being found, for example in the github you linked, the tracks are being loaded from an external URL:

{
      src: 'https://archive.org/download/JM2013-10-05.flac16/V0/jm2013-10-05-t12-MP3-V0.mp3',
      artist: 'John Mayer',
      title: 'Why Georgia',
      art: 'assets/img/johnmayer.jpg',
      preload: 'metadata' // tell the plugin to preload metadata such as duration for this track, set to 'none' to turn off
}

Try using an external mp3 to test to see if your code works and then you’ll need to venture into the filetransfer plugin as well as the file plugin to find out more. Remember that native plugins are built around exactly as they seem, native components, meaning some may not be programmed to see a web server assets folder (how ionic processes assets), therefore requiring you to transfer them into an app readable document first.

If the external files do not work then there may still be a problem with your code, however we’ll debug further if it comes to it.

Good luck!

  • Matt
1 Like

Thank @HeyItsMatty :slight_smile:

1 Like

@HeyItsMatty - Sorry was held up with some deliverable, I tried the external URL that also has the same issue.

As i am calling the .play() on click of a button and events of the media plugin is on platform ready.

I am struggling with this now tried multiple approach , googled but nothing worked for me.

I have even tried re-installing plug in , platform nothing worked.

If you have working sample can you share the link.

Thnak you - Satish

it worked for me !

ionic cordova plugin add cordova-plugin-media@5.0.0