更改目标sdkVersion后的NetworkOnMainThreadException

时间:2013-02-04 04:58:02

标签: android exception

我该怎么做这个例外?

我将目标sdkVersion更改为13.出现此问题! 出了什么问题?

这是我尝试加载广告后的logcat输出

02-04 12:51:23.910: E/AndroidRuntime(7379): FATAL EXCEPTION: main
02-04 12:51:23.910: E/AndroidRuntime(7379): android.os.NetworkOnMainThreadException
02-04 12:51:23.910: E/AndroidRuntime(7379):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at java.net.InetAddress.lookupHostByName(InetAddress.java:391)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at java.net.InetAddress.getAllByNameImpl(InetAddress.java:242)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at java.net.InetAddress.getAllByName(InetAddress.java:220)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpConnection.<init>(HttpConnection.java:71)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:351)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:86)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:308)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:460)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:432)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at com.sfa.coverflow.ImageLoader.DisplayAdvert(ImageLoader.java:93)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at com.sfa.coverflow.MainActivity$LoadAdvert.onPostExecute(MainActivity.java:869)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at com.sfa.coverflow.MainActivity$LoadAdvert.onPostExecute(MainActivity.java:1)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at android.os.AsyncTask.finish(AsyncTask.java:602)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at android.os.AsyncTask.access$600(AsyncTask.java:156)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at android.os.Looper.loop(Looper.java:137)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at android.app.ActivityThread.main(ActivityThread.java:4446)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at java.lang.reflect.Method.invokeNative(Native Method)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at java.lang.reflect.Method.invoke(Method.java:511)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
02-04 12:51:23.910: E/AndroidRuntime(7379):     at dalvik.system.NativeStart.main(Native Method)

这是我的DisplayAdvert方法:

int advert_id = R.drawable.loader; 
public void DisplayAdvert(String image_url, int loader, ImageView image) {
    // TODO Auto-generated method stub
    advert_id = loader;
    imageViews.put(image, image_url);
    try {
        URL url = new URL(image_url);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        if(myBitmap!=null)
        image.setImageBitmap(myBitmap);
        else
        {
            queuePhoto(image_url, image);
            image.setImageResource(loader);
        }
    } catch (IOException e) {
        e.printStackTrace();
        }
    }

这是我的LoadAdvert方法:

/**
     * Background Async Task to Load all product by making HTTP Request
     * */
    class LoadAdvert extends AsyncTask<String, String, String> {

        /**
         * getting All products from url
         * */
        protected String doInBackground(String... args) {
            // Building Parameters
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            // getting JSON string from URL
            JSONObject json = jParser.makeHttpRequest(url_advertisement, "GET", params);

            // Check your log cat for JSON reponse
            Log.d("Advert: ", json.toString());

            try {
                // Checking for SUCCESS TAG
                int success = json.getInt(TAG_SUCCESS);

                if (success == 1) {
                    // ADVERT FOUND
                    // RETRIEVE ADVENT URL
                    advert = json.getJSONArray(TAG_PHOTOS);

                    for (int i = 0; i < advert.length(); i++) {
                        JSONObject c = advert.getJSONObject(i);

                        // STORE EACH JSON ITEM IN VARIABLE
                        banner_url = c.getString(TAG_BANNER_IMAGE);
                        banner_url = banner_url.toString();
                        Log.d("banner URL", banner_url);

                        advert_url = c.getString(TAG_ADVERT_URL);
                        advert_url = advert_url.toString();
                        Log.d("advert URL", advert_url);
                    }       
                } 
                else {

                }

            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        /**
         * After completing background task Dismiss the progress dialog
         * **/
        protected void onPostExecute(String file_url) {

                    // Loader image - will be shown before loading image
                    int loader = R.drawable.loader;

                    // Imageview to show
                    ImageView image = (ImageView) findViewById(R.id.img_advert);

                    // Image url
                    String imageUrl = banner_url;

                    // ImageLoader class instance
                    ImageLoader imgLoader = new ImageLoader(getApplicationContext());

                    // whenever you want to load an image from url
                    // call DisplayImage function
                    // url - image url to load
                    // loader - loader image, will be displayed before getting image
                    // image - ImageView 
                    imgLoader.DisplayAdvert(imageUrl, loader, image);           

        }
    }
}

5 个答案:

答案 0 :(得分:2)

堆栈跟踪的这一部分是“杀手”;

at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164)
at com.sfa.coverflow.ImageLoader.DisplayAdvert(ImageLoader.java:93)
at com.sfa.coverflow.MainActivity$LoadAdvert.onPostExecute(MainActivity.java:869)

当AsyncTask完成时,在GUI线程上执行的onPostExecute调用DisplayAdvert,并立即调用HttpsURLConnectionImpl.connect。由于新API版本中的GUI线程不允许网络访问,因此会抛出异常。

DisplayAdvert内的网络访问需要在非GUI线程中完成,因为它执行网络I / O.

最简单的方法是在DisplayAdvert方法中创建新的AsyncTask,在doInBackground()中进行网络访问,并使用onPostExecute()中的提取数据更新GUI。

答案 1 :(得分:0)

如果您只是想测试代码,那么您可以将以下代码添加到onCreate()

if (android.os.Build.VERSION.SDK_INT > 9) { 
                StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); 
        }

您不希望这是永久性的,因为UI线程上的网络操作在使用应用程序时会带来糟糕的体验,但在测试时非常有用。

答案 2 :(得分:0)

将您的DisplayAdvert方法放在doInBackground中,因为您无法在api级别11及以上的主线程上执行网络操作

请参阅此Resource

答案 3 :(得分:0)

您不应该在主线程中执行网络操作。

在您发布的代码中,您正在display()中执行网络操作,并在onPost()的{​​{1}}中进行调用。

AsycTask中,只有AsyncTask在另一个线程中执行,方法doInBackground()在主线程本身中执行。

请随时再提出疑问。

答案 4 :(得分:0)

针对Honeycomb的应用程序将获得此异常,不应在主UI线程中允许网络操作。

您必须在单独的线程(多线程)中执行所有网络操作或使用AsyncTask。

<强>更新

 public void DisplayAdvert(final String image_url, final int loader, final ImageView image) 
    {
        advert_id = loader;
        imageViews.put(image, image_url);
        try 
        {
            new Thread(new Runnable()
            {
                Bitmap myBitmap;
                public void run() 
                {
                    try 
                    {
                        URL url = new URL(image_url);
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.setDoInput(true);
                        connection.connect();
                        InputStream input = connection.getInputStream();
                        myBitmap = BitmapFactory.decodeStream(input);
                    }
                    catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                    runOnUiThread(new Runnable()
                    {
                        public void run() 
                        {
                            if(myBitmap!=null)
                                image.setImageBitmap(myBitmap);
                            else
                            {
                                queuePhoto(image_url, image);
                                image.setImageResource(loader);
                            }
                        }
                    });
                }
            }).start();
       }
       catch (Exception e) 
       {
            e.printStackTrace();
       }
    }