常に新しい端末に適応する

2010年5月27日(木)
有山 圭二(ありやま けいじ)

センサー依存を解決する

Android端末には、さまざまなセンサーが搭載されていますが、すべての端末に全く同じセンサーが付いているという保証はありません。

第1回でも述べたとおり、HT-03Aには温度センサーが搭載されていますが、Xperiaには有りません。従って、温度センサーがあることを前提に開発されたアプリケーションは、Xperiaでは動作しません。逆に、Xperiaにある近接センサーや照度センサーは、HT-03Aにはないので、同じことが言えます。

複数端末対応では、このような搭載センサーの違いに応じて、きちんと対応できるように開発をする必要があります。

サンプル・コード「SensorTestActivity.java」を見てみましょう。

	<code>
@Override
<font color="red">public void</font> onCreate(Bundle savedInstanceState) {
        <font color="red">super</font>.onCreate(savedInstanceState);
        setContentView(R.layout.<font color="blue">main</font>);

        StringBuilder sb = <font color="red">new</font> StringBuilder();

        <font color="red">int</font> targetSensorType = Sensor.<font color="blue">TYPE_ALL</font>;
<font color="green">//      targetSensorType = Sensor.TYPE_ACCELEROMETER;
//      targetSensorType = Sensor.TYPE_LIGHT;
//      targetSensorType = Sensor.TYPE_PROXIMITY;
//      targetSensorType = Sensor.TYPE_TEMPERATURE;
</font>
        <font color="blue">mSensorManager</font> = (SensorManager)getSystemService(Context.<font color="blue">SENSOR_SERVICE</font>);
        List<sensor> list = <font color="blue">mSensorManager</font>.getSensorList(targetSensorType);
        <font color="red">if</font> (list.size() == 0) {
                ((TextView)findViewById(R.id.<font color="blue">text_view</font>)).setText(<font color="blue">"NO SENSOR"</font>);
        } <font color="red">else</font> {
                <font color="red">for</font> (Sensor sensor : list) {
                        <font color="blue">mSensorManager</font>.registerListener(this, sensor,
                        SensorManager.<font color="blue">SENSOR_DELAY_UI</font>);
                        sb.append(sensor.getName());
                        sb.append(<font color="blue">" "</font>);
                        sb.append(sensor.getVendor());
                        sb.append(<font color="blue">" "</font>);
                        sb.append(sensor.getResolution());
                        sb.append(<font color="blue">" "</font>);
                        sb.append(sensor.getPower());
                        sb.append(<font color="blue">"\n"</font>);
                }
                ((TextView)findViewById(R.id.<font color="blue">text_view</font>)).setText(sb.toString());
        }
}
</sensor></code>





onCreateの中で、SensorManagerを取得した後、getSensorListメソッドを使って利用できるセンサーの一覧を取得し、その後、一覧の中から目的のセンサーにリスナーを登録しています。

目的のセンサーが存在しない場合は、getSensorListメソッドで取得できる一覧のサイズが0になります。ここで、「センサーが利用できない」と表示することができます。

端末に応じて最適なロケーション・プロバイダを選択する

ご存じのように、Androidでは、端末の位置情報を簡単に取得できます。しかし、位置情報を取得する手段は1つではなく、手段の有無も保証されていないことに注意する必要があります。

現在、一般的なAndroid端末で対応している位置情報の取得手段は、2つあります。

1つは、端末に内蔵されたGPS(衛星利用測位システム)ユニットが受信する衛星の電波を元に位置を計測する方法です。もう1つは、携帯端末が通信している基地局の情報に基づいて位置を取得する情報です。

これら位置情報の取得手段を「ロケーション・プロバイダ」と言います。

携帯端末の状態や、ユーザーによる設定によって、利用できるロケーション・プロバイダは変わります。

例えば、設定でGPSを無効にしていた場合は、GPSユニットによる位置情報の取得はできません。それと同様に、携帯電話が圏外であった場合(またはSIMカードがない場合)は、基地局情報に基づいた位置情報の取得はできません。

また、今後は、位置情報の取得に対応していない端末が発売されることも考えられます(実際、携帯電話以外のタブレットAndroid端末には、位置情報が取得できないものがあります)。反対に今後、GPSや基地局情報による位置情報以外のロケーション・プロバイダが追加された端末が発売される可能性もあります。

このような端末ごとの差を吸収して、状況に応じて最適なロケーション・プロバイダを自動的に選択する仕組みを、Androidのフレームワークは用意しています。

それが、LocationManagerのgetBestProviderメソッドです。

getBestProviderメソッドは、条件に応じて最適なロケーション・プロバイダを選択して、名前を返します。

サンプル・コード「LocationTestActivity.java」を見てみましょう。

	<code>
@Override
<font color="red">public void</font> onCreate(Bundle savedInstanceState) {
        <font color="red">super</font>.onCreate(savedInstanceState);
        setContentView(R.layout.<font color="blue">main</font>);

        <font color="blue">mLocationManager</font> = (LocationManager)getSystemService(
                Context.<font color="blue">LOCATION_SERVICE</font>);
<font color="green">        /*
         * LocationProviderを取得する条件を設定
         */</font>
        Criteria criteria = <font color="red">new</font> Criteria();
        criteria.setAccuracy(Criteria.<font color="blue">ACCURACY_COARSE</font>);
        criteria.setPowerRequirement(Criteria.<font color="blue">POWER_LOW</font>);
        criteria.setSpeedRequired(<font color="red">false</font>);
        criteria.setAltitudeRequired(<font color="red">false</font>);
        criteria.setBearingRequired(<font color="red">false</font>);
        criteria.setCostAllowed(<font color="red">false</font>);

        String provider = <font color="blue">mLocationManager</font>.getBestProvider(
                criteria, <font color="red">true</font>);

                ((TextView)findViewById(R.id.<font color="blue">text_view</font>))
                .setText(<font color="blue">"provider = "</font> + provider);

        <font color="blue">mLocationManager</font>.requestLocationUpdates(
                provider, 1000, 10, <font color="red">this</font>);
}
</code>





onCreateの中で、LocationManagerを取得した後、getBestProviderメソッドを実行して、最適なロケーション・プロバイダを取得しています。

第1引数に指定するCriteriaオブジェクトは、取得したいロケーション・プロバイダの条件を指定するものです(詳細は次ページ)。

また、boolean型の引数をtrueにすると、現在有効なロケーション・プロバイダのみに限定して取得します。

このように、使用するロケーション・プロバイダをgetBestProviderメソッドを通じて選択することで、利用可能なロケーション・プロバイダが端末ごとに違う場合でも、最適なロケーション・プロバイダから位置情報を取得できます。

なお、指定する条件に一致するロケーション・プロバイダが全く無い場合は、nullが返るので、「位置情報を取得できない」などのメッセージを表示できます。

最後のページでは、getBestProviderの第1引数、Criteriaに指定できる条件について説明します。

著者
有山 圭二(ありやま けいじ)

有限会社シーリス代表。日本Androidの会 運営委員。手間暇かけてくだらないことをするのが大好きで、2007年11月にAndroidの発表を知り「All applications are created equal」の言葉に惹かれて参入。代表的な開発アプリは「MoreLocale 2」、「近藤昭雄シリーズ(憂鬱・退屈)」、「薬検索」など。twitter ID: keiji_ariyama

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています