android距離感應器控制黑屏,白屏

最近在做一個網絡通話的apk,功能和手機打sim卡電話一樣。雖然只做java部分,但也遇到很多問題,其中一個就是模擬通話時的狀態,要控制屏幕鎖屏。我知道是通過手機上的距離感應器來實現,但也搞了好久,今天終於有了結果,拿出來分享一下。


在eoe上發帖尋問這個問題時,大牛告訴我說點亮屏幕可以做到,但是滅屏需要系統權限,應該無法做到。他說的很對,這裏我們確實需要申請權限:

<uses-permission android:name="android.permission.DEVICE_POWER"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

第一個權限加到xml文件中時會報錯,但是我會很利索的去clean掉,實現步驟:找到eclipse中的菜單選項project>clean,選擇當前項目就ok

接下來看一下一個類的代碼:


import android.app.Activity;  
import android.content.Context;  
import android.hardware.Sensor;  
import android.hardware.SensorEvent;  
import android.hardware.SensorEventListener;  
import android.hardware.SensorManager;  
import android.os.Bundle;  
import android.os.PowerManager;  
import android.util.Log;  
import android.view.Menu;  
import android.view.View;  
  
public class SensorTest extends Activity implements SensorEventListener{  
    public static final String TAG = "SensorTest";  
      
    //調用距離傳感器,控制屏幕  
    private SensorManager mManager;//傳感器管理對象  
    //屏幕開關  
    private PowerManager localPowerManager = null;//電源管理對象  
    private PowerManager.WakeLock localWakeLock = null;//電源鎖  
      
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.sensor);  
          
        mManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);  
        //獲取系統服務POWER_SERVICE,返回一個PowerManager對象  
        localPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);  
        //獲取PowerManager.WakeLock對象,後面的參數|表示同時傳入兩個值,最後的是LogCat裏用的Tag   
        localWakeLock = this.localPowerManager.newWakeLock(32, "MyPower");//第一個參數爲電源鎖級別,第二個是日誌tag  
    }  
      
    public void onResume(){  
        super.onResume();  
        mManager.registerListener(this, mManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),// 距離感應器  
                SensorManager.SENSOR_DELAY_NORMAL);//註冊傳感器,第一個參數爲距離監聽器,第二個是傳感器類型,第三個是延遲類型  
    }  
      
    public void onStop(){  
        super.onStop();  
        Log.d(TAG,"on stop");  
    }  
      
    public void onDestroy(){  
        super.onDestroy();  
        Log.d(TAG,"on destroy");  
        if(mManager != null){  
            localWakeLock.release();//釋放電源鎖,如果不釋放finish這個acitivity後仍然會有自動鎖屏的效果,不信可以試一試  
            mManager.unregisterListener(this);//註銷傳感器監聽  
        }  
    }  
  
    @Override  
    public void onAccuracyChanged(Sensor sensor, int accuracy) {  
        // TODO Auto-generated method stub  
          
    }  
  
    @Override  
    public void onSensorChanged(SensorEvent event) {  
        // TODO Auto-generated method stub  
        float[] its = event.values;  
        //Log.d(TAG,"its array:"+its+"sensor type :"+event.sensor.getType()+" proximity type:"+Sensor.TYPE_PROXIMITY);  
        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("hands up");  
                Log.d(TAG,"hands up in calling activity");  
                if (localWakeLock.isHeld()) {  
                    return;  
                } else{  
  
                    localWakeLock.acquire();// 申請設備電源鎖  
                }  
            } else {// 遠離手機  
  
                System.out.println("hands moved");  
                Log.d(TAG,"hands moved in calling activity");  
                if (localWakeLock.isHeld()) {  
                    return;  
                } else{  
                    localWakeLock.setReferenceCounted(false);  
                    localWakeLock.release(); // 釋放設備電源鎖  
                }  
            }  
        }  
    }  
  
}  


當然,拿出來的例子只是對屏幕鎖做了實現,而沒有通話的功能的。但是原理大概就是這樣,來電或者撥打時手機會切換到一個通話界面,然後這個界面應該具有上面所說的這樣的功能。

需要特別注意的是,在onDestroy()函數裏需要把對象鎖釋放掉(localWakeLock.release()),否則這個功能會一直存在知道你清楚應用數據或者刪除應用,我就爲這個問題困擾了好久。爲此我特意在源代碼例子裏做了一個跳轉頁面,加了log。

這裏我們實例化了兩個管理對象,一個是傳感器管理對象:SensorManager;另一個是 電源管理對象:localPowerManager。

傳感器管理對象負責收集收集與物體之間的距離數據,電源管理對象通過判斷傳感器收集到數據對屏幕的滅屏和白屏做處理。 


本文轉自http://blog.csdn.net/luozhi3527/article/details/9999901



注:1、註冊的時候,最好判斷一下mManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)是不是空的,如果設備沒有改傳感器,會報空


        2、在通常的wakelock使用時,有時會報錯:java.lang.RuntimeException: WakeLock under-locked


              設置localWakeLock.setReferenceCounted(false); 







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章