2011年8月19日金曜日

Android 3.2 でサポートされた Zoom to fill screen 機能

Android 3.2 から、Android 3.0 向けではなくかつ xlarge をサポートしていないアプリを起動すると、System bar に画面のストレッチみたいなアイコンがでます。このアイコンをタップすると、Stretch to fill screen と Zoom to fill screen のいずれをか選ぶことができます。

こんなやつ


詳しくは
Android Developers Blog: New Mode for Apps on Large Screens -

とか

Declaring Tablet Layouts for Android 3.2 | Supporting Multiple Screens | Android Developers -

にありますが、まとめると

■ Stretch to fill screen

通常のモード。Android の多解像度対応のルールに従って画面のレイアウトが決まる(リサイズされる)。

画像やレイアウトなどは、その解像度&画面サイズの識別子がついたものが使われる (= drawable-hdpi, とか layout-xlarge が使われる)

■ Zoom to fill screen

アプリを normal/mdpi スクリーン(だいたい 320dp x 480dp)に描画した場合のものを画面に拡大して表示する。

電話に描画したものを 200 % ズームしたと想像すればよい。

画像やレイアウトなどは、normal /mdpi の場合のものが使われる (= drawable-hdpi があったとしても、drawable-mdpi や layout-normal が使われる)ので、画素化(pixelated)された感じになる。ピクセルが目立つというかがたがたしてる感じかな。


■ Zoom to fill screen が出ない条件

 ・ AndroidManifest.xml で android:minSdkVersion
   11 以上を指定している
 ・ AndroidManifest.xml で android:targetSdkVersion
   11 以上を指定している
 ・ AndroidManifest.xml で以下を指定している
  1. <manifest ... >  
  2.     <supports-screens android:xlargeScreens="true" />  
  3.     ...  
  4. </manifest>  

 のどれか1つでも満たしている場合、Zoom to fill screen は出ない
 (= System bar に画像のストレッチみたいなアイコンがでない)


■ Zoom to fill screen が出る条件

 Zoom to fill screen が出ない条件を満たしていない場合



左が Stretch to fill screen、右が Zoom to fill screen


# Honeycomb で画面がすっかすかーになってしまった
# アプリにはいいモードですね。
# normal/mdpi の拡大なのでどのくらいピクセル化が
# 目立つのかちょっと気になるなぁ。




2011年8月18日木曜日

Android FLAG_DISMISS_KEYGUARD と FLAG_SHOW_WHEN_LOCKED を使う

KeyguardManagerexitKeyguardSecurely() メソッド及び newKeyguardLock() メソッドと、サブクラスの KeyguardManager.KeyguardLockdeprecated になっています。

これらのメソッドの代わりに WindowManager.LayoutParams クラスの FLAG_DISMISS_KEYGUARDFLAG_SHOW_WHEN_LOCKED を使うことが推奨されています。

■ FLAG_DISMISS_KEYGUARD

 このフラグが設定されると、secure lock keyguard でない場合、ウィンドウによって keyguard が表示されなくなる。security が必要でない keyguard では、ユーザーが他のウィンドウに移動したときに再表示されない(反対に FLAG_SHOW_WHEN_LOCKED では、secure、non-secure 両方の key guard を一時的に隠して、ユーザーがこれらを隠さない設定の他の UI に移動したときに再表示する。

 FLAG_SHOW_WHEN_LOCKED が同時に設定されていないと、keyguard が現在アクティブでユーザーより secure な場合(= unlock pattern を要求している場合)、ウィンドウを表示する前に lock pattern を確認する必要がある。

■ FLAG_SHOW_WHEN_LOCKED

 スクリーンがロックされたときに Windows に表示させるための特別なフラグで、このフラグをセットすると、アプリケーションウィンドウが key guard や他のロックスクリーンよりも優先される。
 
 FLAG_KEEP_SCREEN_ON と組み合わせて使うことで、画面をオンした後、 key guard を表示する前に直接ウィンドウを表示できる。
 
 FLAG_DISMISS_KEYGUARD と組み合わせて使うことで、自動で non-secure keyguards を表示させないようにできる。このフラグは一番上の full-screen window にのみ適用される。


関連するフラグ

FLAG_ALLOW_LOCK_WHILE_SCREEN_ON

FLAG_KEEP_SCREEN_ON




  1. public class KeyguardSampleActivity extends Activity {  
  2.   
  3.     @Override  
  4.     public void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.main);  
  7.           
  8.         Window window = getWindow();  
  9.           
  10.         // lock pattern を設定していても、  
  11.         // このアプリ起動中は画面オン時にロックはでない  
  12.         // 別のアプリやホームに移動するときにロックがでる  
  13.         window.setFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,   
  14.                 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);  
  15.   
  16.         // lock pattern を設定していない場合、  
  17.         // このアプリ起動中は画面オン時にロックはでない  
  18.         window.setFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD,   
  19.                 WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);  
  20.     }  
  21. }  



■ まとめ

1. lock pattern あり、FLAG_SHOW_WHEN_LOCKED

 このアプリ起動中は画面オン時にロックはでない
 別のアプリやホームに移動するときにロックがでる


2. lock pattern あり、FLAG_DISMISS_KEYGUARD

 普通にロックがでる


3. lock pattern あり、FLAG_SHOW_WHEN_LOCKED, FLAG_DISMISS_KEYGUARD

 このアプリ起動中は画面オン時にロックはでない
 別のアプリやホームに移動するときにロックがでる


4. lock pattern なし、FLAG_SHOW_WHEN_LOCKED

 このアプリ起動中は画面オン時にロックはでない
 別のアプリやホームに移動するときにロックがでる


5. lock pattern なし、FLAG_DISMISS_KEYGUARD

 このアプリ起動中は画面オン時にロックはでない
 別のアプリやホームに移動するときもロックはでない


6. lock pattern なし、FLAG_SHOW_WHEN_LOCKED, FLAG_DISMISS_KEYGUARD

 このアプリ起動中は画面オン時にロックはでない
 別のアプリやホームに移動するときもロックはでない



Android Keygurad が外されたことを検知する

ロックを設定している場合、Intent.ACTION_SCREEN_ON だと画面がオンになった状態で通知がくるので、ロックが外れる前に通知がきてしまいます。画面がオンになったあと、ロックが外れた時に通知を受け取るには Intent.ACTION_USER_PRESENT を拾うようにします。

  1. public class UserPresentSampleActivity extends Activity {  
  2.   
  3.     private static final String TAG = "UserPresentSampleActivity";  
  4.       
  5.     @Override  
  6.     public void onCreate(Bundle savedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.         setContentView(R.layout.main);  
  9.     }  
  10.       
  11.     @Override  
  12.     protected void onResume() {  
  13.         super.onResume();  
  14.   
  15.         IntentFilter filter = new IntentFilter();  
  16.         filter.addAction(Intent.ACTION_USER_PRESENT);  
  17.         filter.addAction(Intent.ACTION_SCREEN_ON);  
  18.         filter.addAction(Intent.ACTION_SCREEN_OFF);  
  19.         registerReceiver(mReceiver, filter);  
  20.     };  
  21.   
  22.     @Override  
  23.     protected void onPause() {  
  24.         super.onPause();  
  25.           
  26.         unregisterReceiver(mReceiver);  
  27.     };  
  28.       
  29.     BroadcastReceiver mReceiver = new BroadcastReceiver() {  
  30.   
  31.         @Override  
  32.         public void onReceive(Context context, Intent intent) {  
  33.             String action = intent.getAction();  
  34.   
  35.             Log.d(TAG, "mReceiver received : " + action);  
  36.   
  37.             if(action.equals(Intent.ACTION_USER_PRESENT)){  
  38.             }  
  39.             else if(action.equals(Intent.ACTION_SCREEN_ON)){  
  40.             }  
  41.             else if(action.equals(Intent.ACTION_SCREEN_OFF)){                  
  42.             }  
  43.         }  
  44.     };      
  45. }  



D/UserPresentSampleActivity( 9858): mReceiver received : android.intent.action.SCREEN_ON
D/UserPresentSampleActivity( 9858): mReceiver received : android.intent.action.USER_PRESENT
D/UserPresentSampleActivity( 9858): mReceiver received : android.intent.action.SCREEN_OFF




2011年8月17日水曜日

Android Market Multiple APK Support

2011年7月11日から Android Market で Multiple APK がサポートされるようになりました。

詳細は Android Developers のブログ記事
Android Developers Blog: Multiple APK Support in Android Market -



Android のドキュメント
Multiple APK Support | Android Developers -

を参照してください。

Android Market の Help Center もあります。


■まとめ

  • Multiple APK support は Android Market の新しいパブリッシュオプション (つまり、その他の配布プラットフォーム、例えば au one market とか、では使えません)

  • APK を1つだけ Developer Console からアップしている場合はこれまでと同じ

  • 複数の APK をアップロードしている場合、Android Market は1つのプロダクトの一部として扱う( = アプリの詳細ページはどのユーザーからも同じ内容になる)
    つまり、以下の項目は複数の APK で共通、もしくは合算になる
    • アプリの詳細情報(バナーなど、スクリーンショット、ビデオ)
    • レーティング
    • コメント
    • アプリのダウンロード統計
    • レビュー
    • 購入データ

  • Multiple APK で分割できる項目

  • Multiple APK の利点
    • API のバージョンで APK を分割できる (例えば、電話用とタブレット用の APK を分けられる)
    • ハードウェア機能のあり・なしで APK を分割できる
    • 新しい API がリリースされたときに、それをターゲットにしたバージョンを別 APK で開発できるので、既存のユーザーに影響がない
    • 1つの APK で様々な解像度の端末に対応する場合、resource (特に画像)が多くなることで APK サイズが大きくなるが、これを防げる



注意: Multiple APK Support | Android Developers -
Currently, these are the only device characteristics that Android Market supports for publishing multiple APKs as the same application.
とあるように、
現状では、マルチ APK を同じアプリとして配布するために Android Market がサポートしているのはデバイスの特徴(ハードウェア機能のある・なし)のみのようです。


注意2: 基本的には、1つの APK のサイズが 50M を超えるときだけ Multiple APK をつかって、それ以外はなるべく1つの APK で複数のデバイスコンフィグレーションに対応するべき。そのほうがアップデートがシンプルになるし、開発管理も複雑にならなくてすむ。


  

2011年8月13日土曜日

Android TransitionDrawable を使う

TransitionDrawableLayerDrawble の拡張で、2つのレイヤーの間をクロスフェードさせることが可能。

主なメソッドは次の3つ


次のコンストラクタで Drawable の配列を渡して生成することもできるし

TransitionDrawable(Drawable[] layers)

<transition> タグを使って XML で定義することもできる。

例えばこんな感じ
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <transition xmlns:android="http://schemas.android.com/apk/res/android">  
  3.     <item android:drawable="@drawable/trash"  />  
  4.     <item android:drawable="@drawable/trash2"  />  
  5. </transition>  


  1. public class TransitionDrawableSampleActivity extends Activity {  
  2.   
  3.     TransitionDrawable mTransitionDrawable;  
  4.       
  5.     private static final int TRANSITION_DURATION = 1000;  
  6.   
  7.     @Override  
  8.     public void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.main);  
  11.           
  12.         ImageView iv = (ImageView)findViewById(R.id.imageview);  
  13.         mTransitionDrawable = (TransitionDrawable)iv.getDrawable();  
  14.         mTransitionDrawable.setCrossFadeEnabled(false);  
  15.     }  
  16.       
  17.     public void onResetClick(View v) {  
  18.         mTransitionDrawable.resetTransition();  
  19.     }  
  20.       
  21.     public void onTransitionClick(View v) {  
  22.         mTransitionDrawable.startTransition(TRANSITION_DURATION);  
  23.     }  
  24.       
  25.     public void onReverseClick(View v) {  
  26.         mTransitionDrawable.reverseTransition(TRANSITION_DURATION);  
  27.     }  
  28. }  







2011年8月11日木曜日

Android Spannable を使って文字列の一部を装飾する

SpannableStringBuilder を使って、文字列の一部を装飾(bold, italic, typeface, color, size) することができます。

こんな感じ。

  1. public class SpannableSampleActivity extends Activity {  
  2.   
  3.  private static StyleSpan sBoldStyleSpan = new StyleSpan(Typeface.BOLD);  
  4.  private static TypefaceSpan sSerifTypefaceSpan = new TypefaceSpan("serif");  
  5.   
  6.  @Override  
  7.  public void onCreate(Bundle savedInstanceState) {  
  8.    super.onCreate(savedInstanceState);  
  9.    setContentView(R.layout.main);  
  10.   
  11.    TextAppearanceSpan cyanTextAppearanceSpan =  
  12.        new TextAppearanceSpan(this, R.style.MyTextAppearance);  
  13.   
  14.    SpannableStringBuilder sb = new SpannableStringBuilder();  
  15.    sb.append(getString(R.string.pretext) + " ");  
  16.   
  17.    int start = sb.length();  
  18.    sb.append(getString(R.string.boldtext));  
  19.    sb.setSpan(sBoldStyleSpan, start, sb.length(),  
  20.        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  21.   
  22.    sb.append(" " + getString(R.string.posttext) + " ");  
  23.   
  24.    start = sb.length();  
  25.    sb.append(getString(R.string.seriftext));  
  26.    sb.setSpan(sSerifTypefaceSpan, start, sb.length(),  
  27.        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  28.   
  29.    sb.append(" " + getString(R.string.posttext) + " ");  
  30.   
  31.    start = sb.length();  
  32.    sb.append(getString(R.string.cyantext));  
  33.    sb.setSpan(cyanTextAppearanceSpan, start, sb.length(),  
  34.        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  35.   
  36.    sb.append(" " + getString(R.string.posttext));  
  37.   
  38.    ((TextView)findViewById(R.id.textview)).setText(sb);  
  39.  }  
  40. }  


res/values/styles.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3. <style name="MyTextAppearance" parent="@android:style/TextAppearance">  
  4.  <item name="android:textColor">#00ffff</item>  
  5.  <item name="android:textSize">30sp</item>  
  6.  <item name="android:textStyle">italic</item>  
  7. </style>  
  8. </resources>  




SpannableStringBuilder には複数の Span が設定可能で、それぞれ setSpan() メソッドで設定できます。

設定されている Span オブジェクトの一覧は getSpans() メソッドで取得でき、特定の Span オブジェクトの設定されている開始位置や終了位置、フラグなどは getSpanStart(), getSpanEnd(), getSpanFlags() で取得できます。 Span を削除する場合は removeSpan() を呼び出します。

SpannalbeStringBuilder の Span 操作


setSpan() の4つ目の引数で、この span の範囲内に文字が挿入されたときにどう振舞うかを指定することができます。指定できるフラグは Spanned に定義されている SPAN_* の定数のうち次の5個です。
  • SPAN_INCLUSIVE_EXCLUSIVE
  • SPAN_INCLUSIVE_INCLUSIVE
  • SPAN_EXCLUSIVE_EXCLUSIVE
  • SPAN_EXCLUSIVE_INCLUSIVE
  • SPAN_PARAGRAPH


SpannableStringBuilder の文字列操作
  • append()
  • insert()
  • replace()

など

Span オブジェクトとして指定できるクラスとしていくつかあります。
  • StyleSpan
    bold, italic を指定
  • TypefaceSpane
    "monospace", "serif", "sans-serif" を指定
  • TextAppearanceSpan
    文字の色、サイズ、style、typeface を一致する TextAppearance リソースに設定
  • AbsoluteSizeSpan
  • RelativeSizeSpan
  • ReplacementSpan
  • ScaleXSpan
  • SubscriptSpan
  • SuperscriptSpan


StyleSpan を使うときの注意点として、このスタイルが累積するものなので、例えば bold と italic 両方を別々の span で設定したり、ベースのスタイルが bold で italic の span を呼び出した場合、 bold italic になります。ベーススタイルからのスタイルはオフにすることができません。

コンストラクタの引数でスタイルを設定します。設定できるスタイルは Typeface クラスで定義されている次の4個です。


TypefaceSpane のコンストラクタで指定できる family は次の3個です。
  • "monospace"
  • "serif"
  • "sans-serif"


TextAppearanceSpan には、文字の typeface、大きさ、色を引数で指定する

- public TextAppearanceSpan (String family, int style, int size, ColorStateList color, ColorStateList linkColor)

と、TextAppearance のリソース ID を指定する

- public TextAppearanceSpan (Context context, int appearance)

- public TextAppearanceSpan (Context context, int appearance, int colorList)

があります。