Skip to content

Instantly share code, notes, and snippets.

@handstandsam
Last active January 10, 2019 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save handstandsam/86a958e3ce9bffffe43765a1f47f9c3c to your computer and use it in GitHub Desktop.
Save handstandsam/86a958e3ce9bffffe43765a1f47f9c3c to your computer and use it in GitHub Desktop.
NFC Hackathon
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="...">
<!-- To get access to the NFC hardware, you have to apply for permission in the manifest. -->
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.VIBRATE" />
<application>
<activity
android:name=".ui.ContactlessActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/Theme.AppCompat.Light.NoActionBar" />
</application>
</manifest>
import android.Manifest.permission.NFC
import android.app.Activity
import android.content.Context
import android.nfc.NfcAdapter
import android.os.Build
import android.support.annotation.RequiresApi
import android.support.annotation.RequiresPermission
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
class NfcNdefReader(
context: Context,
private val nfcReaderCallback: NfcAdapter.ReaderCallback
) {
var nfcUtils: NfcUtils = NfcUtils(context.applicationContext)
@RequiresPermission(NFC)
fun onResume(activity: Activity) {
enableReaderMode(activity)
}
fun onPause(activity: Activity) {
nfcUtils.nfcAdapter?.disableReaderMode(activity)
}
private fun enableReaderMode(activity: Activity) {
if (nfcUtils.isNfcSupportedAndEnabled) {
nfcUtils.nfcAdapter?.enableReaderMode(activity, { tag ->
nfcReaderCallback.onTagDiscovered(tag)
enableReaderMode(activity)
},
READER_FLAGS, null)
}
}
companion object {
// reader mode flags: listen for type A (not B), skipping ndef check (NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK)
private const val READER_FLAGS =
NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS
}
}
private fun showToast(message: String) {
activity?.runOnUiThread {
Toast.makeText(graph.appContext, message, Toast.LENGTH_SHORT).show()
}
}
override fun onCreate...
nfcNdefReader = NfcNdefReader(
appContext,
NfcAdapter.ReaderCallback {
tapFeedback.vibrate()
processDiscoveredTag(it)
})
tapFeedback = VibrateFeedback(appContext)
fun onTagDiscovered(tag: Tag) {
val message = NfcNdefTagReader(logger).readMessageFromTag(tag)
if (message != null) {
showToast("Message: $message")
} else {
showToast("Message was not valid")
}
}
override fun onPause() {
super.onPause()
graph.logger.log("onPause")
val currActivity: Activity? = activity
currActivity?.let { nfcNdefReader.onPause(currActivity) }
}
override fun onResume() {
super.onResume()
graph.logger.log("onResume")
val currActivity: Activity? = activity
currActivity?.let { nfcNdefReader.onResume(currActivity) }
}
import android.nfc.NdefRecord
import android.nfc.Tag
import android.nfc.tech.Ndef
import android.util.Log
import java.io.UnsupportedEncodingException
import java.nio.charset.Charset
import java.util.Arrays
class NfcNdefTagReader() {
@Throws(UnsupportedEncodingException::class)
private fun readMessageFromNdefRecord(record: NdefRecord): String? {
val payload = record.payload
val fullMessage = String(payload, Charset.forName("UTF-8"))
return fullMessage
}
fun readMessageFromTag(tag: Tag): String? {
var message: String? = null
logIt(
"readMessageFromTag, describeContents= " + tag.describeContents() + ", getId= " + HexUtils.toHexString(
tag.id
) + ", toString= '" + tag.toString() + "'"
)
val techList = tag.techList
if (techList != null) {
for (str in techList)
logIt("Tech: '$str'")
}
val ndef = Ndef.get(tag)
if (ndef == null) {
// NDEF is not supported by this Tag.
logIt("NDEF is not supported by this Tag.")
} else {
val records: Array<NdefRecord>
logIt("Got Ndef: type= '" + ndef.type + "'")
val ndefMessage = ndef.cachedNdefMessage
if (ndefMessage != null) {
logIt("Got ndefMessage: describeContents= " + ndefMessage.describeContents() + ", byteArrayLength= " + ndefMessage.byteArrayLength + ", toString= " + ndefMessage.toString())
records = ndefMessage.records
logIt("Got records: length= " + records.size)
if (records.isNotEmpty()) {
for (ndefRecord in records) {
logIt(
"Got record: tnf= " + ndefRecord.tnf + ", describeContents= " + ndefRecord.describeContents() + ", toMomeType= '" + ndefRecord.toMimeType() + "', toUri= " + ndefRecord.toUri() + ", toString= '" + ndefRecord.toString() + "', getType= " + HexUtils.toHexString(
ndefRecord.type
)
)
if (ndefRecord.tnf == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(
ndefRecord.type,
NdefRecord.RTD_TEXT
)
) {
logIt("ActivateNewCard: Got a Text Record")
try {
message = readMessageFromNdefRecord(ndefRecord)
logIt("text= '" + message!!.trim { it <= ' ' } + "'")
} catch (e: Exception) {
logIt(e, "readMessageFromTag()")
}
}
}
} else {
logIt("No Records!!!")
}
} else {
logIt("No ndefMessage!!!")
}
}
return message
}
private fun logIt(e: Throwable?, message: String) {
logger.log(message, e, Log.DEBUG)
}
private fun logIt(message: String) {
logIt(null, message)
}
}
import android.content.Context
import android.nfc.NfcAdapter
import android.os.Build
class NfcUtils(context: Context) {
val nfcAdapter: NfcAdapter? = NfcAdapter.getDefaultAdapter(context.applicationContext)
/**
* Checks if NFC is fully supported for our needs in the current Android version
*
* @return boolean
*/
private val isNfcSupportedByOs: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
/**
* Checks if NFC is fully supported for our needs in the current Android version
*
* @return boolean
*/
val isNfcSupportedByDevice: Boolean
get() = isNfcSupportedByOs && nfcAdapter != null
/**
* Checks if NFC is enabled on the device
*
* @return boolean
*/
val isNfcEnabled: Boolean
get() = nfcAdapter != null && nfcAdapter.isEnabled
val isNfcSupportedAndEnabled: Boolean
get() = isNfcSupportedByOs && isNfcEnabled
}
import android.content.Context
import android.media.MediaPlayer
import android.os.Vibrator
class VibrateFeedback(context: Context) {
private val vibrator: Vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
fun vibrate() {
//Vibrate
val pattern = longArrayOf(0, 50, 50, 50)
vibrator.vibrate(pattern, -1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment