How can I get defined instance/var from Java in NativeScript? - javascript

I've created a plugin which connects and subscribes to pusher channel successfully via NativeScript using this Java plugin,
now I'm trying to create an eventListener to get events in Nativescript,
this is my Java plugin:
public class PusherAndroid {
public void connectToPusher(String app_key, String channel_name, String event_name) {
PusherOptions options = new PusherOptions().setCluster("eu");
Pusher pusher = new Pusher(app_key, options);
pusher.connect(new ConnectionEventListener() {
#Override
public void onConnectionStateChange(ConnectionStateChange change) {
System.out.println("State changed to " + change.getCurrentState() +
" from " + change.getPreviousState());
}
#Override
public void onError(String message, String code, Exception e) {
System.out.println("There was a problem connecting!");
}
}, ConnectionState.ALL);
Channel channel = pusher.subscribe(channel_name);
channel.bind(event_name, new SubscriptionEventListener() {
#Override
public void onEvent(PusherEvent event) {
System.out.println("Received event with data: " + event.toString());
}
});
}
}
and this is my module:
module.exports = {
connect:function(app_key, channel_name, event_name) {
var psh = new com.pxb.pusherandroid.PusherAndroid();
psh.connectToPusher(app_key, channel_name, event_name);
var EventListener;
function initializeEventListener() {
if (EventListener) {
return;
}
EventListener = com.pxb.pusherandroid.PusherAndroid.extend({
interfaces: [com.pusher.client.channel.SubscriptionEventListener],
onEvent: event => {
console.log(event);
}
});
}
initializeEventListener();
<HERE I NEED MY CHANNEL>.bind(event_name, new EventListener());
}
};
Now, how can I get this channel in Javascript, to use it as my defined connected channel and bind eventListener to it?
Channel channel = pusher.subscribe(channel_name);
thank you

I dont really know how NativeScript works, but couldn't you just searialize your Channel to a json string, store it in a global variable on your PusherAndroid class and then access and desearialize it on your module?

thanks to #Manoj, there's no need to code in Java and try to use them in Javascript,
we can directly use Java classes and methods with Javascript,
there's really not enough reference for this.
here is my module after deleting all java code and just calling the classes and methods from pusher-java-library directly:
module.exports = {
connect:function(app_key, channel_name, event_name) {
PusherOptions = com.pusher.client.PusherOptions;
Pusher = com.pusher.client.Pusher;
Channel = com.pusher.client.channel.Channel;
SubscriptionEventListener = com.pusher.client.channel.SubscriptionEventListener;
PusherEvent = com.pusher.client.channel.PusherEvent;
var options = new PusherOptions().setCluster("eu");
var pusher = new Pusher(app_key, options);
pusher.connect();
var channel = new Channel(pusher.subscribe(channel_name));
}
};
now going to add my eventlistener with Javascript <3

Related

Signalr Close Message Recieved From Server Error

I have been dealing this error for a long time. I just want to make signalr to listen my 2 method. When i comment the (this) methods it works perfectly.
But it doesnt work. Can someone help me? Sometimes i can get the value but then it gets me the error like below the image. I researched some pages but cant find any answer actually.
Vuejs
const hubConnection = new signalR.HubConnectionBuilder()
.configureLogging(signalR.LogLevel.Debug)
.withUrl("http://localhost:7002/ChatHub", {
skipNegotiation: true,
transport: signalR.HttpTransportType.WebSockets,
})
.build();
hubConnection.start();
this.connectionId = hubConnection.connectionId;
this.connection = hubConnection;
hubConnection.on("UserConnected",(users) => console.log(users));(this)
hubConnection.on(categoryId, (all) => {
all = JSON.parse(all);
this.userMessage = {
id: all.Id,
text: all.Text,
userId:all.UserId,
userName:all.UserName,
categoryName: all.CategoryName,
createdOn: all.CreatedOn,
};
this.messages.push(this.userMessage);
console.log(this.userMessages);
});
},
using Microsoft.AspNetCore.SignalR;
using System.Text;
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.AspNetCore.Http;
using System;
using System.Web;
using System.Net.Http.Headers;
using System.Linq;
using System.IdentityModel.Tokens.Jwt;
using System.IdentityModel.Tokens;
using System.Collections.Generic;
using System.Threading.Tasks;
using Message.Dal.Concrete;
using Message.Dal.Abstract;
using Message.Dal.Model;
using Microsoft.Extensions.Configuration;
namespace Message.Dal.SignalRHub
{
public class ChatHub : Hub
{
private readonly IHubContext<ChatHub> _chatHub;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IElasticRepository<OnlineUserModel> _elasticRepository;
private readonly string _indexName;
public ChatHub(IHubContext<ChatHub> chatHub,IElasticRepository<OnlineUserModel> elasticRepository,IConfiguration configuration)
{
_chatHub = chatHub;
_httpContextAccessor = new HttpContextAccessor();
_elasticRepository = elasticRepository;
_indexName = configuration["elasticsearchserver:User"].ToString();
}
public async Task SendMessage(Guid categoryId,string message)
{
await _chatHub.Clients.All.SendAsync(categoryId.ToString(),message);
}
public override Task OnConnectedAsync()
{
var token = string.Empty;
var httpContext = _httpContextAccessor.HttpContext.Request.Cookies;
var onlineUserModel = new OnlineUserModel();
onlineUserModel.Id = Context.ConnectionId;
if(!httpContext.Any())
{
return Task.CompletedTask;
}
token = httpContext.Where(x=> x.Key == "CodeChatBackend").FirstOrDefault().Value;
if(AuthenticationHeaderValue.TryParse(token,out var headerVal))
{
var handler = new JwtSecurityTokenHandler();
var val = handler.ReadJwtToken(headerVal.ToString());
onlineUserModel.UserName = val.Claims.FirstOrDefault(x => x.Type == "Name").Value;
}
var checkOnlineUser = _elasticRepository.GetUserAsync(onlineUserModel.UserName,_indexName);
if(checkOnlineUser.Result == null)
{
_elasticRepository.CreateUserAsync(onlineUserModel.Id,onlineUserModel,_indexName);
}
var getOnlineUser = _elasticRepository.GetAllAsync(_indexName);
_chatHub.Clients.All.SendAsync("UserConnected",getOnlineUser);(this)
base.OnConnectedAsync();
return Task.CompletedTask;
}
public override Task OnDisconnectedAsync(Exception exception)
{
var httpContext = _httpContextAccessor.HttpContext.Request.Cookies;
var token = string.Empty;
var result = _elasticRepository.DeleteUserAsync(Context.ConnectionId,_indexName);
var getOnlineUser = _elasticRepository.GetAllAsync(_indexName);
_chatHub.Clients.All.SendAsync("UserConnected",getOnlineUser);(this)
base.OnDisconnectedAsync(exception);
return Task.CompletedTask;
}
}
}
When i delete the onconnectedasync client method. It works perfectly. Am i missing something?
I fixed it! My mistake totally. I was trying to make one hub to connect different methods. To fix this: Create second hub class and configure your startup, then call hub method with a new connection.

Execute Javascript on external url using HybridView, Xamarin cross platform

I have tried to execute JavaScript on an external url (ie: http://facebook.com) using WebView from Visual Studio Mac 2019, and so far no results.
To do so, I have tried to follow along with the official tutorial here https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/hybridwebview, and also tried a simpler one here: https://xamarinhelp.com/xamarin-forms-webview-executing-javascript/
Here is what I did with explanations:
On my shared folder, I created an HybridWebView class with the following code:
public class HybridWebView : WebView
{
Action<string> action;
public static readonly BindableProperty UriProperty = BindableProperty.Create(
propertyName: "Uri",
returnType: typeof(Func<string, Task<string>>),
declaringType: typeof(HybridWebView),
defaultValue: default(string));
public string Uri
{
get => (string)GetValue(UriProperty);
set
{
SetValue(UriProperty, value);
}
}
public void RegisterAction(Action<string> callback)
{
action = callback;
}
public void Cleanup()
{
action = null;
}
public void InvokeAction(string data)
{
if (action == null || data == null)
{
return;
}
action.Invoke(data);
}
public Func<string, Task<string>> ExecuteJavascript
{
get { return (Func<string, Task<string>>)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
}
From The macOS project which I use to test my cross-platform app, I tried the following custom renderer:
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>
{
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
var webView = e.NewElement as HybridWebView;
if (webView != null)
{
Control.LoadRequest(new NSUrlRequest(new NSUrl(Element.ExecuteJavascript.ToString())));
}
}
}
To note that the following part wouldn't work:
var webView = e.NewElement as HybridWebView;
if (webView != null)
webView.ExecuteJavascript = (js) =>
{
return Task.FromResult(this.ExecuteJavascript(js)); // issue at ExecuteJavascript with following error ('HybridWebViewRenderer' does not contain a definition for 'ExecuteJavascript' ), hence replaced by Control.LoadRequest ...
};
From my ViewModel, I did the following:
public Func<string, Task<string>> EvaluateJavascript { get; set; }
public async Task OnConnectTapped()
{
Console.WriteLine("on connect tapped");
// passing the url onto a connection service
var hybridWebView = new HybridWebView
{
Uri = "https://facebook.com/"
};
//hybridWebView.InvokeAction("document.getElementById('td');");
//var result = await hybridWebView.RegisterAction(data => DisplayAlert("Alert", "Hello " + data, "OK"));
var result = await hybridWebView.ExecuteJavascript("document.cookie;");
Console.WriteLine("result is {0}", result);
}
Here is the error when trying to execute my code:
System.NullReferenceException: Object reference not set to an instance of an object
at MyApp.ViewModel.MainModel.OnConnectTapped () [0x00031] in .../../././/ViewModel/MainModel.cs:451
at .......<.ctor>g__c5|48_9 () [0x0001f] in /../../../.cs:143
at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in /Users/builder/jenkins/workspace/xamarin-macios/xamarin-macios/external/mono/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1021
at Foundation.NSAsyncSynchronizationContextDispatcher.Apply () [0x00002] in /Library/Frameworks/Xamarin.Mac.framework/Versions/6.6.0.12/src/Xamarin.Mac/Foundation/NSAction.cs:178
at at (wrapper managed-to-native) AppKit.NSApplication.NSApplicationMain(int,string[])
at AppKit.NSApplication.Main (System.String[] args) [0x00040] in /Library/Frameworks/Xamarin.Mac.framework/Versions/6.6.0.12/src/Xamarin.Mac/AppKit/NSApplication.cs:100
at redacted.macOS.MainClass.Main (System.String[] args) [0x00017] in /Users/dom-bruise/Projects/redacted/redacted.macOS/Main.cs:11
For me, it could either be because I can't execute external pages, or the part where I replaced by the following messing up my attempt.
if (webView != null)
{
Control.LoadRequest(new NSUrlRequest(new NSUrl(Element.ExecuteJavascript.ToString())));
}
My main goal here is to have my app execute JavaScript underneath the hood on pages using WebView, and fill in forms automatically calling back C# from my app.

Trying to create websockets and using HttpSelfHostServer

I just got handed a new project where most of the job was already done but I needed to change some things for my project. I have a self hosted server setup like this in a consoleapp:
using (var server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
Console.WriteLine("Press enter to exit");
Console.ReadLine();
}
and a route configured like this:
private static HttpSelfHostConfiguration CreateWebServerConfiguration()
{
var config = new HttpSelfHostConfiguration(string.Format("http://{0}:{1}", Environment.MachineName, 80));
config.Routes.MapHttpRoute("Api", "api/{controller}/{id}/{value}", new {id = RouteParameter.Optional, value = RouteParameter.Optional });
config.Routes.MapHttpRoute("Defect", "defect/{action}/{id}", new { controller = "Defect", action = RouteParameter.Optional, id = RouteParameter.Optional });
config.Routes.MapHttpRoute("Content", "content/{action}/{file}", new { controller = "Content"});
config.Routes.MapHttpRoute("Default", "{controller}/{action}/{id}/{date}", new { controller = "Home", action = "Index", id = RouteParameter.Optional, date = RouteParameter.Optional });
var templateConfig = new TemplateServiceConfiguration { Resolver = new DelegateTemplateResolver(name => ReadFileContent("Views", name))};
Razor.SetTemplateService(new TemplateService(templateConfig));
return config;
}
This works perfectly, but I ran into a situation, where I didn't want the front end to pull with a timer on the server(currently auto refresh every 5 min). I want the server to update the frontend, when there is something new to update. I found the solution to this which would be websockets, but I have a lot of problems using those.
my .js file:
(function() {
if ("WebSocket" in window) {
alert("WebSocket is supported by your Browser!");
} ws://' + window.location.hostname + window.location.pathname.replace('index.htm', 'ws.ashx') + '?name='
var socket = new WebSocket("ws://localhost:80/WebsocketServer.cs");
socket.onmessage = function(event) {
alert("message recv.");
alert(event.data);
};
socket.onopen = function() {
alert("open");
}
socket.onerror = function(errorEvent) {
alert("Error");
alert(errorEvent);
};
socket.onclose = function(closeEvent) {
alert(closeEvent.code);
}
})();
I found multiple examples like this one: https://blog.simpleisbest.co.uk/2012/05/01/websockets-with-asp-net-4-5-and-visual-studio-11/ but it doesn't seem to work for me, this is my files:
WebsocketServer.cs
public class WebsocketServer : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (context.IsWebSocketRequest)
{
context.AcceptWebSocketRequest(new WebSocketManager());
}
}
public bool IsReusable
{
get { return false; }
}
}
WebSocketManager.cs
public class WebSocketManager : WebSocketHandler
{
public static WebSocketCollection clients = new WebSocketCollection();
public override void OnClose()
{
clients.Remove(this);
}
public override void OnError()
{
}
public override void OnMessage(string message)
{
}
public override void OnOpen()
{
clients.Add(this);
clients.Broadcast("Connected");
}
}
The frontend returns closing code 1006 or CLOSE_ABNORMAL. My guess is the link to the backend isn't created?

How to establish a click listener in a separate class from the event Vaadin

I am very new to Vaadin and v-Leaflet. I have created a component that takes some geojson data and puts it over a map. I am able to click on any of the polygons/ multi polygons and get back a few bits of information in the form of a notification. The thing is, I need to take this information and click event and have it influence about 4 other separate components in their own separate classes. I have been racking my brain with this for the past 2 days and just can't seem to grasp it.
Here is my map/ click event:
private LMap map;
String filePath = this.getClass().getResource("/fccpeasgeo.json").getPath();
File file = new File(filePath);
//ArrayList<String> peaNames = new ArrayList<String>();
//#Override
public LMap createMap() {
map = new LMap();
FeatureJSON io = new FeatureJSON();
try {
long currentTimeMillis = System.currentTimeMillis();
// Look ma, no proxy needed, how cool is that!
FeatureCollection fc = io.readFeatureCollection(file);
Logger.getLogger(LeafletMap.class.getName()).severe("Download in " + (System.currentTimeMillis() - currentTimeMillis));
currentTimeMillis = System.currentTimeMillis();
FeatureIterator iterator = fc.features();
try {
while (iterator.hasNext()) {
Feature feature = iterator.next();
final String name = feature.getProperty("PEA_Name").getValue().toString();
final String population = feature.getProperty("POPs_2010").getValue().toString();
Geometry geometry = (Geometry) feature.getDefaultGeometryProperty().getValue();
// The geojson provided in example is rather complex (several megabytes)
// Use JTS to simplyfy. Note that it is rather easy to use
// different settings on different zoom levels, as well as decide
// to drop the feature form client altogether
geometry = DouglasPeuckerSimplifier.simplify(geometry, 0.2);
// In this example can be Polygon/Multipolygon
Collection<LeafletLayer> toLayers = JTSUtil.toLayers(geometry);
for (LeafletLayer l : toLayers) {
map.addComponent(l);
if (l instanceof LPolygon) {
LPolygon lPolygon = (LPolygon) l;
lPolygon.addClickListener(new LeafletClickListener() {
#Override
public void onClick(LeafletClickEvent event) {
Notification.show("PEA: " + name + " Population: " + population);
}
});
}
}
}
Logger.getLogger(LeafletMap.class.getName()).severe("Reducing and creating layers " + (System.currentTimeMillis() - currentTimeMillis));
} finally {
iterator.close();
}
} catch (MalformedURLException ex) {
Logger.getLogger(LeafletMap.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(LeafletMap.class.getName()).log(Level.SEVERE, null, ex);
}
map.zoomToContent();
//map.setCenter(40, -95.2);
//map.setZoomLevel(2.5);
LTileLayer tf = new LTileLayer();
tf.setUrl("http://{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png");
tf.setSubDomains(new String[]{"a", "b", "c"});
tf.setActive(true);
map.addBaseLayer(tf, "ThunderForest Transport");
return map;
}
Here is one of the components that will be receiving the event.
public Chart mhzPerSqMile() {
Chart chart = new Chart();
run();
chart.setCaption("Total MHz Per Square Mile");
chart.getConfiguration().setTitle("");
chart.getConfiguration().getChart().setType(ChartType.PIE);
chart.getConfiguration().getChart().setAnimation(false);
chart.setWidth("100%");
chart.setHeight("90%");
DataSeries series = new DataSeries();
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName()!=null)
{
if (evt.getPropertyName().equals("abcTask"))
{
}
}
for (int i = 0; i < 5; i++) {
Operator operator = operators.get(i);
if (selectedPea != null) {
if (operator.getPeaName().toLowerCase() == selectedPea.toLowerCase()){
DataSeriesItem item = new DataSeriesItem(operator.getName(),
operator.getTotalMHzSqMile());
series.add(item);
item.setColor(DummyDataGenerator.chartColors[i]);
}
}
}
chart.getConfiguration().setSeries(series);
PlotOptionsPie opts = new PlotOptionsPie();
opts.setBorderWidth(0);
opts.setShadow(false);
opts.setAnimation(false);
chart.getConfiguration().setPlotOptions(opts);
Credits c = new Credits("");
chart.getConfiguration().setCredits(c);
return chart;
}
}
}
Any advice would be very appreciated!
what I think you simply need to fire a property with any specific name (Event name) and all your listener classes have implemented PropertyChangeListener which triggers on every fireProperty() call , obviously you are matching your event name there and hence all you 4 classes perform their task upon receiving such a property change
You need to register PropertyChangeSupport for current instance
PropertyChangeSupport pcs = new PropertyChangeSupport(this);
further you'll use this object to fire your event
Firing event
//this firing code will probably go inside your click method that actually causes an event to occur
pcs.firePropertyChange("abcTask", oldValue, newValue);
Recieving event
#Override
public void propertyChange(PropertyChangeEvent evt)
{
if (evt.getPropertyName()!=null)
{
if (evt.getPropertyName().equals("abcTask"))
{
//perform task
}
}
}

Consume Server Sent in C#

I am using ServiceStack.Client to consume, the data pushed by my server(which is an aspx page).
Below is the code which i use to consume the data using ServiceStack Client:
using System;
using System.Net.Sockets;
using System.Net;
using System.Security.Cryptography;
using System.Threading;
using ServiceStack;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ServerEventConnect connectMsg = null;
var msgs = new List<ServerEventMessage>();
var commands = new List<ServerEventMessage>();
var errors = new List<Exception>();
var client = new ServerEventsClient("https://testing.leadsquared.com/ReferralCampaign/Demo")
{
OnConnect = e => PrintMsg(e),
OnCommand = e => PrintCmdMsg(e),
OnMessage = e => PrintCmMsg(e),
OnException = e => PrintExMsg(e)
}.Start();
Console.Read();
}
private static void PrintCmMsg(ServerEventMessage e)
{
if (e != null)
{
PrintMsg(e.Data);
}
}
private static void PrintExMsg(Exception e)
{
if (e != null)
{
PrintMsg(e.Message);
}
}
private static void PrintCmdMsg(ServerEventMessage e)
{
if (e != null)
{
PrintMsg(e.Data);
}
}
private static void PrintMsg(ServerEventConnect e)
{
if (e!=null)
{
PrintMsg(e.Data);
}
}
private static void PrintMsg(string x)
{
Console.WriteLine(x);
}
}
}
When I run my code , the client does print any message on the console.
The ConnectionDisplayName property is "(not connected)".
If i subscribe to the same URL using javascript EventSource, i get the notifications.
My requirement is that I would want to consume the data by my server in C#.
How can I achieve this?
Firstly the url needs to be the BaseUri where ServiceStack is hosted, i.e. the same url used in JavaScript ServerEvents Client, e.g:
var client = new ServerEventsClient(BaseUrl).Start();
It's not clear if /ReferralCampaign/Demo is the BaseUri or not.
You will also want to call Connect() to wait for the client to make a connection, e.g:
await client.Connect();
Then to see message events you'll need to call a ServiceStack Service that publishes a Notify* Event on IServerEvents API which you can use with a separate JsonServiceClient or the ServiceClient available in ServerEventsClient, e.g:
client.ServiceClient.Post(new PostRawToChannel {
From = client.SubscriptionId,
Message = "Test Message",
Channel = channel ?? "*",
Selector = "cmd.announce",
});
This is an example calling the Chat PostRawToChannel ServiceStack Service:
public class ServerEventsServices : Service
{
public IServerEvents ServerEvents { get; set; }
public void Any(PostRawToChannel request)
{
// Ensure the subscription sending this notification is still active
var sub = ServerEvents.GetSubscriptionInfo(request.From);
if (sub == null)
throw HttpError.NotFound("Subscription {0} does not exist".Fmt(request.From));
// Check to see if this is a private message to a specific user
if (request.ToUserId != null)
{
// Only notify that specific user
ServerEvents.NotifyUserId(request.ToUserId, request.Selector, request.Message);
}
else
{
// Notify everyone in the channel for public messages
ServerEvents.NotifyChannel(request.Channel, request.Selector, request.Message);
}
}
}
I also recommend looking at the C# ServerEventTests for complete stand-alone examples using C# ServerEventClient.

Categories