Вопрос

I have integrated a currency converter in my app but when I try to get the results from the internet the app crashes. I am getting an error about: android.os.NetworkOnMainThreadException, some people say you have to add asynctask in order to fix the problem as it runs on main thread. So how can I do that in my current code?

Below is the code:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;


import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

public class Activity_Currency_Converter extends DashBoardActivity {
    public int to;
    public int from;
    public String [] val;
    public String s;
    public Handler handler;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_currency_converter);
        Spinner s1 = (Spinner) findViewById(R.id.spinner1);
        Spinner s2 = (Spinner) findViewById(R.id.spinner2);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
                this, R.array.name, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.select_dialog_singlechoice);
        val  = getResources().getStringArray(R.array.value);
        s1.setAdapter(adapter);
        s2.setAdapter(adapter);
        s1.setOnItemSelectedListener(new spinOne(1));
        s2.setOnItemSelectedListener(new spinOne(2));
        Button b = (Button) findViewById(R.id.button1);
        b.setOnClickListener(new OnClickListener(){
            public void onClick(View v) {
                TextView t = (TextView) findViewById(R.id.textView4);   
                if(from == to)
                {
                    Toast.makeText(getApplicationContext(), "Invalid", 4000).show();
                }
                else
                {                                       
                      try {
                         s = getJson("http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22"+val[from]+val[to]+"%22)&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=");                       
                        JSONObject jObj;
                        jObj = new JSONObject(s);
                        String exResult = jObj.getJSONObject("query").getJSONObject("results").getJSONObject("rate").getString("Rate");
                        t.setText(exResult);
                        } catch (JSONException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        catch (ClientProtocolException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }                                                    
                    }                                           
                }                               
        });
    }
    public String getJson(String url)throws ClientProtocolException, IOException {

        StringBuilder build = new StringBuilder();
        HttpClient client = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();
        InputStream content = entity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(content));
        String con;
        while ((con = reader.readLine()) != null) {
                    build.append(con);
                }
        return build.toString();
    }
    private class spinOne implements OnItemSelectedListener
    {
        int ide;
        spinOne(int i)
        {
            ide =i;
        }
        public void onItemSelected(AdapterView<?> parent, View view,
                int index, long id) {
            if(ide == 1)
                from = index;
            else if(ide == 2)
                to = index;

        }

        public void onNothingSelected(AdapterView<?> arg0) {
            // TODO Auto-generated method stub  
        }

    }
}

Logcat log:

11-27 13:58:17.120: E/AndroidRuntime(1470): android.os.NetworkOnMainThreadException
11-27 13:58:17.120: E/AndroidRuntime(1470):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1133)
11-27 13:58:17.120: E/AndroidRuntime(1470):     at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
11-27 13:58:17.120: E/AndroidRuntime(1470):     at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
11-27 13:58:17.120: E/AndroidRuntime(1470):     at java.net.InetAddress.getAllByName(InetAddress.java:214)
11-27 13:58:17.120: E/AndroidRuntime(1470):     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
11-27 13:58:17.120: E/AndroidRuntime(1470):     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
11-27 13:58:17.120: E/AndroidRuntime(1470):     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
11-27 13:58:17.120: E/AndroidRuntime(1470):     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
11-27 13:58:17.120: E/AndroidRuntime(1470):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
11-27 13:58:17.120: E/AndroidRuntime(1470):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
11-27 13:58:17.120: E/AndroidRuntime(1470):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
Это было полезно?

Решение

Try this,

public class Activity_Currency_Converter extends DashBoardActivity {
    public int to;
    public int from;
    public String [] val;
    public String s;
    public Handler handler;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_currency_converter);
        Spinner s1 = (Spinner) findViewById(R.id.spinner1);
        Spinner s2 = (Spinner) findViewById(R.id.spinner2);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
                this, R.array.name, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.select_dialog_singlechoice);
        val  = getResources().getStringArray(R.array.value);
        s1.setAdapter(adapter);
        s2.setAdapter(adapter);
        s1.setOnItemSelectedListener(new spinOne(1));
        s2.setOnItemSelectedListener(new spinOne(2));
        Button b = (Button) findViewById(R.id.button1);
        b.setOnClickListener(new OnClickListener(){
            public void onClick(View v) {
                TextView t = (TextView) findViewById(R.id.textView4);   
                if(from == to)
                {
                    Toast.makeText(getApplicationContext(), "Invalid", 4000).show();
                }
                else
                {                                       
                      new GetResponseData(t).execute();                              
                    }                                           
                }                               
        });
    }
    public String getJson(String url)throws ClientProtocolException, IOException {

        StringBuilder build = new StringBuilder();
        HttpClient client = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();
        InputStream content = entity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(content));
        String con;
        while ((con = reader.readLine()) != null) {
                    build.append(con);
                }
        return build.toString();
    }
    private class spinOne implements OnItemSelectedListener
    {
        int ide;
        spinOne(int i)
        {
            ide =i;
        }
        public void onItemSelected(AdapterView<?> parent, View view,
                int index, long id) {
            if(ide == 1)
                from = index;
            else if(ide == 2)
                to = index;

        }

        public void onNothingSelected(AdapterView<?> arg0) {
            // TODO Auto-generated method stub  
        }

    }
    class GetResponseData extends AsyncTask<String, String, String> {
         private ProgressDialog dialog;
         private ArrayList<String> titleList;
         private TextView textView;

         public GetResponseData(TextView textView) {
             this.textView=textView;
        }

         @Override
         protected void onPreExecute() {
         super.onPreExecute();
         dialog = ProgressDialog.show(Activity_Currency_Converter.this, "", "Loading",
         false);
         }

         @Override
         protected String doInBackground(String... params) {

             try {
                 String s = getJson("http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22"+val[from]+val[to]+"%22)&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=");                       
                JSONObject jObj;
                jObj = new JSONObject(s);
                String exResult = jObj.getJSONObject("query").getJSONObject("results").getJSONObject("rate").getString("Rate");
               return exResult;
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return null;
                }
                catch (ClientProtocolException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return null;
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return null;
                }                      




         }

         @Override
         protected void onPostExecute(String result) {
         super.onPostExecute(result);
         if (dialog != null)
             dialog.dismiss();
         if(result!=null)
         {
          textView.setText(result);
         }
         }

         }
}

Другие советы

Use Asynchtask for performing Network related operations.. Chack this for more details NetworkOnMainThread and Asynchtask

Make StringBuilder class level, create your ProgressDialog accordingly. Inside your getJSON method create an async task like this

new AsyncTask<Void, Void, Void>() {

        protected void onPreExecute() {
          //Your code
        }

        @Override
        protected Void doInBackground(Void... params) {
        StringBuilder build = new StringBuilder();
        HttpClient client = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();
        InputStream content = entity.getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(content));
        String con;
        while ((con = reader.readLine()) != null) {
                    build.append(con);
                }
        return null;
        }

        protected void onPostExecute(Void result) {
          //Update UI from here
        }
      }.execute();

Use AsyncTask as

class myAsyncTask extends AsyncTask<String[] ,String,String>
{
    String s=null;
    String output=null;
    JSONObject main;

    @Override
    protected void onPreExecute() 
    {   


    }

    @Override
    protected String doInBackground(String[]... val) {

        s = getJson("http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20yahoo.finance.xchange%20where%20pair%20in%20(%22"+val[from]+val[to]+"%22)&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=");                       
                    JSONObject jObj;
                    jObj = new JSONObject(s);
                    String exResult = jObj.getJSONObject("query").getJSONObject("results").getJSONObject("rate").getString("Rate");

        return exResult;
    }
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        t.setText(result);
             }
}

and then call the following method from the 'else' block

new myAsyncTask().execute(val);

The app crashes due to strict mode policy, insert below given lines before you send a request to service or connecting to network:

 ThreadPolicy tp = ThreadPolicy.LAX;
 StrictMode.setThreadPolicy(tp);

Hope it Helps you :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top