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);
}
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); }
}
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();
}
}
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);
}
I am using react-native to develop an android app. I am using native code to run a service in the foreground. This service consists of collections the accelerometer sensor readings of the phone.
Starting the service returns a successful promise but I do not receive no events. The following is the implementation of the service class:
public class PhonePositionService extends Service {
public static final String FOREGROUND = "com.testnative.position.FOREGROUND";
...
//Event listener for sensors -start
SensorEventListener sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event) {
PhonePositionService.this.sendMessage(event);
}
...
};
//Event Listener - end
#Override
#TargetApi(Build.VERSION_CODES.M)
public void onCreate() {
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE); //get services provided by sensor manager
mAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); //specifiy sensor
sensorManager.registerListener(sensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); //register it
}
private void sendMessage(SensorEvent event) {
try {
float[] values = event.values;
Intent intent = new Intent("PhonePosUpdate");
intent.putExtra("message", values);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
} catch (Exception e) {
e.printStackTrace();
}
}
...
The thing is not even a notification appears, I'm afraid the service didnt start at all.
The Following is my Module which uses this service:
public class PhonePositionModule extends ReactContextBaseJavaModule {
public PhonePositionModule(ReactApplicationContext reactContext) {
super(reactContext);
BroadcastReceiver phonePositionReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
float[] message = intent.getFloatArrayExtra("message");
PhonePositionModule.this.sendEvent(message);
}
};
LocalBroadcastManager.getInstance(getReactApplicationContext()).registerReceiver(phonePositionReceiver, new IntentFilter("PhonePosUpdate"));
}
...
#ReactMethod
public void startService(Promise promise) {
String result = "Success";
try {
Intent intent = new Intent(PhonePositionService.FOREGROUND); ///////
intent.setClass(this.getReactApplicationContext(), PhonePositionService.class);
getReactApplicationContext().startService(intent);
} catch (Exception e) {
promise.reject(e);
return;
}
promise.resolve(result);
}
...
private void sendEvent(float[] message) {
WritableMap map = Arguments.createMap();
map.putDouble("x", message[0]);
map.putDouble("y", message[1]);
map.putDouble("z", message[2]);
getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("updatePosition", map);
}
}
When I call startService() from JavaScript, I get a success. However no notification appears and
DeviceEventEmitter.addListener('updatePosition', (Data) => {
console.log(Data);
in App.js shows nothing.
Thus:
1) The Notification does not appear
2) Given that the notification does not appear, the service did not start (even though the promise did not return an error).
I tried debugging the native code on Android Studio but logcat isn't working for me.
I want to send data from socket in android client to node.js server ..
what ive done in server side :
socket.on('new user',function(data,callback){
console.log('ON new user');
if(data in users ){
callback(false);
}else {
callback(true);
socket.nickname = data;
users[socket.nickname]= socket;
UpdateNickNames();
}
});
and on my client android :
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
EditText edt;
Button btn;
boolean msg;
private Socket mSocket;
{
try {
mSocket = IO.socket("http://192.168.1.101/");
Log.v(TAG,"fine");
} catch (URISyntaxException e) {
Log.v(TAG,"Error..... "+e.getMessage());
e.printStackTrace();
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSocket.connect();
edt=(EditText)findViewById(R.id.editText);
btn=(Button)findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
attemptSend();
}
});
}
private void attemptSend() {
String message = edt.getText().toString().trim();
if (TextUtils.isEmpty(message)) {
return;
}
mSocket.emit("new user", message, true);
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
but it's crash with error :
throw er; // Unhandled 'error' event ^ TypeError: callback is not a function
I believe your server-side code looks good. the problem is on the clientside... when you are emiting the "new user" event, make sure its a function you are passing as a parameter, instead you passed a boolean value(true). Try this,
mSocket.emit("new user", message, callback);
Also, based on the callback result you get from serverSide, you do something, else you do something else..
HOPE THIS HELPS!
I've found The Solution here :
mSocket.emit("new user", message, new Ack() {
#Override
public void call(Object... args) {
//Code goes here
}
});
}