The printer uses USB connection and ESC/POS commands, I can send commands with BulkTransfer:
val usbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager
val device: UsbDevice? =
usbManager.deviceList.values.firstOrNull { it.vendorId == vid && it.productId == pid }
if (device != null) {
var textToPrint = text("Prueba")
textToPrint = appendCommands(textToPrint, printAndNLinesFeedForward("6"))
textToPrint = appendCommands(textToPrint, paperCut("0"))
val connection: UsbDeviceConnection = usbManager.openDevice(device)
connection.claimInterface(device.getInterface(0), true)
val con = connection.bulkTransfer(
device.getInterface(0).getEndpoint(0),
textToPrint.toByteArray(),
textToPrint.size,
0
)
println(con)
connection.releaseInterface(device.getInterface(0))
connection.close()
} else {
Log.e("errores", "device=null")
}
textToprint has the commands to send, appendCommands is a function that add commands and returns an array with the added command
private fun appendCommands(byteArray1: UByteArray, byteArray2: UByteArray): UByteArray {
var byteArray = byteArray1
for (byte in byteArray2) {
byteArray += byte
}
return byteArray
}
private fun text(text: String): UByteArray {
val charset = Charsets.UTF_8
return text.toByteArray(charset).toUByteArray()
}
private fun printAndNLinesFeedForward(linesToFeed: String): UByteArray {
return ubyteArrayOf("1B".hexAsUByte, "64".hexAsUByte, linesToFeed.hexAsUByte)
}
private fun paperCut(typeCut: String): UByteArray {
return ubyteArrayOf("1D".hexAsUByte, "56".hexAsUByte, typeCut.hexAsUByte)
}
this those commands in each function have hexadecimal codes provided by the printer manual
However, I don't know how to listen to the printer's response in the event that it doesn't have paper, for example, because the functions that I issue to listen do not return anything or I don't know where to pick it up
private fun receiveData(pid: Int, vid: Int, context: Context) {
val usbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager
val device: UsbDevice? =
usbManager.deviceList.values.firstOrNull { it.vendorId == vid && it.productId == pid }
if (device != null) {
val buffer = byteArrayOf("1D".hexAsByte, "72".hexAsByte, "1".hexAsByte)
val connection: UsbDeviceConnection = usbManager.openDevice(device)
connection.claimInterface(device.getInterface(0), true)
connection.bulkTransfer(
device.getInterface(0).getEndpoint(1),
buffer,
buffer.size,
0
)
connection.releaseInterface(device.getInterface(0))
connection.close()
} else {
Log.e("errores", "device=null")
}
}
here i connect another endpoint, this endpoint is to receive data, and the command in buffer is this:
I dont know how to receive code errors from the printer
Related
I am trying to make an mp4 video recoding, its not working on all android devices and I am getting grayscale recordings on S21 Android OS 12, S22 Green bars
Not sure where I went wrong, Following is all the possible code that could impact
What I am expecting is that it should work on all devices producing colored 1080p mp4 video and no green bars
ImageAnalysis Initilization
val imageAnalysis = ImageAnalysis.Builder()
// enable the following line if RGBA output is needed.
// .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
.setOutputImageRotationEnabled(true)
//.setTargetAspectRatio(quality.getAspectRatio(quality))
.setTargetResolution(fhdResolution)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_BLOCK_PRODUCER)
.build()
imageAnalysis.setAnalyzer(executorService, ImageAnalysis.Analyzer { imageProxy ->
// convert image to bytearray before closing
val bytearray = ImageUtil.imageToNv21ByteArray(imageProxy)
imageProxy.close()
frameMetadata?.let {
val metadata = it
bytearray?.let {
trySend(
FrameWrapper(
it,
imageProxy.imageInfo,
imageProxy.width,
imageProxy.height,
state,
metadata
)
)
}
}
})
imageToNv21ByteArray
fun imageToNv21ByteArray(image: ImageProxy): ByteArray? {
var data: ByteArray? = null
if (image.format == ImageFormat.YUV_420_888) {
data = yuv_420_888toNv21(image) // <=== this seems to be the best one
} else {
Timber.e("Unrecognized image format: %s", image.format)
}
return data
}
yuv_420_888toNv21
private fun yuv_420_888toNv21(image: ImageProxy): ByteArray? {
val yPlane = image.planes[0]
val uPlane = image.planes[1]
val vPlane = image.planes[2]
val yBuffer = yPlane.buffer
val uBuffer = uPlane.buffer
val vBuffer = vPlane.buffer
yBuffer.rewind()
uBuffer.rewind()
vBuffer.rewind()
val ySize = yBuffer.remaining()
var position = 0
// TODO(b/115743986): Pull these bytes from a pool instead of allocating for every image.
val nv21 = ByteArray(ySize + image.width * image.height / 2)
// Add the full y buffer to the array. If rowStride > 1, some padding may be skipped.
for (row in 0 until image.height) {
yBuffer[nv21, position, image.width]
position += image.width
yBuffer.position(
Math.min(ySize, yBuffer.position() - image.width + yPlane.rowStride)
)
}
val chromaHeight = image.height / 2
val chromaWidth = image.width / 2
val vRowStride = vPlane.rowStride
val uRowStride = uPlane.rowStride
val vPixelStride = vPlane.pixelStride
val uPixelStride = uPlane.pixelStride
// Interleave the u and v frames, filling up the rest of the buffer. Use two line buffers to
// perform faster bulk gets from the byte buffers.
val vLineBuffer = ByteArray(vRowStride)
val uLineBuffer = ByteArray(uRowStride)
for (row in 0 until chromaHeight) {
vBuffer[vLineBuffer, 0, Math.min(vRowStride, vBuffer.remaining())]
uBuffer[uLineBuffer, 0, Math.min(uRowStride, uBuffer.remaining())]
var vLineBufferPosition = 0
var uLineBufferPosition = 0
for (col in 0 until chromaWidth) {
nv21[position++] = vLineBuffer[vLineBufferPosition]
nv21[position++] = uLineBuffer[uLineBufferPosition]
vLineBufferPosition += vPixelStride
uLineBufferPosition += uPixelStride
}
}
return nv21
}
Mp4EncoderFrameFlowConsumer
class Mp4EncoderFrameFlowConsumer(var context: Context, callback: (videoStartTime: Long) -> Unit) : OpsisModule {
var recording = false
var pendingStart = false
var encoder: VideoEncoder? = null
var job: Job? = null
var videoStartTime: Long? = null
var callback:((videoStartTime: Long) -> Unit) = callback
override fun start() {
thread(start = true) {
val frameFlow: FrameFlow = FlowManager.getFlow(FlowManager.FlowType.frame) as FrameFlow
runBlocking {
job = CoroutineScope(Job()).launch {
frameFlow.frameFlow().collect {
if (pendingStart) {
val wrapper = it
pendingStart = false
encoder?.let {
it.startEncoding(wrapper.width, wrapper.height)
}
}
if (recording) {
if (videoStartTime == null) {
videoStartTime = it.frameMetadata.timestamp
callback(videoStartTime!!)
}
addFrame(it)
}
}
}
}
}
Timber.d("Done encoder consumer")
}
override fun startRecording() {
recording = true;
Timber.d("Start Recording")
encoder = VideoEncoder()
pendingStart = true
}
override fun stopRecording(startFrame:Long, dir:File, callback: (result: File) -> Unit) {
if (recording) {
recording = false
encoder?.let {
try {
it.stopEncoding() { file ->
// copy file to directory
val newfile = File(dir.absolutePath + "/breeze_video.mp4")
if (file.exists()) {
file.copyTo(newfile)
file.delete()
}
callback(newfile)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
override fun stop() {
Timber.d("STOPPING ENCODER CONSUMER")
job?.let {
it.cancel()
}
}
suspend fun addFrame(wrapper: FrameWrapper) {
// Timber.d("RECORD META ${wrapper.frameMetadata.timestamp} FRAME ${wrapper.info.timestamp}")
encoder?.let {
it.addFrame(wrapper.image)
}
}
}
VideoEncoder
class VideoEncoder() {
var mOutputFile: File? = null
private var mediaCodec: MediaCodec? = null
private var mediaMuxer: MediaMuxer? = null
private var mGenerateIndex = 0
private var mTrackIndex = 0
private var mNoMoreFrames = false
private var mAbort = false
private val _encodingFlow = MutableSharedFlow<ByteArray>(
extraBufferCapacity = 20,
onBufferOverflow = BufferOverflow.DROP_OLDEST
)
init {
mOutputFile = File(Util.getFilePath("opsis_video", ".mp4"))
thread(start = true) {
runBlocking {
CoroutineScope(Job()).launch {
_encodingFlow.collect {
mediaCodec?.let { codec ->
mediaMuxer?.let { muxer ->
try {
val TIMEOUT_USEC: Long = 500000
val inputBufIndex = codec.dequeueInputBuffer(TIMEOUT_USEC)
val ptsUsec =
computePresentationTime(mGenerateIndex.toLong(), FRAME_RATE)
if (inputBufIndex >= 0) {
val inputBuffer: ByteBuffer? =
codec.getInputBuffer(inputBufIndex)
inputBuffer?.let { buffer ->
buffer.clear()
buffer.put(it)
try {
codec.queueInputBuffer(inputBufIndex, 0, it.size, ptsUsec, 0)
} catch (e: Exception) {
e.printStackTrace()
}
mGenerateIndex++
}
}
val mBufferInfo = MediaCodec.BufferInfo()
val encoderStatus =
codec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC)
if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
// no output available yet
Timber.e("No output from encoder available")
} else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// not expected for an encoder
val newFormat = codec.outputFormat
mTrackIndex = muxer.addTrack(newFormat)
muxer.start()
} else if (encoderStatus < 0) {
Timber.e("unexpected result from encoder.dequeueOutputBuffer: $encoderStatus")
} else if (mBufferInfo.size != 0) {
val encodedData: ByteBuffer? =
codec.getOutputBuffer(encoderStatus)
if (encodedData == null) {
Timber.e("encoderOutputBuffer $encoderStatus was null")
} else {
encodedData.position(mBufferInfo.offset)
encodedData.limit(mBufferInfo.offset + mBufferInfo.size)
muxer.writeSampleData(
mTrackIndex,
encodedData,
mBufferInfo
)
codec.releaseOutputBuffer(encoderStatus, false)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
}
}
}
}
fun encodingFlow(): Flow<ByteArray> {
return _encodingFlow
}
val isEncodingStarted: Boolean
get() = mediaCodec != null && mediaMuxer != null && !mNoMoreFrames && !mAbort
fun startEncoding(width: Int, height: Int) {
mWidth = width
mHeight = height
val outputFile = mOutputFile!!
val outputFileString: String
outputFileString = try {
outputFile.getCanonicalPath()
} catch (e: IOException) {
Timber.e("Unable to get path for $outputFile")
return
}
val codecInfo = selectCodec(MIME_TYPE)
if (codecInfo == null) {
Timber.e("Unable to find an appropriate codec for " + MIME_TYPE)
return
}
Timber.d("found codec: " + codecInfo.name)
mediaCodec = try {
MediaCodec.createByCodecName(codecInfo.name)
} catch (e: IOException) {
Timber.e("Unable to create MediaCodec " + e.message)
return
}
val mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight)
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE)
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE)
mediaFormat.setInteger(
MediaFormat.KEY_COLOR_FORMAT,
CodecCapabilities.COLOR_FormatYUV420Flexible
)
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, I_FRAME_INTERVAL)
mediaCodec?.let { codec ->
codec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
codec.start()
mediaMuxer = try {
MediaMuxer(outputFileString, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
} catch (e: IOException) {
Timber.e("MediaMuxer creation failed. " + e.message)
return
}
Timber.d("Initialization complete. Starting encoder...")
}
}
suspend fun addFrame(frame: ByteArray) {
_encodingFlow.emit(frame)
}
fun stopEncoding(callback: (result: File) -> Unit) {
release()
callback(mOutputFile!!)
}
private fun release() {
mediaCodec?.let {
try {
it.stop()
it.release()
} catch (e: Exception) {
e.printStackTrace()
}
mediaCodec = null
}
mediaMuxer?.let {
try {
it.stop()
it.release()
} catch (e: Exception) {
e.printStackTrace()
}
mediaMuxer = null
}
}
// from google:
// https://android.googlesource.com/platform/cts/+/jb-mr2-release/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java#1128
private fun computePresentationTime(frameIndex: Long, framerate: Int): Long {
return 132 + frameIndex * 1000000 / framerate
}
companion object {
private const val MIME_TYPE = "video/avc" // H.264 Advanced Video Coding
private var mWidth = 0
private var mHeight = 0
private const val BIT_RATE = 16000000
private const val FRAME_RATE = 30 // Frames per second
private const val I_FRAME_INTERVAL = 1
private fun selectCodec(mimeType: String): MediaCodecInfo? {
val numCodecs = MediaCodecList.getCodecCount()
for (i in 0 until numCodecs) {
val codecInfo = MediaCodecList.getCodecInfoAt(i)
if (!codecInfo.isEncoder) {
continue
}
val types = codecInfo.supportedTypes
for (j in types.indices) {
if (types[j].equals(mimeType, ignoreCase = true)) {
return codecInfo
}
}
}
return null
}
}
}
My NetSelector class:
class NetSelector(
private var selector: Selector,
private val emptySelectThreshold: Int
) : NetSelector {
private var keyIterator: MutableIterator<SelectionKey> = emptyKeyIterator
private var lastEmptySelectTime: Long = 0L
private var emptySelectCount: Int = 0
private var isClose = false
override fun next(): SelectionKey {
if (keyIterator.hasNext()) {
val next = keyIterator.next()
keyIterator.remove()
println("next>>>>>>>> $next")
return next
}
var selectCount = selector.select()
println("selectCount>>>>>>>>> $selectCount")
while (selectCount == 0) {
val now = epochMillis()
if (now == lastEmptySelectTime) {
emptySelectCount++
if (emptySelectCount >= emptySelectThreshold) {
//High CPU if select count is always 0
emptySelectCount = 0
rebuildSelector()
return next()
} else {
selectCount = selector.select()
}
} else {
lastEmptySelectTime = now
emptySelectCount = 0
selectCount = selector.select()
}
}
val selectedKeys = selector.selectedKeys()
keyIterator = selectedKeys.iterator()
return next()
}
private fun rebuildSelector() {
val newSelector = Selector.open()
for (key in selector.keys()) {
if (!key.isValid || key.interestOps() == 0) {
continue
}
key.cancel()
val channel = key.channel()
val attachment = key.attachment()
channel.register(newSelector, key.interestOps(), attachment)
selector.selectNow()
}
synchronized(this) {
selector.close()
selector = newSelector
if (isClose) {
newSelector.close()
}
}
}
override fun close() {
synchronized(this) {
selector.close()
isClose = true
}
}
companion object {
private val emptyKeyIterator: MutableIterator<SelectionKey> = object : MutableIterator<SelectionKey> {
override fun hasNext(): Boolean = false
override fun next(): SelectionKey = throw NoSuchElementException("This iterator is empty!")
override fun remove() = throw IllegalStateException("This iterator is empty!")
}
}
}
It returns same SelectionKey when I use next() method:
selectCount>>>>>>>>> 1
next>>>>>>>> sun.nio.ch.SelectionKeyImpl#30beb8f5
selectCount>>>>>>>>> 1
next>>>>>>>> sun.nio.ch.SelectionKeyImpl#30beb8f5
Where is the mistake?
I'm really new in Kotlin.
I have two application one is Client in Android emulator and one is in Windows Form Application Server (My server is Using SimpleTCP library in C#) .
Here is the Server Code:
private void Form1_Load(object sender, EventArgs e)
{
server = new SimpleTcpServer();
server.Delimiter = 0x13;
server.StringEncoder = Encoding.UTF8;
server.DataReceived += Server_DataReceived;
messageList.Text += "Server starting...";
server.Start("192.168.1.7", 5000);
messageList.Text += "\r\n Server started...";
}
private void Server_DataReceived(object sender, SimpleTCP.Message e)
{
messageList.Invoke((MethodInvoker)delegate ()
{
messageList.Text += string.Format("\r\n Client Message: {0} \n ", e.MessageString);
});
e.ReplyLine("Hello from Server");
}
I'm communicating via localhost. I can send request and Server can get this request without problem but when i try to get response from Server unfortunately cannot receive response.
val message = input!!.readLine() is always returning null
Can you help me why i cannot do this?
Here my code
var thread: Thread? = null
var etIP: EditText? = null
var etPort: EditText? = null
var tvMessages: TextView? = null
var etMessage: EditText? = null
var btnSend: Button? = null
var SERVER_IP: String? = null
var SERVER_PORT = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
etIP = findViewById(R.id.etIP)
etPort = findViewById(R.id.etPort)
tvMessages = findViewById(R.id.tvMessages)
etMessage = findViewById(R.id.etMessage)
btnSend = findViewById(R.id.btnSend)
val btnConnect: Button = findViewById(R.id.btnConnect)
btnConnect.setOnClickListener {
tvMessages!!.text = ""
SERVER_IP = etIP!!.text.toString().trim { it <= ' ' }
SERVER_PORT = etPort!!.text.toString().trim { it <= ' ' }.toInt()
thread = Thread(Thread1())
thread!!.start()
}
btnSend!!.setOnClickListener {
val message = "Android!"+etMessage!!.text.toString().trim { it <= ' ' }
if (!message.isEmpty()) {
Thread(Thread3(message)).start()
}
}
}
private var output: PrintWriter? = null
private var input: BufferedReader? = null
internal inner class Thread1 : Runnable {
override fun run() {
val socket: Socket
try {
socket = Socket(SERVER_IP, SERVER_PORT)
output = PrintWriter(socket.getOutputStream())
input = BufferedReader(InputStreamReader(socket.getInputStream()))
runOnUiThread(Runnable { tvMessages!!.text = "Connected\n" })
Thread(Thread2()).start()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
internal inner class Thread2 : Runnable {
override fun run() {
while (true) {
try {
val message = input!!.readLine().toString()
run {
runOnUiThread(Runnable { tvMessages!!.append("server: $message\n") })
}
run {
thread = Thread(Thread1())
thread!!.start()
return
}
} catch (e: Exception) {
tvMessages!!.text = e.toString()
}
}
}
}
internal inner class Thread3(private val message: String) : Runnable {
override fun run() {
output!!.write(message)
output!!.flush()
runOnUiThread(Runnable {
tvMessages!!.append("client: $message\n")
tvMessages!!.setMovementMethod(ScrollingMovementMethod())
etMessage!!.setText("")
})
}
}
fun clearAll(view: View){
tvMessages!!.text = ""
}
My device has two ports USB, on one I have connected and read the name (this is GPS) and on the second port I connected a USB storage device and I want to read a file which is on it. Only on one of the device's storage I cannot perform a read like this:
Map<String, File> externalLocations = ExternalStorage.getAllStorageLocations();
File externalSdCard = externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD);
if (externalSdCard != null && externalSdCard.exists() && externalSdCard.listFiles() != null) {
for (File f : externalSdCard.listFiles()) {
if ("key.xml".equalsIgnoreCase(f.getName())) {
String path = f.getPath().replace(".xml", "_DUMP.xml");
File file11 = new File(path);
if (!file11.exists()) {
moveFile(file11, f);
}
return f;
}
}
}
And I think I should do this to read a file :
UsbManager usbManager = ((UsbManager)(GetSystemService(Context.UsbService)));
var deviceList = usbManager.DeviceList;
IEnumerable<UsbDevice> deviceIterator = deviceList.Values.AsEnumerable();
if ((deviceIterator.Count() > 0)) {
UsbDevice device = deviceIterator.ElementAt(0);
usbManager.RequestPermission(device, mPermissionIntent);
if (usbManager.HasPermission(device)) {
if (usbManager.HasPermission(device)) {
System.Diagnostics.Debug.WriteLine("HasPermission");
UsbDeviceConnection connection = usbManager.OpenDevice(device);
if ((connection != null)) {
System.Diagnostics.Debug.WriteLine(" connection is not null");
var model = device.DeviceName;
string inline = null;
BufferedReader reader = null;
reader = new BufferedReader(new FileReader("/mnt/media_rw/C227-875D/test/hello.txt"));
System.Diagnostics.Debug.WriteLine("no exception occured");
while ((reader.ReadLine() != null)) {
System.Diagnostics.Debug.WriteLine(inlne);
}
}
}
But can I have open two ports at the same time?
I want to push notification from my server.for that i am using web push API for java , i am able to send the notification to endpoint url but on receiver side my service worker not executing push event,As I am using VAPID so no need to use gcm Id as per my understanding,here you are my service worker file.
'use strict';
const applicationServerPublicKey = 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-
SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U';
function urlB64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
self.addEventListener('install', function(event){
event.waitUntil(self.skipWaiting());
console.log("activate");
});
self.addEventListener('activate', function(event){
event.waitUntil(self.clients.claim());
console.log("install");
});
self.addEventListener('push', function(event) {
console.log('Received push');
let notificationTitle = 'Hello';
const notificationOptions = {
body: 'Thanks for sending this push msg.',
icon: '/JMS/resources/images/icon.png',
badge: '/JMS/resources/images/badge.png',
tag: 'simple-push-demo-notification',
data: {
url: 'https://developers.google.com/web/fundamentals/getting-
started/push-notifications/',
},
};
if (event.data) {
const dataText = event.data.text();
notificationTitle = 'Received Payload';
notificationOptions.body = `Push data: '${dataText}'`;
}
event.waitUntil(
Promise.all([
self.registration.showNotification(
notificationTitle, notificationOptions),
])
);
});
self.addEventListener('notificationclick', function(event) {
event.notification.close();
event.waitUntil(
clients.openWindow('https://www.auctiontiger.net')
);
let clickResponsePromise = Promise.resolve();
if (event.notification.data && event.notification.data.url) {
clickResponsePromise = clients.openWindow(event.notification.data.url);
}
event.waitUntil(
Promise.all([
clickResponsePromise
])
);
});
here you are my main.js file from where i am able to call to my local server.
'use strict';
const applicationServerPublicKey = 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-
SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U';
const pushButton = document.querySelector('.js-push-btn');
let isSubscribed = false;
let swRegistration = null;
function urlB64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function updateBtn() {
if (Notification.permission === 'denied') {
pushButton.textContent = 'Push Messaging Blocked.';
pushButton.disabled = true;
updateSubscriptionOnServer(null);
return;
}
if (isSubscribed) {
pushButton.textContent = 'Disable Push Messaging';
} else {
pushButton.textContent = 'Enable Push Messaging';
}
pushButton.disabled = false;
}
function updateSubscriptionOnServer(subscription) {
// TODO: Send subscription to application server
const subscriptionJson = document.querySelector('.js-subscription-json');
const subscriptionDetails =
document.querySelector('.js-subscription-details');
if (subscription) {
subscriptionJson.textContent = JSON.stringify(subscription);
subscriptionDetails.classList.remove('is-invisible');
} else {
subscriptionDetails.classList.add('is-invisible');
}
}
function subscribeUser() {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey:applicationServerKey
})
.then(function(subscription) {
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
initialiseUI();
return sendSubscriptionToServer(subscription);
})
.catch(function(err) {
console.log('Failed to subscribe the user: ', err);
});
}
function sendSubscriptionToServer(subscription) {
var key = subscription.getKey ? subscription.getKey('p256dh') : '';
var auth = subscription.getKey ? subscription.getKey('auth') : '';
return fetch('/JMS/profile/subscription', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
endpoint: subscription.endpoint,
// Take byte[] and turn it into a base64 encoded string suitable for
// POSTing to a server over HTTP
key:key ? btoa(String.fromCharCode.apply(null, new Uint8Array(key)))
: '',
auth:auth ? btoa(String.fromCharCode.apply(null, new
Uint8Array(auth))) : ''
})
});
}
function unsubscribeUser() {
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
return subscription.unsubscribe();
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
})
.then(function() {
updateSubscriptionOnServer(null);
console.log('User is unsubscribed.');
isSubscribed = false;
updateBtn();
});
}
function initialiseUI() {
pushButton.addEventListener('click', function() {
pushButton.disabled = true;
if (isSubscribed) {
unsubscribeUser();
} else {
subscribeUser();
}
});
// Set the initial subscription value
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
isSubscribed = !(subscription === null);
updateSubscriptionOnServer(subscription);
if (isSubscribed) {
console.log('User IS subscribed.');
} else {
console.log('User is NOT subscribed.');
}
updateBtn();
});
}
if ('serviceWorker' in navigator && 'PushManager' in window) {
console.log('Service Worker and Push is supported');
navigator.serviceWorker.register('sw.js')
.then(function(swReg) {
console.log('Service Worker is registered', swReg.scope);
swReg.update();
swRegistration = swReg;
initialiseUI();
})
.catch(function(error) {
console.error('Service Worker Error', error);
});
} else {
console.warn('Push messaging is not supported');
pushButton.textContent = 'Push Not Supported';
}
here is the URL for webpush API that i have used for my application,
[https://github.com/web-push-libs/webpush-java][1]
finally my server side code,
#RequestMapping(value = "profile/subscription", method = RequestMethod.POST,
headers = "Content-Type=application/json")
#ResponseBody
public String post(#RequestBody String body,byte[]
payload,HttpServletResponse response)
throws GeneralSecurityException, IOException, JoseException,
ExecutionException, InterruptedException, ParseException, JSONException
{
String data="";
org.json.JSONObject ob = new org.json.JSONObject(body);
final int TTL = 255;
payload= "hello".getBytes();
com.demo.controller.PushService pushService = new
com.demo.controller.PushService();
nl.martijndwars.webpush.Notification notification =new
nl.martijndwars.webpush.Notification(ob.getString("endpoint")
,new Subscription().getUserPublicKey((ob.getString("key"))),
Base64.decode(ob.getString("auth")),
payload,TTL);
pushService.send(notification);
org.json.JSONObject ob2 = new org.json.JSONObject(body);
ob2.put("data", notification.getPayload());
JSONArray arr= new JSONArray();
arr.add(ob2);
data=arr.toJSONString();
response.setHeader("Service-Worker-Allowed", "/");
return data;
}
actually I am fetching this from client browser and on server-side sending notification on the endpoint, and i am able to send the notification but my
service worker is not able to fire push event so i am not getting notification on my browser.
{
auth:"hcQQq+1FeDuSu7V0zd5DXA=="
endpoint:"https://fcm.googleapis.com/fcm/send/
cXgp0l3svNo:APA91bG8dDfZhrc0iaSyzvuV1BvnxXz9T-
SmLCKOymKrEdwvrh0_SjzjnU3ORRKvW5QD-
Zp196T5nAGPayR7EKu_Bkb0pQrSex7Q3DZSu54Lo83AEiUE6p-2Xn-nrquCymKVFt6Z4nY8"
key:"BJv2qC3WSCsRszMi57vOBpFjnIpdJ/
uXQQFj4d0XZD9lRuZKuBgJNVFra0SFEvRlQQ88eG8RWWs7sSvO9Pbdkwk="
}
Please help me to get out of this, any help would be greatly appreciated.Thank you in advance.
The issue might be due to some firewall blocking you from receiving the push notification. This was the case with me.