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 = ""
}
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
}
}
}
Hello guys I'm using NotificationListenerService to get WhatsApp messages
But now I have a problem that I don't know how to replay to WhatsApp notifications
So here is the code and how I'm getting WhatsApp notifications but my problem is in how actually to replay on them
public class NotificationListener extends NotificationListenerService {
// StaticFields:
public static final String WHATSAPP_PACKAGE_NAME = "com.whatsapp";
// TAGS:
private static final String TAG = "NotificationListener";
private static final String NP_FIELD = "onNotificationPosted: ";
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
super.onNotificationPosted(sbn);
// Fields:
ARPreferencesManager manager = new ARPreferencesManager(getApplicationContext());
String currentPackages = manager.getStringPreferences(ARPreferencesManager.PACKAGE_APP_NAME);
List<Chat.Messages> messages = new ArrayList<>();
// CheckingStatusBarNotification:
if (sbn.getPackageName().equals(WHATSAPP_PACKAGE_NAME)) {
// Initializing(DateTime):
String date = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(new Date());
List<Chat> chats;
// Initializing(Data):
String sender = sbn.getNotification().extras.getString(Notification.EXTRA_TITLE);
String msg = sbn.getNotification().extras.getString(Notification.EXTRA_TEXT);
String currentSenders = manager.getStringPreferences(ARPreferencesManager.SENDER_NAME);
// AddingData:
messages.add(new Chat.Messages(msg));
// Developing:
if (manager.getPreferences().contains(ARPreferencesManager.WHATSAPP_CHATS)) {
// Initializing:
chats = ARUtils.fromJsonToChats(manager.getStringPreferences(ARPreferencesManager.WHATSAPP_CHATS));
// Developing:
for (Chat chat : chats) {
if (chat.getSender().equals(sender)) {
// AddingTheNewMessage:
chat.getMessages().addAll(messages);
// AddingSender($Preferences):
if (!currentSenders.contains(sender)) {
// Initializing:
manager.setStringPreferences(ARPreferencesManager.SENDER_NAME, sender + ",");
// Refreshing:
currentSenders = manager.getStringPreferences(ARPreferencesManager.SENDER_NAME);
}
}
}
// CheckingSenders:
if (!currentSenders.contains(sender)) {
// Initializing:
Chat chat = new Chat(sender, "", date, null, messages);
// AddingTheNewChat:
chats.add(chat);
}
} else {
// Initializing:
chats = new ArrayList<>();
// Developing:
chats.add(new Chat(sender, "", date, null, messages));
}
// SettingPreferences:
manager.setStringPreferences(ARPreferencesManager.WHATSAPP_CHATS, ARUtils.fromChatsToJson(chats));
// Debugging:
ARUtils.debug(TAG, NP_FIELD, manager.getStringPreferences(ARPreferencesManager.WHATSAPP_CHATS));
}
// Debugging:
ARUtils.debug(TAG, NP_FIELD, "Whatsapp Package Was Founded In Preferences");
// Debugging:
ARUtils.debug(TAG, NP_FIELD, "Start");
}
}
Did you try using this function?
fun reply(action: Notification.Action, message: String, exception: Exception.() -> Unit = {}) {
try {
val sendIntent = Intent()
val msg = Bundle()
for (inputable in action.remoteInputs) {
msg.putCharSequence(inputable.resultKey, message)
}
RemoteInput.addResultsToIntent(action.remoteInputs, sendIntent, msg)
action.actionIntent.send(applicationContext, 0, sendIntent)
} catch (exception: Exception) {
exception(exception)
}
}
You can get Notification.Action for this way:
override fun onNotificationPosted(sbn: StatusBarNotification) {
super.onNotificationPosted(sbn)
val wExt = Notification.WearableExtender(sbn.notification)
for (action in wExt.actions) {
...
i've got problem getting data from Node server, i've searching many reference from internet, but i haven't found one yet that can solve my problem.
this is my node server
var socket = require('socket.io');
var express = require('express');
var app = express();
/*
var options = {
key: fs.readFileSync('cert/file.key'),
cert: fs.readFileSync('cert/file.crt')
};
var server = require('https').createServer(options, app);
*/
var server = require('http').createServer(app);
var io = socket.listen( server );
var port = process.env.PORT || 3000;
//server.listen(port, '103.126.57.4', function () {
server.listen(port, function () {
console.log('Server listening at port %d', port);
//console.log('Server listening at port %d', port, server.address());
});
io.on('connection', function (socket) {
console.log( "New client connected !" );
//console.log(socket.handshake.headers.host);
socket.on( 'new_message', function( data ) {
io.sockets.emit( 'new_message', {
idleveluser: data.idleveluser,
nama: data.nama,
level: data.level,
idchat: data.idchat,
pesan: data.pesan,
file: data.file,
reply: data.reply,
created_at: data.created_at
});
});
socket.on( 'new_chat_kelas', function( data ) {
io.sockets.emit( data.tabelchat, {
idleveluser: data.idleveluser,
nama: data.nama,
level: data.level,
idchat: data.idchat,
pesan: data.pesan,
file: data.file,
reply: data.reply,
created_at: data.created_at
});
});
socket.on( 'change_chat_status', function( data ) {
io.sockets.emit( 'change_status'+data.tabelchat, {
status: data.status
});
});
/*
socket.on('disconnect', function () {
console.log( "Client disconnected !" );
});
*/});
And this is my Android code
try {
//if you are using a phone device you should connect to same local network as your laptop and disable your pubic firewall as well
socket = IO.socket("http://192.168.100.13:3000");
socket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
refreshChat(url);
getTabelKelas();
getDiskusiChat(sharedDiskusi.getSpdiskusi());
private void getDiskusiChat(String tabelChat) {
socket.on(tabelChat, new Emitter.Listener() {
#Override
public void call(final Object... args) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
String jsonStr = data.toString();
Log.d("cek", "cek data : "+data);
Toast.makeText(mContext, (CharSequence) data, Toast.LENGTH_LONG).show();
try {
//extract data from fired event
String cek = String.valueOf(data.getJSONArray("idleveluser"));
// String nickname = data.getString("senderNickname");
// String message = data.getString("message");
// make instance of message
//
// Message m = new Message(nickname,message);
// Message m = new Message(nickname,message);
//
//
// //add the message to the messageList
//
// MessageList.add(m);
//
// // add the new updated list to the dapter
// chatBoxAdapter = new ChatBoxAdapter(MessageList);
//
// // notify the adapter to update the recycler view
//
// chatBoxAdapter.notifyDataSetChanged();
//
// //set the adapter for the recycler view
//
// myRecylerView.setAdapter(chatBoxAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
i have try to Toast and log it but did not appear.
Can anyone help me to retrieve data ?I confuse how to get data if the data in the form of an array. I'm helped if someone helps me.
Sry for my bad english brother.
This is my log
Change this code line
String cek = String.valueOf(data.getJSONArray("idleveluser"));
to
String cek = String.valueOf(data.getString("idleveluser"));
as each item in the data object is a string.
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.
I currently have a java backend running on my server and I have come across a script to communicate from Java to Node.js. I am wondering how I can modify the script to allow more then one message at a time, and if possible, use it in reverse to communicate back to Java.
Here is the code:
Java Side:
package com.timetablr.backend.nodecommunicator;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class NodeCommunicator {
public static void main(String[] args) {
try {
Socket nodejs = new Socket("localhost", 8080);
sendMessage(nodejs, "testnamespace");
Thread.sleep(100);
int x = 0;
while (true)
{
sendMessage(nodejs, x + "");
x++;
Thread.sleep(1000);
System.out.println(x + " has been sent to server");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void sendMessage(Socket s, String message) throws IOException {
s.getOutputStream().write(message.getBytes("UTF-8"));
s.getOutputStream().flush();
}
public static String readMessage(Socket s) throws IOException {
InputStream is = s.getInputStream();
int curr = -1;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((curr = is.read()) != -1) {
if (curr == '\n') {
break;
}
baos.write(curr);
}
return baos.toString("UTF-8");
}
}
Node.js Side:
var javaPort = 8080;
var sIOPort = 8081;
var javaServer = require('net').createServer();
var browserServer = require('socket.io').listen(sIOPort);
console.log('=====================================================');
console.log('JamesS237 Timetablr Node.js/Java Communication Module');
console.log('=====================================================');
console.log('Socket.IO version: ' + require('socket.io').version);
javaServer.on('listening', function () {
console.log('Server is listening on ' + javaPort);
});
javaServer.on('error', function (e) {
console.log('Server error: ' + e.code);
});
javaServer.on('close', function () {
console.log('Server closed');
});
javaServer.on('connection', function (javaSocket) {
var clientAddress = javaSocket.address().address + ':' + javaSocket.address().port;
console.log('Java ' + clientAddress + ' connected');
var firstDataListenner = function (data) {
console.log('Received namespace from java: ' + data);
console.log(data);
javaSocket.removeListener('data', firstDataListenner);
createNamespace(data, javaSocket);
}
javaSocket.on('data', firstDataListenner);
javaSocket.on('close', function() {
console.log('Java ' + clientAddress + ' disconnected');
});
});
javaServer.listen(javaPort);
function createNamespace(namespaceName, javaSocket) {
var browserConnectionListenner = function (browserSocket) {
console.log('Browser Connected');
var javaSocketDataListenner = function(data) {
console.log('Data received from java socket and sent to browser: ' + data);
browserSocket.emit('m', data + '\r\n');
}
var javaSocketClosedListenner = function() {
console.log('The java socket that was providing data has been closed, removing namespace');
browserSocket.disconnect();
browserServer.of('/' + namespaceName).removeListener('connection', browserConnectionListenner);
javaSocket.removeListener('data', javaSocketDataListenner);
javaSocket.removeListener('close', javaSocketClosedListenner);
}
javaSocket.on('close', javaSocketClosedListenner);
javaSocket.on('data', javaSocketDataListenner);
browserSocket.on('disconnect', function () {
console.log('Browser Disconnected');
javaSocket.removeListener('data', javaSocketDataListenner);
javaSocket.removeListener('close', javaSocketClosedListenner);
});
}
var namespace = browserServer.of('/' + namespaceName).on('connection', browserConnectionListenner);
}
Thanks in advance, this is a tricky one