Isai FL
「au 発表会 2014 Summer」で発表された isai FL という端末が発表されました。この端末は以下の資料のように640(XXX High DPI)のDensityを持つもので、国内では初めてのXXX High DPI の端末です。
その発売を記念して、該当するAndroid 4.4 のソースコードを調査してみたいと思います。
Android 公式ドキュメントでは、Metrics and Gridsで紹介されています。
4.4ソースコード調査
XXX High DPI が定義、利用されているソースコードは以下のもののようです。
public class DisplayMetrics { /** * Standard quantized DPI for low-density screens. */ public static final int DENSITY_LOW = 120; /** * Standard quantized DPI for medium-density screens. */ public static final int DENSITY_MEDIUM = 160; /** * This is a secondary density, added for some common screen configurations. * It is recommended that applications not generally target this as a first * class density -- that is, don't supply specific graphics for this * density, instead allow the platform to scale from other densities * (typically {@link #DENSITY_HIGH}) as * appropriate. In most cases (such as using bitmaps in * {@link android.graphics.drawable.Drawable}) the platform * can perform this scaling at load time, so the only cost is some slight * startup runtime overhead. * * This density was original introduced to correspond with a * 720p TV screen: the density for 1080p televisions is * {@link #DENSITY_XHIGH}, and the value here provides the same UI * size for a TV running at 720p. It has also found use in 7" tablets, * when these devices have 1280x720 displays. */ public static final int DENSITY_TV = 213; /** * Standard quantized DPI for high-density screens. */ public static final int DENSITY_HIGH = 240; /** * Standard quantized DPI for extra-high-density screens. */ public static final int DENSITY_XHIGH = 320; /** * Intermediate density for screens that sit somewhere between * {@link #DENSITY_XHIGH} (320dpi) and {@link #DENSITY_XXHIGH} (480 dpi). * This is not a density that applications should target, instead relying * on the system to scale their {@link #DENSITY_XXHIGH} assets for them. */ public static final int DENSITY_400 = 400; /** * Standard quantized DPI for extra-extra-high-density screens. Applications * should not generally worry about this density; relying on XHIGH graphics * being scaled up to it should be sufficient for almost all cases. */ public static final int DENSITY_XXHIGH = 480; /** * Standard quantized DPI for extra-extra-extra-high-density screens. Applications * should not generally worry about this density; relying on XHIGH graphics * being scaled up to it should be sufficient for almost all cases. A typical * use of this density would be 4K television screens -- 3840x2160, which * is 2x a traditional HD 1920x1080 screen which runs at DENSITY_XHIGH. */ public static final int DENSITY_XXXHIGH = 640;
http://tools.oesf.biz/android-4.4.2_r1.0/xref/frameworks/base/include/androidfw/ResourceTypes.h
enum { DENSITY_DEFAULT = ACONFIGURATION_DENSITY_DEFAULT, DENSITY_LOW = ACONFIGURATION_DENSITY_LOW, DENSITY_MEDIUM = ACONFIGURATION_DENSITY_MEDIUM, DENSITY_TV = ACONFIGURATION_DENSITY_TV, DENSITY_HIGH = ACONFIGURATION_DENSITY_HIGH, DENSITY_XHIGH = ACONFIGURATION_DENSITY_XHIGH, DENSITY_XXHIGH = ACONFIGURATION_DENSITY_XXHIGH, DENSITY_XXXHIGH = ACONFIGURATION_DENSITY_XXXHIGH, DENSITY_NONE = ACONFIGURATION_DENSITY_NONE };
http://tools.oesf.biz/android-4.4.2_r1.0/xref/frameworks/native/include/android/configuration.h
struct AConfiguration; typedef struct AConfiguration AConfiguration; enum { ACONFIGURATION_ORIENTATION_ANY = 0x0000, ACONFIGURATION_ORIENTATION_PORT = 0x0001, ACONFIGURATION_ORIENTATION_LAND = 0x0002, ACONFIGURATION_ORIENTATION_SQUARE = 0x0003, ACONFIGURATION_TOUCHSCREEN_ANY = 0x0000, ACONFIGURATION_TOUCHSCREEN_NOTOUCH = 0x0001, ACONFIGURATION_TOUCHSCREEN_STYLUS = 0x0002, ACONFIGURATION_TOUCHSCREEN_FINGER = 0x0003, ACONFIGURATION_DENSITY_DEFAULT = 0, ACONFIGURATION_DENSITY_LOW = 120, ACONFIGURATION_DENSITY_MEDIUM = 160, ACONFIGURATION_DENSITY_TV = 213, ACONFIGURATION_DENSITY_HIGH = 240, ACONFIGURATION_DENSITY_XHIGH = 320, ACONFIGURATION_DENSITY_XXHIGH = 480, ACONFIGURATION_DENSITY_XXXHIGH = 640,
おまけとしてツールやテストコードも調査
aaptツールのコード
http://tools.oesf.biz/android-4.4.2_r1.0/xref/frameworks/base/tools/aapt/AaptAssets.cpp
bool AaptGroupEntry::getDensityName(const char* name, ResTable_config* out) { if (strcmp(name, kWildcardName) == 0) { if (out) out->density = ResTable_config::DENSITY_DEFAULT; return true; } if (strcmp(name, "nodpi") == 0) { if (out) out->density = ResTable_config::DENSITY_NONE; return true; } if (strcmp(name, "ldpi") == 0) { if (out) out->density = ResTable_config::DENSITY_LOW; return true; } if (strcmp(name, "mdpi") == 0) { if (out) out->density = ResTable_config::DENSITY_MEDIUM; return true; } if (strcmp(name, "tvdpi") == 0) { if (out) out->density = ResTable_config::DENSITY_TV; return true; } if (strcmp(name, "hdpi") == 0) { if (out) out->density = ResTable_config::DENSITY_HIGH; return true; } if (strcmp(name, "xhdpi") == 0) { if (out) out->density = ResTable_config::DENSITY_XHIGH; return true; } if (strcmp(name, "xxhdpi") == 0) { if (out) out->density = ResTable_config::DENSITY_XXHIGH; return true; } if (strcmp(name, "xxxhdpi") == 0) { if (out) out->density = ResTable_config::DENSITY_XXXHIGH; return true; } char* c = (char*)name; while (*c >= '0' && *c <= '9') { c++; } // check that we have 'dpi' after the last digit. if (toupper(c[0]) != 'D' || toupper(c[1]) != 'P' || toupper(c[2]) != 'I' || c[3] != 0) { return false; } // temporarily replace the first letter with \0 to // use atoi. char tmp = c[0]; c[0] = '\0'; int d = atoi(name); c[0] = tmp; if (d != 0) { if (out) out->density = d; return true; } return false; }
holo向けCTS(Compatibility Test Suite)のテストコード
public class DisplayInfoActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.display_info); WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); DisplayMetrics metrics = new DisplayMetrics(); display.getMetrics(metrics); DisplayMetrics dm = getResources().getDisplayMetrics(); int width = Math.round(dm.widthPixels / dm.density); int height = Math.round(dm.heightPixels / dm.density); TextView text = (TextView) findViewById(R.id.text); text.setText(getString(R.string.display_info_text, metrics.densityDpi, getScreenDensityBucket(metrics), width, height)); } private String getScreenDensityBucket(DisplayMetrics metrics) { switch (metrics.densityDpi) { case DisplayMetrics.DENSITY_LOW: return "ldpi"; case DisplayMetrics.DENSITY_MEDIUM: return "mdpi"; case DisplayMetrics.DENSITY_HIGH: return "hdpi"; case DisplayMetrics.DENSITY_XHIGH: return "xdpi"; case DisplayMetrics.DENSITY_XXHIGH: return "xxdpi"; case DisplayMetrics.DENSITY_XXXHIGH: return "xxxdpi"; case DisplayMetrics.DENSITY_TV: return "tvdpi"; default: return "" + metrics.densityDpi; } } }
au Isai FL向けのアプリアイコン
アプリアイコンは、通常の4倍の大きさの192×192 px の必要だそうです。ただ、以下のようにGoogle Play向けに512×512 px のアイコンを作っておいて、そこから各DPIごとのアイコンを生成していると思いますので問題ないかとは思います。アプリの機能を変更しないのに、versionCodeをあげて、google play に apkをアップしなおさないといけないのは少し手間ですね。Google Playにアップした512×512 px アイコンから自動的に各DPIごとのアイコンを生成して、配布するapkにいれてくれればいいのになぁと思ってしまいました。