Titanium JIRA Archive
Appcelerator Community (AC)

[AC-5622] ios simulator crashes when playing a sound from local filesystem

GitHub Issuen/a
TypeBug
Priorityn/a
StatusResolved
ResolutionDone
Resolution Date2018-03-06T21:30:59.000+0000
Affected Version/sAppcelerator Studio 4.5.0
Fix Version/sn/a
ComponentsTitanium SDK & CLI
Labelsn/a
Reportermvschilt
AssigneeShak Hossain
Created2018-02-25T21:23:31.000+0000
Updated2018-03-06T21:30:59.000+0000

Description

I'm creating an app to record sound from the microphone. This code was working before but suddenly the simulator crashes. I thought it was my app, so I tried to isolate it in a separate app to test it. But if I use the code from http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Media.AudioRecorder and adjust it a little bit to my code the simulator also the simulator crashes without giving any pointer to the problem. My code: added permission: NSMicrophoneUsageDescription app.js
var window = Ti.UI.createWindow({
  backgroundColor: '#fff'
});

var recordStart = Ti.UI.createButton({
  title: 'Start',
  top: 10
});

var recordPause = Ti.UI.createButton({
  title: 'Pause',
  top: 60
});

var recordStop = Ti.UI.createButton({
  title: 'Stop',
  top: 110
});

var recordPlay = Ti.UI.createButton({
  title: 'Play',
  top: 160
});

var audioRecorder = Ti.Media.createAudioRecorder();
var record;
var audioPlayer;
var voiceFile;
var recDir = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory,'Recordings');
     if(!recDir.exists()){
       recDir.createDirectory();
     };

window.addEventListener('open', function(e) {
  if (!Ti.Media.hasAudioRecorderPermissions()) {
    Ti.Media.requestAudioRecorderPermissions(function(e) {
      if (e.success) {
        window.add(recordStart);
      }
    });
  } else {
    window.add(recordStart);
  }
});

recordStart.addEventListener('click', function(e) {
  audioRecorder.start();
});

recordPause.addEventListener('click', function(e) {
  if (audioRecorder.getPaused()) {
    recordPause.setTitle('Pause');
    audioRecorder.resume();
  } else {
    recordPause.setTitle('Resume');
    audioRecorder.pause();
  }
});

recordStop.addEventListener('click', function(e) {

	record = audioRecorder.stop();
	var date = new Date();
	var millisec = date.getMilliseconds();
	voiceFile =     Ti.Filesystem.getFile(recDir.nativePath, "Test_"+ millisec +".mp4");
        voiceFile.write(record);
        Ti.API.info("voiceFile native " +  voiceFile.nativePath);
});

recordPlay.addEventListener('click', function(e) {
  Ti.API.info("start playing sound");
  Ti.API.info("voiceFile native " +  voiceFile.nativePath);
  audioPlayer = Ti.Media.createAudioPlayer({
    url: voiceFile.nativePath
  });
  audioPlayer.start();
});

window.add(recordPause);
window.add(recordStop);
window.add(recordPlay);

window.open();

Attachments

FileDateSize
console trace log.txt2018-02-25T21:22:40.000+000032960

Comments

  1. Mostafizur Rahman 2018-02-26

    Hello [~mvschilt], Thanks for sharing with us. Can you please share us the exact test case to reproduce this on our end and the error logs during the app crash.
  2. mvschilt 2018-02-26

    Hi @mrahman, Thanks for your response. I've got the main part of the code from the example given on page http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Media.AudioRecorder. I added the lines to the code so the file is saved in a specific folder within the Titanium.Filesystem.applicationDataDirectory. The testcase to reproduce: push start button (Start recording) push stop button (Stop recording) push play button (Play sound) The expectation is that when pushing the play button the sound will be played. Instead the simulator ends abnormally and no error is logged.
  3. Hans Knöchel 2018-02-26

    Hey there! When exactly did that work before? Which SDK version? Or do you mean it worked inside the app and then crashes?
  4. mvschilt 2018-02-26

    Hi Hans Knöchel, I made a successful build on the 6th of February with SDK 7.0.0.GA. When I build the app with the SDK to 7.0.0.GA, then also this problem occurs. Before this functionality worked in the app. The sound was playing. But now the simulator crashes. Can you reproduce it? Best regards, Michiel
  5. Hans Knöchel 2018-02-26

    Hey @[~mvschilt], so first of all, you need to set a proper [audio session category](http://docs.appcelerator.com/platform/latest/#!/api/Titanium.Media-property-audioSessionCategory) before:
       Ti.Media.audioSessionCategory = Ti.Media.AUDIO_SESSION_CATEGORY_PLAY_AND_RECORD;
       
    But after that, the app still seems to crash when playing the audio again, although I am not sure if that may be related to the mp4 format which is rather a video than audio format. I will dig some more into this, but this does not seem to be an SDK issue. *EDIT*: See [this example](https://github.com/appcelerator/KitchenSink/blob/stable/Resources/ui/handheld/ios/phone/sound_record.js) for more details. *EDIT 2*: The following works:
       var window = Ti.UI.createWindow({
         backgroundColor: '#fff'
       });
       
       Ti.Media.audioSessionCategory = Ti.Media.AUDIO_SESSION_CATEGORY_PLAY_AND_RECORD;
        
       var recordStart = Ti.UI.createButton({
         title: 'Start',
         top: 200
       });
        
       var recordPause = Ti.UI.createButton({
         title: 'Pause',
         top: 60
       });
        
       var recordStop = Ti.UI.createButton({
         title: 'Stop',
         top: 110
       });
        
       var recordPlay = Ti.UI.createButton({
         title: 'Play',
         top: 160
       });
        
       var audioRecorder = Ti.Media.createAudioRecorder({
         compression: Ti.Media.AUDIO_FORMAT_AAC,
         format: Ti.Media.AUDIO_FILEFORMAT_MP4
       });
       var record;
       var audioPlayer;
       var voiceFile;
       var recDir = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory,'Recordings');
            if(!recDir.exists()){
              recDir.createDirectory();
            };
        
       window.addEventListener('open', function(e) {
         if (!Ti.Media.hasAudioRecorderPermissions()) {
           Ti.Media.requestAudioRecorderPermissions(function(e) {
             if (e.success) {
               window.add(recordStart);
             }
           });
         } else {
           window.add(recordStart);
         }
       });
        
       recordStart.addEventListener('click', function(e) {
         audioRecorder.start();
       });
        
       recordPause.addEventListener('click', function(e) {
         if (audioRecorder.getPaused()) {
           recordPause.setTitle('Pause');
           audioRecorder.resume();
         } else {
           recordPause.setTitle('Resume');
           audioRecorder.pause();
         }
       });
        
       recordStop.addEventListener('click', function(e) {
        
       	record = audioRecorder.stop();
       	var date = new Date();
       	var millisec = date.getMilliseconds();
       	voiceFile =     Ti.Filesystem.getFile(recDir.nativePath, "Test_"+ millisec +".mp4");
               voiceFile.write(record);
               Ti.API.info("voiceFile native " +  voiceFile.nativePath);
       });
        
       recordPlay.addEventListener('click', function(e) {
         Ti.API.info("start playing sound");
         Ti.API.info("voiceFile native " +  voiceFile.nativePath);
         audioPlayer = Ti.Media.createAudioPlayer({
           url: voiceFile.nativePath
         });
         audioPlayer.start();
       });
        
       window.add(recordPause);
       window.add(recordStop);
       window.add(recordPlay);
        
       window.open();
       
    We should update the docs to reflect this configuration. Let us know if it works for you as well! The AudioRecorder API is pretty powerful, but also requires some configuration.
  6. mvschilt 2018-02-26

    Hi Hans, Thank you very much for your digging. It works fine at my side, I added some code to clear the record variable. so when you record again this variable will be empty.
       recordStart.addEventListener('click', function(e) {
       	record = '';
         audioRecorder.start();
       });
       
    But I'm still wondering if there was someting changed in the SDK, because I believe the code is handled more strict. Before I had this code: $.Login.fbProxy = fb.createActivityWorker({lifecycleContainer: $.Login}); Running it on ios didn't cause any problem. But as the issue logged in this ticket the app also crashed, so I made it specifically for android platform and there was no problem anymore. Thanks for your help.
  7. Hans Knöchel 2018-02-26

    createActivityWorker is Android only, so if it didn't cause issues on iOS before, that was the actual issue. 7.0.0 uses the native JSCore by default, which reduces the app size and brings other advantages like the safari debugger. But you can still try to disable it by using <use-jscore-framework>false</use-jscore-framework>. Can we resolve this issue? Let me know!
  8. mvschilt 2018-02-26

    Hi Hans, Ah that is good to know, thanks for letting me know. yes the issue can be put to resolved. Many thanks for your help. Best regards, Michiel

JSON Source