Avatar

本体を購入して、開発環境を整えて、マーケットでアプリケーションを公開するまで全部そろえても格安で開発ができるのがAndroidの売りのひとつ。パソコンとインターネット環境があればたったの25ドルでマーケットに公開できるのだ。

アイコンを描くアプリも無料でやってしまいたい。イラストレーターなんて個人の趣味では手がでない・・。NexusOneやXperiaやDesireが買えてしまうではないか!

私はInkscapeでアイコンを作って、PaintDotNetでトリミングするなどして間に合わせている。両方フリーソフト。
GIMPも有名で超強力なツールだけど、Windowsを使っているならPaintDotNetでも十分だな。InkscapeやGIMPはLinuxやMacでも使えるので、Androidのアプリ開発はWin、Mac、Linuxのどれを使ってもよい。すばらしい!

AndroboiceのアイコンのデータもInkscapeで作成したもの。

作成方法はまず、フリーハンドで輪郭を描いてノードっていうポイントを調整して輪郭を整える。
そしてストロークのスタイルと塗りで線の太さと色を決める。
それからフィルで中身を塗りつぶす。




グラデーションをつける。
レイヤー管理ができるので、別のレイヤーに輪郭のパスをコピーして、
ストロークは「x」にして線を消す。フィルはグラデーションを選んでうまい具合に調整する。
この画ではレイヤーを3つしか使ってないけど、複雑な絵になるともっと細かく分けたほうが良いかもしれない。




口のなかのパーツもつくる。レイヤーの表示・非表示切り替えやロック機能を使うと作業しやすい。




最後に全てのレイヤーを表示して絵になっているかチェック。
これで元になるデータが完成。保存形式はSVGっていうXMLでできたベクターデータで、イラストレータでも読み込める形式だからデザイナーとの連携もできる。
ベクターデータの良いところは拡大縮小しても線が滑らかなこと。

Android1.6からは複数の画面解像度に対応したアイコンをアプリに使うことを推奨しているので、このデータを素にして複数のPNG形式のビットマップを出力する。




出力したい画像を選択ツールで選択しておいて、「ファイル>>ビットマップにエクスポート」でエクスポート用のダイアログが出るので、エクスポート領域が「選択」、ビットマップサイズを大体欲しいサイズに合わせて「エクスポート」ボタンを押せばOK。
3種類のPNGを出力して別のソフトで調整する。
大きさはここにもあるとおり、36x36px, 48x48px, 72x72pxくらいで作っておく。

あとはPaintDotNetで大きさを調整すればよい。線や塗り以外の部分は透明になるのでここで背景をつけてもよいかも。

絵のセンスはないけど、拡大されてギザギザになったイメージが端末に表示されなければ何とか見れるものだなー。

デベロッパーサイトのリンクからアイコンのテンプレートがダウンロードできるが、これがpsd形式なのである。PhotoShopの形式ね・・・。どうかと思うでしかし・・・
これを読むためにンー万円は払えないなー。
フォトショップとイラストレータっていまいち使いづらい。あの独自インタフェース。負け惜しみではないが・・・・「弘法筆を選ばず」というけど高い金払ったらすばらしいデザインができるわけでもないしねー。

そこでPaintDotNetで読み込む方法があった。「Paint.NET PSD Plugin」ってやつ。ここから読み込んで[PhotoShop.dll」ってライブラリをゲットしたら、「C:/Program Files/Paint.NET/FileTypes」フォルダにコピーする。次にPaintDotNetを起動すると「PSD形式」の読み書きができる。
これでデザイナーさんと連携できるなー。

InkscapeはほかにもPDFの編集もできるし、インストールしておいて損はないソフト。
昔は洋書しかなかったけど最近はAmazonで何冊か解説本が出ている。
私は

を買った。GIMPの解説もあるけど素材データが付録のCD-ROMについている。

まとめ。
Androidの開発環境はパソコンとインターネットがあればそろってしまう。お金は必要ないし、25ドルでアプリをマーケットに公開することもできる。野良アプリでよければ25ドルさえ必要ない。
恋人に電話を掛けるだけのアプリ。こんなの作って自分の電話機に入れておいたら素敵じゃないか!通話履歴なんかもクラウドなんかにアップロードして・・・??
記念日に一言メッセージを表示するウィジットなんてのもありかもしれん。新機種ゲットするため奥さんを説得するのに「愛情カスタム」したお古の端末をプレゼントするなんて作戦はどうかね。うまくいけば新機種が出るたびに機種変できるかも?
とにかくこんなにすばらしい環境は他には無いと思うので少しでも多くの人にこの楽しさを味わってもらいたいなー。

Avatar

TechCrunchの「[jp] Appleをめぐる永遠のすれ違い論議」を読んで少し昔のことを思い出した。

Appleを批判する記事は確かに多い。私もAppleはどうも好きになれんな。
でも古いけどApple製品はもっている。
iBook G4 800 と iPod(第3世代)iPod nano(初代)の3つ。
むかしはアップルのファンであった。
MacPeopleも購入していたし、そこで連載していた呉エイジさんの「我妻との闘争」は毎週楽しみにしていた。私の実家は呉エイジさんと同じなので地元の話も出てきて余計に面白かった。
単行本も何冊か出ているのでMacやデジタルガジェットが好きかどうかに関わらず、「怖い妻」に怯えながら趣味を楽しんでいる人に読んでもらいたいな。・・・また、読み返そうっと。

iBook G4 は初めて購入したノートPCだ。アップルストアで注文した。
それまでWindows95・98・2000と使ってきたがMacOS10.3は安定していた。
周辺機器とソフトが少なかったが満足であった。

iPodを購入して手持ちのCDを全部iTunesに入れてiPodに入れて楽しんだ。
15GBのうち7GBが音楽で埋まって、残りはシステムのバックアップディスクにした。

それからiTunes Music Storeがオープンした。
これも面白そうだと思ったので曲を購入しようとしたがうまくいかなかった。
iBookを購入したアップルストアのアカウントではiTunesMusicStoreで登録できないといわれた。

それからアップル熱は冷めた。

TechCrunchの記事にもあったがAppleは誰にでも使える製品を作り出すハードウェアメーカーなんだな。仕事でiPhone3Gを使うこともあるけど、やっぱりAndroidより良くできている。Xperiaも触ったけど、スマートフォンで誰にでも無難に薦められるのはiPhone。どんなやり方をしてもiPhoneやiPadは売れ続けるなー、と思った。
OSとハードは一体というのがAppleの考えらしい。各種サービスはハードを売るための「おまけ」なのかな。iTMSの件以来いまいちアップルのサービスは信用できないなー。

mp3の販売でDRMの廃止を後押ししたのはよかったな。CCCDとか専用プレイヤーとかアフォか!とおもってたし。でも日本では未だに制限が多い。結局レンタルして取り込んで聴く・・・・。

USBの普及もすばらしい。IEEE1394はこけたが・・・。
WiFiの普及もすばらしい。モバイルでモデムだの電話回線だのを気にする必要がなくなった。

Adobe締め出しはスゲーなー。PhotoShopElementsとかPremiereなどのアプリも同等の製品がバンドルされたりしてパソコン部門でもひどい仕打ちだったが・・。印刷業界でこれだけAppleが売れているのは誰のおかげ??
今度はFlashかー。せめてHTML5のVideo規格まとめてからにしてチョーダイ。

スマートフォンの特許でHTCを訴えたけど、HTCはアップルより前からスマートフォン作ってるし、MicrosoftやNokiaはなんも無しかえ?
特許は弱いものイジメするために使うものじゃないと思うね。

アップルはとっても使いやすくてよい製品を作っている。でもユーザーにとって良い製品よりももっと大事なのは選択できることだな。
どんなに良い製品でも選択肢が1つしかないようではなんとも寂しいではないか。

開発者にとっても自由があるほうがよい。iPhoneやWindowsPhoneは開発者にとって縛りが多いなー。
コンピュータを使う楽しみはプログラミングをしてこそ味わえると思う。スマートフォンにもそんな選択肢は必要だな。

むー。思い出というかAppleの悪口になってしまったかな。でもこれからも良い製品を出し続けてもらいたい。
Androidにはもっと頑張ってもらわねば。

Tagged with: , .
Avatar

DoCoMoのニュータイプ、Xperiaのタッチパネルについてである。

Androidのタッチパネルではタッチした強さを取得できる。
はずなんだ。

取得方法は
onTouchEvent(MotionEvent event) 内の getPressure() メソッドで0.0から1.0の値が取得できるはず。
少なくともHT-03Aでは取得できていたが、Xperiaでは常に1.0が返ってくるようだ。

こんなコードを書いてしらべた。

// package略
// import略

public class Main extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int a = event.getAction();
        String act = "";
        if (a == MotionEvent.ACTION_CANCEL) {
            act = "ACTION_CANCEL";
        }
        if (a == MotionEvent.ACTION_DOWN) {
            act = "ACTION_DOWN";
        }
        if (a == MotionEvent.ACTION_MOVE) {
            act = "ACTION_MOVE";
        }
        if (a == MotionEvent.ACTION_OUTSIDE) {
            act = "ACTION_OUTSIDE";
        }
        if (a == MotionEvent.ACTION_UP) {
            act = "ACTION_UP";
        }
        ((TextView)findViewById(R.id.touch_action)).setText(act);
        ((TextView)findViewById(R.id.touch_x)).setText(""+event.getX());
        ((TextView)findViewById(R.id.touch_y)).setText(""+event.getY());
        int size = event.getHistorySize();

        String histPress = " size=" + size;
        for (int i = 0;i < size;i++) {
            if (i > 1) break;
            histPress = histPress + "," + event.getHistoricalPressure(i);
        }
        ((TextView)findViewById(R.id.touch_pressure)).setText(histPress);

        String histSize = " size=" + size;
        for (int i = 0;i < size;i++) {
            if (i > 1) break;
            histSize = histSize + "," + event.getHistoricalSize(i);
        }
        ((TextView)findViewById(R.id.touch_size)).setText(histSize);

        return true;
    }
}

// layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/title"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="MotionEvent.getX()=" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/touch_x"
            android:text="0" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="MotionEvent.getY()=" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0"
            android:id="@+id/touch_y" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="MotionEvent.getSize()=" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0"
            android:id="@+id/touch_size" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="MotionEvent.getPressure()=" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="0"
            android:id="@+id/touch_pressure" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="MotionEvent.getAction()=" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/touch_action" />
    </LinearLayout>

</LinearLayout>

同様にタッチした範囲もgetSize()で取得できるのだが、Xperiaは常に0.0を返すのであった。
これは機種依存なのかもしれない。
マルチタッチをサポートしてたらタッチした範囲は求められそうだが、Xperiaのタッチパネルにはこんな情報もあり、機種的に取得ができないのかもしれん。

幅広い端末をサポートするなら、タッチパネルのプレッシャーを測り知ろうとしてはならぬのかもしれない。
Xperiaを猛烈に強くタッチしても「私にプレッシャーをかけるパイロットとは・・・」などとは言ってくれなさそうである。

はたしてXperia君はAndroidOS2.X にアップデートして真のニュータイプになれるのであろうか。

Tagged with: , , .
« Previous Page