編輯:關於Android編程
我們都知道在不修改源代碼的情況下,只能是解鎖之後才能使用NFC功能。而在鎖屏和黑屏2個狀態下是沒辦法用NFC的,但是最近有個客戶要求手機在黑屏狀態下能夠使用NFC,因此我們需要去修改Android源代碼關於NFC模塊。
最開始可以通過查看分析源代碼,找到到NfcService的相關代碼,如下: packagesappsNfcsrccomandroid fcNfcService.java
找到186行,這句是定義NFC能夠使用的屏幕最小狀態
// minimum screen state that enables NFC polling static final int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;
這幾個狀態分別是:
SCREEN_STATE_OFF黑屏狀態
SCREEN_STATE_ON_LOCKED屏幕亮了,但是是鎖屏狀態
SCREEN_STATE_ON_UNLOCKED 屏幕亮了,並且是解鎖狀態
代碼定義如下,在packagesappsNfcsrccomandroid fcScreenStateHelper中定義
static final int SCREEN_STATE_UNKNOWN = 0; static final int SCREEN_STATE_OFF = 1; static final int SCREEN_STATE_ON_LOCKED = 2; static final int SCREEN_STATE_ON_UNLOCKED = 3;
private NfcDiscoveryParameters computeDiscoveryParameters(int screenState) { Log.d(TAG, computeDiscoveryParameters() screenState:+describeScreenState(screenState)); if(screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED) Log.d(TAG, !!!! SCREEN_STATE_ON_LOCKED,, mNfcUnlockManager.isLockscreenPollingEnabled():+mNfcUnlockManager.isLockscreenPollingEnabled()); // Recompute discovery parameters based on screen state NfcDiscoveryParameters.Builder paramsBuilder = NfcDiscoveryParameters.newBuilder(); // Polling if (screenState >= NFC_POLLING_MODE) {//這裡被調用 // Check if reader-mode is enabled if (mReaderModeParams != null) { int techMask = 0; if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_A) != 0) techMask |= NFC_POLL_A; if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_B) != 0) techMask |= NFC_POLL_B; if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_F) != 0) techMask |= NFC_POLL_F; if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_V) != 0) techMask |= NFC_POLL_ISO15693; if ((mReaderModeParams.flags & NfcAdapter.FLAG_READER_NFC_BARCODE) != 0) techMask |= NFC_POLL_KOVIO; Log.d(TAG, mReaderModeParams != null paramsBuilder.setTechMask:+techMask); paramsBuilder.setTechMask(techMask); paramsBuilder.setEnableReaderMode(true); } else { Log.d(TAG, mReaderModeParams == null paramsBuilder.setTechMask:+NfcDiscoveryParameters.NFC_POLL_DEFAULT + NFC_POLL_DEFAULT); paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT); paramsBuilder.setEnableP2p(mIsNdefPushEnabled); } } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mInProvisionMode) { paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT); // enable P2P for MFM/EDU/Corp provisioning paramsBuilder.setEnableP2p(true); } else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mNfcUnlockManager.isLockscreenPollingEnabled()) { Log.d(TAG, !!!! SCREEN_STATE_ON_LOCKED setTechMask ); // For lock-screen tags, no low-power polling paramsBuilder.setTechMask(mNfcUnlockManager.getLockscreenPollMask()); paramsBuilder.setEnableLowPowerDiscovery(false); paramsBuilder.setEnableP2p(false); } if (mIsHceCapable && mScreenState >= ScreenStateHelper.SCREEN_STATE_ON_LOCKED) { // Host routing is always enabled at lock screen or later Log.d(TAG, >= SCREEN_STATE_ON_LOCKED paramsBuilder.setEnableHostRouting(true) ); paramsBuilder.setEnableHostRouting(true); } return paramsBuilder.build(); }因此如果要改成黑屏狀態下可以使用NFC的話,只要將變量NFC_POLLING_MODE改成
// minimum screen state that enables NFC polling //static final int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; static final int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_OFF;
客戶的要求是:當雙擊物理按鍵Camera鍵的時候,可以在黑屏狀態下使用NFC十分鐘,十分鐘之類,差不多關於NFC的工作完成了,之後將狀態改回來,即:只能在解鎖狀態下使用NFC,這樣的話就可以黑屏使用NFC又節電。
因此,思路如下:
1、接收物理按鍵Camera鍵發送的廣播,來判斷是雙擊,並將NFC_POLLING_MODE的最小模式改為ScreenStateHelper.SCREEN_STATE_OFF。
2、需要寫一個定時器來處理十分鐘之後將NFC_POLLING_MODE的最小模式改為會原來的ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED。
因此,首先先定義幾個常量,從第185行static final int NFC_POLLING_MODE= ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED;處開始修改,修改代碼如下:
// minimum screen state that enables NFC polling // edited by ouyang [2015-10-19] start // static final int NFC_POLLING_MODE= ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; //默認為要解鎖才能使用NFC static final int NFC_POLLING_MODE_DEFALUT = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; //在黑屏情況下也可以使用NFC static final int NFC_POLLING_MODE_SCREEN_OFF = ScreenStateHelper.SCREEN_STATE_OFF; //默認能使用NFC時的屏幕狀態 static int NFC_POLLING_MODE = ScreenStateHelper.SCREEN_STATE_ON_UNLOCKED; public static int getNFC_POLLING_MODE() { return NFC_POLLING_MODE; } public static void setNFC_POLLING_MODE(int mNFC_POLLING_MODE) { NFC_POLLING_MODE = mNFC_POLLING_MODE; } //是否是雙擊Camera鍵 static boolean isDoublePress=false; //從黑屏可用NFC恢復到要解鎖才能用NFC的時間 static final int TIME_TO_Restore_Default_Values=(60*1000)*10;//10分鐘 10*1000*60 // edited by ouyang [2015-10-19] end
因為是要判斷雙擊Camera,所以這裡只要接收松開Camera鍵時發出的廣播即可。這個廣播是公司自己定義的,定義的廣播為:com.runbo.camera.key.up。所以現在處理這個廣播。因為代碼中本來就動態注冊了一個廣播接收者,因此我們在這個廣播接收者種再注冊一個Intent即可。代碼如下:在第450行
// Intents for all users IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_USER_PRESENT); filter.addAction(Intent.ACTION_USER_SWITCHED); //added by ouyang start [2015-10-19] //Camera物理鍵按下後松開 發出的廣播 filter.addAction(com.runbo.camera.key.up); //added by ouyang end [2015-10-19] registerForAirplaneMode(filter); mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
//added by ouyang start [2015-10-19] Camera物理鍵按下後松開 else if (action.equals(com.runbo.camera.key.up)) { Log.d(oyp, <----com.runbo.camera.key.up---->); Handler checkHandler=new Handler(); Handler restoreHandler=new Handler(); //單擊 if (!isDoublePress) { isDoublePress=true;//500ms之類再單擊Camera鍵的話,就是雙擊了,直接進入 else語句塊 //500ms後觸發該線程,查看是單擊還是雙擊 Runnable CheckDoubleRunnable=new Runnable(){ @Override public void run() { if (isDoublePress) { Log.i(oyp, <----Single Press the Camera Key---->); //顯示為單擊 }else{ Log.i(oyp, <----Double Press the Camera Key---->); //顯示為雙擊 } isDoublePress=false;//500ms後在單擊Camera鍵的話 依舊是單擊 ,還是進入了 if語句塊 } }; checkHandler.postDelayed(CheckDoubleRunnable, 500);// 500ms內兩次單擊,觸發雙擊 } // 500ms內兩次單擊,觸發雙擊 else{ isDoublePress=false;//雙擊後,將該值設為false,下次在單擊Camera鍵的話 依舊是單擊 ,還是進入了 if語句塊 //設置在屏幕關閉情況下仍然可以使用NFC setNFC_POLLING_MODE(NFC_POLLING_MODE_SCREEN_OFF); applyRouting(true); Log.d(oyp, 2、NFC_POLLING_MODE=+getNFC_POLLING_MODE()); //10分鐘後觸發該線程,恢復原來值 Runnable RestoreDefaultValues=new Runnable(){ @Override public void run() { //設置在屏幕解鎖情況下可以使用NFC setNFC_POLLING_MODE(NFC_POLLING_MODE_DEFALUT); applyRouting(true); Log.d(oyp, 3、NFC_POLLING_MODE=+getNFC_POLLING_MODE()); } }; restoreHandler.removeCallbacks(RestoreDefaultValues);//先取消定時器 restoreHandler.postDelayed(RestoreDefaultValues, TIME_TO_Restore_Default_Values);//10分鐘後恢復原來值 } } //added by ouyang end [2015-10-19]
// if (screenState >= NFC_POLLING_MODE) { //edited by ouyang [2015-10-19 11:13:17] if (screenState >= getNFC_POLLING_MODE()) {
最近在弄個項目,要求有跑馬燈效果的圖片展示。網上搜了一堆,都沒有完美實現的算了還是自己寫吧! 實現原理利用 ViewPager 控件,這個控件本身就支持滑動翻頁很好很強大
為了引入這個概率 首先從需求說起 即:現有某Activity專門用於手機屬性設置 那麼應該如何做呢? 根據已學知識 很快一個念頭閃過 即:Activity + Prefe
在寫著東西之前,從網上找到很多這方面的源碼,但是基本沒有找到滿意的,包括在GitHub上的比較有名的Android-PullToRefresh-master,思來想去還是
本文實例講述了Android獲取手機屏幕大小的方法。分享給大家供大家參考,具體如下:這裡主要用了三個對象TextView ,Button ,以及DisplayMetric