Presentation--MoMo Managing Android Fragmentation.key

tibburfrogtownMobile - sans fil

14 déc. 2013 (il y a 3 années et 3 mois)

45 vue(s)

Managing Android
Fragmentation
Carter Jernigan
two forty four a.m. LLC
1
Android 2.1 only
http://developer.android.com/resources/dashboard/platform-versions.html
Only 1.6% of all Android users are running pre 2.0 versions of
Android. Not only is the Android 1.0 market small, but all the
growth is under Android 2.3 or later. So why divert significant
development effort to support less than 2% of your user base?
public

class

AndroidTestActivity

extends
Activity
{

/** Called when the activity is first created. */

@Override

public

void
onCreate(
final
Bundle savedInstanceState)
{

super
.onCreate(savedInstanceState);
setContentView(R.layout.
main
);

// Only for Gingerbread or later

if
(Integer.parseInt(android.os.Build.VERSION.
SDK
) > 9)
{

try
{

final
Class<?> strictModeClass = Class.forName(
"android.os.StrictMode"
);
//$NON-NLS-1$

final
Method enableDefaultsMethod = strictModeClass.getMethod(
"enableDefaults"
);
//$NON-NLS-1$
enableDefaultsMethod.invoke(strictModeClass);
}

catch
(
final
ClassNotFoundException e)
{

throw

new
RuntimeException(e);
}

catch
(
final
SecurityException e)
{

throw

new
RuntimeException(e);
}

catch
(
final
NoSuchMethodException e)
{

throw

new
RuntimeException(e);
}

catch
(
final
IllegalArgumentException e)
{

throw

new
RuntimeException(e);
}

catch
(
final
IllegalAccessException e)
{

throw

new
RuntimeException(e);
}

catch
(
final
InvocationTargetException e)
{

throw

new
RuntimeException(e);
}
}
}
}
The Dalvik virtual machine changed significantly between Android 1.6 and Android 2.0 with respect to
backwards compatibility.
Let’s look at a code example.
SDK 9 (Android 2.3/Gingerbread) introduced “Strict Mode” which prints warnings when apps do things
they shouldn’t do. Strict Mode requires apps opt-in, but the method to opt-in is only available on SDK 9
or later.
This example is compatible with Android 1.5 and later. It checks the SDK level and then uses reflection to
enable Strict Mode for supported versions of Android. This is ugly, complicated, and doesn’t give the
developer compile time checks.
public

class

AndroidTestActivity

extends
Activity
{

/** Called when the activity is first created. */

@Override

public

void
onCreate(
final
Bundle savedInstanceState)
{

super
.onCreate(savedInstanceState);
setContentView(R.layout.
main
);

// Only for Gingerbread or later

if
(android.os.Build.VERSION.
SDK_INT
> 9)
{
StrictMode.enableDefaults();
}
}
}
Android 2.0’s virtual machine is much more lax about handling
classes that it doesn’t recognize. When this is run on API 5
through 8, Dalvik will print out a warning to logcat but
otherwise this runs fine and is much simpler.
2
Single app store
Only distribute your app through a single app store: Android Market.
The first problem is administrative: Every time you update your app you have to upload it to multiple app
stores. That’s a lot of additional overhead, especially considering that many app stores have different
requirements.
In addition, multiple app stores provide a poor user experience.
If users buy your app from a carrier-specific app store, what happens when they switch carriers? What
happens if they move to another country? Here’s what happens: they lose access to their apps and then
they email you for support and demand that you transfer their apps to the Android Market, which isn’t
possible.
3
Be explicit
    
<
supports-screens
       
android:anyDensity
=
"true"
       
android:largeScreens
=
"true"
       
android:normalScreens
=
"true"
       
android:smallScreens
=
"true"
        
android:xlargeScreens
=
"true"
/>
The Android documentation currently states that for apps that target
SDK level 4 or greater, the support-screens entry defaults to true for all
entries. In reality, this behavior is undefined. To ensure your app is
visible to all users, explicitly set supports-screens Android Manifest
entry.
android:hardwareAccelerated
=
"false"
Honeycomb introduced hardware acceleration as an option feature
and ICS turns this on by default. What isn’t well documented is the
fact that hardware acceleration can significantly increase the memory
usage of your application.
As a foreground app, this probably doesn’t matter. But if your
application has a background component you should seriously
consider what happens.

<
activity

android:name
=
".ui.EditActivity"

android:exported
=
"true"

android:icon
=
"@drawable/ic_locale_plugin"

android:label
=
"@string/plugin_name"

android:theme
=
"@style/Theme.Locale.Dark"

android:uiOptions
=
"splitActionBarWhenNarrow"

>

<
intent-filter
>

<
action

android:name
=
"com.twofortyfouram.locale.intent.action.EDIT_SETTING"

/>

</
intent-filter
>

</
activity
>

<
receiver

android:name
=
".receiver.FireReceiver"

android:exported
=
"true"

android:process
=
":background"

>

<
intent-filter
>

<
action

android:name
=
"com.twofortyfouram.locale.intent.action.FIRE_SETTING"

/>

</
intent-filter
>

</
receiver
>
Locale’s plug-in examples run background processing in a different
process that never touches the UI, to ensure the background process
never has the hardware acceleration memory overhead.
4
Scale up and down
Different devices have different characteristics, so your Android app
should be able to scale up and down based on what features are
available.
context.getPackageManager().hasSystemFeature(PackageManager.
FEATURE_SENSOR_ACCELEROMETER
))
“android.hardware.sensor.accelerometer”
<
uses-library

android:name
=
"com.google.android.maps"

android:required
=
"false"

/>
try
{
Class.forName(
"com.google.android.maps.MapActivity"
);
//$NON-NLS-1$
startActivity(
new
Intent(getIntent()).setClass(getApplicationContext(), LocationConditionActivityGoogleMaps.
class
));
}
catch
(
final
Exception e)
{

/*
* A ClassNotFound exception is usually what occurs, but other strange exceptions have also been observed
*/
startActivity(
new
Intent(getIntent()).setClass(getApplicationContext(), LocationConditionActivityNoMaps.
class
));
}
5
Configuration control
6
Unit tests
7
Buy, beg, and borrow
It is important to test as many devices as possible. Buy some devices,
then beg friends, family, and other developers to borrow devices.
Some manufacturers, like Sony Ericsson, have a device loaner
program.
8
Phased rollout
Use Android Market’s multi-APK feature to roll out a new version of
an app to a smaller subset of users initially.
http://developer.android.com/resources/dashboard/platform-versions.html
For example, Android 4.0+ is only 1% of the user base and
would be a great place to start a phased rollout of an app
update.
9
Tools
Android Lint, Findbugs, etc.
http://www.android-permissions.org
/
10
Bugs to watch out for
Samsung Ringtone
Picker Crash
final
Intent pickerIntent =
new
Intent(RingtoneManager.
ACTION_RINGTONE_PICKER
);
pickerIntent.putExtra(RingtoneManager.
EXTRA_RINGTONE_SHOW_DEFAULT
,
false
);
pickerIntent.putExtra(RingtoneManager.
EXTRA_RINGTONE_TYPE
, RingtoneManager.
TYPE_RINGTONE
);
pickerIntent.putExtra(RingtoneManager.
EXTRA_RINGTONE_SHOW_SILENT
,
false
);
startActivity(pickerIntent);
Setting
RingtoneManager.
EXTRA_RINGTONE_SHOW_SILENT
causes a crash on
Samsung Galaxy S/Galaxy S II devices.
Intent security
public

class
AndroidTestActivity
extends
Activity
{

/** Called when the activity is first created. */

@Override

public

void
onCreate(Bundle savedInstanceState)
{

super
.onCreate(savedInstanceState);
startActivity(
new
Intent(Settings.
ACTION_WIFI_SETTINGS
).putExtra(
"serializable"
,

new
CustomSerializable()));
}

private

static

final

class
CustomSerializable
implements
Serializable
{

private

static

final

long

serialVersionUID
= 1L;
}
}
http://code.google.com/p/android/issues/detail?id=16006
Sensor Accuracy
Certain devices like the Kyocera Echo and the Motorola Xoom always
report that the accelerometer is inaccurate but that isn’t true.