This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 8 years ago.
I know this question has been asked a lot on SO already so I apologize if it is redundant, but I can't seem to find an answer to my specific problem anywhere.
I'm attempting to connect my Android emulator to a localhost. Here is my connection code:
public void readPHP(String filename) throws IOException {
url = new URL("http://10.0.2.2:8000/" + filename);
URLConnection conn = url.openConnection();
InputStream stream = null;
try {
stream = conn.getInputStream();
} catch (IOException e) {
System.out.println(e.getMessage());
}
// more code....
stream.close();
}
I've also added the following line to my manifesto:
<uses-permission android:name="android.permission.INTERNET"/>
The app installs properly with no error messages but when I try to run it from the phone, it crashes with the vague message "Unfortunately, CodeGlass GDK has stopped." I'm sure this is a problem with Android because when I try to run the same code in a simple Java program it works as expected.
You are opening a connection in your UI Thread, which is causing an NetworkOnMainThreadException . Just put your code inside an AsyncTask, inside doInBackground() method, like this:
public class MyAsyncTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(String fileName) {
url = new URL("http://10.0.2.2:8000/" + filename);
URLConnection conn = url.openConnection();
InputStream stream = null;
try {
stream = conn.getInputStream();
} catch (IOException e) {
System.out.println(e.getMessage());
}
// more code....
stream.close();
return null;
}
}
You must use asynctask to get the data from url like they said.
But there is another way. İt is not advisable normally, but if you want to move on for now and get back and properly write an asynctask, you can use this piece of code for now;
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Hope this helps.
Related
I am given a shortened url and I want to get the expanded form. The below java function is used to achieve this.
public String expand(String shortenedUrl){
URL url = null;
try {
url = new URL(shortenedUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
}
// open connection
HttpURLConnection httpURLConnection = null;
try {
httpURLConnection = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
} catch (IOException e) {
e.printStackTrace();
}
// stop following browser redirect
httpURLConnection.setInstanceFollowRedirects(false);
// extract location header containing the actual destination URL
String expandedURL = httpURLConnection.getHeaderField("Location");
httpURLConnection.disconnect();
return expandedURL;
}
The code works fine in Eclipse but the same doesn't work in android.
String expandedURL = httpURLConnection.getHeaderField("Location");
The above line throws java.lang.RuntimeException: Unable to start activity ComponentInfo. And the error is pointed to the above line. If I remove the above line no error is encountered. Even I am not able to use getResponseCode() function.
int status = 0;
try {
status = httpURLConnection.getResponseCode();
} catch (IOException e) {
e.printStackTrace();
}
This piece of code also has the same problem. works in eclipse but not in android.
Any kind of help will be greatly appreciated.
Edit: The code using above function is,
ExpandUrl expandUrl = new ExpandUrl();
String expandedUrl = expandUrl.expand(shortenedUrl);
Note: The function expand is defined inside the class ExpandUrl.
Well, the code works in Eclipse but not in android. The reason is that you are doing it in Main thread and blocking it. Android wouldn't allow you to do so and throw runtime error.
I have tried to implement your code using AsyncTask in android. It works fine.
Give it a try.
To know more about AsyncTask follow: Android Documentation on AsyncTask
Good Luck!
Edit: The thing causing the error was a typo in the url variable declaration. The code provided works, given correct input. See my answer for details.
Original Question: I'm working on an application that regularly sends a GET request to a certain web server.
I have tried and verified the URL and the query in the browser and I get the information in XML format as expected.
The URL/query looks like this:
http://foo.bar.com:8080/bla/ha/get_stuff?param1=gargle¶m2=blurp
I'm trying to get the raw content to my device (Android tablet) and output it to the screen.
However, when calling getInputStream() on my URLConnection object, I get the following exception:
java.net.ProtocolException: Unexpected status line: SSH-2.0-OpenSSH_5.9p1 Debian-5ubuntu1.1
Calling connect() on the same object causes no exception (however other methods, such as getContent(), do).
getContentType() returns null.
I'm using AsyncTask to collect and display the data (displaying works fine).
In the code is also an Authenticator part, but removing it has no change on the exception thrown, so I don't think it's the issue.
Is this because the data is in XML format?
If so, how else should I access it?
Code
class GetPositionTask extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
String url = "http://foo.bar.com/8080/bla/ha/get_stuff";
String charset = "UTF-8";
String param1 = "gargle";
String param2 = "blurp";
try {
String query = String.format("param1=%s¶m2=%s",
URLEncoder.encode(param1, charset),
URLEncoder.encode(param2, charset));
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("userName", "passWord".toCharArray());
}
});
URLConnection urlConnection = new URL(url + "?" + query).openConnection();
urlConnection.setRequestProperty("Accept-Charset", charset);
InputStream response = urlConnection.getInputStream(); //Commenting this out prevents exception
return "Made it through!"; // Never reaches this
}
catch (IOException e) {
e.printStackTrace();
return "Exception in GetPositionTask";
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
TextView textView = (TextView) findViewById(R.id.textView);
textView.setText(s);
}
}
Note: This is similar to a couple of other questions, however I wasn't able to solve my problem reading those.
The cause was a simple type in the url string, which was supposed to be
String url = "http://foo.bar.com:8080/bla/ha/get_stuff";
rather than
String url = "http://foo.bar.com/8080/bla/ha/get_stuff";
Fixing that typo made the whole thing work as a charm.
Interestingly though, when I circumvented the whole concatenation and formatting business by pasting the complete URL/query into the URLconstructor as below, it still worked (even though the URLEncoder#encode calls did switch some :characters out in param2).
URLConnection urlConnection = new URL("http://foo.bar.com:8080/bla/ha/get_stuff?param1=gurgle¶m2=blurp").openConnection();
(in my real case, the param2 variable includes a MAC address, and the :'s were replaced with something of the type %xx)
You're connecting to an SSH server, not an HTTP server.
The reason it doesn't happen on connect() is that connect() doesn't actually connect. The other methods you mention do, if necessary.
I'm trying to write a String to my webpage using Java in Android Studio by reusing some piece of codes of one Java Eclipse project which works well on my PC.
However, the String just cannot be written to the web page using my Android phone.
public void upload(String FTPaddress, String message){
try {
URL url = new URL(FTPaddress); // my server address
URLConnection urlc = url.openConnection();
OutputStream os = (OutputStream) urlc.getOutputStream(); // To upload
OutputStream buffer = new BufferedOutputStream(os);
buffer.write(message.getBytes());
buffer.close();
os.close();
} catch (FileNotFoundException e) {
// print in log
} catch (IOException e) {
// print in log
}
}
Please note that the function is executed, the mobile phone is connected to the internet, thus I am running it on another thread using asyncTask, and there is no exceptions
So can anyone tell me why it worked on my laptop but not for my mobile phone?
My app is crashing unpredictably and I don't understand why. I'm using HttpURLConnection to retrieve a json file and I'm trying to use the JsonReader class to read from, and use that file. The trouble is that the application crashes after reading or doing anything to the instance of JsonReader.
I've read the input stream with scanner but that causes a similar problem. However when reading with the scanner I can print small amounts of json from the server. So the data from the server is probably making it into the JsonReader as well.
This is my code:
public class ConnectToServer implements Runnable {
private URL connectionUrl;
private MainActivity output;
public ConnectToServer(URL url, MainActivity mainActivity) {
connectionUrl = url;
output = mainActivity;
}
public void printError(String errorMessage){
output.output(errorMessage);
}
public InputStream GetInputStream(){
try {
HttpURLConnection connection = (HttpURLConnection)connectionUrl.openConnection();
InputStream inputStream = new BufferedInputStream(connection.getInputStream());
if (inputStream == null){
printError("Input stream is null");
}
return inputStream;
} catch (IOException ex){
printError("IO exception has been thrown");
} catch (Exception ex){
printError("Normal exception thrown: " + ex.getClass().getSimpleName());
}
return null;
}
#Override
public void run() {
InputStream inputStream = GetInputStream();
try {
if (inputStream == null){
printError("Input stream not initiated");
} else {
JsonReader reader = new JsonReader(new InputStreamReader(inputStream, "UTF-8"));
printError(reader.toString());
reader.close();
}
} catch (Exception ex){
printError("Exception while printing input stream: " + ex.getClass().getSimpleName());
}
printError("Thread finished");
}
This gets run on a thread created in the main UI thread.
public void connect(){
output("connect started");
boolean success = true;
try {
URL url = new URL("http://geonews.azurewebsites.net/api/Location");
serverConnection = new ConnectToServer(url,this);
Thread thread = new Thread(serverConnection);
thread.start();
} catch (MalformedURLException ex){
output("Messed up the URL");
success = false;
}
if (success){
output("Thread has been started");
} else {
output("exception was thrown while trying to run thread");
}
}
Does anybody know why this code would be causing my app to crash? Even if it gets to "Thread finished" it will crash soon after.
Btw I realise I should be using AsyncTask but I've already gone down this track and I'd rather get this going first.
Logcat:
06-14 22:45:00.058 4032-4052/com.tomsapps.thomas.jsonreadertestapp E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-314
Process: com.tomsapps.thomas.jsonreadertestapp, PID: 4032
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6247)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:867)
at android.view.View.requestLayout(View.java:17364)
at android.view.View.requestLayout(View.java:17364)
at android.view.View.requestLayout(View.java:17364)
at android.view.View.requestLayout(View.java:17364)
at android.view.View.requestLayout(View.java:17364)
at android.view.View.requestLayout(View.java:17364)
at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
at android.view.View.requestLayout(View.java:17364)
at android.widget.TextView.checkForResize(TextView.java:6798)
at android.widget.TextView.updateAfterEdit(TextView.java:7693)
at android.widget.TextView.handleTextChanged(TextView.java:7709)
at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:9440)
at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:964)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:515)
at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:272)
at android.text.SpannableStringBuilder.append(SpannableStringBuilder.java:33)
at android.widget.TextView.append(TextView.java:3616)
at android.widget.TextView.append(TextView.java:3603)
at com.tomsapps.thomas.jsonreadertestapp.MainActivity.output(MainActivity.java:63)
at com.tomsapps.thomas.jsonreadertestapp.ConnectToServer.printError(ConnectToServer.java:26)
at com.tomsapps.thomas.jsonreadertestapp.ConnectToServer.run(ConnectToServer.java:74)
at java.lang.Thread.run(Thread.java:818)
I believe your output method from MainActivity modifies a TextView, therefore triggering the exception.
A view hierarchy can only be changed from the "Main" thread, in this case, you might want to try looking into runOnUiThread , some resources on StackOverflow :
how to use runOnUiThread
Android runOnUiThread explanation
Android Java runOnUiThread()
Hope this helps, good luck :)
Edit :
You might also want to use android Log instead of using TextView to display the errors.
I am trying to create a GUI-based program in Java that has a 'Submit' button and when clicked, it takes you to a website.
I have read about the URL and URLConnection classes online and the connection to the website is established but the program does not open the link... This is what I have so far:
if(command.equals("Submit data"))
{
try {
URL myURL = new URL("http://google.com/");
URLConnection myURLConnection = myURL.openConnection();
myURLConnection.connect();
}
catch (IOException t) {
// openConnection() failed
// ...
}
}
The connection seems to be established but I want the program to open up the browser and take to the website.. I've tried everything and no luck..
Thank you
You could either used a swing component like you can see in this thread --> Best Java/Swing browser component?
Otherwise use this snippet found at http://andy.ekiwi.de/?p=1026
public void openUrl(String url) throws IOException, URISyntaxException {
if(java.awt.Desktop.isDesktopSupported() ) {
java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
if(desktop.isSupported(java.awt.Desktop.Action.BROWSE) ) {
java.net.URI uri = new java.net.URI(url);
desktop.browse(uri);
}
}
}