關門變數

鴨脖發表於2012-07-20

今天要寫一個檢測手機震動的android程式,剛開始竟然不知到怎麼寫,後來來來回回跳了一天,最後還是用了一個很簡單的方法便解決了。咳坑爹的是最後發現是自己感測器的問題他孃的啊。


寫感測器的程式無非就是過載onSensorChanged這個方法。這個方法應該是被一個執行緒(當然不是主執行緒)一直在監聽,如果有數值改變的事件發生,那麼便響應這個方法。那麼手機晃動的程式該怎麼寫呢?很簡單啊,粗糙的方法只需要判斷這個xyz各個方向上的加速值是不是達到了某一哥邊界就可以了。我取得邊界擲是15,如果能達到便是震動的。


但關鍵是這個方法是在不斷監聽的,我們的目地是檢測到手機晃動然後執行一個動畫。但是現在加速度只要有一點變化,那麼就會重新執行那個動畫,這當然不服和我們的意願,因為我們希望的是在執行動畫的過程中不再去觸發那個事件。那麼怎麼做呢?其實這個思想我們見過的,還記得作業系統中的訊號量機制嗎?對就是互斥思想,我們只需要設定一個guard,一旦進去之後就必須得把門關住了,這就好比上廁所,上的時候關上門,等你拉完屎後,再把門開啟,讓別人上廁所。就是這麼簡單,但是我之所以跳了一天是因為我的感測器懷了好像~!!!!!!



下面摘一段程式,是微信的搖一搖便知道幾個好友線上的程式,也是基於這種思想的:

package boke.sensor.yao;


import com.se.yao.R;


import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;


public class SeActivity extends Activity {
    SensorManager sm;
    SensorL listener;


    private boolean isRefresh=false;
    
    Dialog d;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


        sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);


        listener = new SensorL();
        // 對加速計進行監聽
        sm.registerListener(listener, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                SensorManager.SENSOR_DELAY_FASTEST);
        // sm.registerListener(listener,
        // sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),SensorManager.SENSOR_DELAY_FASTEST);
        // sm.registerListener(listener,sm.getDefaultSensor(Sensor.TYPE_PRESSURE),SensorManager.SENSOR_DELAY_FASTEST);


        AlertDialog.Builder b = new Builder(this);
        // 用來顯示的對話方塊
        d = b.setPositiveButton("ok", new OnClickListener() {


            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub
                isRefresh = false;
                dialog.cancel();
            }
        }).setMessage("搖到了.................").create();


    }


    private class SensorL implements SensorEventListener {


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


        }


        @Override
        public void onSensorChanged(SensorEvent event) {
            // TODO Auto-generated method stub
            if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
                // 判斷是否在重新整理
                if (isRefresh)
                    return;
                float newX = Math.abs(event.values[SensorManager.DATA_X]);
                float newY = Math.abs(event.values[SensorManager.DATA_Y]);
                float newZ = Math.abs(event.values[SensorManager.DATA_Z]);
                // 這裡是關鍵,判斷某個方向上的加速度值是否達到自己想要的值
                // X
                if (newX >= 18) {
                    Toast.makeText(SeActivity.this, "newX" + newX, 0).show();
                    isRefresh = true;
                    d.show();
                    return;
                }
                // Y
                if (newY >= 20) {
                    Toast.makeText(SeActivity.this, "newY" + newY, 0).show();
                    isRefresh = true;
                    d.show();
                    return;
                }
                // Z
                if (newZ >= 20) {
                    Toast.makeText(SeActivity.this, "newZ" + newZ, 0).show();
                    isRefresh = true;
                    d.show();
                    return;
                }


            }
            if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
                // Log.e("TYPE_MAGNETIC_FIELD", ""+event.sensor.toString());
            }
            if (event.sensor.getType() == Sensor.TYPE_PRESSURE) {
                // Log.e("TYPE_PRESSURE", ""+event.sensor.toString());
            }
        }


    }


    @Override
    protected void onPause() {
        // ACTIVITY消失時取消監聽
        sm.unregisterListener(listener);
        super.onPause();
    }
}

相關文章