Understanding Android Resources android application development for for dummies

165

Chapter 7: Turning Your Application into a Home-Screen Widget

Figure 7-2: The two states of the app widget you’re about to build. Silent mode is enabled. Phone is in regular mode. Working with remote views When dealing with Android, you should remember that Android is based on the Linux 2.6 kernel. Linux comes with some of its very own idioms about security, and the Android platform inherits those idioms. For example, the Android security model is heavily based around the Linux user, file, and process security model. Each application in Android is usually associated with a unique user ID. All processes run under a particular user. This prevents one application from modifying the files of another application — which could result in a malicious developer injecting code into another app. Because the home screen is actually an application that is currently running on the Android device — hosted by the Android system, not you — it would not be feasible to allow you as a developer to modify actual running code on the home screen because a malicious developer could do some really evil things, such as shut down your home screen. How would you use your phone then? This is a big issue. The Android engineers still wanted to give you a way to access the home screen and modify the contents of a particular area of the home screen from your app- lication. Therefore, they decided to handle the problem by implementing what is known as the RemoteView architecture. This architecture allows you to run code inside your application, completely away from the home screen applica- tion, but still allowing you to update a view inside the home screen. The end result is that no arbitrary code can be run inside the home screen application — all your app widget code runs within your application. This app widget stuff may sound confusing, but imagine it like this: The user taps the home-screen app widget in this case, an icon on the home screen that he added. This action fires off a request to change the ringer mode. This request is addressed to your application. Android routes that request to your application, and it processes the request. During the processing of that request, your application instructs the Android platform to change the ringer mode as well as update the app widget on the home screen with a new image to indicate that the ringer mode has been changed. None of this code was run 166 Part II: Building and Publishing Your First Android Application in the home-screen application — all of it was run remotely in your application with Android messaging performing the message routing to the appropriate application. Remote views are a little bit of magic mixed with innovative engineering. Remote views known as the RemoteView class in the Android platform allow your application to programmatically supply a remote UI to the home screen in another process. The app widget code is not an actual activity as in previous chapters, but an implementation of an AppWidgetProvider. As stated in the previous example, Android routes messages to the appropri- ate application. When Android routes a message to your application from the home screen, your implementation of the AppWidgetProvider class is where you handle the message. Using AppWidgetProviders The AppWidgetProvider class provides the hooks that allow you to pro- grammatically interface with the app widget on the home screen. When the user interacts with the app widget, messages are sent form the home screen app widget to your application through what is known as a broadcast event. Through these broadcast events, you can respond to when the app widget is updated, enabled, disabled, and deleted. You can also update the look and feel of the app widget on the home screen by providing a new view. Because this view is located on the home screen and not within your actual running application, you will use what is known as a RemoteView to update the layout on the home screen. All the logic that determines what should happen is initiated through an implementation of an AppWidgetProvider. The app widget framework can be thought of as a translator for a conversa- tion between two entities. Imagine that you need to speak to someone who knows Italian, but you don’t know Italian. How would you do this? You’d find a translator. The translator would accept your input, translate it to Italian, and relay the message to the native Italian speaker. The same goes for the app widget framework. This framework is your translator. Here’s a great analogy: When the Italian native the home screen, in this case needs to let you know that something has happened such as a button click, the translator the app widget framework and the Android system translates that into a message that you can understand a tap occurred on a particular button. At that time, you can respond with what you’d like to do such as changing the app widget background color to lime green, and the translator the app widget framework relays the message to the native Italian speaker through the Android system to the home screen. The home screen updates the view to have a background color of green. 167

Chapter 7: Turning Your Application into a Home-Screen Widget

Updating the view is about the only thing you can do in regard to app widgets. App widgets can only accept input from tap-type events. You do not have access to other basic input widgets, such as an editable text box, drop-down lists, or any other input mechanism when working within an app widget. Working with Pending Intents When the user needs to interact with your application, she will communicate through the system using the Android messaging architecture as described previously. Because of this, you will not be immediately notified when the user taps the app widget. However, this does not mean you cannot be notified when a click event happens on your app widget — it’s just done a little differently. App widget click events contain instructions on what to do when a click event happens through the use of the PendingIntent class in the Android framework. Pending intents are an implementation of the Intent class in Android, as explained in the following section. Understanding the Android intent system Before you go any further, you should understand what an Intent object is and why they’re used. An Intent object in Android is, well, exactly that: an intent. The best way to think about intents is to envision yourself turning on a light with a light switch. The action of your intent is to turn on the light, and to do so, you flip the switch to the On position. In Android, this would correlate to creating an instance of the Intent class with an Action in it specifying that the light is to be turned on, as shown here: Intent turnLightOn = new Intent“TURN_LIGHT_ON”; This intent would be fired off into the Android messaging system as I describe in Chapter 1, and the appropriate activity or various different Activity objects would handle the Intent if many activities respond, Android lets the user choose which one to do the work. However, in the physical world, an electrical connection is made by positioning the switch to the On posi- tion, resulting in the light illuminating. In Android, you have to provide code to make the same type of thing happen in the form of an activity. This would be an activity that could be named TurnLightOnActivity that responds to the turnLightOn intent. If you’re working with an app widget, you must handle the intent in a BroadcastReceiver. An AppWidgetProvider is an 168 Part II: Building and Publishing Your First Android Application instance of a BroadcastReceiver with a few extra bells and whistles that wire up a lot of the app widget framework for you. The BroadcastReceiver object is responsible for receiving broadcast messages. The AppWidgetProvider is essentially a translator. Therefore, the AppWidgetProvider handles the intent from the home screen and responds with the appropriate result that you determined through your code inside of your custom AppWidgetProvider. The AppWidgetProvider does not work with any intent, though. If you want to receive input from your app widget, you need to use what’s called a PendingIntent. A PendingIntent contains a child Intent object. At a high level, a pending intent acts just like a regular intent. To understand what a PendingIntent is, you need to fully grasp the basic Intent class. As stated in Chapter 1, an intent is a message that can carry a wide variety of data that describes an operation that needs to be performed. Intents can be addressed to a specific activity or broadcast to generic category of receivers known as BroadcastReceivers which, as you know, an AppWidgetProvider is. The Intent, Activity, and BroadcastReceiver system is reminiscent of the message bus architec- ture where a message is placed onto a message bus and one or many of the endpoints on the bus respond to the message if and only if they know how to. If each endpoint has no idea how to respond to the message, or if the message was not addressed to the endpoint, the message is ignored. An intent can be launched into the message bus system a couple of ways: ✓ To start another activity, you would use the startActivity call. The startActivity accepts an Intent object as a parameter. ✓ To notify any interested BroadcastReceiver components, you would use the sendBroadcast call, which also takes an intent as a parameter. ✓ To communicate with a background service covered later in this chapter, you would use the startService or bindService call, which both take intents as parameters. An activity can be thought of as the glue between various components of the application because it provides a late-binding mechanism that allows inter intra-application communication. Understanding intent data An intent’s primary data is as follows: ✓ Action: The general action to be performed. A few common actions include ACTION_VIEW, ACTION_EDIT, and ACTION_MAIN. You can also provide your own custom action if you choose to do so. 169

Chapter 7: Turning Your Application into a Home-Screen Widget