1. Trang chủ
  2. » Công Nghệ Thông Tin

Lập trình Androi part 55 pot

8 200 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Handling platform changes
Trường học University of Technology
Chuyên ngành Computer Science
Thể loại Bài viết
Năm xuất bản 2023
Thành phố Hanoi
Định dạng
Số trang 8
Dung lượng 317,43 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Hierarchy Viewer Layout view Changing Resources The core Android team may change resources with an Android upgrade, and those may have unexpected effects in your application.. You also

Trang 1

359

Chapter

Handling Platform

Changes

Android will continue to rapidly evolve over the next few years Perhaps, in time, the rate

of change will decline some However, for the here and now, you should assume that

there will be significant Android releases every 6 to 12 months, and changes to the

lineup of possible Android hardware on an ongoing basis So, while right now, the focus

of Android is phones, soon you will see Android netbooks, Android tablets, Android

media players, and so on

Many of these changes will have little impact on your existing code However, some will

necessitate at least new rounds of testing for your applications, and perhaps changes to

those applications based on the test results

This chapter covers a number of the areas that may cause you trouble in the future as

Android evolves, with some suggestions on how to deal with them

Brand Management

As of the time of this writing, the Android devices that have been released have been

Google Experience phones This means they get the standard Android interface—the

things you find in the emulator—along with the standard roster of add-on applications

like Google Maps and Gmail In turn, manufacturers are allowed to put the “with Google”

brand on the device But not all devices will be this way

Some manufacturers will take Android as a base and change what is included, adding

some of their own applications and perhaps even changing the look and feel (menu

icons, home screen structure, etc.)

Others may use Android solely from the open source repository, and while they may

ship with the standard look and feel, they will lack the commercial add-on applications

38

Trang 2

More Things That Make You Go Boom

Most of the items noted in the previous section focused on hardware changes Now, let’s examine some ways in which Android can cause difficulty to you when the

operating system itself changes

View Hierarchy

Android is not designed to handle arbitrarily complicated view hierarchies Here, view

hierarchy means containers holding containers holding containers holding widgets

The Hierarchy Viewer program, described in Chapter 35, depicts such view hierarchies well, as shown in Figure 38–1 In this example, you see a five-layer-deep hierarchy, because the longest chain of containers and widgets is five (from

PhoneWindow$DecorView through to Button)

Android has always had limits as to how deep the view hierarchy can be In Android 1.5, though, the limit was reduced, so some applications that worked fine on Android 1.1 would crash with a StackOverflowException in the newer Android This, of course, was frustrating to developers who never realized there was an issue with view hierarchy depth and then got caught by this change

The lessons to take from this are as follows:

 Keep your view hierarchies shallow Once you drift into double-digit depth, you are increasingly likely to run out of stack space

 If you encounter a StackOverflowException, and the stack trace looks like it is somewhere in the middle of drawing your widgets, your view hierarchy is probably too complex

Trang 3

Figure 38–1 Hierarchy Viewer Layout view

Changing Resources

The core Android team may change resources with an Android upgrade, and those may

have unexpected effects in your application For example, in Android 1.5, they changed

the stock Button background, to allow for smaller buttons However, applications that

implicitly relied on the former larger minimum size wound up breaking and needing

some UI adjustment

Similarly, applications can reuse public resources, such as icons, available inside of

Android proper While doing so saves some storage space, many of these resources are

public by necessity and are not considered part of the SDK For example, hardware

manufacturers may change the icons to fit some alternative UI look and feel Relying on

the existing ones to always look as they do is a bit dangerous You are better served

copying those resources out of the Android open source project

(http://source.android.com/) into your own code base

Trang 4

applications) allows you to upload only one APK file for each application Hence, you need that one APK file to deal with as many Android versions as possible Many times, your code will “just work” and not require changing Other times, though, you will need

to make adjustments, particularly if you want to support new APIs on new versions while not breaking old versions Let’s examine some techniques for handling these cases

Detecting the Version

If you just want to take different branches in your code based on version, the easiest thing to do is inspect android.os.VERSION.SDK_INT This public static integer value will reflect the same API level as you use when creating AVDs and specifying API levels in the manifest So, you can compare that value to, say, android.os.VERSION_CODES.DONUT

to see whether you are running on Android 1.6 or newer

Wrapping the API

So long as the APIs you try to use exist across all Android versions you are supporting, just branching may be sufficient Where things get troublesome is when the APIs

change, such as when there are new parameters to methods, new methods, or even new classes You need code that will work regardless of Android version, yet lets you take advantage of new APIs where available

There is a recommended trick for dealing with this: reflection, plus a wee bit of caching For example, back in Chapter 8, we used getTag() and setTag() to associate an

arbitrary object with a View Specifically, we used this to associate a wrapper object that would lazy-find all necessary widgets You also learned that about the new versions of getTag() and setTag() that are indexed, taking a resource ID as a parameter

However, these new indexed methods do not exist on Android 1.5 If you want to use this new technique, you need to wait until you are willing to support only Android 1.6 and beyond, or you will need to use reflection Specifically, on Android 1.5, you could associate an ArrayList<Object> as the tag, and have your own getTag()/setTag() pair that takes the index

This seems straightforward enough, so let’s look at APIVersions/Tagger Our activity has

a simple layout, with just a TextView:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

Trang 5

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

<TextView android:id="@+id/test"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

/>

</LinearLayout>

The source code to our Tagger activity looks at the API version we are running, and

routes our getTag() and setTag() operations to either the native indexed one (for

Android 1.6 and above) or to the original nonindexed getTag() and setTag(), where we

use a HashMap to track all of the individual indexed objects:

package com.commonsware.android.api.tag;

import android.app.Activity;

import android.os.Build;

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.widget.TextView;

import java.util.HashMap;

import java.util.Date;

public class Tagger extends Activity {

private static final String LOG_KEY="Tagger";

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

TextView view=(TextView)findViewById(R.id.test);

setTag(view, R.id.test, new Date());

view.setText(getTag(view, R.id.test).toString());

}

public void setTag(View v, int key, Object value) {

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.DONUT) {

v.setTag(key, value);

}

else {

HashMap<Integer, Object> meta=(HashMap<Integer, Object>)v.getTag();

if (meta==null) {

meta=new HashMap<Integer, Object>();

}

meta.put(key, value);

}

}

Trang 6

}

result=meta.get(key);

}

return(result);

}

}

This looks great, and if we build it and deploy it on a Android 1.6 or greater emulator or device, it runs like a champ, showing the current time in the activity

If we build it and deploy it on an Android 1.5 emulator or device, and try to run it, it blows up with a VerifyError VerifyError, in this case, basically means we are referring

to things that do not exist in our version of Android, specifically:

 We are referring to SDK_INT, which was not introduced until Android 1.6

 We are referring to the indexed versions of getTag() and setTag()

Even though we will not execute that code, the classloader still wants

to resolve those methods and fails

So, we need to use some reflection

Take a look at APIVersions/Tagger2 This is the same project with the same layout, but

we have a more elaborate version of the Java source:

package com.commonsware.android.api.tag;

import android.app.Activity;

import android.os.Build;

import android.os.Bundle;

import android.util.Log;

import android.view.View;

import android.widget.TextView;

import java.lang.reflect.Method;

import java.util.HashMap;

import java.util.Date;

public class Tagger extends Activity {

private static final String LOG_KEY="Tagger";

private static Method _setTag=null;

private static Method _getTag=null;

Trang 7

static {

int sdk=new Integer(Build.VERSION.SDK).intValue();

if (sdk>=4) {

try {

_setTag=View.class.getMethod("setTag",

new Class[] {Integer.TYPE,

Object.class});

_getTag=View.class.getMethod("getTag",

new Class[] {Integer.TYPE});

}

catch (Throwable t) {

Log.e(LOG_KEY, "Could not initialize 1.6 accessors", t);

}

}

};

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

TextView view=(TextView)findViewById(R.id.test);

setTag(view, R.id.test, new Date());

view.setText(getTag(view, R.id.test).toString());

}

public void setTag(View v, int key, Object value) {

if (_setTag!=null) {

try {

_setTag.invoke(v, key, value);

}

catch (Throwable t) {

Log.e(LOG_KEY, "Could not use 1.6 setTag()", t);

}

}

else {

HashMap<Integer, Object> meta=(HashMap<Integer, Object>)v.getTag();

if (meta==null) {

meta=new HashMap<Integer, Object>();

v.setTag(meta);

}

meta.put(key, value);

}

}

public Object getTag(View v, int key) {

Object result=null;

if (_getTag!=null) {

try {

Trang 8

v.setTag(meta);

}

result=meta.get(key);

}

return(result);

}

}

First, when the class is initially loaded, the static initialization routines run Here, we see what version of Android we are running, using the old SDK String instead of the new SDK_INT integer If we are on Android 1.6 or newer, we use reflection to attempt to find the indexed getTag() and setTag() methods, and we cache those results Since those methods should not change during the lifetime of our application, it is safe to cache them in static variables

Then, when it comes time to actually use getTag() or setTag(), we look to see if the cached Method objects exist or are null If they are null, we assume we need to use the old versions of those methods If the Method objects exist, we use them instead, to take advantage of the native indexed versions

This version of the application works fine on Android 1.5 and above Android 1.6 and above uses the built-in indexed methods, and Android 1.5 uses our fake version of the indexed methods

There is a little extra overhead for going through the Method-based reflection, but it may

be worth it in some cases, to access APIs that exist in newer versions of Android, rather than restricting ourselves to only the older APIs There are even ways to use this technique for cases where entire classes are new to newer Android versions (see

http://android-developers.blogspot.com/2009/04/backward-compatibility-for-android.html)

Ngày đăng: 01/07/2014, 21:20

TỪ KHÓA LIÊN QUAN