BufferedReader does not work in Android - android

I have tried to use an instance of BufferReader to read a content of a web page but when running the app, it moves immediately to catch block when reaching this line:
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
Could you please tell me what is the problem?
By the way, I have made a permmition to Internet connection in the mainifest file and there is no error registered in the Log cat!
this is my java code:
Thread thrd = new Thread( new Runnable() {
#Override
public void run() {
final Button btn = (Button) findViewById(R.id.btn_1);
final TextView tv = (TextView) findViewById(R.id.tv_1);
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
URL url = null;
url = new URL("http://www.google.com/");
URLConnection conn = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String Line = "";
while( (Line= reader.readLine() ) != null){
tv.append(Line);
}
catch (Exception e){
tv.append("There is a problem");
}
}
});
}
});
thrd.start();
return true;
}

have you tried logging the exception? something along the lines of
Log.d(TAG, "onClick", e);
in your catch block.
With that said, you are probably getting a NetworkOnMainThreadException, because you are trying to access the network on the main thread. Because network calls are blocking, this will cause the UI to freeze - which is a very bad User Experience. All network calls should be done in a separate thread (be that a Service, AsyncTask, or a Thread).
see this SO answer for more information about the NetworkOnMainThreadException

Related

HttpURLConnection crashes application

I want to receive and send data with a web server but the code does not work
What do I do for this code to work?
Note this code inside onCreate
try {
URL url = new URL("http://myweb.com/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream Stream = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(Stream);
BufferedReader b = new BufferedReader(reader);
StringBuilder s = new StringBuilder();
String str ="";
while ((str = b.readLine())!=null) {
s.append(str);
}
String data = s.toString();
TextView myText = (TextView) findViewById(R.id.Text);
myText.setText(data);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Make sure that you do network-related tasks on a separate thread in Android. Also, check that you have the INTERNET permission set.
If you want to then update the UI from another thread, you have to use
runOnUiThread (new Runnable () {
public void run() {
//update ui in here
}
}
All your code runs in Main thread which should be always used for setting up the UI and to listen for UI events such as on click listeners.
Network calls are not allowed on this thread as they might take long time. Use AsyncTask API of android which is designed for running code in separate thread.
Create a class like one below for all GET request tasks.
public class DownloadTask extends AsyncTask<String, Void, Integer> {
private String TAG = "InDownloadTask";
private DownloadCallback callback;
private String data;
public DownloadTask(DownloadCallback cb){
callback = cb;
}
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
HttpURLConnection urlConnection;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
data = response.toString();
result = 1;
} else {
result = 0;
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return result;
}
#Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
callback.onFinishDownload(data, integer);
}
}
Create a callback interface that we use for the above class.
public interface DownloadCallback {
public void onFinishDownload(String data, Integer result);
}
Now from your activity onCreate
String url = "http://myweb.com/";
new DownloadTask(new DownloadCallback() {
public void onFinishDownload(String data, Integer result) {
if(result == 1)
myText.setText(data);
else
myText.setText("Error");
}
}).execute(url);
If you have many network related operations, use a Network library such as Volley which will take care of this.

NetworkOnMainThread error still

I am experimenting with firebase and want to read a textfile from the bucket. I can copy the file to local disk, which works fine. Now I want to read the textfile and copy the contents to an arraylist. This time I get the NetworkOnMainThread although I start a new thread to do the work. At least I think I am.I read about using Asynchtask, but would like to know WHY this is not working as expected. The code to get the InputstreamfromURL worked fine in the past.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download);
downloadtext = (TextView) findViewById(R.id.downloadtext);
text = new ArrayList<>();
listViewText = (ListView) findViewById(R.id.listViewtext);
listViewText.setAdapter(new ArrayAdapter(getApplicationContext(), android.R.layout.simple_list_item_1, text));
Thread thread= new Thread(){
public void run() {
storage = FirebaseStorage.getInstance();
storageRef = storage.getReferenceFromUrl("gs://fir-test-68815.appspot.com");
filename = "testfile.txt";
StorageReference file = storageRef.child(filename);
file.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Log.d(MainActivity.TAG, "URL =" + uri.toString());
try {
InputStream is = getInputStreamFromURL(uri);
text = getText(is);
textReady.post(new Runnable() {
#Override
public void run() {
((ArrayAdapter)listViewText.getAdapter()).notifyDataSetChanged();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
private ArrayList<String> getText(InputStream is) throws IOException {
ArrayList<String> text = new ArrayList<>();
BufferedReader reader = null;
reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
text.add(line);
}
return text;
}
private InputStream getInputStreamFromURL(Uri urlToGet) throws IOException {
InputStream is = null;
URL downloadURL = new URL(urlToGet.toString());
HttpURLConnection conn = (HttpURLConnection) downloadURL.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
// Starts the query
conn.connect();
// next two lines produce the error
int response = conn.getResponseCode();
is = conn.getInputStream();
return is;
}
};
thread.start();
textReady = new Handler();
}
Firebase event callbacks are by default invoked on the main UI thread. That also happens with your OnSuccessListener.
There are also other ways to download files with Firebase. But if you still want to use getDownloadUrl(), you'll need to implement the downloading on a separate thread (for example using AsyncTask) after getDownloadUrl() callback fires.

HTTP POST REQUEST To PHP Server Android Studio

public class MainActivity extends AppCompatActivity {
EditText editmsg , editmail ;
TextView content ;
String Message , Email ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editmsg = (EditText) findViewById(R.id.editMessage);
editmail = (EditText) findViewById(R.id.editMail);
Button btnsubmit = (Button) findViewById(R.id.btnSubmit);
btnsubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
GetText();
} catch (Exception ex) {
content.setText(" Url Exception!");
}
}
});
}
public void GetText()throws UnsupportedEncodingException {
Message = editmsg.getText().toString();
Email = editmail.getText().toString();
String data = URLEncoder.encode("message", "UTF-8")
+ "=" + URLEncoder.encode(Message, "UTF-8");
data += "&" + URLEncoder.encode("email", "UTF-8") + "="
+ URLEncoder.encode(Email, "UTF-8");
String text = "";
BufferedReader reader=null;
HttpURLConnection urlConnection = null;
try
{
// Defined URL where to send data
URL url = new URL("http://nitesh.com/feedback/add.php");
// Send POST data request
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(urlConnection.getOutputStream());
wr.write( data );
wr.flush();
// Get the server response
reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
// Read Server Response
while((line = reader.readLine()) != null)
{
// Append server response in string
sb.append(line + "\n");
}
text = sb.toString();
}
catch(Exception ex)
{
}
finally
{
try
{
reader.close();
}
catch(Exception ex) {}
}
// Show response on activity
content.setText( text );
}
}
I dont know what is wrong with code when i click the send button it showing Unfortunately,HTTP has stop (looking just like app crashed).
please review my code and tell me what i have done wrong.
One thing I see at once is that you are making your request in main UI thread (in onCreate). This is not allowed because network connections usually take some time to finish. There should also be an error message in the logcat about this.
What you should do is make your request in a separate thread. You can accomplish this by using AsyncTask, or Thread. Google it.
UPD:
Example on how to use Threads in Java. The method run will be executed asynchronously.
new Thread(new Runnable(){
#Override
public void run(){
GetText();
}
}).start();
Next time, please include the logcat errors in the question.
Consider using http://square.github.io/retrofit/ for network communication.
You will get a simple api and all request will be wrapped into correct thread.
You can accomplish this task by using AsyncTask

Android AsyncTask send/read data using Socket

I'm working on a test project, something like a basic chat program using wi-fi connection.
I'm creating sockets to connect two different devices, but my problem is that when I send the first message, it's showing in the other device. But if I try to send again, I can see in the logs from the first one, that the message is sent, but it never shows up in the second device.
I've tried to implement the reading of the received data in another thread..or in Async Task, but the problem is still there. Here are both ways of my implementation :
Single Thread :
public void listenForSocket(){
thread = new Thread(new Runnable() {
public void run() {
Log.e("READDATAFROMSOCKET","READDATAFROMSOCKET");
try {
// sets the service running state to true so we can get it's state from other classes and functions.
serverSocket = new ServerSocket(DNSUtils.port);
client = serverSocket.accept();
client.setKeepAlive(true);
InputStream is = client.getInputStream();
Log.d("","is Size : "+is.available());
BufferedReader in = new BufferedReader(new InputStreamReader(is));
int readed = in.read();
Log.d("","readed bytes : "+readed);
String line = "";
while ((line = in.readLine()) != null) {
Log.i("","line : "+line);
changeText(line);
}
//client.close();
//serverSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
}
And here is AsyncTask :
class ServerTask extends AsyncTask<Void, Void, Void>{
private String line = "";
#Override
protected Void doInBackground(Void... params) {
try {
Log.e("ASYNCTASK","ASYNCTASK");
// sets the service running state to true so we can get it's state from other classes and functions.
serverSocket = new ServerSocket(DNSUtils.port);
client = serverSocket.accept();
client.setKeepAlive(true);
InputStream is = client.getInputStream();
Log.d("","is Size : "+is.available());
BufferedReader in = new BufferedReader(new InputStreamReader(is));
int readed = in.read();
Log.d("","readed bytes : "+readed);
while ((line = in.readLine()) != null) {
Log.i("","line : "+line);
}
//client.close();
//serverSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
changeText(line);
}
}
changeText(String); -
private void changeText(final String line) {
runOnUiThread(new Runnable() {
#Override
public void run() {
LinearLayout.LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.RIGHT;
TextView sendMsg = new TextView(MainActivity.this);
sendMsg.setText(DNSUtils.clientName+" : "+line);
sendMsg.setTextColor(Color.DKGRAY);
sendMsg.setTextSize(18);
layout.addView(sendMsg, params);
}
});
}
Any ideas how to fix this issue?
And another problem is that when I am reading the received data, the first letter of the sent string never shows. It always starts from the second letter.
Thanks in advance.
If i were you i will try to implement serverSocket = new ServerSocket(DNSUtils.port); only once with new; not in every thread.

how to handle NetworkOnMainThreadException while reading text from a file which is present on server

i am geting NetworkOnMainThreadException while i am trying to read the text from a .txt file which is present on server how can i solve this problem
thanks in advance.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv= new TextView(this);
TextView tv2 = new TextView(this);
StringBuilder content = new StringBuilder();
try {
URL url = new URL("http://linktomywebsite/textfile.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String str;
while ((str = in.readLine()) != null) {
content.append(str +"\n");
tv.setText(content);
}
in.close();
} catch (MalformedURLException e){
} catch (IOException e) {
e.printStackTrace();
}
catch (NetworkOnMainThreadException e){
tv2.setText("not connecting to server");
setContentView(tv2);
}
};
}
Network operations are forbidden on ui thread since api 11 . You can use AsyncTask, requesting string in doInBackground and showing results in onPostExecute
cearte a new thread and do heavy operation like getting the data from that......
ans use handler or Async Task to update the result on UI
as in this
http://www.vogella.com/articles/AndroidPerformance/article.html
One solution is to permit Network operation(Though it is not advisable to do so). Add this below onCreate().
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

Categories

Resources