6月 19

久しぶりです!

しばらく更新できていませんでしたが、『sak’s Android Avenue』は、株式会社キロルの公式ブログ『Kiroru Offical Blog』としてリニューアルします。

現在、サイトのリニューアル並びにネタを準備中です。

株式会社キロルについて

株式会社キロルは、今年(2012年)の1月に設立した Android/iOS アプリ開発にフォーカスした札幌に拠点を持つソフトウェア会社です。

現在、以下の製品を取り扱っています。

  • auスマートパス「アプリ取り放題」にも採用!電話/EMAIL を簡単にする ウィジェットアプリケーション「コールW Pro/メールW Pro」
  • 電話/EMAIL/SMS を簡単にする Android 4.0 専用のウィジェットアプリケーション「Stack Dialer」
  • レストランやカフェのメニューブックを Android タブレットに置き換える「キロル・スマートメニュー」

また、Android/iOS アプリケーションの企画/開発/コンサルテーションも承ります。お問い合わせは 問い合わせフォーム からどうぞ。

是非、一度、ホームページへもお越しください!


Posted by sak+

2月 23
今日の話題は ICS(Android 4.0)から ActionBar を取り上げます。

ActionBar は Android 3.0 (API Level 11) から導入された Android の新しいメニューの仕組みです。
これまでは本体にハードウェアキーとして「メニュー」ボタンがありましたが Android 3.0 以降では、「メニュー」を含むハードウェアボタンが基本的に廃止されました。メニュー以外のボタンはそれでもソフトウェアキーとして引き続き画面下部に配置されるのですがメニューボタンだけは廃止され Action Bar を使うことが推奨されています。

Action Bar の構成

Action Bar は4つの部分から構成されています。(参考サイト

  1. App Icon
  2. View Control
  3. Action Buttons
  4. Action Overflow

p0.png

App Icon は、アプリを識別する用途で用いられます。またトップレベルで無い場合は、ひとつ上の階層に遷移するためのボタンとしても使用されます。

View Control には、ドロップダウンメニューやタブコントロールなどを配置できます。そういうもの必要でない場合はアプリのタイトルを表示します。

Action Buttons には、頻度が高いアクションや重要なアクションに対する操作ボタンが割り当てられます。

Action Overflow には、頻度の低いアクションや Action Buttons の領域に入りきらなかったボタンが格納されます。

Action Bar の作成

Action Bar はこれまでのメニューと同様にプログラムまたはリソースから作成することができます。ただし、showAsAction という属性が追加されており、その項目が Action Buttons の領域に表示されるべきか Action Overflow の領域に表示するかの判断の材料になります。リソースで指定した場合の一例です。

res/menu/list.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/action_one"
         android:icon="@drawable/ic_action_one"
         android:title="@string/action_one"
         android:showAsAction="ifRoom" />
        :
    <item android:id="@+id/action_five"
         android:icon="@drawable/ic_action_five"
         android:title="@string/action_five"
         android:showAsAction="ifRoom" />
</menu>

ここで android:showAsAction には ifRoom が指定されています。これは、表示できない場合は Action Overflow 領域に格納せよという指示です。他に常に Action Buttons 領域に表示する always、常に Action Overflow に格納する never という設定値があります。

Action Bar の表示

Action Bar を表示させる場合はこれまで同様 Activity で onCreateOptionsMenu をオーバライドさせてやれば良いのですが、Fragment を使用する場合、各 Fragment の onCreateOptionsMenu をオーバライドさせてやることが可能です。

ここで良くやってしまうミスがタイトルにもつけた、おまじないの付け忘れです。
Fragment でメニューを追加する場合は、必ず setHasOptionsMenu(true) を付けましょう。

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
   
        setHasOptionsMenu(true); // 付け忘れないように!!
    }

サンプル

Action Bar を使用したサンプルとして Fragment でメニューを指定したものを作成しました。

p1.png p2.png

47都道府県をリスト表示したメイン画面と、アクションバーのアクションを実行して遷移する詳細画面の2画面で構成しています。それぞれ別のメニューを設定しています。詳細画面からメイン画面に戻るには Action Bar 上の App Icon を押してください。

また、メイン画面のリスト上のアイテムを長押しすると Action Mode になり、複数のアイテムが選択できるようになります。このときも別のメニューを表示するようにしています。

p3.png

完全なサンプルコード

いつものようにサンプルアプリのソースコードは Google Code で公開しています。完全なサンプルコードを参照したい場合はそちらをどうぞ。


Posted by sak+

Tagged with:
2月 17
最初に ICS 開発でのハマりポイントの紹介です。私はこれで1晩悩みました。(^^;

過去のエントリ『プログレスダイアログから処理を中断する。』の中で、端末の向きを変更した場合に onCreate が走るのを避けたい場合、AndroidManifest.xml の中で android:configChanges=”orientation” を指定すると onCreate の代わりに onConfigurationChanged が走りますよ!と紹介しています。

ICS で開発において同じようにしたのですが onConfigurationChanged がどうしても呼ばれません。コードをいろいろ変更して切り分けたところ android:targetSdkVersion を Android 3.2 (API Level 13) 以降で動作するように設定した場合、onConfigurationChanged が呼ばれなくなることが分かりました。理由は Android Developers の API リファレンスにズバリ記載されてました。


Caution: Beginning with Android 3.2 (API level 13), the “screen size” also changes when the device switches between portrait and landscape orientation. Thus, if you want to prevent runtime restarts due to orientation change when developing for API level 13 or higher (as declared by the minSdkVersion and targetSdkVersion attributes), you must include the “screenSize” value in addition to the “orientation” value. That is, you must decalare android:configChanges=”orientation|screenSize”. However, if your application targets API level 12 or lower, then your activity always handles this configuration change itself (this configuration change does not restart your activity, even when running on an Android 3.2 or higher device).


要するに Android 3.2 からは android:configChanges=”orientation” とするだけではダメで、新たに追加された screenSize も一緒に指定してねということのようです。

こんな感じで。

 <activity android:name=".Main"
     android:configChanges="orientation|screenSize">

android:configChanges=”orientation|screenSize” を AndroidManifest.xml の中で指定するとちゃんと onConfigurationChanged が呼ばれるようになりました。めでたしめでたし (^^

では!


Posted by sak+

2月 17
去年の 12/2。 待望の ICS搭載機 Galaxy Nexus を私も手に入れました。
発売日に予約無しで札幌のヨドバシに足を運んだものの入手でききるかどうかは心配でしたが、
並んでいるひともいないし、在庫も豊富にありました。初の Android 端末 HT-03A の発売日を彷彿させる肩すかし感です。
スマホ人気というものの、iPhone の人気とは全然違いますね。(^^;

そんなこんなで入手した私の愛機がこれです。

gn.png

発売からもう2ヶ月以上経っちゃってますが、ここへきて、ようやくこの愛機を使って ICS のプログラミングを始めています。ここで培ったノウハウをブログで発信していけたらなと考えています。こうご期待を!


Posted by sak+

2月 10
ご無沙汰してました。
しばらく多忙な日々を送っていましたが、ようやくいろいろ落ち着いてきたのでブログを再開します。

iOS 開発の話し

去年の9月に事務所を開設したとのお話しは以前のエントリで記載していますが、そのころから iOS(具体的には iPad2)の開発案件に関わっていました。その後、12月の頭にアプリをリリースするまでほんと多忙な日々を過ごしました。その甲斐もあってリリースされたアプリは都内某所で商品検索端末として順調に稼働中です。また、評判も上々と聞いています。私も実際に稼働しているところを見に行きましたが全部で250台ほどの iPad2 が店内の至る箇所で配備され、その上で自分の作ったアプリが稼働し使用されているのを見た時にこれまでの苦労が報われた思いで感無量でした。

開発者にとって作ったアプリが実際に使われて評価されているのを見るのが一番のご褒美ですね。(^^

会社設立の話し

事務所を借りたときに実は会社設立を視野に入れていました。去年中に設立する予定だったのですが。前述の iOS 開発案件が思った以上に大変で手が回らなかったので今年にずれ込みました。2012/01/11 の登記です。会社名は「株式会社キロル」。キロルは「道」を意味するアイヌ語です。札幌の円山動物園のシロクマの名前と一緒です。(^^

株式会社キロル
http://kiroru-inc.jp/

会社のロゴです。

kiroru-320x160.png

黒バージョンもあります。(^^

kiroru-320x160-black.png

まとめ

というわけで、しばらく Android 開発から遠ざかっていたので感が鈍っていますがリハビリがてらぼちぼちやっていきます。

iOS でのアプリ開発も経験して iOS のいいところもずいぶん知った私ですが、2012年もやっぱり Android 推しでいきます。個人で使用しているメイン携帯ももちろん Android のまま。Galaxy Nexsus を発売日に入手して愛用してます。Android 4.0 になってだいぶ操作性やアプリの作成方法が変わってきていますが、その辺りも含め、このブログで引き続き情報を発信できたらなと思ってます。

これからも会社『株式会社キロル』ともどもよろしくお願いします。


Posted by sak+

10月 12
前回、「オフィスを借りました\(^O^)/」というエントリを書いてから約1月多忙にかまけてブログ更新できていませんでした。ほんと多忙なんです。(TT ここんところブログ更新の他にジム通いやオンライン英会話なんかも中断中です。でもあともう一息。一段落ついたらまたブログも再開しようと思ってます。もしかするとブログタイトルの変更もあるかも?それではまた!


Posted by sak+

9月 06
フリーランスとして活動し1年が経過しました。ここまで多くの方に助けられながらなんとかやってきましたが、今後の事業展開を考えオフィスを借りることにしました。今後はここを拠点に一層がんばっていきます。

オフィスの場所は札幌の地下鉄大通り駅にほど近いビルの一室です。この建物は事務所利用可の一般マンションですが8割方は何らかの事務所が入っているようです。まだ部屋の中には何もありません。とりあえず折りたたみテーブルと座布団を買って直ぐに仕事に入れるようにしました。もちろんネットは真っ先に繋げましたよ!

photo-0.png

窓からは札幌のテレビ塔の先っちょが見えます。時刻が見えるか見えないかの微妙な感じもご愛嬌です。

photo-1.png

テレビ塔は夜にはライトアップしてきれいです。

photo-2.png

何も無いゼロからのスタートですが気を引き締めてがんばります!


Posted by sak+

8月 26
我が家に4台目のタブレット端末として Apple の iPad2 がやってきました。Google と Android が大好きな私ですが、なんだかんだ言って Apple 製品も大好きです。

DSC_1.png

いつものように記念撮影。

DSC_2.png

他の仲間達と一緒に撮影。(左から Xoom, iPad2, Web Station)

DSC_3.png

重ねて撮影。(上から Web Station, Xoom, iPad2)

DSC_4.png

あれ?4台目って言ってなかったけ?そう Google のイベントでゲットした Optimus Pad (関連記事)が見当たりません。そうです。実は彼は今某所でハニカムの修行中なのです。きっともう直ぐ立派なハニカムアプリを携えて帰ってくる事でしょう。乞うご期待!!


Posted by sak+

Tagged with:
8月 20
前回の記事ではレイアウトファイルを使用して Fragment の生成を行いました。レイアウトが固定の場合はそれで良いのですが、レイアウトを動的に変更したい、あるいはボタンを押すなどの操作を行いその結果としてレイアウトの一部を変更させたい場合などは今回取り上げる方法が有効です。

その方法とは、予め Fragment を挿入する領域を確保し(サンプルでは LinearLayout)そこに Fragment を挿入する方法です。

今回のサンプルの画面は前回とほぼ同じです。

device-1.png

まず、レイアウトファイルでは Fragment を挿入する枠組みを用意します。

(res/layout/main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="horizontal"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   >
    <LinearLayout
       android:id="@+id/fragment1"
       android:layout_height="match_parent"
       android:layout_width="0dp"
       android:layout_weight="1"
       />
    <LinearLayout
       android:orientation="vertical"
       android:layout_height="match_parent"
       android:layout_width="0dp"
       android:layout_weight="2"
       >
        <LinearLayout
           android:id="@+id/fragment2"
           android:orientation="horizontal"
           android:layout_height="0dp"
           android:layout_width="match_parent"
           android:layout_weight="1"
           />
        <LinearLayout
           android:id="@+id/fragment3"
           android:orientation="horizontal"
           android:layout_height="0dp"
           android:layout_width="match_parent"
           android:layout_weight="2"
           />
    </LinearLayout>
</LinearLayout>

プログラムで Fragment を生成し LinearLayout で定義してあった領域に挿入します。(replace)

(Main.java)

public class Main extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        MyFragment1 df1 = MyFragment1.newInstance();
        MyFragment2 df2 = MyFragment2.newInstance();
        MyFragment3 df3 = MyFragment3.newInstance();

        FragmentTransaction ft = getFragmentManager().beginTransaction();
       
        ft.replace(R.id.fragment1, df1);
        ft.replace(R.id.fragment2, df2);
        ft.replace(R.id.fragment3, df3);
       
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        ft.commit();
    }
}

最後に commit すると反映されます。

この仕組みを使うと画面遷移にいろいろな効果を与える事ができそうです。その件についてはまたの機会にでも。

サンプルコード

サンプルアプリのソースコードは Google Code で公開しています。完全なサンプルコードを参照したい場合はそちらをどうぞ。


Posted by sak+

Tagged with:
8月 15
以前、『レイアウトを分割しよう!』という記事を書きましたがそれと同じことが fragment を使うと簡単に実現できちゃいます。Fragment は Honeycomb(Android 3.0)から導入された機能ですが、Backport を使えば、それ以前のバージョンの Android でも使用できちゃいます。Google の中の人も積極的に使ってくださいと言っていますので、これを使わない手はないですね。

Fragment を使ったサンプルはまだ意外と少ないのでなるべき最小構成でのサンプルを目指します。といってもそれだけでは寂しいのでActionButton を付けてみました。ActionButton はメニューに変わる新しい機能でよく使うボタンはメニューを開くことなく押せるようになっています。この ActionButton は Fragment をホストする Activity に付与してもいいし、Activity の中に配置する Fragment に付与してもいいです。

では、今回のサンプルアプリの画面はこちら。

device-1.png

赤(Fragment1)、緑(Fragment2)、青(Fragment3)の部分は Fragment でそれぞれ対応するレイアウトファイルを持っています。

(Main.java)

public class Main extends Activity {

    private static final int MENU_FRAGMENT_0_0 = Menu.FIRST + 0;
    private static final int MENU_FRAGMENT_0_1 = Menu.FIRST + 1;
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
   
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(0, MENU_FRAGMENT_0_0, 0, "Main_0")
            .setIcon(android.R.drawable.ic_menu_help)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
        menu.add(0, MENU_FRAGMENT_0_1, 0, "Main_1")
            .setIcon(android.R.drawable.ic_menu_compass)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
        return true;
    }
   
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        boolean result = true;
        switch (item.getItemId()){
        case MENU_FRAGMENT_0_0:
            Toast.makeText(this, "MENU_FRAGMENT_0_0 が選択された。", Toast.LENGTH_LONG).show();
            break;
        case MENU_FRAGMENT_0_1:
            Toast.makeText(this, "MENU_FRAGMENT_0_1 が選択された。", Toast.LENGTH_LONG).show();
            break;
        default:
            result = super.onOptionsItemSelected(item);
            break;
        }
        return result;
    }
}

(Fragment1.java)

public class MyFragment1 extends Fragment {

    private static final int MENU_FRAGMENT_1_0 = Menu.FIRST + 100;
    private static final int MENU_FRAGMENT_1_1 = Menu.FIRST + 101;
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        this.setHasOptionsMenu(true);
    }
   
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment1, container, false);
        return v;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, android.view.MenuInflater inflater) {
        menu.add(0, MENU_FRAGMENT_1_0, 0, "Fragment1_0")
            .setIcon(android.R.drawable.ic_menu_call)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
        menu.add(0, MENU_FRAGMENT_1_1, 0, "Fragment1_1")
            .setIcon(android.R.drawable.ic_menu_gallery)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
    }
   
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        boolean result = true;
        switch (item.getItemId()){
        case MENU_FRAGMENT_1_0:
            Toast.makeText(getActivity(), "MENU_FRAGMENT_1_0 が選択された。", Toast.LENGTH_LONG).show();
            break;
        case MENU_FRAGMENT_1_1:
            Toast.makeText(getActivity(), "MENU_FRAGMENT_1_1 が選択された。", Toast.LENGTH_LONG).show();
            break;
        default:
            result = super.onOptionsItemSelected(item);
            break;
        }
        return result;
    }
}

(res/layout/main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="horizontal"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   >
    <fragment class="sak.samples.hellofragment.MyFragment1"
       android:id="@+id/fragment1"
       android:layout_height="match_parent"
       android:layout_width="0dp"
       android:layout_weight="1"
       />
    <LinearLayout
       android:orientation="vertical"
       android:layout_height="match_parent"
        android:layout_width="0dp"
       android:layout_weight="2"
        >
        <fragment class="sak.samples.hellofragment.MyFragment2"
           android:id="@+id/fragment2"
           android:orientation="horizontal"
           android:layout_height="0dp"
           android:layout_width="match_parent"
           android:layout_weight="1"
           />
        <fragment class="sak.samples.hellofragment.MyFragment3"
           android:id="@+id/fragment3"
           android:orientation="horizontal"
           android:layout_height="0dp"
           android:layout_width="match_parent"
           android:layout_weight="2"
           />
    </LinearLayout>
</LinearLayout>

(res/layout/fragment1.xml)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:background="#ff00"
   >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Fragment 1"
        android:textColor="#ffff"
        android:textSize="64sp"
       />        
</RelativeLayout>

サンプルコード

サンプルアプリのソースコードは Google Code で公開しています。完全なサンプルコードを参照したい場合はそちらをどうぞ。


Posted by sak+

Tagged with:
preload preload preload