Profile

Cover photo
Joanna Smith
Works at Google
3,701 followers|738,929 views
AboutPostsCollectionsPhotosVideos

Stream

Joanna Smith

Shared publicly  - 
 
 
Put Android’s accessibility services to work as a testing tool
Pro-tip by +Joanna Smith

Android provides a ton of accessibility support, and building that into your app is easy to do. But once you’ve finished making your app accessible, you’ll want to be sure that you’ve done a good job. As with any other app development process, you need to test your app.

The easiest way to do this is to use the accessibility services that are already on your device. Then, just walk through your app, trying every component and cleaning up the bad behavior. The goal here is to be certain that nothing surprises you, and that the app flow is clear and interactive and accessible.

First, consider users who rely on a screen reader. Fortunately, most devices already have a screen reader installed, in the form of TalkBack. TalkBack works by speaking the UI elements aloud as the user focuses on them.

To enable TalkBack, simply navigate to Settings > Accessibility > TalkBack, and either check the box or slide the control to the on position. TalkBack will immediately become active. A tap will bring an element into focus and tell you what it is, a double tap anywhere on the screen will select the current focused element, and swiping in any direction will move the focus in that direction. As a bonus, all of TalkBack’s settings are adjustable (https://goo.gl/vXr6fD), so that you can test any scenario you need to.

Once enabled, you need to start using your app to see if TalkBack understands each UI component. If a button isn’t read aloud, you should give it a label. Any image or graphic needs a content description explaining what it is. And for elements like EditText, you’ll want to use a hint to explain what the user should enter, without interfering with the text input.

Secondly, consider users that rely on focus-based navigation instead of touch navigation. To test focus-based navigation, you’ll want to simulate a directional-pad. This can easily be done in the Android Emulator (https://goo.gl/K49tmG), which has a d-pad by default. But if you’d like to test on a device, you can download the Eyes-Free Keyboard (https://goo.gl/4nJldM).

Once you have your d-pad, simply begin using your app again, testing each component and transition. This will allow you to be certain that your UI elements are all focusable and reachable. And even more importantly, you can confirm that the focus order is logical for your app. Because when a user cannot simply tap on the element they are interested in, they need another way to get there.

Finally, you can rely on accessibility settings to test specific cases that may be relevant to your app. If your app relies on audio, captions are available on devices running Android 4.4 or higher. Magnification gestures and large text will enable you to see what your app looks like when stretched or zoomed. And color inversion and color correction are experimental features on Android 5.0 for low-vision or color-blind users. You may want to check that your app is still clear and comprehensible when the colors have been modified.

So test your app and continue to #BuildBetterApps.
11 comments on original post
4
Add a comment...

Joanna Smith

Shared publicly  - 
 
+Ian Lake explains how to add branding to your app without slowing your users down.
 
Use cold start time effectively with a branded launch theme
Pro-tip by +Ian Lake

When your app isn’t in memory and is launched, that ‘cold start’ can take significantly longer than if your app is already in memory. Depending on the size of your app and what you’re doing in your Application’s onCreate() (as little as possible I hope!), there may be lag between when the user starts your app and your Activity’s onCreate() is actually called. During that time, the window manager makes its best effort to draw a placeholder UI using elements from your theme such as the background and status bar color.

But the background doesn’t have to be a solid color: it can be an opportunity to add a little more personality and branding to your app without slowing down the user through the use of a branded launch screen (http://goo.gl/gp6FDE), allowing your app UI to focus on content rather than additional branding. The key is creating a custom theme that overrides android:windowBackground, then replacing that custom theme with your standard theme before calling super.onCreate().

Assuming you have a theme called AppTheme, your launcher theme would be:
<style name="AppTheme.Launcher">
  <item name="android:windowBackground">@drawable/launch_screen</item>
</style>

This implies that everything about the launcher theme is inherited from your main theme - you’re just changing the windowBackground. One other attribute you may consider changing here is colorPrimaryDark: the status bar color on Android 5.0+ devices. Setting colorPrimaryDark to your main background color can put more emphasis on your branding at the expense of another element changing when transitioning to your final theme.

But drawable/launch_screen can’t be just a simple image, unfortunately - it’ll end up stretched to fill the entire screen. Instead, you can use an XML file such as:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:opacity="opaque">
  <!-- The background color, preferably the same as your normal theme -->
  <item android:drawable="@android:color/white"/>
  <!-- Your product logo - 144dp color version of your app icon -->
  <item>
    <bitmap
      android:src="@drawable/product_logo_144dp"
      android:gravity="center"/>
  </item>
</layer-list>

Make particular note of the android:opacity=”opaque” line - this is critical in preventing a flash of black as your theme transitions.

Then apply your theme to your activity in your AndroidManifest.xml using android:theme="@style/AppTheme.Launcher".

The easiest way to transition back to your normal theme is to call setTheme(R.style.AppTheme) before super.onCreate() and setContentView():
public class MyMainActivity extends AppCompatActivity {
 @Override
  protected void onCreate(Bundle savedInstanceState) {
    // Make sure this is before calling super.onCreate
    setTheme(R.style.Theme_MyApp);
    super.onCreate(savedInstanceState);
    // ...
  }
}


Things to note with this approach:
- No launchpad activity - there’s no delay such as there would be if you were launching a second activity from a dedicated splash screen style activity
- No artificial delays - you’re only using the time that you have, just taking advantage of theming
- No extra overdraw - resetting your theme removes a layer of overdraw compared to having an opaque view with your normal background above the custom windowBackground
- Only for your launcher activity - this isn’t appropriate for deep links into your app or handling a URI, but for launches done through the home screen - the point is to minimize dead time, not to annoy users.
- Fast is best - keeping your app lean and minimizing work done at startup is critical to a good experience, even if that means slightly less time for branding - remember: getting users to the content they care about should be your #1 priority.
- Watch your transition - keep both the number and complexity of your transitions to a minimum by sharing as many elements (colors, etc) as possible to make for a seamless transition straight to content.

#BuildBetterApps  
43 comments on original post
5
1
Ali Ahmed's profile photo
Add a comment...

Joanna Smith
moderator

Development Patterns  - 
 
Here's a good way to make sure your BroadcastReceiver is dependable.
 
Reliable message processing with WakefulBroadcastReceivers
Pro-tip by +Joanna Smith

A common pattern used to process an incoming broadcast is for your BroadcastReceiver to start a service, often times an IntentService, to process the message. But what if that processing never happened?

I ran into this when I was using Google Cloud Messaging to deliver severe weather alerts to affected devices in a weather app: the message would be received and yet the notification wouldn’t fire. Tracing the bug led me to the following scenario:

The device would be idle, just chilling, doing it’s thing on the tabletop, while the screen was off. Then I would send the weather message to the GCM servers, which would pass it along to my device. This causes the device CPU to wake up and trigger onReceive().

The onReceive() method would then get excited to be called up to do its job, and so it would call startService() to trigger my IntentService. But in that moment between onReceive() finishing its work and the IntentService beginning, the CPU was being super protective of my device battery and was going back to sleep. This didn’t happen every time, but only occasionally. And it left me sitting there, staring at my device and wondering where my alert was!

And this, my friends, is the exact reason we created the WakefulBroadcastReceiver [1], a BroadcastReceiver that automatically creates a partial wakelock. So in onReceive(), instead of calling startService(), now I call startWakefulService(), and the system will take care of acquiring and holding the wakelock for me while my IntentService does its job, preventing the device from falling back asleep. Then, when the service is finished, I call completeWakefulIntent() to let the system know that it can release the wakelock because I’m done building my notification.

So, you may be wondering why would anyone ever use a BroadcastReceiver if the super cool WakefulBroadcastReceiver exists. And honestly, it comes down to your use case. How critical is your response to a message? If you are expecting immediate action, like a severe weather notification so that your users are informed of potential danger, you want to depend on that wakelock. But if your response is only relevant while the user is active on their device, you don’t need to worry, and you can stick with the classic BroadcastReceiver.

For more information on receivers, you can check out Managing Device Awake State: https://goo.gl/hU5tiR

[1] - https://goo.gl/GIjGvH

#BuildBetterApps
9 comments on original post
1
1
Санек просто's profile photo
Add a comment...

Joanna Smith

Shared publicly  - 
 
Google I/O 2014 has been announced!  (And this year, registration is going to be simpler.)  I'm excited to meet more Google developers this year, so let me know if you will be attending.
 
Only 126 days until the 7th annual Google I/O, when we come together with amazing developers like you to talk about what's next. On June 25-26, 2014, we’ll be broadcasting live from Moscone West. You can join us in person in San Francisco or remotely, via a live stream and through I/O Extended community events around the world. 

More details to come next month, including registration info. In the meantime, you can check out highlights from last year at https://developers.google.com/events/io/

Also, quick note for those who want to join in person: this year we’re making some changes to registration, so you won’t need to scramble the second registration opens. We'll be implementing a new system, where you can submit your interest to attend Google I/O 2014. Successful applicants will then be randomly selected and notified shortly thereafter. We’ll be following up with more details from +GoogleDevelopers, so stay tuned.
Google I/O 2013 brings together thousands of developers for three days of deep technical content focused on building the next generation of web, mobile, and enterprise applications with Google and open web technologies such as Android, Google Chrome, Google APIs, Google Web Toolkit, App Engine, and more.
14
Joanna Smith's profile photoTejas Jani's profile photoAnanda Mishra's profile photoBrandon K's profile photo
5 comments
 
Hi what type of code do Google Developers write?
Add a comment...

Joanna Smith

Shared publicly  - 
 
We are capable of focusing while working, I promise.  But did you know that aspirin lost its trademark as a war reparation from WWI?  #thankswikipedia
 
Aspirin and heroin lost their status as registered trademarks in the 1919 Treaty of Versailles.

"As part of war reparations specified in the 1919 Treaty of Versailles following Germany's surrender after World War I, Aspirin (along with heroin) lost its status as a registered trademark in France, Russia, the United Kingdom, and the United States, where it became a generic name."

Wikipedia is fun.

http://en.wikipedia.org/wiki/Aspirin#Trademark
http://en.wikipedia.org/wiki/File:Aspirin-B-3D-balls.png
10
Add a comment...

Joanna Smith

Shared publicly  - 
 
Thanks to my dad for helping me take things apart as a kid, instead of getting mad when I couldn't put them back together.  He started me down this tech path.  #AdaLovelaceDay
47
1
Ian Douglas's profile photoNatalie Villalobos's profile photoAndre Speek's profile photoYonatan Bisk (‫יונתן ביסק‬‎)'s profile photo
3 comments
 
Thanks for sharing +Joanna Smith... Sometimes when I see all those youngsters who all want to be a manager or do something in sales or marketing... I fear that in the not-so-distant future there will be a serious lack of people who want to take things apart and work with their hands to put it back together... We need more dads like yours... ;-)
Add a comment...
Have her in circles
3,701 people
mayank sud's profile photo
Erika Schnaps's profile photo
david ehrgott's profile photo
Brian Duff's profile photo
Md Islam's profile photo
张帆's profile photo
Gen Kenneth Tovo's profile photo
KateLynn Feola's profile photo
charles lyles's profile photo

Joanna Smith
moderator

Development Patterns  - 
 
These small changes make a huge difference for users who otherwise may not be able to use your app at all. Just saying.
 
Put Android’s accessibility services to work as a testing tool
Pro-tip by +Joanna Smith

Android provides a ton of accessibility support, and building that into your app is easy to do. But once you’ve finished making your app accessible, you’ll want to be sure that you’ve done a good job. As with any other app development process, you need to test your app.

The easiest way to do this is to use the accessibility services that are already on your device. Then, just walk through your app, trying every component and cleaning up the bad behavior. The goal here is to be certain that nothing surprises you, and that the app flow is clear and interactive and accessible.

First, consider users who rely on a screen reader. Fortunately, most devices already have a screen reader installed, in the form of TalkBack. TalkBack works by speaking the UI elements aloud as the user focuses on them.

To enable TalkBack, simply navigate to Settings > Accessibility > TalkBack, and either check the box or slide the control to the on position. TalkBack will immediately become active. A tap will bring an element into focus and tell you what it is, a double tap anywhere on the screen will select the current focused element, and swiping in any direction will move the focus in that direction. As a bonus, all of TalkBack’s settings are adjustable (https://goo.gl/vXr6fD), so that you can test any scenario you need to.

Once enabled, you need to start using your app to see if TalkBack understands each UI component. If a button isn’t read aloud, you should give it a label. Any image or graphic needs a content description explaining what it is. And for elements like EditText, you’ll want to use a hint to explain what the user should enter, without interfering with the text input.

Secondly, consider users that rely on focus-based navigation instead of touch navigation. To test focus-based navigation, you’ll want to simulate a directional-pad. This can easily be done in the Android Emulator (https://goo.gl/K49tmG), which has a d-pad by default. But if you’d like to test on a device, you can download the Eyes-Free Keyboard (https://goo.gl/4nJldM).

Once you have your d-pad, simply begin using your app again, testing each component and transition. This will allow you to be certain that your UI elements are all focusable and reachable. And even more importantly, you can confirm that the focus order is logical for your app. Because when a user cannot simply tap on the element they are interested in, they need another way to get there.

Finally, you can rely on accessibility settings to test specific cases that may be relevant to your app. If your app relies on audio, captions are available on devices running Android 4.4 or higher. Magnification gestures and large text will enable you to see what your app looks like when stretched or zoomed. And color inversion and color correction are experimental features on Android 5.0 for low-vision or color-blind users. You may want to check that your app is still clear and comprehensible when the colors have been modified.

So test your app and continue to #BuildBetterApps.
11 comments on original post
2
1
김경철's profile photo
Add a comment...

Joanna Smith

Shared publicly  - 
 
BroadcastReceivers should be dependable, you know.
 
Reliable message processing with WakefulBroadcastReceivers
Pro-tip by +Joanna Smith

A common pattern used to process an incoming broadcast is for your BroadcastReceiver to start a service, often times an IntentService, to process the message. But what if that processing never happened?

I ran into this when I was using Google Cloud Messaging to deliver severe weather alerts to affected devices in a weather app: the message would be received and yet the notification wouldn’t fire. Tracing the bug led me to the following scenario:

The device would be idle, just chilling, doing it’s thing on the tabletop, while the screen was off. Then I would send the weather message to the GCM servers, which would pass it along to my device. This causes the device CPU to wake up and trigger onReceive().

The onReceive() method would then get excited to be called up to do its job, and so it would call startService() to trigger my IntentService. But in that moment between onReceive() finishing its work and the IntentService beginning, the CPU was being super protective of my device battery and was going back to sleep. This didn’t happen every time, but only occasionally. And it left me sitting there, staring at my device and wondering where my alert was!

And this, my friends, is the exact reason we created the WakefulBroadcastReceiver [1], a BroadcastReceiver that automatically creates a partial wakelock. So in onReceive(), instead of calling startService(), now I call startWakefulService(), and the system will take care of acquiring and holding the wakelock for me while my IntentService does its job, preventing the device from falling back asleep. Then, when the service is finished, I call completeWakefulIntent() to let the system know that it can release the wakelock because I’m done building my notification.

So, you may be wondering why would anyone ever use a BroadcastReceiver if the super cool WakefulBroadcastReceiver exists. And honestly, it comes down to your use case. How critical is your response to a message? If you are expecting immediate action, like a severe weather notification so that your users are informed of potential danger, you want to depend on that wakelock. But if your response is only relevant while the user is active on their device, you don’t need to worry, and you can stick with the classic BroadcastReceiver.

For more information on receivers, you can check out Managing Device Awake State: https://goo.gl/hU5tiR

[1] - https://goo.gl/GIjGvH

#BuildBetterApps
9 comments on original post
8
Add a comment...

Joanna Smith

Shared publicly  - 
 
Some poodles are just too cute not to let them nap all afternoon.
28
1
harmeet bahra's profile photoCristina Noland's profile photoSaif Ansari's profile photoEmad Omar's profile photo
6 comments
 
salodo  donda to astas drmyano
Add a comment...

Joanna Smith

Shared publicly  - 
 
Mondays are hard. #poodlelife
18
1
Emad Omar's profile photo
Add a comment...

Joanna Smith

Shared publicly  - 
 
Happy December from the Texas highways! The horizon is so flat that you can see Christmas approaching. Or perhaps that is simply the music coming from KITZ 106.7.
19
Joanna Smith's profile photoDavid Farrell (Masonicmoron)'s profile photoSasch Mayer's profile photoDJ Bourassa's profile photo
5 comments
 
Merry Christmas, From Zeli
New Hampshire. 
Add a comment...

Joanna Smith

Shared publicly  - 
 
Pro tip: Don't mix up the cube before taking a good look at it.  This only took me forever to solve.
38
2
John Sheu's profile photojoe ikhsan's profile photoBrad Golden's profile photoStephen Harris (TrackMasterSteve)'s profile photo
4 comments
 
:)
Add a comment...
Joanna's Collections
People
Have her in circles
3,701 people
mayank sud's profile photo
Erika Schnaps's profile photo
david ehrgott's profile photo
Brian Duff's profile photo
Md Islam's profile photo
张帆's profile photo
Gen Kenneth Tovo's profile photo
KateLynn Feola's profile photo
charles lyles's profile photo
Work
Employment
  • Google
    DPE, present
Links
Story
Tagline
You had me at "Hello, World!"
Introduction
I am a Developer Programs Engineer at Google, working with the Google+ development community.

I recently graduated from the University of Texas at Austin, having studied Computer Science, with a thesis based in CS Education.

I love learning new trivia, and trying to challenge (read: scare) myself.
Bragging rights
avid reader, adequate bowler
Basic Information
Gender
Female