【问题标题】:Creating custom Cordova plugin for NfcV Tags为 NfcV 标签创建自定义 Cordova 插件
【发布时间】:2015-10-05 23:22:36
【问题描述】:

我需要从 NfcV (ISO 15693) 标签中读取数据,我已经尝试过 Chariotsolution 的 Phonegap-Nfc 插件,但似乎这个插件只能读取 TagId 和 Type off NfcV 标签,所以我决定我可以创建我自己的自定义插件,我首先找到了 echo Hello World 插件教程,它运行良好且没有问题,所以我寻找 Java NfcV 阅读器并找到了这个Java NfcV Reader。

据我目前了解的是,我需要调用 cordova.exec 函数并从 CordovaPlugin 扩展我的 Java 类,它正在工作。

由于我是一名 Web 开发人员,所以我不懂 Java,这对我来说有点困难。

这实际上看起来不错,但我尝试以 Hello World echo 示例的方式实现它,但没有按计划进行。

我现在有一个插件文件夹

Hello.java

    package org.apache.cordova.plugin;

    import org.apache.cordova.CallbackContext;
    import org.apache.cordova.CordovaPlugin;
    import org.json.JSONArray;
    import org.json.JSONException;


    /**
     * This class echoes a string called from JavaScript.
     */
    public class Hello extends CordovaPlugin
    {
        @Override
        public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
            if (action.equals("hello")) {
                String message = args.getString(0);
                this.hello(message, callbackContext);
                return true;
            }
            return false;
        }

        private void hello(String message, CallbackContext callbackContext) {
            if (message != null && message.length() > 0) {
                callbackContext.success(message);
            } else {
                callbackContext.error("Expected one non-empty string argument.");
            }
        }
    }

从上面的链接中读取NfcV.java

    package org.apache.cordova.plugin;

    import org.apache.cordova.CallbackContext;
    import org.apache.cordova.CordovaPlugin;
    import org.json.JSONArray;
    import org.json.JSONException;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    import java.util.HashMap;

    import org.apache.http.util.ByteArrayBuffer;

    import android.nfc.Tag;
    import android.nfc.TagLostException;
    import android.nfc.tech.NfcV;
    import android.nfc.tech.TagTechnology;
    //import android.os.Parcelable;
    import android.util.Log;

    /**
        * @author uhahn
        *
        */
    public class ReadNfcV extends CordovaPlugin implements TagTechnology {
            protected NfcV mynfcv;
    //      protected Tag mytag; // can be retrieved through mynfcv
    
            private final String TAG=this.getClass().getName();
            protected final int maxtries=3;
    
            protected boolean isTainted=true; // Tag info already read?
            protected byte[] mysysinfo=null;        // NfcV SystemInformation - or generated
            protected byte[] myuserdata=null;       // buffer user content
            protected boolean[] blocktainted;       // true when block is to be uploaded to tag
            protected byte[] blocklocked;           // 0 means writable
    
            protected byte afi=0;
            public byte nBlocks=0;
            public byte blocksize=0;
            public byte[] Id;
            public byte[] UID; // becomes valid when a real tag is contacted
            public byte DSFID = -1;
            public int maxtrans=0; // tag dependent max transceive length
            public byte lastErrorFlags=-1; // re-set by each transceive
            public byte lastErrorCode=-1; // re-set by each transceive
            public byte manuByte=0;
    
            public static final byte BYTE_IDSTART=(byte)0xe0;
            public static final byte MANU_TAGSYS=0x04;
            public static final HashMap<Byte,String> manuMap = new HashMap<Byte, String>();
    
            static{
                    manuMap.put(MANU_TAGSYS, "TagSys");
            }
    
            /**
             * read new NfcV Tag from NFC device
             */
            public ReadNfcV(Tag t) {
                    UID = t.getId(); // sysinfo holds the UID in lsb order -  Id will be filled lateron from sysinfo!
    //              Log.d(TAG,"getId: "+toHex(t.getId()));
                    mynfcv=NfcV.get(t);
                    try {
                            mynfcv.connect();
                            mysysinfo=getSystemInformation(); 
                            // explore Nfcv properties..
                            //initfields(); // done by getSys..

                            maxtrans=mynfcv.getMaxTransceiveLength();
                            DSFID=mynfcv.getDsfId();
                            Log.d(TAG,nBlocks + " x " + blocksize + " bytes");
                            blocklocked=new byte[nBlocks]; // init the lock shadow
                            getMultiSecStatus(0, nBlocks);  // and fill from tag
                    
                            blocktainted=new boolean[nBlocks];
                            taintblock(0,nBlocks);
                    
    //                      Log.d(TAG,"maxtrans "+maxtrans);
                            // init space for userdata ?
                            myuserdata= new byte[nBlocks*blocksize]; 
                    } catch (IOException e) {
                            // TODO Auto-generated catch block
                            lastErrorFlags=-1;
                            Log.d(TAG, "MyNfcV failed: "+e.getMessage());
                            e.printStackTrace();
                    }
            }
    
            /**
             * recreate NfcV Tag from log
             * @param sysinfo: the logged system info only
             */
            public ReadNfcV(String sysinfo){
                    int startat=0;
                    sysinfo.toLowerCase(); // ignore case
                    if(sysinfo.startsWith("0x")){ // lets believe in HEX
                            startat=2;
                    }
                    mysysinfo=hexStringToByteArray(sysinfo.substring(startat));
                    initfields();
                    // init space for userdata TODO limit size?
                    //myuserdata= new byte[nBlocks*blocksize]; 
                    isTainted=false; 
    // TODO fake Tag?               mytag = Tag.CREATOR.createFromParcel(???);
            }

            /**
             * recreate NfcV Tag from log
             * @param sysinfo: the logged system info
             * @param userdata: the logged userdata
             */
            public ReadNfcV(String sysinfo, String userdata){
                    this(sysinfo);
                    // TODO fake userdata
                    int startat=0;
                    userdata.toLowerCase(); // ignore case
                    if(userdata.startsWith("0x")){ // lets believe in HEX
                            startat=2;
                    }
                    myuserdata=hexStringToByteArray(userdata.substring(startat));
            }
    
            /**
             * parse system information byte array into attributes
             * with respect to the flags found
             * DSFID
             * AFI
             * memsize values (block count and length)
             */
            private void initfields(){
                    byte[] read=mysysinfo;
                    if((null!=read)&&(12<read.length)&&(0==read[0])){// no error
                            char flags=(char)read[1]; //s.charAt(1);

                            //      String s=new String(read);
                            //s.substring(2, 9).compareTo(Id.toString())  // the same?
                            //set the Id from mysysinfo
                            int pos=2;
                            boolean forwardId=false; // the Id field is in lsb order
                            if(BYTE_IDSTART==read[pos]){
                                    forwardId=true;
                                    manuByte=read[pos+1];
                            }else if(BYTE_IDSTART==read[pos+7]){
                                    manuByte=read[pos+6];
                                    forwardId=false;
                            }else
                                    Log.e(TAG,"Id start byte not found where expected");
                            if(null==Id){ // dont overwrite, if given
                                    Id=new byte[8];
                                    for(int i=0;i<8;i++) 
                                            // TODO decide if Id to be reversed (Zebra needs msb order, that is Id[7] changes between tags)
                                            Id[i]=(forwardId? read[pos+i] : read[pos + 7 - i]); //reverse?!
                                    Log.d(TAG,"Id from sysinfo (reversed): "+toHex(Id));
                            }
                    
                            pos=10; // start after flags, Infoflags and Id TODO: change if transceive should eat up the error byte 
                            if(0<(flags&0x1)){ // DSFID valid
                                    pos++; // already implemented 
                            }
                            if(0<(flags&0x2)){ // AFI valid
                                    afi=(byte)read[pos++];//s.charAt(pos++);
                            }
                            if(0<(flags&0x4)){ // memsize valid
                                    nBlocks=(byte)(read[pos++]+1);//(s.charAt(pos++)+1);
                                    blocksize=(byte)(read[pos++]+1); //((s.charAt(pos++)&0x1f)+1);
                            }       
                    }
            }
    
            /**
             * @return the stored afi byte
             */
            public byte getAFI(){
                    if(isTainted){ // system info not read yet
                            getSystemInformation(); // fill in the fields
                    }
                    return afi;
            }
    
            public byte getDsfId(){
    //              return mynfcv.getDsfId(); // avoid re-reading
                    return DSFID;
            }
    
            public int getblocksize(){
                    return (int)blocksize;
            }
    
            public int getnBlocks(){
                    return (int)nBlocks;
            }
    
            public byte[] getSystemInformation(){
                    if(isTainted){ // dont reread 
                            mysysinfo=transceive((byte)0x2b);
                            isTainted=false; // remember: we have read it and found it valid
                            if(0==lastErrorFlags){// no error
                                    isTainted=false; // remember: we have read it and found it valid
                                    initfields(); // analyze 
                            }}
                    return mysysinfo;
            }
    
            /**
             * overload method transceive
             * @return resulting array (or error?)
             */
            protected byte[] transceive(byte cmd){
                    return transceive(cmd, -1, -1, null);
            }

            protected byte[] transceive(byte cmd, int m){
                    return transceive(cmd, m, -1, null);
            }
    
            protected byte[] transceive(byte cmd, int m ,int n){
                    return transceive(cmd, m, n, null);
            }
    
            /**
             * prepare and run the command according to NfcV specification
             * @param cmd command byte
             * @param m command length
             * @param n 
             * @param in input data
             * @return
             */
            protected byte[] transceive(byte cmd,int m, int n, byte[] in){
                            byte[] command;
                            byte[] res="transceive failed message".getBytes();
            
                    ByteArrayBuffer bab = new ByteArrayBuffer(128);
                    // flags: bit x=adressed, 
                    bab.append(0x00);
                    bab.append(cmd); // cmd byte
                    // 8 byte UID - or unaddressed
            //      bab.append(mytag.getId(), 0, 8);
                    // block Nr
                    if(-1!=m)bab.append(m);
                    if(-1!=n)bab.append(n);
                    if(null!=in)bab.append(in, 0, in.length);
            
                    command=bab.toByteArray();
                    Log.d(TAG,"transceive cmd: "+toHex(command));
    //              Log.d(TAG,"transceive cmd length: "+command.length);
            
                    // TODO background!
                    try {
                            if(!mynfcv.isConnected()) return res;
                            for(int t=maxtries;t>0;t++){ // retry reading
                                    res=mynfcv.transceive(command);
                                    if(0==res[0]) break;
                            }
                    } 
                    catch (TagLostException e){ //TODO roll back user action
                            Log.e(TAG, "Tag lost "+e.getMessage());
                            try {
                                    mynfcv.close();
                            } catch (IOException e1) {
                                    e1.printStackTrace();
                            }
                            return e.getMessage().getBytes();               
                    }
                    catch (IOException e) {
                            Log.d(TAG, "transceive IOEx: "+e.getMessage()+toHex(res));
            //              e.printStackTrace();
                            return e.getMessage().getBytes();
                    }
                    finally{
                            Log.d(TAG,"getResponseFlags: "+mynfcv.getResponseFlags()); 
                            lastErrorFlags=res[0];
                            Log.d(TAG,"Flagbyte: "+String.format("%2x", lastErrorFlags));
                            if(0!=lastErrorFlags){
                                    lastErrorCode=res[1];
                                    Log.d(TAG,"ErrorCodebyte: "+String.format("%2x", lastErrorCode));
                            }
                    }

                    if(0==mynfcv.getResponseFlags())
                            return (res);
                    else
    //                      return new String("response Flags not 0").getBytes();
                            return res;
            }

    
            public void taintblock(int i, int n){
                    for(int j=0;j<n;j++)
                            setblocktaint(j,true);
            }

            public void taintblock(int i){
                    setblocktaint(i,true);
            }
    
            protected void setblocktaint(int i, boolean b){
                    blocktainted[i]=b;
            }
    
    
            /* (non-Javadoc)
             * @see android.nfc.tech.TagTechnology#getTag()
             * 
             */
            @Override
            public Tag getTag() {
                    // TODO Auto-generated method stub
                    //return mytag;
                    return mynfcv.getTag();
            }
    
            /* (non-Javadoc)
             * @see android.nfc.tech.TagTechnology#close()
             */
            @Override
            public void close() throws IOException {
                    try {
                            mynfcv.close();
                    } catch (IOException e) {
                            // TODO Auto-generated catch block
                            Log.d(TAG, "close failed: "+e.getMessage());
                            e.printStackTrace();
                    }
            }

            /* (non-Javadoc)
             * @see android.nfc.tech.TagTechnology#connect()
             */
            @Override
            public void connect() throws IOException {
                    try {
                            mynfcv.connect();
                    } catch (IOException e) {
                            lastErrorFlags=-1; // TODO discriminate error states
                            Log.d(TAG,"connect failed: "+e.getMessage());
                            e.printStackTrace();
                    }
            }

            /* (non-Javadoc)
             * @see android.nfc.tech.TagTechnology#isConnected()
             */
            @Override
            public boolean isConnected() {
                    // TODO Auto-generated method stub
    //              mynfcv.getDsfId();
                    return mynfcv.isConnected(); // better?
            }

            public byte[] readSingleBlock(int i){
                    byte[] read=transceive((byte)0x20,i);
            
                    setblocktaint(i,false); // remember we read this block
                    if(0!=lastErrorFlags)return read; // TODO not so ignorant..
            
                    byte[] res=new byte[read.length-1]; // drop the (0) flag byte TODO: in transceive?
                    for (int l = 0; l < read.length-1; l++) {
                            res[l]=read[l+1];
                            myuserdata[i*blocksize+l]=res[l]; // sort block into our buffer
                    }
            
                    return res;
            
            }

            /**
             * 
             * @param i starting block number
             * @param j block count
             * @return block content concatenated 
             */
            public byte[] readMultipleBlocks(int i,int j){
                    if(0==blocksize){
                            Log.e(TAG,"readMult w/o initfields?");
                            getSystemInformation(); // system info was not read yet
                    }

                    byte[] read = transceive((byte)0x23,i,j);
                    if(0!=read[0])return read; // error flag set: TODO  left as exercise..

                    byte[] res=new byte[read.length-1]; // drop the (0) flag byte
                    for (int l = 0; l < read.length-1; l++) {
                            res[l]=read[l+1];
                            myuserdata[i*blocksize+l]=res[l]; // sort block into our buffer
                    }
            
                    if(res.length<j*blocksize) return read; // da fehlt was
                    for (int k = i; k < j; k++) { // all blocks we read
                            setblocktaint(k, false); // untaint blocks we read
    // @TODO reverting block order should be done on demand - or under user control (done again in DDMData)
    //              reverse(res,k*blocksize,blocksize); // swap string positions
                    }
                    return res;
            }
    
            public byte[] getMultiSecStatus(int i,int n){
                    byte[] read = transceive((byte)0x2c,i,n-1);
                    Log.d(TAG,"secstatus "+toHex(read));
                    if(0!=read[0])return read;
                    int startat=1; // TODO transceive will skip the error field soon
            
                    for(int j=0;j<nBlocks;j++)
                            blocklocked[j]=read[startat+i+j];

                    return read;
            }
    
    

            /**
             * move anywhere to utils
             * @param s
             * @return
             */
    
        public static String toHex(byte[] in){
            String text=String.format("0x");
            for (byte  element : in) {
                            text=text.concat(String.format("%02x", element));
                    }
            return text;
        }

    
            public static byte[] hexStringToByteArray(String s) {
                int len = s.length();
                byte[] data = new byte[len / 2];
                for (int i = 0; i < len; i += 2) {
                    data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                                         + Character.digit(s.charAt(i+1), 16));
                }
                return data;
            }
    }

我的 hello.js 文件

        var hello = {
        world: function(str, callback) {
            cordova.exec(callback, function(err) {
                callback('Nothing to hello.');
            }, "Hello", "hello", [str]);
        }
    }

    var ReadNfcV = {
        read: function (str, callback) {
            cordova.exec(callback, function (err) {
                callback('Nothing to hello.');
            }, "Hello", "hello", [str]);
        }
    }

    module.exports = hello;
    module.exports = ReadNfcV;

还有我的 plugin.xml

  <?xml version="1.0" encoding="UTF-8"?>

  <plugin xmlns="http://cordova.apache.org/ns/plugins/1.0"
          id="org.apache.cordova.plugin"
          version="0.1.0">


      <js-module src="hello.js" name="hello">
          <clobbers target="hello" />
      </js-module>

      <!-- Android -->
      <platform name="android">
          <source-file src="Hello.java" target-dir="src/org/apache/cordova/plugin" />
          <source-file src="ReadNfcV.java" target-dir="src/org/apache/cordova/plugin" />

          <config-file target="res/xml/config.xml" parent="/*">
              <feature name="Hello" >
                  <param name="android-package" value="org.apache.cordova.plugin.Hello"/>
              </feature>
          </config-file>
      </platform>
  </plugin>

我能够部署应用程序,因此我可以进行一些测试,我的问题是我真的不明白如何通过 javascript 从我的应用程序中调用 ReadNfcV.java 文件中的 ReadNfc 类。我只是做了与教程中相同的操作,但现在 hello.World 函数不再是一个函数,所以我想我在 hello.js 文件中做错了。如果有人可以帮助并解释我如何通过 javascript 调用我的 java 类,然后将 java 类的结果返回到我的 javascript,我将不胜感激。我花了 2 天时间寻找一个已经存在的插件,但除了 phonegap-nfc 插件外,没有找到关于该主题的任何内容。

克里斯托弗

更新第一天

我将 tech.NfcV 添加到导入列表中

import android.nfc.tech.NfcV;

按照建议更改了执行功能

@Override
public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException {

    Log.d(TAG, "execute " + action);

    if (!getNfcStatus().equals(STATUS_NFC_OK)) {
        callbackContext.error(getNfcStatus());
        return true; // short circuit
    }

    createPendingIntent();


    if (action.equals(REGISTER_DEFAULT_TAG)) {
        addTechList(new String[]{NfcV.class.getName()});  //changed this form Mifare to NfcV
        registerDefaultTag(callbackContext);


    } else if (action.equalsIgnoreCase(INIT)) {
        init(callbackContext);

    } else {
        // invalid action
        return false;
    }

    return true;
}

问题似乎是我现在返回了无效的操作,所以这里出了点问题

我将 registerDefault 函数更改为

private void registerDefaultTag(CallbackContext callbackContext) {
addTechFilter();
callbackContext.success();
}

我将解析消息功能更改为

void parseMessage() {
    cordova.getThreadPool().execute(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "parseMessage " + getIntent());
            Intent intent = getIntent();
            String action = intent.getAction();
            Log.d(TAG, "action " + action);
            if (action == null) {
                return;
            }
            if (action.equals(NfcAdapter.ACTION_TECH_DISCOVERED) || action.equals(NfcAdapter.ACTION_TAG_DISCOVERED)){

             Tag tagFromIntent  = (Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
             NfcV mfc = NfcV.get(tagFromIntent);
             fireTagEvent(tag);

            }

            /*if (action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED)) {
                Ndef ndef = Ndef.get(tag);
                fireNdefEvent(NDEF_MIME, ndef, messages);

            } else if (action.equals(NfcAdapter.ACTION_TECH_DISCOVERED)) {
                for (String tagTech : tag.getTechList()) {
                    Log.d(TAG, tagTech);
                    if (tagTech.equals(NdefFormatable.class.getName())) {
                        fireNdefFormatableEvent(tag);
                    } else if (tagTech.equals(Ndef.class.getName())) { //
                        Ndef ndef = Ndef.get(tag);
                        fireNdefEvent(NDEF, ndef, messages);
                    }
                }
            }

            if (action.equals(NfcAdapter.ACTION_TAG_DISCOVERED)) {
                fireTagEvent(tag);
            }*/

            setIntent(new Intent());
        }
    });
}

所以目前我在点击开始监听并在 Javascript atm 中调用 Taglisteners 时立即收到错误无效操作,我使用所有 4 个不同的监听器来查看是否有任何工作。看来我需要为 NfcV 编写一个新的 fireEvent 函数,因为现有的函数不起作用

更新 2

我已成功编译插件并部署应用程序,但没有任何反应,我没有返回 Tag 对象

解析消息函数

void parseMessage() {
    cordova.getThreadPool().execute(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "parseMessage " + getIntent());
            Intent intent = getIntent();
            String action = intent.getAction();
            Log.d(TAG, "action " + action);
            if (action == null) {
                return;
            }
        if (action.equals(NfcAdapter.ACTION_TECH_DISCOVERED) || action.equals(NfcAdapter.ACTION_TAG_DISCOVERED)){
            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
                    if(tag != null){
                      byte[] id = tag.getId();
                      // set up read command buffer
                      byte blockNo = 0; // block address
                      byte[] readCmd = new byte[3 + id.length];
                      readCmd[0] = 0x20; // set "address" flag (only send command to this tag)
                      readCmd[1] = 0x20; // ISO 15693 Single Block Read command byte
                      
                      System.arraycopy(id, 0, readCmd, 2, id.length); // copy ID
                      readCmd[2 + id.length] = blockNo; // 1 byte payload: block address

                      NfcV tech = NfcV.get(tag);
                      if (tech != null) {
                        // send read command
                        try {
                          tech.connect();
                          byte[] data = tech.transceive(readCmd); 
                          fireTagEvent(data);
                        } catch (IOException e) {
                          e.printStackTrace();
                        } finally {
                          try {
                            tech.close();
                          } catch (IOException e) {
                            e.printStackTrace();
                          }
                        }
                      }
                    }

            setIntent(new Intent());
        }
    

    }
 });
}

我的fireTagEvent

private void fireTagEvent(byte[] data) {

    String s2 = new String(data);
    String command = MessageFormat.format(javaScriptEventTemplate, TAG_DEFAULT, s2);
    Log.v(TAG, s2);
    this.webView.sendJavascript(s2);

}

执行函数

@Override
public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException {

    Log.d(TAG, "execute " + action);

    if (!getNfcStatus().equals(STATUS_NFC_OK)) {
        callbackContext.error(getNfcStatus());
        return true; // short circuit
    }

    createPendingIntent();


    if (action.equals(REGISTER_DEFAULT_TAG)) {
        addTechList(new String[]{NfcV.class.getName()});
        registerDefaultTag(callbackContext);


    } else if (action.equalsIgnoreCase(INIT)) {
        init(callbackContext);

    } else {
        // invalid action
        return false;
    }

    return true;
}

应用程序启动时“addTagDiscoveredListener”已注册,但我没有得到任何对象,所以要么未读取 nfcv 标签,要么我只是没有得到任何东西,不确定......

【问题讨论】:

  • 嗨,我会在这个周末花一些时间来改进我的答案。您是否尝试过在 android studio 中导入应用并设置断点以查看标签是否可见? (并且在原始插件中是否可以看到...我想我的是,但我只能获得 ID)
  • 原始插件正在读取标签,我正在获取标签的 id 和类型,问题是我需要存储在标签上的字节信息。不,我没有与 Visual Studio 合作,而用于混合开发的 Telerik appbuilder 并没有真正尝试设置断点,但没有发生任何事情,我必须承认,我不熟悉那种调试类型-.-。非常感谢非常感谢
  • 嘿,quickfix,你有时间详细阐述你的方法,我尝试了一段时间没有成功
  • @QuickFix 很喜欢如果你能抽出时间来解释你的定制解决方案更多

标签: javascript java cordova cordova-plugins


【解决方案1】:

我使用 Chariotsolution 插件作为开始构建我自己的 nfc 阅读插件。如果你不从头开始,我认为这会节省你很多时间。

你可以删除很多东西,因为原始插件只处理 NDEF 标签,但删除行比重新发明轮子要快。

这在我的脑海里有点老了,所以我不确定我能解释清楚一切...... 我需要阅读 Mifare 经典标签中的信息,但也许你可以适应你的需要...... 因此,如果您查看 NfcPlugin.java,在执行函数中,我只保留了 REGISTER_DEFAULT_TAG 和 INIT 操作的代码。

更新了 REGISTER_DEFAULT_TAG 中的代码以注册监听 mifare 经典标签。并修改 registerDefaultTag 函数调用 addTechFilter 而不是 addTagFilter。

所以这给我们留下了 public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException {

    Log.d(TAG, "execute " + action);

    if (!getNfcStatus().equals(STATUS_NFC_OK)) {
        callbackContext.error(getNfcStatus());
        return true; // short circuit
    }

    createPendingIntent();


    if (action.equals(REGISTER_DEFAULT_TAG)) {
        addTechList(new String[]{MifareClassic.class.getName()});
        registerDefaultTag(callbackContext);


    } else if (action.equalsIgnoreCase(INIT)) {
        init(callbackContext);

    } else {
        // invalid action
        return false;
    }

    return true;
}
private void registerDefaultTag(CallbackContext callbackContext) {
    addTechFilter();
    callbackContext.success();
}

现在你需要明白的是,一旦你从js中调用了init函数,每次设备看到nfc标签时都会调用插件的parseMessage函数。

所以在 parseMessage 函数中我有一个测试

if (action.equals(NfcAdapter.ACTION_TECH_DISCOVERED) || action.equals(NfcAdapter.ACTION_TAG_DISCOVERED))

我有所有的代码来处理我的标签。

在该代码中,可以使用类似这样的方式从 Intent 中的标签获取信息:

            Tag tagFromIntent  = (Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            MifareClassic mfc = MifareClassic.get(tagFromIntent);

然后根据您的处理方式,您可以调用 fireErrorEvent 或 fire...您自己的事件,使用 webView.sendJavascript 函数将数据返回到 javascript。

我没时间详细介绍 js 部分了。

不确定它是否会对您有所帮助,或者它是否是您想要的方式(不知道您使用的标签是如何工作的)。让我知道它是否对您有帮助,如果您需要更多详细信息。

【讨论】:

  • 嘿,非常感谢您的回复,这绝对比我尝试将 nfcv 功能添加到 chariot 插件的方法更好。如果你能给我一些关于周末去的 javascript 部分的更多细节,那就太好了,所以不要着急
  • 我用您建议的更改更新了问题
  • 主要问题似乎是触发 nfc 事件,将数据转换为 json,然后使用 webView.sendJavascript 将其发送回去,但不能真正让它工作..
【解决方案2】:

好吧,我终于设法让它工作了

在 Phonegap-nfc.js 中,我为 NFCV 标签添加了一个事件监听器

addNfcVListener: function (callback, win, fail) {
        document.addEventListener("nfcv", callback, false);
        cordova.exec(win, fail, "NfcPlugin", "registerNfcV", []);
    },

匹配的 Execute 函数如下所示

@Override
    public boolean execute(String action, JSONArray data, CallbackContext callbackContext) throws JSONException {

        Log.d(TAG, "execute " + action);

        if (!getNfcStatus().equals(STATUS_NFC_OK)) {
            callbackContext.error(getNfcStatus());
            return true; // short circuit
        }

        createPendingIntent();


         if (action.equalsIgnoreCase(REGISTER_NFCV)) {
          registerNfcV(callbackContext);

        }else {
            // invalid action
            return false;
        }

        return true;
    }

这里是标签被添加到技术列表的地方

private void registerNfcV(CallbackContext callbackContext) {
      addTechList(new String[]{NfcV.class.getName()});
      callbackContext.success();
  }

在这里,标签被解析并触发一个事件

void parseMessage() {
        cordova.getThreadPool().execute(new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "parseMessage " + getIntent());
                Intent intent = getIntent();
                String action = intent.getAction();


                Log.d(TAG, "action " + action);
                if (action == null) {
                    return;
                }


                if (action.equals(NfcAdapter.ACTION_TECH_DISCOVERED) || action.equals(NfcAdapter.ACTION_TAG_DISCOVERED)){
                     NfcvData ma;

                     Tag tagFromIntent  = (Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
                     Parcelable[] messages = intent.getParcelableArrayExtra((NfcAdapter.EXTRA_NDEF_MESSAGES));
                     NfcV mfc = NfcV.get(tagFromIntent);
                     Tag tag = mfc.getTag();
                     fireNfcVReadEvent(NFCV, mfc, messages);

                }

                setIntent(new Intent());
            }
        });
    }

那么这个事件就叫

private void fireNfcVReadEvent(String type, NfcV nfcv, Parcelable[] messages) {

        JSONObject jsonObject = buildNfcVReadJSON(nfcv, messages);
        String tag = jsonObject.toString();

        String command = MessageFormat.format(javaScriptEventTemplate, type, tag);
        Log.v(TAG, command);
        this.webView.sendJavascript(command);

    }

将标签信息发送回我的 Javascript

【讨论】:

  • 感谢 stackg91。您能否分享您的函数 buildNfcVReadJSON 的代码,因为它不包含在您的帖子中。
【解决方案3】:

您似乎没有在回调中发回任何数据,只是cordova SUCCESS。 callbackContext.success(returndatahere);有关支持的数据类型,请参阅 cordova 插件规范。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-19
    • 1970-01-01
    • 1970-01-01
    • 2012-02-29
    • 1970-01-01
    • 2011-03-14
    • 2019-12-11
    • 2014-11-14
    相关资源
    最近更新 更多