Working with the Android Framework Classes

You're now getting into the good stuff: the real nitty-gritty of Android development — the Android framework classes! Yes, activities, views, and widgets are integral parts of the system, but when it comes down to it, they're plumbing and they're required in any modern operating system (in one capacity or another). The real fun is just about to start.

In the following section, you add a class to your app that determines whether the device's brightness setting is currently in a daytime mode (bright) or in evening mode (dim) and that sets the brightness to the other mode. At that point, you can start toggling the device brightness.

To add these classes, you could type all of this into the MainActivity.java file — but then the application would start to get long and complicated. My grandparents used to remind me that the key to keeping anything clean is good organization, and I believe the same is true for code. To keep things clean, then, you are going to create another Java file in your application that will house the code for implementing the brightness toggling logic.

Retrieving and setting screen brightness

Add a new file with the name of BrightnessHelper.java to your src/ folder. Inside of this class, you are going to add two static methods with the method names setCurrentBrightness and getCurrentBrightness. The basic code for the class should look like this (here I exclude the specifics of the two methods — I get to these later — and I exclude the import statements for brevity):

public class BrightnessHelper {

    public static void setCurrentBrightness(Activity activity, int brightness) {

    }

    public static int getCurrentBrightness(Context context) {

    }
}

The two methods in the BrightnessHelper class file are static methods because they do not need to maintain any application state within them. The contents of each method will only need to get or set the current brightness of the device.

Now that you have a sense of how this class should look, you can begin filling in the methods. Logically speaking, before you can know how you should change the brightness, you need to determine the current brightness of the device. The first method you add is the getCurrentBrightness method. In your BrightnessHelper.java class, change your getCurrentBrightness method to look like Listing 7-2.

Listing 7-2: Retrieving the current brightness

public static int getCurrentBrightness(Context context) {
    int brightness = 0;                                              →2
    try {                                                            →3
      brightness =
            Settings.System.getInt(context.getContentResolver(),
            Settings.System.SCREEN_BRIGHTNESS);                      →6
    } catch (SettingNotFoundException e) {                           →7
        Log.e(context.getPackageName(), e.getMessage(), e);          →8
    }
    return brightness;                                              →10
}

Here's what these lines of code do:

→2 This line defines the brightness variable. When the system returns this variable, on line 4, it will contain an integer value for the brightness setting. Here you set the default value to zero so that, in a worst-case scenario (if, say, an error occurs in the next few lines of code), the screen would become brighter, rather than dimmer.
→3 The beginning of a try/catch block. A try/catch block acts as a safety mechanism for your code. When an error occurs within the try block, the catch block catches it (if you specify the exception type) and then allows you to perform some sort of action. In this instance, line 3 is the beginning of the try block and line 6 is the beginning of the catch block.
→6 This line retrieves the brightness from the Android system. You are delving into the Setttings object and retrieving an integer value for the setting whose identifier is Settings.System.SCREEN_BRIGHTNESS. When importing this class, please use the import android.provider.Settings.
→7 On this line the catch block is instantiated and begins seeking any exception of type SettingNotFoundException. If the exception is any other type of exception, the method will fail and the exception will bubble up the stack until the application is stopped (the application crashes). The reason you are only looking for the SettingNotFoundException is that this is the only logical exception that could be thrown here. If any other exception occurs, something strange has happened and the developer should investigate. Letting the application fail at this point allows the developer to review the logs to determine the cause.
→8 This line logs the exception caught by the catch block to the Android error log. The log helps the developer (you) debug the code. (I cover debugging later in this chapter.)
→10 This line returns the brightness value determined in line 4 back to the calling code at this point. If the screen brightness is 42, then a value of 42 is returned. If the value is 76, then 76 will be returned.

Setting the current screen brightness is a little more complicated, but this process is nothing that should scare you off by now (heck, you're almost a seasoned pro by this point!). Replace the setCurrentBrightness method with the code shown in Listing 7-3.

Listing 7-3: Setting the screen brightness

public static void setCurrentBrightness(Activity activity,
    int brightness) {

    // Change the screen brightness mode to Manual
    Settings.System.putInt(activity.getContentResolver(),
        Settings.System.SCREEN_BRIGHTNESS_MODE,
        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);                        →7

    // Set the screen brightness for the system.
    Settings.System.putInt(activity.getContentResolver(),
        android.provider.Settings.System.SCREEN_BRIGHTNESS,
        brightness);                                                          →12

    // Adjust the current window brightness to reflect the new system brightness.
    LayoutParams params =
        activity.getWindow().getAttributes();                                 →16

    // Brightness is determined from values of 1 through 255
    if(brightness == 255) {
                                                                              →19
        params.screenBrightness = 1.0f;
                                                                              →20
    } else {
        params.screenBrightness = 0.2f;
                                                                              →22
    }

    activity.getWindow().setAttributes(params);
                                                                              →23
}

These lines do the following:

→7 Whoa! This line is doing a whole bunch of things. Here is the breakdown. The Settings.System.putInt() method requires a ContentResolver object to do its job. A ContentResolver object is a built-in Android mechanism that can access and modify data outside of an application — in this case, the settings storage mechanism (think database). In other words, the putInt() method needs a storage mechanism, and it accesses it using the activity.getContentResolver() method. (This method is passed in as a method parameter from the calling code. The code that calls this method will be your MainActivity.java file, as you see later when you tie everything together.) The putInt() method tells Android to update the SCREEN_BRIGHTNESS_MODE setting to SCREEN_BRIGHTNESS_MODE_MANUAL. This update allows you to manually control the brightness, so Android's automatic screen brightness code won't interfere with what you're doing.

image ContentResolver objects are an intricate part of Android and are part of the content provider model. For more about them, look in the documentation here: http://d.android.com/guide/topics/providers/content-providers.html.

→12 This line does something very similar to line 4, except that instead of modifying a setting's mode it modifies a setting's value. The brightness value is passed into this call along with the name of the setting to be modified — SCREEN_BRIGHTNESS. (The brightness variable comes from the MainActivity.java file, as you see later.)

Even though this line updates the system's screen brightness setting, it won't adjust the brightness level in your currently running window. The reason is because your application, when launched, inherits its screen brightness value from the system screen brightness setting. Your app won't track updates to the system settings, however, and it won't reflect these changes automatically. You have to manually update it. The next few lines do this for you.

→16 This line retrieves the layout parameters for the window. The next few lines of code determine whether the window's current brightness should be increased or decreased. Please use the import from android.view.WindowManager.LayoutParams for the import statement.
→19 This line determines whether the system brightness is equivalent to 255.
→20 If the system brightness level is 255 (bright), then this line changes the current window's screen brightness parameters to 1.0f (full brightness). The window brightness is a different value than the system brightness. The window brightness is a value from 0 to 1 (think percentages) while the system setting relies on values from 0 to 255.
→22 If the system brightness level is not 255, then this line sets the current window's screen brightness parameter to 0.2f (20% brightness).
→23 This line updates the current window's layout parameters. Because you updated the screen brightness value, the brightness will now be changed on the device.

This class is now complete! The application will now change the system brightness as well as the brightness on the currently active application window.

Toggling screen brightness

Now that you have a class that handles getting and setting the screen brightness of the device, you can implement the logic that determines whether to make the screen bright or dim. You do this in the MainActivity.java file. Open that file now and replace the contents with the code shown in Listing 7-4.

Listing 7-4: The Toggle Logic

public class MainActivity extends Activity {

    ToggleButton tb;
    TextView tv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        tb = (ToggleButton)findViewById(R.id.toggleButton);
        tv = (TextView)findViewById(R.id.currentBrightness);

        tb.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                int currentBrightness =
                                                           →17
                BrightnessHelper.getCurrentBrightness(MainActivity.this);
                if(currentBrightness > 51) {
                    // Dim it to 20 %. 20% of 255 is 51
                 BrightnessHelper.setCurrentBrightness(MainActivity.this, 51);
                                                           →21
               } else {
                   // Push it back to full brightness
                 BrightnessHelper.setCurrentBrightness(MainActivity.this, 255);
                                                           →24
               }
            }
        });
    }
 }

That's a lot of new stuff happening! Following is a brief explanation of what each new section of code does:

→17 This line retrieves the current brightness level so you can determine whether or not you should make the screen bright or dim.
→21 If the retrieved brightness value was greater than 51 (20% of the maximum brightness value of 255 is 51), this sets the current brightness to 20% — a comfortable brightness setting for evening use.
→24 If the retrieved brightness value was not greater than 51, this line sets the screen brightness 255.

Congratulations! You've now added code to make the screen toggle back and forth between bright and dim. The last step is to let the user know that something happened!

Adding Visual Feedback

At this point, your application does what it needs to do. However, it's not very user friendly. The application is missing a few key components to make it usable:

  • A way to inform the user that something has happened.
  • A way to let the user know what state the device is in. Dim or bright? (That is, 20% brightness or 100% brightness?)
  • A way to update the information about the state of the device when the button is clicked.

All of these are pretty simple to implement. You just need to update the state of the ToggleButton as “On” when the screen is dim, and “Off” when the screen is bright. You also must update the TextView directly below the ToggleButton to reflect which brightness percentage the device is in (either 20% or 100% brightness).

To do this, add the code in Listing 7-5 to the MainActivity.java file.

Listing 7-5: Providing the user with feedback through the user interface

public class MainActivity extends Activity {

    ToggleButton tb;
    TextView tv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        tb = (ToggleButton)findViewById(R.id.toggleButton);
        tv = (TextView)findViewById(R.id.currentBrightness);

        tb.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
             int currentBrightness =
             BrightnessHelper.getCurrentBrightness(MainActivity.this);
             if(currentBrightness > 51) {
                 // Dim it to 20 %. 20% of 255 is 51
               BrightnessHelper.setCurrentBrightness(MainActivity.this, 51);
               renderUi(51);                                                             →22
             } else {
                 // Push it back to full brightness
              BrightnessHelper.setCurrentBrightness(MainActivity.this, 255);
              renderUi(255);                                                             →26
             }
            }
         });

         int initialBrightness =

             BrightnessHelper.getCurrentBrightness(this);
                                                                                         →32
         renderUi(initialBrightness);
                                                                                         →33
    }

    private void renderUi(int brightness) {                                              →36
      if(brightness <= 0) {
          tv.setText(“Default”);
                                                                                         →38
      } else {
          tv.setText(((brightness / 255.0f)*100) + “%”);
                                                                                         →40

      }

      if(brightness == 51) {
          tb.setChecked(true);
                                                                                         →44
       } else {
          tb.setChecked(false);
                                                                                         →46
       }
   }
}

These lines do the following:

→22 This line calls the renderUi method with the value of 51 for the brightness. (The renderUI method initializes the TextView and ToggleButton on the app to the correct state.)
→26 This method calls the renderUi method with the value of 255 for the brightness.
→32 This line gets the initial brightness of the device. This line executes when the application is started; it retrieves the brightness value so your application can set the brightness properly and display the correct value.
→33 This method calls the renderUi method with the current brightness value so that the screen can initialize properly.
→36 This line defines the renderUi method.
→38 If the brightness is less than or equal to 0, the value of “default” will be placed into the TextView. This may happen if your application encounters an exception when retrieving the value from the getCurrentScreenBrightness() method.
→40 This line sets the text of the current brightness level. This lets the user know what state the dimmer is in. To get a correct percentage, you divide the brightness value by 255 (the max brightness). Multiplying the result by 100 (to eliminate the fraction) and appending a % symbol produces a value like 20% or 100% for the TextView.
→44 If the brightness value is set to 51, then this line sets the ToggleButton attribute checked to true. This causes the ToggleButton to have an “On” state. At this point the “Dimmer On” text will be shown on the ToggleButton.
→46 If the brightness is 255, this line sets the ToggleButton attribute checked to false. This causes the ToggleButton to be in an “Off” state. At this point the “Dimmer Off” text will be shown on the ToggleButton.

Obtaining permission to change system settings

Before you can compile and install your application, you must update the AndroidManifest.xml file to include the requested application permissions that this application needs to operate. The AndroidManifest.xml file declares what is in your application and what permissions are required for the application to run.

Each application in Android runs within its own process space (sometimes called a sandbox) in the Android operating system. This allows the application to perform its work without interfering with other applications on the device. Sometimes, however, your application needs to use parts of the device that the user might be interested in knowing about. A common example would be the Internet permission (if your app needs to access the Internet for any reason). Your application will not be using the Internet, so you do not have to worry about Internet permission. However, this application is changing system settings, so you need to update the AndroidManifest.xml file to inform the user of this. When a user installs an application from the Android Market, he is informed of the requested permissions this application requires and can decide whether to install the application. The user does not have the option to decide that an application can have one permission over another. The Android Market does not offer that level of granularity because, if it did, your app would not work. (It would crash because it would not have sufficient permission at run time.)

To add the appropriate permission to your application, open the AndroidManifest.xml file by double-clicking it. Select the AndroidManifest.xml tab at the bottom of the screen to see the xml definition. Your file should look similar to Listing 7-6. You need to add one line, the bold line shown in Listing 7-6.

Listing 7-6: The Updated AndroidManifest.xml File with Permissions Added

<?xml version=“1.0” encoding=“utf-8”?>
<manifest xmlns:android=“http://schemas.android.com/apk/res/android”
    package=“com.dummies.android.screeenbrightnesstoggle”
    android:versionCode=“1” android:versionName=“1.0”>
    <uses-permission android:name=“android.permission.WRITE_SETTINGS”></uses-
              permission>
    <application android:icon=“@drawable/icon” android:label=“@string/app_name”>
        <activity android:name=“.MainActivity” android:label=“@string/app_name”>
            <intent-filter>
                <action android:name=“android.intent.action.MAIN” />
                <category android:name=“android.intent.category.LAUNCHER” />
            </intent-filter>
        </activity>
        <activity android:name=
           “com.dummies.android.screeenbrightnesstoggle.ToggleActivity”
            android:theme=“@android:style/Theme.Translucent” />
    </application>
    <uses-sdk android:minSdkVersion=“11” />
</manifest>

With this permission in place, you can run the application.

image Forgetting to add permission to your application will not prevent the code from compiling. However, when the application is deployed to the end user's device it will crash when it executes the code that requires that particular permission to run.

Congratulations! You've coded your first Android application!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.205.57