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.
Related
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
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.
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());
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.
I have this code for an Android application I'm trying to create into interact with my PHP website. I have the android.permission.INTERNET permission activated and it keeps creating a toast that says "ERROR." instead of the contents of the website. Here is my only java file:
package com.http.request;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
public class HttprequestActivity extends Activity {
/** Called when the activity is first created. */
private String doHTTPRequest(String url){
String results = "ERROR";
try
{
HttpClient hc = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
HttpResponse rp = hc.execute(post);
if(rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
results = EntityUtils.toString(rp.getEntity());
}
}catch(IOException e){
e.printStackTrace();
}
return results;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String results = doHTTPRequest("http://www.yahoo.com");
Toast.makeText(getApplicationContext(), results, Toast.LENGTH_LONG).show();
}
}
I would check to make sure that,
If there is an exception being thrown, investigate what is causing the IOException
Your server could potentially be returning a non-200 response code.
Put in some breakpoints and see whats happening there. My bet is on the response code.
That is your own "ERROR" string which the Toast() displays. Better change
catch(IOException e){
e.printStackTrace();
}
to
catch(IOException e){
result = "ERROR IOException";
e.printStackTrace();
}
The exception is thrown as you try to connect in the main thread which is not permitted. Put doHTTPRequest() in a thread or AsyncTask.
What is your stacktrace says, LogCat? What is the error? Add more info, make it more clear to understand than "guessing of coffee beans"
My guess is: this happens because you are trying to do network operation in UI thread which is not allowed in 3.0+ versions.
http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html