ヘッドセットプラグの状態変化を監視するACTION_HEADSET_PLUG - ReDo

2011年1月 4日

ヘッドセットプラグの状態変化を監視するACTION_HEADSET_PLUG

あけましておめでとうございました。本年もよろしくお願いします。 今年はもう少しこのblogも放置プレイから脱出したいところです。

A4:Ahoな Android Application Award
http://ahoapp.appspot.com/

上記のA4をターゲットとして、ACTION_HEADSET_PLUGトリガで画像を揺らす低空飛行な「InsertDroid」というアプリを思いついたのですが、オチとして肝心のプラグ検出周期が1Hz(秒間1回)程度のため、実用(?)にはほど遠くお蔵入りと相成りました。

20110102_insert.jpg

以下、コード等は続きに。

  • ヘッドセットのプラグの状態が変化すると、Broadcast IntentでACTION_HEADSET_PLUGが飛びます。
  • IntentFilterにIntent.ACTION_HEADSET_PLUGをセットしたBroadcastReceiverをregisterします。
  • AndroidManifest.xmlで宣言したreceiverでは受け取れない問題がある様なので動的にReceiverを生成した方が良さそうです。
    • そもそもBroadcast Intentの中にはmanifest記載では捕まえられないものがいくつかあるのでそのうちの1つなのかもしれません。
  • BroadcastReceiver#onReceiveのIntentからgetIntExtra("state")するとプラグ状態が同時に取れます。0が抜けている、で1が挿さっている状態です。
    • X06HT(HTC Desire)ではregister直後に必ず現在のプラグ状態のイベントが飛んできました。全機種で必ずこうなのかは分かりません。
  • ヘッドセットが抜けたりBluetoothのA2DP接続が切れた際に「音が急に大きくなるよ!」という意味でのAudioManager.ACTION_AUDIO_BECOMING_NOISYという別のBroadcast Receiverもあるので、用途によってはこちらを使う方が良いかもしれません。
package youten.redo.insert;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;

/**
 * ヘッドセットの挿抜を検出するアプリ
 */
public class MainActivity extends Activity {
    /** ログタグ */
    private static final String TAG = "InsertDroid";
    /** REQUEST:画像選択 */
    private static final int REQUEST_IMAGE_SELECT = 1;
    /** MENU:画像選択 */
    private static final int MENU_IMAGE_SELECT = 1;

    /** ヘッドセットプラグ状態取得Intent Filter */
    private static IntentFilter plugIntentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
    /** 指令を飛ばすBroadCastReceiver */
    private static BroadcastReceiver plugStateChangeReceiver = null;
    /** 前面ImageView */
    private static ImageView frontImage = null;
    /** Animation in */
    private static Animation inAnim = null;
    /** Animation out */
    private static Animation outAnim = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        frontImage = (ImageView) findViewById(R.id.frontImage);

        // Animation preload
        inAnim = AnimationUtils.loadAnimation(this, R.anim.y_translate_in);
        outAnim = AnimationUtils.loadAnimation(this, R.anim.y_translate_out);

        plugStateChangeReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // plug状態を取得
                boolean isPlugged = false;
                if (intent.getIntExtra("state", 0) > 0) {
                    isPlugged = true;
                }

                // plug状態でメッセージを変更。
                if (isPlugged) {
                    // ヘッドセットが挿された
                    if (frontImage != null) {
                        frontImage.startAnimation(inAnim);
                    }
                } else {
                    // ヘッドセットが抜かれた
                    if (frontImage != null) {
                        frontImage.startAnimation(outAnim);
                    }
                }
            }
        };
    }

    @Override
    protected void onResume() {
        super.onResume();
        // headset plug状態 Broadcast Receiver登録
        registerReceiver(plugStateChangeReceiver, plugIntentFilter);
    }

    @Override
    protected void onPause() {
        super.onPause();
        // headset plug状態 Broadcast Receiver登録解除
        unregisterReceiver(plugStateChangeReceiver);
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(0, MENU_IMAGE_SELECT, 0, android.R.string.search_go).setIcon(android.R.drawable.ic_menu_gallery);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case MENU_IMAGE_SELECT:
            // 画像を選択。
            Intent intent = new Intent(Intent.ACTION_PICK);
            intent.setType("image/*");
            startActivityForResult(intent, REQUEST_IMAGE_SELECT);
            break;
        default:
        }
        return true;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
        case REQUEST_IMAGE_SELECT:
            if (resultCode == RESULT_OK) {
                Uri uri = data.getData();
                if ((uri != null) && (frontImage != null)) {
                    frontImage.setImageURI(uri);
                }
            }
            break;
        default:
        }
    }

}

コメントする