Last active
January 10, 2019 16:20
-
-
Save handstandsam/86a958e3ce9bffffe43765a1f47f9c3c to your computer and use it in GitHub Desktop.
NFC Hackathon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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