Observe Socket-IO Messages - android

I am implementing a chat feature in my app using nkzawa sockets library. I have sent message to server using sockets and an endpoint (url string).
I have heard talk about RxJava and RxAndroid being the best way to observer data streams.
Observable.from(MyEndPoint).subscribe()
But I am having trouble passing a url parameter to observable.
Is it possible to create an observable to listen on my server's endpoint for new and existing messages. Please how do you go about retrieving socket messages in this way or another way, Thanks.
Edited as suggested:
Here's the code snippet I tried without Rx but not working:
private com.github.nkzawa.socketio.client.Socket mSocket;
{
try {
mSocket = IO.socket(Constants.PUBLIC_CHAT_ENDPOINT);
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
Socket initialized like above and connected here:
mSocket.connect();
I am trying to get messages as demoed in the library docs but not working.
mSocket.on(Constants.SOCKET_GET_MESSAGE_EVENT, new Emitter.Listener() {
#Override
public void call(final Object... args) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
JSONObject jsonObject = (JSONObject) args[0];
JSONObject dataObject = jsonObject.getJSONObject("data");
String type = dataObject.getString("type");
Log.d(TAG, "Message is of type:\t" + type);
JSONObject contentObject = dataObject.getJSONObject("content");
String roomId = contentObject.getString("roomid");
String userId = contentObject.getString("userId");
String message = contentObject.getString("message");
Log.d(TAG, "Get Message is:\t" + message);
Log.d(TAG, "roomId:\t" + roomId);
Log.d(TAG, "Get userId is:\t" + userId);
TingTingUser otherUsers = new TingTingUser(userId, "Abhiram Labhani", "Unknown");
HomeMessage othersHomeMessages = new HomeMessage(message, otherUsers, System.currentTimeMillis());
List<HomeMessage> othersList = new ArrayList<>();
othersList.add(othersHomeMessages);
Log.d(TAG, "Other Messages size is:\t " + othersList.size());
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
I want to implement the above code using RxJava but have no idea how to observe data from a dynamic, constantly updating endpoint as most of the docs and articles only use pre-defined data. Thanks.

Related

The App connection is timing out before the server could process the data

The app that I Built connects to a local server which I have built in flask, But the python program takes time to execute and the client app closes the connection without taking the return statement and goes to the catch block and says Failed!!!. So what should I do to maintain the connection. I want to show a processing bar or
**
the server should notify the app when done with processing
**
I guess I can even build another button to get the processed data (so I will need notification that the processing is completed)
So what should I do. Can someone guide me in detail?Thanks.
enter code here''' `
import flask
import werkzeug
import time
from flask import flash
app = flask.Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def handle_request():
files_ids = list(flask.request.files)
print("\nNumber of Received Images : ", len(files_ids))
image_num = 1
for file_id in files_ids:
print("\nSaving Image ", str(image_num), "/", len(files_ids))
imagefile = flask.request.files[file_id]
filename = werkzeug.utils.secure_filename(imagefile.filename)
print("Image Filename : " + imagefile.filename)
timestr = time.strftime("%Y%m%d-%H%M%S")
imagefile.save(timestr + '_' + filename)
image_num = image_num + 1
print("\n")
// flash("Connected")
return "Image(s) Uploaded Successfully. Come Back Soon."
app.run(host="0.0.0.0", port=5000, debug=True)
'''
This is the flask code which accepts the incoming connection.
public void connectServer(View v) {
TextView responseText = findViewById(R.id.responseText);
if (imagesSelected == false) { // This means no image is selected and thus nothing to upload.
responseText.setText("No Image Selected to Upload. Select Image(s) and Try Again.");
return;
}
responseText.setText("Sending the Files. Please Wait ...");
EditText ipv4AddressView = findViewById(R.id.IPAddress);
String ipv4Address = ipv4AddressView.getText().toString();
EditText portNumberView = findViewById(R.id.portNumber);
String portNumber = portNumberView.getText().toString();
Matcher matcher = IP_ADDRESS.matcher(ipv4Address);
if (!matcher.matches()) {
responseText.setText("Invalid IPv4 Address. Please Check Your Inputs.");
return;
}
String postUrl = "http://" + ipv4Address + ":" + portNumber + "/";
MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
for (int i = 0; i < selectedImagesPaths.size(); i++) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
// Read BitMap by file path.
Bitmap bitmap = BitmapFactory.decodeFile(selectedImagesPaths.get(i), options);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
}catch(Exception e){
responseText.setText("Please Make Sure the Selected File is an Image.");
return;
}
byte[] byteArray = stream.toByteArray();
multipartBodyBuilder.addFormDataPart("image" + i, "Android_Flask_" + i + ".jpg", RequestBody.create(MediaType.parse("image/*jpg"), byteArray));
}
RequestBody postBodyImage = multipartBodyBuilder.build();
postRequest(postUrl, postBodyImage);
}
void postRequest(String postUrl, RequestBody postBody) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(postUrl)
.post(postBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
// Cancel the post on failure.
call.cancel();
Log.d("FAIL", e.getMessage());
// In order to access the TextView inside the UI thread, the code is executed inside runOnUiThread()
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView responseText = findViewById(R.id.responseText);
responseText.setText("Failed to Connect to Server. Please Try Again.");
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
// In order to access the TextView inside the UI thread, the code is executed inside runOnUiThread()
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView responseText = findViewById(R.id.responseText);
try {
responseText.setText("Server's Response\n" + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
});
}
'''
And This is my android studio connect server code
For getting the image from server to your app use
Picasso.get()
.load("*The link of your server*")
.into(imageView);

How to send a notification to a distinct user of Android App

I am working on an android app in which client request for a job. When his job is completed I want to send a notification to submit feedback on Android App. Server Api needs to build in laravel and notifications will be send through Firebase. If you have any idea of helping material please share.
I have tried many youtube tutorials but no success. Most of them use custom php apis but i need in laravel and send notification to a specific user.
Thanks!
First of all you need to grab the InstanceToken from the app in the frontend and submit it to your backend somehow.
After you have that you can send notifications from the backend using Firebase. Have a look at this great package for some guidance on how that can be done:
https://firebase-php.readthedocs.io/en/latest/cloud-messaging.html
first of all you get devicetoken from firebase and then send notification from application using this below code.
public class UtilsFcm {
static OkHttpClient mClient;
static Context context;
static JSONArray jsonArray;
public static void sendNotification(final Context context1, final JSONArray jsonArray1) {
mClient = new OkHttpClient();
context = context1;
jsonArray = jsonArray1;
new MyTask().execute();
}
static class MyTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
try {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject root = new JSONObject();
JSONObject notification = new JSONObject();
notification.put("text", "Your notification message");
notification.put("title", "App Title");
notification.put("line1", R.mipmap.ic_launcher);
notification.put("line2", "high");
root.put("to", jsonArray.get(i));
root.put("data", notification);
String result = postToFCM(root.toString());
Log.d("Main Activity", "Result: " + result);
return result;
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
if (result != null) {
try {
JSONObject resultJson = new JSONObject(result);
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(context, "" + e.toString(), Toast.LENGTH_SHORT).show();
}
}
}
}
static String postToFCM(String bodyString) throws IOException {
final String FCM_MESSAGE_URL = "https://fcm.googleapis.com/fcm/send";
final MediaType JSON
= MediaType.parse("application/json");
RequestBody body = RequestBody.create(JSON, bodyString);
Request request = new Request.Builder()
.url(FCM_MESSAGE_URL)
.post(body)
.addHeader("Authorization", "key=" + "firebase_web_api_key")
.build();
Response response = mClient.newCall(request).execute();
return response.body().string();
}
}
and then you call this method like this.
UtilsFcm.sendNotification(this,jsonArray);
here jsonarray have all device token.
hope this will help you.

Parsing JSON data from an HTTP connection

I'm trying to get the value for the key 'GBP' in the following link: https://api.fixer.io/latest
I've managed to connect to the API successfully and I'm able to cycle through the keys until I get "rates". Inside rates though, I don't know how I cycle through all the currencies until I find 'GBP'.
Note: I'm paring the Json - I'm struggling to parse a Json object that has a Json within it. It's different to the duplicates you've referenced.
My code so far looks like this:
String urlStr = "https://api.fixer.io/latest";
AsyncTask.execute(new Runnable() {
#Override
public void run() {
// Create URL
URL url = null;
try {
url = new URL(urlStr);
} catch (MalformedURLException e) {
e.printStackTrace();
}
// Create connection
try {
HttpURLConnection myConnection =
(HttpURLConnection) url.openConnection();
if (myConnection.getResponseCode() == 200) {
InputStream responseBody = myConnection.getInputStream();
InputStreamReader responseBodyReader =
new InputStreamReader(responseBody, "UTF-8");
JsonReader jsonReader = new JsonReader(responseBodyReader);
jsonReader.beginObject(); // Start processing the JSON object
while (jsonReader.hasNext()) { // Loop through all keys
String key = jsonReader.nextName(); // Fetch the next key
if (key.equals("rates")) { // Check if desired key
// Fetch the value as a String
String value = jsonReader.nextString();
//currentCurrency = value;
break; // Break out of the loop
} else {
jsonReader.skipValue(); // Skip values of other keys
}
}
} else {
// Error handling code goes here
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
Try this
JSONObject jsonObject = new JSONObject(" your json response ");
Iterator iteratorObj = jsonObject.keys();
while (iteratorObj.hasNext())
{
String JsonObjRates = (String)iteratorObj.next();
if (JsonObjRates.equals("rates")) {
JSONObject jo_rates = jsonObject.getJSONObject(JsonObjRates);
Iterator<String> keys = jo_rates.keys();
while (keys.hasNext())
{
String key = keys.next();
String value = jo_rates.getString(key);
Log.i("RATES key", key);
Log.i("RATES value", value);
if(key.equals("GBP"))
{
Log.i("GBP RATES key", key);
Log.i("GBP RATES value", value);
}
}
}
}
Output
Instead of Using manual parsing used below things.
Please Use RoboPojo Generator into Android Studio it will helps you to create model class for you and directly setData to your model class.
if you are using Gson to setData.
Below ilink is helping to you :
https://github.com/robohorse/RoboPOJOGenerator
hope this helps you.
You can use Volleylibrary to make request that url and you will take response.
after take response via related url, you can parse it on Android Studio.
dependencies {
...
compile 'com.android.volley:volley:1.1.0'
}
above will be added in dependencies.
below will be added in your Activity(like MainActivity).
String url ="https://api.fixer.io/latest";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
JSONObject resultJSON=new JSONObject(response);
JSONObject rates=resultJSON.getJSONObject("rates");
string GPB=rates.getString("GPB");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
mTextView.setText("That didn't work!");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
I guess it will work. make feedback whether it works or not.
Try this.
You have to loop through jsonobject so first create class for rates.
public Rates readRates(JsonReader reader) throws IOException {
String country_rate = null;
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
if (name.equals("GBP")) {
country_rate = reader.nextString();
} else {
reader.skipValue();
}
}
reader.endObject();
return new Rates(country_rate);
}
Decalre your class at start of this http method
Rates rate = null;
Replace this Code
if (key.equals("rates")) { // Check if desired key
// Fetch the value as a String
String value = jsonReader.nextString();
//currentCurrency = value;
break; // Break out of the loop
} else {
jsonReader.skipValue(); // Skip values of other keys
}
With this
if (key.equals("rates"))
{
rate = readRates(jsonReader);
String rate_value = rate.country_rate;
}
else
{
jsonReader.skipValue(); // Skip values of other keys
}
For more details https://developer.android.com/reference/android/util/JsonReader.html
Hope it helps.!

how to get from MySQL data to android with json

I was tried to get data from MySQL PHP to Android with JSON Object but not work with me. I was searching about my problem but the examples I found didn't help me.
I have an array list of strings, then I set the strings MySQL DB.
After that, I want to get the cities strings from the DB with JSON, but I was unsuccessful.
My questions are:
How can I make sure that if I have city, it won't appear again?
How can I set the cities in an array list in Android?
My PHP code:
<?php
include 'connection/connection.php';
$noResult = "no results";
// to set the names at the list view
$sql = "SELECT workrCity FROM workersTable ";
$result = $connect->query($sql);
if ($result->num_rows > 0){
while($row[] = $result->fetch_assoc()) {
$json = json_encode($row,JSON_UNESCAPED_UNICODE);
}
} else {
echo $noResult;
}
echo $json;
$connect->close();
?>
the array list function in my Fragment working good :
private ArrayList<City> initCities() {
Log.d(TAG, "ArrayList_CitiesFragment_initCities");
String[] cityName = {"","","",""}; // the cities names
ArrayList<City> theCities = new ArrayList<>();
for (String aCityName : cityName) {
City city = new City(aCityName, false);
theCities.add(city);
}
return theCities;
}
Now I want to get the cities names from MySQL in a JSON-like output:
handler = new Handler(Looper.getMainLooper());
Thread runner = new Thread(new Runnable() {
#Override
public void run() {
Log.d(TAG, " runner");
GetCitiesJson getCitiesJson = new GetCitiesJson();
try{
String[] res = getCitiesJson.getCitiesDataFromDB();
JSONObject jsonObject = new JSONObject(String.valueOf(res));
JSONObject workrCity = jsonObject.getJSONObject("workrCity");
Activity activity = getActivity();
Toast.makeText(activity,"its :" + workrCity, Toast.LENGTH_SHORT).show();
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
});
runner.start();
I know that my code is not correct, but I don't know what's missing...
Hi: Im using Volley library to get a Json file from my server and works fine and fast.
In app/build.gradle under dependencies:
compile 'com.android.volley:volley:1.0.0'
Then, in the activity you want to get the json data:
String from = "http://www.yourserver.com/file.json";
StringRequest request = new StringRequest(from, new Response.Listener<String>() {
#Override
public void onResponse(String string) {
try {
parseJson(URLDecoder.decode(URLEncoder.encode(string, "iso8859-1"),"UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
// Error
Log.d("ERROR:", String.valueOf(volleyError));
}
});
Volley.newRequestQueue(this).add(request);
Then you can parse the Json:
public static void parseJson(String jsonString) {
try {
JSONObject object = new JSONObject(jsonString);
getMessage(this, object);
} catch (JSONException e) {
e.printStackTrace();
}
}
And finally you can get the strings inside your Json:
public static void getMessage(JSONObject object){
if(object.length() != 0) {
try {
message = String.valueOf(object.get("message"));
} catch (JSONException e) {
e.printStackTrace();
}
} }
Okay i was copy the code. but have one problem.that the message = String.valueOf(object.get("message")); where is the var named message? it's on red colo
message is a String:String message; Then in your Json, you need a node called message to get it.

Update Chat Every second

I am making an chat application while implementing it i need to update the messages automatically for this i am using asyntacks. For this i am having doubt that every time we cant able to refresh through asyntaks option. So, is there any way or any other method to refresh the chat activity for every second.
Chat.java
public class chatclass extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
String receiverid = getIntent().getStringExtra("Rid");
try {
URL url = new URL("" + Constant.cht);
Map<String, Object> paramm = new LinkedHashMap<>();
paramm.put("sid", "" + Session.getUserID(getApplicationContext()));
paramm.put("rid", "" + receiverid);
StringBuilder postData = new StringBuilder();
for (Map.Entry<String, Object> param : paramm.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
String urlParameters = postData.toString();
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(urlParameters);
writer.flush();
String result = "";
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
while ((line = reader.readLine()) != null) {
result += line;
}
writer.close();
reader.close();
JSONObject response = new JSONObject(result);
JSONArray array = response.getJSONArray("data");
chatslistdata.clear();
for (int i = 0; i < array.length(); i++) {
JSONObject chatobj = array.getJSONObject(i);
ChatBeanData chatBeanData = new ChatBeanData();
chatBeanData.setChat_id(chatobj.getString("chat_id"));
chatBeanData.setRid(chatobj.getString("rid"));
chatBeanData.setReciever_name(chatobj.getString("reciever_name"));
chatBeanData.setReciever_image(chatobj.getString("reciever_image"));
chatBeanData.setSid(chatobj.getString("sid"));
chatBeanData.setSender_name(chatobj.getString("sender_name"));
chatBeanData.setSender_image(chatobj.getString("sender_image"));
chatBeanData.setMessage(chatobj.getString("message"));
chatBeanData.setSeen_status(chatobj.getInt("seen_status"));
chatBeanData.setTime(chatobj.getString("time"));
chatslistdata.add(chatBeanData);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
chatadapter = new ChatAdapter(ChatsPage.this, chatslistdata);
LinearLayoutManager mychatmanager = new LinearLayoutManager(ChatsPage.this, LinearLayoutManager.VERTICAL, false);
mychatmanager.setStackFromEnd(true);
chatlist.setLayoutManager(mychatmanager);
chatlist.setAdapter(chatadapter);
chatclass chatclass = new chatclass();
chatclass.execute();
}
}
It's really bad idea to refresh your chat every seconds because you lose a lot of server efficiency. You should do It like this:
Download all messages from server,
Download all messages with greater ID than last one message has (for example with long-polling or polling),
If there is any message, update list.
Or use Soket.io for example, or weboskect.
Then:
Create connection with server,
Download all messages,
Then server should send information if you will have new message,
If you receive this information, download messages with greater ID than last one message has.
I thing, it is good idea for chat. Here you have demo of chat on socket.io
Have fun
It is not really good approach to refresh your chat every second to retrieve messages.
This might overload your server with excessive requests which can be avoided.
To achieve real-time chat your server should send information if you have received any new messages.
On client-side you need to set a listener for that purpose. Once the listener is triggered, you can download the new messages.
Check ConnectyCube Android implementation as an example:
IncomingMessagesManager incomingMessagesManager = chatService.getIncomingMessagesManager();
incomingMessagesManager.addDialogMessageListener(new ChatDialogMessageListener() {
#Override
public void processMessage(String dialogId, ConnectycubeChatMessage message, Integer senderId) {
}
#Override
public void processError(String dialogId, ChatException exception, ConnectycubeChatMessage message, Integer senderId) {
}
});

Categories

Resources