2011年10月15日土曜日

IPhone 4S、さっそく分解される

発売されたばかりのiPhone 4Sだが、さっそくiFixitが分解している(iFixitの記事)。 

0.05WH容量が増加したバッテリーはiPhone 4のバッテリーとほぼ同サイズだが、コネクターの形状が異なるため、iPhone 4で使用することはできないとのこと。A5 CPU内蔵のメモリーは512MBのDDR2とみられる。フラッシュメモリーは東芝製、液晶はiPhone 4と同じもののようだ。 

iPhone 4Sの「修理しやすさスコア」は10点満点で6点。ほとんどがネジ止めされており、接着剤があまり使われていない点および、リアパネルやバッテリを交換しやすい点がプラス評価。一方、液晶とガラスパネルが結合されている点や、1つのフレキシブルケーブルに多くのコンポーネントがハンダ付けされている点を挙げ、これらの交換コストは高いとしてマイナス評価。また、特殊なペンタローブネジを使用している点もマイナス評価となっている。 
ちなみに、Siriで使用しているのではないかと噂になった、Cyberdyne Systemsのコンポーネントは搭載されていないとのこと。
 

Project Avatar - HTML5サポートによる全方位戦略

 JavaFXとJava MEの融合でデスクトップアプリケーションもモバイルアプリケーションも同じAPIで開発できるようになるのは開発者にとってうれしいニュースです。しかし現在Webアプリケーションの基盤技術として最もホットなのは「HTML5」ではないでしょうか。

 HTML5は、FlashやSilverlightなどの特定のベンダ固有の技術に頼らずWebブラウザ上で動くアプリケーションにリッチなUIを実装できるのが魅力的です。ただし、アプリケーションロジックはJavaScriptで実装することになり、大規模なアプリケーション開発やエンタープライズアプリケーションとの連携という面では必ずしも優れているとはいえません。

 そこでオラクルは、「Project Avatar」と呼ばれるHTML5とJavaのハイブリッドアプリケーション技術が研究中であることに触れました。技術の詳細は明らかにされませんでしたが、アプリケーションのUIにHTML5を、アプリケーションのロジック部分にJavaを使うマルチプラットフォーム対応の環境のようです。

 UIのリッチなアプリケーションをマルチプラットフォーム対応で実績のあるJavaで実現するという点で目標はJavaFXと似ていますが、HTML5を重心に置くことでRIAプラットフォームやHTML5に慣れたデザイナや非Java開発者に対してもフレンドリーな環境を用意するという戦略のようです。

 デモでは、JavaFXと同じくiPadやAndroidタブレットで同じアプリケーションが動作する様子をアピールしていました。

Java ME - JavaFXと融合しAndroid/iOSに対応!?

 iPhoneAndroidの爆発的な普及から盛り上がっているモバイルアプリケーション市場の中、いまひとつ元気がないのが、Java MEです。

 フィーチャーフォンJava CardBlu-rayプレイヤーなどあまり目立たない形で広く普及はしているのですが、開発者にとって魅力のあるプラットフォームとはいえないのが正直なところではないでしょうか。

 Java MEでは現在、非接触通信ジャイロセンサの読み取りなど現在普及しているスマートフォンで実装している多くの機能をJava MEのAPIでも実現できるようにする取り組みを行っています。

 また、これまでJava SEとは異なるライフサイクルで開発されていたのを歩調を合わせる形にし、Java SE 8と同時に新しいメジャーバージョンをリリースすることが予告されました。

 さらにJava MEはJavaFXと親和性を高め、JavaFXアプリケーションがあらゆるJava ME対応デバイスでも動作することを目指しているようです。非常に関心を呼んだのはJavaFXで書かれたゲームがWindowsタブレット、Androidタブレット、さらにはiPadで動作してしまうというデモです。

 Androidは「Dalvik」と呼ばれるJavaと非常に似た仮想マシンを搭載しているためJavaFXを移植するのはそれほど難しいことではないかもしれません。しかし、Objective-Cで開発を行うことを前提としているiOSプラットフォームでJava/JavaFXアプリケーションが動くようになれば開発者コミュニティにおけるインパクトは非常に大きなものとなります。

 ただし、Android/iOSデバイス上のJavaFXはあくまで技術デモに過ぎず、これらのプラットフォーム向けのJavaFX、JVMのリリースに関して具体的なロードマップは示されていません。これは、技術上はすでにある程度実現していても、実際にマーケットに登場させるために乗り越えなければならない政治的な壁が多くあるからと想像できます。

 例えば、Androidについてはオラクルとグーグルの間で特許上の訴訟問題があり、またアップルはiOSでObjective-C以外のプログラミング言語をあまり歓迎しない姿勢です。JavaFX、Java MEという技術の融合でデスクトップ、モバイルアプリケーションでも「Write once, run anywhere」が達成できれば開発者コミュニティに広く歓迎されるのは間違いありませんが、早急な実現は期待しない方がよさそうです。

 Mac OS X for OpenJDKのBoFセッションでは、「ランタイムを全部アプリに含めていればiOSの規約はクリアできるんじゃないか」という話があったようです。Adobe AIRが最新版の3で実現している「Captive Runtime」機能のようなものなら可能性はあるのかもしれません。

 

Java SE 8のマイルストーンアップデート

 昨年のJavaOneでは次期Java SEのリリースの大幅な遅れが懸念されたため、言語仕様に大きな影響を与える取り組みをJava SE 8へと延期することで早いJava SE 7のリリースを目指すという方向が決定されました。後回しとなった主要なプロジェクトは、ライブラリの依存関係管理をシンプルにする「Jigsaw」と、Javaに関数型言語の味付けをする「Lambda」です。

 今年のJavaOneでは、去年決定した通りJigsawとLambdaをJava SE 8で取り込むことをあらためて約束し、関連する技術セッションも多く用意されました。ただし、Java SE 8のリリース予定は当初の2012年から2013年へと延期されました。想定よりも仕様策定に時間がかかっているようです。

 なお、開発中のビルドはすでにOpenJDKプロジェクトのサイトよりダウンロードできるので積極的に試してフィードバックしてほしいとのことです。

 

 Java SE 9の取り組みはまだ具体化しておらずアイデアをまとめている段階です。ビッグデータの取り扱いやマルチ言語サポートの強化、Java EE 7と歩調を合わせる形でクラウド対応のための機能追加、自分でチューニングできるJVMなどを検討しているそうです。キーワードとしては以下のものが挙がりました。

  • Self Tuning JVM Improved Native Integration
  • Big Data
  • Reification
  • Tail Calls / Continuations
  • Meta-Object Protocol
  • Multi-Tenancy
  • Resource Management
  • Heterogeneous Compute Models
 
 

 Java EEの最新バージョンであるJava EE 6は2009年12月にリリースされました。GlassFishがいち早く対応したものの、他に仕様に準拠したアプリケーションサーバがなかなか出揃わず、現在のところJ2EE 1.4やJava EE 5ベースのプロジェクトが多いようです。

 しかし、いまやJava EE 6認証済みのアプリケーションサーバは4種類、Webプロファイルのみ対応のものも含めるとは7種類にまで増え(参考:Java EE Compatibility)、Java EE 6はいよいよ普及期に入ったことがアピールされました。

 

 

2011年10月13日木曜日

非同期処理

UI操作(textView.setText("hoge")など)が可能なのはメインスレッドのみ。
UI操作する時はHandlerやMessageを使い、UI操作とは別に裏で処理を行いたい時はThreadやTimerを使う。 

非同期処理

クラス

スレッド種別

用途

サンプル

Handler

メインスレッド

UI操作

Handler handler=new Handler();

handler.postDelayed(new Runnable(){

    public void run() {

        android.util.Log.e("","UI操作可能");

    }

},100);

Message

メインスレッド

UI操作。
任意の引数追加とキャンセル可能

Handler handler=new Handler();

Message msg=Message.obtain(handler,new Runnable() {

    public void run() {

        android.util.Log.e("","UI操作可能");

    }   

});

msg.what=MESSAGE_ID;//メッセージID

msg.obj=object;     //任意のオブジェクト引数

msg.arg1=0;         //任意のint引数

msg.arg2=0;         //任意のint引数

handler.sendMessageDelayed(msg,100);

handler.removeMessages(MESSAGE_ID);

Thread

独自スレッド

UI操作不可。
メインスレッドとは別に裏で処理

Thread thread=new Thread(){

    public void run() {

        android.util.Log.e("","UI操作不可");

    }

};

thread.start();

Timer

独自スレッド

UI操作不可。
メインスレッドとは別に裏で繰り返し処理

Timer timer=new Timer();

TimerTask task=new TimerTask() {

    public void run() {

        android.util.Log.e("","UI操作不可");

    }

};

timer.schedule(task,0,100);

AsyncTask

メインスレッド+
独自スレッド

メインスレッドと独自スレッドが共存

public class DownloadTask extends AsyncTask<T1, T2, T3> {

     @Override

     protected T3 doInBackground(T1... args) {

         android.util.Log.e("","UI操作不可");

     }

     @Override

     protected void onPostExecute(T3 result) {

         android.util.Log.e("","UI操作可能");

     }

}

new DownloadTask().execute(args);

 

Androidで定期的に処理を実行する方法

課題
Androidで一定の間隔をおいて定期的に処理を実行する。

方法
1.Handler#postDelayed()を使う方法
2.Handler#sendMessageDelayed()を使う方法
3.Threadを使う方法
(TimerTaskとかAlarmManagerってのでもできるっぽいけどやらない)
Handler#postDelayed()を使う方法
postDelayed()を使って一定間隔ごとにRunnableを起動させる
/**
* 1.初回実行
* 2.繰り返し
* 3.次回処理をセット(Handler#postAtTime()でも代用可)
* 4.停止
*/
public class RepeatByPost extends Activity {

//繰り返し間隔(ミリ秒)
private final int REPEAT_INTERVAL = 3000;

private Handler handler = new Handler();
private Runnable runnable;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

runnable = new Runnable() {
@Override
public void run() {

//2.繰り返し処理
doSomething();

//3.次回処理をセット
handler.postDelayed(this, REPEAT_INTERVAL);
}
};

//1.初回実行
handler.postDelayed(runnable, REPEAT_INTERVAL);
}

private void doSomething() {
Log.i("Repeat by", "post");
}

@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("onTouchEvent()", "STOP");

//4.画面がタッチされたらhandlerからコールバック(runnable)を削除して処理を停止する
handler.removeCallbacks(runnable);
return true;
}
}

Handler#sendMessageDelayed()を使う方法
sendMessageDelayed()を使って一定間隔ごとにMessageを発行し、handleMessage()で受け取る。
/**
* 1.初回実行
* 2.繰り返し判定
* 3.繰り返し処理
* 4.次回処理をセット
* 5.停止処理
*/
public class RepeatBySendMessage extends Activity {

//繰り返し間隔(ミリ秒)
private final int REPEAT_INTERVAL = 3000;

//繰り返し処理を続けるかどうかのフラグ
private boolean isRepeat = true;

//Messageコード(数値は適当)
private final int MESSAGE_WHAT = 100;

private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {

//2.isRepeatがtrueなら処理を繰り返す
if (isRepeat) {

//3.繰り返し処理
doSomething();

//4.次回処理をセット
handler.sendMessageDelayed(obtainMessage(), REPEAT_INTERVAL);
}
}
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Message message = new Message();
message.what = MESSAGE_WHAT;

//1.初回実行
handler.sendMessageDelayed(message, REPEAT_INTERVAL);
}

private void doSomething() {
Log.i("Repeat by", "sendMessage");
}

@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("onTouchEvent()", "STOP");

//5.画面がタッチされたらisRepeatをfalseにして繰り返し処理を停止させる
isRepeat = false;
return true;
}
}

Threadを使う方法
起動させたThreadにsleep()を入れて一定の間隔で処理を実行させる。
/**
* 1.スレッド起動
* 2.繰り返し判定
* 3.繰り返し処理
* 4.停止処理
*/
public class RepeatByThread extends Activity {

//繰り返し間隔(ミリ秒)
private final int REPEAT_INTERVAL = 3000;

//繰り返し処理を続けるかどうかのフラグ
private boolean isRepeat = true;

private Thread thread;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Runnable looper = new Runnable() {
@Override
public void run() {

//2.isRepeatがtrueなら処理を繰り返す
while(isRepeat) {
try {
Thread.sleep(REPEAT_INTERVAL);
} catch (InterruptedException e) {
Log.e("looper", "InterruptedException");
}

//3.繰り返し処理
doSomething();
}
}
};

//1.スレッド起動
thread = new Thread(looper);
thread.start();
}

private void doSomething() {
Log.i("Repeat by", "thread");
}

@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("onTouchEvent()", "STOP");

/*
* 4.画面がタッチされたらisRepeatをfalseにして繰り返し処理を停止させる
* Threadを利用した場合は停止のタイミングがずれることがある
*/
isRepeat = false;
return true;
}
}

admobのSDKが新しくなっています。

admobSDKが多分2011年4月くらいから新しくなっています。

■ 新SDKの組み込み

まずはManifest.xmlに組み込みます。ポイントは二つ。パーミッションの追加と、アクティビィティーの追加です。

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
まずパーミッションとして、2つを加えます。ACCESS_NETWORK_STATEは、前回は必要なかったのですが、今回より必要になっています。

<!-- admob追加 -->
<activity android:name="com.google.ads.AdActivity"
android:configChanges="orientation|keyboard|keyboardHidden"
/>
Activityの追加です。applicationの内部に、他Activity同様に追加してください。

次に、attr.xmlを追加します。ここは前回までと同じですが、xmlでadViewを定義するため、idの追加をしておきましょう。

<attr name="adUnitId" format="string"/>
ここまでくれば、最後はLayoutファイルです。

<com.google.ads.AdView
android:id="@+id/ad"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
myapp:adUnitId="パブリッシャーID"
/>
これでOKです。

 

admobを組み込む

■ admobに登録する

Androidアプリの広告として、もっともメジャーなのが、Google傘下のadmobだと思います。adSenseに統一したいところですが、今のところ一般開発者向けには開けてないようで・・・。

ではさっそく登録から始めます。とは言っても、普通にメールアドレス等を入力してアカウントを取るだけです。

その後、アプリに組み込む為に、「サイト/アプリケーションの追加」からAndroidアプリを選択します。

選択すると、アプリ名や公開時のアドレス等を入力します。公開時のアドレスは、未公開時は予定するアドレスを入力するか最悪適当に入れておいて後で変更できます。

入力後、次へを押下で上記画面になります。この時、adMobSDKをまだ取得していない場合(最初はみんな取得していないのですが)、SDKをダウンロードしておきましょう。

追加が済むと、上記のように追加されます。ステータスが赤くなっていますが、これはまだアクティブになっていませんよ。ということです。アクティブ(広告表示要求が出た後)になると緑色になります。

この追加作業の途中でパブリッシャーIDなるものが表示されます。組み込む時に必要なので、控えておきましょう。もちろん後で上記画面「設定を管理」よりIDを確認することができます。

この他、入金方法の設定等の作業があります。現在、adMobでは、小切手で受け取る方法とPaypalを用いて受け取る方法があります。わしは小切手ってよくわからないので、Paypalにしましたが、後でも変更できるのでとりあえず。

■ SDKを組み込む

まず最初の作業として、adMobSDKを組み込みます。先にダウンロードしたSDKを解凍すると、admob-android-sdk.jarファイルが出てきますが、これをadMobを入れたいプロジェクトの下に「lib」のフォルダを作成し、そこに入れます。

その後、jarファイルを右クリックし、「ビルド・パス」から「外部アーカイブの追加」を選択し、ライブラリ化します。

これでSDKの組み込みは終了です。

■ adModを組み込む

さて、ここからadMobをアプリに組み込んでいきます。まずはAndroidManifest.xmlからパーミッションを追加します。

<uses-permission android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
INTERNETさえあればOKなんですが、LOCATIONによる広告の最適化を利用したいので、下二つのパーミッションも有効にします。

さらに</apprication>の前に

<meta-data android:name="ADMOB_PUBLISHER_ID" android:value="メモしたID"/>

</application>
を追記しましょう。ここでメモしたIDを入力します。これでマニフェストファイルは終了です。

次に/res/valuesにattr.xmlを追加します。中身は以下です。

<?xml version="1.0" encoding="utf-8"?>
<resources>
 <declare-styleable name="com.admob.android.ads.AdView">
 <attr name="backgroundColor" format="color" />
 <attr name="primaryTextColor" format="color" />
 <attr name="secondaryTextColor" format="color" />
 <attr name="keywords" format="string" />
 <attr name="refreshInterval" format="integer" />
 <attr name="isGoneWithoutAd" format="boolean"/>
 </declare-styleable>
</resources>
何も考えず、そのままコピペ・・・。

最後に追加したいレイアウトに以下を追加します。

<com.admob.android.ads.AdView
 android:id="@+id/ad"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 myapp:backgroundColor="#000000"
 myapp:primaryTextColor="#FFFFFF"
 myapp:secondaryTextColor="#CCCCCC"
 myapp:refreshInterval="13"
 />
Viewクラスと同じ扱いです。ちなみに、軽いアプリはこれでOKですが、処理が重いアプリ、もしくはレイアウトをxmlを使わない場合は、ソース(javaファイル)でAdViewをaddしてやってください。

ちなみにですが、adMobは決して表示率がいいほうではありません。レイアウトの一部として利用する場合は注意が必要です。割り切ってRelativeLayoutで作成し、その中にadViewを入れてやるのが個人的オススメです。

表示率の問題で表示されない件の対応として、テストする場合は、以下のコードをActivityのonCreateに入れると表示されるようになります。

AdManager.setTestDevices( new String[] {
 AdManager.TEST_EMULATOR,
 });
さて、ここまでで表示されるようになるのですが、実は、わしはこれだけでは全く表示されませんでした。で、logcatを確認すると、「ManifestにadMobアクティビティーを追加して!」というメッセージが・・・・。しようがないので、以下Activityを追加しました。

<activity android:name="com.admob.android.ads.AdMobActivity"
 android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
 android:configChanges="orientation|keyboard|keyboardHidden"
 />
で、ようやく表示までこぎつけました。

実際、テストモードを外すとほとんど表示されません。logcatで確認すると、「No fill.  Server replied that no ads are available」と出ており、表示する広告がないと・・・。

adMobではこのような場合の為にさまざまな設定が用意されています。個人開発者の場合、他に宣伝することもないんですけどね・・・。

 

 

Understanding Android Themes And Styles

I don't know how many hours I've spent struggling with Android's theme engine, trying to figure out — mostly by trial and error — how styles are applied and how to properly define them (let's be honest: the documentation on styles in Android is a bit lacking). I thought it may be worth sharing what I've found out so far, in order to save my fellow Android developers from baldness due to ripped out hair (I sure lost some). This is a work in progress (so is Android), and some information may be inaccurate. If you find anything that you think is wrong or unclear, please let me know by dropping a line in the comments section. On another note, I assume that you have read the reference documentation on Android styles, if not, you should do that now.

What are Android styles?

A style in Android is a collection of attribute/value pairs applied to a view, an Activity or the entire application (which means, all Activities in your application). Styles for Activities are called themes, but do not get confused: they are syntactically equivalent to styles (because they are styles), they merely have a different scope. At this point I want to clarify something upfront: Themes or styles in Android have nothing to do with user styles known from applications such as, say, Firefox. Android users can not change the looks of Android applications by downloading themes from the Market or creating their own (yet). Android themes are of interest for developers only, think of them as syntactic sugar, a way of making your application's view code more DRY

.

Let's look into a simple theme definition (stored in res/values/styles.xml):

01

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

02

<resources>

 

03

  <style name="MyTheme" parent="android:Theme.Light">

04

    <item name="android:windowNoTitle">true</item>

 

05

    <item name="android:windowBackground">@color/translucent_blue</item>

06

    <item name="android:listViewStyle">@style/MyListView</item>

 

07

  </style>

08

 

 

09

  <style name="MyListView" parent="@android:style/Widget.ListView">

10

    <item name="android:listSelector">@drawable/list_selector</item>

 

11

  </style>

12

</resources>

First, we declare a new theme called MyTheme, which inherits from another theme called Theme.Light in the android namespace (specified by the 'parent' attribute). This means that all styles we do not explicitly specify in our custom theme will be merged down from the definition of android:Theme.Light (the curious among you may want to download the Android source code and go to frameworks/base/core/res/res/values to see how it is defined; all stock styles are defined in themes.xml and styles.xml in that folder).

In our theme definition, we also set some custom styles using the 'item' element. We set the windowNoTitle attribute to true, so all activities that use our theme won't have a title bar. We also set the window background color to a custom color called 'translucent_blue'; this is a resource reference (indicated by the @ symbol) to a color definition in values/colors.xml. We could also have passed a reference to a drawable here, or have provided a hex color value directly. Finally, we set the default style for ListView widgets to a custom style called MyListView. Its style definition follows the exact same structure as the MyTheme definition, just that this time it is not a theme, but simply a style that can be applied to ListView objects. It inherits from the default styles for ListView but replaces the default selector image with a custom drawable.

There are two important things to understand here. First, those two style definitions are completely independent of each other (well, apart from the fact that we reference MyListView in MyTheme of course). This means, that if I remove the reference to MyListView from MyTheme, I can still use that style by applying it manually to a ListView declaration in a layout file. Think of styles simply as a bunch of attributes and values you would have otherwise typed directly into your view definition, so instead of writing

1

<ListView android:listSelector="@drawable/list_selector" />

we write

1

<ListView style="@style/MyListView" />

or better yet, we let this style be applied automatically to all ListView widgets by setting it in a theme definition (as seen above). (Note the missing 'android:' namespace reference here; this is intentional, the 'style' attribute is not defined in the 'android' namespace. You will get an error if you try to set a style using 'android:style', there is no such attribute.)

That way we never have to touch the ListView definition anymore; we can do all its styling from a single point, the style sheet. This helps in leaving the code for defining structure in your layouts, while leaving the code for definingappearance in your style sheets — a good example for separation of concerns. More importantly, your style definitions can be reused, which is particularly useful if styles are shared between several views.

The other important thing to understand is that styles do not have any type semantics. When we create a style called MyListView which inherits from Widget.ListView, then the intuition is that we are creating a style that is only supposed to apply to ListView objects. That's not entirely correct though. There is no mechanism that will check whether we indeed apply that style to a ListView or even prevent us from applying it to an entirely different view type. It just so happens that Widget.ListView defines some attributes that only make sense when being applied to a ListView (such as listDivider), this doesn't stop us, however, from creating a style that totally makes sense for any widget type (maybe because it only uses attributes defined in the View class, the parent class of all views). The bottom line is that you have to figure out yourself whether a style you define makes sense when you apply it to a view. Android will not do any sanity checks for you. In the worst case, the targeted view will expose odd behavior when being rendered, but more probably nothing will happen at all.

To get going with styles, it's of course important to know two things:

1.      what's there to be styled, and

2.      what styles are already there to inherit from

The easy answer is: Anything in android.R.styleable can be used inside a style body as a subject for styling (using the item tag), while anything in android.R.style can be used as parent styles to inherit from. So, to stick with the ListView example style, the android:listSelector style item can be found in android.R.styleable, while android:style/Widget.ListView is defined in android.R.style. Those two files are therefore what you want to turn your attention to first when defining custom styles. You should generally always inherit all default style items first, and then overwrite them one by one with your custom items.

That's basically already it, a simple yet powerful style framework if used correctly!

Text Appearance

Did you find yourself defining text appearance like font size or text color over and over again in your layouts? Don't do that, use text appearances instead. Text appearances are styles, too, and Android already defines some for you which you can override (they are, of course, defined in R.style). This helps tremendously in keeping your view code DRY, and encourages you to get some structure into your different font styles used throughout your app by grouping them into styles you can reference and reuse. If, for example, you want to change the default text appearance in your app, simply define a custom text appearance in your stylesheet and set it as the default in your theme:

01

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

02

<resources>

 

03

  <style name="MyTheme" parent="android:Theme.Light">

04

    <item name="android:textAppearance">@style/MyDefaultTextAppearance</item>

 

05

  </style>

06

 

 

07

  <style name="MyDefaultTextAppearance" parent="@android:style/TextAppearance">

08

    <item name="android:textSize">12sp</item>

 

09

    <item name="android:textColor">#333</item>

10

    <item name="android:textStyle">bold</item>

 

11

  </style>

12

</resources>

Make yourself familiar with all the text appearances Android already defines, and customize them for your application as you see fit.

Colors

Avoid setting color values directly in layouts or styles. Define them in a color resource file instead, and only use references to those color values from your layouts and styles. This helps in isolating them from the rest of your view code and makes your styles less brittle if you should decide to change a color afterwards. For simple, non-stateful colors, you can simply create a colors.xml file in res/values:

1

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

2

<resources>

 

3

    <color name="default_text_color">#FFEAEAEA</color>

4

    ...

 

5

</resources>

Often, however, colors can be more complex. If, for instance, you use a custom list selector image, it may happen that list text is readable when not selected, but becomes difficult or impossible to read when the custom selector is drawn (e.g. because the coloring is too similar). In that case, you need a ColorStateList, which you can use to automatically change colors for the view it's applied to, based on that view's state. Start by creating a new file, e.g. 'stateful_text_color.xml' in your res/colors directory. The resource root is 'selector', which is what you always use when creating resources that change with a view's state:

1

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

2

  <item android:state_enabled="false" android:color="#333" />

 

3

  <item android:state_window_focused="false" android:color="#CCC" />

4

  <item android:state_pressed="true" android:color="#FFF" />

 

5

  <item android:state_selected="true" android:color="#FFF" />

6

  <item android:color="@color/default_text_color" /> <!-- not selected -->

 

7

</selector>

You get the idea. You can set this stateful color resource like any other color, it's simply defined in a different way.

Also keep in mind that there are already color definitions shipped with Android. The most useful of them is probably android:color/transparent, which corresponds to the color #00000000. The first 8 bit, i.e. the first two hex digits, represent the alpha channel which is used to define opacity. A value of zero means zero opacity, or 100% transparency; the remaining color bits are therefore of no relevance, because they will be invisible. You can then turn the background of your views transparent by doing something like:

1

<style name="MyListView" parent="@android:style/Widget.ListView">

2

  <item name="android:background">@android:color/transparent</item>

 

3

</style>

That's it for now. If I find out more about styles in Android, I'll update this post accordingly. Feel free to contribute in the comments section, too.