Titanium Community Questions & Answer Archive

We felt that 6+ years of knowledge should not die so this is the Titanium Community Questions & Answer Archive

Any Android module devs out there want to help me solve a problem? (That everyone could benefit from)

Hello,
I need help.

You might have seen the demo on the Dev Blog a while ago showing how to use Activity Intents to record audio on Android. (Yes, yes, I know about the Codeboxed module.. that's not the point ;) )

Here's the post:
http://developer.appcelerator.com/blog/2011/02/launching-activities-and-using-content-uris-in-android.html/comment-page-1#comment-67235

The issue I have with the demo is that the recorder returns a 'contentUri' to the recorded file. This is actually a reference to the file which is stored in the internal database in the device. This, as you may discover, is pretty useless when it comes to wanting to upload it or save it somewhere, for exmaple, since Ti.Filesystem just can't get a handle on it.

The actual path to the audio in the database is in a field called "_data" as far as I can tell.

So, (as Don Thorpe suggested in the comments on the blog post about this) all we need to do is create a simple module that can query the Media database of the file based on the contentUri and return the full file path.

Now, I'm no Java programmer at all (that's why we use Titanium right? ;) ) but I know some of you are. I have had a dabble in trying to get this working though, and I've made some progress, I think!!

But, it's not working, and I know I must be missing something obvious (to those of you with a firmer grip on Java and how Titanium/Kroll uses it)

Here's a link to a Gist to see the java code I'm come up with so far, and also the javascript I'm using to call it.

https://gist.github.com/1152360

Here's a link to the JavaScript I'm using to test it (based o nthe blog post exmaple)

https://gist.github.com/1152362

Here's the error I'm getting : I must be doing some wrong with understanding maybe how proxies work? I don't know.. ;/

https://gist.github.com/1152370

If anyone could help get this sorted, I think it would help make a great tutorial/exmaple on how to go about building these things. From what I've learned so far while struggling for the past few days on this, it looks as if a better understanding could really pay dividends when it comes to extending Ti with modules.

Cheers!
:)

— asked August 17th 2011 by Kosso
  • android
  • contenturi
  • modules
  • query
  • tutorials
7 Comments
  • Here's also a link which helped me get this far.. but not when it comes to making this work with Titanium:

    http://www.higherpass.com/Android/Tutorials/Accessing-Data-With-Android-Cursors/4/

    — commented August 17th 2011 by Kosso
  • Here's a nother useful snippet, which looks to make things even easier, but I don't seems to be able to get it working for Mediastore.Audio.Media.DATA

    http://stackoverflow.com/questions/3401579/get-filename-and-path-from-uri-from-mediastore

    The module build fails on the managedQuery part.

    : cannot find symbol
        [javac] symbol  : method managedQuery(android.net.Uri,java.lang.String[],<nulltype>,<nulltype>,<nulltype>)
        [javac] location: class com.kosso.contentquery.ContentqueryModule
        [javac]         Cursor cursor = managedQuery(contentUri, proj, null, null, null);
        [javac]                         ^
        [javac] 1 error
    
    — commented August 17th 2011 by Kosso
  • OK.. now I've tweeked the Java class and I feel like I'm getting closer..

    here's the error I'm now getting :

    https://gist.github.com/1152720

    — commented August 17th 2011 by Kosso
  • Nnow getting : " Cannot convert content://media/external/audio/media/24 to android.net.Uri "

    
    E/KrollMethod( 3117): at org.appcelerator.titanium.kroll.KrollHandlerThread.run(KrollHandlerThread.java:86)
    E/KrollCallback( 3117): (kroll$3: app://rec.js) [9,10869] Error evaluating source, invocation: [callMethod Activity.(anonymous) org.appcelerator.titanium.kroll.KrollCallback@406d1890], message: Cannot convert content://media/external/audio/media/24 to android.net.Uri (app://rec.js#85)
    E/KrollCallback( 3117): org.mozilla.javascript.EvaluatorException: Cannot convert content://media/external/audio/media/24 to android.net.Uri (app://rec.js#85)
    E/KrollCallback( 3117): at org.appcelerator.titanium.TiContext.runtimeError(TiContext.java:299)
    E/KrollCallback( 3117): at org.mozilla.javascript.Context.reportRuntimeError(Context.java:945)
    E/KrollCallback( 3117): at org.mozilla.javascript.Context.reportRuntimeError(Context.java:1001)
    E/KrollCallback( 3117): at org.mozilla.javascript.Context.reportRuntimeError2(Context.java:971)
    E/KrollCallback( 3117): at org.mozilla.javascript.NativeJavaObject.reportConversionError(NativeJavaObject.java:896)
    E/KrollCallback( 3117): at org.mozilla.javascript.NativeJavaObject.coerceTypeImpl(NativeJavaObject.java:584)
    E/KrollCallback( 3117): at org.mozilla.javascript.Context.jsToJava(Context.java:1729)
    E/KrollCallback( 3117): at org.appcelerator.kroll.KrollConverter.convertJavascript(KrollConverter.java:329)
    E/KrollCallback( 3117): at com.kosso.contentquery.ContentqueryModuleBindingGen$3.invoke(ContentqueryModuleBindingGen.java:150)
    E/KrollCallback( 3117): at org.appcelerator.kroll.KrollMethod.call(KrollMethod.java:51)
    E/KrollCallback( 3117): at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:1701)
    E/KrollCallback( 3117): at script(app://rec.js:85)
    E/KrollCallback( 3117): at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:854)
    E/KrollCallback( 3117): at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:164)
    E/KrollCallback( 3117): at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:426)
    E/KrollCallback( 3117): at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3177)
    E/KrollCallback( 3117): at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:162)
    E/KrollCallback( 3117): at org.appcelerator.titanium.kroll.KrollCallback.callSync(KrollCallback.java:139)
    E/KrollCallback( 3117): at org.appcelerator.titanium.kroll.KrollCallback$1.run(KrollCallback.java:164)
    E/KrollCallback( 3117): at android.os.Handler.handleCallback(Handler.java:587)
    E/KrollCallback( 3117): at android.os.Handler.dispatchMessage(Handler.java:92)
    E/KrollCallback( 3117): at android.os.Looper.loop(Looper.java:123)
    E/KrollCallback( 3117): at org.appcelerator.titanium.kroll.KrollHandlerThread.run(KrollHandlerThread.java:86)
    E/TiJSError( 3117): (kroll$3: app://rec.js) [7,10876] ----- Titanium Javascript Runtime Error -----
    E/TiJSError( 3117): (kroll$3: app://rec.js) [0,10876] - In app://rec.js:85,0
    E/TiJSError( 3117): (kroll$3: app://rec.js) [1,10877] - Message: Cannot convert content://media/external/audio/media/24 to android.net.Uri (app://rec.js#85)
    E/TiJSError( 3117): (kroll$3: app://rec.js) [0,10877] - Source: null
    
    — commented August 17th 2011 by Kosso
  • Hi Kosso,

    I will have a look on your issue tomorrow and hope that i can help, if you don't solve it till then. Its late here and i have to get some shut eye and reboot my system :)

    Talk to you tomorrow and don't worry, we will get to the bottom of it.

    Thanks.

    Alex

    — commented August 17th 2011 by Alexandru Budin
  • Thanks Alex ;)
    I really feel like it's SO close!

    — commented August 17th 2011 by Kosso
  • I THINK I'VE DONE IT! ;)
    It turns out I was very close..
    Lots and lots of trial and error…

    I'll calm down a bit, then put up an example somewhere. :)

    — commented August 17th 2011 by Kosso

4 Answers

  • OK. I'm going to answer my own question, since after hacking around at this ALL DAY (I'm not even a Java programmer) I managed to get it working.

    Here's some Java module code which works (I haven't built out the full app exmaple yet, but I'll do that in due course).

    https://gist.github.com/1153138

    Hey, go me! ;)

    — answered August 18th 2011 by Kosso
    permalink
    0 Comments
  • Hey Kosso, you code that java class?

    — answered August 18th 2011 by Emrah Mehmedov
    permalink
    1 Comment
    • yup. I did ;)
      Lots of trial and error.. ALL day and a LOT of googling!

      — commented August 18th 2011 by Kosso
  • Hi Kosso,

    Did you want something different from the audio recorder? were you missing some features, that made you go with the intent driven one? Just curious, because we are in the process of updating it and your input would help.

    I am really glad that you fixed the problem.

    Alex

    — answered August 18th 2011 by Alexandru Budin
    permalink
    1 Comment
    • Hi Alex.

      Actually, the reason I originally started to look at the intents demo was to try and use it for recording video. I now have a test/demo app working which use the built in intents to record audio and video and also give back the real path, so that Ti.Filesystem can use it and also use it for uploading. :)

      Actually, it was only a few days ago that I was inspired by your audio recording module that I even started to really try and have a go at building my own. I've been doing a lot of Googling and research around the Android MediaRecorder class after reading your blog post and I think I have something working now which is capable of recording AAC/MPEG_4 .m4a audio at a decent bitrate too. :) Here's a test http://mobods.com/1kv I recorded with it inside my app. (I do the waveform processing on the server, after uploading. The next post is a test using the iPhone version I have built.)

      I had to update my Nexus One to Gingerbread for it to work though, as my previous version did not support the API level needed.

      I have always really hated the native audio recording quality in Android - AMR @ 8KHz so bad! ;)

      I was going to see if I could get MediaRecorder to to video capture too, but then decided to try the intents method first. I also see that I could try using the AudioRecord class to save PCM uncompressed audio - and maybe also try and show the audio levels while recording, but I don't need that. Also I need to have a small file for uploading. PCM file sound good, but are WAY too big!

      BTW: Feel free to let me test your latest module. I'm very happy to give some feedback. It was your module and blog post that inspired me to try an make my own. :)

      — commented August 18th 2011 by Kosso
  • Hi Kosso,

    I am currently working on a Video Recording module, its not easy, but it will be cool and i think it will help a lot of people.

    About the audio recording. We are updating that module and offer support for recording raw audio and high bitrate audio, basically its being rebuilt from the ground app. We received a lot of suggestions among which the exact same thing that you are saying, "audio quality", so we are putting a lot of effort into delivering a high end module with high quality audio recordings.

    I will be glad to send you a pre-release version to test it out. I will DM you on twitter when i have something ready.

    Thank you.
    Alex

    — answered August 18th 2011 by Alexandru Budin
    permalink
    1 Comment
    • Cool. By the way, I have just committed my module and the demo app to use with intents to my Github. The video recorded with intents is actually very simple and perfect for most needs - especially as the user can choose the quality settings themselves in their settings.

      See the record_video.js in my My GitHub in the 'mediaDroid' demo app.

      High quality raw PCM is good, but the file sizes are then far too big to use for uploading. This is why I now got MediaRecorder to use the MPEG_4 and AAC settings (supported on Gingerbread). Much better than AMR_NB or AMR_WB. Now I can create AAC .m4a audio on both iPhone and Android, which is good for my server backend (where I also create mp3 and ogg versions to support HTML5 players)

      For my audio MediaRecorder settings, I'm using setAudioEncodingBitRate(64000) and setAudioSamplingRate(44100) which gives quite good results for a relatively small file size.

      http://developer.android.com/reference/android/media/MediaRecorder.OutputFormat.html

      — commented August 18th 2011 by Kosso
The ownership of individual contributions to this community generated content is retained by the authors of their contributions.
All trademarks remain the property of the respective owner.