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
}
}
Related
My android application is not receiving any data from my server, for some reason. Strangely enough, a different socket client I wrote (which runs on my computer rather than an AVD) receives and prints all server-sent messages without fault. It uses similar code to what is held within the doInBackground method.
public class Client extends AsyncTask<Void, Void, Void> {
int port;
Socket s;
#Override
protected Void doInBackground(Void... voids) {
try {
port = 1818;
s = new Socket("xx.xx.xx.xx", port);
if (!s.isConnected()) {
s.close();
}
BufferedReader re = new BufferedReader(new InputStreamReader(s.getInputStream()));
String temp = null;
while ((temp = re.readLine()) != null)
{
MainActivity.changeT(temp); // This will replace the TextView's text with temp.
}
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
}
I am thinking a possible solution would be to place the while loop into a separate thread, but I am not sure. Any suggestions are welcome! :-)
While the application was accessing the server appropriately, MainActivity.changeT(temp); is attempting to access the UI thread from a background thread, which is not appropriate.
I solved this by passing an instance of the MainActivity to this Client class, and I used the runnable method runOnUiThread(...).
public class Client extends AsyncTask<Void, Void, Void> {
int port;
Socket s;
MainActivity instance;
Client(MainActivity instance)
{
this.instance = instance;
}
#Override
protected Void doInBackground(Void... voids) {
try {
port = 1818;
s = new Socket("xx.xx.xx.xx", port);
if (!s.isConnected()) {
s.close();
return null;
}
BufferedReader re = new BufferedReader(new InputStreamReader(s.getInputStream()));
String temp = null;
TextView t = instance.getT(); // Accesses a getter method that returns the TextView.
while ((temp = re.readLine()) != null)
{
setText(t, temp); // Accesses the UI Thread and changes the TextView.
}
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
private void setText(final TextView text,final String value){
instance.runOnUiThread(new Runnable() {
#Override
public void run() {
text.setText(value); // This is equivalent to writing the code in the UI thread itself.
}
});
}
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)
I created a REST API which appears to work fine (I tested the GET request of interest using Postman).
I am working to make an identical request from an Android application using an AsyncTask. The hope is to assign a string value generated by the AsyncTask to a string variable in the Android activity.
I have used a Toast to view the string output of the doInBackground method, which is passed to the onPostExecute method of the AsyncTask, to make sure that the call to the API is working and it works fine.
The problem comes when I assign the string output of the AsyncTask to the string variable defined in the Activity class. After executing the AsyncTask I am using a Toast to view the value of the string variable and it is reflecting the assignment performed in the onPostExecute method.
I will now share the code that I am using in the hope that you can help me to find where I might be going wrong. After the button is clicked, I intend for the validate AsyncTask to execute and assign a value to emailValid.
In view of the code below, my question in the most direct way I can put it: "Why is Toast 2 displaying while Toast 1 is not?"
Thank you in advance for your assistance.
public class JoinActivity extends AppCompatActivity implements View.OnClickListener
{
EditText email_et;
Button join_b;
String emailValid;
#Override
protected void onCreate(Bundle savedInstance)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_join);
emailValid = "No";
join_b = (Button) findViewById(R.id.aj_join_b);
join_b.setOnClickListener(this);
}
#Override
public void onClick(View view)
{
email_et = (EditText) findViewById(R.id.et_aj_email_address);
new JoinActivity.validate().execute(email_et.getText().toString());
// Toast 1 here:
Toast.makeText(getApplicationContext(), emailValid,
Toast.LENGTH_LONG).show();
}
private class validate extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... params)
{
// ... GET request produces string with either yes or no i.e. outcome
return outcome;
}
#Override
protected void onPostExecute (String s)
{
// Toast 2 here:
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();
emailValid = s;
super.onPostExecute(s);
}
}
}
As requested, the detail in the doInBackground method is pasted below. The method actually return some XML. My original question which said "a string variable which is either a "yes" or "no"" was my attempt to simplify the setup. As I mentioned before, displaying the string in a Toast from within the onPostExecute works fine showing the participantXML sent from the doInBackground:
#Override
protected String doInBackground(String... params) {
InputStream inputStream;
String emailAddress = params[0];
String outcome = null;
HttpURLConnection httpURLConnection = null;
BufferedReader bufferedReader = null;
try
{
URL url = new URL("http://10.0.2.2:8080/project_name/webresources/entity.participant/email");
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Accept", "application/xml");
httpURLConnection.addRequestProperty("Email-address", emailAddress);
httpURLConnection.connect();
inputStream = httpURLConnection.getInputStream();
StringBuffer stringBuffer = new StringBuffer();
if (inputStream == null) {
return null;
}
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuffer.append(line + "\n");
}
if (stringBuffer.length() == 0) {
return participantXML;
}
participantXML = stringBuffer.toString();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
validEmailAddress = participantXML;
return participantXML;
}
The answer by user3691697 to this question: How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class? did the trick. I created task object (myTask) when executing the task and thereafter used it to assign the result to the variable like this:
AsyncTask myTask = new JoinActivity.validate.execute(email_et.getText().toString());
emailValid = myTask.get().toString();
The Toast message confirms that the assignment worked! Thank you for the help Pulak and LeoNeo.
In my code,first I access an address and I got the text file. In that, there are many picture links, such as http://dnight-math.stor.sinaapp.com/%E5%9C%B0%E7%90%861_img004.jpg. I use regular expression to find all the links to make a arraylist. Then I use downloadService to download all the pictures. When I first press a button to download ,it can run successfully. But it doesn't work if the button is pressed again and throws error. I think this bug is about thread but I don't know how to solve it.
HttpUtil.sendHttpRequest(address,
new HttpCallbackListener() {
#Override
public void onFinish(String response) {
try {
ArrayList<String> urlList = new ArrayList<>();
Pattern p = Pattern.compile("http:.*?.com/(.*?.(jpg|png))");
Matcher m = p.matcher(response);
StringBuffer buffer = new StringBuffer();
while (m.find()) {
m.appendReplacement(buffer, "<T>" + + m.group(1) + "</T>");
urlList.add(m.group());
}
m.appendTail(buffer);
response = buffer.toString();
Message m2 = Message.obtain();
m2.obj = response;
m2.what = 1;
mHandler.sendMessage(m2);
new DownloadService("/data/data/com.baodian/files",
urlList,
new DownloadStateListener() {
#Override
public void onFinish() {
}
#Override
public void onFailed() {
}
}, context).startDownload();
;
// JSONObject singleChoice=all.getjson
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onError(Exception e) {
}
});
public class HttpUtil {
public static void sendHttpRequest(final String address,
final HttpCallbackListener listener) {
new Thread(new Runnable() {
#Override
public void run() {
HttpURLConnection connection=null;
try {
URL url=new URL(address);
connection=(HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
connection.setDoInput(true);
connection.setDoOutput(true);
InputStream in=connection.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(in,"gbk"));
StringBuilder response=new StringBuilder();
String line=null;
while ((line=reader.readLine())!=null) {
response.append(line);
}
if (listener!=null) {
listener.onFinish(response.toString());
}
} catch (Exception e) {
if (listener != null) {
listener.onError(e);
}
}
}
}).start();
}
}
If you look at SimY4's answer here,
he says that the error you're getting "means the thread pool is busy and queue is full as well".
What you currently do is call onFailed when you encounter the error. What you can do is implement
a supplementary enqueing scheme. You can cache the newer urls until the thread queue has space, create and enqueue
the new threads at that point.
The following thread might prove useful : Java executors: how to be notified, without blocking, when a task completes?
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());