Search Unity

NFC for Android (Unity 5.6)

Discussion in 'Scripting' started by oOKhyteOo, Jul 28, 2017.

  1. oOKhyteOo

    oOKhyteOo

    Joined:
    Mar 6, 2017
    Posts:
    7
    Hi !

    I want to read NFC tags with Unity, but I didn't found any good solution for this.
    This solution is not updated (https://github.com/twisprite-developers/unity-nfc-plugin), the Android NFC on the Asset Store is no longer available, ... I only got crash or no detection...
    All I found are obsolete solutions :( !

    So, any solution for reading NFC tags in Unity 5.6 with Android device ?
     
  2. oOKhyteOo

    oOKhyteOo

    Joined:
    Mar 6, 2017
    Posts:
    7
  3. oOKhyteOo

    oOKhyteOo

    Joined:
    Mar 6, 2017
    Posts:
    7
  4. coverpage

    coverpage

    Joined:
    Mar 3, 2016
    Posts:
    385
    You might want to email a developer of an "Android native tools" asset to see if they can implement it for you as part of their asset. An asset such as this one: https://www.assetstore.unity3d.com/en/#!/content/67473

    You might get the quickest solution this way.

    I'm clueless as I haven't need to do this before, but it probably require low level wrapping of methods with the android java libraries.
     
  5. oOKhyteOo

    oOKhyteOo

    Joined:
    Mar 6, 2017
    Posts:
    7
    (Sorry for the late answer)

    Thanks for your answer. I finally found a solution, without using java.
    I think it can help some developpers, so here's the solution :
    - go to your Unity installation folder and find the AndroidManifest.xml (like : C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Apk) and edit it like this :
    Code (csharp):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <manifest
    3.  
    4.     xmlns:android="http://schemas.android.com/apk/res/android"
    5.     package="com.unity3d.player"
    6.     xmlns:tools="http://schemas.android.com/tools"
    7.     android:installLocation="preferExternal"
    8.     android:versionCode="1"
    9.     android:versionName="1.0">
    10.  
    11.     <uses-permission android:name="android.permission.NFC" />
    12.  
    13.     <uses-feature
    14.       android:name="android.hardware.nfc"
    15.       android:required="true" />
    16.  
    17.     <uses-sdk android:minSdkVersion="10"/>
    18.  
    19.     <supports-screens
    20.         android:smallScreens="true"
    21.         android:normalScreens="true"
    22.         android:largeScreens="true"
    23.         android:xlargeScreens="true"
    24.         android:anyDensity="true"/>
    25.  
    26.     <application
    27.         android:theme="@style/UnityThemeSelector"
    28.         android:icon="@drawable/app_icon"
    29.         android:label="@string/app_name"
    30.         android:debuggable="true">
    31.         <activity android:name="com.unity3d.player.UnityPlayerActivity"
    32.                   android:label="@string/app_name">
    33.             <intent-filter>
    34.                 <action android:name="android.intent.action.MAIN" />
    35.                 <category android:name="android.intent.category.LAUNCHER" />
    36.             </intent-filter>
    37.             <intent-filter>
    38.                 <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    39.                 <action android:name="android.nfc.action.TECH_DISCOVERED" />
    40.                 <action android:name="android.nfc.action.TAG_DISCOVERED" />
    41.                 <category android:name="android.intent.category.DEFAULT" />
    42.             </intent-filter>
    43.             <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" android:value="true" />
    44.         </activity>
    45.     </application>
    46. </manifest>
    47.  
    - save this file in your Unity project, in Assets/Plugins/Android (this path can't be modify)
    - create a new xml file named nfc_tech_filter.xml in Assets/Plugins/Android/res/xml :
    Code (csharp):
    1. <?xml version="1.0" encoding="utf-8"?>
    2. <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    3.   <tech-list>
    4.     <tech>android.nfc.tech.IsoDep</tech>
    5.   </tech-list>
    6.   <tech-list>
    7.     <tech>android.nfc.tech.NfcA</tech>
    8.   </tech-list>
    9.   <tech-list>
    10.     <tech>android.nfc.tech.NfcB</tech>
    11.   </tech-list>
    12.   <tech-list>
    13.     <tech>android.nfc.tech.NfcF</tech>
    14.   </tech-list>
    15.   <tech-list>
    16.     <tech>android.nfc.tech.NfcV</tech>
    17.   </tech-list>
    18.   <tech-list>
    19.     <tech>android.nfc.tech.Ndef</tech>
    20.   </tech-list>
    21.   <tech-list>
    22.     <tech>android.nfc.tech.NdefFormatable</tech>
    23.   </tech-list>
    24.   <tech-list>
    25.     <tech>android.nfc.tech.MifareClassic</tech>
    26.   </tech-list>
    27.   <tech-list>
    28.     <tech>android.nfc.tech.MifareUltralight</tech>
    29.   </tech-list>
    30.   <tech-list>
    31.     <tech>android.nfc.tech.NfcBarcode</tech>
    32.   </tech-list>
    33. </resources>
    - now you can use NFC with Android. Here's a little code to get the ID of the NFC tag in a text canvas (this code is not 100% working today, because you can only have one tag ID, then NFC stop trying to get another tag) :
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using System;
    4. using System.Reflection;
    5. using UnityEngine;
    6. using UnityEngine.UI;
    7.  
    8. public class NFCDevice : MonoBehaviour {
    9.  
    10.     public string tagID;
    11.     public Text tag_output_text;
    12.     public bool tagFound = false;
    13.  
    14.     private AndroidJavaObject mActivity;
    15.     private AndroidJavaObject mIntent;
    16.     private string sAction;
    17.  
    18.  
    19.     void Start() {
    20.         tag_output_text.text = "No tag...";
    21.     }
    22.  
    23.     void Update() {
    24.         if (Application.platform == RuntimePlatform.Android) {
    25.             if (!tagFound) {
    26.                 try {
    27.                     // Create new NFC Android object
    28.                     mActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity");
    29.                     mIntent = mActivity.Call<AndroidJavaObject>("getIntent");
    30.                     sAction = mIntent.Call<String>("getAction");
    31.                     if (sAction == "android.nfc.action.NDEF_DISCOVERED") {
    32.                         Debug.Log("Tag of type NDEF");
    33.                     }
    34.                     else if (sAction == "android.nfc.action.TECH_DISCOVERED") {
    35.                         Debug.Log("TAG DISCOVERED");
    36.                         // Get ID of tag
    37.                         AndroidJavaObject mNdefMessage = mIntent.Call<AndroidJavaObject>("getParcelableExtra", "android.nfc.extra.TAG");
    38.                         if (mNdefMessage != null) {
    39.                             byte[] payLoad = mNdefMessage.Call<byte[]>("getId");
    40.                             string text = System.Convert.ToBase64String(payLoad);
    41.                             tag_output_text.text = text;
    42.                             tagID = text;
    43.                         }
    44.                         else {
    45.                             tag_output_text.text = "No ID found !";
    46.                         }
    47.                         tagFound = true;
    48.                         return;
    49.                     }
    50.                     else if (sAction == "android.nfc.action.TAG_DISCOVERED") {
    51.                         Debug.Log("This type of tag is not supported !");
    52.                     }
    53.                     else {
    54.                         tag_output_text.text = "No tag...";
    55.                         return;
    56.                     }
    57.                 }
    58.                 catch (Exception ex) {
    59.                     string text = ex.Message;
    60.                     tag_output_text.text = text;
    61.                 }
    62.             }
    63.         }
    64.     }
    65. }
    :)
     
    adar_unity, pikifou and Philkrom like this.
  6. fiezi

    fiezi

    Joined:
    Jul 10, 2017
    Posts:
    3
    Thank you so much for this! Works great!

    In order to scan multiple tags one after another, you just have to call

    mIntent.Call("removeExtra", "android.nfc.extra.TAG");

    when you are finished reading. At least, that's how it works for me.
     
  7. Vardemis_DE

    Vardemis_DE

    Joined:
    Apr 11, 2017
    Posts:
    2
    Hi oOKhyteOo and fiezi,

    I tried that but unfortunately it didn't work. When building the APK I get a popup window with the message Failed to re-package resources. See console for details.

    In the console the following messages are shown:

    1)
    CommandInvokationFailure: Failed to re-package resources.
    C:\Users\Antonio\AppData\Local\Android\sdk\build-tools\25.0.2\aapt.exe package --auto-add-overlay -v -f -m -J "gen" -M "AndroidManifest.xml" -S "res" -I "C:/Users/Antonio/AppData/Local/Android/sdk\platforms\android-16\android.jar" -F bin/resources.ap_ --extra-packages com.MyComp.RFID.resources -S "E:\Android RF-Delete Test\Temp\StagingArea\android-libraries\unity-android-resources\res"
    - rest of the message is ommited because of its length-

    2)
    UnityEditor.BuildPlayerWindow+BuildMethodException: Build failed with errors.
    at UnityEditor.BuildPlayerWindow+DefaultBuildMethods.BuildPlayer (BuildPlayerOptions options) [0x001b9] in C:\buildslave\unity\build\Editor\Mono\BuildPlayerWindowBuildMethods.cs:162
    at UnityEditor.BuildPlayerWindow.CallBuildMethods (Boolean askForBuildLocation, BuildOptions defaultBuildOptions) [0x00050] in C:\buildslave\unity\build\Editor\Mono\BuildPlayerWindowBuildMethods.cs:83
    UnityEditor.HostView:OnGUI()

    I'm working with Unity Version 2017.1.0f3
    Android SDK Build-Tools Shows Update Available 26.0.1 (I dont know much about Android dev, I usually work with Windows standalone applications).

    Do you know what may be causing the problem?
    Is it required to change the manifest.xml in Unity or is it enough to modifying the one in the project? I changed both but I don't like changing the files in the Unity installation directory.
    Which versions of Android SDK and Unity are you using?

    Thanks in advance!

     
  8. Vardemis_DE

    Vardemis_DE

    Joined:
    Apr 11, 2017
    Posts:
    2
    Ok, I managed to solve that problem, now compiles and runs in the Galaxy S7 i'm testing it in.
    Still have some issues with it reading more than one tag. I want it to notice when the tag is removed and read automatically the next tag that comes close, now I need to manually tell the program to read when a new tag is placed, but I guess I just need to play around a bit.

    How did I solve it? In the player settings -> Android -> Other settings -> Turn off Android TV compatibility
    I also turned off Android Game option but I think the important option is TV comp since it says "update the manifest if needed"
    I also played around with Minimum and Target API levels, currently I've set them to API level 22, need to check if that mattered.
     
    ROBYER1 likes this.
  9. oscarboude

    oscarboude

    Joined:
    Sep 19, 2017
    Posts:
    1
    Hi oOKhyteOo,

    great work, do you have some project sample? I´m new in Unity and need some initial help.
    thanks for upgrade this solution!!!
     
  10. 1155032854

    1155032854

    Joined:
    Jun 21, 2015
    Posts:
    7
    Thank you very much!

    I got an error about merging the manifest file
    I then fixed it by updating android sdk to the latest version
    and use this in the manifest:
    <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="10"
    tools:eek:verrideLibrary="com.unity3d.player"/>

    Just in case someone need to know this.
     
  11. Philkrom

    Philkrom

    Joined:
    Dec 26, 2015
    Posts:
    90
    GREAT !!!!! I was looking for a way to use NFC use for a so long time !!! I tried several tools but nothing worked. So I am very happy to read that something is working. But my problem is that I am very newbie in coding, and I don't have any idea how I can make this code working. What I want to do is to open a scene when scanning a RFID code. I mean I plan to have several scenes, each one corresponding to an NFC code. I would be very gratefull if someone could help me with something I could understand ;)
     
  12. Vel_1828

    Vel_1828

    Joined:
    Apr 12, 2014
    Posts:
    53
    Looks great but I also get the Failed to repackage the resources error. Any ideas of how to fix it? :l
     
  13. Vel_1828

    Vel_1828

    Joined:
    Apr 12, 2014
    Posts:
    53
    Alright, got it built into a scene after a hard battle with Android SDK and Java DK. Still, there is a problem - when I read an NFC, nothing happens. It let's me choose to read it with default smartphone app or with Unity app (the one created by me). Still, if I choose Unity, nothing happens.

    Am I doing something wrong? P:
     
  14. TC131425

    TC131425

    Joined:
    Jan 8, 2018
    Posts:
    2
  15. ChristophGeske

    ChristophGeske

    Joined:
    Apr 26, 2015
    Posts:
    5
  16. TC131425

    TC131425

    Joined:
    Jan 8, 2018
    Posts:
    2
    ChristophGeske. First of all thanks for your reply. Found you project on my ohne shortly after my piost here. The next problem that occurs while developing is the following. I try to use your NFC plugin together with Google Tango. So i have two plugins in my project which use the Androidmanifest.xml. Does any one know how i could manage to use them both in the same project. I found some solution but they did not worked at all.
     
  17. TheRaider

    TheRaider

    Joined:
    Dec 5, 2010
    Posts:
    2,250
  18. TheRaider

    TheRaider

    Joined:
    Dec 5, 2010
    Posts:
    2,250
  19. Ilirvg

    Ilirvg

    Joined:
    Jan 26, 2018
    Posts:
    3
    I am trying to use the above examples to read tags between two Android Phones. But I am not being able to read tags if both phones are on. If in one of them I am running the app and the other one is on sleep it works fine. But if both of them are on than the beam is being used but with beam I am not being able to read the tag it is only opening the app in the second phone.
     
    tinatotty91 likes this.
  20. Stexe

    Stexe

    Joined:
    Feb 2, 2014
    Posts:
    217
    This stuff has worked great, but I'm having some trouble figuring out how to make it automatically use the currently open app when scanning an NFC. I either get no choice or it brings up the "Open with" and then I have to select the Unity app I made.

    How do you make it automatically use the current app (my Unity project running on my Android phone) when I scan the NFC?
     
  21. rcaettano

    rcaettano

    Joined:
    Dec 11, 2012
    Posts:
    6
    Having the same issue, have you found any solution ? :)
     
  22. Stexe

    Stexe

    Joined:
    Feb 2, 2014
    Posts:
    217
    Nope. Planning on researching it in the next week again since it is a roadblock for me in continuing the dev cycle of the game I'm working on.
     
  23. rcaettano

    rcaettano

    Joined:
    Dec 11, 2012
    Posts:
    6
    Thank you Stexe, studding here how to make a java interface, the ones i found in github does not work.
     
    Stexe likes this.
  24. PravenPJose

    PravenPJose

    Joined:
    Jun 17, 2017
    Posts:
    1
    Hi,Did any one find solution for automatically use the current app?
     
  25. Stexe

    Stexe

    Joined:
    Feb 2, 2014
    Posts:
    217
    Nope, I didn't do a lot of research on it yet, but couldn't find anything that easily does it using the current method. Would love it if someone found something...
     
  26. r35

    r35

    Joined:
    Mar 5, 2015
    Posts:
    9
    Add this line for clearing the intent and scan again :
    Code (CSharp):
    1. mIntent.Call<AndroidJavaObject>("setAction", "");
    You're welcome.
     
  27. r35

    r35

    Joined:
    Mar 5, 2015
    Posts:
    9
    In order to specify NFC records to a certain app,
    the NFC tag MUST support NDEF and recorded with it.

    Edit/Add intent filter like this in Android manifest :
    (replace 'custom' to your own protocol name)
    Code (CSharp):
    1. <intent-filter>
    2.   <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    3.   <category android:name="android.intent.category.DEFAULT" />
    4.   <data android:scheme="custom" />
    5. </intent-filter>
    And write a custom URI record to your NFC tag like this :
    Code (CSharp):
    1. custom://blabla
    With this manifest and NDEF NFC tag,
    NFC scanning will launch your unity app when it's not running,
    and will not ask for how to deal with it when your app is running.

    Good luck!
     
    Stexe likes this.
  28. mojtabashamsabadi

    mojtabashamsabadi

    Joined:
    Nov 14, 2018
    Posts:
    2
    hi guys
    How to read directly nfc tag App not open again? not show choose an action read directly.
     
  29. JusticarJohn

    JusticarJohn

    Joined:
    Dec 29, 2017
    Posts:
    4
  30. plhacko

    plhacko

    Joined:
    Mar 25, 2021
    Posts:
    1
    Hi guys,
    I have made few changes to the design and managed to read simple text from the tag. (btw thanks to all, this blog helped me a lot)

    1. add to the manifest
    <data android:mimeType="text/plain" />
    and
    android:launchMode="singleTask" // this should stop the app from restartin everytime the tag is detected (this was importatnt in my Java app, but might not be needed)

    Code (CSharp):
    1.       android:name="android.hardware.nfc"
    2.       android:required="true" />
    3.  
    4.     <uses-sdk android:minSdkVersion="21"/>
    5.  
    6.     <supports-screens
    7.         android:smallScreens="true"
    8.         android:normalScreens="true"
    9.         android:largeScreens="true"
    10.         android:xlargeScreens="true"
    11.         android:anyDensity="true"/>
    12.  
    13.     <application
    14.         android:theme="@style/UnityThemeSelector"
    15.         android:icon="@drawable/app_icon"
    16.         android:label="@string/app_name">
    17.         <activity android:name="com.unity3d.player.UnityPlayerActivity"
    18.                   android:label="@string/app_name"
    19.                   android:launchMode="singleTask">
    20.             <intent-filter>
    21.                 <action android:name="android.intent.action.MAIN" />
    22.                 <category android:name="android.intent.category.LAUNCHER" />
    23.             </intent-filter>
    24.             <intent-filter>
    25.                 <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    26.                 <action android:name="android.nfc.action.TECH_DISCOVERED" />
    27.                 <action android:name="android.nfc.action.TAG_DISCOVERED" />
    28.                 <category android:name="android.intent.category.DEFAULT" />
    29.                 <data android:mimeType="text/plain" />
    30.             </intent-filter>
    31.             <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" android:value="true" />
    32.         </activity>
    33.     </application>
    34. </manifest>
    this is the code for reading (I am using tags only for plain text):

    Code (CSharp):
    1. ...
    2. ...
    3. if (!tagFound)
    4.             {
    5.                 try
    6.                 {
    7.                     // Create new NFC Android object
    8.                     mActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity"); // Activities open apps
    9.                     mIntent = mActivity.Call<AndroidJavaObject>("getIntent");
    10.                     sAction = mIntent.Call<String>("getAction"); // resulte are returned in the Intent object
    11.                     if (sAction == "android.nfc.action.NDEF_DISCOVERED")
    12.                     {
    13.                         Debug.Log("Tag of type NDEF");
    14.                         AndroidJavaObject[] rawMsg = mIntent.Call<AndroidJavaObject[]>("getParcelableArrayExtra", "android.nfc.extra.NDEF_MESSAGES");
    15.                         AndroidJavaObject[] records = rawMsg[0].Call<AndroidJavaObject[]>("getRecords");
    16.                         byte[] payLoad = records[0].Call<byte[]>("getPayload");
    17.                         string result = System.Text.Encoding.Default.GetString(payLoad); // not sure if it works for all encodings, but it works for me
    18.            
    19.                         tag_output_text.text =  result; // first few letters are about used language (for english "en..")
    20.  
    21.                     }
    22. ...
    23. ...
     
    unity_Tsz-0O-xkIpA2Q and Stexe like this.
  31. unity_Tsz-0O-xkIpA2Q

    unity_Tsz-0O-xkIpA2Q

    Joined:
    Oct 28, 2020
    Posts:
    7

    Your code really helps me, but as soon as the first nft tag has been recognized, the query runs in a continuous loop. Even if no nfc tag is held against the device, the last tag that was recognized is output as a new tag.
     
  32. awsomejojop

    awsomejojop

    Joined:
    Aug 19, 2020
    Posts:
    2
    Thank god for this, I've been stuck on an issue for a while with being able to scan a tag only once per scan, and wait for a tag after one scan is done. This one line solved the issue, and now it works exactly how I want. I can scan a tag, and as soon as I'm done with the scan, I can scan another, and it works perfectly. TYSM