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 ?
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.
(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): <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools" android:installLocation="preferExternal" android:versionCode="1" android:versionName="1.0"> <uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <uses-sdk android:minSdkVersion="10"/> <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true"/> <application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="true"> <activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <action android:name="android.nfc.action.TECH_DISCOVERED" /> <action android:name="android.nfc.action.TAG_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" android:value="true" /> </activity> </application> </manifest> - 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): <?xml version="1.0" encoding="utf-8"?> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.IsoDep</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcA</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcB</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcF</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcV</tech> </tech-list> <tech-list> <tech>android.nfc.tech.Ndef</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NdefFormatable</tech> </tech-list> <tech-list> <tech>android.nfc.tech.MifareClassic</tech> </tech-list> <tech-list> <tech>android.nfc.tech.MifareUltralight</tech> </tech-list> <tech-list> <tech>android.nfc.tech.NfcBarcode</tech> </tech-list> </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): using System.Collections; using System.Collections.Generic; using System; using System.Reflection; using UnityEngine; using UnityEngine.UI; public class NFCDevice : MonoBehaviour { public string tagID; public Text tag_output_text; public bool tagFound = false; private AndroidJavaObject mActivity; private AndroidJavaObject mIntent; private string sAction; void Start() { tag_output_text.text = "No tag..."; } void Update() { if (Application.platform == RuntimePlatform.Android) { if (!tagFound) { try { // Create new NFC Android object mActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity"); mIntent = mActivity.Call<AndroidJavaObject>("getIntent"); sAction = mIntent.Call<String>("getAction"); if (sAction == "android.nfc.action.NDEF_DISCOVERED") { Debug.Log("Tag of type NDEF"); } else if (sAction == "android.nfc.action.TECH_DISCOVERED") { Debug.Log("TAG DISCOVERED"); // Get ID of tag AndroidJavaObject mNdefMessage = mIntent.Call<AndroidJavaObject>("getParcelableExtra", "android.nfc.extra.TAG"); if (mNdefMessage != null) { byte[] payLoad = mNdefMessage.Call<byte[]>("getId"); string text = System.Convert.ToBase64String(payLoad); tag_output_text.text = text; tagID = text; } else { tag_output_text.text = "No ID found !"; } tagFound = true; return; } else if (sAction == "android.nfc.action.TAG_DISCOVERED") { Debug.Log("This type of tag is not supported !"); } else { tag_output_text.text = "No tag..."; return; } } catch (Exception ex) { string text = ex.Message; tag_output_text.text = text; } } } } }
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.
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!
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.
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!!!
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" toolsverrideLibrary="com.unity3d.player"/> Just in case someone need to know this.
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
Looks great but I also get the Failed to repackage the resources error. Any ideas of how to fix it? :l
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:
Hey Guys, the Example of oOKhyteOo works fine for me. The only Problem I have is that the detection only works if the App is not running. If the App is running nothings happening. Do you have any suggestion where this Problem comes from?
I created a simple project on github using your code so everyone who wants to build a NFC reader can safe some time. https://github.com/ChristophGeske/Near-Field-Communication-NFC-For-Unity-Android
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.
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.
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?
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.
Thank you Stexe, studding here how to make a java interface, the ones i found in github does not work.
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...
Add this line for clearing the intent and scan again : Code (CSharp): mIntent.Call<AndroidJavaObject>("setAction", ""); You're welcome.
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): <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="custom" /> </intent-filter> And write a custom URI record to your NFC tag like this : Code (CSharp): 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!
What Equipment did you connect in order to read the NFC? I have my reader connected to the arduino. It reads fine in IDE but in unity it does nothing
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): android:name="android.hardware.nfc" android:required="true" /> <uses-sdk android:minSdkVersion="21"/> <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true"/> <application android:theme="@style/UnityThemeSelector" android:icon="@drawable/app_icon" android:label="@string/app_name"> <activity android:name="com.unity3d.player.UnityPlayerActivity" android:label="@string/app_name" android:launchMode="singleTask"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> <action android:name="android.nfc.action.TECH_DISCOVERED" /> <action android:name="android.nfc.action.TAG_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" android:value="true" /> </activity> </application> </manifest> this is the code for reading (I am using tags only for plain text): Code (CSharp): ... ... if (!tagFound) { try { // Create new NFC Android object mActivity = new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity"); // Activities open apps mIntent = mActivity.Call<AndroidJavaObject>("getIntent"); sAction = mIntent.Call<String>("getAction"); // resulte are returned in the Intent object if (sAction == "android.nfc.action.NDEF_DISCOVERED") { Debug.Log("Tag of type NDEF"); AndroidJavaObject[] rawMsg = mIntent.Call<AndroidJavaObject[]>("getParcelableArrayExtra", "android.nfc.extra.NDEF_MESSAGES"); AndroidJavaObject[] records = rawMsg[0].Call<AndroidJavaObject[]>("getRecords"); byte[] payLoad = records[0].Call<byte[]>("getPayload"); string result = System.Text.Encoding.Default.GetString(payLoad); // not sure if it works for all encodings, but it works for me tag_output_text.text = result; // first few letters are about used language (for english "en..") } ... ...
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.
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