POS doesn't start printing - android

I am building an Android Application that helps users to print a receipt. What I've done so far:
Right now, I can find the device/printer(DATECS DP-25) through Bluetooth and connect it to the printer. The connection flow works perfectly. Problem is that my printer doesn't start printing at all with the commands that I've introduced so far.
Probably commands are wrong, or I don't really know exactly what is the problem. I tried a lot of apps but none of them with success in printing. Just one app from PlayStore it's working but no access to the code of that app.
Code for the printing flow:
Initializing variables:
private suspend fun init(): Boolean {
return withContext(Dispatchers.IO) {
return#withContext try {
uuidSting = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb")
bluetoothSocket = bluetoothDevice.createRfcommSocketToServiceRecord(uuidSting)
bluetoothSocket.connect()
outputStream = bluetoothSocket.outputStream
inputStream = bluetoothSocket.inputStream
printWriter = PrintWriter(outputStream.bufferedWriter(Charsets.ISO_8859_1))
true
} catch (e: Exception) {
println(e.stackTraceToString())
false
}
}
}
Print function:
fun print(text: String){
printerController.apply {
initPrinter()
patchText(text)
nextLine()
nextLine()
}
}
#Throws(IOException::class)
fun initPrinter() {
printWriter.write(0x1B)
printWriter.write(0x40)
printWriter.flush()
}
#Throws(IOException::class)
fun patchText(text: String) {
printWriter.println(text)
printWriter.flush()
}
#Throws(IOException::class)
fun nextLine() {
printWriter.write("\n")
printWriter.flush()
}
I would be more than happy if anybody can help me with some advice or directions.

Related

Android Health Connect freezing when making a request after 15 seconds

I am using Health Connect to read records, like steps and exercises. I use Health Connect in a few different places in Kotlin, and the code generally looks something like:
suspend fun fetchStepData(
healthConnectClient: HealthConnectClient,
viewModel: StepViewViewModel,
): StepViewViewModel {
kotlin.runCatching {
val todayStart = Instant.now().atZone(ZoneId.systemDefault()).toLocalDate().atStartOfDay();
val response: ReadRecordsResponse<StepsRecord>
try {
response = healthConnectClient.readRecords(
ReadRecordsRequest(
StepsRecord::class,
timeRangeFilter = TimeRangeFilter.after(todayStart)
)
)
var steps: Long = 0;
if (response.records.isNotEmpty()) {
for (stepRecord in response.records) {
steps += stepRecord.count
}
}
return viewModel
} catch (e: Exception) {
Log.e("StepUtil", "Unhandled exception, ", e)
}
}
return viewModel
}
I have an update function that is run when focus changes to ensure that the app is in the foreground.
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
binding.root.invalidate()
val fragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment_activity_main)?.childFragmentManager?.primaryNavigationFragment
if (fragment is MyFragment) {
displayLoadingIndicator(true)
runBlocking {
if (fragment.fetchStepData(this#MainActivity.healthConnectClient, fragment.getViewModel()) != null) {
displayLoadingIndicator(false)
}
}
}
I have a loading indicator present when I am fetching the data.
I use a drawer, and if I wait about 15 seconds and press the drawer button corresponding with MyFragment, the application hangs on the loading indicator, never successfully dismissing it.
I've tried stepping through the application in debug mode, and as I do, I always hang on
response = healthConnectClient.readRecords(
ReadRecordsRequest(
StepsRecord::class,
timeRangeFilter = TimeRangeFilter.after(todayStart)
)
)
in fetchStepData. I did at one point have my application making multiple requests for HealthConnectClient.getOrCreate(context), but I have since consolidated them to one instantiation call. I'm thinking I may be reading the data wrong and maybe I need to use getChanges, or maybe I'm being rate limited. Does anyone have any insight? Thanks in advance!

How to implement the checking of internet Android using RxJava/Rx Android Kotlin?

The answer for checking internet was posted back in 2014 in this post: https://stackoverflow.com/a/27312494/12359431
However, in one of the answer, there is this piece of code
fun hasInternetConnection(): Single<Boolean> {
return Single.fromCallable {
try {
// Connect to Google DNS to check for connection
val timeoutMs = 1500
val socket = Socket()
val socketAddress = InetSocketAddress("8.8.8.8", 53)
socket.connect(socketAddress, timeoutMs)
socket.close()
true
} catch (e: IOException) {
false
}
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
I have tried it by implementing the code above to my code at the bottom. However, it just crashes and I could not get any finding of the error as to why the app crash.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
/* Initialise Azure Service Adapter */
AzureServiceAdapter.Initialize(this)
hasInternetConnection().subscribe{hasInternet->
/*Call database and check phone number*/
Log.i("Logger", "Connected")}
/* Authentication */
authUser()
}
}
This is my implementations
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'io.reactivex.rxjava3:rxjava:3.0.0'
Is there anything I'm lacking or I shouldn't add to my MainActivity File? Or a clue as to why my kotlin app crash ?
That's because you cant call this on main Thread.
Check if you added Internet permission in Manifest.
hasInternetConnection()
.subscribeOn(Schedulars.io())
.observeOn(AndroidSchedulars.mainThread()).subscribe{hasInternet->
/*Call database and check phone number*/
Log.i("Logger", "Connected")}

Handling incoming bluetooth data stream in Kotlin Android app

I am working on a small app that connects via bluetooth to an Arduino with a bluetooth shield attached. My bluetooth connection is fine and I'm able to send commands from my app to the Arduino. I'm doing this in Kotlin. I'm learning as I go, so I'm misunderstanding something. Which is where I hope someone can point me in the right direction.
You can assume that all the bluetooth connection stuff is working fine(it is).
This is the part of my code that handles the sending of data to the Arduino.
private fun writeDataSendToMothership(outputToBt: String) {
try {
bluetoothSocket.outputStream.write(outputToBt.toByteArray())
Log.i(LOGTAG, "Button clicked, info sent: $outputToBt")
} catch (e: IOException) {
e.printStackTrace()
}
}
button_led_on.setOnClickListener { writeDataSendToMothership("1")}
button_led_off.setOnClickListener { writeDataSendToMothership("0")}
The part i'm having trouble with is receiving data from the Arduino(Mothership) and doing something with it. I cannot figure out what I need to do.
What I am trying to do is show an image in the app depending on what the Arduino sends after a button on the Arduino is pushed.
What I have so far is:
private fun readDataFromMothership(inputFromBt: String) {
try {
bluetoothSocket.inputStream.read(inputFromBt.toByteArray())
Log.i(LOGTAG, "Incoming data from Mothership recieved: $inputFromBt")
} catch (e: IOException) {
e.printStackTrace()
}
}
private fun View.showOrInvisible(imageShow: Boolean) {
visibility = if (imageShow) {
View.VISIBLE
} else {
View.INVISIBLE
}
}
This is where I fall flat.
if (readDataFromMothership()) {
imageView_mothership_button_pushed.showOrInvisible(true)
} else {
imageView_mothership_button_pushed.showOrInvisible(false)
}
I've left out anything from that function call. I've tried many different things, but I'm just not understanding what parameter I need, or am I way off. Am I even in the right neighborhood?
EDIT Other than my lack of general knowledge about programming, I think my hangup has to do with what to do with the "inputFromBt" String. Do I need to use a buffer of some sort. I'm trying/researching/reading up on everything I can. But stalling out.
Here is the code I have in place and currently working in my app:
private fun readBlueToothDataFromMothership(bluetoothSocket: BluetoothSocket) {
Log.i(LOGTAG, Thread.currentThread().name)
val bluetoothSocketInputStream = bluetoothSocket.inputStream
val buffer = ByteArray(1024)
var bytes: Int
//Loop to listen for received bluetooth messages
while (true) {
try {
bytes = bluetoothSocketInputStream.read(buffer)
val readMessage = String(buffer, 0, bytes)
liveData.postValue(readMessage)
} catch (e: IOException) {
e.printStackTrace()
break
}
}
}
// display or don't star image
private fun View.showOrHideImage(imageShow: Boolean) {
visibility = if (imageShow) View.VISIBLE else View.GONE
}
I mentioned in a comment to user frnnd, My main issue was the data being sent from my arduino. I was using println() instead of print() and that newline was messing things up.

How to send and receive strings through TCP connection using kotlin

I have a TCP Server on Windows, and I want to send and receive text strings between the server and my Android device.
I spent alot of time searching for an example using Kotlin but I didn't find any useful code, so I'm now only able to create the socket and connect.
fun connect() {
try{
val soc = Socket("192.168.1.5", 1419)
val dout = DataOutputStream(soc.getOutputStream())
dout.writeUTF("1")
dout.flush()
dout.close()
soc.close()
}
catch (e:Exception){
e.printStackTrace()
}
}
You can check this simple example. Hope it'll help you!
Server:
fun main() {
val server = ServerSocket(9999)
println("Server running on port ${server.localPort}")
val client = server.accept()
println("Client connected : ${client.inetAddress.hostAddress}")
val scanner = Scanner(client.inputStream)
while (scanner.hasNextLine()) {
println(scanner.nextLine())
break
}
server.close()
}
Client:
fun main() {
val client = Socket("127.0.0.1", 9999)
client.outputStream.write("Hello from the client!".toByteArray())
client.close()
}
You can also do it with ktor, it's a kotlin based asynchronous framework. It uses coroutines natively which allow concurrency.
Use Kotlin 1.4 and ktor 1.6.0, add it to your build.gradle.kts:
plugins {
kotlin("jvm") version "1.4.32"
}
dependencies {
implementation("io.ktor:ktor-server-netty:1.6.0")
implementation("io.ktor:ktor-network:1.6.0")
}
Then you can use the sockets, it's still a bit experimental but it's getting there, with newer version ktor-network is now necessary.
Here is the code:
Server:
suspend fun server() {
val server = aSocket(ActorSelectorManager(Executors.newCachedThreadPool().asCoroutineDispatcher())).tcp()
.bind(InetSocketAddress("127.0.0.1", 2323))
println("Server running: ${server.localAddress}")
val socket = server.accept()
println("Socket accepted: ${socket.remoteAddress}")
val input = socket.openReadChannel()
val output = socket.openWriteChannel(autoFlush = true)
val line = input.readUTF8Line()
println("received '$line' from ${socket.remoteAddress}")
output.writeFully("$line back\r\n".toByteArray())
}
Client:
suspend fun client() {
val socket = aSocket(ActorSelectorManager(Dispatchers.IO)).tcp()
.connect(InetSocketAddress("127.0.0.1", 2323))
val input = socket.openReadChannel()
val output = socket.openWriteChannel(autoFlush = true)
output.writeFully("hello\r\n".toByteArray())
println("Server said: '${input.readUTF8Line()}'")
}
Run them both:
fun main() {
CoroutineScope(Dispatchers.Default).launch { server() }
runBlocking { client() }
}
When you run them, the client will send a message, the server will respond and you should see something like this:
Server running: /127.0.0.1:2323
Socket accepted: /127.0.0.1:56215
received 'hello' from /127.0.0.1:56215
Server said: 'hello back'
Find more example on their documentation simple echo server
There are 2 important things based on my experiment:
get permission in AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
create the socket from a background thread, the following works for me:
Executors.newSingleThreadExecutor().execute {
val socket = Socket("192.168.0.15", 50000)
val scanner = Scanner(socket.getInputStream())
val printWriter = PrintWriter(socket.getOutputStream())
while (scanner.hasNextLine()) {
Log.d(TAG, "${ scanner.nextLine() }")
}
}
This is the source code in GitHub.
There is a video of my experiment.

Android NSD - hangs / runs forever - device specific?

I'm attempting to perform service discovery on my company's proprietary hardware device which hosts its own WiFi network and advertises a bonjour service over that network. When I'm connected to that WiFi network, I'm using NSD to discover that service and resolve it.
The code is pretty simple and generally works great and quickly. Except I'm having a fairly recurring issue (~5 out of 10 attempts) so far localized to my Samsung S8+. Cannot reproduce on a S6 or Pixel XL so far.
The issue is that DiscoveryListener never does anything beyond onDiscoveryStarted(), it just runs forever. If I kill the app and start over, sometimes it works sometimes it continues to hang.
It's like there's a blocked thread or something, but there is no useful info in the logs (that I can find) and nothing I have yet found to latch on to as something I can do to recover from this.
I have added a timeout that will stop the listener after 30 seconds, but generally when I retry after that it still doesn't work.
The service discovery process is wrapped in a LiveData, which starts it upon active.
const val SERVICE_TYPE_FOO = "_foo._tcp."
private val serviceDiscoveryListener = ServiceDiscoveryListener()
override fun onActive() {
super.onActive()
stopRunnable = StopDiscoveryRunnable()
nsdManager.discoverServices(
SERVICE_TYPE_FOO,
NsdManager.PROTOCOL_DNS_SD,
serviceDiscoveryListener
)
handler.postDelayed(stopRunnable, SERVICE_DISCOVERY_TIMEOUT_MS)
}
private lateinit var stopRunnable: Runnable
private inner class StopDiscoveryRunnable : Runnable {
override fun run() {
try {
nsdManager.stopServiceDiscovery(serviceDiscoveryListener)
Timber.w("service discovery timed out")
postValue(ServiceDiscoveryState.Error)
} catch (e: Throwable) {
// no-op
}
}
}
The listeners are very simple...
private inner class ServiceDiscoveryListener : NsdManager.DiscoveryListener {
override fun onServiceFound(serviceInfo: NsdServiceInfo?) {
if (serviceInfo != null) {
if (serviceInfo.serviceName.isNotEmpty() &&
serviceInfo.serviceName.containsFoo()
) {
nsdManager.resolveService(serviceInfo, ResolveListener())
handler.removeCallbacks(stopRunnable)
}
}
}
override fun onStopDiscoveryFailed(serviceType: String?, errorCode: Int) {
Timber.d("stop discovery failed")
nsdManager.stopServiceDiscovery(this)
postValue(ServiceDiscoveryState.Error)
}
override fun onStartDiscoveryFailed(serviceType: String?, errorCode: Int) {
Timber.d("start discovery failed")
nsdManager.stopServiceDiscovery(this)
postValue(ServiceDiscoveryState.Error)
}
override fun onDiscoveryStarted(serviceType: String?) {
Timber.d("discovery started")
}
override fun onDiscoveryStopped(serviceType: String?) {
Timber.d("discovery stopped")
}
override fun onServiceLost(serviceInfo: NsdServiceInfo?) {
Timber.d("discovery service lost")
postValue(ServiceDiscoveryState.Error)
}
}
private inner class ResolveListener : NsdManager.ResolveListener {
override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) {
Timber.d("resolve failed. errorCode = $errorCode")
if (errorCode != NsdManager.FAILURE_ALREADY_ACTIVE) {
Timber.d("not already active, so error")
postValue(ServiceDiscoveryState.Error)
} else {
Timber.d("already active")
}
}
override fun onServiceResolved(serviceInfo: NsdServiceInfo?) {
if (serviceInfo != null) {
Timber.d("resolved service: ${serviceInfo.serviceName} host: ${serviceInfo.host}:${serviceInfo.port} type: ${serviceInfo.serviceType}")
postValue(ServiceDiscoveryState.FooService(serviceInfo))
}
}
}
I have not been able to find much of value in the logs, although I did see this one message when things were not working. Attempts to search for answers about this have not been fruitful.
04-26 13:50:14.541 953-1218/? W//system/bin/netd: dnssd_clientstub DNSServiceProcessResult called with invalid DNSServiceRef 0x72bb818000 FFFFFFFF DDDDDDDD
What other information can I provide?
I've reproduced the hang using Andriy Druk's bonjour Service Browser sample code on my S8+, which doesn't even use NSD... so it seems that perhaps the problem is in the core mDNS code and not specific to Google's NSD implementation?
Is there some system software or bloatware on the S8+ that may be interfering with my use of NSD or mDNS - thread blocking or something?

Categories

Resources