<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Android Studio - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Android Studio - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 28 Jul 2026 22:40:24 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/android-studio/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Handle UI Events in Jetpack Compose ]]>
                </title>
                <description>
                    <![CDATA[ In this short and practical article, we will talk about how to handle UI events in Jetpack Compose. In the old system, we used OnClickListeners and other interfaces. In Compose, we can take full advantage of Kotlin’s Sealed Classes, Function Types an... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-handle-ui-events-in-jetpack-compose/</link>
                <guid isPermaLink="false">66d460c99f2bec37e2da066a</guid>
                
                    <category>
                        <![CDATA[ Android ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Android Studio ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jetpack Compose ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kotlin ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ User Interface ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ryan Michael Kay ]]>
                </dc:creator>
                <pubDate>Tue, 16 Mar 2021 18:22:24 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/03/cat-4793068_1280-5.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this short and practical article, we will talk about how to handle UI events in Jetpack Compose.</p>
<p>In the old system, we used OnClickListeners and other interfaces. In Compose, we can take full advantage of Kotlin’s <strong>Sealed Classes</strong>, <strong>Function Types</strong> and <strong>Lambda Expressions</strong>.</p>
<p>If you do not know what a composable is, consider reading <a target="_blank" href="https://www.freecodecamp.org/news/jetpack-compose-beginner-tutorial-composables-recomposition/">this article which explains the fundamentals</a>.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/LrNPw1LQHEw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h2 id="heading-how-to-model-ui-events-with-a-sealed-class">How to Model UI Events with a Sealed Class</h2>
<p>First, we must learn what is meant by UI Events and how to model them with Sealed Classes.</p>
<p>I have described this same process for <a target="_blank" href="https://medium.com/swlh/simplify-your-ui-interactions-with-events-java-kotlin-any-language-5062c1b1e0e4">Java and Kotlin</a> (with the old view system) before, so I will keep this brief.</p>
<h3 id="heading-the-process">The Process</h3>
<p>For each screen or sub-screen of your UI, ask yourself this question: What are all the different ways which the user can interact with it?</p>
<p>Let's take an example from my first app built fully in compose, <a target="_blank" href="https://play.google.com/store/apps/details?id=com.bracketcove.graphsudoku">Graph Sudoku</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/graph_sudoku_small_screen.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Screenshot of a Sudoku Android App</em></p>
<p>The sealed class I use to represent the UI interactions of this screen looks like this:</p>
<pre><code class="lang-kotlin"><span class="hljs-keyword">sealed</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ActiveGameEvent</span> </span>{
    <span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OnInput</span></span>(<span class="hljs-keyword">val</span> input: <span class="hljs-built_in">Int</span>) : ActiveGameEvent()
    <span class="hljs-keyword">data</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OnTileFocused</span></span>(<span class="hljs-keyword">val</span> x: <span class="hljs-built_in">Int</span>, 
    <span class="hljs-keyword">val</span> y: <span class="hljs-built_in">Int</span>) : ActiveGameEvent()
    <span class="hljs-keyword">object</span> OnNewGameClicked : ActiveGameEvent()
    <span class="hljs-keyword">object</span> OnStart : ActiveGameEvent()
    <span class="hljs-keyword">object</span> OnStop : ActiveGameEvent()
}
</code></pre>
<p>To explain briefly:</p>
<ul>
<li><p>OnInput represents a user touching an input button (like 0, 1, 2, 3, 4)</p>
</li>
<li><p>OnTileFocused represents a user selecting a tile (like the amber highlighted one)</p>
</li>
<li><p>OnNewGameClicked is self-explanatory</p>
</li>
<li><p>OnStart and OnStop are lifecycle events which my composables do not care about, but they are used in the Activity which acts as a Container for the composables</p>
</li>
</ul>
<p>Once you have your sealed class set up, you can now handle a wide variety of events using a single event handler function. Sometimes it might make more sense to have multiple event handler functions, so keep in mind that <strong>this approach must be adapted to your project's specific requirements</strong>.</p>
<h2 id="heading-how-to-connect-your-software-architecture">How to Connect Your Software Architecture</h2>
<p>What you have handling these events is totally up to you. Some people think that MVVM is the golden standard of software architectures, but it seems like more and more people are realizing that <strong>there is no single architecture which works best for every situation</strong>.</p>
<p>For Android with Compose, my current approach is to use a very 3rd party minimalist approach which typically has these things in each feature (screen):</p>
<ul>
<li><p>A (Presentation) Logic class <strong>as an event handler</strong></p>
</li>
<li><p>A ViewModel to store the data necessary to render the View (as the name implies)</p>
</li>
<li><p>An Activity which acts as a Container (not a god object)</p>
</li>
<li><p>Composables to form the View</p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/03/model_view_whatever-3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Model-View-Whatever</em></p>
<p>I do not care what you use as long as you are applying <a target="_blank" href="https://youtu.be/B_C41SF0KbI">separation of concerns</a>. This is how I arrived at this architecture, by simply asking what should and should not be put together in the same class.</p>
<p>Whether you want your ViewModel, a Fragment, or an Activity to be your event handler, all of them can be set up the same way: <strong>Function Types!</strong></p>
<p>Within your class of choice, set up an event handler function which accepts your sealed class as its argument:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ActiveGameLogic</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> container: ActiveGameContainer?,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> viewModel: ActiveGameViewModel,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> gameRepo: IGameRepository,
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> statsRepo: IStatisticsRepository,
    dispatcher: DispatcherProvider
) : BaseLogic&lt;ActiveGameEvent&gt;(dispatcher),
    CoroutineScope {
    <span class="hljs-comment">//...</span>
    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onEvent</span><span class="hljs-params">(event: <span class="hljs-type">ActiveGameEvent</span>)</span></span> {
        <span class="hljs-keyword">when</span> (event) {
            <span class="hljs-keyword">is</span> ActiveGameEvent.OnInput -&gt; onInput(
                event.input,
                viewModel.timerState
            )
            ActiveGameEvent.OnNewGameClicked -&gt; onNewGameClicked()
            ActiveGameEvent.OnStart -&gt; onStart()
            ActiveGameEvent.OnStop -&gt; onStop()
            <span class="hljs-keyword">is</span> ActiveGameEvent.OnTileFocused -&gt; onTileFocused(event.x, event.y)
        }
    }
    <span class="hljs-comment">//...</span>
}
</code></pre>
<p>This approach is very organized and makes it easy to test every Unit in this 3rd party library free class through a single entry point.</p>
<p>However, we are not done yet. Naturally, we need a way to get a reference to this event handler function, <code>onEvent</code>, to our Composables. We can do this using a <strong>function reference</strong>:</p>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ActiveGameActivity</span> : <span class="hljs-type">AppCompatActivity</span></span>(), ActiveGameContainer {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">lateinit</span> <span class="hljs-keyword">var</span> logic: ActiveGameLogic

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">onCreate</span><span class="hljs-params">(savedInstanceState: <span class="hljs-type">Bundle</span>?)</span></span> {
        <span class="hljs-keyword">super</span>.onCreate(savedInstanceState)

        <span class="hljs-keyword">val</span> viewModel = ActiveGameViewModel()

        setContent {
            ActiveGameScreen(
                onEventHandler = logic::onEvent,
                viewModel
            )
        }

        logic = buildActiveGameLogic(<span class="hljs-keyword">this</span>, viewModel, applicationContext)
    }

      <span class="hljs-comment">//...</span>
}
</code></pre>
<p>I am sure some of you are wondering why I am using an Activity. You can ask me during a <a target="_blank" href="https://youtu.be/-xV8k-4UW50">livestream Q&amp;A sometime for a detailed answer</a>.</p>
<p>In short, Fragments appear to be a bit pointless with Compose with my approach to architecture (I do not use Jetpack Navigation), and there is nothing wrong with using Activities as a feature specific container. <strong>Just avoid writing god activities, basically.</strong></p>
<p>To be specific, the way you make a reference to a function in Kotlin, is by providing the <strong>class/interface name</strong> (or <strong>skip that if it is a Top-Level function</strong>), followed by <strong>two colons</strong>, and the <strong>name of the function without any arguments or brackets</strong>:</p>
<pre><code class="lang-pgsql">onEventHandler = logic::onEvent
</code></pre>
<h2 id="heading-how-to-replace-onclicklistener-with-jetpack-compose-onclick-modifier">How to Replace onClickListener With Jetpack Compose onClick Modifier</h2>
<p>With that stuff ready, we can look at how this works within the composable. Naturally, your root composable will need the event handler function as a parameter:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">ActiveGameScreen</span><span class="hljs-params">(
    onEventHandler: (<span class="hljs-type">ActiveGameEvent</span>) -&gt; <span class="hljs-type">Unit</span>,
    viewModel: <span class="hljs-type">ActiveGameViewModel</span>
)</span></span> {
<span class="hljs-comment">//...</span>
}
</code></pre>
<p>It can be a bit tricky to get function type syntax correctly, but understand that this <strong>really is a reference to a function,</strong> which is not so different from a reference to a class.</p>
<p>Just as you should not build god objects, you should not build giant composables:</p>
<ol>
<li><p>Break your UI down into the <strong>smallest reasonable parts</strong></p>
</li>
<li><p>Wrap them in a composable function</p>
</li>
<li><p>For each composable which has a UI interaction associated with it, <strong>it must be given a reference to your event handler function</strong></p>
</li>
</ol>
<p>Here is a composable which represents the input buttons of the Sudoku app, which is given the event handler by reference:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">SudokuInputButton</span><span class="hljs-params">(
    onEventHandler: (<span class="hljs-type">ActiveGameEvent</span>) -&gt; <span class="hljs-type">Unit</span>,
    number: <span class="hljs-type">Int</span>
)</span></span> {
    Button(
        onClick = { onEventHandler.invoke(ActiveGameEvent.OnInput(number)) },
        modifier = Modifier
            .requiredSize(<span class="hljs-number">56</span>.dp)
            .padding(<span class="hljs-number">2</span>.dp)
    ) {
        Text(
            text = number.toString(),
            style = inputButton.copy(color = MaterialTheme.colors.onPrimary),
            modifier = Modifier.fillMaxSize()
        )
    }
}
</code></pre>
<p>To actually pass the event to the logic class, we must use the <code>invoke</code> function, which will accept arguments as per the function type definition (which accepts an <code>ActiveGameEvent</code> in this case).</p>
<p>At this point, you are ready to handle UI interaction events in Kotlin (compose or not) by taking full advantage of this beautiful and modern programming language.</p>
<p>If you liked this article, share it on social media and consider checking out the resources below to support an independent programmer and content creator.</p>
<h3 id="heading-social">Social</h3>
<p>You can find me on <a target="_blank" href="https://www.instagram.com/rkay301/">Instagram here</a> and on <a target="_blank" href="https://twitter.com/wiseAss301">Twitter here</a>.</p>
<h3 id="heading-here-are-some-of-my-tutorials-amp-courses">Here are some of my tutorials &amp; courses</h3>
<p><a target="_blank" href="https://www.youtube.com/channel/UCSwuCetC3YlO1Y7bqVW5GHg">https://youtube.com/wiseass</a> <a target="_blank" href="https://www.freecodecamp.org/news/author/ryan-michael-kay/">https://www.freecodecamp.org/news/author/ryan-michael-kay/</a> <a target="_blank" href="https://skl.sh/35IdKsj">https://skl.sh/35IdKsj</a> (introduction to Android with Android Studio)</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ ADB Android Install Guide: Drivers and Commands ]]>
                </title>
                <description>
                    <![CDATA[ In this article, we will explore how you can use the ADB to gain some fine-grained control when you're installing, testing, diagnosing, and managing one or more devices and emulators. For my first few years as a software developer, primarily working ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/adb-android-install-guide-drivers-and-commands/</link>
                <guid isPermaLink="false">66d460c5a326133d12440a5b</guid>
                
                    <category>
                        <![CDATA[ Android ]]>
                    </category>
                
                    <category>
                        <![CDATA[ android app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Android Studio ]]>
                    </category>
                
                    <category>
                        <![CDATA[ command line ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ryan Michael Kay ]]>
                </dc:creator>
                <pubDate>Thu, 18 Feb 2021 16:48:06 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/60297d780a2838549dcc57f3.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, we will explore how you can use the ADB to gain some fine-grained control when you're installing, testing, diagnosing, and managing one or more devices and emulators.</p>
<p>For my first few years as a software developer, primarily working with the Android SDK, I had no idea of what the Android Debug Bridge (ADB/adb) was, what it did, or when to use it.</p>
<p>Amusingly, it was not some professional goal which motivated me to learn about it initially. Rather it was my boot looping Nexus 6 which I desperately wanted to resurrect. For a problem like that, Android Studio and Gradle are about as useful as a waterproof tea bag.</p>
<p>I would also like to mention that this article has been written with <strong>two kinds of individuals in mind</strong>:</p>
<ul>
<li><p>Those who are familiar with CLI, Shell, Processes, and the Client-Server Model</p>
</li>
<li><p>Those who are not familiar with CLI, Shell, Processes, and the Client-Server Model</p>
</li>
</ul>
<p>For those in the first category, you may wish to skip the section titled: "<strong>How to Work With The ADB</strong>."</p>
<p>For those in the second category, I will assume you were like me as a Junior developer and know very little about CLIs, Shells, and the ADB. The first section is a soft introduction and glossary for some basic terms and ideas, explained in the simplest way I can manage.</p>
<h2 id="heading-preliminaries">Preliminaries</h2>
<p>Here, we will learn about some topics which are important if you want to understand how the ADB works and is used.</p>
<p>Some of you may have been scared away from learning command line tools in the past by sneering Vim enthusiasts or judgmental Unix System Administrators. As you will see, I freely admit that CLI is not ideal for how my brain works, so I think you might enjoy my take on the subject.</p>
<h3 id="heading-command-line">Command Line</h3>
<p>Simply put, a command line is an interface (way of sending/receiving information) to a computer which <strong>only uses lines of text</strong>.</p>
<p>It is important to understand that a command line interface (CLI) is not itself a program, but rather some programs will provide a CLI (and perhaps other interfaces such as a GUI as well).</p>
<p>At some point, you may have typed something into Windows Command Prompt (or MS-DOS if you are a 90s kid like me), Mac Terminal, or something like GNOME Terminal common on many Linux distributions. All of these are primarily used via a CLI.</p>
<p>The benefits and deficits of using a CLI depend largely on the individual using it, and what kind of problem they are trying to solve. <strong>I personally do not like using a CLI unless it is for something that I do almost every day</strong>.</p>
<p>My brain is simply not suited for memorizing obscure shorthand text commands (I had trouble learning to read as a kid for the same reason), so I must rely on a great deal of repetition-based implicit memory (muscle memory) and cheat sheets.</p>
<p>For those who are willing to put the time in even if it is a struggle (like I do), or those who are really quite good at remembering such things, <strong>you will likely learn to appreciate how much more efficient you can be within a CLI versus a GUI</strong>.</p>
<p>Many operations can be carried out in a fraction of the time it takes to point and click your way through various menus and screens. It is also possible to write scripts, which are files containing a series of text commands, that can increase your efficiency even further.</p>
<h3 id="heading-how-to-use-the-abd-shell">How to use the ABD Shell</h3>
<p>I will have to assume that you are familiar with the term Operating System (OS), which includes Android, iOS, Windows, Mac, Linux, and any other Unix-like system.</p>
<p>Why is this term relevant to the ADB? To give an explanation which prioritizes clarity over precision, the Android OS is based on Linux, and Linux is based on Unix.</p>
<p>As a result of this, we can use the ADB to get a hold of the Unix Shell for the device or emulator we are working with. This allows us a great deal of flexibility, capabilities, and control over the device or emulator by directly interacting with its shell.</p>
<p>A shell is a general term for the program which you use to interact with an OS. Just as a turtle shell provides protection and access to a turtle (and is the outermost layer), the shell of an OS both protects and provides access to the inner workings of the OS. Personally, I was quite surprised to learn that "Shell" was not some esoteric acronym.</p>
<p>Do not feel the need to overthink this term. If you are reading this on a computer of some kind, you used a shell to help you get here.</p>
<p>A shell can provide either or both a CLI or GUI. In either case you will use it to create/update/delete/move files, start other programs, and access the various services of the OS which are made available through the shell.</p>
<h3 id="heading-how-to-use-the-abd-client-and-abd-server">How to use the ABD Client and ABD Server</h3>
<p>Again, let us start with a slightly imprecise explanation which is hopefully easier to understand. I will correct this definition shortly, though.</p>
<p>Clients and Servers are both computers. The reason why we differentiate them in this way is based on their <strong>role</strong>. For example, your computer (whether it is a desktop, laptop, phone, or whatever else) is a Client of a freeCodeCamp Server, which <strong>serves</strong> you this HTML page.</p>
<p>In general, a client is <strong>something which uses something else</strong>, whereas a server is <strong>that which is being used</strong>. Do not overthink this term, as a Client-Server Model can describe a very large number of things both inside and outside of computing.</p>
<p>Now, when I said that Clients and Servers are both “computers”, that is not really true in the context that we will use these terms later on.</p>
<p>As programmers and engineers, we typically ought to think of Clients and Servers as being processes (<strong>a process is simply a running program</strong>).</p>
<p>This means that while a Client process and a Server process often do run on separate computers, it is also fine if they run on the same computer.</p>
<p>They will occupy distinct locations in the memory space of said computer, so effectively the only difference is that they will communicate using IPC (inter-process communication) as opposed to sending messages to each other through a network connection.</p>
<p>As we will see shortly, the ADB makes use of a Server process, which allows multiple developers (multiple clients) to manage multiple Android devices and/or emulators.</p>
<p>In an enterprise setting, this Server process would likely sit on a remote (communicated to through a network connection) computer, but we will set up a Server which is local to our Client. Doing that will be much simpler than you probably think it will be.</p>
<h3 id="heading-what-is-an-abd-daemon">What is an ABD Daemon?</h3>
<p>In case you skipped ahead, I already explained that a process is simply a running program. A Daemon is a process which runs in the background, which is to say that the user does not directly interact with it.</p>
<p>For example, if you open a web browser, then chances are that the actual work of managing the network connections required to connect to the Internet will be carried out by something like a NetworkManager Daemon (as opposed to the browser process itself).</p>
<p>Each Android device (physical or emulated), assuming it is configured properly, will have an ADB Daemon (adbd) which executes commands given to it by a Server process.</p>
<p>In short, when our Client issues a command to the Server, the Server will forward that command to the ADBD, which will execute it on the device.</p>
<h2 id="heading-how-to-use-adb-for-android-development">How to Use ADB for Android Development</h2>
<p>For the remainder of this article, we will explore the following topics:</p>
<ul>
<li><p>Drivers and configuration necessary to use the ADB on your system</p>
</li>
<li><p>Using the ADB with physical devices and emulators</p>
</li>
<li><p>Basic commands using the ADB’s CLI</p>
</li>
<li><p>A glance at more complicated usage using an Android device’s Shell via the ADB</p>
</li>
</ul>
<p>Before proceeding, you will want to establish what CLI tool you will be using to interact with the ADB. On Windows, I prefer using PowerShell, but Command Prompt would work too. For Linux and Mac, the default Terminal should work.</p>
<p>Feel free to use whatever gets the job done.</p>
<p>This article contains a very detailed explanation of the whole process, but I have prepared a video tutorial which covers it succintly here:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/g___gGA9jn8" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h3 id="heading-how-to-understand-the-cli-examples">How To Understand The CLI Examples</h3>
<p>This article contains many commands to be inputted to your preferred CLI tool. Any part of a given command which changes situationally will be written within angle brackets.</p>
<p><strong>Do not include the angle brackets in the CLI command you write.</strong></p>
<p>For example, if I wrote...:</p>
<p><code>adb pair &lt;ip-address&gt;:&lt;port&gt;</code></p>
<p>...you would substitute the angle brackets and name for the actual value, such as:</p>
<p><code>adb pair 192.168.0.1:5554</code></p>
<h3 id="heading-abd-drivers-amp-configuration">ABD Drivers &amp; Configuration</h3>
<p>Firstly, ensure that you have the latest (or at least a recent) version of the <a target="_blank" href="https://developer.android.com/studio/releases/platform-tools">Android SDK Platform-Tools</a>. If for some reason you do not use Android Studio (AS), click that link and download the standalone package for your respective OS.</p>
<p>If you have Android Studio, you can download or update this package using the SDK Manager.</p>
<p>There is typically a toolbar icon in AS to open the SDK Manager, but they like to change what it looks like practically every hotfix.</p>
<p>If you do not have luck finding it, go to <strong>File -&gt; Settings</strong> and in the search bar, type “SDK”, and search for the “Android SDK” menu item.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/as_sdk_manager.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Systems setting showing that Android SDK Platform Tools are installed</em></p>
<p>The next step changes depending on a number of variables. As discussed in the <strong>Preliminaries</strong> section, the ADB uses a Client-Server Model which allows a lot of flexibility in how you use the tool.</p>
<p>To be more specific, you may have:</p>
<ul>
<li><p>Multiple Clients interacting with a remote Server</p>
</li>
<li><p>A Server which is local (same computer) to one Client</p>
</li>
<li><p>A variety of physical devices and emulators hooked up to the same server</p>
</li>
</ul>
<p>Advanced configuration with multiple Clients and an exceedingly large number of devices is possible with the ADB, but outside of the scope of this article.</p>
<p>One Server can manage up to 16 emulators and as many physical devices as you would like (within reason), without requiring advanced configuration.</p>
<p>For the remainder of this article, the most we will work with is one physical device and one emulator for a single ADB server process.</p>
<h4 id="heading-how-to-configure-an-abd-emulator">How to Configure An ABD Emulator</h4>
<p>Most likely you do not need to make any further configurations, but it is possible you may need to enable <strong>Developer Options</strong> on your emulator. You will know very shortly if it is working properly when we get to our first few ADB commands.</p>
<p>If you do wish to enable this feature on your emulator, you will need to <a target="_blank" href="https://developer.android.com/studio/debug/dev-options">research</a> how to do that for your particular version of Android.</p>
<h3 id="heading-usb-debugging-how-to-configure-a-physical-device">USB Debugging – How to Configure a Physical Device</h3>
<p>If you are not planning to use a physical Android device, you can skip this section. However, it is worth noting that you may still need to enable Developer Options</p>
<p>In order to proceed, you will need to configure either USB Debugging or WiFi Debugging on your Android device and development machine.</p>
<p>In either case, start by enabling <strong>Developer Options</strong> on your device. You will need to <a target="_blank" href="https://developer.android.com/studio/debug/dev-options">research</a> how to do that for your particular version of Android.</p>
<h4 id="heading-usb-debugging">USB Debugging</h4>
<p>Ensure that you have enabled USB Debugging on the Android device via Developer Options. The link I shared above will describe that process, which tends to change somewhat across different versions of the Android OS.</p>
<p>Before proceeding, Windows users will need to <a target="_blank" href="https://developer.android.com/studio/run/oem-usb">download a USB Driver</a>. Ubuntu users also <a target="_blank" href="https://developer.android.com/studio/run/device">require some extra steps</a>. For Mac and Chrome OS, you should be good to go.</p>
<p>Once USB Debugging is enabled via Developer Options, connect your Android device via a USB cable.</p>
<h4 id="heading-wifi-debugging">WiFi Debugging</h4>
<p>If you happen to have multiple physical devices or a shortage of USB cables, then you may want to opt for WiFi Debugging.</p>
<p>Again, visit Developer Options on your Android device and enable Wireless debugging. It should prompt you about Allowing debugging on the network which the device is currently connected to, which you should allow (assuming that is the appropriate network).</p>
<p><strong>Time to start working with your CLI</strong>. First, you will need to locate the platform-tools directory (or folder – same thing) within your Android SDK installation directory.</p>
<p>Assuming you have Android Studio installed, a quick way to locate it via the app is to again go to File -&gt; Settings, then type “SDK” in the search bar. The “Android SDK” menu will show you where your SDK is installed, which will be the directory that should contain platform-tools.</p>
<p>In the example below, <strong>I copied the path to my Android SDK directory</strong>, and then opened an instance of Windows PowerShell. I then typed the following commands:</p>
<p><strong>Change Directory:</strong></p>
<pre><code class="lang-pgsql">cd &lt;<span class="hljs-type">path</span>-<span class="hljs-keyword">to</span>-SDK-directory&gt;
</code></pre>
<p><strong>List Files and Directories:</strong></p>
<pre><code class="lang-pgsql">ls
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/power_shell_cd_ls.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, I typed <code>cd platform-tools</code> to navigate to that directory. Note that the following steps assume you are using a device which is running Android OS 11 or higher.</p>
<p>If you are working with a device running Android 10 or lower, detailed instructions for that situation can be <a target="_blank" href="https://developer.android.com/studio/command-line/adb#wireless">found here</a>.</p>
<p>Once you are within the platform-tools directory, you are ready to pair an Android device to a development machine using the following steps:</p>
<ol>
<li><p>Within the Wireless debugging submenu in Settings -&gt; System -&gt; Developer options, select <strong>Pair device with pairing code</strong>.</p>
</li>
<li><p>Within your CLI tool which should be set to the platform-tools directory, enter the following command:</p>
</li>
</ol>
<p><code>adb pair &lt;IP address&gt;:&lt;Port&gt;</code></p>
<p>where both the IP address and the Port come from the dialogue on your Android device which popped up after selecting <strong>Pair device with pairing code</strong> (do not include the angle brackets).</p>
<p><strong>Note: You may need to prepend your call to adb with some other symbols or commands depending on which CLI tool you are using, your OS, and your access controls.</strong> For example, I had to type .\adb pair : using PowerShell on Windows.</p>
<ol start="3">
<li><p>Assuming things went well with your CLI, you will be prompted to enter the pairing code which was made visible in the same dialog on the Android device which gave you the IP address and Port number.</p>
</li>
<li><p>After entering the pairing code, you will know this operation was successful if you receive a message stating:</p>
</li>
</ol>
<p><code>Successfully paired to &lt;IP Address&gt;:&lt;Port&gt; [guid=&lt;Some GUID&gt;]</code></p>
<ol start="5">
<li>If you are using Windows or Linux, you will also need to run the following command using the IP Address &amp; Port which is visible from within the Wireless debugging preferences menu (not the dialogue which pops up after selecting Pair device with pairing code):</li>
</ol>
<p><code>adb connect &lt;IP Address&gt;:&lt;Port&gt;</code></p>
<p>after which you should receive a notification on the phone to indicate that you are connected.</p>
<h3 id="heading-how-to-use-the-adb-commands">How to Use The ADB: Commands</h3>
<p>Assuming you managed to properly configure your Android device and your development machine, you can now use the ADB tool.</p>
<p>Before proceeding, navigate to the directory which contains adb using a CLI tool (unless you just followed the steps in the previous section for setting up WiFi debugging).</p>
<p>Otherwise do so now, or check out that section for instructions on how to locate that folder.</p>
<h4 id="heading-how-to-see-which-devices-are-currently-connected-to-the-server">How to See Which Devices Are Currently Connected To The Server</h4>
<p>You can now start up an adb server by calling just about any command on the ADB except <code>adb kill-server</code>. Whether or not your server process is running, type in the following command:</p>
<p><code>adb devices</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/pwershell_devices-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the above screenshot, I first called <code>adb devices</code> when my Android phone was connected to the server. After killing the server via the <code>adb kill-server</code> command, I once again called devices which restarted the server.</p>
<p>Again, if an ADB server is not currently running, <strong>calling more or less any ADB command will start the server back up</strong> (except <code>adb kill-server</code>, of course). There is an explicit <code>adb start-server</code> command, but in practice I have never needed to use it.</p>
<p>Since the server was reset, devices did not return any items. Therefore, before moving to the next example I had to once again use the <code>adb pair</code> and <code>adb connect</code> (if on Windows or Linux) commands described in the previous section.</p>
<p>I have now fired up an emulator using PowerShell and the emulator program which is also located in a subdirectory of platform-tools called "emulator."</p>
<p>You may of course use the AVD Manager or Android Studio to start up an emulator to follow along with the example if you would like to.</p>
<p>If you have many connected devices, a useful option for the <code>adb devices</code> command is <code>-l</code>, which gives you more information about the devices.</p>
<p>Below you will see several entries which refer to my physical Android device, as well as an emulator which has been attached to a specific port:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/powershell_devices_list-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h4 id="heading-how-to-send-commands-to-a-specific-device">How to Send Commands To A Specific Device</h4>
<p>To avoid accidentally bricking my phone, I want to send commands to the emulator instead. To do this, I must prepend the <code>-s</code> option, followed by the serial number of the target device, before typing the command.</p>
<p>The serial number is the first set of characters which describes a connected device after using the devices command.</p>
<p>For example, the emulator’s serial number in this case is just the word emulator followed by the port which the emulator is currently attached to.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/powershell_devices_serial-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The other red arrow points to the serial number for my phone (blocked out for obvious reasons).</p>
<p>Naturally, if you only have one device connected (whatever kind it is), you do not need to use the <code>-s</code> option.</p>
<h4 id="heading-install-an-apk-app-on-a-device">Install An APK (App) On A Device</h4>
<p>I am now going to install a test APK on the running emulator using the <code>adb install</code> command.</p>
<p>This is basically equivalent to having Android Studio and Gradle install a debug APK. As you will see, test APKs require the <code>-t</code> option after the install command:</p>
<p><code>adb -s &lt;device-serial-number&gt; install -t &lt;path-to-APK&gt;</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/powershell_install_test_apk.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>Note: The Android OS requires that any APK must be signed before it can be installed</strong> (even if it is just a test/debug APK).</p>
<p>One solution is to build and run the app to be installed in Android Studio, which will sign it with a generated debug certificate. There are several other ways to sign such an APK which you can explore by visiting this <a target="_blank" href="https://developer.android.com/studio/publish/app-signing#debug-mode">link</a>.</p>
<h4 id="heading-what-else-can-adb-do">What Else Can ADB Do?</h4>
<p>Before we take a look at some more advanced usage of the ADB, I strongly encourage you to try the <code>adb --help</code> command. As is customary for most CLI based programs, the help command will print out documentation which describes the various commands and options of the tool.</p>
<p>I am happy to say that the documentation for the ADB is quite legible and useful, which is not always the case in CLI programs.</p>
<h2 id="heading-advanced-adb-usage-tips">Advanced ADB Usage Tips</h2>
<p>It would be a waste of time for both of us to cover every usage and command of the ADB in this article.</p>
<p>In case there is any confusion, using the ADB to install APKs and do many of the things which Android Studio and Gradle do for you is not something that I would recommend (unless you have a good reason to do so).</p>
<p>With that being said, there are plenty of things that the ADB can do which are either difficult or impossible to do without it.</p>
<p>In the preliminaries section, I mentioned that the ADB can be used to get a hook to the shell of the device. To finish this article off, we will look at how to use shell commands and where to find more information about them.</p>
<p>If you do not know what a shell is, you probably skipped the section above where I explained that.</p>
<h3 id="heading-how-to-use-the-abd-shell-1">How to Use the ABD Shell</h3>
<p>Sending a command to the device’s shell using the ADB is fairly simple. Remember that if you have multiple devices connected, follow it with <code>-s &lt;device-serial-number&gt;</code> to direct the command to a specific device.</p>
<p>To make a single shell command, we must use the <code>adb shell</code> command (big surprise, eh?), followed by the actual command we want to make on the device's shell:</p>
<p><code>adb shell ls</code></p>
<p>Output:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/powershell_shell_ls.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>As mentioned previously, the <code>ls</code> command displays a list of files and directories at the CLI's current directory. This happens to be the Android device's root directory until we move to a different one.</p>
<p>If you plan to be making many commands via the Shell, you can also start an interactive Shell session. This can be done via the simple command:</p>
<p><code>adb shell</code></p>
<p>While in an interactive Shell session, you can type Shell commands directly without further use of <code>adb shell &lt;command&gt;</code>.</p>
<p>Note that when you want to quit the interactive Shell session, you can do so by typing <code>exit</code> or hitting Ctrl + D.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/powershell_start_interactive_shell.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>There are a variety of different commands and utilities you can work with via the Shell. The ActivityManager (<code>am</code>) of an Android device can be particularly useful for testing different components (Activities, Services, BroadcastReceivers, to name a few) of an Android app under different circumstances.</p>
<p>Suppose we want to launch straight into a particular Activity, but this Activity is not designated as the launcher Activity in the manifest.</p>
<p>You will still need to add the <code>android:exported=”true”</code> attribute to each <code>&lt;activity/&gt;</code> entry in the manifest which you want to launch (assuming it is not already the launcher Activity).</p>
<p>After that you can use the following command to go straight to it:</p>
<p><code>am start -n &lt;app-package-id&gt;/&lt;activity-name&gt;</code></p>
<p>Note that the <code>&lt;activity-name&gt;</code> must include whichever packages, relative to the package-id, within which it is located. See the output below for an example of launching an Activity which sits within several packages.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/02/powershell_shell_start.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-further-reading">Further Reading</h3>
<p>My goal in this article was to do my best to introduce, explain, and guide you through the usage of the ABD in my own words (insofar as that is possible).</p>
<p>At this point I would need to start making some very contrived examples or to simply carbon copy the documentation, neither of which are things that I am interested in doing.</p>
<p>Instead, I would like to encourage you to visit the <a target="_blank" href="https://developer.android.com/studio/command-line/adb#shellcommands">documentation</a>, and to have a brief look at some of the cool things you can do using tools like the Activity Manager, Package Manager, Policy Manager, and others.</p>
<h4 id="heading-you-can-get-in-touch-with-me-on-social-media-here"><strong>You can get in touch with me on social media here:</strong></h4>
<p><a target="_blank" href="https://www.instagram.com/wiseassbrand/">https://www.instagram.com/rkay301/</a><br><a target="_blank" href="https://www.facebook.com/wiseassblog/">https://www.facebook.com/wiseassblog/</a><br><a target="_blank" href="https://twitter.com/wiseass301">https://twitter.com/wiseass301</a><br><a target="_blank" href="http://wiseassblog.com/">http://wiseassblog.com/</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to build an Augmented Reality Android App with ARCore and Android Studio ]]>
                </title>
                <description>
                    <![CDATA[ By Ayusch Jain This article was originally posted here In the previous post, I explained what ARCore is and how it helps developers build awesome augmented reality apps without the need to understand OpenGL or Matrix maths. If you haven’t checked i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-an-augmented-reality-android-app-with-arcore-and-android-studio-43e4676cb36f/</link>
                <guid isPermaLink="false">66c3501ff41767c3c96bacfe</guid>
                
                    <category>
                        <![CDATA[ Android ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Android Studio ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Apps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Augmented Reality ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 15 Nov 2018 16:57:24 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*YjUBhRlE5eEKPbl-.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ayusch Jain</p>
<blockquote>
<p>This article was originally posted <a target="_blank" href="http://ayusch.com/building-arcore-app-android-studio/">here</a></p>
</blockquote>
<p><a target="_blank" href="https://ayusch.com/what-is-arcore/">In the previous post</a>, I explained <a target="_blank" href="https://ayusch.com/what-is-arcore/">what ARCore is</a> and how it helps developers build awesome augmented reality apps without the need to understand <strong>OpenGL</strong> or <strong>Matrix</strong> maths.</p>
<p>If you haven’t checked it out yet, I highly recommend doing so before moving ahead with this article and diving into ARCore app development.</p>
<h3 id="heading-overview">Overview</h3>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/ARCore">According to Wikipedia</a>, ARCore is a software development kit developed by Google that allows for augmented reality applications to be built.</p>
<p><strong>ARCore</strong> uses three key technologies to integrate virtual content with the real environment:</p>
<ol>
<li><strong>Motion Tracking:</strong> it allows the phone to understand its position relative to the world.</li>
<li><strong>Environmental understanding:</strong> This allows the phone to detect the size and location of all type of surfaces, vertical, horizontal and angled.</li>
<li><strong>Light Estimation:</strong> it allows the phone to estimate the environment’s current lighting conditions.</li>
</ol>
<h3 id="heading-getting-started">Getting Started</h3>
<p>To get started with <strong>ARCore app</strong> development, you first need to enable ARCore in your project. This is simple as we will be using Android Studio and Sceneform SDK. There are two major operations Sceneform performs automatically:</p>
<ol>
<li><strong>Checking for availability of ARCore</strong></li>
<li><strong>Asking for camera permission</strong></li>
</ol>
<p>You don’t need to bother with these two steps when creating an ARCore app using Sceneform SDK. But you do need to include Sceneform SDK in your project.</p>
<p>Create a new Android Studio project and select an empty activity.</p>
<p><strong>Add the following dependency to your project level build.gradle file:</strong></p>
<pre><code>dependencies {    classpath <span class="hljs-string">'com.google.ar.sceneform:plugin:1.5.0'</span>}
</code></pre><p><strong>Add the following to your app level build.gradle file:</strong></p>
<pre><code>implementation <span class="hljs-string">"com.google.ar.sceneform.ux:sceneform-ux:1.5.0"</span>
</code></pre><p>Now sync project with Gradle files and wait for the build to finish. This will install the Sceneform SDK to the project and Sceneform plugin to <strong>AndroidStudio</strong>. It will help you to view the .<strong>sfb</strong> files. These files are the 3D models which are rendered in your camera. It also helps you in importing, viewing, and building <strong>3D assets</strong>.</p>
<h3 id="heading-building-your-first-arcore-app">Building your first ARCore app</h3>
<p>Now with our <strong>Android Studio</strong> setup complete and Sceneform SDK installed, we can get started with writing our very first <strong>ARCore app.</strong></p>
<p>First, we need to add the Sceneform fragment to our layout file. This will be the Scene where we place all our 3D models. It takes care of the camera initialization and permission handling.</p>
<p>Head over to your main layout file. In my case it is <strong>activity_main.xml</strong> and add the Sceneform fragment:</p>
<pre><code>&lt;?xml version=<span class="hljs-string">"1.0"</span> encoding=<span class="hljs-string">"utf-8"</span>?&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">FrameLayout</span> <span class="hljs-attr">xmlns:android</span>=<span class="hljs-string">"http://schemas.android.com/apk/res/android"</span>    <span class="hljs-attr">xmlns:tools</span>=<span class="hljs-string">"http://schemas.android.com/tools"</span>    <span class="hljs-attr">android:layout_width</span>=<span class="hljs-string">"match_parent"</span>    <span class="hljs-attr">android:layout_height</span>=<span class="hljs-string">"match_parent"</span>    <span class="hljs-attr">tools:context</span>=<span class="hljs-string">".MainActivity"</span>&gt;</span></span>
</code></pre><pre><code>    &lt;fragment android:name=<span class="hljs-string">"com.google.ar.sceneform.ux.ArFragment"</span>        android:id=<span class="hljs-string">"@+id/ux_fragment"</span>        android:layout_width=<span class="hljs-string">"match_parent"</span>        android:layout_height=<span class="hljs-string">"match_parent"</span> /&gt;
</code></pre><pre><code>&lt;/FrameLayout&gt;
</code></pre><p>I’ve set the width and height to match parent as this will cover my entire activity. You can choose the dimensions according to your requirements.</p>
<h3 id="heading-compatibility-check">Compatibility Check</h3>
<p>This is all that you need to do in the layout file. Now head over to the java file, in my case which is MainActivity.java. Add the method below in your class:</p>
<pre><code>public <span class="hljs-keyword">static</span> boolean checkIsSupportedDeviceOrFinish(final Activity activity) {    <span class="hljs-keyword">if</span> (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.N) {        Log.e(TAG, <span class="hljs-string">"Sceneform requires Android N or later"</span>);        Toast.makeText(activity, <span class="hljs-string">"Sceneform requires Android N or later"</span>, Toast.LENGTH_LONG).show();        activity.finish();        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;    }    <span class="hljs-built_in">String</span> openGlVersionString =            ((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE))                    .getDeviceConfigurationInfo()                    .getGlEsVersion();    <span class="hljs-keyword">if</span> (Double.parseDouble(openGlVersionString) &lt; MIN_OPENGL_VERSION) {        Log.e(TAG, <span class="hljs-string">"Sceneform requires OpenGL ES 3.0 later"</span>);        Toast.makeText(activity, <span class="hljs-string">"Sceneform requires OpenGL ES 3.0 or later"</span>, Toast.LENGTH_LONG)                .show();        activity.finish();        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;    }    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;}
</code></pre><p>This method checks whether your device can support Sceneform SDK or not. The SDK requires Android API level 27 or newer and <strong>OpenGL ES</strong> <strong>version 3.0</strong> or newer. If a device does not support these two, the Scene would not be rendered and your application will show a blank screen.</p>
<p>Although, you can still continue to deliver all the other features of your app which don’t require the Sceneform SDK.</p>
<p>Now with the device compatibility check complete, we shall build our 3D model and attach it to the scene.</p>
<h3 id="heading-adding-the-assets">Adding the assets</h3>
<p>You will need to add the 3D models which will be rendered on your screen. Now you can build these models yourself if you are familiar with 3D model creation. Or, you can visit <strong>Poly.</strong></p>
<p>There you’ll find a huge repository of 3D assets to choose from. They are free to download. Just credit the creator and you are good to go.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/n-nw06cs3-ISxbKFW3j1ICdyfLIJM7Jpf0dR" alt="Image" width="800" height="379" loading="lazy"></p>
<p>In the Android Studio, expand your app folder available on the left-hand side project pane. You’ll notice a <strong>“</strong>sampledata<strong>”</strong> folder. This folder will hold all of your 3D model assets. Create a folder for your model inside the sample data folder.</p>
<p>When you download the zip file from poly, you will most probably find 3 files.</p>
<ol>
<li><strong>.mtl file</strong></li>
<li><strong>.obj file</strong></li>
<li><strong>.png file</strong></li>
</ol>
<p>Most important of these 3 is the .obj file. It is your actual model. Place all the 3 files inside <strong>sampledata</strong> <strong>-&gt; “your model’s folde</strong>r”.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/jInoAjquRuqEpoCSH3RSO4VRoWi5tNu9GLL9" alt="Image" width="800" height="429" loading="lazy"></p>
<p><strong>Now right click on the .obj</strong> <strong>file</strong>. The first option would be to Import Sceneform Asset. Click on it, do not change the default settings, just click finish on the next window. Your gradle will sync to include the asset in the assets folder. Once the gradle build finishes, you are good to go.</p>
<p>You’ve finished importing a 3D asset used by Sceneform in your project. <strong>Next</strong>, let’s build the asset from our code and include it in the scene.</p>
<h3 id="heading-building-the-model">Building the Model</h3>
<p>Add the following code to your MainActivity.java file (or whatever it is in your case). Don’t worry, I’ll explain all the code line by line:</p>
<pre><code>private <span class="hljs-keyword">static</span> final <span class="hljs-built_in">String</span> TAG = MainActivity.class.getSimpleName();private <span class="hljs-keyword">static</span> final double MIN_OPENGL_VERSION = <span class="hljs-number">3.0</span>;
</code></pre><pre><code>ArFragment arFragment;ModelRenderable lampPostRenderable;
</code></pre><pre><code>@Override@SuppressWarnings({<span class="hljs-string">"AndroidApiChecker"</span>, <span class="hljs-string">"FutureReturnValueIgnored"</span>})
</code></pre><pre><code>protected <span class="hljs-keyword">void</span> onCreate(Bundle savedInstanceState) {    <span class="hljs-built_in">super</span>.onCreate(savedInstanceState);    <span class="hljs-keyword">if</span> (!checkIsSupportedDeviceOrFinish(<span class="hljs-built_in">this</span>)) {        <span class="hljs-keyword">return</span>;    }    setContentView(R.layout.activity_main);    arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment);
</code></pre><pre><code>    ModelRenderable.builder()            .setSource(<span class="hljs-built_in">this</span>, Uri.parse(<span class="hljs-string">"LampPost.sfb"</span>))            .build()            .thenAccept(renderable -&gt; lampPostRenderable = renderable)            .exceptionally(throwable -&gt; {                Toast toast =                        Toast.makeText(<span class="hljs-built_in">this</span>, <span class="hljs-string">"Unable to load andy renderable"</span>, Toast.LENGTH_LONG);                toast.setGravity(Gravity.CENTER, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);                toast.show();                <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;            });
</code></pre><pre><code>}
</code></pre><p><strong>First</strong>, we find the <strong>arFragment</strong> that we included in the layout file. This fragment is responsible for hosting the scene. You can think of it as the container of our scene.</p>
<p><strong>Next</strong>, we are using the <strong>ModelRenderable</strong> class to build our model. With the help of setSource method, we load our model from the .<strong>sfb</strong> file. This file was generated when we imported the assets. <strong>thenAccept</strong> method receives the model once it is built. We set the loaded model to our <strong>lampPostRenderable.</strong></p>
<p>For error handling, we have <strong>.exceptionally</strong> method. It is called in case an exception is thrown.</p>
<p>All this happens <strong>asynchronously</strong>, hence you don’t need to worry about multi-threading or deal with handlers XD</p>
<p>With the model loaded and stored in the <strong>lampPostRenderable</strong> variable, we’ll now add it to our scene.</p>
<h3 id="heading-adding-the-model-to-scene">Adding the Model to Scene</h3>
<p>The <strong>arFragment</strong> hosts our scene and will receive the tap events. So we need to set the onTap listener to our fragment to register the tap and place an object accordingly. Add the following code to onCreate method:</p>
<pre><code>arFragment.setOnTapArPlaneListener(        (HitResult hitresult, Plane plane, MotionEvent motionevent) -&gt; {            <span class="hljs-keyword">if</span> (lampPostRenderable == <span class="hljs-literal">null</span>){                <span class="hljs-keyword">return</span>;            }
</code></pre><pre><code>            Anchor anchor = hitresult.createAnchor();            AnchorNode anchorNode = <span class="hljs-keyword">new</span> AnchorNode(anchor);            anchorNode.setParent(arFragment.getArSceneView().getScene());
</code></pre><pre><code>            TransformableNode lamp = <span class="hljs-keyword">new</span> TransformableNode(arFragment.getTransformationSystem());            lamp.setParent(anchorNode);            lamp.setRenderable(lampPostRenderable);            lamp.select();        });
</code></pre><p>We set the <strong>onTapArPlaneListener</strong> to our <strong>AR fragment</strong>. Next what you see is the <strong>Java 8 syntax</strong>, in case you are not familiar with it, I would recommend checking out <a target="_blank" href="https://www.tutorialspoint.com/java8/index.htm"><strong>this guide</strong></a>.</p>
<p><strong>First,</strong> we create our anchor from the HitResult using <strong>hitresult.createAnchor()</strong> and store it in an Anchor object.</p>
<p><strong>Next</strong>, create a node out of this anchor. It will be called <strong>AnchorNode.</strong> It will be attached to the scene by calling the setParent method on it and passing the scene from the fragment.</p>
<p>Now we create a <strong>TransformableNode</strong> which will be our <strong>lamppost</strong> and set it to the anchor spot or our anchor node. The node still doesn’t have any information about the object it has to render. We’ll pass that object using <strong>lamp.setRenderable</strong> method which takes in a renderable as it’s parameter. Finally call lamp.select();</p>
<p><strong>Phew!!</strong> Too much terminology there, but don’t worry, I’ll explain it all.</p>
<ol>
<li><strong>Scene</strong>: This is the place where all your 3D objects will be rendered. This scene is hosted by the AR Fragment which we included in the layout. An anchor node is attached to this screen which acts as the root of the tree and all the other objects are rendered as its objects.</li>
<li><strong>HitResult</strong>: This is an imaginary line (or a ray) coming from infinity which gives the point of intersection of itself with a real-world object.</li>
<li><strong>Anchor</strong>: An anchor is a fixed location and orientation in the real world. It can be understood as the x,y,z coordinate in the 3D space. You can get an anchor’s post information from it. <strong>Pose</strong> is the position and orientation of the object in the scene. This is used to transform the object’s local coordinate space into real-world coordinate space.</li>
<li>AnchorNode: This is the node that automatically positions itself in the world. This is the first node that gets set when the plane is detected.</li>
<li><strong>TransformableNode</strong>: It is a node that can be interacted with. It can be moved around, scaled rotated and much more. In this example, we can scale the <strong>lamp</strong> and rotate it. Hence the name Transformable.</li>
</ol>
<p>There is no rocket science here. It’s really simple. The entire scene can be viewed as a graph with Scene as the parent, <strong>AnchorNode</strong> as its child and then branching out different nodes/objects to be rendered on the screen.</p>
<p>Your final MainActivity.java must look something like this:</p>
<pre><code>package com.ayusch.arcorefirst;
</code></pre><pre><code><span class="hljs-keyword">import</span> android.app.Activity;<span class="hljs-keyword">import</span> android.app.ActivityManager;<span class="hljs-keyword">import</span> android.content.Context;<span class="hljs-keyword">import</span> android.net.Uri;<span class="hljs-keyword">import</span> android.os.Build;<span class="hljs-keyword">import</span> android.support.v7.app.AppCompatActivity;<span class="hljs-keyword">import</span> android.os.Bundle;<span class="hljs-keyword">import</span> android.util.Log;<span class="hljs-keyword">import</span> android.view.Gravity;<span class="hljs-keyword">import</span> android.view.MotionEvent;<span class="hljs-keyword">import</span> android.widget.Toast;
</code></pre><pre><code><span class="hljs-keyword">import</span> com.google.ar.core.Anchor;<span class="hljs-keyword">import</span> com.google.ar.core.HitResult;<span class="hljs-keyword">import</span> com.google.ar.core.Plane;<span class="hljs-keyword">import</span> com.google.ar.sceneform.AnchorNode;<span class="hljs-keyword">import</span> com.google.ar.sceneform.rendering.ModelRenderable;<span class="hljs-keyword">import</span> com.google.ar.sceneform.ux.ArFragment;<span class="hljs-keyword">import</span> com.google.ar.sceneform.ux.TransformableNode;
</code></pre><pre><code>public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MainActivity</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">AppCompatActivity</span> </span>{    private <span class="hljs-keyword">static</span> final <span class="hljs-built_in">String</span> TAG = MainActivity.class.getSimpleName();    private <span class="hljs-keyword">static</span> final double MIN_OPENGL_VERSION = <span class="hljs-number">3.0</span>;
</code></pre><pre><code>    ArFragment arFragment;    ModelRenderable lampPostRenderable;
</code></pre><pre><code>    @Override    @SuppressWarnings({<span class="hljs-string">"AndroidApiChecker"</span>, <span class="hljs-string">"FutureReturnValueIgnored"</span>})    protected <span class="hljs-keyword">void</span> onCreate(Bundle savedInstanceState) {        <span class="hljs-built_in">super</span>.onCreate(savedInstanceState);        <span class="hljs-keyword">if</span> (!checkIsSupportedDeviceOrFinish(<span class="hljs-built_in">this</span>)) {            <span class="hljs-keyword">return</span>;        }        setContentView(R.layout.activity_main);        arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment);
</code></pre><pre><code>        ModelRenderable.builder()                .setSource(<span class="hljs-built_in">this</span>, Uri.parse(<span class="hljs-string">"LampPost.sfb"</span>))                .build()                .thenAccept(renderable -&gt; lampPostRenderable = renderable)                .exceptionally(throwable -&gt; {                    Toast toast =                            Toast.makeText(<span class="hljs-built_in">this</span>, <span class="hljs-string">"Unable to load andy renderable"</span>, Toast.LENGTH_LONG);                    toast.setGravity(Gravity.CENTER, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);                    toast.show();                    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;                });
</code></pre><pre><code>            arFragment.setOnTapArPlaneListener(                    (HitResult hitresult, Plane plane, MotionEvent motionevent) -&gt; {                        <span class="hljs-keyword">if</span> (lampPostRenderable == <span class="hljs-literal">null</span>){                            <span class="hljs-keyword">return</span>;                        }
</code></pre><pre><code>                        Anchor anchor = hitresult.createAnchor();                        AnchorNode anchorNode = <span class="hljs-keyword">new</span> AnchorNode(anchor);                        anchorNode.setParent(arFragment.getArSceneView().getScene());
</code></pre><pre><code>                        TransformableNode lamp = <span class="hljs-keyword">new</span> TransformableNode(arFragment.getTransformationSystem());                        lamp.setParent(anchorNode);                        lamp.setRenderable(lampPostRenderable);                        lamp.select();                    }            );
</code></pre><pre><code>    }
</code></pre><pre><code>    public <span class="hljs-keyword">static</span> boolean checkIsSupportedDeviceOrFinish(final Activity activity) {        <span class="hljs-keyword">if</span> (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.N) {            Log.e(TAG, <span class="hljs-string">"Sceneform requires Android N or later"</span>);            Toast.makeText(activity, <span class="hljs-string">"Sceneform requires Android N or later"</span>, Toast.LENGTH_LONG).show();            activity.finish();            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;        }        <span class="hljs-built_in">String</span> openGlVersionString =                ((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE))                        .getDeviceConfigurationInfo()                        .getGlEsVersion();        <span class="hljs-keyword">if</span> (Double.parseDouble(openGlVersionString) &lt; MIN_OPENGL_VERSION) {            Log.e(TAG, <span class="hljs-string">"Sceneform requires OpenGL ES 3.0 later"</span>);            Toast.makeText(activity, <span class="hljs-string">"Sceneform requires OpenGL ES 3.0 or later"</span>, Toast.LENGTH_LONG)                    .show();            activity.finish();            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;        }        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;    }}
</code></pre><p><strong>Congratulations!!</strong> You’ve just completed your first ARCore app. Start adding objects and see them come alive in the real world!</p>
<p>This was your first look into how to create a simple <strong>ARCore app</strong> from scratch with Android studio. In the next tutorial, I would be going deeper into ARCore and adding more functionality to the app.</p>
<blockquote>
<p><em>If you have any suggestions or any topic you would want a tutorial on, just mention in the comments section and I’ll be happy to oblige.</em></p>
</blockquote>
<p><em>Like what you read? Don’t forget to share this post on <a target="_blank" href="https://www.facebook.com/AndroidVille"><strong>Facebook</strong></a>, <strong>Whatsapp</strong> and <strong>LinkedIn</strong>.</em></p>
<p><em>You can follow me on <a target="_blank" href="https://www.linkedin.com/in/ayuschjain">LinkedIn</a>, <a target="_blank" href="https://www.quora.com/profile/Ayusch-Jain">Quora</a>, <a target="_blank" href="https://twitter.com/ayuschjain">Twitter</a> and <a target="_blank" href="https://www.instagram.com/androidville/">Instagram</a> where I <strong>answer</strong> questions related to <strong>Mobile Development, especially Android and Flutter</strong>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
