Kristin Marsicano - Big Nerd Ranch Tue, 19 Oct 2021 17:46:17 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.5 UI Updates in a Multi-Window World https://bignerdranch.com/blog/ui-updates-in-a-multi-window-world/ https://bignerdranch.com/blog/ui-updates-in-a-multi-window-world/#respond Tue, 30 Aug 2016 10:00:53 +0000 https://nerdranchighq.wpengine.com/blog/ui-updates-in-a-multi-window-world/ With the advent of multi-window in Android Nougat, you need to more carefully consider what your UI should be doing when your activity is visible vs. in the foreground. This post will highlight considerations to make in updating your UI on Nougat (and beyond) devices, while still providing a smooth experience for pre-Nougat users.

The post UI Updates in a Multi-Window World appeared first on Big Nerd Ranch.

]]>

Up until now, it has been common practice to kick off and cancel UI updates during the foreground lifecycle of an activity. However, with the advent of multi-window in Android Nougat, the visible lifecycle is no longer as roughly equivalent to the foreground lifecycle as it was before. In turn you should carefully consider what your UI should be doing when your activity is visible vs. in the foreground, rather than treating them as one and the same.

This post will highlight considerations to make in updating your UI on Nougat (and beyond) devices, while still providing a smooth experience for pre-Nougat users.

Activity States: A Quick Review

If you are not already familiar with the activity states and lifecycle callback methods, or even if you are, check out my in-depth talk on the activity lifecycle from 360AnDev 2016. But not to worry, we’ll do a quick overview here.

An activity’s state depends on three things:

  1. Is there an instance of the activity in memory?
  2. Is the activity’s view visible to the user?
  3. Is the activity active in the foreground?

There are four states an activity can be in:

State In memory? Visible to user? In foreground?
Non-Existent No No No
Stopped Yes No No
Paused Yes Yes/Partially No
Running (aka Resumed, Active) Yes Yes Yes

Nonexistent represents an activity that has not been launched yet, or that was just destroyed (e.g. by the user pressing back). There is no instance in memory, and in turn there is no view associated with it for the user to see nor to interact with.

Stopped represents an activity that has an instance in memory, but the whose view is not visible on the screen. This state occurs in passing when the activity is first spinning up, and any time the view is fully occluded (e.g. when the user launches another full screen activity to the foreground, presses the home button, or uses the overview screen to switch tasks).

Paused represents an activity whose view is visible, or partially visible, but is not active in the foreground. An activity would be partially-visible, for example, if the user launches a new dialog-themed or transparent activity on top of it. An activity could also be fully-visible but not in the foreground if the user is viewing two separate activities in multi-window mode.

Running represents an activity that is in memory, fully visible, and is in the foreground. It is the activity the user is interacting with currently. Only one activity across the entire system can be running at any given time. That means if one activity is moving to the running state, another is likely moving out of the running state.

The operating system calls methods, known as lifecycle callbacks, on the Activity object to notify us developers the state of the activity is changing. onStop() is one such lifecycle callback.

onStop() signifies the activity is moving out of view

The operating system calls onStop() on an activity as the activity’s view moves out of the user’s sight. Once onStop() completes, the activity is in the stopped state.

Activity Lifecycle State Diagram

onStop() represents the end of the visible lifecycle of an activity (the time in which the user can see the activity’s view). Its counterpart, onStart(), represents the beginning of the visible lifecycle of an activity. You can assume the activity’s view is partially- or wholly-visible in any callbacks called between onStart() and onStop().

Knowing when your activity’s view will no longer be visible to the user is important. As Android developers we want to provide the best user experience while minimizing resource usage. Consider, for example, an app that displays location data. Polling for location drains power. The more accurate and more frequent, the more power. If the user is not able to see your application, do you still need to be polling for such information? It depends on your requirements, but it behooves you as a developer to consider what work you might be able to minimize or stop altogether when your activity in the stopped state.

Prior to Nougat, an activity spent very little time in the scenario where it was both paused and fully-visible. The main scenario where paused and fully-visible occurred was on activity launch. And in that case, the scenario lasted very briefly as the activity was cycled immediately to running (aka resumed) state. For the most part, pre-Nougat activities find themselves in the paused state when their view is partially occluded (for example, when a new activity that is transparent or smaller than the entire screen is launched on top).

Because of this, it has been common practice to use onResume() and onPause to set up or tear down any updates related to the user interface. The assumption was you do not need to update your UI when the activity is paused, only when it is in the foreground. In other words, the foreground lifecycle (see diagram above) was treated as roughly equivalent to the visible lifecycle.

However, with the advent of multi-windowing in Nougat, activities will find themselves in the paused and fully-visible state for longer periods of time. This means your user will be looking at your paused activity alongside a window containing a different running activity. Remember, only one activity can be running at a time, so when the user interacts with the activity in the window on the left, it comes to the foreground and, in turn the activity in the window on the right cannot be running and thus is paused.

Multi-Window Example from Android Documentation

Since your activity’s view is fully visible, users will still expect your app to be running (e.g. updating data, playing video, etc.) even though it is not in the foreground. In a Nougat world, then, your activity should update the UI during the entire visible lifecycle of your activity, between onStart() and onStop().

Consider video, for example. You have a legacy app that does simple video playback. You start or resume video playback in onResume() and pause playback in onPause. This worked well up until now.

However, in multi-window mode, your users are complaining because they want to watch their video while they send a text message in a separate window, but your app stops video whenever they interact with another app in that second window. You can fix the problem by moving your playback resuming and pausing to onStart() and onStop(). Same would go for any live updating date, like a photo gallery app that refreshes to show new images as they are pushed to a Flickr stream.

onStop() is lazy no more

A word of caution, though, before you blindly move all of your UI setup and teardown code. Prior to Nougat, onStop() was a lazy operation. It was not guaranteed that onStop() would be called as soon as the activity was no longer visible. Instead, it could occur a short time after.

On Nougat and beyond, though, you are guaranteed onStop() will be called called as soon as the activity is no longer visible.

With respect to our video example, if you move your code to pause or stop playback to onStop(), users on pre-Nougat may hear the audio continuing to play momentarily after they press the back button, even after the video is no longer visible.

So what are you to do? To ensure a positive user experience on both pre-Nougat and Nougat devices, add conditionals to address scenarios like this one. Place the clean up code (in this case, stopping video playback) in both onPause() and onStop(), guarded with conditional checks for API level, as shown in this snippet from the ExoPlayer demo code:

...
@Override
public void onPause() {
  super.onPause();
  if (Util.SDK_INT <= 23) {
    onHidden();
  }
}
@Override
public void onStop() {
  super.onStop();
  if (Util.SDK_INT > 23) {
    onHidden();
  }
}
...

Not all scenarios are as extreme as video when it comes to pre-Nougat lazy stop manifesting itself in a noticeable way. In many cases it will be just fine to always stop your UI updates in onStop(), rather than conditionally running the updates in both onPause and onStop().

Parting thoughts

Making decisions about what to do in each of the activity lifecycle methods requires consideration of:

  • the requirements for your application
  • balancing resource usage and user experience
  • how the activity states correspond to what the user can see and do

The states and their meaning have not changed, but the addition of multi-windowing renders a previously rare state (paused and fully-visible for an extended period of time) more common. Luckily, having a strong understanding of the activity lifecycle will help you reason about how to update your code (if at all) when new additions like multi-windowing are added as the platform evolves!

The post UI Updates in a Multi-Window World appeared first on Big Nerd Ranch.

]]>
https://bignerdranch.com/blog/ui-updates-in-a-multi-window-world/feed/ 0
Polishing Your Android Overview Screen Entry https://bignerdranch.com/blog/polishing-your-android-overview-screen-entry/ https://bignerdranch.com/blog/polishing-your-android-overview-screen-entry/#respond Wed, 19 Nov 2014 10:10:22 +0000 https://nerdranchighq.wpengine.com/blog/polishing-your-android-overview-screen-entry/

Looking for a way to further polish your Android app on Lollipop? One option a lot of developers overlook is the Overview Screen.

The post Polishing Your Android Overview Screen Entry appeared first on Big Nerd Ranch.

]]>

Looking for a way to further polish your Android app on Lollipop? One option a lot of developers overlook is the Overview Screen.

As the developer docs state:

The overview screen (also referred to as the recents screen, recent task list, or recent apps) is a system-level UI that lists recently accessed activities and tasks. The user can navigate through the list and select a task to resume, or the user can remove a task from the list by swiping it away.

Before Lollipop, the Overview Screen was not configurable. Entries included the application label, launcher icon and a screen shot of what the user was last doing in the app.

Side-by-side Comparison: KitKat vs. Lollipop

With Lollipop, a more sleekly styled Overview Screen was introduced. More importantly, the new API enables you to customize the icon, title and top bar color of your application’s Overview Screen “card”:

Side-by-side Comparison: KitKat vs. Lollipop

With a little effort, you can ensure that your Overview Screen card shines amongst the rest.

Default Overview Card Styling and XML

Let’s first explore what happens if you rely on the built-in default Lollipop behavior for styling.

The system will pull values for the Overview card’s icon, label and top bar from your manifest:

  • Icon – android:icon
  • Label text – android:label
  • Top Bar Color – colorPrimary value of android:theme

These values will be pulled from the manifest entry for the activity at the base of the activity stack.1 In most cases, this means the values will be based on your launcher/main activity. If there is no value specified on the activity itself, the system will use the application level value.

An interesting thing to note is that the color of the label text is not configurable directly. Instead, the system automatically selects the text color based on the color used for the top bar. If the top bar is dark, the text will be light. Otherwise, the text will be dark.

Backwards Compatibility and colorPrimary

The colorPrimary attribute was introduced in Lollipop. However, the attribute is available in the v7 appcompat library. If you have not already, you should make sure your app’s theme is Lollipop-compatible. An easy way to do this is include the v7 appcompat library and then base your theme on one of the Appcompat.Theme values, such as Theme.AppCompat.Light.

Default Styling: The Limitations of Using XML

So when would this default behavior not be enough? That depends on how it looks with your app’s design.

One of the simplest, most impactful, things you can do to polish your app’s Overview Screen card is to provide a separate overview icon that looks great at a very small size and on the primaryColor background. Unfortunately, this usually cannot be achieved using XML.

Consider screenshots for my demo Big Nerd Ranch app:

Big Nerd Ranch Demo App: XML Overview Screen Example

Here is a snippet from the AndroidManifest.xml file:

		...
	    <application
	        android:allowBackup="true"
	        android:icon="@drawable/ic_launcher_bnr"
	        android:label="@string/app_name"
	        android:theme="@style/AppTheme" >
	
	        <activity
	            android:name="com.bignerdranch.android.bignerdranch.WelcomeActivity"
	            android:label="@string/app_name">
	            <intent-filter>
	                <action android:name="android.intent.action.MAIN" />
	                <category android:name="android.intent.category.LAUNCHER" />
	            </intent-filter>
	        </activity>
		...

And here is the styles.xml file:

	<resources>

	    <style name="AppTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar">
	        <item name="colorPrimary">#747501</item>
	        <item name="colorPrimaryDark">#595a02</item>
	        <item name="colorAccent">#e7ad10</item>
	    </style>
	</resources>

You can see the example icon is pulled from application android:icon, the label is pulled from WelcomeActivity’s android:label and the top bar color is pulled from AppTheme’s colorPrimary.

Kar Loong Wong, one of our awesome designers here at Big Nerd Ranch, took a look at my Overview card styling and immediately called out the inadequacies of using my launcher icon in the overview screen. Namely, the yellow does not show well at such a small size, so the propeller on top of the hat is too hard to see.

So I set off to specify a separate icon for the launcher activity. The problem is, the manifest doesn’t give you ability to specify the Overview icon separately from the activity icon. Setting an android:icon value on WelcomeActivity overwrites the launcher icon displayed. This means you will need another way to specify the Overview card styling. Lucky for you, there is another way…

Overriding Overview Card Style in Code

Lollipop introduced the ability to set a TaskDescription on an activity at run time. Doing so will override the icon, color and label that the Overview card would otherwise get.

By default, the TaskDescription is based on the activity at the base of the task’s activity stack, as discussed in the XML section above. Other activities that pile on will not affect the styling, unless those activities have a TaskDescription explicitly set at run time. The topmost activity with a TaskDescription explicitly set will trump the styling specified in the manifest or in activities below in the stack with TaskDescriptions set.

The following code snippet from the WelcomeActivity.xml file builds and sets a task description for my app’s launcher activity:

	public class WelcomeActivity extends ActionBarActivity {
	
	    @Override
	    protected void onCreate(Bundle savedInstanceState) {
	        super.onCreate(savedInstanceState);
	        setContentView(R.layout.activity_welcome);
	
	        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
	
	            TypedValue typedValue = new TypedValue();
	            Resources.Theme theme = getTheme();
	            theme.resolveAttribute(R.attr.colorPrimary, typedValue, true);
	            int color = typedValue.data;
	
	            Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_activity_welcome);
	            ActivityManager.TaskDescription td = new ActivityManager.TaskDescription(null, bm, color);
	
	            setTaskDescription(td);
	            bm.recycle();
	
	        }
	    }
	    
	    ...
	}

Activity.setTaskDescription() is available only in API 21 (Lollipop). In order to support older devices while still showing the latest and greatest on Lollipop devices, it is important to guard your TaskDescription code with an API level check.

The code then uses the three-parameter version of the TaskDescription constructor, ActivityManager.TaskDescription(String label, Bitmap icon, int colorPrimary), to create an TaskDescription instance. Avoid the other TaskDescription constructors; they all ignore colorPrimary, which is rarely what you want.

I pass null for the label on purpose. If you don’t provide a label value, or provide a null value, the most-specific value available from the manifest is used (as discussed in the XML section above).

colorPrimary is pulled from the theme. This way, you don’t have to change the value in multiple places if your color palette changes. I recommend you use your colorPrimary value, unless you have good reason not to. It is also important to note that the primary color you specify must be completely opaque. If not, the system will throw a runtime exception.

Finally, call setTaskDescription(), which associates the TaskDescription instance with the Activity instance.

The end result looks like this, with separate launcher and Overview icons:

Big Nerd Ranch Demo App: TaskDescription Overview Screen Example

Beware Non-Standard Toolbars

The Overview card is essentially a screenshot with a top bar drawn over top of it. It just so happens that the size of the top bar is the same size as the default Toolbar size. If your Toolbar is larger than the default size, it will hang below the top bar in the Overview card. If you do not have a Toolbar, your Toolbar is in a non-standard location or your Toolbar is smaller than the default size, your app’s screenshot will look clipped in the Overview screen.

Big Nerd Ranch Demo App: No Toolbar Example

Go Forth and Polish your App

Styling your app’s Overview card is one of the many ways you can polish the Lollipop version of your app. What other things have you tried? Stay tuned for more blog posts to help you get your app ready for Lollipop.

Many thanks to UX/UI Designer Kar Loong Wong for the icon assets in this post.

  1. Not sure about tasks and the activity back stack? Check out our Android bootcamp to learn all the fundamentals necessary to be a solid Android developer.

The post Polishing Your Android Overview Screen Entry appeared first on Big Nerd Ranch.

]]>
https://bignerdranch.com/blog/polishing-your-android-overview-screen-entry/feed/ 0
News From Google I/O: Android Everywhere https://bignerdranch.com/blog/news-from-google-i-o-android-everywhere/ https://bignerdranch.com/blog/news-from-google-i-o-android-everywhere/#respond Wed, 25 Jun 2014 10:10:22 +0000 https://nerdranchighq.wpengine.com/blog/news-from-google-i-o-android-everywhere/

Sitting in the Google I/O keynote yesterday, one thing became apparent to me: Android is everywhere. I was well aware that Android is used all over the world, but Android will very soon not just be on many people’s phones in many diverse locations, but on many devices that a single person interacts with on a daily basis.

The post News From Google I/O: Android Everywhere appeared first on Big Nerd Ranch.

]]>

Sitting in the Google I/O keynote yesterday, one thing became apparent to me: Android is everywhere. I was well aware that Android is used all over the world, but Android will very soon not just be on many people’s phones in many diverse locations, but on many devices that a single person interacts with on a daily basis.

Watches and Cars and Televisions, Oh My!

New modalities of interaction with Android are appearing at a rapid pace. Google has announced that you will now (or soon) be able to use Android in the following new ways in addition to using Android-powered phones, tablets or Glass:

On Your Wrist

Three smart watch models are available (two are ready for purchase now and one is available for preorder). Each is powered by Android Wear. (For more info about wearables, see Kurt Nelson’s post on the state of the Weariverse.)

In Your Car

According to the keynote, more than 40 new members have joined the Open Automotive Alliance, and “the rubber will hit the road” when the Android Auto SDK becomes available with the public “L” release later this year.

On Your Television

Chromecast was announced last year, allowing users to stream content from a device to their television. Yesterday, Google announced Android TV (not to be confused with Google TV from 2010), which supports streaming content from your phone or tablet, along with an integrated experience for playing content directly from the television itself and interacting with apps developed expressly for TV using the Android TV SDK.

On Your Laptop

While it seems farther off, Sundar Pinchai announced in the keynote that Google is working on supporting interaction between Android apps and Chrome OS. In the short term, Chromebook is able to tell you things about your phone, like when its battery is low or if you are getting an incoming call.

Unifying the User Experience

In response to the growing number of Android interaction options available, a common theme presented itself in the keynote and again through the various talks I attended yesterday: unifying a user’s experience as he or she transitions between modes or devices.

Of course, converging data using the cloud is old news. The focus here was on syncing a user’s interactions across all their devices. For example:

Notifications

I heard in three different talks that, with the new Android Wear APIs, developers will be able to easily offer users unified Android notifications, mostly managed by phone and presented through Android Wear on auxiliary devices. A user sees notifications from their phone apps on their watch, Glass or even their Chromebook. If the user dismisses a notification in one place, it will also be dismissed on the others. Key for me was that “no extra work is needed on the developer’s part.” Also of great interest is that developers can customize these notifications in an “enhanced” fashion (e.g., we can display player controls for an audio player).

Applications

Apps installed on your phone are automatically synced with your Wear device. The Wear device will install its compatible version of the app. A demo of the Allthecooks app showed that you can open
a recipe on your phone and then view a single step at a time on your Wear-powered watch.

Controlling One Device from Another

Several demos (including the Allthecooks demo) highlighted the importance of allowing users to control what’s happening on one device through another when it’s more convenient. You can use your watch to control music playing on your phone, use your phone to control Android TV content selection or use your Chromebook to take over your Evernote interactions.

Leveraging a User’s Multiple Devices for Context Awareness

One neat feature discussed in the keynote was using devices to provide authentication validation. For example, if your watch is on your wrist or your phone is in your hand, your Android-powered devices can assume they are in a “safe” context and allow you to interact with them without a PIN verification. I’m excited to see other ideas that grow from the premise that a single user has multiple Android devices.

In order to create the unified experience, Google is adding API support for the following in Google Play Services 5.0L:

  • Message API: Send unidirectional messages between a wearable and phone. (For example, you can tell your phone to change a song being played).
  • Asset API: Transfer binary blocks (such as images) between a wearable and another device (Your phone could download an image and resize it to match the resolution of your device and send it over to your wearable as an asset).
  • DataItem API: Have data that is in sync in both the wearable and another device, so if it changes in one side it will be available in the other.

I’m looking forward to learning more about these new platforms and incorporating them into our Android bootcamps. I hope you will join us—solid Android knowledge will make developing for any of these new platforms easy!

The post News From Google I/O: Android Everywhere appeared first on Big Nerd Ranch.

]]>
https://bignerdranch.com/blog/news-from-google-i-o-android-everywhere/feed/ 0
Standing out from the Crowd at Big Nerd Ranch Bootcamps https://bignerdranch.com/blog/standing-out-from-the-crowd-at-big-nerd-ranch-bootcamps/ https://bignerdranch.com/blog/standing-out-from-the-crowd-at-big-nerd-ranch-bootcamps/#respond Thu, 13 Mar 2014 18:23:46 +0000 https://nerdranchighq.wpengine.com/blog/standing-out-from-the-crowd-at-big-nerd-ranch-bootcamps/

What drives me as an instructor is my desire to connect with my students. To know what they want to learn and why they want to learn it. To understand what they already know and figure out how we can use that as the foundation for something more. As a teacher, I want to meet people where they are with the material, figure out where they want to go, and help them find a path.

The post Standing out from the Crowd at Big Nerd Ranch Bootcamps appeared first on Big Nerd Ranch.

]]>

What drives me as an instructor is my desire to connect with my students. To know what they want to learn and why they want to learn it. To understand what they already know and figure out how we can use that as the foundation for something more. As a teacher, I want to meet people where they are with the material, figure out where they want to go, and help them find a path.

Fortunately, my role as an Android instructor at Big Nerd Ranch offers me the opportunity to connect with and help students in a way that I love. Here’s what is great about teaching our bootcamps:

Working closely with students

Having one-on-one interaction with students is important. And it’s not just the quantity, but the quality, of the one-on-one time. As an instructor, I can work directly with a single student to figure out how to help him or her best proceed on the path to learning. I can have conversations with students to understand what their misconceptions are, what things are going well and where they need further instruction.

Face time is crucial to developing a relationship and trust. And trust is important because learning can be a scary thing. It’s scary to admit you don’t know something or that you are struggling with material. As students get more comfortable with the instructor, they start to be more forthcoming about what they need and what they think is hard.

A mix of hands-on labs and lectures

Something I heard once has always stuck with me: “As a teacher, it’s not what you say or do that matters… It’s what you get your students to do.” In Big Nerd Ranch bootcamps, students are supported as they do hands-on work.

A majority of student time is spent “on task,” doing actual programming in our top-notch guided labs. Students not only get to live and breathe the concepts and material, they overcome a huge barrier to entry by getting experience with the development tools they will be using in practice. By getting hands-on practice with the support of an expert to walk them through issues as they come up, students are better prepared to make applications on their own after the class.

Awesome class materials

I’ve read a lot of technical books and textbooks in my time. Android Programming: The Big Nerd Ranch Guide is by far one of my favorites from both a learner and an instructor perspective. The book is practical and thorough. It is fun to read and has a sense of humor. It has the right mix of basics and challenging material. The guided labs are easy to follow and complete. The fact that the materials are solid allows me to focus more time and energy on my students.

Motivated students

Big Nerd Ranch students are motivated. They come to the Ranch because they want to learn a particular subject. They have taken a whole week away from work, from family, from their daily life, to learn this one subject. Motivated students make for a more focused classroom and increased opportunity to learn from peers. I love hearing the conversations between students as they help and challenge each other.

No grades

Best of all, I don’t have to assign grades. But how do students know if the week was a success? The answer is different for each person. One of my favorite parts of the week-long Big Nerd Ranch course is helping people define what success looks like for them. I help them determine what they want to get out of the week and then remind them of it. As an instructor, I try to help my students assess throughout the process where they are with respect to their goals, and help them adjust their course if necessary.

Students see me as a peer

The Big Nerd Ranch experience helps students see their teacher as a peer. We eat three meals a day together. We hike in the afternoons together. We spend all day in the classroom together.

Being seen as a peer is a huge benefit. It helps students open up to me. It also helps them feel comfortable in asking questions and for help. Rather than being seen as a “sage on the stage,” students begin to see me as a peer or a guide. And I quite like that.

Empowering students to learn

To me, teaching is about empowering people to learn, encouraging them when they want to give up on learning, and challenging them when they think they’ve learned enough. All of this requires getting to know the learner, as well as being open to adjusting your role as a teacher as the needs of the learner changes.

I love to help people define and achieve their learning goals. This is what drove me to be an instructor. Teaching at Big Nerd Ranch offers me the opportunity to help people figure out what they want to know, what they don’t know and how they can close the gap. I hope students find the experience as fulfilling as I do!

The post Standing out from the Crowd at Big Nerd Ranch Bootcamps appeared first on Big Nerd Ranch.

]]>
https://bignerdranch.com/blog/standing-out-from-the-crowd-at-big-nerd-ranch-bootcamps/feed/ 0