<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/rss-style.xsl" type="text/xsl"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	     xmlns:dc="http://purl.org/dc/elements/1.1/"
	   xmlns:atom="http://www.w3.org/2005/Atom"
	     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>Kotlin &#8211; Terence Eden’s Blog</title>
	<atom:link href="https://shkspr.mobi/blog/tag/kotlin/feed/" rel="self" type="application/rss+xml" />
	<link>https://shkspr.mobi/blog</link>
	<description>Regular nonsense about tech and its effects 🙃</description>
	<lastBuildDate>Wed, 26 Feb 2025 23:06:13 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shkspr.mobi/blog/wp-content/uploads/2023/07/cropped-avatar-32x32.jpeg</url>
	<title>Kotlin &#8211; Terence Eden’s Blog</title>
	<link>https://shkspr.mobi/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title><![CDATA[ManyTag Colour eInk Badge SDK - Minimum Viable Example for Android]]></title>
		<link>https://shkspr.mobi/blog/2025/02/manytag-colour-eink-badge-sdk-minimum-viable-example-for-android/</link>
					<comments>https://shkspr.mobi/blog/2025/02/manytag-colour-eink-badge-sdk-minimum-viable-example-for-android/#respond</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 28 Feb 2025 12:34:30 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[eink]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[Kotlin]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=58487</guid>

					<description><![CDATA[Last year, I reviewed a Four-Colour eInk Name Badge - the ManyTag HSN371. The hardware itself is perfectly fine, but the Android app isn&#039;t great. It is complicated, crash-prone, and not available in the app-store.  After some back-and-forth with the manufacturer, they agreed to send me their Android SDK and documentation. Sadly, the PDF they sent me was riddled with errors and the software…]]></description>
										<content:encoded><![CDATA[<p>Last year, I reviewed a <a href="https://shkspr.mobi/blog/2024/11/review-four-colour-eink-name-badge-hsn371-plus-linux-and-android-tips/">Four-Colour eInk Name Badge</a> - the ManyTag HSN371. The hardware itself is perfectly fine, but the Android app isn't great. It is complicated, crash-prone, and not available in the app-store.</p>

<p>After some back-and-forth with the manufacturer, they agreed to send me their Android SDK and documentation. Sadly, the PDF they sent me was riddled with errors and the software library is also a bit dodgy. So, with the help of <a href="https://hades.omg.lol/">Edward Toroshchyn</a> and a hefty amount of automated boiler-plate, I managed to get it working.</p>

<p>The <a href="https://codeberg.org/edent/eInk-SDK/">full code is open source</a>, but here's a quick walk-through of the important bits.</p>

<p>First, the AAR library needs to be imported into the project. Place it in <code>app/libs</code> and then include it in the Gradle build file:</p>

<pre><code class="language-java">dependencies {
    implementation(files("libs/badge_nfc_api-release.aar"))
}
</code></pre>

<p>The key to getting it working is in the Android permissions. It needs Bluetooth, NFC, and location. So the manifest has to contain:</p>

<pre><code class="language-xml">&lt;uses-permission android:name="android.permission.BLUETOOTH"/&gt;
&lt;uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/&gt;
&lt;uses-permission android:name="android.permission.BLUETOOTH_SCAN"/&gt;
&lt;uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/&gt;
&lt;uses-permission android:name="android.permission.NFC"/&gt;
&lt;uses-permission android:name="android.permission.NFC_TRANSACTION_EVENT"/&gt;
&lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/&gt;
&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/&gt;
</code></pre>

<p>The following imports are needed from the Android Archive library:</p>

<pre><code class="language-java">import cn.manytag.badge_nfc_api.manager.BadgeWriteManager
import cn.manytag.badge_nfc_api.manager.OnNFCReaderCallback
import cn.manytag.badge_nfc_api.manager.OnBluetoothCallBack
import cn.manytag.badge_nfc_api.manager.OnSendImageCallback
</code></pre>

<p>The library needs to be initialised with:</p>

<pre><code class="language-java">val state = BadgeWriteManager.getInstance().init(this)
</code></pre>

<p>When the phone reads the NFC tag, it gets a bunch of information:</p>

<pre><code class="language-java">BadgeWriteManager.getInstance().setOnNFCReaderCallback(object : OnNFCReaderCallback {
    override fun onReaderMessage(i: Int, tag: Tag) {
        if (i == 0) {
            BadgeWriteManager.getInstance().readNFC(tag)
        }
    }

    //  Get the data from the badge
    override fun onReaderType(tag: Tag, isodep: IsoDep, i: Int, type: String, size: String, color: String) {
        if (i == 0) {
            nfcData = """
                NFC Tag Detected!!!
                Tag: $tag
                IsoDep: $isodep
                Type: $type
                Size: $size
                Color: $color
            """.trimIndent()
            colorFromNFC = color
            tagObject = tag
            isoDepObject = isodep
            badgeType = type
            badgeSize = size
        }
    }
})
</code></pre>

<p>The <code>color</code> is most important right now. It says whether the badge is black and white, or black and white and red, or black and white and red and yellow.</p>

<p>After picking an image from the filesystem, it needs to be dithered into the correct colour format:</p>

<pre><code class="language-java">processedBitmap = originalBitmap?.let { bitmap -&gt;
    colorFromNFC?.let { color -&gt;
        BadgeWriteManager.getInstance().processImage(bitmap, color)
    }
}
</code></pre>

<p>Finally, the processed image needs to be converted to bytes and then sent to the badge via Bluetooth:</p>

<pre><code class="language-java">if (processedBitmap != null &amp;&amp; badgeType != null &amp;&amp; badgeSize != null &amp;&amp; colorFromNFC != null) {
    val imgData = BadgeWriteManager.getInstance().getImageData(processedBitmap!!, colorFromNFC!!)

    BadgeWriteManager.getInstance().sentImageResource(
        tagObject!!, isoDepObject!!, imgData, badgeType!!, badgeSize!!, colorFromNFC!!
    )
}
</code></pre>

<p>I realise this is a bit "<a href="https://knowyourmeme.com/memes/how-to-draw-an-owl">draw the rest of the owl</a>" but that should be enough to get you started on building an app which can communicate with these badges.</p>

<p>The app I've built isn't the prettiest in the world but at least it works. It scans a badge, gets its info, picks an image, dithers it, then sends it to the badge.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/02/badge-app-fs8.png" alt="Screenshot of an app." width="504" height="957" class="aligncenter size-full wp-image-58494">

<p>You can <a href="https://codeberg.org/edent/eInk-SDK/">play with the code on CodeBerg</a>.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=58487&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/02/manytag-colour-eink-badge-sdk-minimum-viable-example-for-android/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
