Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Hello.Android.3rd.Edition.pdf
Скачиваний:
33
Добавлен:
02.02.2015
Размер:
3.24 Mб
Скачать

BUG ON PARADE 265

public int getPointerId(int pointerIndex) { return event.getPointerId(pointerIndex);

}

}

If you try to run the program now, it will work in the 1.6 emulator as well as new versions (2.0 and beyond). On old versions, of course, you’ll lose some functionality. Multi-touch is not supported on 1.6, so you won’t be able to use the pinch zoom gesture to shrink or grow the image. But you will be able to move the image around using the drag gesture.

In a real program, you might have to implement some alternate way to resize the picture when pinch zoom is not available. For example, you could add buttons to zoom in and out.

Just for fun, start up the em15 (1.5 emulator), and run the program there. It looks OK, but try doing the drag gesture. Nothing happens! We’ve discovered a bug in Android 1.5.

13.4Bug on Parade

It turns out that Android 1.5 (Cupcake) has a bug in the ImageView class. The bug prevents the setImageMatrix( ) method from working when the ImageView is in “matrix” mode, which is pretty ironic if you think about it.

Unfortunately, there is no complete list of bugs, so figuring out this was a bug in Android (as opposed to a bug in our code or a misunderstanding of how something works) took a bit of sleuthing. In case you find yourself in a similar situation, here are the steps that I went through:

1.My first suspect was the new code we just added: the WrapMotionEvent and EclairMotionEvent classes. I put in a few logging statements to verify events were being handled correctly and the transformation matrix was created correctly. They turned up no problems, so I began to suspect something was wrong with the ImageView class or matrix manipulation.

2.Next, I checked the release notes4 for each version of Android to see whether there were any breaking changes mentioned that

4. http://d.android.com/sdk/RELEASENOTES.html

BUG ON PARADE 266

might affect the ImageView class. Breaking changes are updates that cause code that was working to stop working, or vice versa. I didn’t find any that seemed related.

3.Then I searched the Android bug database5 for the keywords ImageView and matrix. Unfortunately, the public bug database is incomplete because Google keeps its own private list of bugs, so I didn’t find anything.

4.Next, I searched all the Android Developer Forums6 to see whether anybody else was having the same problem. The groups all have search forms of their own, but the quickest and most accurate way to search the forums is just to use the Google search engine and search the entire Web. Using the same keywords (ImageView and matrix), I found a posting from 2009 that looked exactly the same. Unfortunately, there was no follow-up or workaround posted, but I knew I was on the right track.

5.Finally, I went to the source.7 With a few exceptions, all the code for Android is available in a public repository online. I had a clue about where the source to the ImageView class was located in the source tree because one of the earlier searches had revealed the path name. It was in the platform/frameworks/base.git project, under the core/java/widget directory. I opened the history using the repository’s web interface.8 And there it was, a change made on July 30, 2009, with the comment: “Fix a bug in ImageView: The drawing matrix is not updated when setImageMatrix is called.” This bug fix was performed in between the Cupcake and Donut versions of Android, which explained why the problem happened in 1.5 but not in 1.6.

In almost all cases, you’ll be able to find a solution without resorting to reading the Android source code. But it’s nice to know it’s there if you need it. By studying the code and trying a few things, I was able to create a workaround for the bug.

5. http://b.android.com

6.http://d.android.com/resources/community-groups.html

7.http://source.android.com

8.https://android.git.kernel.org/?p=platform/frameworks/base.git;a=history;f=core/java/android/widget/ImageView.java

ALL SCREENS GREAT AND SMALL 267

Add these lines to the end of the onCreate( ) method in the Touch class:

Download Touchv2/src/org/example/touch/Touch.java

@Override

public void onCreate(Bundle savedInstanceState) {

//...

//Work around a Cupcake bug matrix.setTranslate(1f, 1f); view.setImageMatrix(matrix);

}

By running the program in the emulator using various versions of Android, you can verify that this fixes the problem in Android 1.5 and doesn’t break anything in later versions. Once your program is working with different versions of Android, you should try it at different screen sizes as well.

13.5All Screens Great and Small

Supporting different screen sizes, resolutions, and pixel densities is important because you want your application to look its best on as many Android devices as possible. Unlike the iPhone, which has just one standard screen (OK, three, if you count the iPad and the iPhone 4), Android-powered devices come in all shapes and sizes.

Android will try to scale your user interface to fit the device, but it doesn’t always do a great job of it. The only way to tell is through, you guessed it, testing. Use the emulator skins recommended in Section 13.1, Gentlemen, Start Your Emulators, on page 257 to make sure your program works on the most common sizes. If you need to tweak the layouts or images for particular configurations, you can use suffixes in the resource directory names.

For example, you can put images for high-density displays in the res/ drawable-hdpi directory, medium density in res/drawable-mdpi, and low density in res/drawable-ldpi. All the examples do that for their program icons, which will be shown on the home screen. Graphics that are density-independent (that should not be scaled) go in the res/drawablenodpi directory.

INSTALLING ON THE SD CARD 268

The following is a list of the valid directory name qualifiers, in order of precedence:9

Qualifier

Values

MCC and MNC

Mobile country code and optional mobile net-

 

work code. I don’t recommend using this.

Language and region

Two-letter language and optional two-letter

 

region code (preceded by lowercase r). For

 

example: fr, en-rUS, fr-rFR, es-rES.

Screen dimensions

small, normal, large.

Wider/taller screens

long, notlong.

Screen orientation

port, land, square.

Screen pixel density

ldpi, mdpi, hdpi, nodpi.

Touchscreen type

notouch, stylus, finger.

Keyboard available?

keysexposed, keyshidden, keyssoft.

Keyboard type

nokeys, qwerty, 12key.

Navigation available?

navexposed, navhidden.

Navigation type

nonav, dpad, trackball, wheel.

Screen dimensions

320x240, 640x480, and so on (not recommended

 

by Google but people use it anyway).

SDK version

API level supported by the device (preceded by

 

lowercase “v”). For example: v3, v8.

To use more than one qualifier, just string them together with a hyphen (-) in between. For example, the res/drawable-fr-land-ldpi directory could contain pictures for low-density displays in landscape mode in French.

Note: In versions prior to 2.1, Android had bugs in how it matched these qualifiers. For advice on dealing with quirks like this, see Justin Mattson’s Google I/O presentation.10

13.6 Installing on the SD Card

Starting in Android 2.2, you can specify that your application may be installed on the SD card instead of on the phone’s limited internal memory.

9. See http://d.android.com/guide/topics/resources/resources-i18n.html#best-match for a full explanation of how Android finds the best matching directory.

10. http://code.google.com/events/io/2010/sessions/casting-wide-net-android-devices.html

INSTALLING ON THE SD CARD 269

To do that, add the android:installLocation= attribute to the <manifest> tag in your AndroidManifest.xml file like this:

<manifest ... android:installLocation="auto">

Valid values are auto and preferExternal. I recommend you use auto, which lets the system decide where it should go. Specifying preferExternal requests that your app be installed on the SD card but doesn’t guarantee it. Either way, the user can move your application between internal and external storage with the Settings application.

The attribute will be quietly ignored on older versions of Android. If you leave it off entirely, Android will always put your program in internal storage.

So, why aren’t SD card installs the default? It turns out that there are many situations where external installation is not a good idea. When you plug your phone’s USB cable into your computer to charge it or share files, any running application installed on external storage will be killed. This is especially problematic for home screen widgets, which will simply vanish and never reappear.

Therefore, Google recommends11 that you do not allow external installation of applications that use any of the following features:

Account managers

Alarms

Device administrators

Input method engines

Live folders

Live wallpapers

Services

Sync adapters

Widgets

As Android 2.2 adoption grows, users will expect everything to be installable on the SD card. If you choose not to allow it, be prepared to explain why to your users.

11. http://d.android.com/guide/appendix/install-location.html

FAST -FORWARD >> 270

13.7Fast-Forward >>

Supporting multiple versions of Android running on multiple hardware devices with multiple screen sizes is not easy. In this chapter, we’ve covered the most common issues and solutions to get you started. If you find yourself wanting more, I recommend reading the excellent best-practices document called “Supporting Multiple Screens” at the Android website.12

You’ve worked hard to get your application to this point. Now comes the fun part: letting other people use it. The next chapter will cover how to publish your app to the Android Market.

12. http://d.android.com/guide/practices/screens_support.html

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]