-2

I am trying to reset a string from an android javaclass. the app is an nfc app which basically has a string called value that updates every frame. When an nfc tag is detected the value updates with the stored data and if the tag data matches a specific condition an if statement is run.

However the issue I am having is the NFC tag data is stored in value constantly and this keeps triggering my if statement.

How can i clear the value string or reset it or set it to null?

void Start ()
{
    Debug.Log("JAVACLASSOBJECT CREATED");
    AndroidJNI.AttachCurrentThread ();
    pluginTutorialActivityJavaClass = new AndroidJavaClass 
    ("com.twinsprite.nfcplugin.NFCPluginTest");

}

void Update ()
{
    value = pluginTutorialActivityJavaClass.CallStatic<string> ("getValue");

    nfc_output_text.text = value;
    nfc_output_.text = outputvalue;

    if (value == "SPECIFICDATASTRING") {

        Debug.Log ("NFC BLUE SCANNED " + value);
        //DO SOMETHING
    }

I have tried to Dispose the class pluginTutorialActivityJavaClass.CallStatic<string> ("getValue").Dispose but that caused the app to crash.

Java Class

package com.twinsprite.nfcplugin;

import java.nio.charset.Charset;
import java.util.Arrays;

import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.NfcF;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;

import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.primitives.Bytes;
import com.unity3d.player.UnityPlayerActivity;

public class NFCPluginTest extends UnityPlayerActivity {

    public static final String MIME_TEXT_PLAIN = "text/plain";

    private static final BiMap URI_PREFIX_MAP = ImmutableBiMap.builder().put((byte) 0x00, "")
            .put((byte) 0x01, "http://www.").put((byte) 0x02, "https://www.").put((byte) 0x03, "http://")
            .put((byte) 0x04, "https://").put((byte) 0x05, "tel:").put((byte) 0x06, "mailto:")
            .put((byte) 0x07, "ftp://anonymous:anonymous@").put((byte) 0x08, "ftp://ftp.").put((byte) 0x09, "ftps://")
            .put((byte) 0x0A, "sftp://").put((byte) 0x0B, "smb://").put((byte) 0x0C, "nfs://")
            .put((byte) 0x0D, "ftp://").put((byte) 0x0E, "dav://").put((byte) 0x0F, "news:")
            .put((byte) 0x10, "telnet://").put((byte) 0x11, "imap:").put((byte) 0x12, "rtsp://")
            .put((byte) 0x13, "urn:").put((byte) 0x14, "pop:").put((byte) 0x15, "sip:").put((byte) 0x16, "sips:")
            .put((byte) 0x17, "tftp:").put((byte) 0x18, "btspp://").put((byte) 0x19, "btl2cap://")
            .put((byte) 0x1A, "btgoep://").put((byte) 0x1B, "tcpobex://").put((byte) 0x1C, "irdaobex://")
            .put((byte) 0x1D, "file://").put((byte) 0x1E, "urn:epc:id:").put((byte) 0x1F, "urn:epc:tag:")
            .put((byte) 0x20, "urn:epc:pat:").put((byte) 0x21, "urn:epc:raw:").put((byte) 0x22, "urn:epc:")
            .put((byte) 0x23, "urn:nfc:").build();

    private NfcAdapter mNfcAdapter;

    private PendingIntent pendingIntent;

    private IntentFilter[] mIntentFilter;

    public String value = "";

    private String[][] techListsArray;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Foreground Dispatch: 1. Creates a PendingIntent object so the Android
        // system can populate it with the details of the tag when it is
        // scanned.
        pendingIntent = PendingIntent.getActivity(NFCPluginTest.this, 0,
                new Intent(NFCPluginTest.this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

        // Foreground Dispatch: 2. Declare intent filters to handle the intents
        // that you want to intercept
        mIntentFilter = new IntentFilter[] { new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED) };

        // Foreground Dispatch: 3. Set up an array of tag technologies that your
        // application wants to handle.
        techListsArray = new String[][] { new String[] { NfcF.class.getName() } };

        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (mNfcAdapter == null) {
            Log.e(NFCPluginTest.class.toString(), "This device doesn't support NFC.");
            finish();
            return;
        }

        if (!mNfcAdapter.isEnabled()) {
            Log.e(NFCPluginTest.class.toString(), "NFC is disabled.");
        } else {
            Log.i(NFCPluginTest.class.toString(), "NFC reader initialized.");
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        mNfcAdapter.enableForegroundDispatch(this, pendingIntent, mIntentFilter, techListsArray);
    }

    @Override
    public void onPause() {
        super.onPause();
        mNfcAdapter.disableForegroundDispatch(this);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        handleIntent(intent);
    }

    private void handleIntent(Intent intent) {

        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (tag != null) {

            // parse through all NDEF messages and their records and pick text
            // type only
            Parcelable[] data = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);

            String s = "";

            if (data != null) {
                try {
                    for (int i = 0; i < data.length; i++) {
                        NdefRecord[] recs = ((NdefMessage) data[i]).getRecords();
                        for (int j = 0; j < recs.length; j++) {
                            if (recs[j].getTnf() == NdefRecord.TNF_WELL_KNOWN
                                    && Arrays.equals(recs[j].getType(), NdefRecord.RTD_TEXT)) {
                                /*
                                 * See NFC forum specification for
                                 * "Text Record Type Definition" at 3.2.1
                                 * 
                                 * http://www.nfc-forum.org/specs/
                                 * 
                                 * bit_7 defines encoding bit_6 reserved for
                                 * future use, must be 0 bit_5..0 length of IANA
                                 * language code
                                 */
                                byte[] payload = recs[j].getPayload();
                                String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
                                int langCodeLen = payload[0] & 0077;
                                s += new String(payload, langCodeLen + 1, payload.length - langCodeLen - 1,
                                        textEncoding);
                            } else if (recs[j].getTnf() == NdefRecord.TNF_WELL_KNOWN
                                    && Arrays.equals(recs[j].getType(), NdefRecord.RTD_URI)) {
                                /*
                                 * See NFC forum specification for
                                 * "URI Record Type Definition" at 3.2.2
                                 * 
                                 * http://www.nfc-forum.org/specs/
                                 * 
                                 * payload[0] contains the URI Identifier Code
                                 * payload[1]...payload[payload.length - 1]
                                 * contains the rest of the URI.
                                 */
                                byte[] payload = recs[j].getPayload();
                                String prefix = (String) URI_PREFIX_MAP.get(payload[0]);
                                byte[] fullUri = Bytes.concat(prefix.getBytes(Charset.forName("UTF-8")),
                                        Arrays.copyOfRange(payload, 1, payload.length));
                                s += new String(fullUri, Charset.forName("UTF-8"));
                            }
                        }
                    }
                } catch (Exception e) {
                    value = e.getMessage();
                    Log.e(NFCPluginTest.class.toString(), e.getMessage());
                }
            }
            Log.i(NFCPluginTest.class.toString(), s);
            value = s;
        }
    }

    public static String getValue() {
            return value;
    }

}
RKEONECS
  • 47
  • 1
  • 4

1 Answers1

1

You have to clear the string on the Java side not the C# side.

Add to your Java plugin:

public static void clearValue() 
{
    value = "";
}

From your C#, clear it after using it:

void Update ()
{
    value = pluginTutorialActivityJavaClass.CallStatic<string> ("getValue");

    nfc_output_text.text = value;
    nfc_output_.text = outputvalue;

    if (value == "SPECIFICDATASTRING") {
        //Clear
        pluginTutorialActivityJavaClass.CallStatic("clearValue");
        Debug.Log ("NFC BLUE SCANNED " + value);
        //DO SOMETHING
    }
}

That's the lazy way to accomplish it. Your Nfc plugin implementation is not good. To properly make this plugin, use a callback implemetation to call C# from Java when you receive data from NFC.

Use this to call C# from Java:

UnityPlayer.UnitySendMessage("GameObjectName", "MethodName", "parameter to send");

Java (Sender):

From your handleIntent function in Java, send the value variable to C#:

UnityPlayer.UnitySendMessage("GameObjectName", "OnNfcData", value);

The "GameObjectName" parameter is the name of GameObject this script is attached to. It will receive this callback sent from Java.

C# (Receiver):

void OnNfcData(string data)
{
    Debug.Log(data);
}

See this post to lean how to setup UnityPlayer.UnitySendMessage in Java.

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Thanks, I tried something similar, but the class file is in a jar file. I changed the jar to a zip and extracted out the class file. I am trying to edit it by adding the method clearValue but when i add the edited class file inside the jar and go to do a unity build it fails on unable to convert classes into dex format...i am using CE class editor to edit the file – RKEONECS Mar 27 '18 at 20:38
  • Why are you talking about zip files and extraction? You are supposed to modify the source code of your Java plugin from the Android Studio, compile it to jar or aar then put it in your Unity Assets/Plugin path. There is no need for every step you did above. – Programmer Mar 27 '18 at 20:49