首先說一下android平台下的11種感應器:
           1. ACCELEROMETER 加速,描述加速度的。
           2.GRAVITY 重力,這個在大家都知道。
           3.GYROSCOPE 陀螺儀,對於物體跌落檢測更強大些,開發遊戲少了它會有點遺憾的,API Level 9新增的類型。
           4. LIGHT 光線感應器,很多Android手機的屏幕亮度是根據這個感應器的數組自動調節的。
           5. LINEAR_ACCELERATION 線性加速器,API Level 9新增的。
           6. MAGNETIC_FIELD 磁極感應器。
           7. ORIENTATION 方向感應器。
           8. PRESSURE 壓力感應器。  
           9. PROXIMITY 距離感應器,對於通話後關閉屏幕背光很有用。
         10. ROTATION_VECTOR 旋轉向量,Android 2.3新增的,如果我們過去處理圖像會發現這個還是很有用的,不過這裏還是對遊戲開發起到輔助。
  11. TEMPERATURE 溫度感應器,可以獲取手機的內部溫度,不過和周邊的有些差距,畢竟手機內部一般溫度比較高。
要善於應用這些資源,今天要說的就是距離感應器。其這個锁頻的原理也很簡單,就是當有物體靠近距離感應器的時候,會觸發事件,然後在事件裏面申請設備電源锁,讓屏幕處於黑屏出台,然後當物體離開距離感應器,釋放設備電源锁,就ok了。下面看看代碼
MainActivity.java  這個類很簡單,就是启動一個Service。
public class MainActivity extends Activity {

/** Called when the activity is first created. */

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.main);

Intent intent = new Intent(MainActivity.this, MyService.class);
startService(intent);

}
}

   然後就是MyService.java   主要內容

public class MyService extends Service {

private SensorManager mManager;

private Sensor mSensor = null;

private SensorEventListener mListener = null;

private PowerManager localPowerManager = null;
private PowerManager.WakeLock localWakeLock = null;


@Override
public void onCreate() {

//獲取系統服務POWER_SERVICE,返回一個PowerManager對象
localPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
//獲取PowerManager.WakeLock對象,後面的参數|表示同時傳入兩個值,最後的是LogCat裏用的Tag 
localWakeLock = this.localPowerManager.newWakeLock(32, "MyPower");

//獲取系統服務SENSOR_SERVICE,返回一個SensorManager對象
mManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
//獲取距離感應器對象
mSensor = mManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
//注冊感應器事件
mListener = new SensorEventListener() {

@Override
public void onSensorChanged(SensorEvent event) {

float[] its = event.values;

if (its != null

&& event.sensor.getType() == Sensor.TYPE_PROXIMITY) {

System.out.println("its[0]:" + its[0]);

//經過測試,當手貼近距離感應器的時候its[0]返回值为0.0,當手離開時返回1.0
if (its[0] == 0.0) {// 貼近手機

System.out.println("手放上去了...");

if (localWakeLock.isHeld()) {
return;
} else
localWakeLock.acquire();// 申請設備電源锁

} else {// 遠離手機

System.out.println("手拿開了...");

if (localWakeLock.isHeld()) {
return;
} else
localWakeLock.setReferenceCounted(false);
localWakeLock.release(); // 釋放設備電源锁
} }
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {

}
};
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

//注冊監聽
mManager.registerListener(mListener, mSensor,
SensorManager.SENSOR_DELAY_GAME);

return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {

//取消監聽
mManager.unregisterListener(mListener);

super.onDestroy();
}

@Override
public IBinder onBind(Intent intent) {
return null;
}

}

  

AndroidManifest.xml 中需要添加權限
<uses-permissionandroid:name="android.permission.DEVICE_POWER"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

 

由於時間原因,我這裏只是實現了功能,還有很多要優化的地方,有需要的話自己可以加上。
    優化1:當按下的時候,屏幕會锁住,但是感應器事件依然會觸發,也就是說,當你擋住距離感應器,然後再放開,屏幕依然會亮。
     解决方法:當系統锁屏或黑屏會廣播兩個消息分別是:ACTION_SCREEN_OFFACTION_SCREEN_ON,所以我們可以自己寫個BroadcastReceiver來接受這個廣播,並且做相應的處理。具體處理方法大家可以在黑屏的時候停止service,然後在屏幕亮後再启動service。或者更簡單的定義個boolean變量,黑屏为false,亮的時候为true,然後判斷在true的情況下才申請設備電源锁,應該都可以。大概代碼如下
public class MyReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if (action.equals("android.intent.action.SCREEN_OFF")) {


} else if (action.equals("android.intent.action.SCREEN_ON")) {


}

}

}

  

優化2:實現可以手動關閉和启動service。在MainActivity中可以添加個checkBox,以便開启和停止服務。這個應該很簡單就不詳細說明了。

 

優化3:開機自启動。這個就不說了,網上大把大把的資料。



最後再講解下PowerManager這個類。
PowerManager這個類主要是用來控制電源狀態的. 通過使用該類提供的api可以控制電池的待機時間,一般情況下不要使用。如果確實需要使用,那麼盡可能的使用最低級別的WakeLocks锁。並且確保使用完後釋放它。你可以通過context.getSystemService(Context.POWER_SERVICE)的方式獲得PowerManager的實例。在PowerManager中,最主要的newWakeLock方法,SDK源碼如下
/**
* Get a wake lock at the level of the flags parameter. Call
* {@link WakeLock#acquire() acquire()} on the object to acquire the
* wake lock, and {@link WakeLock#release release()} when you are done.
*
* {@samplecode
*PowerManager pm = (PowerManager)mContext.getSystemService(
* Context.POWER_SERVICE);
*PowerManager.WakeLock wl = pm.newWakeLock(
* PowerManager.SCREEN_DIM_WAKE_LOCK
* | PowerManager.ON_AFTER_RELEASE,
* TAG);
*wl.acquire();
* // ...
*wl.release();
* }
*
* @param flags Combination of flag values defining the requested behavior of the WakeLock.
* @param tag Your class name (or other tag) for debugging purposes.
*
* @see WakeLock#acquire()
* @see WakeLock#release()
*/
public WakeLock newWakeLock(int flags, String tag)
{
return new WakeLock(flags, tag);
}

  這個方法將創建WakeLock對象,通過調用此對象的方法你就可以方便的去控制電源的狀態。方法如下:

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
wl.acquire();
屏幕將停留在設定的狀態,一般为亮、暗狀態
wl.release();
釋放掉正在運行的cpu或關閉屏幕。

  

flags参數說明:
                         *                                                   cpu       screen       keyboard
                         * PARTIAL_WAKE_LOCK                   on         off             off
                         * SCREEN_DIM_WAKE_LOCK            on         dim             off
                         * SCREEN_BRIGHT_WAKE_LOCK      on         bright          off
                         * FULL_WAKE_LOCK                        on         bright          bright

 

如果你持有PARTIAL_WAKE_LOCK锁,不論任何定時器甚至是按下電源按鈕,cpu都將繼續運行,無法進入休眠狀態。除非你釋放掉它。其他锁的話,雖然cpu也在運行,但是當用戶按下電源按鈕時,設備將立刻進入休眠狀態。

就說到這裏了,這個也沒什麼效果圖,下面會附上源碼。(此程序只在 htc G7  真機測試)。
歡迎熱愛安卓開發的朋友們加入群共同進步。南京群 220818530,成都群 252743807,西安群252746034,武漢群121592153,杭州群253603803,廈門群253604146

From:CNBLOGS
創作者介紹
創作者 shadow 的頭像
shadow

資訊園

shadow 發表在 痞客邦 留言(0) 人氣()