mixi engineer blog

*** 引っ越しました。最新の情報はこちら → https://medium.com/mixi-developers *** ミクシィ・グループで、実際に開発に携わっているエンジニア達が執筆している公式ブログです。様々なサービスの開発や運用を行っていく際に得た技術情報から採用情報まで、有益な情報を幅広く取り扱っています。

Androidの機種依存問題を吸収するプロジェクトAndroid-Device-Compatibilityを公開したお話

こんにちは。Androidユニットで開発とスクラムマスターをしています、横幕です。すっかり寒くなって、朝起きるのが辛い季節になりました。

先日、Android(TM)の様々な機種に依存する問題を吸収するためのライブラリプロジェクトをmixi, IncのGitHubリポジトリで公開しました。

今回は、このライブラリプロジェクトを公開するに至った経緯をお話しようと思います。

続きを読む

Titanium? いいえ、Triainaです。

どうも、5ヶ月ぶりのブログ投稿です、佐野です。僕は2012年8月よりメッセージユニットに加わり、主にiPhone公式クライアントにおけるメッセージ機能の改修に携わっておりました。

mixi Touch(スマートフォンブラウザ版)では2012年10月より一部のユーザに向けてmixiメッセージにおけるリアルタイムコミュニケーションを実現するための新UIを提供しておりました。この機能が近いうちに mixi の iPhone版、Android 版 公式クライアントでも利用できるようになります。

 
triaina1.png
(画面は開発中のイメージです)
続きを読む

続・Android開発のちょっとしたお話

こんにちは。横幕です。
今回もAndroid(TM)開発についてお話をしたいと思います。

設定画面の作り込み

今回のトピックは、設定画面のちょっとした工夫の仕方についてです。

Androidでは、PreferenceActivityという設定画面を作るためのActivityが用意されています。
個々の設定項目はXMLで記述し、それをPreferenceActivityがコントローラとして画面を制御するような形になります。

設定画面の大まかな作り方

まずは、どんな設定項目を準備するのかを、res/xml/pref.xmlに定義します。
Androidには予め幾つかの設定方法を用意してあり、例えば項目の一覧の中から1つ選択するListPreferenceや、チェックボックスの状態で設定を変更するCheckBoxPreferenceなどがあります。
また、設定項目のまとまりごとにカテゴライズするためのPreferenceCategoryも用意されており、これらを組み合わせて設定画面に表示するものを記述してきます。

* res/xml/pref.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <PreferenceCategory android:title="設定1">
        <CheckBoxPreference
            android:key="checkbox_1"
            android:title="チェックボックス1"
            android:summaryOn="チェックしました"
            android:summaryOff="チェックしていません"/>
        <ListPreference
            android:key="list_1"
            android:title="リスト1"
            android:summary="選択した項目"
            android:dialogTitle="選んでください"
            android:entries="@array/list_entries"
            android:entryValues="@array/list_entry_values"/>
    </PreferenceCategory>
    <PreferenceCategory android:title="設定2">
        <EditTextPreference
            android:key="edit_text_1"
            android:title="テキスト1"
            android:summary="入力した内容"
            android:dialogTitle="入力してください"/>
    </PreferenceCategory>
</PreferenceScreen>

* res/values/arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="list_entries">
        <item>First Element</item>
        <item>Second Element</item>
        <item>Third Element</item>
    </string-array>
    <string-array name="list_entry_values">
        <item>First Value</item>
        <item>Second Value</item>
        <item>Third Value</item>
    </string-array>
</resources>

設定項目のスタイルに応じて、記述するアトリビュートも変わってきますね。
android:keyは、設定を読み書きするために使う情報です。キーとバリューのペアで扱うイメージですね。
android:titleには、何を設定するのかを記述します。例えば、「文字の大きさ」と言った具合です。
android:summaryには、実際に何が設定されているかを記述します。「文字の大きさ」であれば、「14pt」などですね。
これ以外にも、ダイアログを表示するListPreferenceやEditTextPreferenceには、ダイアログのタイトルのアトリビュート(android:dialogTitle)や、
一覧の項目を設定するためのアトリビュート(android:entries、android:entryValues)などが用意されています。

これらのアトリビュートはプログラムで簡単に操作できるようになっています。

次にプログラム側の作り方を見ていきましょう。
設定画面は、PreferenceActivityを継承して作ります。
通常のActivityと違うのは、onCreateをオーバライドしたときに、setContentView()でレイアウトを指定するのではなく、addPreferencesFromResource()でpref.xmlを読み取ることです。

* MyPreferenceActivity.java

package com.text.app05;

import android.os.Bundle;
import android.preference.PreferenceActivity;

public class MyPreferenceActivity extends PreferenceActivity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.pref);
  }
}

* AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.app04"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="8" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".Example05Activity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:label="@string/app_name"
            android:name=".MyPreferenceActivity" >
        </activity>
    </application>
</manifest>

これだけで、設定画面を表示することができ、実際に設定内容の読み出し・保存も出来ているはずです。

画面1

しかし、このままでは設定内容に応じて見た目を変更することができません。
設定に変更があったことを知るには、OnPreferenceChangeListenerを実装する必要があります。

package com.test.app05;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceActivity;

public class MyPreferenceActivity extends PreferenceActivity {
    private ListPreference mListPreference;
    private EditTextPreference mEditTextPreference;
    private SharedPreferences mSharedPreference;
    private OnPreferenceChangeListener mListPreferenceListener = new OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            preference.setSummary((String) newValue);
            return true;
        }
    };
    private OnPreferenceChangeListener mEditTextPreferenceListener = new OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            preference.setSummary((String) newValue);
            return true;
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.pref);

        mSharedPreference = PreferenceManager.getDefaultSharedPreferences(this);
        mListPreference = (ListPreference)findPreference("list_1");
        mEditTextPreference = (EditTextPreference)findPreference("edit_text_1");

        mListPreference.setSummary(mSharedPreference.getString("list_1", "First Value"));
        mListPreference.setOnPreferenceChangeListener(mListPreferenceListener);
        mEditTextPreference.setSummary(mSharedPreference.getString("edit_text_1", "Not assigned"));
        mEditTextPreference.setOnPreferenceChangeListener(mEditTextPreferenceListener);
    }
}

個々の設定項目(Preference)を取得するには、findPreference()を利用します。引数にandroid:keyアトリビュートの値を指定することで特定します。
そして、取得してきたPreferenceにOnPreferenceChangeListenerをセットします。
これで、設定を変更すると、それに応じて内容の表示も切り替えることができるようになりました。

画面2

表現の工夫

設定、と一口に言っても、実際の関心は、文字の大きさ・着信音・背景色・時間など、多岐にわたります。

そのような関心の中で、現在設定されている内容を表示することを考えてみると、
例えば、文字の大きさであれば、現在設定されている内容の表現として、「大」「中」「小」と言った表示の表現がありますし、
時間についても、「1時間ごと」「2時間ごと」等と言った表現が考えられます。

ではここで、色の設定について考えてみたいと思います。

今何色に設定しているか、を表示したい場合、色の名前を表示するという手段もありますが、
直感的には、色そのものを表示したほうが、分かりやすさがぐっと向上すると思います。

実装方法

設定画面の個々の項目には、widgetLayoutというアトリビュートがあります。
公式開発ドキュメントには、レイアウトへのリファレンスを記述することができることが書かれています。実際、チェックボックスを表示するCheckboxPreferenceもこのwidgetLayoutを利用して作られているようです。
つまり、このwidgetLayoutに独自のレイアウトのリファレンスを記述すれば、チェックボックス以外のViewを表示することができることになります。

例えば、先程のpref.xmlの、ListPreferenceにwidgetLayoutを利用してみると...

* pref.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <PreferenceCategory android:title="設定1">
        <CheckBoxPreference
            android:key="checkbox_1"
            android:title="チェックボックス1"
            android:summaryOn="チェックしました"
            android:summaryOff="チェックしていません"/>
        <ListPreference
            android:key="list_1"
            android:title="リスト1"
            android:summary="選択した項目"
            android:dialogTitle="選んでください"
            android:entries="@array/list_entries"
            android:entryValues="@array/list_entry_values"
            android:widgetLayout="@layout/indicator"/>
    </PreferenceCategory>
    <PreferenceCategory android:title="設定2">
        <EditTextPreference
            android:key="edit_text_1"
            android:title="テキスト1"
            android:summary="入力した内容"
            android:dialogTitle="入力してください"/>
    </PreferenceCategory>
</PreferenceScreen>

* indicator.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentTop="true">
    <View
        android:id="@+id/indicator"
        android:layout_width="30dip"
        android:layout_height="30dip"
        android:background="#FF0000"/>
</FrameLayout>

画像4

このように表示されるはずです。

レイアウトへのリファレンスですから、Viewに限らず、ImageViewを置いて画像を表示する、ということも実現可能ですね。

せっかくですから、項目に応じてViewの色を変更してみましょう。

widgetLayoutを操作するには、ListPreferenceを拡張する必要があります。
ListPreferenceを継承し、onBindView()の中で、widgetLayoutのViewを取り出して、背景色を変更します。

package com.test.app05;

import com.test.app05.R;
import android.content.Context;
import android.graphics.Color;
import android.preference.ListPreference;
import android.util.AttributeSet;
import android.view.View;

public class MyListPreference extends ListPreference {
    public MyListPreference(Context context) {
        super(context);
    }

    public MyListPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onBindView(View view) {
        super.onBindView(view);
        View v = view.findViewById(R.id.indicator);
        if ("First Value".equals(getValue())) {
            v.setBackgroundColor(Color.RED);
        } else if ("Second Value".equals(getValue())) {
            v.setBackgroundColor(Color.BLUE);
        } else if ("Third Value".equals(getValue())){
            v.setBackgroundColor(Color.GREEN);
        } else {
            v.setBackgroundColor(Color.RED);
        }
    }
}

また、pref.xmlのListPreferenceを、独自に定義したMyListPreferenceに変更します。
要素名をFQNで指定するだけで完了です。


<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <PreferenceCategory android:title="設定1">
        <CheckBoxPreference
            android:key="checkbox_1"
            android:title="チェックボックス1"
            android:summaryOn="チェックしました"
            android:summaryOff="チェックしていません"/>
        <com.test.app05.MyListPreference
            android:key="list_1"
            android:title="リスト1"
            android:summary="選択した項目"
            android:dialogTitle="選んでください"
            android:entries="@array/list_entries"
            android:entryValues="@array/list_entry_values"
            android:widgetLayout="@layout/indicator"/>
    </PreferenceCategory>
    <PreferenceCategory android:title="設定2">
        <EditTextPreference
            android:key="edit_text_1"
            android:title="テキスト1"
            android:summary="入力した内容"
            android:dialogTitle="入力してください"/>
    </PreferenceCategory>
</PreferenceScreen>

これで、設定の内容に応じてwidgetLayoutの背景色を変更することができるようになりました。

画像4

終わりに

今回は設定画面の作り込みについてのお話でした。
利用頻度はそれほど高くない場所かもしれませんが、だからこそ、使い方を学習する手間・思い出す手間が極力少ないUI設計にしていくことが重要になってくるのだと思います。

最後になりましたが、先日弊社主催のAndroid開発イベント「Build Challenge for Android」が開催されました。
その際に使用したスライド資料を掲載致しますので、こちらも合わせて参考にしていただければと思います。

Android開発のちょっとしたお話

こんにちは。新卒入社で今年から働き始めました、横幕です。現在は、mixiのAndroid(TM)版公式クライアントアプリを開発しています。

Android開発を始めてから数か月になりますが、今回は、開発に携わる中で知ったことをご紹介したいと思います。

レイアウトの複雑さで発生するStackOverFlowError

Androidでは、見た目(UI)のデザインやレイアウトをXMLで記述することができます。XMLを書くときには、UIのパーツ(ウィジェット:ボタンやチェックボックスなど)のほか、ウィジェットの配置を決めるためのコンテナ(LinearLayoutやFrameLayoutなど)を用います。そして、それらを入れ子にしながら画面を設計していきます。

たとえば、以下のような感じに。
* main.xml

<?xml version="1.0" encoding="utf-8"?>
 
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical">
  <Button
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="ボタン"/>
  <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="テキスト"/>
  <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <Button
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="0.3"
      android:text="ホゲホゲ"/>
    <Button
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="0.7"
      android:text="フガフガ"/>
  </LinearLayout>
</LinearLayout>

また、XMLで画面を作っていると、あるパーツは他の画面でも使いたいので、その部分だけ切り出したいということがよくあります。
そのような場合には、切り出したい部分だけを記述したXMLを用意し、使いたい場所でインクルードするという方法が利用できます。

* main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical">
  <Button
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="ボタン"/>
  <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="テキスト1"/>
  <include layout="@layout/hogehoge"/>
</LinearLayout>

* hogehoge.xml

<?xml version="1.0" encoding="utf-8"?>
  <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <Button
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="0.3"
      android:text="テキスト2"/>
    <Button
      android:layout_width="0dip"
      android:layout_height="wrap_content"
      android:layout_weight="0.7"
      android:text="テキスト3"/>
  </LinearLayout>

入れ子の深さにご用心

さて、このようにしながら画面を作っていると、コンテナの入れ子が深くなったり、複雑になったりしてきます。
特に、コンテナの入れ子の深さには注意が必要です。
というのも、あまりにコンテナの入れ子が深くなりすぎると、StackOverFlowErrorが発生して強制終了の原因になるからです。
パーツごとに切り出してXMLを書いている場合には、特に注意が必要です。

Android 1.5の場合、Androidが持っているスタックの大きさは8KBになっています
このため、TabHostを使って画面を作った場合に、12回程度の入れ子を作るとStackOverFlowErrorになる例もあったようです。

検証してみる

では、Android 2.xになった現在、具体的にどの程度の深さでStackOverFlowが発生するのか、手持ちのGalaxy S2(Android2.3.3)で検証してみました。

まず始めに、LinearLayoutの入れ子を単純に増やし続けてみます。

* 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">
  <LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    ...
    <LinearLayout
      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="こんにちは"/>
    </LinearLayout>
  ...
  </LinearLayout>
</LinearLayout>

すると、25回の入れ子を作ったところでアプリがStackOverFlowErrorで強制終了しました。

次に、ListViewを使って、Listの各要素のレイアウトに入れ子構造を作った場合にどうなるか試してみました。
* MainActivity

package com.test.app02;
 
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
 
public class MainActivity extends Activity {
	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        String[] data = new String[]{"hoge", "fuga"};
        ListView list = (ListView)findViewById(R.id.ListView);
        list.setAdapter(new MyAdapter(this, R.layout.list_item, data));
    }
 
    private class MyAdapter extends ArrayAdapter {
        private String[] data;
        private LayoutInflater inflater;
 
        public MyAdapter(Context context, int resourceId, String[] data) {
            super(context, resourceId, data);
            this.data = data;
            this.inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
 
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                v = inflater.inflate(R.layout.list_item, null);
            }
            TextView text = (TextView)v.findViewById(R.id.string);
            text.setText(data[position]);
            return v;
        }
    }
}

* 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">
  <ListView
    android:id="@+id/ListView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>
</LinearLayout>

* list_item.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">
  <LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    ...
    <LinearLayout
      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="こんにちは"/>
    </LinearLayout>
  ...
  </LinearLayout>
</LinearLayout>

今度は、list_item.xmlの中のLinearLayoutを22回入れ子にしたところでStackOverFlowErrorとなりました。

最後に、TabHostを使って試してみました。
* MainActivity

package com.test.app03;
 
import android.app.TabActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;
 
public class MainActivity extends TabActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TabHost tabHost = getTabHost();
        LayoutInflater.from(this).inflate(R.layout.main, tabHost.getTabContentView(), true);
        TabSpec tab1 = tabHost.newTabSpec("Tab1");
        tab1.setIndicator("1");
        tab1.setContent(R.id.tab1);
        TabSpec tab2 = tabHost.newTabSpec("Tab2");
        tab2.setIndicator("2");
        tab2.setContent(R.id.tab2);
        tabHost.addTab(tab1);
        tabHost.addTab(tab2);
        tabHost.setCurrentTab(0);
    }
}

* 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">
  <TabHost
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TabWidget
      android:id="@android:id/tabs"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"/>
    <FrameLayout 
      android:id="@android:id/tabcontent"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content">
      <include 
        layout="@layout/tab_content"
        android:id="@+id/tab1"/>
      <include
        layout="@layout/tab_content"
        android:id="@+id/tab2"/>
    </FrameLayout>
  </TabHost>
</LinearLayout>

* tab_content.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">
  <LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    ...
    <LinearLayout
      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="こんにちは"/>
    </LinearLayout>
  ...
  </LinearLayout>
</LinearLayout>

TextViewが入れ子の中に1つあるだけの単純な構造ですが、20回の入れ子を作った所でStackOverFlowErrorとなりました。

今回は、単純にコンテナの入れ子を増やすだけで検証してみましたが、実際には、もっと複雑な作りになるはずですし、レイアウトをプログラムで動的に制御したいというような場面も出てくると思います。
そのようなときに、StackOverFlowErrorに出くわしたら、レイアウトの入れ子が深くなりすぎていないか、
Hierarchy Viewerなどを使って探ってみると良いかもしれません。
(ちなみに、Android4.0のエミュレータ上で実行したところ、どのコードもすんなり実行することができました。)

終わりに

今回は、かなりこまごまとしたお話になりましたが、いかがでしたでしょうか。
この記事が何かのお役に立つことが出来れば幸いです。

mixi Girls Hackathon featuring Android 女子部 の参加者募集

みなさま、はじめまして!
お花が好きな女性エンジニアのすずです
プラットフォームサービス開発部にてmixi Graph APIの開発をしています。

弊社の@yoichiroがmixi Hackathonを主催し毎回多くの開発者の方にご参加頂いていますが、
女性開発者の方々も気軽にご参加いただけるように女性限定イベント
mixi Girls event」を立ち上げることにしました
"event"は企画により毎回変わります。

記念すべき第1回目が決まりましたのでご紹介します!

mixi Girls Hackathon featuring Android 女子部

第1回目はAndroid女子部さんと共催で、
弊社の「mixi API SDK for Android?」を使ったソーシャルAndroidアプリのHackathonをします。
「mixi API SDK for Android?」は面倒な認証認可処理も肩代わりしますので、
簡単にソーシャルAndroidアプリを作ることができます!
弊社社員もチューターとして参加しますし、
今回はハイスキルなAndroid女子部の方たちもチューターとしてアプリ作成をサポートしてくれますっ

女子同士楽しくおしゃべりしながら、アプリをつくりましょう

mixi API SDK for Android?についてはこちらをご覧ください。
http://developer.mixi.co.jp/connect/mixi_graph_api/android/
対象OSは2.2〜です。

■日時
8/6(土) 10:00〜18:00くらい

■内容
10:00 - 10:05 開始のごあいさつ
10:05 - 10:15 Android女子部の紹介 (どなたか)
10:15 - 10:35 女子目線のアプリ (@asyoulike007)
10:35 - 11:05 SDK 使い方のご紹介 (@hidey)
11:05 - 11:15 -- 休憩 --
11:15 - 11:30 チーム分け&自己紹介
11:30 - 12:30 アイデア出し
12:30 - 13:30 -- 昼食 --
13:30 - 17:00 コーディング
17:00 - 17:30 発表

■申し込み
定員:30名
Android女子部さんが用意してくださったATNDにて、申し込みをお願いします。
http://atnd.org/events/17697

■会場
株式会社ミクシイ 本社 7F 0725 セミナールーム
東京都渋谷区東1-2-20 住友不動産渋谷ファーストタワー7F (地図はこちら)

■持ち物
* 無線LAN接続ができるノートパソコン (会場にはゲスト用無線LANがあります)

■事前準備 コーディングの時間を多くとるため、以下の準備をお願いします。

ぜひ、ご参加ください!お待ちしております。
またイベント共催などのお問い合わせもお待ちしております。
お問い合わせは、support-mixihackathonあっとmixi.co.jp までよろしくお願い致します。
flower

Android向けmixi公式クライアントを公開しました

はじめまして!新卒で入社した藤崎友樹です。 ...と書こう書こうと思って、うっかり 2 年半が過ぎ去ってしまいました。システム本部技術部たんぽぽグループの rai と申します。

Android 端末をご利用中の方へ、クリスマスプレゼント!

本日、 Android 端末向けの mixi 公式クライアントアプリケーションをリリースしました。 Android 端末をご利用の方は、マーケットより「mixi」で検索していただくとダウンロードできるようになっています。以前のプレスリリースでは、 Android 2.2 以上対応となっていたため、残念な思いをされた方もご安心ください。 2.1 でもご利用いただけるようになっております。
screenshot 1 screenshot 2
本日リリースのアプリでは、つぶやきと友人の最新情報の閲覧、フォトのアップロード、あとチェックインをご利用いただけます。端末に標準で用意されている写真ギャラリーの「共有」メニューから、mixiフォトへのアップロードが簡単に行えるほか、フォト付きのつぶやきも、アプリから手軽にご利用いただけるようになりました。つぶやきにイイネ!をつけたり、コメントをするのも簡単です。

また、クライアントアプリケーションとしても、できるだけ使いやすくなるよう心がけています。たとえば、スライドキーボード付きの端末などで横に向けて使った時でも、タイトルやメニューバーは横に避けて、上下の表示領域を最大限取ることで、狭さを軽減しています。発言の投稿やフォトのアップロードは、バックグラウンドで行うため、投稿完了を待つ必要はありません。さらに、電波状態が悪くてつぶやきの投稿に失敗してしまっても、書いた発言は失われず、失敗の旨を表示している通知バーより元の状態に復元できるようになっています。

一方で、今回リリースしたアプリは、正直なところ、機能数としてはまだまだ不足があり、クライアントとして実装が及んでいない部分に関しては、潔くデフォルトのブラウザの mixi Touch へ飛ばしてしまっています。これを、埋込みのブラウザ (WebView) で実装するという選択もあったのですが、
  • Android には戻るボタンがあり、ブラウザに遷移してもすぐに前の画面に戻ることができる
  • 普段使っているブラウザのCookieが使えるため、各種ページでのログインセッションがそのまま生きる
  • 普段から使っているブラウザの機能(ブックマークなど)をそのまま使うことができる
  • リンク先の URL に対して Intent Filter が仕掛けられている場合、直接遷移できる
といった利点もあるため、今回は直接ブラウザに遷移させるように実装しています。このような、まだまだ改善が行えそうな部分に関しては、今後の機能の拡充に合わせて調整していく見込みです。

これから、 mixi をもっと様々な場面で活用できるよう、今後に向けた検討を続けていきます。 mixi 上のサービスを利用できることはもちろんですが、 Android らしく、他のアプリケーションから連携しやすいよう、各種 Intent や Account Manager, Content Provider を用いた Android 開発者向け情報も充実させていくことを検討しています。先日から、一般の開発者の方にも mixi Connect の Graph API がご利用いただけるようになりましたが、公式クライアントがインストールされている Android 上ではさらに、ユーザーがログイン情報の入力を省略できるようになるなど、便利な機能を提供していく見込みです。アップデートにご期待ください。

ちなみに、今回のクライアントアプリケーションは、 11 月スタートという割とタイトなスケジュールで開発を行っています。チームも、ディレクター 1 人、プログラマー 2 人、デザイナー 1 人、テスター 2 人、といった小規模なものです。私自身、スタート時点で、個人で細々としたアプリの開発経験はあれど、ガッツリと作り込むのは初めてという状態でした。短い期間に、色々詰め込んだり、あーでもないこーでもないと試行錯誤を繰り返していたら、間違いなく痛い目に遭ってオシマイになってしまうのが目に見えていたため、急いで本屋に駆けこんで(ギリギリにならないと動き出せません)アジャイル開発に関する書籍にあたり、 Hudson と Android Emulator Plugin を用いた自動ビルド環境の構築、 Test Driven Development といったアジャイルのプラクティスの数々(と書いて文明の利器と呼ぶ)を積極的に取り込むことで、無事リリースに至る事ができました。このあたりの詳しいお話も、またどこかのタイミングで書けたらなと思います。

年末年始、簡単になったフォト付きのつぶやきやチェックインをお楽しみください。メリークリスマス!
(ちなみに、今日は「クリスマスを1人ですごさない会」という会合に参加します)