I'm trying to send date from an Android app as the client side to a NetBeans app on the desktop as the server side, the connection works just fine, even sending data but that was before i updated my Android IDE to the version 3!
Now, when i try sending data i get the following exception :
android.os.NetworkOnMainThreadException
Now i saw a post here is Stackoverflow... this one, and i got that because sending the data is happening on the main thread, but i'm not using the main thread to send the data, and i'm still getting this error every time i try to send data.
Code Explanation : I have two methods that sends data, one to send data only once after the connection has been made, and the second once is to send data at any time, now my fist one is on the main thread, but the second one is on another thread, the exception well never occur on the first one, but it will always occur on the second one, i heard that one solution is to use AsyncTask and i'v used it on the second one, and now i get the excpention most of the time but not always.
Here is my code for better understanding :
This is the first method that runs only once and on the main thread, and it will always work :
private void SendInformation(){
try{
OutPut = new BufferedWriter(new OutputStreamWriter(ConnectionSocket.getOutputStream(), "UTF-8"));
OutPut.write(android.os.Build.MODEL);
OutPut.newLine();
OutPut.flush();
}catch(Exception e){
e.printStackTrace();
}
}
This is my second one with a thread, and this always give the exception :
public static void SendDetails(String S1, String S2){
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
public void run(){
try{
OutPut = new BufferedWriter(new OutputStreamWriter(ConnectionSocket.getOutputStream(), "UTF-8"));
OutPut.write(S1 + "," + S2);
OutPut.newLine();
OutPut.flush();
}catch(Exception e){
e.printStackTrace();
MainActivity.ErrorMessage.setText(e.toString());
}
}
}, Delay * 1000);
}
And this is the same second once but using AsyncTask :
private static SendInfoTask SIT = new SendInfoTask();
public static void SendDetails(String S1, String S2){
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
public void run(){
SIT.execute();
}
}, Delay * 1000);
}
static class SendInfoTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
try{
OutPut = new BufferedWriter(new OutputStreamWriter(ConnectionSocket.getOutputStream(), "UTF-8"));
OutPut.write(Client.AppName + "," + Client.NotificationText);
OutPut.newLine();
OutPut.flush();
}catch(Exception e){
e.printStackTrace();
MainActivity.ErrorMessage.setText(e.toString());
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
}
Sometimes it works and some times it does not, and when it does work, after trying to send like 5 time the whole application Crashes!!
Can someone please help me? What is the best practice to do what i'm trying to do? (appreciate any help)
Related
Im attempting to read a text file from my onedrive, I need to check the version of the database and update if necessary.
This is an example of my code:
private void checkVersion() {
try {
int dbversion = prefs.getInt("dbversion", 1);
int dblastversion;
URL url = new URL("");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
str = in.readLine();
in.close();
System.out.println(str);
dblastversion = Integer.valueOf(str);
if (dbversion < dblastversion)
System.out.println("updates available");
} catch (IOException e) {
e.printStackTrace();
}
}
When I try to run the app crash and I got this error from logcat:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ex.example/com.ex.example.ActMenu}: android.os.NetworkOnMainThreadException
On this line
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
Somebody know what is the problem? Or its better use another cloud to stor the textfile. Thanks for the help.
UPDATE 2
Ok as GPRathour said I updated my code to this:
class Getversion_Async extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... arg0) {
System.out.println("starting");
try {
URL url = new URL("https://onedrive.live.com/redir?resid=b9186f8cb138a030!56556&authkey=!AFmrzOGv_OMArzo&ithint=file%2ctxt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
str = in.readLine();
in.close();
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(final Void unused) {
System.out.println("ended");
}
}
And I call in th onCreate like this to test:
new Getversion_Async().execute();
Ok this code runs fine I use a site to host the file and the link ends with .txt and works fine but I cant edit the file. Somebody know how I can do this with onedrive?
The exception clearly says android.os.NetworkOnMainThreadException. To read file from server you need to perform some Network operation and it is not a good practice to perform it on Main Thread / UI Thread as it will hang the UI till the operation is performed.
What you need to do is, run this in AsyncTask
class LogoutUser_Async extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... arg0) {
// Do your network task here
return null;
}
#Override
protected void onPostExecute(final Void unused) {
// Process the result
}
}
For my activities to work, I have to get data from the internet.
I implemented threads, but I am not that good with Java or threads yet, so I kinda rushed through it just hoping it would work. Well it works, but the UI feels slow sometimes because it takes awhile until the activity appears.
Here is my code
an activity, lets call it MainActivity calls:
JSONObject Data = WebApi.getData(id);
the class WebApi pieces the url together:
public static JSONObject getData(String id) {
String url = URL;
url += DATA_URL;
url += VALUE_DATA_ID + id;
return WebInterface.executeWeb(url);
}
and hands it over to WebInterface, in WebInterface the whole thing gets executed:
public static String getUrl(final String url) {
final StringBuilder sb = new StringBuilder();
Thread thread = new Thread(new Runnable() {
public void run()
{
try
{
InputStream is = (InputStream) new URL(url).getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String result, line = reader.readLine();
result = line;
while((line=reader.readLine())!=null){
result+=line;
}
sb.append(result);
} catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
}
});
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String result = sb.toString();
Log.d(App.TAG, result);
return result;
}
public static JSONObject executeWeb(final String url) {
String result = WebInterface.getUrl(url);
JSONObject json = null;
try {
json = new JSONObject(result.trim());
} catch (JSONException e) {
try {
json = new JSONObject("{}");
} catch (JSONException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return json;
}
well this works but i feel like this would work even better, if I would implement it with ASyncTask. My Activity could show some cached data until the "real" data appears. Would that be possible with AsyncTask? And would I need to redo a lot of my code for that?
thanks in advance for the help!
Edit:
thanks to whoever suggested AsyncTaskLoader (i think that one deleted his answer)
I did it with AsyncTaskLoader, very handy and very easy!
In effect your code is single threaded because of thread.join(). The current thread just waits for the newly spawned thread to finish. You have in effect not removed the network from the main thread, hence the UI "locks up" or feels slow.
You could have a callback that runs on the main thread when your thread is finished, but AsyncTask does this for you, and allows you to update a progress bar properly if desired. Read the documentation on how to implement AsyncTask.
svenoaks is correct that your use of thread.join() is making your code effectively single threaded. His solution of using an AsyncTask is also correct.
An alternative approach is to use a Handler in conjunction with the threads you already have. Create the Handler on your main thread, then in the spawned thread obtain() a new message and use the handler to send it. You then have code in the handler (which executes on the main thread) that receives the message and updates the UI.
Without seeing more of your code I can't be sure what it is you want to do with the data, but I can give you a basic example of how to use an AsyncTask. First you won't need any of that Thread stuff in getUrl(), so lets get rid of it. getUrl() should look something like this:
public static String getUrl(String url) {
final StringBuilder sb = new StringBuilder();
try
{
InputStream is = (InputStream) new URL(url).getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String result, line = reader.readLine();
result = line;
while((line=reader.readLine())!=null){
result+=line;
}
sb.append(result);
} catch (Exception e)
{
// TODO: handle exception
e.printStackTrace();
}
String result = sb.toString();
return result;
}
Next lets wrap your call to WebApi.getData in an AsyncTask, so that it runs in the background.
new AsyncTask<Void, Void, JSONObject>(){
#Override
protected JSONObject doInBackground(Void... params) {
JSONObject data = WebApi.getData(id);
return data;
}
#Override
protected void onPostExecute(JSONObject result){
//here you can do something with result
}
}.execute();
AsynTask will execute whatever code is in doInBackground() in a background thread, and then return the result to onPostExecute(), which will be run on the UI thread. Please note id will have to be declared final in the example I gave above.
As has already been said, you should probably read the documentation on AsyncTask.
I'm new in java, and im trying to read a text file from the web into a variable, but i'm getting the text file's url, instead of the content, and just can't figure out what could be the problem.
The class where i'm trying to read the file:
public class readtextfile extends AsyncTask<String, Integer, String>{
private TextView description;
public readtextfile(TextView descriptiontext){
this.description = descriptiontext;
}
#Override
protected String doInBackground(String... params) {
URL url = null;
String result ="";
try {
url = new URL("http://example.com/description1.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String line = null;
while ((line = in.readLine()) != null) {
result+=line;
}
in.close();
}
catch (MalformedURLException e) {e.printStackTrace();}
catch (IOException e) {e.printStackTrace();}
return result;
}
protected void onProgressUpdate() {
//called when the background task makes any progress
}
protected void onPreExecute() {
//called before doInBackground() is started
}
#Override
protected void onPostExecute(String result) {
this.description.setText(result);
}
}
The Activity where i call the class:
public class PhotosActivity extends Activity {
TextView description;
String descriptiontext;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.photos_layout);
description = ((TextView)findViewById(R.id.description1));
new readtextfile(description).execute();
}
}
Try url.openConnection and the use connection object to get inputStream. The updated method would be like
protected String doInBackground(String... params) {
URL url = null;
String result = "";
try {
url = new URL("http://www.example.com/description1.txt");
URLConnection connection = url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
result += line;
}
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
Update based on your comment.
You need not invoke the postExecute method. If you invoke postExecute it just execute that method. The doInBackground wont get exeuted. Instead you should use the execute method. Just like java thread.start() method invoke the overridden run() method.
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
refer developer doc
Try using Scanner like this.
URL url = new URL("http://www.example.com/description1.txt");
Scanner s = new Scanner(url.openStream());
First of all i am fairly new to this i have server/client socket in action and the server is sending/receiving data but my client at the moment is only sending data in a try/catch block and i need to write a another method to just catch the incoming data?
and to keep it outside my original try/ctach*
Any help would be great
public void onClick(View v)
{
setMyIp(ipaddress.getText().toString());
// myComs.sending_data(getMyIp() , "Got connected");
try
{
InetAddress inet = InetAddress.getByName(getMyIp());
Socket s = new Socket(inet, 2000);
OutputStream o = s.getOutputStream();
PrintWriter p = new PrintWriter(o);
InputStream in = s.getInputStream();
p.println("You are connected");
p.flush();
readContacts();
//inboxConversations();
//outboxConversations();
readSms();
}
catch (UnknownHostException e)
{
ipaddress.setText("Unknown host");
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
This is my code and i need to create a separate listener outside of the button any idea
Thank you
you'll have to keep the socket opened in a loop constantly listening for any data to write. Do this on a seperate thread/process of course. Actually both server and client side should be on a seperate thread in my opinion. You can look up java NIO, but here is some code JUST TO GET YOU STARTED, as android has a class that can do things in the background and update the main UI afterwards its called ASYNCHTASK. you can spawn a thread in other ways of course just showing you a convenient way:
(note i havent ran this i just wrote it how i would do it so it take it as pseudo code)
class ClientTask extends AsyncTask<Void, Void, Void> // or whatever you want to pass in
{
public static String ip = "10.0.2.1";
public static int port = 5061;
Socket socket;
public DataInputStream dis;
public DataOutputStream dos;
public String message;
#Override
protected Void doInBackground(Void... params) {
/* set up our socket and open a stream to read */
try {
socket = new Socket(ip, port);
dis = new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (Exception e) {
Log.i("AsyncTank class", "Socket has some trouble opening");
}
/*heres the stuff your looking for to listen to a socket all day long*/
while(socket.isConnected()){
String mymessage=dis.readLine(); //readline blocks
/* do something with your message */
publishProgress(mymessage); //publishes update to main UI thread
}
}
}
return null;
}
#Override
protected void onProgressUpdate(String... messages) {
Toast.makeText(this, messages,Toast.LENGTH_LONG).show(); //announce updates on incoming socket
}
}
-------- if you dont need to update the main UI after the sockets closed for any reason just do the same thing but use a runnable or Thread class to create and listen.
If you need a client to act as a receiver you have run a thread for this asynchronous behaviour else it will freeze your application if you do it on main thread.
So do the following thing
in your client's main method start a receiver thread
Thread receiver_thread=new Thread(new Reciever());
reciever_thread.start();
Here is the receiver class
public class Receiver implements Runnable
{
public void run()
{
While(true)
{
//check here if there is some data in your input stream so what
//you receive when server sends something to you
//so that's it here do your work with the incoming data
//suggestion make an inner class to your main ui class so that data that comes here can be printed to those ui components.
}
}
}
hope it helps you
I am trying to keep a connection open for a multithreaded server program. When I hit a button, I want it to send a test message to all clients that are connected.
public void run() {
try {
Scanner in = new Scanner(socket.getInputStream());
PrintWriter out = new PrintWriter(socket.getOutputStream());
readUpdate(out, in);
while(true){sendUpdate(out);}
} catch (Exception e) {
e.printStackTrace();
}
}
Uses way to much CPU.
This is my sendUpdate method.
private void sendUpdate(final PrintWriter out) {
new Thread(new Runnable() {
public void run() {
if(Server.send) {
try {
if (Server.command != "idle") {
System.out.println("Sending");
out.println("!msg#" + Server.command);
out.flush();
Server.send = false;
Thread.sleep(100);
}
} catch (Exception ex) {
}
}
}
}).start();
}
If somebody can help me keep the connection open, and ready to send data, I would appreciate it.
If your server can initiate messages and so can your client, you probably want a separate thread reading and writing. One thread makes sense for request-response style communication, where you can block on the next client request, do some server-side processing, respond to the client, and then block again.
But if you need to block on two separate conditions (receiving a message from the client and you clicking the button on the server) then you should have two separate threads. Otherwise, you will find yourself needing to repeatedly wake your thread up to check if either of the conditions are true.
So create two threads, and give one your Scanner (that does the readUpdate logic) and the other your PrintWriter. This is what your output handler could look like:
public class WriteHandler implements Runnable {
private final PrintWriter out;
private final BlockingQueue<String> messageQueue = new LinkedBlockingQueue<String>();
//initialize the above in a constructor;
public void run() {
while(true) {
String nextMessageToWrite = messageQueue.poll();
out.println(nextMessageToWrite);
}
}
public void send(String message) {
messageQueue.add(message);
}
}
This uses a blocking queue, which is a much better concurrency mechanism than a check-sleep loop. Then when the button is clicked, you can just have something like this:
public void actionPerformed() {
for ( WriteHandler handler : handlers ) {
handler.send("PING!");
}
}