nstudio / nativescript-audio

:microphone: NativeScript plugin to record and play audio :musical_note:
Other
150 stars 104 forks source link

Can not play audio from App folder #131

Closed karo-dc closed 5 years ago

karo-dc commented 6 years ago

.initFromFile({ audioFile: '~/resources/sample.mp3', loop: false, completeCallback: console.log('reference back to player:', player), errorCallback: console.log('the error:', player), })

Vue.js is the framework being used.

I noticed there was a closed issue like this one, but I didn't see the answer there https://github.com/nstudio/nativescript-audio/issues/126

Thanks in advance.

dodas commented 5 years ago

Having same issue. Can play from URL, but not from local file. output with debug enabled:

JS: 'NativeScript-Audio - TNSPlayer' [ 'audioPath', '@/test.mp3', [length]: 2 ]
JS: 'NativeScript-Audio - TNSPlayer' [ 'android mediaPlayer is not initialized, creating new instance',
JS:   [length]: 1 ]
JS: 'NativeScript-Audio - TNSPlayer' [ '_mAudioFocusGranted', false, [length]: 2 ]
JS: 'NativeScript-Audio - TNSPlayer' [ 'resetting mediaPlayer...', [length]: 1 ]
JS: 'NativeScript-Audio - TNSPlayer' [ 'setting datasource', '@/test.mp3', [length]: 2 ]
JS: 'NativeScript-Audio - TNSPlayer' [ 'playFromFile error',
JS:   [Error: java.io.IOException: setDataSource failed.
JS:       android.media.MediaPlayer.setDataSource(MediaPlayer.java:1282)
JS:       android.media.MediaPlayer.setDataSource(MediaPlayer.java:1223)
JS:       android.media.MediaPlayer.setDataSource(MediaPlayer.java:1190)
JS:       com.tns.Runtime.callJSMethodNative(Native Method)
JS:       com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1116)
JS:       com.tns.Runtime.callJSMethodImpl(Runtime.java:996)
JS:       com.tns.Runtime.callJSMethod(Runtime.java:983)
JS:       com.tns.Runtime.callJSMethod(Runtime.java:967)
JS:       com.tns.Runtime.callJSMethod(Runtime.java:959)
JS:       com.tns.gen.java.lang.Object_vendor_30443_26_ClickListenerImpl.onClick(Object_vendor_30443_26_ClickListenerImpl.java:17)
JS:       android.view.View.performClick(View.java:6877)
JS:       android.widget.TextView.performClick(TextView.java:12651)
JS:       android.view.View$PerformClick.run(View.java:26069)
JS:       android.os.Handler.handleCallback(Handler.java:789)
bradmartin commented 5 years ago

Only time I've had this issue is when the file type isn't supported on the device. Can you share the file you're trying to use?

The demo app works fine with a local .mp3 seen here

dodas commented 5 years ago

I tried using the angel.mp3 file from demo app and it doesn't work either.

@bradmartin are you using nativescript-vue?

karo-dc commented 5 years ago

@dodas I have solved: import { knownFolders, Folder, File, path, FileSystemEntity } from 'tns-core-modules/file-system'; const folder: Folder = knownFolders.currentApp().getFolder('resources'); const file: File = folder.getFile('sample.m4a.png');

please put and rename mp3 or m4a file with .png ext, it will be work, look above how I implemented, after that you can play file

player .initFromFile({ audioFile: file.path, loop: false, }) .then(() => { player.play().then((isPlay) => { console.log(PlayPlay:, isPlay); }); player.getAudioTrackDuration().then((duration) => { console.log(song duration:, duration); }); });

NL33 commented 5 years ago

Follow-up: using the plugin+NS Angular+iOS, I also have only been able to get a local file to play if I have .png at the end of it, like:

import { TNSPlayer } from "nativescript-audio";
...
Export class...

private _player: TNSPlayer;

constructor() {
   this._player = new TNSPlayer();
}
...
playSound(){
     this._player.playFromFile({
          audioFile: '~/audio/mySound.mp3.png',
          loop: false
       })
}

Previously, mySound ended in mp3 and played fine with prior NS versions. Since upgrading to NS 5.0+, it stopped working, and would give error: Error: Uncaught (in promise): Error Domain=NSOSStatusErrorDomain Code=2003334207 "(null)"

It now works with the .png at the end. This seems odd, because I had thought png was an image file. How could it play audio?

dparolin commented 5 years ago

Same issue here on both iOS and Android using Nativescript-Vue. Demo indeed works fine and I tried to understand the issue comparing the source of the demo, source of the plugin, use plain Javascript etc., but could not really make sense out of it.

The workaround to use png (and jpg for that matter) indeed works for wav/mp3 and m4a (iOS) files, my uneducated guess is that the os helps identifying the type of the file then.

snowch commented 5 years ago

Renaming to .png didn't work for me. Playing from Url does work. I'm using nativescript-angular 5.2.4

Robbt commented 5 years ago

I was able to diagnose this slightly by determining that for some reason the nativescript filesystem could not see my sounds folder that existed inside of the app folder. I don't think there was anything special about the permissions but it could see my images folder, so I tried moving my audio into there and playFromFile still failed.

So I instead moved all of my mp3 audio files into the assets folder which the nativescript filesystem could see and they were suddenly able to play again without the setDataSource failure.

To diagnose this I hacked the reslveAudioFilePath in nativescript-audio/common.js to determine if nativescript could see the various file folders and files.

function resolveAudioFilePath(path) {
    if (path) {
        var isUrl = isStringUrl(path);
        if (isUrl === true) {
            return path;
        }
        else {
            var audioPath = void 0;
            var fileName = types_1.isString(path) ? path.trim() : '';

            if (fileName.indexOf('~/') === 0) {
                fileName = fs.path.join(fs.knownFolders.currentApp().path, fileName.replace('~/', ''));
                audioPath = fileName;
                console.log(fileName);
                console.log(fs.knownFolders.currentApp().path)
            }
            else {
                audioPath = fileName;
            }
            const soundFolder = fs.path.join(fs.knownFolders.currentApp().path, 'assets/')
            const exists = fs.Folder.exists(soundFolder);
            console.log(soundFolder);
            console.log(`Does the assets folder exist: ${exists}`);
            return audioPath;
        }
    }
}

You could if you were desperate try copying this code into your common.js

            const soundFolder = fs.path.join(fs.knownFolders.currentApp().path, 'assets/')
            const exists = fs.Folder.exists(soundFolder);
            console.log(soundFolder);
            console.log(`Does the assets folder exist: ${exists}`);

It might make sense to add an additional level of error checking somewhere in the nativescript-audio app to provide a better error to people so that they are aware the problem is nativescript can't see the files vs. the issue being with underlying android audio.

I also don't have any idea why assets works and sounds doesn't. Is there some kind of underlying pre-approved folders that nativescript has accesss too ? I'm using vue-nativescript and this all changed with the upgrade so I had to spend hours rebuilding my app to get it working again so now I can resume actual development.

sylwesterdigital commented 5 years ago

Try to add to Info.plist this:

<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>

uvigii commented 5 years ago

In my case it was related with webpack in webpack.config.js new CopyWebpackPlugin([ { from: { glob: "fonts/**" } }, { from: { glob: "**/*.jpg" } }, { from: { glob: "**/*.png" } }, { from: { glob: "**/*.mp3" } },

apbassi89 commented 5 years ago

In my case it was related with webpack in webpack.config.js new CopyWebpackPlugin([ { from: { glob: "fonts/**" } }, { from: { glob: "**/*.jpg" } }, { from: { glob: "**/*.png" } }, { from: { glob: "**/*.mp3" } },

This fixed it for me. Thanks so much!

My particular solution was just adding the new folder I had created with my audio files, media, to the webpack config:

new CopyWebpackPlugin([
    { from: { glob: "fonts/**" } },
    { from: { glob: "**/*.+(jpg|png)" } },
    { from: { glob: "assets/**/*" } },
    { from: { glob: "media/**/*" } },
], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),