javascript - 为NfcV标签创建自定义的Cordova插件

2019年5月24日 2点热度 0条评论

嗨,我有问题,我需要从NfcV(ISO 15693)标签中读取数据,我已经尝试了Chariotsolution的Phonegap-Nfc插件,但似乎此插件只能读取TagId和NfcV标签的类型,所以我决定我可以创建自己的自定义插件,我首先对echo Hello World Plugin教程进行了演示,该教程运行良好且没有问题,因此我寻找了Java NfcV阅读器并找到了Java NfcV Reader

到目前为止,我需要调用cordova.exec函数并从正在运行的CordovaPlugin扩展我的Java类。

我不懂Java,因为我是Webdeveloper,这对我来说有点难。

这实际上看起来还不错,但是我试图以Hello World回声示例的方式实现该示例,但该示例并未按计划进行。

我现在有一个插件文件夹

你好

    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.");
            }
        }
    }

从上面的链接中读取ReadNfcV.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插件,没有找到任何关于该主题的东西。

亲切的问候克里斯托弗

更新第1天

我将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标签没有被读取,要么我只是没有得到任何不确定的东西...

解决方案如下:

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

您可以删除很多东西,因为原始插件仅处理NDEF标签,但是删除线条比重新发明轮子要快。

我的脑袋有点老了,所以我不确定我能正确解释一切吗...
我的需要是读取Mifare经典标签中的信息,但也许您可以适应您的需求...
因此,如果您查看NfcPlugin.java,则在execute函数中,我所保留的只是 Action REGISTER_DEFAULT_TAG和INIT的代码。

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

所以这让我们
public boolean execute(String action,JSONArray data,CallbackContext callbackContext)抛出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))

在这方面,我拥有处理代码的所有代码。

在该代码中,可以使用类似以下内容的意图从标记中获取信息:

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

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

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

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