Not sure if I am doing something wrong but using this api https://www.firebase.com/docs/security/simple-login-email-password.html I can successfully create a user - according to the return message, but I can not see that user anywhere in the Forge console. How do you know what users are registered?
Should I be taking the return user ID and creating my own user object in Firebase or is this duplication unnecessary. I do need to add some additional user properties so perhapes I will need to do this anyway.
When using email / password authentication in Firebase Authentication (previously known as Firebase SimpleLogin), your user's email and password combination is securely stored separately from the data actually stored in your Firebase.
This barrier between the data in your Firebase and your users' email / password hash combinations is by design: we want to make it easier for you to (1) develop your application, (2) prevent any accidental user credential leaks, and (3) still give you total flexibility with how to store your user data in Firebase.
That means that we only store the email address / password hash combination and nothing else, so it is up to you to decide how to store actual user data in your Firebase. As you suggested, you should be taking the user id and storing that data in your Firebase in a location such as /users/$id, and using the Firebase Security Rules Language to determine read / write access to that data. Your user's unique id and email are already in the auth variable you'll use when writing rules.
Here i created an Android program to do what Rob said for firebase beginner(like me)
out there.this program first store the username of the signedUp or signedIn user and then display them in a listView
SignInActivity.java
public class SignInActivity extends BaseActivity implements View.OnClickListener,View.OnKeyListener{
private DatabaseReference mDatabase;
public static FirebaseAuth mAuth;
private static final String TAG = "MainActivity";
EditText usernameField;
EditText passwordField;
TextView changeSignUpModeTextView;
Button signUpButton;
ImageView logo;
RelativeLayout relativeLayout;
Boolean signUpModeActive;
static ArrayList<String> userList = new ArrayList<>();
#Override
public void onStart() {
super.onStart();
// Check auth on Activity start
if (mAuth.getCurrentUser() != null) {
onAuthSuccess(mAuth.getCurrentUser());
}
}
#Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
if(i == keyEvent.KEYCODE_ENTER && keyEvent.getAction() == keyEvent.ACTION_DOWN){
signUpOrLogIn(view);
}
return false;
}
#Override
public void onClick(View view) {
if(view.getId() == R.id.changeSignUpMode){
if (signUpModeActive == true){
signUpModeActive = false;
changeSignUpModeTextView.setText("Sign Up");
signUpButton.setText("Log In");
}else{
signUpModeActive = true;
changeSignUpModeTextView.setText("Log In");
signUpButton.setText("Sign Up");
}
}else if(view.getId() == R.id.logo || view.getId() == R.id.relativeLayout){
InputMethodManager inm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
inm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0);
}
}
public void signUpOrLogIn(View view) {
showProgressDialog();
String email = usernameField.getText().toString().trim();
String password = passwordField.getText().toString().trim();
if (signUpModeActive == true) {
mAuth.createUserWithEmailAndPassword(email,password)
.addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
hideProgressDialog();
Toast.makeText(MainActivity.this, "createUserWithEmail:onComplete:" + task.isSuccessful(), Toast.LENGTH_SHORT).show();
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Toast.makeText(MainActivity.this, "Authentication failed." + task.getException().toString().substring(task.getException().toString().indexOf(" ")),
Toast.LENGTH_SHORT).show();
Log.i("Error", task.getException().toString());
} else {
onAuthSuccess(task.getResult().getUser());
showUserList();
}
}
});
} else {
mAuth.signInWithEmailAndPassword(email,password)
.addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
hideProgressDialog();
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
// there was an error
Toast.makeText(MainActivity.this, task.getException().toString(),
Toast.LENGTH_LONG).show();
} else
{
onAuthSuccess(task.getResult().getUser());
showUserList();
}
}
});
}
}
public void showUserList(){
startActivity(new Intent(getApplicationContext(), UserList.class));
finish();
}
private void onAuthSuccess(FirebaseUser user) {
String username = usernameFromEmail(user.getEmail());
// Write new user
writeNewUser(user.getUid(), username, user.getEmail());
// Go to MainActivity
}
private String usernameFromEmail(String email) {
if (email.contains("#")) {
return email.split("#")[0];
} else {
return email;
}
}
private void writeNewUser(String userId, String name, String email) {
User user = new User(name, email);
mDatabase.child("users").child(userId).setValue(user);
ArrayList<String> userNames = new ArrayList<>();
userNames.add(name);
mDatabase.child("usernamelist").setValue(userNames);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAuth = FirebaseAuth.getInstance();
mDatabase = FirebaseDatabase.getInstance().getReference();
if(mAuth.getCurrentUser()!=null){
showUserList();
}
usernameField = (EditText) findViewById(R.id.username);
passwordField = (EditText) findViewById(R.id.password);
changeSignUpModeTextView = (TextView) findViewById(R.id.changeSignUpMode);
signUpButton = (Button) findViewById(R.id.signupbutton);
logo = (ImageView)findViewById(R.id.logo);
relativeLayout= (RelativeLayout)findViewById(R.id.relativeLayout);
signUpModeActive = true;
changeSignUpModeTextView.setOnClickListener(this);
usernameField.setOnKeyListener(this);
passwordField.setOnKeyListener(this);
logo.setOnClickListener(this);
relativeLayout.setOnClickListener(this);
}
}
UserList.java
public class UserList extends AppCompatActivity {
private static final String TAG = "UserList" ;
private DatabaseReference userlistReference;
private ValueEventListener mUserListListener;
ArrayList<String> usernamelist = new ArrayList<>();
ArrayAdapter arrayAdapter;;
ListView userListView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_list);
userlistReference = FirebaseDatabase.getInstance().getReference().child("usernamelist");
onStart();
userListView = (ListView) findViewById(R.id.userlistview);
}
#Override
protected void onStart() {
super.onStart();
final ValueEventListener userListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
usernamelist = new ArrayList<>((ArrayList) dataSnapshot.getValue());
usernamelist.remove(usernameOfCurrentUser());
Log.i(TAG, "onDataChange: "+usernamelist.toString());
arrayAdapter = new ArrayAdapter(UserList.this,android.R.layout.simple_list_item_1,usernamelist);
userListView.setAdapter(arrayAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "onCancelled: ",databaseError.toException());
Toast.makeText(UserList.this, "Failed to load User list.",
Toast.LENGTH_SHORT).show();
}
};
userlistReference.addValueEventListener(userListener);
mUserListListener = userListener;
}
public String usernameOfCurrentUser()
{
String email = MainActivity.mAuth.getCurrentUser().getEmail();
if (email.contains("#")) {
return email.split("#")[0];
} else {
return email;
}
}
#Override
public void onStop() {
super.onStop();
// Remove post value event listener
if (mUserListListener != null) {
userlistReference.removeEventListener(mUserListListener);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.action_logout:
FirebaseAuth.getInstance().signOut();
startActivity(new Intent(this, MainActivity.class));
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
You can use Google Identity Toolkit API to get a list of all registered users in your Firebase project, this API is used by the Firebase CLI which can be accessed by running firebase auth:export results-file
Make sure Identity Toolkit API is enabled
firebase-users-list.js
const serviceAccount = require('path/to/firebase-sdk-json-service-account');
const googleapis = require('googleapis');
const identitytoolkit = googleapis.identitytoolkit('v3');
const authClient = new googleapis.auth.JWT(
serviceAccount.client_email,
null,
serviceAccount.private_key,
['https://www.googleapis.com/auth/firebase'],
null
);
authClient.authorize((err) => {
if (err) {
return console.error(err);
}
let nextPageToken = undefined;
let users = [];
const getAccounts = () => identitytoolkit.relyingparty.downloadAccount({
auth: authClient,
resource: {
targetProjectId: serviceAccount.project_id,
maxResults: 200,
nextPageToken: nextPageToken
}
}, (e, results) => {
if (e) {
return console.error(err);
}
users = users.concat(results.users);
if (results.nextPageToken) {
nextPageToken = results.nextPageToken;
return getAccounts();
} else {
console.log(users);
}
});
getAccounts();
});
It's possible to use cloud function to fetch users list (view docs at firebase). Note, in the following example custom claims feature is used to check if user has enough privileges.
// USERS: return full users list for admin
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
import * as admin from 'firebase-admin'
import * as functions from 'firebase-functions'
export const listUsers = functions.https.onCall((data, context) => {
// check if user is admin (true "admin" custom claim), return error if not
const isAdmin = context.auth.token.admin === true
if (!isAdmin) {
return { error: `Unauthorized.` }
}
return admin
.auth()
.listUsers()
.then((listUsersResult) => {
// go through users array, and deconstruct user objects down to required fields
const result = listUsersResult.users.map((user) => {
const { uid, email, photoURL, displayName, disabled } = user
return { uid, email, photoURL, displayName, disabled }
})
return { result }
})
.catch((error) => {
return { error: 'Error listing users' }
})
})
You can do it using admin.auth().listUsers
Here is the doc for this: https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth.html#listusers
And an usage example: https://firebase.google.com/docs/auth/admin/manage-users#list_all_users
function listAllUsers(nextPageToken) {
// List batch of users, 1000 at a time.
admin.auth().listUsers(1000, nextPageToken)
.then(function(listUsersResult) {
listUsersResult.users.forEach(function(userRecord) {
console.log('user', userRecord.toJSON());
});
if (listUsersResult.pageToken) {
// List next batch of users.
listAllUsers(listUsersResult.pageToken);
}
})
.catch(function(error) {
console.log('Error listing users:', error);
});
}
// Start listing users from the beginning, 1000 at a time.
listAllUsers();
i will answer it simply as much as possible
just add the registered user to your data base by using the following code
you can also use shared prefernces to save the data locally but it won't be able for other user.
once you save the list of user in the database simply retrieve it from there using adapters
FirebaseDatabase.getInstance().getReference().child("my_user")
.child(task.getResult().getUser().getUid())
.child("username").setValue(autoCompleteTextView1.getText().toString());
Users list in python:
from firebase_admin import credentials, db, auth
cred = credentials.Certificate('\path\to\serviceAccountKey.json')
default_app = firebase_admin.initialize_app(cred, {
"databaseURL": "https://data_base_url.firebaseio.com"
})
users = auth.list_users()
Related
I need to establish connection between client websocket threw my backend on spring java to another websocket where my backend is a client, I established connection as client but can't figure out how to send it back as soon as my client send me message,
My Client Endpoint works as I need
#Service
#ClientEndpoint
public class ClientEndpoint {
Session userSession = null;
private MessageHandler messageHandler;
public WbsClientEndpoint(#Value("${url}") String url) {
try {
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, new URI(url));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
#OnOpen
public void onOpen(Session userSession) {
System.out.println("opening web socket");
this.userSession = userSession;
}
#OnClose
public void onClose(Session userSession, CloseReason reason) {
System.out.println("closing web socket");
this.userSession = null;
}
#OnMessage
public void onMessage(String message) {
if (this.messageHandler != null) {
this.messageHandler.handleMessage(message);
}
}
public void addMessageHandler(MessageHandler msgHandler) {
this.messageHandler = msgHandler;
}
public void sendMessage(String message) {
this.userSession.getAsyncRemote().sendText(message);
}
public interface MessageHandler {
void handleMessage(String message);
}
}
and example of method when I send my message as client, it does what I need but now I only printing the message cause cannot connect it to my message handler:
#Override
public void addDevice(DeviceTransfer deviceTransfer) {
clientEndPoint.addMessageHandler(message -> {
System.out.println("Response: " + message);
});
clientEndPoint.sendMessage(JSON.toJSONString(deviceTransfer));
}
Also I wrote a websockethandler for messages that comes to my backend:
#Component
public class WebSocketHandler extends AbstractWebSocketHandler {
#Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
System.out.println("New Text Message Received" + message + " ___ " + session);
String clientMessage = message.getPayload();
if (clientMessage.startsWith("/addDevice")) {
//Here I don't know how to send this clientMessage and wait for result from my addDevice method to return it back
}
}
}
And I need to connect both of the realizations to establish connection in real time.
When client sends message to me I must send this message to another server as client.
My client code on JavaScript as example, when I press button it establish connection to my web socket and send my message:
const connectBtn = document.getElementById('connect');
if (connectBtn) {
connectBtn.addEventListener('click', function () {
window.socket1 = new WebSocket("ws://localhost:8081/ws");
socket1.onopen = function(e) {
console.log("[open]");
socket1.send(JSON.stringify({"command": "subscribe","identifier":"{\"channel\":\"/topic/addDevice\"}"}))
};
socket1.onmessage = function(event) {
console.log(`[message]: ${event.data}`);
};
socket1.onclose = function(event) {
if (event.wasClean) {
console.log(`[close],code=${event.code}reason=${event.reason}`);
} else {
console.log('[close]');
}
};
socket1.onerror = function(error) {
console.log(`[error] ${error.message}`);
};
});
}
It seems to me like you need to keep track of your ClientEndpoint instances:
public class ClientEndpoint {
private HashSet<ClientEndpoint> endpoints = new HashSet<>();
// or perhaps a HashMap using `userSession.id` or similar
private HashMap<string, ClientEndpoint> userToEndpoint = new HahsMap<>();
#OnOpen
public void onOpen(Session userSession) {
System.out.println("opening web socket");
this.userSession = userSession;
this.endpoints.add(this);
this.userToEndpoint.put(userSession.id, this);
}
#OnClose
public void onClose(Session userSession, CloseReason reason) {
System.out.println("closing web socket");
this.endpoints.remove(this);
this.userToEndpoint.delete(userSession.id);
this.userSession = null;
}
}
You can use endpoints/userToEndpoint to find all connected clients, perhaps filter by which rooms they're in (I assume that's what you're trying to accomplish with that subscribe command), and do whatever you want with that information. E.g. a broadcast to everyone except the sender:
for (ClientEnpoint endpoint : this.endpoints) {
if (endpoint == sender) continue; // Don't send to sender
endpoint.sendMessage("message");
}
I'm using Firebase Cloud database and Firebase functions. I have the following code which sends a notification once was executed by firebase functions:
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
Log.d(TAG, "onMessageReceived: started");
Log.d(TAG, "onMessageReceived: message is: " + remoteMessage.getData());
if (FirebaseAuth.getInstance().getCurrentUser() == null) {
Log.d(TAG, "User is logged out. Will not fire notification");
return;
}
String payloadDisplayStatus = remoteMessage.getData().get("display_status");
if (payloadDisplayStatus == null) {
Log.d(TAG, "onMessageReceived: did not find a display status field");
return;
}
buildAdminBroadcastNotification(remoteMessage.getData());
}
#Override
public void onNewToken(#NonNull String token) {
sendRegistrationToServer(token);
}
#Override
public void onDeletedMessages() {
super.onDeletedMessages();
}
private void sendRegistrationToServer(final String token) {
FirebaseFirestore db = FirebaseFirestore.getInstance();
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user == null) {
return; // Failed to get current user
}
final String usersEmail = user.getEmail();
final String usersPhoneNumber = user.getPhoneNumber();
if (usersEmail != null && !(usersEmail.isEmpty())) {
db.collection("managers").document(usersEmail).get()
.addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
Log.d(TAG, "addOnSuccessListener:success");
if (documentSnapshot.exists()) {
List<DocumentReference> groups = (List<DocumentReference>) documentSnapshot.get("groups");
if (groups == null || groups.size() == 0) {
Log.d(TAG, "Failed to fetch the manager group");
return;
}
DocumentReference connectedGroupDocumentRef = groups.get(0);
connectedGroupDocumentRef.collection("managers").document(usersEmail).update("tokens", FieldValue.arrayUnion(token));
} else {
Log.d(TAG, "Document does not exist");
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.d(TAG, "addOnSuccessListener:failed", exception);
}
});
} else if (usersPhoneNumber != null && !(usersPhoneNumber.isEmpty())) {
db.collection("employees").document(usersPhoneNumber).get()
.addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
#Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
Log.d(TAG, "addOnSuccessListener:success");
if (documentSnapshot.exists()) {
List<DocumentReference> groups = (List<DocumentReference>) documentSnapshot.get("groups");
if (groups == null || groups.size() == 0) {
Log.d(TAG, "Failed to fetch the volunteer group");
return;
}
DocumentReference connectedGroupDocumentRef = groups.get(0);
connectedGroupDocumentRef.collection("employees").document(usersPhoneNumber).update("tokens", FieldValue.arrayUnion(token));
} else {
Log.d(TAG, "Document does not exist");
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
Log.d(TAG, "addOnSuccessListener:failed", exception);
}
});
}
}
The functions index.js file has the following piece of code which executes the onMessageReceived method:
let tokens = deliveredUserData.tokens;
const payload = {
data: {
display_status: 'admin_broadcast',
notification_type: 'DELIVERED',
message: deliveredUser.message,
receiver_path: deliveredUserDoc.ref.toString()
}
};
return admin.messaging().sendToDevice(tokens, payload);
The tokens is an array of all tokens of the user. My app contains two types of people - managers and employees. If user connected to manager, log out and then connected to employee (or the other way around), the notification will be sent to both of them, even though only one of the is actually connected. How can I prevent it from happening in?
EDIT: Is there some way to check if a token is of the connected user? something like:
if (!(FirebaseAuth.getInstance().getCurrentUser().verifyToken(token))) {
return; // Invalid token
}
That way I could pass the token from js to java and check it. But I didn't find a way to do it without SDK.
I want to show my notifications in a channel that I create so I can fully customize my channel with my preferences. I'm using a Firebase function to send notifications (messages) from user to user:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.pushNotification = functions.firestore.document('/devices/{tokenId}/notifications/{notificationId}')
.onWrite((change, context) => {
console.log('Push notification event triggered');
const tokenId = context.params.tokenId;
const document = change.after.exists ? change.after.data() : null;
if (document == null) {
return console.log('A notification has been deleted from database');
}
const payload = {
notification: {
title: document.username,
body: document.message,
sound: "default"
},
data: {
sender: document.sender
}
};
const options = {
priority: "high",
timeToLive: 60 * 60 * 24 //24 hours
};
return admin.messaging().sendToDevice(tokenId, payload, options).then(result => {
console.log('A notification sent to device with tokenId: ', tokenId);
});
});
I have implemented my FirebaseMessagingService service:
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
showNotification(remoteMessage);
}
private void showNotification(RemoteMessage remoteMessage) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
RemoteMessage.Notification remoteNotification = remoteMessage.getNotification();
if (remoteNotification == null) return;
String title = remoteNotification.getTitle();
String message = remoteNotification.getBody();
Notification notification;
Notification.Builder builder = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ?
new Notification.Builder(this, CH_MESSAGE) : new Notification.Builder(this);
notification = builder
.setContentTitle(title)
.setContentText(message)
.setCategory(CATEGORY_MESSAGE)
.build();
notificationManager.notify(0, notification);
}
And created my own notification channel at my Application class:
#Override
public void onCreate() {
super.onCreate();
createNotificationChannels();
}
private void createNotificationChannels() {
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (notificationManager == null) return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(CH_MESSAGE,
getString(R.string.messages), NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setDescription(getString(R.string.message_channel_description));
notificationManager.createNotificationChannel(notificationChannel);
}
}
I can successfully send notifications, but notifications are going to Miscellaneous channel.
I tried to remove the channel by using its channel ID with notificationManager.deleteNotificationChannel("fcm_fallback_notification_channel");, but it still recreates the channel and sends the notification there. How can I remove Miscellaneous channel permanently and handle my notifications with my own channels?
I have found the problem I am facing, my message payload contains both notification and data fields. According to this documentation my messages were not calling onMessageReceived method when app is in background. Now I'm using only data payload which calls the method when app is at both background and foreground.
const payload = {
data: {
sender: document.sender,
username: document.username,
message: document.message
}
};
And in my onMessageReceived method:
Map<String, String> remoteMap = remoteMessage.getData();
String senderUid = remoteMap.get("sender");
String senderUsername = remoteMap.get("username");
String message = remoteMap.get("message");
Notification.Builder builder = android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O ?
new Notification.Builder(this, CH_MESSAGE) : new Notification.Builder(this);
Notification notification = builder
.setContentTitle(senderUsername)
.setContentText(message)
.setSmallIcon(R.drawable.ic_notif_message)
.build();
notificationManager.notify(0, notification);
I have a problem that I don't seem to figure out. I want to send a http request from my
Angular client
export class UsersService {
private baseUrl = 'http://localhost:8095/rest/users';
createUser(user: Object): Observable<Object> {
return this.http.post(`${this.baseUrl}` , user);
}
getUsers(): Observable<any> {
return this.http.get(`${this.baseUrl}/all`);
}
}
create user component.ts :
save() {
this.userService.createUser(this.user)
.subscribe(data => console.log(data), error => console.log(error));
this.user = new User();}
this is the SpringBoot backend
#RestController
#RequestMapping("/rest/users")
public class UsersResource {
private UserRepository userRepository;
public UsersResource(UserRepository userRepository) {
this.userRepository = userRepository;
}
#GetMapping("/all")
public List<Users> getAll() {
return userRepository.findAll();
}
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public void create(#RequestBody Users users) {
userRepository.save(users);
}
}
when i call http://localhost:4200/users i got a clean result with all users without any problem
but when i want to add a user from here http://localhost:4200/adduser it show for me some issue
by the way iam using CORS chrome extension
i hope that someone help me for this isse.
thanks
I've started this multi chat thread alert system and I've successfully gotten multiple clients on the server, but when broadcasting the message to everyone, it only interacts with the initial client sending the message and the sever only, the other client does not receive the message.
Here are the codes I'm working with
Client 1
package popup;
import java.io.*;
import java.net.*;
import javax.swing.*;
public class ClientJFrame extends javax.swing.JFrame {
static Socket s;
static DataInputStream din;
static DataOutputStream dout;
public ClientJFrame() {
super("Client 1");
initComponents();
}
private void alertButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
try {
String msgout = "Alert client 1\n";
dout.writeUTF(msgout);
} catch (Exception e) {
}
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ClientJFrame().setVisible(true);
}
});
try {
s = new Socket("127.0.0.1", 111);
din = new DataInputStream(s.getInputStream());
dout = new DataOutputStream(s.getOutputStream());
String msgin = "";
while (true) {
msgin = din.readUTF();
messageArea.append(msgin);
JOptionPane.showMessageDialog(null, "BITCH WE ON FIRE");
s.close();
System.exit(0);
}
} catch (Exception e) {
}
}
// Variables declaration - do not modify
private javax.swing.JButton alertButton;
private javax.swing.JScrollPane jScrollPane1;
private static javax.swing.JTextArea messageArea;
// End of variables declaration
}
Server
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class TestJFrame extends javax.swing.JFrame {
static ServerSocket listener;
static Socket s;
private static final int PORT = 111;
public TestJFrame() {
super("Main");
initComponents();
}
public static class Handler extends Thread {
private final Socket socket;
private DataInputStream in;
private DataOutputStream out;
public Handler(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
in = new DataInputStream(socket.getInputStream());
messageArea.append("in\n");
out = new DataOutputStream(socket.getOutputStream());
messageArea.append("Out\n");
} catch (IOException e) {
}
while (true) {
try {
String input = in.readUTF();
messageArea.append(input);
out.writeUTF("We on Fire!!!\n");
} catch (IOException ex) {
Logger.getLogger(TestJFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
public static void main(String args[]) throws IOException, InterruptedException {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new TestJFrame().setVisible(false);
createAndShowGUI();
}
});
listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
// Variables declaration - do not modify
private javax.swing.JButton alertButton;
private javax.swing.JScrollPane jScrollPane1;
private static javax.swing.JTextArea messageArea;
// End of variables declaration
}
When a client connects to the server, add him to a list, so you always know who's connected. The same goes for when he disconnects.
When a client sends a message, process it however you want, then iterate over the list of connected clients and send them the message.
Take a look at the observer pattern, I think it will help for your project.