サンプル作成
なんか微妙なサンプルを作成しようとしています。メモを以下に。
とりあえず
加速度センサをナニして 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