B4A Library NfcForeground library - NFC Foreground Dispatch System

(Previous related posts:
http://www.b4x.com/android/forum/threads/nfc-foreground-dispatch-system.23576/
http://www.b4x.com/android/forum/threads/using-the-foreground-dispatch-system-for-nfc.31002/ )

Usually when a NFC tag is scanned, a list of applications defined to handle NFC tag information is shown on the screen.
By using the Foreground Dispatch System, if a NFC tag is scanned while the application/activity is active (foreground), then the activity will use the NFC tag information immediately instead of showing a list of applications.

Background: Android Developers - Advanced NFC: http://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc.html.
Generally the foreground dispatch system allows an activity to intercept an intent and claim priority over other activities that handle the same intent.

The NfcForeground library gives the possibility to use the NFC Foreground Dispatch System.

The library contains NfcForeground type with following members:
  • .EnableForeground
    Tests if NFC Adapter exists in the device, and enables the Foreground Dispatch System.
    To be used in Sub Activity_Resume.

  • .DisableForeground
    Tests if NFC Adapter exists in the device, and disables the Foreground Dispatch System.
    To be used in Sub Activity_Pause.

  • .NfcExists
    Tests if NFC Adapter exists in the device.
    Returns True or False. [Read only]

  • .NfcEnabled
    Tests if NFC Adapter exists and is enabled (active).
    Returns True (NFC enabled) or False (NFC disabled or does not exist). [Read only]

Here is an example of code using this library.
Put a button "Btn_NFC" on your layout. The button will be automatically disabled by the code if the device does not have NFC function.
You can click on the button in order to access NFC settings. NFC cannot be activated programmatically, this has to be done manually by the user.

B4X:
Sub Process_Globals
 
  ' Check if SDK >= 10, otherwise you get an error message if SDK < 10
  ' Settings list: http://developer.android.com/reference/android/provider/Settings.Secure.html
  Dim Obj_Phone2 As Phone  ' Phone type from Phone library
  Dim AndroidSdk10 As Boolean        : AndroidSdk10 = False  ' Valeur de contrôle de SDK >= 10
  If Obj_Phone2.SdkVersion >= 10 Then
      AndroidSdk10 = True
      Dim NFC1 As NFC
  End If
 
End Sub

Sub Globals
 
  If AndroidSdk10 = True Then
      Dim NfcF As NfcForeground  ' NfcForeground type from NfcForeground library
  End If
 
  ' Button on the layout
  Dim Btn_NFC As Button
 
End Sub

Sub Activity_Resume
 
  ' Remove views from the layout in case the activity is restarted by NFC
  ' otherwise the new views come above the old ones
  For i = Activity.NumberOfViews - 1 To 0 Step -1
      Activity.RemoveViewAt(i)
  Next
 
  ' (...Layout/views...)
 
   
  ' Button initially not activated (SDK < 10)
  'Btn_NFC.Text = "NFC ikke tilgjengelig"
  Btn_NFC.Text = "NFC not available"
  Btn_NFC.Enabled = False
 
  If AndroidSdk10 = True Then 
     
      ' Enable/disable button if NFC adapter exists or not
      Btn_NFC.Enabled = NfcF.NfcExists
      ' It is also possible to hide/show button with Btn_NFC.Visible = NfcF.NfcExists
     
      If NfcF.NfcExists = False Then
        'Btn_NFC.Text = "NFC ikke tilgjengelig"
        Btn_NFC.Text = "NFC not available"
     
      Else If NfcF.NfcEnabled Then
        'Btn_NFC.Text = "NFC På - " & CRLF & "Hold mot NFC-merke"
        Btn_NFC.Text = "NFC On - " & CRLF & "Tap NFC tag"
        Btn_NFC.Color = Colors.Green
      Else
        'Btn_NFC.Text = "NFC Av - " & CRLF & "Åpne innstillinger"
        Btn_NFC.Text = "NFC Off - " & CRLF & "Open settings"
        Btn_NFC.Color = Colors.RGB(255, 127, 255)
      End If
     
      ' Enable NFC Foreground Dispatch System
      NfcF.EnableForeground
     
      ' Read NFC tag
      ' http://www.b4x.com/android/forum/threads/reading-ndef-data-from-nfc-tags.14931/
      If NFC1.IsNdefIntent(Activity.GetStartingIntent) Then
       
        Dim List_NdefRecords As List
        List_NdefRecords = NFC1.GetNdefRecords(Activity.GetStartingIntent)
       
        Dim NdefRecord2 As NdefRecord
        NdefRecord2 = List_NdefRecords.Get(0)
        Dim NfcText As String
        If NdefRecord2.IsTextType Then
            NfcText = NdefRecord2.GetAsTextType
            ' => Go to Sub using the data from the NFC tag
            Sub_NfcFound(NfcText)
        Else
            ' Error message if wrong data format
            Msgbox("Wrong data format in NFC tag", "xxxxx")
        End If
       
      End If  ' End If NFC1.IsNdefIntent
     
  End If  ' End If MobilAndroidSdk10 = True
   
End Sub

Sub Activity_Pause(UserClosed As Boolean)
 
  ' Disable NFC Foreground Dispatch System
  If AndroidSdk10 = True Then 
      NfcF.DisableForeground
  End If
 
End Sub

' Action when clicking on button
Sub Btn_NFC_Click
 
  If AndroidSdk10 = True Then 
      ' Open NFC Settings screen (not possible to activate/deactivate NFC programmatically)
      Dim DoAction As Intent
      DoAction.Initialize("android.settings.NFC_SETTINGS", "")
      StartActivity(DoAction)
  End If
 
End Sub

' Action to do with the NFC tag information
' Sub called from Activity_Resume
Sub Sub_NfcFound(NfcText As String)
   
   ToastMessageShow("NFC text =" & CRLF & _
     NfcText, True)
   ' ......

End Sub


In addition, if you want the application to be shown on the screen when you scan a NFC tag, you have to put following code in the Manifest Editor:

B4X:
' Open application when using NFC
AddActivityText(activityxxxxxxxxxxxxx,
<intent-filter>
  <action android:name="android.nfc.action.NDEF_DISCOVERED" />
  <category android:name="android.intent.category.DEFAULT" />
  <data android:mimeType="text/plain" />
</intent-filter>)
where "activityxxxxxxxxxxxxx" is the name of the activity to be opened.
NB: You don't need this code in the Manifest Editor if you only want to use the NFC tag information when the application/activity is already active in foreground.

Please find attached NfcForeground library in ZIP file. Decompress the ZIP file and put the JAR and XML files in your B4A library folder.

Version 1.0 - 2013-07-17.

Tested with Asus Nexus 7 tablet (Android 4.2.2) and Samsung Galaxy S Relay phone (Android 4.1.2).

This is the first libray I make and I'm just an occasional programmer, so I guess it's possible to improve the code. Your comments are welcome :)
 

Attachments

  • NfcForeground 1.0.zip
    3 KB · Views: 949

sdujolo

Member
Licensed User
Longtime User
If you switch between landscape and portrait it act like you reading the tag again how to fix that?

Regards
 

sdujolo

Member
Licensed User
Longtime User
Store Activity.GetStartingIntent in a process global variable (of type Intent).

Now you can check in Activity_Resume:
B4X:
If Activity.GetStartingIntent <> StoredIntent Then
  ...
End If
StoredIntent = Activity.GetStartingIntent
Thanks :)
 

raphaelcno

Active Member
Licensed User
Longtime User
The code in the Sub opening NFC settings
B4X:
Sub Btn_NFC_Click
    If AndroidSdk10 = True Then 
        ' Open NFC Settings screen (not possible to activate/deactivate NFC programmatically)
        Dim DoAction As Intent
        DoAction.Initialize("android.settings.NFC_SETTINGS", "")
        StartActivity(DoAction)
    EndIf
End Sub

may be replaced by this code found in NFCtestapp.zip > NFCcheckApp.b4a from DavideV
https://www.b4x.com/android/forum/threads/check-if-a-device-has-nfc-and-its-status.49863/
B4X:
Sub OpenNFCsettings

    'try open the nfc setting, the intent is api dependant
    'http://developer.android.com/reference/android/provider/Settings.html
  
    Dim In As Intent
    Dim Ph As Phone
    Dim ApiLevel As Int = Ph.SdkVersion
  
    Try      
        If ApiLevel >=16 Then          
            In.Initialize("android.settings.NFC_SETTINGS","")
        Else
            'on old devices is located in wireless settings
            In.Initialize("android.settings.WIRELESS_SETTINGS","")
        End If
          
        StartActivity(In)
    Catch
        Log("error opening the NFC settings: " & LastException.Message)
    End Try

End Sub
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
Is there a way to get this to work without the activity re-opening each time? Maybe through a service instead of the activity?
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
The method GetNdefByteArray has gone missing as of B4A Beta 1. How would I get the MAC address/ID code of the NFC chip now?

Dim NFC1 As NFC
Also no longer works within Process_Globals
 

raphaelcno

Active Member
Licensed User
Longtime User
The method GetNdefByteArray has gone missing as of B4A Beta 1. How would I get the MAC address/ID code of the NFC chip now?

Dim NFC1 As NFC
Also no longer works within Process_Globals

Are you sure this question is related to the NfcForeground library?
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
No, I figured out some of it. The regular NFC library doesn't work anymore. I can't get the ID bytes
 
Top