How to connect sockets and receive Data? - java

I am new to sockets, I was hoping someone knows how to connect sockets on Android Studio and receive data.
This is the websocket which uses socket.io that I am trying to receive data from: https://ws-api.iextrading.com/1.0/stock/aapl/quote
This is a link to the API which explains the websocket: https://iextrading.com/developer/docs/#websockets
I am trying to get realtime stock data for my app, but I do not know how to connect to the socket then receive the data and my app crashes before it even opens, this is my code so far:
package com.example.android.stocksApp;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class MainActivity extends AppCompatActivity {
private static Socket s;
private static InputStreamReader isr;
private static BufferedReader br;
TextView result;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
result = (TextView)findViewById(R.id.result);
stockData();
}
public void stockData (){
myTask mTask = new myTask();
mTask.execute();
}
class myTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
try {
s = new Socket("https://ws-api.iextrading.com/1.0/stock/aapl/quote", 80);
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String quote = br.readLine();
result.setText(quote);
s.close();
is.close();
isr.close();
br.close();
} catch (IOException e){
e.printStackTrace();
}
return null;
}
}
}

You're trying to connect to a Web service. Web services may return either a XML or JSON. The actual Socket library isn't needed nor used for this. This specific web service returns a JSON, so what you need is a library that is capable of making a GET request to this URL and parse the response. For Android, I recommend using Volley. You can include Volley in your project by adding this line to your build.gradle.
implementation 'com.android.volley:volley:1.0.0'
This question might help you get started.

Related

Continuously send UDP packets in background in Java

I want to send the data like button states, joystick values, etc from my app to a server repeatedly through UDP protocol to control a drone, I searched and tried the infinite while loop approach but it makes my app crash. I do not have much knowledge about working, I just want a Client that sends a string/JSON object continuously in the background as a datagram to defined IP and port. Any code snippets of the client or suggestions are welcome. Thank you.
Currently using Asynctask, but someone told me it's deprecated and not suitable. The code is given below. (reposting)
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import android.annotation.SuppressLint;
import android.os.AsyncTask;
public class UDP_Client {
public String Message;
#SuppressLint({"NewApi", "StaticFieldLeak"})
public void sendUDP() {
AsyncTask<Void, Void, Void> async_cient = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params){
try (DatagramSocket ds = new DatagramSocket()) {
DatagramPacket dp;
dp = new DatagramPacket(Message.getBytes(), Message.length(), InetAddress.getByName("192.168.***.***"), 3000);
ds.setBroadcast(true);
ds.send(dp);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
};
async_cient.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
If you want to run it on background. You need to use service.

Use Infura to run a IPFS node in Java Android

I am trying to connect to an Infura node from Java Android application.
I was following these documents to connect to an infura node.
https://kauri.io/managing-storage-in-a-java-application-with-ipfs/3e8494f4f56f48c4bb77f1f925c6d926/a
https://github.com/ipfs-shipyard/java-ipfs-http-client/issues/115
Code:
package com.example.javahttp;
import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import io.ipfs.api.IPFS;
public class MainActivity extends AppCompatActivity {
IPFS ipfs ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new MyTask().execute();
}
private class MyTask extends AsyncTask<Void , Void, Void > {
#Override
protected Void doInBackground(Void... voids) {
IPFS ipfs = new IPFS("/dnsaddr/ipfs.infura.io/tcp/5001/https");
try{
System.out.println("connected");
System.out.println("id: "+ ipfs.id());
}catch(Exception e){
System.out.println("not connected"+e);
}
return null;
}
}
}
I am getting this error.
java.lang.RuntimeException: IOException contacting IPFS daemon.
Trailer: null ipfs method not allowed
Any suggestions please.
I don't get why there is such an error but when I used a plain java class to connect with it. It was possible ,you may refer here to my repository blockchain with java to see if you have all the relevant dependencies and you have been doing it properly because I am not familiar with android but I am familiar with web3j.
You can use the below code to connect with an infura node and parse a file to it.
import io.ipfs.api.IPFS;
import io.ipfs.api.MerkleNode;
import io.ipfs.api.NamedStreamable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class App {
public static void main(String[] args) throws IOException {
IPFS ipfs = new IPFS("/dnsaddr/ipfs.infura.io/tcp/5001/https");
try {
NamedStreamable.InputStreamWrapper is = new NamedStreamable.InputStreamWrapper(new FileInputStream());
MerkleNode response = ipfs.add(is).get(0);
} catch (IOException ex) {
throw new RuntimeException("Error whilst communicating with the IPFS node", ex);
}
}
}
In case anyone has trouble with this nowadays, the fix to this issue was simply to upgrade to the newest version.
I upgraded from v1.2.3 to v1.3.3 and the issue disappeared.
For maven, pom.xml:
<dependency>
<groupId>com.github.ipfs</groupId>
<artifactId>java-ipfs-http-client</artifactId>
<version>v1.3.3</version>
</dependency>

Carrying and reusing information (json string) from an AsyncTask?

I have created a simple android app with 3 TextViews and then run an AsyncTask Task via a different class the next step would be to carry the information over and make the task reusable.
The Task will consume a String (URL) and the context of the MainActivity.
The Task will make a simple REST Request (GET) and retrieve a json string.
I have then created another class that which gets the json response and creates a .json file saves it to
..../0/Notes/launch.json
The folder "Notes is created by myself via file.mkdirs().
In the MainActivity I created an InputStream to read the .json file saved by the AsyncTask but once I try to open it, it gives me a FileNotFoundException.
Here's the code of my MainActivity.class
package com.example.root.example;
import android.Manifest;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 200);
String url = "https://api.spacexdata.com/v3/launches/upcoming"; //Copy the url and open it in your browser to see the json.
AsyncCall asyncCall = new AsyncCall(getApplicationContext());
asyncCall.myAsyncTask(url);
try {
InputStream inputStream = this.getAssets().open("launch.json");
int size = inputStream.available();
byte[] buffer = new byte[size];
inputStream.read(buffer);
inputStream.close();
String jsonStringFromFile= new String(buffer,"UTF-8");
JSONObject launchObject = new JSONObject(jsonStringFromFile);
System.out.println(launchObject.get("flight_number"));
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
This is the AsyncCall.class (making and retrieving the json etc..)
package com.example.root.example;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class AsyncCall {
FileCreator fileCreator = new FileCreator();
private final Context myContext;
public AsyncCall(final Context context) {
myContext = context;
}
public void myAsyncTask(final String url) {
AsyncTask asyncTask = new AsyncTask() {
#Override
protected Object doInBackground(Object[] objects) {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Response response = null;
try {
response = okHttpClient.newCall(request).execute();
fileCreator.generateFile(myContext, myContext.getString(R.string.fileName), response.body().string());
} catch (IOException ioe) {
ioe.getMessage();
}
return null;
}
}.execute();
}
}
what am I trying to archive? I'm trying to save information (json here) and make it reusable just as the Falcon 9.
The issue lies in carrying information over to a different class.
If there's an alternative solution (other than saving a .json file) to fix this issue then please don't hesitate to post it.
This is just my first issue, the second issue appears once you open the api link and see that there are a few more than just one JSON String (0,1,2,3,4... upcoming missions).
I have no clue in any way to tacle the first let alone the second problem and have started over a few times, a while ago multiple times.
Within your Activity, you can get the JSON like so
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onResponse(Call call, final Response response) throws IOException {
try {
final String responseData = response.body().string();
JSONObject json = new JSONObject(responseData);
String flightNumber = json.getString("flight_number");
// TODO: Load number into a TextView
} catch (JSONException e) {
e.printStackTrace();
}
}
});
Looking at your API response, though, you'll actually need new JSONArray(responseData), and you would have to loop over that to get each individual object's flight number

Android calling page that returns JSON error [duplicate]

This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 9 years ago.
I have a aspx page that I am calling from my android app that is returning JSON text but the java code below breaks here BufferedReader reader = new BufferedReader(new InputStreamReader(jc.getInputStream()));
with this error.
error android.os.NetworkOnMainThreadException
ARe you able to help plesae? Thanks
default.aspx return json
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Response.ContentType = "text/plain";
//Write the message
Response.Write("{'testvar':'testtext'}");
//End the response causing it to be sent
Response.End();
}
}
android java
public void connectWCF() {
try {
URL json = new URL("http://localhost:50851/Default.aspx");
URLConnection jc = json.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(jc.getInputStream()));
String line = reader.readLine();
reader.close();
} catch(Exception e){
}
links where I got the code ideas from
http://wyousuf.wordpress.com/2012/03/01/android-with-wcf-services/
http://matijabozicevic.com/blog/android-development/android-with-wcf-service
You are placing network communication on the main thread. You should use AsyncTask
http://developer.android.com/reference/android/os/AsyncTask.html
here's a nice video that explains JSON Parsing using AsyncTask.
http://www.youtube.com/watch?v=qcotbMLjlA4
For testing ONLY you can add the following in your Main Activity but it is consider bad practice.
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Since android 3.0, you can't put any calls to webpages or similar external resources in the main thread (in other words, any part of the activity) unless you do it with an AsyncTask, in order to avoid apps to look "locked" and unresponsive when waiting for a response from an external datasource. Therefore, you'll need to implement the webservice call with and AsyncTask.
Example class for AsyncTask:
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
public class cargaDatosRest extends AsyncTask<Context, Void, Void> {
private Context c;
private boolean resul = false;
private String control = "";
private String respStrS = "";
public cargaDatosRest(Context C)
{
c = C;
}
public String getStr()
{
return respStrS;
}
public String getControl()
{
return control;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//mProgressDialog.show();
}
#Override
protected Void doInBackground(Context... params) {
HttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet("url");
HttpResponse resp;
get.setHeader("content-type", "application/json");
try
{
/*resp contains the response from the webService. respStr and respJSON allows to read that resp in JSON format. Just delete them if you don't need them. You can asign the values returned by the webservice to local variables in the AsyncTask class and then read them with public methods, like the resul variable.*/
resp = httpClient.execute(getUsuarios);
String respStr = EntityUtils.toString(resp.getEntity());
JSONArray respJSON = new JSONArray(respStr);
this.resul = true;
}
catch(Exception ex)
{
Log.e("ServicioRest","Error!", ex);
this.resul = false;
}
}
public boolean getResul()
{
return this.resul;
}
protected void onProgressUpdate(String... progress) {
Log.d("ANDRO_ASYNC",progress[0]);
//mProgressDialog.setProgress(Integer.parseInt(progress[0]));
}
#Override
protected void onPostExecute(Void unused) {
//mProgressDialog.dismiss();
}
}
//calling the AsyncTask from the activity:
CargaDatosRest CallRest = new CargaDatosRest(this.getApplicationContext());
CallRest.execute();
Log.v("WebService", "Just trying "+arest.getResul());

Using JAVA RMI in Android application

I've read lots of threads about this issue, and i couldnt see a 'real' solution for it.
I made a java project - which is a rmi server and i have an android application which suppose to be also a rmi client.
When i checked if the server works I wasn't wise enough to test the client on an android project and i made a test client on a simple java project.
Now when i'm trying to connect my android application to server i fail because the android project doesn't recognize the java rmi package.
Why that happen? what should I do?
You can also use the following library LipeRMI
Here is an example of a Android client interacting with Java Server via LipeRMI.
Create the Following 2 classes and a interface for Java application.
//TestService.java
package test.common;
public interface TestService {
public String getResponse(String data);
}
//TestServer.java
import java.io.IOException;
import java.net.Socket;
import test.common.TestService;
import lipermi.exception.LipeRMIException;
import lipermi.handler.CallHandler;
import lipermi.net.IServerListener;
import lipermi.net.Server;
public class TestServer implements TestService {
public TestServer() {
try {
CallHandler callHandler = new CallHandler();
callHandler.registerGlobal(TestService.class, this);
Server server = new Server();
server.bind(7777, callHandler);
server.addServerListener(new IServerListener() {
#Override
public void clientDisconnected(Socket socket) {
System.out.println("Client Disconnected: " + socket.getInetAddress());
}
#Override
public void clientConnected(Socket socket) {
System.out.println("Client Connected: " + socket.getInetAddress());
}
});
System.out.println("Server Listening");
} catch (LipeRMIException | IOException e) {
e.printStackTrace();
}
}
#Override
public String getResponse(String data) {
System.out.println("getResponse called");
return "Your data: " + data;
}
}
//TestMain.java
public class TestMain {
public static void main(String[] args) {
TestServer testServer = new TestServer();
}
}
Android client:
//MainActivity.java
package com.example.lipermidemoandroidclient;
import java.io.IOException;
import test.common.TestService;
import lipermi.handler.CallHandler;
import lipermi.net.Client;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Looper;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
private String serverIP = "192.168.1.231";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnGet = (Button) findViewById(R.id.btnGet);
btnGet.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
new Conn().execute();
}
});
}
class Conn extends AsyncTask<Void, Void, MainActivity> {
#Override
protected MainActivity doInBackground(Void... params) {
Looper.prepare();
try {
CallHandler callHandler = new CallHandler();
Client client = new Client(serverIP, 7777, callHandler);
TestService testService = (TestService) client.getGlobal(TestService.class);
String msg = testService.getResponse("qwe");
//Toast.makeText(MainActivity.this, testService.getResponse("abc"), Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
Looper.loop();
return null;
}
}
}
//TestService.java
package test.common;
public interface TestService {
public String getResponse(String data);
}
Add the LipeRMI library to both the projects
Make sure you add INTERNET permission in Android project
Also make sure you have the TestService.java file placed in same package name at both places for eg. test.common package here
Also change value of serverIP variable in Android MainActivity.java to the IP of the machine running the Java code.
I had the same problem and changed my communication to socket communication!
As far as I could figure out Java.rmi unfortunately does not come with Android and therefore it's not possible to use it.
However there are some more disucssions in this post.
Android doesn't support RMI. You should change to socket or raw TCP communication.

Categories