Files
jims-blog/blogs/binding-the-cognitive-services-android-speech-sdk-part-3-java-8-fun/index.html
2023-01-21 22:30:31 +00:00

12 lines
18 KiB
HTML

<!doctype html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=x-ua-compatible content="ie=edge"><link rel=icon href=/fav.png type=image/png><link rel=preconnect href=https://fonts.googleapis.com><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=preload as=style href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"><link rel=stylesheet href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" media=print onload='this.media="all"'><noscript><link href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel=stylesheet></noscript><link rel=stylesheet href=/css/font.css media=all><meta property="og:title" content="Binding the Cognitive Services Android Speech SDK - Part 3 - Java 8 fun"><meta property="og:description" content="In the first part of this post, I showed how to get started binding the Microsoft Cognitive Services speech API. In the second part I showed how to make the code look more C#-like. In this part, I&rsquo;ll show how to use it and fix up a nasty issue with the Android compiler and using jars created with the latest versions of Java.
Using the SDK To use the SDK, you will need an Android app."><meta property="og:type" content="article"><meta property="og:url" content="https://jimbobbennett.dev/blogs/binding-the-cognitive-services-android-speech-sdk-part-3-java-8-fun/"><meta property="og:image" content="https://jimbobbennett.dev/blogs/binding-the-cognitive-services-android-speech-sdk-part-3-java-8-fun/banner.png"><meta property="article:section" content="blogs"><meta property="article:published_time" content="2018-09-10T11:22:55+00:00"><meta property="article:modified_time" content="2018-09-10T11:22:55+00:00"><meta property="og:site_name" content="JimBobBennett"><meta name=twitter:card content="summary_large_image"><meta name=twitter:image content="https://jimbobbennett.dev/blogs/binding-the-cognitive-services-android-speech-sdk-part-3-java-8-fun/banner.png"><meta name=twitter:title content="Binding the Cognitive Services Android Speech SDK - Part 3 - Java 8 fun"><meta name=twitter:description content="In the first part of this post, I showed how to get started binding the Microsoft Cognitive Services speech API. In the second part I showed how to make the code look more C#-like. In this part, I&rsquo;ll show how to use it and fix up a nasty issue with the Android compiler and using jars created with the latest versions of Java.
Using the SDK To use the SDK, you will need an Android app."><meta name=twitter:site content="@jimbobbennett"><meta name=twitter:creator content="@jimbobbennett"><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css integrity=sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3 crossorigin=anonymous><link rel=stylesheet href=/css/header.css media=all><link rel=stylesheet href=/css/footer.css media=all><link rel=stylesheet href=/css/theme.css media=all><link rel="shortcut icon" type=image/png href=/fav.png><link rel="shortcut icon" sizes=192x192 href=/fav.png><link rel=apple-touch-icon href=/fav.png><link rel=alternate type=application/rss+xml href=https://jimbobbennett.dev/index.xml title=JimBobBennett><script type=text/javascript>(function(e,t,n,s,o,i,a){e[n]=e[n]||function(){(e[n].q=e[n].q||[]).push(arguments)},i=t.createElement(s),i.async=1,i.src="https://www.clarity.ms/tag/"+o,a=t.getElementsByTagName(s)[0],a.parentNode.insertBefore(i,a)})(window,document,"clarity","script","dctc2ydykv")</script><style>:root{--text-color:#343a40;--text-secondary-color:#6c757d;--background-color:#000;--secondary-background-color:#64ffda1a;--primary-color:#007bff;--secondary-color:#f8f9fa;--text-color-dark:#e4e6eb;--text-secondary-color-dark:#b0b3b8;--background-color-dark:#000000;--secondary-background-color-dark:#212529;--primary-color-dark:#ffffff;--secondary-color-dark:#212529}body{background-color:#000;font-size:1rem;font-weight:400;line-height:1.5;text-align:left}</style><meta name=description content><link rel=stylesheet href=/css/index.css><link rel=stylesheet href=/css/single.css><link rel=stylesheet href=/css/projects.css media=all><script defer src=/fontawesome-5/all-5.15.4.js></script><title>Binding the Cognitive Services Android Speech SDK - Part 3 - Java 8 fun | JimBobBennett</title></head><body class=light onload=loading()><header><nav class="pt-3 navbar navbar-expand-lg"><div class="container-fluid mx-xs-2 mx-sm-5 mx-md-5 mx-lg-5"><a class="navbar-brand primary-font text-wrap" href=/><img src=/fav.png width=30 height=30 class="d-inline-block align-top">
JimBobBennett</a>
<button class=navbar-toggler type=button data-bs-toggle=collapse data-bs-target=#navbarContent aria-controls=navbarContent aria-expanded=false aria-label="Toggle navigation"><svg aria-hidden="true" height="24" viewBox="0 0 16 16" width="24" data-view-component="true"><path fill-rule="evenodd" d="M1 2.75A.75.75.0 011.75 2h12.5a.75.75.0 110 1.5H1.75A.75.75.0 011 2.75zm0 5A.75.75.0 011.75 7h12.5a.75.75.0 110 1.5H1.75A.75.75.0 011 7.75zM1.75 12a.75.75.0 100 1.5h12.5a.75.75.0 100-1.5H1.75z"/></svg></button><div class="collapse navbar-collapse text-wrap primary-font" id=navbarContent><ul class="navbar-nav ms-auto text-center"><li class="nav-item navbar-text"><a class=nav-link href=/ aria-label=home>Home</a></li><li class="nav-item navbar-text"><a class=nav-link href=/#about aria-label=about>About</a></li><li class="nav-item navbar-text"><a class=nav-link href=/#projects aria-label=projects>Recent Highlights</a></li><li class="nav-item navbar-text"><a class=nav-link href=/blogs title="Blog posts">Blog</a></li><li class="nav-item navbar-text"><a class=nav-link href=/videos title=Videos>Videos</a></li><li class="nav-item navbar-text"><a class=nav-link href=/livestreams title=Livestreams>Livestreams</a></li><li class="nav-item navbar-text"><a class=nav-link href=/conferences title=Conferences>Conferences</a></li><li class="nav-item navbar-text"><a class=nav-link href=/resume title=Resume>Resume</a></li></ul></div></div></nav></header><div id=content><section id=projects><div class="container pt-5" id=list-page><div class="row justify-content-center px-3 px-md-5"><h1 class="text-left pb-2 content">Binding the Cognitive Services Android Speech SDK - Part 3 - Java 8 fun</h1><div class="text-left content">Jim Bennett
<small>|</small>
Sep 10, 2018</div></div></div></section><section id=single><div class=container><div class="row justify-content-center"><div class="col-sm-12 col-md-12 col-lg-9"><div class=pr-lg-4><article class="page-content p-2"><p>In the <a href=/blogs/binding-the-cognitive-services-android-speech-sdk>first part</a> of this post, I showed how to get started binding the <a href="https://docs.microsoft.com/azure/cognitive-services/speech-service/?WT.mc_id=speech-blog-jabenn">Microsoft Cognitive Services speech API</a>. In the <a href=/blogs/binding-the-cognitive-services-android-speech-sdk-part-2-making-the-code-more-c-like>second part</a> I showed how to make the code look more C#-like. In this part, I&rsquo;ll show how to use it and fix up a nasty issue with the Android compiler and using jars created with the latest versions of Java.</p><h2 id=using-the-sdk>Using the SDK</h2><p>To use the SDK, you will need an Android app. Create a new single-view Android app, and reference the SDK binding project. Then build the app and try to run it.</p><p>Then marvel, as your app spectacularly fails to compile with a really weird error message.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-sh data-lang=sh><span style=display:flex><span>COMPILETODALVIK : Uncaught translation error : com.android.dx.cf.code.SimException: invalid opcode ba <span style=color:#f92672>(</span>invokedynamic requires --min-sdk-version &gt;<span style=color:#f92672>=</span> 26<span style=color:#f92672>)</span>
</span></span></code></pre></div><p>WooHoo, invalid opcode ba. Ba indeed! What is this gibberish?</p><p>Well the issue comes down to Java versions. Android in the past only supported Java code up to version 7. They are now adding support for later versions but Xamarin doesn&rsquo;t have this yet, and this is only available on newer versions of Android (>= 26). To make your code work on earlier versions and with Xamarin you have to do a thing called desugaring (yes, really), and this alters the Java bytecode to convert Java 8 bytecode to a version that is supported by Java 7.</p><p>At the moment there isn&rsquo;t a nice IDE way to turn on desugaring, instead it has to be set inside the <code>.csproj</code> file of the client application. Open up the <code>.csproj</code> file for your newly created Android app inside <a href="https://code.visualstudio.com/?WT.mc_id=speech-blog-jabenn">VSCode</a> (other editors are available, but hey - why would you), or by editing the file inside Visual Studio, and add the following to the default <code>PropertyGroup</code>:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#f92672>&lt;AndroidEnableDesugar&gt;</span>true<span style=color:#f92672>&lt;/AndroidEnableDesugar&gt;</span>
</span></span></code></pre></div><p>Your app should now build without errors!</p><blockquote><p>I have this working and compiling in the preview versions of Visual Studio on Windows at the time of writing cos that&rsquo;s how I roll. If you are on stable and get weird errors then try with preview as I know support for this is being actively worked on.</p></blockquote><blockquote><p>If you do this on VS for Mac then you will get a crash at run-time. The workaround is documented here: <a href=https://github.com/xamarin/xamarin-android/pull/1973>https://github.com/xamarin/xamarin-android/pull/1973</a></p></blockquote><h2 id=buiding-an-app-using-the-sdk>Buiding an app using the SDK</h2><p>To use the SDK you do need to sign up for the Speech service in Azure. Head to <a href="https://portal.azure.com/?WT.mc_id=speech-blog-jabenn">portal.azure.com</a> and add a new Speech resource (at the time of writing this is in preview).</p><div class=image-div style=max-width:600px><p><img src=2018-09-09_20-43-15.png alt="Searching for the speech resource in Azure"></p></div><p>Once you have this, note down the endpoint from the <strong>Overview</strong> page. It will be a URL, and you will need the bit before <code>.api.cognitive.microsoft.com</code>. For example, if your endpoint is <code>https://northeurope.api.cognitive.microsoft.com/sts/v1.0</code>, then you will need <code>northeurope</code>. You will also need one of the two keys from the <strong>Keys</strong> page.</p><p>You can then create a <code>SpeechFactory</code> using these values:</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-cs data-lang=cs><span style=display:flex><span><span style=color:#66d9ef>var</span> factory = SpeechFactory.FromSubscription(&lt;SpeechApiKey&gt;, &lt;endpoint&gt;);
</span></span></code></pre></div><p>Once you have a speech factory, you can create different recognizers - simple speech, a translator, or an intent recognizer using <a href="https://www.luis.ai/?WT.mc_id=speech-blog-jabenn">LUIS</a>. To detect speech, handle the relevant events. You can see an example of using the <code>TranslationRecognizer</code> to convert English to spoken German in an example project in my <a href=https://github.com/jimbobbennett/SpeechSdkXamarinSample/blob/master/SpeechQuickStart/MainActivity.cs>GitHub repo</a>.</p><blockquote class=twitter-tweet data-lang=en><p lang=en dir=ltr>Had a successful day. Created a <a href="https://twitter.com/hashtag/Xamarin?src=hash&ref_src=twsrc%5Etfw">#Xamarin</a> binding for the <a href="https://twitter.com/Azure?ref_src=twsrc%5Etfw">@Azure</a> <a href="https://twitter.com/hashtag/CognitiveServices?src=hash&ref_src=twsrc%5Etfw">#CognitiveServices</a> Android speech SDK, and built a sample app that translates me voice into spoken German. <a href=https://t.co/Bg4XDvhBjv>pic.twitter.com/Bg4XDvhBjv</a></p>&mdash; Jim Bennett ☁️ (@jimbobbennett) <a href="https://twitter.com/jimbobbennett/status/1035559022743760896?ref_src=twsrc%5Etfw">August 31, 2018</a></blockquote><script async src=https://platform.twitter.com/widgets.js></script><hr><p>In these three posts you have seen how to <a href=/blogs/binding-the-cognitive-services-android-speech-sdk>create a binding library for the Speech SDK <code>aar</code></a>, make the code <a href=/blogs/binding-the-cognitive-services-android-speech-sdk-part-2-making-the-code-more-c-like>more C#-like</a>, then finally use it from a client app, working around a Java bytecode issue. You can check out my implementation and a sample at on <a href=https://github.com/jimbobbennett/SpeechSdkXamarinSample>GitHub</a>. As always, the best source of information with much more depth is the <a href="https://docs.microsoft.com/xamarin/android/platform/binding-java-library/?WT.mc_id=speech-blog-jabenn">java binding dos on docs.microsoft.com</a>.</p><p>Let me know what you build with this SDK - my DMs are always open on <a href=https://twitter.com/jimbobbennett>Twitter</a>.</p></article></div></div><div class="col-sm-12 col-md-12 col-lg-3"><div class=sticky-sidebar><aside class=toc><h5>Table Of Contents</h5><div class=toc-content><nav id=TableOfContents><ul><li><a href=#using-the-sdk>Using the SDK</a></li><li><a href=#buiding-an-app-using-the-sdk>Buiding an app using the SDK</a></li></ul></nav></div></aside><aside class=tags><h5>Tags</h5><ul class="tags-ul list-unstyled list-inline"><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/xamarin target=_blank>xamarin</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/technology target=_blank>Technology</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/xamarin.android target=_blank>xamarin.android</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/java target=_blank>java</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/binding target=_blank>binding</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/aar target=_blank>aar</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/jar target=_blank>jar</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/compiletodalvik target=_blank>COMPILETODALVIK</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/invalid-opcode-ba target=_blank>invalid opcode ba</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/invokedynamic target=_blank>invokedynamic</a></li></ul></aside></div></div></div><div class=row><div class="col-sm-12 col-md-12 col-lg-9 p-4"><div id=disqus_thread></div><script>var disqus_config=function(){this.page.url="https://jimbobbennett.dev/blogs/binding-the-cognitive-services-android-speech-sdk-part-3-java-8-fun/",this.page.identifier="bda4f678cddac375d519676475949e65"};(function(){if(window.location.hostname=="localhost")return;var e=document,t=e.createElement("script");t.src="https://jimbobbennett.disqus.com/embed.js",t.setAttribute("data-timestamp",+new Date),(e.head||e.body).appendChild(t)})()</script><noscript>Please enable JavaScript to view the <a href=https://disqus.com/?ref_noscript>comments powered by Disqus.</a></noscript></div></div></div><button class="p-2 px-3" onclick=topFunction() id=topScroll>
<i class="fas fa-angle-up"></i></button></section><script>var topScroll=document.getElementById("topScroll");window.onscroll=function(){scrollFunction()};function scrollFunction(){document.body.scrollTop>20||document.documentElement.scrollTop>20?topScroll.style.display="block":topScroll.style.display="none"}function topFunction(){document.body.scrollTop=0,document.documentElement.scrollTop=0}</script></div><footer><div class="container py-4"><div class="row justify-content-center"><div class="col-md-4 text-center">&copy; 2023 All Rights Reserved</div></div></div></div></footer><script src=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js integrity=sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13 crossorigin=anonymous></script>
<script>document.body.className.includes("light")&&(document.body.classList.add("dark"),localStorage.setItem("pref-theme","dark"))</script><script>let loadingIcons;function loading(){myVar=setTimeout(showPage,100)}function showPage(){try{document.getElementById("loading-icons").style.display="block"}catch{}}</script><script>function createCopyButton(e,t){const n=document.createElement("button");n.className="copy-code-button",n.type="button",n.innerText="Copy",n.addEventListener("click",()=>copyCodeToClipboard(n,e,t)),addCopyButtonToDom(n,e)}async function copyCodeToClipboard(e,t,n){const s=t.querySelector("pre > code").innerText;try{n.writeText(s)}finally{codeWasCopied(e)}}function codeWasCopied(e){e.blur(),e.innerText="Copied!",setTimeout(function(){e.innerText="Copy"},2e3)}function addCopyButtonToDom(e,t){t.insertBefore(e,t.firstChild);const n=document.createElement("div");n.className="highlight-wrapper",t.parentNode.insertBefore(n,t),n.appendChild(t)}if(navigator&&navigator.clipboard)document.querySelectorAll(".highlight").forEach(e=>createCopyButton(e,navigator.clipboard));else{var script=document.createElement("script");script.src="https://cdnjs.cloudflare.com/ajax/libs/clipboard-polyfill/2.7.0/clipboard-polyfill.promise.js",script.integrity="sha256-waClS2re9NUbXRsryKoof+F9qc1gjjIhc2eT7ZbIv94=",script.crossOrigin="anonymous",script.onload=function(){addCopyButtons(clipboard)},document.querySelectorAll(".highlight").forEach(e=>createCopyButton(e,script)),document.body.appendChild(script)}</script></body></html>