最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
巧用事件分發(fā)機(jī)制,和我一起hold住android外圍設(shè)備

外圍輸入設(shè)備,例如:藍(lán)牙鍵盤,usb鍵盤,barcode掃碼槍...
由于平時(shí)都是在做純軟件程序的開發(fā),博主在需求遇到android設(shè)備與外圍設(shè)備交互時(shí)有點(diǎn)不知所措。我最初的思路是這樣:既然是藍(lán)牙連接,那不就是socket嗎,那么截獲他的I/O流然后解析里面的內(nèi)容...那不就ok啦?
然而事情并沒有那么簡(jiǎn)單,首先解析數(shù)據(jù)流是一個(gè)難點(diǎn),再一個(gè)萬(wàn)一我藍(lán)牙連接換成usb連接,或者wifi,那不就得再改了?
參考了網(wǎng)上的方案后發(fā)現(xiàn),外圍設(shè)備是通過(guò)KeyEvent事件機(jī)制android交互的,既然是這樣那我就不用再關(guān)心外設(shè)是通過(guò)什么方式連接的,直接截獲外設(shè)發(fā)送的事件,并且還可直接獲取到輸入內(nèi)容!

創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站制作、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的硯山網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

本文將通過(guò)一個(gè)android設(shè)備與掃碼槍連接案例來(lái)向大家詳述android的事件機(jī)制
首先看一個(gè)我具體使用的類庫(kù)

以下就是我寫的的藍(lán)牙掃碼槍的類庫(kù),已上傳至github
https://github.com/sally519/BarCode-android

巧用事件分發(fā)機(jī)制,和我一起hold住android外圍設(shè)備
我們直接來(lái)看看是怎么用的

public class MainActivity extends AppCompatActivity implements BarCodeIpml.OnScanSuccessListener {

//activity實(shí)現(xiàn)了BarCodeIpml.OnScanSuccessListener借口,即回調(diào)成功時(shí)的借口

private BarCodeIpml barCodeIpml = new BarCodeIpml();
private TextView textView;
private TextView mTv;
private static final String TAG="MainActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //設(shè)置掃碼成功的回調(diào)監(jiān)聽
    barCodeIpml.setOnGunKeyPressListener(this);
    mTv = (TextView) findViewById(R.id.mTv);
}

//重寫事件分發(fā)的方法
@Override
public boolean dispatchKeyEvent(KeyEvent event) {

    if (barCodeIpml.isEventFromBarCode(event)) {
        barCodeIpml.analysisKeyEvent(event);
        return true;
    }
    Log.e("keycode",event.getKeyCode()+"");
    return super.dispatchKeyEvent(event);
}
//在activity獲得焦點(diǎn)時(shí)
@Override
protected void onResume() {
    super.onResume();
    try {
        barCodeIpml.hasConnectBarcode();
    } catch (DevicePairedNotFoundException e) {
        e.printStackTrace();
        Log.e(TAG, "badcode槍未連接!");
    }
}
 //借口的實(shí)現(xiàn),掃碼成功后的回調(diào),寫你自己的實(shí)現(xiàn)
@Override
public void onScanSuccess(String barcode) {
    Log.e("mcallback", barcode);
    mTv.setText(barcode);
}

 //與activity生命周期綁定,防止內(nèi)存泄漏
@Override
protected void onDestroy() {
    super.onDestroy();
    barCodeIpml.onComplete();
}
}

從注釋和方法的名稱我們大概可以判斷出各個(gè)方法的作用,我們來(lái)看其中最關(guān)鍵的一個(gè)方法

dispatchKeyEvent(KeyEvent event)

大家首先需要知道,這個(gè)方法返回一個(gè)boolean

 @Override
public boolean dispatchKeyEvent(KeyEvent event) {

    if (barCodeIpml.isEventFromBarCode(event)) {
        barCodeIpml.analysisKeyEvent(event);
        return true;
    }
    Log.e("keycode",event.getKeyCode()+"");
    return super.dispatchKeyEvent(event);
}

當(dāng)我返回一個(gè)true的時(shí)候,這個(gè)事件就會(huì)被我們消費(fèi)(類庫(kù)里的主要操作就是獲取KeyCode,即外圍設(shè)備輸入的內(nèi)容),不會(huì)再交給系統(tǒng)處理。在以上的代碼中我拿到這個(gè)事件后我調(diào)用類庫(kù)的方法判斷他是否來(lái)自外圍設(shè)備,如果是的話我們自己將其截獲處理,不再交給系統(tǒng),否則的話我們交由系統(tǒng)處理。這個(gè)方法大家應(yīng)該比較熟悉,我們常常用來(lái)重寫back鍵或者h(yuǎn)ome鍵。
之后我們進(jìn)去dispatchKeyEvent里面看一下,系統(tǒng)是如何處理這個(gè)事件的,直接在activity中查看源碼

/**
 * Called to process key events.  You can override this to intercept all
 * key events before they are dispatched to the window.  Be sure to call
 * this implementation for key events that should be handled normally.
 *
 * @param event The key event.
 *
 * @return boolean Return true if this event was consumed.
 */
public boolean dispatchKeyEvent(KeyEvent event) {
    onUserInteraction();

    // Let action bars open menus in response to the menu key prioritized over
    // the window handling it
    final int keyCode = event.getKeyCode();
    if (keyCode == KeyEvent.KEYCODE_MENU &&
            mActionBar != null && mActionBar.onMenuKeyEvent(event)) {
        return true;
    } else if (event.isCtrlPressed() &&
            event.getUnicodeChar(event.getMetaState() & ~KeyEvent.META_CTRL_MASK) == '<') {
        // Capture the Control-< and send focus to the ActionBar
        final int action = event.getAction();
        if (action == KeyEvent.ACTION_DOWN) {
            final ActionBar actionBar = getActionBar();
            if (actionBar != null && actionBar.isShowing() && actionBar.requestFocus()) {
                mEatKeyUpEvent = true;
                return true;
            }
        } else if (action == KeyEvent.ACTION_UP && mEatKeyUpEvent) {
            mEatKeyUpEvent = false;
            return true;
        }
    }  

源碼不算復(fù)雜,注釋說(shuō)你可以在事件發(fā)送到窗口前攔截此事件,但要對(duì)關(guān)鍵事件執(zhí)行,這里說(shuō)的關(guān)鍵事件可能是back鍵或者h(yuǎn)ome鍵。
我們一步一步來(lái)做下分析,先來(lái)看看onUserInteraction()

  /**
 * Called whenever a key, touch, or trackball event is dispatched to the
 * activity.  Implement this method if you wish to know that the user has
 * interacted with the device in some way while your activity is running.
 * This callback and {@link #onUserLeaveHint} are intended to help
 * activities manage status bar notifications intelligently; specifically,
 * for helping activities determine the proper time to cancel a notfication.
 *
 * 

All calls to your activity's {@link #onUserLeaveHint} callback will * be accompanied by calls to {@link #onUserInteraction}. This * ensures that your activity will be told of relevant user activity such * as pulling down the notification pane and touching an item there. * *

Note that this callback will be invoked for the touch down action * that begins a touch gesture, but may not be invoked for the touch-moved * and touch-up actions that follow. * * @see #onUserLeaveHint() */ public void onUserInteraction() { }

實(shí)現(xiàn)居然是空的,注釋上說(shuō)當(dāng)事件分發(fā)到activity的時(shí)候調(diào)用,你可以實(shí)現(xiàn)這個(gè)方法來(lái)獲知用戶是否在和當(dāng)前activity交互。onUserInteraction()和onUserLeaveHint()是本意是幫助activity更好的管理推送消息,后者將會(huì)跟隨前者一起調(diào)用,上面還說(shuō)onUserInteraction()可能不會(huì)跟隨著手指的移動(dòng)而調(diào)用。
由此,我們也知道onUserInteraction()會(huì)在事件分發(fā)最初的時(shí)候調(diào)用,我們可以用這和方法監(jiān)聽用戶于activity的交互。
我們接著往下看

// Let action bars open menus in response to the menu key prioritized over
// the window handling it
final int keyCode = event.getKeyCode();
if (keyCode == KeyEvent.KEYCODE_MENU &&
        mActionBar != null && mActionBar.onMenuKeyEvent(event)) {
    return true;
}

首先獲取用戶的輸入內(nèi)容keyCode ,之后的意圖很明顯,如果用戶點(diǎn)擊的是ToolBar或者ActionBar的菜單那直接return了一個(gè)true,我們剛剛說(shuō)過(guò)return一個(gè)true的意思就是事件不再交給系統(tǒng)處理,return一個(gè)false則依舊需要交給系統(tǒng)處理,這里的目的想必就是把我們的事件拋給ToolBar或者ActionBar來(lái)處理。
接著往下看

else if (event.isCtrlPressed() &&
            event.getUnicodeChar(event.getMetaState() & ~KeyEvent.META_CTRL_MASK) == '<') {
        // Capture the Control-< and send focus to the ActionBar
        final int action = event.getAction();
        if (action == KeyEvent.ACTION_DOWN) {
            final ActionBar actionBar = getActionBar();
            if (actionBar != null && actionBar.isShowing() && actionBar.requestFocus()) {
                mEatKeyUpEvent = true;
                return true;
            }
        } else if (action == KeyEvent.ACTION_UP && mEatKeyUpEvent) {
        mEatKeyUpEvent = false;
        return true;
    }

第一個(gè)判斷條件event.isCtrlPressed() &&event.getUnicodeChar(event.getMetaState() & ~KeyEvent.META_CTRL_MASK) == '<'或許有點(diǎn)抽象,但下面的注釋告訴我們這段代碼的意圖是捕獲“<”鍵,之后判斷ActionBar是否在請(qǐng)求焦點(diǎn),如果是的話強(qiáng)行將ACTION_UP的事件(也就是按壓屏幕后抬起那一下)消費(fèi),不再由系統(tǒng)處理,并且強(qiáng)行讓ActionBar獲得焦點(diǎn),交由ActionBar處理。否則告訴activityACTION_UP的事件還未被消費(fèi)。

搞懂了以上的內(nèi)容我們就可以隨意截獲事件,并通過(guò)KeyCode獲知是否點(diǎn)擊了虛擬鍵盤,具體點(diǎn)擊的是哪一個(gè)鍵?如果是回車鍵,那就將其內(nèi)容通過(guò)回調(diào)發(fā)送給activity,由此來(lái)獲取外圍輸入設(shè)備的內(nèi)容。具體可查看 https://github.com/sally519/BarCode-android 中的使用詳情。
#小結(jié)
好了,我們來(lái)總結(jié)幾個(gè)需要特別注意的點(diǎn)

  • dispatchKeyEvent(KeyEvent event)中,但我們返回了true,則事件將會(huì)被消費(fèi),不會(huì)在有系統(tǒng)處理,當(dāng)返回false則還要交由系統(tǒng)來(lái)處理
  • onUserInteraction()和onUserLeaveHint()可以用來(lái)監(jiān)聽用戶的和activity的交互,注意:activity必須是獲得焦點(diǎn)的
  • 我們?cè)谙M(fèi)事件的時(shí)候需要對(duì)注意home鍵back鍵等常用的鍵,如果沒有特殊需求,記得將他們拋給系統(tǒng)處理
博主難免有疏忽和遺漏,若有錯(cuò)誤或疑點(diǎn)歡迎指正! 以上內(nèi)容均為原創(chuàng),歡迎關(guān)注博主!
當(dāng)前文章:巧用事件分發(fā)機(jī)制,和我一起hold住android外圍設(shè)備
URL地址:http://fisionsoft.com.cn/article/gcihip.html