I try to communicate between a Java WebsocketServer (https://github.com/TooTallNate/Java-WebSocket) with an a Webpage via a JS-WebSocket.
My JS-Websocket:
window.websocket = new WebSocket("ws://localhost:8000");
window.websocket.onopen = () => {
window.websocket.send("Hello")
}
window.websocket.onmmessage = function(event) {
alert('Hi');
console.log(event.data);
}
and my Java-Websocket-Server:
package test;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.HashSet;
import java.util.Set;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
public class testsocket extends WebSocketServer {
private static int TCP_PORT = 9000;
private Set<WebSocket> conns;
public testsocket() throws UnknownHostException {
super(new InetSocketAddress(TCP_PORT));
conns = new HashSet<>();
}
#Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
conns.add(conn);
System.out.println("New connection from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
#Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
}
#Override
public void onMessage(WebSocket conn, String message) {
System.out.println(message);
String s2send = "hello";
System.out.println(s2send);
conn.send(s2send);
}
#Override
public void onError(WebSocket conn, Exception ex) {
ex.printStackTrace();
if (conn != null) {
conns.remove(conn);
// do some thing if required
}
}
}
So my Java-Websocket prints "Hello", so I can communicate from JS to Java, but on the other hand my Websocket is neither showing the alert nor printing in the console, so I assume onmessage isn't firing
If you are sure, your java ws server is working... Then
There is a typo! the event listener should be window.websocket.onmessage. NOT window.websocket.onmmessage. Two "m"s :)
window.websocket = new WebSocket("ws://localhost:8000");
window.websocket.onopen = () => {
window.websocket.send("Hello");
};
window.websocket.onmessage = function(event) {
alert("Hi");
console.log(event.data);
};
Related
Could you explain me how I could use concatMap on getPrices() and getDetails()?
export class HistoricalPricesComponent implements OnInit, OnDestroy {
private unsubscribe$ = new Subject < void > ();
infoTitle: string = "";
lines: HistoryPoint[] = [];
model: Currency = new Currency();
svm: string;
constructor(
private location: Location,
private service: HistoricalPricesService,
private activatedRoute: ActivatedRoute
) {}
ngOnInit(): void {
let svm: string | null;
svm = this.activatedRoute.snapshot.paramMap.get('svm');
if (!svm) {
this.goBack();
return;
}
this.svm = svm;
this.getPrices();
this.getDetails(svm)
}
ngOnDestroy(): void {
this.unsubscribe$.next();
this.unsubscribe$.complete();
}
getPrices(): void {
this.service.getInstrumentHistoryEquities(this.svm, this.model).pipe(
takeUntil(this.unsubscribe$)
).subscribe(res => {
if (res.RETURNCODE === ApiResponseCodeEnum.Ok) {
if (res.HISTO.POINT.length > 0) {
this.lines = res.HISTO.POINT.reverse();
}
}
});
}
getDetails(svm: string): void {
this.service.getInstrumentInfo(svm).pipe(
takeUntil(this.unsubscribe$)
).subscribe(res => {
if (res.RETURNCODE === ApiResponseCodeEnum.Ok) {
this.infoTitle += " " + res.ADVTITRE.BASIQUETITRE.LABEL + " (" + res.ADVTITRE.BASIQUETITRE.PLACELABEL + ")";
}
});
}
goBack(): void {
this.location.back();
}
}
I tried to look on this page
https://www.tektutorialshub.com/angular/using-concatmap-in-angular/
But I don't know where to start?
The example does not allow me to understand how I could create this?
here it is
concatMap is a operator stream so you just need to use it through a creator stream to that I initialize two Subject for each actions getPrices & getDetails.
Then I perform the AJAX call following the concatMap strategy and get that into Observable in order to be combined or used directly into the template of the component.
export class HistoricalPricesComponent implements OnInit, OnDestroy {
private unsubscribe$ = new Subject < void > ();
infoTitle: string = "";
lines: HistoryPoint[] = [];
model: Currency = new Currency();
svm: string;
// actions
getPrices$ = new Subject<void>();
getDetails$ = new Subject<string>();
// states
prices$: Observable<any>();
details$: Observable<any>();
constructor(
private location: Location,
private service: HistoricalPricesService,
private activatedRoute: ActivatedRoute
) {}
ngOnInit(): void {
let svm: string | null;
svm = this.activatedRoute.snapshot.paramMap.get('svm');
if (!svm) {
this.goBack();
return;
}
this.svm = svm;
this.prices$ = this.getPrices$.pipe(concatMap(this.getPrices)
this.details$ = this.getDetails$.pipe(concatMap((svm => this.getDetails(svm))
}
ngOnDestroy(): void {
this.getPrices$.complete()
this.getDetails$.complete()
this.unsubscribe$.complete();
}
getPrices(): void {
this.service.getInstrumentHistoryEquities(this.svm, this.model).pipe(
takeUntil(this.unsubscribe$)
).subscribe(res => {
if (res.RETURNCODE === ApiResponseCodeEnum.Ok) {
if (res.HISTO.POINT.length > 0) {
this.lines = res.HISTO.POINT.reverse();
}
}
});
}
getDetails(svm: string): void {
this.service.getInstrumentInfo(svm).pipe(
takeUntil(this.unsubscribe$)
).subscribe(res => {
if (res.RETURNCODE === ApiResponseCodeEnum.Ok) {
this.infoTitle += " " + res.ADVTITRE.BASIQUETITRE.LABEL + " (" + res.ADVTITRE.BASIQUETITRE.PLACELABEL + ")";
}
});
}
goBack(): void {
this.location.back();
}
}
I've been trying to make a simple WebRTC app using Firebase Database and PeerJs that can switch cameras. I found one tutorial and it works properly, but I want to switch the camera between front and back which is not included in the tutorial.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
...
<uses-feature android:name="android.hardware.camera.any"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
...
</manifest>
CallActivity.java
import static android.view.View.GONE;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.PermissionRequest;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.UUID;
public class CallActivity extends AppCompatActivity {
private static final String TAG = CallActivity.class.getSimpleName();
private final String CAMERA_FRONT = "user";
private final String CAMERA_BACK = "environment"; // Tried to use it on navigator.mediaDevices.getUserMedia({video: {facingMode: camera}}) but it didn't work.
private RelativeLayout layoutIncoming, layoutCall, layoutCallControl;
private Button buttonReject, buttonAccept, buttonCall, buttonAudio, buttonVideo, buttonCamera;
private EditText editTextCallName;
private TextView textViewIncoming;
private WebView webView;
private String name;
private String callerName;
private boolean isPeerConnected = false;
private DatabaseReference usersRef = FirebaseDatabase.getInstance("link_to_firebase_database").getReference("users");
private boolean videoEnabled = true;
private boolean audioEnabled = true;
private String camera = CAMERA_FRONT;
private String uniqueID;
//== Overridden ==//
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call);
layoutIncoming = findViewById(R.id.activity_call_layoutIncoming);
layoutCall = findViewById(R.id.activity_call_layoutCall);
layoutCallControl = findViewById(R.id.activity_call_layoutCallControl);
buttonAccept = findViewById(R.id.activity_call_buttonAccept);
buttonReject = findViewById(R.id.activity_call_buttonReject);
buttonCall = findViewById(R.id.activity_call_buttonCall);
buttonVideo = findViewById(R.id.activity_call_buttonVideo);
buttonAudio = findViewById(R.id.activity_call_buttonAudio);
buttonCamera = findViewById(R.id.activity_call_buttonCamera);
editTextCallName = findViewById(R.id.activity_call_editTextCallName);
textViewIncoming = findViewById(R.id.activity_call_textViewIncoming);
webView = findViewById(R.id.activity_call_webView);
if (getIntent().hasExtra("name")) {
name = getIntent().getStringExtra("name");
}
buttonCall.setOnClickListener(view -> {
callerName = editTextCallName.getText().toString().trim();
if (!callerName.isEmpty()) sendCallRequest();
});
buttonVideo.setOnClickListener(view -> {
videoEnabled = !videoEnabled;
callJsFunction("javascript:toggleVideo(\"" + videoEnabled + "\")");
if (videoEnabled)
buttonVideo.setText("Video Off");
else
buttonVideo.setText("Video On");
});
buttonAudio.setOnClickListener(view -> {
audioEnabled = !audioEnabled;
callJsFunction("javascript:toggleAudio(\"" + audioEnabled + "\")");
if (audioEnabled)
buttonAudio.setText("Mute");
else
buttonAudio.setText("Unmute");
});
buttonCamera.setOnClickListener(view -> {
if (camera.equals(CAMERA_FRONT)) camera = CAMERA_BACK;
else camera = CAMERA_FRONT;
switchCamera();
});
setupWebView();
}
//== Public ==//
public void onPeerConnected() {
isPeerConnected = true;
}
//== Private ==//
private void setupWebView() {
WebChromeClient client = new WebChromeClient() {
#Override
public void onPermissionRequest(PermissionRequest request) {
runOnUiThread(() -> request.grant(request.getResources()));
}
};
webView.setWebChromeClient(client);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
webView.addJavascriptInterface(new JsInterface(this), "Android");
loadVideoCall();
}
private void loadVideoCall() {
String filePath = "file:///android_asset/call.html";
webView.loadUrl(filePath);
WebViewClient client = new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
initializePeer();
}
};
webView.setWebViewClient(client);
}
private void initializePeer() {
uniqueID = getUniqueID();
callJsFunction("javascript:init(\"" + uniqueID + "\")");
usersRef.child(name).child("incoming").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
Log.d(TAG, "Received incoming call!!!");
onCallRequest(snapshot.getValue(String.class));
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void sendCallRequest() {
if (!isPeerConnected) {
Toast.makeText(this, "You're not connected to internet. Please try again.", Toast.LENGTH_SHORT).show();
return;
}
usersRef.child(callerName).child("incoming").setValue(name);
usersRef.child(callerName).child("isAvailable").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
boolean isAvailable = snapshot.getValue() != null? snapshot.getValue(boolean.class): false;
if (isAvailable) {
listenForConnectionID();
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void onCallRequest(String caller) {
if (caller == null) return;
String incomingMessage = caller + " is calling...";
textViewIncoming.setText(incomingMessage);
buttonAccept.setOnClickListener(view -> {
usersRef.child(name).child("connectionID").setValue(uniqueID);
usersRef.child(name).child("isAvailable").setValue(true);
layoutIncoming.setVisibility(GONE);
switchToCallControls();
});
buttonReject.setOnClickListener(view -> {
usersRef.child(name).child("incoming").setValue(null);
layoutIncoming.setVisibility(GONE);
});
layoutIncoming.setVisibility(View.VISIBLE);
}
private void listenForConnectionID() {
usersRef.child(callerName).child("connectionID").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.getValue() == null) return;
switchToCallControls();
callJsFunction("javascript:startCall(\"" + snapshot.getValue(String.class) + "\")");
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
private void switchToCallControls() {
layoutCall.setVisibility(GONE);
layoutCallControl.setVisibility(View.VISIBLE);
}
private void switchCamera() {
Log.d(TAG, "switchCamera: " + camera);
callJsFunction("javascript:switchCamera(\"" + camera + "\")");
}
private void callJsFunction(String functionString) {
webView.post(() -> webView.evaluateJavascript(functionString, value -> Log.d(TAG, value)));
}
private String getUniqueID() {
return UUID.randomUUID().toString();
}
}
call.html
<!DOCTYPE html>
<html>
<head>
<link href="./style.css" rel="stylesheet"/>
</head>
<body>
<script src="./peerjs.js"></script>
<video class="secondaryVideo" autoplay id="remoteVideo"></video>
<video class="primaryVideo" autoplay muted id="localVideo"></video>
<script src="./call.js"></script>
</body>
</html>
call.js
let localVideo = document.getElementById("localVideo")
let remoteVideo = document.getElementById("remoteVideo")
localVideo.style.opacity = 0
remoteVideo.style.opacity = 0
let peer
function init(userID) {
peer = new Peer(userID)
peer.on('open', () => {
Android.onPeerConnected();
})
listen()
}
let localStream
function listen() {
peer.on('call', (call) => {
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(function(mediaStream) {
localStream = mediaStream
localVideo.srcObject = localStream
localVideo.style.opacity = 1
call.answer(localStream)
call.on('stream', (remoteStream) => {
remoteVideo.srcObject = remoteStream
remoteVideo.style.opacity = 1
// Swap classes of localVideo and remoteVideo
localVideo.className = "secondaryVideo"
remoteVideo.className = "primaryVideo"
})
})
})
}
function startCall(otherUserID) {
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(function(mediaStream) {
localStream = mediaStream
localVideo.srcObject = localStream
localVideo.style.opacity = 1
const call = peer.call(otherUserID, localStream)
call.on('stream', (remoteStream) => {
remoteVideo.srcObject = remoteStream
remoteVideo.style.opacity = 1
// Swap classes of localVideo and remoteVideo
localVideo.className = "secondaryVideo"
remoteVideo.className = "primaryVideo"
})
})
}
function toggleVideo(b) {
if (b == "true") {
localStream.getVideoTracks()[0].enabled = true
} else {
localStream.getVideoTracks()[0].enabled = false
}
}
function toggleAudio(b) {
if (b == "true") {
localStream.getAudioTracks()[0].enabled = true
} else {
localStream.getAudioTracks()[0].enabled = false
}
}
let camIndex = 0
function switchCamera() {
navigator.mediaDevices.enumerateDevices().then(function(devices) {
var cameras = []
devices.forEach(function(device) {
'videoinput' === device.kind && cameras.push(device.deviceId)
})
console.log(cameras.length)
if (camIndex == cameras.length - 1) {
camIndex = 0
} else {
camIndex = camIndex + 1
}
var constraints = {
video: {deviceId: {exact: cameras[camIndex]}},
audio: true
}
navigator.mediaDevices.getUserMedia(constraints).then(function(mediaStream) {
localStream = mediaStream
localVideo.srcObject = localStream
console.log("camera switched to camIndex " + camIndex) // Only triggered when camIndex = 0
})
})
}
I assume that camIndex = 1 is a back camera but it gives this error message in the logcat
D/CallActivity: switchCamera: environment
E/chromium: [ERROR:web_contents_delegate.cc(218)] WebContentsDelegate::CheckMediaAccessPermission: Not supported.
E/chromium: [ERROR:web_contents_delegate.cc(218)] WebContentsDelegate::CheckMediaAccessPermission: Not supported.
D/CallActivity: null
I/chromium: [INFO:CONSOLE(97)] "2", source: file:///android_asset/call.js (97)
E/libc: Access denied finding property "persist.vendor.camera.privapp.list"
W/ThreadPoolSingl: type=1400 audit(0.0:35101): avc: denied { read } for name="u:object_r:vendor_camera_prop:s0" dev="tmpfs" ino=19669 scontext=u:r:untrusted_app:s0:c161,c256,c512,c768 tcontext=u:object_r:vendor_camera_prop:s0 tclass=file permissive=0
E/cr_VideoCapture: cameraDevice encountered an error
I/chromium: [INFO:CONSOLE(0)] "Uncaught (in promise) NotReadableError: Could not start video source", source: file:///android_asset/call.html (0)
D/CallActivity: switchCamera: user
E/chromium: [ERROR:web_contents_delegate.cc(218)] WebContentsDelegate::CheckMediaAccessPermission: Not supported.
E/chromium: [ERROR:web_contents_delegate.cc(218)] WebContentsDelegate::CheckMediaAccessPermission: Not supported.
D/CallActivity: null
I/chromium: [INFO:CONSOLE(97)] "2", source: file:///android_asset/call.js (97)
D/: PlayerBase::stop() from IPlayer
D/AudioTrack: stop(398): called with 62088 frames delivered
I/chromium: [INFO:CONSOLE(115)] "camera switched to camIndex 0", source: file:///android_asset/call.js (115)
W/.testapp_webrt: Attempt to remove non-JNI local reference, dumping thread
W/AudioManager: Use of stream types is deprecated for operations other than volume control
W/AudioManager: See the documentation of requestAudioFocus() for what to use instead with android.media.AudioAttributes to qualify your playback use case
i am developing a role-based application using android studio, since my project needs admin rights for creating user and deleting user i used firebase admin sdk for my project. I tried to delete multiple accounts but i faced with issue. The response returns not a valid json object. As in my code i tried to handle possible errors. However the response still returns not a valid json object.
See below
index.js
exports.deleteUser = functions.https.onCall(async (data,context) => {
try {
if(!context.auth) {
throw new AuthenticationError('Kimlik Doğrulaması Yapılmamış');
}
const uids = JSON.parse(data);
console.log(uids);
const callerUid = context.auth.uid;
const callerUser = await admin.auth().getUser(callerUid);
if(!callerUser.customClaims.admin && !callerUser.customClaims.superadmin) {
throw new NotAnAdminError('Bu işlemi sadece yöneticiler gerçekleştirebilir');
}
const reference = admin.firestore().collection("Users");
const res = await admin.auth().deleteUsers(uids);
res.errors.forEach(element => console.log(element));
const successes = res.successCount;
const fails = res.failureCount;
console.log(fails);
console.log(successes);
if(fails===0) {
await uids.forEach(element => reference.doc(element).delete());
return {result:successes+' Öğrenci Silindi!'};
}else {
throw new functions.https.HttpsError('Silme Hatası','Bilinmeyen hata,
silinemeyen öğrenci sayısı: '+fails);
}
}
catch(error) {
if(error.type === 'NotAnAdminError') {
throw new functions.https.HttpsError('Bu işlemi yapma yetkiniz
yok.',error.message);
}else if(error.type === 'AuthenticationError') {
throw new functions.https.HttpsError('Kimlik Hatası',error.message);
}else {
throw new functions.https.HttpsError('internal ERROR from catch
block',error.message);
}
}
});
Android Code
private Task<String> deleteUsers(List<CheckableUser> users) {
List<String> idlist = new ArrayList<>();
for (CheckableUser user:users) {
idlist.add(user.getUid());
}
return mFunctions.getHttpsCallable("deleteUsers").call(jsonFormatted).
continueWith(new Continuation<HttpsCallableResult, String>() {
#Override
public String then(#NonNull Task<HttpsCallableResult> task) throws Exception {
HashMap<String,Object> data = task.getResult().getData();
String result = data.get("result");
Log.d(TAG, "then: "+result);
return result;
}
});
mFunctions.getHttpsCallable("deleteUsers").call(jsonFormatted).continueWith(new
Continuation<HttpsCallableResult, String>() {
#Override
public String then(#NonNull Task<HttpsCallableResult> task) throws Exception {
HashMap<String,Object> data = task.getResult().getData();
String result = data.get("result");
Log.d(TAG, "then: "+result);
return result;
}
});
}
deleteUsers(users).addOnCompleteListener(new OnCompleteListener<String>() {
#Override
public void onComplete(#NonNull Task<String> task) {
if (task.isSuccessful()) {
Snackbar snackbar =
Snackbar.make(requireView().findViewById(R.id.constraintlayout),"Selected users are
deleted",4000);
snackbar.show();
}else {
debugFirebase(task.getException());
}
}
});
private void debugFirebase(Exception e) {
if (e instanceof FirebaseFunctionsException) {
FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
Log.d(TAG, "debugFirebase: MESSAGE: "+ffe.getMessage());
Log.d(TAG, "debugFirebase: CODE: "+ffe.getCode());
Log.d(TAG, "debugFirebase: DETAILS: "+ffe.getDetails());
Log.e(TAG, "debugFirebase: EXCEPTION: ",ffe );
}
}
Exception
com.google.firebase.functions.FirebaseFunctionsException: Response is not valid
JSONobject.
Caused by: org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be
converted to JSONObject
Your function is declared and exported as "deleteUser", but you are calling it in the Android client as "deleteUsers", which is not the same. The strings need to match.
I am working on an Android application where I need to connect to a web socket and receive messages to unlock the app from the web server. Receiving messages have been implemented through Stompclient on java script but i need to do the same on Android. I read about Okhttp3 and its support for web socket so I was able to implement it The websocket is opening but I don't know how to subscribe to receive the messages on Android.
Here is the Java Script Code:
<html>
<head>
<title>Chat WebSocket</title>
<script src="/gravity/resources/sockjs-0.3.4.js"></script>
<script src="/gravity/resources/stomp.js"></script>
<script type="text/javascript">
var stompClient = null;
function setConnected(connected) {
document.getElementById('connect').disabled = connected;
document.getElementById('disconnect').disabled = !connected;
document.getElementById('conversationDiv').style.visibility
= connected ? 'visible' : 'hidden';
document.getElementById('response').innerHTML = '';
}
function connect() {
var socket = new SockJS('/gravity/api/gravitywebsocket');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
stompClient.subscribe('/pos/asycnronous', function(messageOutput) {
var body = messageOutput.body; body.a=5;
showMessageOutput(body);
});
});
}
function disconnect() {
if(stompClient != null) {
stompClient.disconnect();
}
setConnected(false);
console.log("Disconnected");
}
function sendMessage() {
var from = document.getElementById('from').value;
var text = document.getElementById('text').value;
stompClient.send("/api/poschannel", {},JSON.stringify({'from':from, 'text':text}));
}
function showMessageOutput(messageOutput) {
var response = document.getElementById('response');
var p = document.createElement('p');
p.style.wordWrap = 'break-word';
p.appendChild(document.createTextNode(messageOutput.a + "***" +messageOutput.from + ": "
+ messageOutput.text + " (" + messageOutput.time + ")"));
response.appendChild(p);
}
</script>
</head>
<body onload="disconnect()">
<div>
<div>
<input type="text" id="from" placeholder="Choose a nickname"/>
</div>
<br />
<div>
<button id="connect" onclick="connect();">Connect</button>
<button id="disconnect" disabled="disabled" onclick="disconnect();">
Disconnect
</button>
</div>
<br />
<div id="conversationDiv">
<input type="text" id="text" placeholder="Write a message..."/>
<button id="sendMessage" onclick="sendMessage();">Send</button>
<p id="response"></p>
</div>
</div>
</body>
</html>
My Android Implementation:
public class ServerConnection {
public enum ConnectionStatus {
DISCONNECTED,
CONNECTED
}
public interface ServerListener {
void onNewMessage(String message);
void onStatusChange(ConnectionStatus status);
}
private WebSocket mWebSocket;
private OkHttpClient mClient;
private String mServerUrl;
private Handler mMessageHandler;
private Handler mStatusHandler;
private ServerListener mListener;
public class SocketListener extends WebSocketListener {
#Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
try {
System.out.println("On Open: Observe Response: " + response.body().string());
} catch (Exception e) {
Utility.stringify(e);
}
Message message = mMessageHandler.obtainMessage(Contract.ACTIVATE_POS_MESSAGE, ConnectionStatus.CONNECTED);
mStatusHandler.sendMessage(message);
}
#Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
System.out.println("OnMessage: Observe result: " + text);
Message message = mMessageHandler.obtainMessage(Contract.ACTIVATE_POS_MESSAGE, text);
mMessageHandler.sendMessage(message);
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
super.onMessage(webSocket, bytes.toString());
System.out.println("OnMessage: Observe result: " + bytes.toString());
Message message = mMessageHandler.obtainMessage(Contract.ACTIVATE_POS_MESSAGE, bytes.toString());
mMessageHandler.sendMessage(message);
}
#Override
public void onClosed(WebSocket webSocket, int code, String reason) {
super.onClosed(webSocket, code, reason);
System.out.println("OnClosed: Observe Reason: " + reason);
Message message = mMessageHandler.obtainMessage(Contract.ACTIVATE_POS_MESSAGE, ConnectionStatus.DISCONNECTED);
mMessageHandler.sendMessage(message);
}
#Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
System.out.println("OnFailure: Observe Response: " + response);
disconnect();
}
}
public ServerConnection(String url) {
mClient = new OkHttpClient.Builder()
.readTimeout(5, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build();
mServerUrl = url;
}
public void connect(ServerListener listener) {
Request request = new Request.Builder()
.url(mServerUrl)
.build();
mWebSocket = mClient.newWebSocket(request, new SocketListener());
mWebSocket.send("Hello, Testing Connection!");
mListener = listener;
mMessageHandler = new Handler(msg -> {
mListener.onNewMessage((String) msg.obj);
return true;
});
mStatusHandler = new Handler(msg -> {
mListener.onStatusChange((ConnectionStatus) msg.obj);
return true;
});
}
public void disconnect() {
mWebSocket.close(1000, "Completed");
mListener = null;
mMessageHandler.removeCallbacksAndMessages(null);
mStatusHandler.removeCallbacksAndMessages(null);
}
public void sendMessage(String message) {
mWebSocket.send(message);
}
}
The LockScreenActivity that needs to receive unlock message from server:
public class LockScreenActivity extends AppCompatActivity implements ServerConnection.ServerListener{
private ServerConnection mServerConnection;
private JSONObject jsonObject;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lock_screen);
mServerConnection = new ServerConnection(TerminalDetails.WEB_SOCKET_URL);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
Timer timer = new Timer();
timer.schedule(timerTask, 10000);
}
#Override
protected void onResume() {
super.onResume();
mServerConnection.connect(this);
mServerConnection.sendMessage("Hello, Testing Connection!");
Utility.showToast(this, "Connected to the Web Socket");
}
#Override
public void onNewMessage(String message) {
try {
Utility.showToast(this, "A new message received!");
jsonObject = new JSONObject(message);
} catch (JSONException e) {
Utility.stringify(e);
}
validateResponse(jsonObject);
}
I will answer more questions about the code if needed. Thanks
I have a server, and I connect to it perfectly and receives messages if I work with node.js and javascript.
I started an app on Android Studio that has an EditText and TextView attributes.
My goal is to type in the EditText press send and send that msg to the server and print the response in the TextView.
For some reason I can't get it to work, and I can see the Socket does connect when I debug it. But I can't seem to get the responses from the server as I would in my js example.
This is my code:
public class MainActivity extends AppCompatActivity {
private Socket socket;
String response = "";
BufferedReader in = null;
PrintStream out = null;
TextView tv;
EditText et;
private static final int SERVERPORT = 80;
private static final String ONLY_HOST = "myServer.azurewebsites.net";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.textView);
et = (EditText) findViewById(R.id.messages);
ClientThread client = new ClientThread();
client.execute();
}
class ClientThread extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
try {
socket = new Socket(ONLY_HOST, SERVERPORT);
byte[] buffer = new byte[1024];
InputStream inputStream = socket.getInputStream();
while (inputStream.read(buffer) != -1) {
response += new String(buffer);
}
} catch (UnknownHostException e1) {
Log.e("UnknownHost","Socket not starting" );
e1.printStackTrace();
} catch (IOException e1) {
Log.e("IO Exception","Socket not starting" );
e1.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
if (tv != null) {
tv.setText(response);
}
super.onPostExecute(result);
}
}
public void sendIt(View v) {
try {
if (socket.isConnected()) {
out = new PrintStream(socket.getOutputStream(), true);
out.write(et.getText().toString().getBytes());
out.flush();
}
} catch (UnknownHostException e1) {
Log.e("sendIt","1st" );
e1.printStackTrace();
} catch (IOException e1) {
Log.e("sendIt","2nd" );
e1.printStackTrace();
}
}
}
Any help will do i've been on this too long already.
Thanks!