0

我应该如何处理这个异常?

在我将目标 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);           

        }
    }
}
4

5 回答 5

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 完成时,onPostExecute在 GUI 线程上执行的调用会立即调用. 由于在较新的 API 版本中不允许在 GUI 线程上进行网络访问,因此会引发异常。DisplayAdvertHttpsURLConnectionImpl.connect

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

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

于 2013-02-04T05:07:00.760 回答
0

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

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

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

于 2013-02-04T05:07:29.523 回答
0

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

看到这个资源

于 2013-02-04T05:07:31.387 回答
0

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

在您发布的代码中,您正在执行网络操作display()onPost()AsycTask.

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

请随时提出任何进一步的疑问。

于 2013-02-04T05:11:00.210 回答
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();
       }
    }
于 2013-02-04T05:13:53.957 回答