サンプル作成

なんか微妙なサンプルを作成しようとしています。メモを以下に。

とりあえず

加速度センサをナニして shake 判定なサンプルをでっち上げてます。

package com.example.sampleaccelerometer;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.widget.Toast;

public class MainActivity extends Activity {
        private SensorManager mySensorManager;
        
        /* Here we store the current values of acceleration, one for each axis */
        private float xAccel;
        private float yAccel;
        private float zAccel;

        /* And here the previous ones */
        private float xPreviousAccel;
        private float yPreviousAccel;
        private float zPreviousAccel;

        /* Used to suppress the first shaking */
        private boolean firstUpdate = true;

        /*What acceleration difference would we assume as a rapid movement? */
        private final float shakeThreshold = 1.5f;
        
        /* Has a shaking motion been started (one direction) */
        private boolean shakeInitiated = false;

        
        private final SensorEventListener mySensorEventListener = new SensorEventListener() {

                @Override
                public void onAccuracyChanged(Sensor sensor, int accuracy) {
                        // TODO Auto-generated method stub
                        
                }

                @Override
                public void onSensorChanged(SensorEvent event) {
                        updateAccelParameters(event.values[0], event.values[1], event.values[2]);
                        if ((!shakeInitiated) && isAccelerationChanged()) {
                                shakeInitiated = true; 
                        } else if ((shakeInitiated) && isAccelerationChanged()) {
                                executeShakeAction();
                        } else if ((shakeInitiated) && (!isAccelerationChanged())) {
                                shakeInitiated = false;
                        }
                }
                                
        };
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                mySensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); // (1)
                mySensorManager.registerListener(mySensorEventListener, mySensorManager
                                .getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                                SensorManager.SENSOR_DELAY_NORMAL);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu; this adds items to the action bar if it is present.
                getMenuInflater().inflate(R.menu.main, menu);
                return true;
        }

        /* Store the acceleration values given by the sensor */
        private void updateAccelParameters(float xNewAccel, float yNewAccel,
                        float zNewAccel) {
                /* we have to suppress the first change of acceleration, it results from first values being initialized with 0 */
                if (firstUpdate) {  
                        xPreviousAccel = xNewAccel;
                        yPreviousAccel = yNewAccel;
                        zPreviousAccel = zNewAccel;
                        firstUpdate = false;
                } else {
                        xPreviousAccel = xAccel;
                        yPreviousAccel = yAccel;
                        zPreviousAccel = zAccel;
                }
                xAccel = xNewAccel;
                yAccel = yNewAccel;
                zAccel = zNewAccel;
        }
        
        /* If the values of acceleration have changed on at least two axises, we are probably in a shake motion */
        private boolean isAccelerationChanged() {
                float deltaX = Math.abs(xPreviousAccel - xAccel);
                float deltaY = Math.abs(yPreviousAccel - yAccel);
                float deltaZ = Math.abs(zPreviousAccel - zAccel);
                return (deltaX > shakeThreshold && deltaY > shakeThreshold)
                                || (deltaX > shakeThreshold && deltaZ > shakeThreshold)
                                || (deltaY > shakeThreshold && deltaZ > shakeThreshold);
        }

        private void executeShakeAction() {
                /* Save the cheerleader, save the world 
                   or do something more sensible... */
                Toast.makeText(this, "shaked", Toast.LENGTH_SHORT).show();
        }

}

以下を参考にしてます。

これで shake な挙動を捕まえることができる模様。

もう少し材料を

ちょっとワケワカになったのでメモを以下に。

  • 機能
    • Service 起動して加速度センサで shake 挙動ヲチ
    • Service の起動/終了を Notification を使って処理
    • 電源投入で Sercice 起動

これらを順に実装していきたいなと思っていますが、とりあえず設定 Activity 作らないといけないですね。一応上記機能を実装するにあたっての TODO を以下に控え。

Service

加速度センサをリスンして shake 挙動 で wakelock を云々。最初、スイッチによる制御が必要かな、と思っていたのですがリスンしないのであれば Sercice も止めれば良いですね。

Notification

出し方は以下らしい。deprecated なナニが多くてアレでした。

    private void showNotification(int drawableId, CharSequence text) {
        
    	//PendingIntentはタイミングを指定したインテント
    	//今回はユーザーがnotificationを選択した時にActivityを起動
    	PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
    			new Intent(this, MainActivity.class), 0);
    	 
        //通知内容を決定
    	Notification notification = new Notification.Builder(this)
    	.setContentTitle("Shake Device")
    	.setContentText("Touch")
    	.setContentIntent(contentIntent)
    	.getNotification();
     
        mNotificationManager.notify(NOTIFICATION_ID, notification);
    }

上記の例だと Activity を起動する形になってますが、この課題の場合は broadcast Intent を投げてそれを捕まえるような実装にする必要あり。
なので、PendingIntent#getBroadcast を使う必要があるはずです。
ああ、BroadcastReceiver は二つ用意 (ということはフィルタも二つ用意) しないといけないのかな。そしてそこから {start, stop}Service するような形なのか。

電源投入で Sercice 起動

これは決まった (名前忘れた) IntentFilter を定義して receiver で startService してあげれば OK です。これはいっちゃん最後に実装の方向。

こうやって纏めてみると

なんとなく作れそうな気がしてくるんですが、今日はもう休む。疲れた。何もしてないけど疲れた (ぇ
とりあえず設定 Activity をでっちあげて、Service を起動できたら github 方面に放り込んで Google Play にも登録してやれ (ぇ

ちなみに

こないだ Screen Off にするソレも widget にして同じパケジに同梱の方向。
実装するのもアレですが、アイコンとかの制作がorz