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.
Related
I'm using spring boot in my backend and vuejs in my front-end . I've defined everything in the guide yet I still don't get my project to work.
FrontEnd
connectToWS() {
this.socket = new Sock("http://localhost:8754/stomp-endpoint");
this.stompClient = Stomp.over(this.socket);
this.stompClient.connect(
{},
frame => {
this.connected = true;
console.log(frame);
this.stompClient.subscribe("/topic/greetings", tick => {
console.log(tick);
this.received_messages.push(JSON.parse(tick.body).content);
});
},
error => {
console.log(error);
this.connected = false;
}
);
},
Backend
WebSocketConfiguration Class :
#Configuration
#EnableWebSocketMessageBroker
public class WebsocketConfiguration implements
WebSocketMessageBrokerConfigurer
{
#Override
public void registerStompEndpoints(StompEndpointRegistry registry)
{
// with sockjs
registry.addEndpoint("/stomp-endpoint")
.setAllowedOrigins("http://localhost:8081")
.withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.setApplicationDestinationPrefixes("/app")
.enableSimpleBroker("/topic");
}
}
WebSecurityConfigClass :
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/api/v*/registration/**").permitAll()
.antMatchers("/topic**").permitAll()
.antMatchers("/stomp-endpoint").permitAll()
UPDATE :
The error is actually coming out from the browser . It actually changes the route of the api because it has sockjs integrated into it. I couldn't figure out why the API always gets a /info?t=RandomNumber after it. I need the route to remain the same as I typed it in the front-end.
How can I stop the browser from updating my path. Thanks for helping !
My goal is to notify, if a player joins a team in real-time.
Since the player will be created in the controller, i want to notify the team about this change via socket.
This has been my first attempt in doing that:
#RestController
#RequestMapping("/api/secure/players/")
public class PlayerController {
#Autowired
private SimpMessagingTemplate simpMessageTemplate;
#PostMapping
public ResponseEntity<PlayerDTO> createPlayer() {
// ...
// data is being processed
// notify team about the change
simpMessageTemplate.convertAndSend("/teams/" + selectedTeam.getId() + "/", player);
return ...
}
}
#Controller
public class TeamSocket {
private static final Logger logger = LoggerFactory.getLogger(TeamSocket.class);
#MessageMapping("/teams/{team}")
#SendTo("/teams/{team}")
public void teamEvent(#DestinationVariable String team) {
logger.debug("Received message -> {}", team);
}
}
#Configuration
#ComponentScan
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// I still dont fully understand this. Do i have to enable it? (It does not fix the issue).
// config.enableSimpleBroker("/teams/");
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/api/secure/stomp/").withSockJS();
}
}
However, Spring tells me, that it was unable to map the request. What am i doing wrong?
DEBUG 29487 --- [nboundChannel-4] .WebSocketAnnotationMethodMessageHandler : Searching methods to handle SUBSCRIBE /teams/16 id=sub-0 session=0nkqv1km, lookupDestination='/teams/16'
DEBUG 29487 --- [nboundChannel-4] .WebSocketAnnotationMethodMessageHandler : No matching message handler methods.
DEBUG 29487 --- [nboundChannel-2] org.springframework.web.SimpLogging : Processing SUBSCRIBE /teams/16 id=sub-0 session=0nkqv1km
const client = new SockJS(`${REST_API}/api/secure/stomp/`);
const stompClient = Stomp.over(client);
stompClient.connect({}, (frame) => {
stompClient.subscribe(`/teams/${teamId}`, (message) => {
...
});
});
I see you are using path "/teams/" + selectedTeam.getId() + "/" in your convertAndSend method while you are subscribing to /teams/${teamId}. Do you need to add additional slash while subscribing or you may need to remove additional slash from convertAndSend?
Well, I have a signalR hub:
public class ReportHub : Hub
{
private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<ReportHub>();
public void SendMessage(string text)
{
Clients.All.sendMessage(text);
}
public static void ServerSendMessage(string text)
{
hubContext.Clients.All.sendMessage(text);
}
}
Also I have the client code in js, on some view
report.client.sendMessage = message => {
alert('message from server: '+ message);
}
And I have webapi action, like this:
[HttpGet]
[Route("api/Report/test")]
public int GetTest()
{
ReportHub.ServerSendMessage("message");
return 42;
}
When I open the view with signalR-catching js code in one browser, and in another browser window requesting the webapi action, by typing http://../api/report/test - all working, and alert is appearing
But when I calling webapi action via postman, or any other rest client, no effect at all, report.client.sendMessage = message => {
alert('message from server: '+ message);
} - not working
Can anyone help?
ReportHub.ServerSendMessage("message");
It is wrong.
You should return ReportHubContext for the connection before pushing the data to clients;
[HttpGet]
[Route("api/Report/test")]
public int GetTest()
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ReportHub>();
hubContext.ServerSendMessage("message");
return 42;
}
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
}
});
}
I am new in AngularJS as well as FullStack development. The architecture of my current app is already set up and should not change preferably (for security reasons). So far, I can emit messages to the server using angular-websocket-service. Here is the code snippet of the service from the front-end:
proxiMiamApp.service('WebSocketService', function ($websocket) {
var wsEndpoint = {};
this.openWsEndpoint = function () {
wsEndpoint = $websocket.connect("ws://localhost:9000/proximiamHandler");
console.log(wsEndpoint);
return wsEndpoint;
}
this.sendMessage = function(){
if($.isEmptyObject(this.wsEndpoint)){
this.openWsEndpoint();
}
eventUser = {
idEvent : '1',
idUser : '49'
};
wsEndpoint.register('/eventUser', function(){
console.log('Register OK!');
});
console.log('Ready!');
wsEndpoint.emit('/eventUser',eventUser);
}});
As for the back-end, I am using an implementation of the WebSocketHandler interface:
#Controller
public class ProximiamHandler implements WebSocketHandler {
#Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
System.out.println("afterConntectionEstablished called");
}
#Override
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
System.out.println("handleMessage called");
// My code here...
}
#Override
public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
System.out.println("handleTransportError called");
}
#Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
System.out.println("afterConnectionClosed called");
}
#Override
public boolean supportsPartialMessages() {
return true;
}}
The Implementation of the WebSocketHandler is called via Spring WebSocketConfigurer
#Configuration
#EnableWebSocket
#Controller
public class WebSocketConfig implements WebSocketConfigurer {
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/proximiamHandler").setAllowedOrigins("*");
}
#Bean
public WebSocketHandler myHandler() {
return new ProximiamHandler();
}}
My questions are:
Can I notify subscribed clients using this architecture?
If yes, how can I do it?
Is there a way to return something to subscribed clients from the server? (an Object or a String for instance)
Thanks in advance for your help
Can I notify subscribed clients using this architecture?
=> Yes.
If yes, how can I do it?
=> Based on the Spring web socket APIs, you have to retain the ' WebSocketSession' passed to you via "afterConnectionEstablished" callback.
Use the sendMessage() API of Web socket session to send notifications to client.
Is there a way to return something to subscribed clients from the server? (an Object or a String for instance)
=> You can format your data in either JSON or XML & wrap it using "WebSocketMessage" and pass it to client.
I never worked on spring, however, I am answering this based on my knowledge on web socket. See if it helps.