I am sending a notification message from my localhost server like this:
Javascript:
function send_notification(empno,charge,op){
return $.ajax({
url: '/notification_server/firebase_server.php',
type: 'POST',
data:{
"employee": empno,
"body":op
},
cache: false
})
}
(async() => {
await send_notification("Hi Leo","This is a test notification");
})();
PHP:
<?php
require __DIR__.'/vendor/autoload.php';
use Kreait\Firebase\Factory;
use Kreait\Firebase\Messaging\CloudMessage;
$factory = (new Factory)
->withServiceAccount('admin.json')
->withDatabaseUri("https://nfr-qtr-electric-billing-default-rtdb.firebaseio.com");
$deviceToken = '.....'; //I have my actual device token here
$messaging = $factory->createMessaging();
$message = CloudMessage::withTarget('token', $deviceToken)
->withNotification(['title' => $_POST["employee"], 'body' => $_POST["body"]]);
$messaging->send($message);
?>
I am reading the notification like this in my android:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onNewToken(#NonNull String token) {
super.onNewToken(token);
}
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
String notificationTitle = null, notificationBody = null;
if (remoteMessage.getNotification() != null) {
notificationTitle = remoteMessage.getNotification().getTitle();
notificationBody = remoteMessage.getNotification().getBody();
sendLocalNotification(notificationTitle, notificationBody);
}
}
private void sendLocalNotification(String notificationTitle, String notificationBody) {
Intent intent = new Intent(this, record_viewer.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setAutoCancel(true) //Automatically delete the notification
.setSmallIcon(R.mipmap.ic_launcher) //Notification icon
.setContentIntent(pendingIntent)
.setContentTitle(notificationTitle)
.setContentText(notificationBody)
.setSound(defaultSoundUri);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1234, notificationBuilder.build());
}
}
Upon executing the code, I don't receive any notifications. In the network console, it shows that the AJAX request has been sent and there are no errors in my php server code. I tried logging the notificationTitle and the notificationBody in my FirebaseMessagingService, but it too doesn't show anything. Am I doing anything wrong? Why am I not receiving notification? Please help me.
Based on your payload, you're sending data message with employee and body fields.
However, your message handling implementation uses getNotification() which is for notification messages. It won't return any value for notificationTitle and notificationBody since there's no title and body fields set in the payload.
You should use getData() instead. It should look something like this:
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
if (true) {
scheduleJob();
} else {
handleNow();
}
}
Related
I am trying to load a web url in my app which is a login page. On entering the details and after authentication it is supposed to return a token . I have used EvaluateJavascript property in HybridWebView . This is working completely fine in iOS , whereas in Android , after the login process it throws 404 error suddenly for the past few days. All the code is same except for the renderers.I do not have a custom control instead have created the ContentViews for hybridwebview as it is prism Template.
Does anyone know/have any solution for this?
Android HybridWebViewRenderer.cs file
public class HybridWebViewRenderer : WebViewRenderer //ViewRenderer<HybridWebView, Android.Webkit.WebView>
{
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
var webView = e.NewElement as HybridWebView;
if (webView != null)
{
webView.EvaluateJavascript = async (js) =>
{
var reset = new ManualResetEvent(false);
var response = string.Empty;
Device.BeginInvokeOnMainThread(() =>
{
Control?.EvaluateJavascript(js, new JavascriptCallback((r) => { response = r; reset.Set(); }));
});
await Task.Run(() => { reset.WaitOne(); });
return response;
};
}
}
}
internal class JavascriptCallback : Java.Lang.Object, IValueCallback
{
public JavascriptCallback(Action<string> callback)
{
_callback = callback;
}
private Action<string> _callback;
public void OnReceiveValue(Java.Lang.Object value)
{
_callback?.Invoke(Convert.ToString(value));
}
}
In VM :
I have declared EvaluateJavascript
String innerHtml = await EvaluateJavascript("document.body.innerHTML");
HybridWebView Content View :
public static readonly BindableProperty EvaluateJavascriptProperty =
BindableProperty.Create(nameof(EvaluateJavascript),
typeof(Func<string, Task<string>>),
typeof(HybridWebView),
null,
BindingMode.OneWayToSource);
public Func<string, Task<string>> EvaluateJavascript
{
get { return (Func<string, Task<string>>)GetValue(EvaluateJavascriptProperty); }
set { SetValue(EvaluateJavascriptProperty, value); }
}
From a Javascript function I want to get the device token.
I come from Javascript and PHP and I need to do it this way. I'm newbie to kotlin.
This is my project, where is the problem?
MainActivity.kt ### I'ts Works
class MainActivity : AppCompatActivity() {
private lateinit var webVisor: WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ejecutarWebView() // Ejecuta mi WebView
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w(TAG, "Fetching FCM registration token failed", task.exception)
return#OnCompleteListener
}
// Obtenga un nuevo token de registro de Firebase Cloud Messaging (FCM)
val token = task.result
// MOSTRAR LOG Y TOAST
//val msg = getString(R.string.msg_token_fmt, token)
val msg = "TOKEN>$token"
Log.d(TAG, msg)
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
})
}
fun ejecutarWebView (){
webVisor = findViewById(R.id.webView)
webVisor.setWebViewClient(WebViewClient())
//webVisor.webViewClient = WebViewClient()
//webVisor.settings.javaScriptEnabled = true // Javascript habilitado
webVisor.getSettings().setJavaScriptEnabled(true)
//webVisor.getSettings().setAllowFileAccess(true); // Permiso en TRUE para accedera archivos locales
webVisor.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
webVisor.loadUrl("http://server20host-net.com/app.php")
webVisor.addJavascriptInterface(WebAppInterface(this), "Android")
webVisor.setWebViewClient(object : WebViewClient() {
#Deprecated("Deprecated in Java")
public override fun onReceivedError(
view: WebView,
errorCode: Int,
description: String,
failingUrl: String
) {
webVisor.loadUrl("file:///android_asset/error.html")
}
})
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && webVisor.canGoBack()) {
webVisor.goBack()
return true
}
return super.onKeyDown(keyCode, event)
}
MyFirebaseMessagingService.kt ### I'ts Works
#SuppressLint("MissingFirebaseInstanceTokenRefresh")
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
Log.d(ContentValues.TAG, "Kotlin Refreshed token: $token")
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// FCM registration token to your app server.
sendRegistrationToServer(token)
}
private fun sendRegistrationToServer(token: String) {
val urlServer ="http://server20host-net.com/registrarToken.php"
val stringRequest: StringRequest = object : StringRequest(Request.Method.POST, urlServer,
Response.Listener<String> {
fun onResponse(response: String?) {
val men = "REGISTRED SUCCEFULL"
Log.d(ContentValues.TAG, men)
Toast.makeText(baseContext, men, Toast.LENGTH_LONG).show()
}
}, Response.ErrorListener {
fun onErrorResponse(error: VolleyError?) {
Toast.makeText(
getApplicationContext(),
"Error en la Conexión",
Toast.LENGTH_LONG
).show()
}
}) {
#Throws(AuthFailureError::class)
override fun getParams(): Map<String, String> {
val params = HashMap<String, String>()
params.put("Token", token)
return params
}
}
Log.d(ContentValues.TAG, "REGISTRED SUCCEFULL")
val requestQueue: RequestQueue = Volley.newRequestQueue(this)
requestQueue.add(stringRequest)
}
}
WebAppInterface.kt
Here many errors || I have many doubts about how I call the token variable
class WebAppInterface(private val mContext: Context) {
private lateinit var webVisor: WebView
/** Show a toast from the web page */
#JavascriptInterface
fun showToast() {
webVisor.setWebViewClient(WebViewClient())
webVisor.webViewClient = WebViewClient()
lateinit var webVisor: WebView
webVisor.post( Runnable() {
run() {
//NOTE: $token var from MainActivity.kt call
// or WebAppInterface.kt how? I don't know what to do
// Error in all three cases
webVisor.evaluateJavascript("javascript: sendToken($token);",null)
webVisor.loadUrl("javascript: sendToken($token);");
webVisor.loadUrl("javascript:(function sendToken(tokenDevice) { console.log('token from Kotlin>'+$tokenDevice); }")
}
});
}
script.js
the script is jquery functions (or does it have to be vanilla javascript?)
$(document).on("click",".button", function(evt) { // LISTERNER FOR BUTTON
evt.preventDefault();
getToken();
});
function getToken() { // CALL TO KOTLIN FUNCTION FOR GET TOKEN DEVICE
Android.showToast();
}
function sendToken(tokenDevice) { // RECIVED FROM KOTLIN
console.log("token from Kotlin>"+tokenDevice);
}
I am new in RSocket world.
Can you tell me how to send message from server to specific observer in javascript(Angular) application. I am creating multiplayer pacman game where i have to send monster position from a server to a client. I want to do this in other place then controller. I know how to do this in spring to spring application because we can use RsocketRequester.route() to send message to specific endpoint on client side but i dont know how to create something like that in js environment. To be more precise I want to do the same thing like in websocket ( + STOMP). This is example:
Here i have exact endpoint. I can send there message using SimpleMessagingTemplate( in every place) but how to do something similar in rsocket?
Client side:
const ws = new SockJS(this.serverUrl);
this.stompClient = Stomp.over(ws);
this.state = new BehaviorSubject<SocketClientState>(SocketClientState.ATTEMPTING);
this.stompClient.connect({}, (frame) => {
this.stompClient.subscribe('/pacman/update/monster', (monster) => {
if (monster.body) {
this.monsterToUpdate.next(JSON.parse(monster.body));
}
});
// other code ...
this.state.next(SocketClientState.CONNECTED);
}, (error) => {
this.state.next(SocketClientState.ERROR);
});
In RSocket (js) request looks like this and we can for example subscribe response from server easy only if we handle request in controller.(controller know where to send response)
socket.requestStream({
data: {
'author': 'linustorvalds'
},
metadata: String.fromCharCode('tweets'.length) + 'tweets',
}).subscribe({
onComplete: () => console.log('complete'),
onError: error => {
console.log(error);
},
onNext: payload => {
console.log(payload.data);
},
onSubscribe: subscription => {
console.error('Subskrybuje')
subscription.request(2147483647);
},
});
Server
#Service
public class GameObjectSender implements ISender {
private final SimpMessagingTemplate template;
public GameObjectSender(SimpMessagingTemplate template) {
this.template = template;
}
#Override
public void send(String destination, GameObject gameObject) {
// Here i want to send monster position using RScoket
this.template.convertAndSend(destination, gameObject);
}
#Override
public void sendWithTimestamp(String destination, GameObject gameObject) {
// Here i want to send monster position using RScoket
this.template.convertAndSend(destination, gameObject, Map.of("timestamp", System.currentTimeMillis()));
}
}
Here i can use SimpMessagingTemplate to send message to specific place like '/pacman/update/monster' (js). Application flow for monster looks like (create 5 threads in service which move and send all time position to client side (GameObjectSender is injected here)):
Server:
private void createMonsters() {
for (int i = 0; i < Game.NUMBER_OF_MONSTERS; i++) {
int[] position = positionSetterService.getStartPositionForFigure();
Game.getGame().getMonsters().add(new Monster(i, position[0], position[1], Direction.NONE));
new Thread(() -> {
int idMonster = Integer.parseInt(Thread.currentThread().getName());
logger.info("Stworzylem potwora o id: " + idMonster);
Monster monster = Game.getGame().getMonsters().get(idMonster);
while (true) {
try {
Thread.sleep(50);
move(monster);
} catch (InterruptedException e) {
logger.error("Przerwano watek potwora");
Thread.currentThread().interrupt();
}
}
}, String.valueOf(i)).start();
}
}
#Override
public void move(Monster monster) {
int[] position = chasePlayer(monster);
if (spriteCollisionService.checkCollisionWithMonsters(position[0], position[1])) {
position[0] = position[0] - (position[0] % 32) + 16;
position[1] = position[1] - (position[1] % 32) + 16;
}
monster.setPositionX(position[0]);
monster.setPositionY(position[1]);
Optional<Player> playerToRemove = spriteCollisionService.getPlayerWhoCollideWithMonster(position[0], position[1]);
if (playerToRemove.isPresent()) {
resetPreviousDirection();
logger.info("Monster wpada na Gracza i go zabija");
Game.getGame().getPlayers().remove(playerToRemove.get());
this.spriteSender.send("/pacman/remove/player", playerToRemove.get());
}
synchronized (Game.getGame().getMonsters()) {
Game.getGame().getMonsters().remove(monster);
Game.getGame().getMonsters().add(monster);
}
this.spriteSender.send("/pacman/update/monster", monster);
}
This is my JS code to receive a message from Azure Service Bus
function receiveMessage(serviceBusTopic, serviceBusSubscriber, callback) {
serviceBus.receiveSubscriptionMessage(serviceBusTopic, serviceBusSubscriber,
{ isPeekLock: true }, function (error, lockedMessage) {
if (!error) {
try {
const receivedMessage = JSON.parse(lockedMessage.body);
console.log('receivedMessage', receivedMessage);
if (!_.isEqual(receivedMessage.Type, messageType.USERPROFILES_USER_UPDATED)) {
return;
}
//Message received and locked
callback(receivedMessage);
serviceBus.deleteMessage(lockedMessage, function (deleteError) {
if (!deleteError) {
// Message deleted
console.log('message has been deleted.');
}
});
}
catch (error) {
console.log('Start debugging');
console.log(lockedMessage.body);
}
When I receive a message it has strange encoding and JSON.parse throws an exception.
The lockedMessage output is:
{ body: '#\fbase64Binary\b3http://schemas.microsoft.com/2003/10/Serialization/�s\u0002{"Type":"SomeEvent"�\u0001}',
brokerProperties:
{ DeliveryCount: 9,
EnqueuedSequenceNumber: 0,
EnqueuedTimeUtc: 'Thu, 16 Nov 2017 23:50:16 GMT',
LockToken: '6e3e311f-0fe9-4366-844d-18046fd000db',
LockedUntilUtc: 'Fri, 17 Nov 2017 00:10:46 GMT',
MessageId: 'nil',
PartitionKey: '1d84084f-65af-4a33-bb30-62d97d85557d',
SequenceNumber: 61643019899633670,
SessionId: '1d84084f-65af-4a33-bb30-62d97d85557d',
State: 'Active',
TimeToLive: 1566804.069 },
location: '',
contentType: 'application/xml; charset=utf-8',
customProperties: { 'strict-transport-security': NaN, connection: NaN } }
The message is coming from a .NET Core service and that service sends with this code:
var payload = JsonConvert.SerializeObject(SomeEvent);
var serviceBusMessage = new Message(Encoding.UTF8.GetBytes(payload));
serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
topicClient.SendAsync(serviceBusMessage).Wait();
Why is Node.js not able to parse the message? Another .NET app can receive the same message without any issues.
To avoid this, you need to set ContentType to text/plain when sending a message from .NET Core service. So it should be something like this:
var payload = JsonConvert.SerializeObject(SomeEvent);
var serviceBusMessage = new Message(Encoding.UTF8.GetBytes(payload))
{
ContentType = "text/plain"
};
serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
topicClient.SendAsync(serviceBusMessage).Wait();
In this article, they explained the problem and the solution for .NET.
Update:
After some diving, this would not happen to me when I either use .NET Core or .NET to send a message with the standard library Microsoft.Azure.ServiceBus whether ContentType is specified or not.
This is my C# code to send a message:
class Program
{
static void Main(string[] args)
{
string connectionString = "Endpoint=sb://...";
var client = new TopicClient(connectionString, "MyTopic");
var payload = JsonConvert.SerializeObject(new DemoMessage() { Title = $"hello core!!! {DateTime.Now}" });
var serviceBusMessage = new Message(Encoding.UTF8.GetBytes(payload));
serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
client.SendAsync(serviceBusMessage).Wait();
}
private class DemoMessage
{
public DemoMessage()
{
}
public string Title { get; set; }
}
}
This is my Node.js code to receive a message:
var azure = require('azure');
var serviceBusService = azure.createServiceBusService("Endpoint=sb://...");
serviceBusService.receiveSubscriptionMessage('MyTopic', 'sub1', { isPeekLock: true }, function(error, lockedMessage) {
if(!error) {
console.log(lockedMessage);
serviceBusService.deleteMessage(lockedMessage, function (deleteError){
if(!deleteError){
// Message deleted
console.log('message has been deleted.');
}
})
}
});
The lockedMessage output is:
This only happens when I use .NET and the SDK WindowsAzure.ServiceBus with this code:
class Program
{
static void Main(string[] args)
{
string connectionString = "Endpoint=sb://...";
var client = TopicClient.CreateFromConnectionString(connectionString, "MyTopic");
var payload = JsonConvert.SerializeObject(new DemoMessage() { Title = $"hello core!!! {DateTime.Now}" });
var serviceBusMessage = new BrokeredMessage(Encoding.UTF8.GetBytes(payload));
serviceBusMessage.SessionId = Guid.NewGuid().ToString("D");
client.Send(serviceBusMessage);
}
private class DemoMessage
{
public DemoMessage()
{
}
public string Title { get; set; }
}
}
Now, the lockedMessage output is:
So, I think the message you received is sent from another .NET client and I suggest you clear all messages from the topic before you test it in Node.js.
I ran into this issue as well. If you are using Stream Analytics then its compatibility level may be the cause of this issue. Stream Analytics compatibility level 1.0 uses an XML serializer producing the XML tag you are seeing. Compatibility level 1.1 "fixes" this issue.
See my previous answer here: https://stackoverflow.com/a/49307178/263139.
I have a method which save an image file in the database as a BLOB file. The method works fine, but when I get the callback in ExtJS filefield component, it always goes through failure function and I don't know what I have to respond to go through success function, this is my code:
Server method:
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces({ MediaType.APPLICATION_JSON })
public ServiceResponse uploadFile(#QueryParam("id") Long iconId, FormDataMultiPart form) {
CatIcon icon;
if (iconId != null) {
icon = catIconBean.getOne(iconId);
} else {
icon = new CatIcon();
}
byte[] image = form.getField("iconBmp").getValueAs(byte[].class);
if (image.length != 0) {
MultivaluedMap<String, String> headers = form.getField("iconBmp").getHeaders();
String type = headers.getFirst("Content-type");
List<String> list = Arrays.asList("image/gif", "image/png", "image/jpg", "image/jpeg",
"image/x-icon", "image/bmp");
if (list.contains(type)) {
icon.setIconBmp(image);
icon.setType(type);
}
}
icon.setDescription(form.getField("description").getValue());
icon.setFileName(form.getField("fileName").getValue());
icon = catIconBean.saveIcon(icon);
ServiceResponse sr = new ServiceResponse();
sr.httpResponse = true;
return sr;
}
What I have to return in the code above?
Client:
uploadIcon : function(item, e, eOpts) {
var me = this;
var form = this.getDetail().getForm();
var valid = form.isValid();
if (!valid) {
return false;
}
var values = form.getValues();
if(values) {
form.submit({
url : myApplication.defaultHost() + 'icon/upload?id=' + values.id,
waitMsg : 'Uploading...',
success : function(form, action) {
me.onCompleteSaveOrDelete();
},
failure : function(form, action) {
me.onCompleteSaveOrDelete();
}
});
}
},
I write the same function, me.onCompleteSaveOrDelete(), in both callback functions to make it be called, that's the method which I want to be called in success.
Greetings.
UPDATE:
I did almost the same Alexander.Berg answered. The only difference was that I write #Produces({ MediaType.APPLICATION_JSON }) instead of #Produces({ MediaType.TEXT_HTML }), because I need Json Response. But when I debug in chrome and check the response, I get this:
In failure:
failure : function(form, action) {
me.onCompleteSaveOrDelete();
}
In action param, within responseText:
"{"data":"{\"success\":true}","httpResponse":true,"totalCount":0}"
But It's still going through failure...I think I'm very close, any help??
Greetings.
The fileupload in Extjs is more tricky, because it is using iframe and submit, not a real ajax request for uploading files.
Try this on Server method:
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.TEXT_HTML)
public String uploadFile(#QueryParam("id") Long iconId, FormDataMultiPart form) {
(...)
JSONObject json = new JSONObject();
json.put("success", true);
json.put("msg", "Success");
return json.toString();
}
this is because the upload accepts Content-Type text/html,
see Example at http://docs.sencha.com/extjs/4.2.2/#!/api/Ext.form.field.File -> Example Usage -> Live Preview
Use Firefox browser with Firebug plugin and on Net tab the following URL -> http://docs.sencha.com/extjs/4.2.2/photo-upload.php
Response Headersview source
(...)
Content-Type text/html
(...)
Request Headersview source
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
(...)