zoukankan      html  css  js  c++  java
  • 【转】 Pro Android学习笔记(六七):HTTP服务(1):HTTP GET

    目录(?)[-]

    1. HTTP GET小例子
      1. 简单小例子
      2. 出现异常NetworkOnMainThreadException
      3. 通过StrictMode进行处理
      4. URL带键值对

    Andriod应用可利用service提供很多功能,例如利用Google Maps API,现在我们将聚焦在HTTP serice中。

    Android SDK提供HttpClient,和J2EE中的接口非常相似。最常用的就是HTTP GET和HTTP POST。相关内容也可以阅读Android学习笔记(四五):互联网通信-HttpClient、XML解析(W3C)

    HTTP GET小例子

    因为要访问互联网,所以要在AndriodManifest.xml文件中加入android.permission.INTENT的权限。

    简单小例子

    小例子很简单,发送一个HTTP Get,请求打开某个网址,并将收到的HTTP响应通过Log打印出来。

    public class HttpGetDemo extends Activity{  
        @Override 
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.activity_main);  
                     
            BufferedReader in = null; 
            try{  
                //【Step 1】创建一个HttpClient的对象(或使用已有的)
                HttpClient client = new DefaultHttpClient(); 
                //【Step 2】实例化一个HTTP GET或者HTTP POST,本例是HTTP GET 
                HttpGet request = new HttpGet("
    http://www.baidu.com"); 
                //【Step 3】设置HTTP参数,本例子是最简单地打开某个网址的HTTP GET,无需设置 
               //【Step 4】通过HttpClient来执行HTTP call(发出HTTP请求)  
                HttpResponse response = client.execute(request);
     
                //【Step 5】处理HTTP响应,本例将整个响应的内容(HTTP 200消息的body)都在String中。 
                in = new BufferedReader( 
                        new InputStreamReader( 
                                response.getEntity().getContent())
    ); 
                StringBuffer buff = new StringBuffer(""); 
                String line = ""; 
                String NL = System.getProperty("line.separator");  //实际上就是“ ”,可自动适配系统的换行符。 
                while((line = in.readLine()) != null ){ 
                    buff.append(line + NL); 
                } 
                in.close();  
                Log.d("PRO",buff.toString());  
            }catch(Exception e){ 
                e.printStackTrace(); 
                Log.d("PRO",e.toString()); 
            }finally{  //try{}catch(){}finally{}中finally见得稍微少,但是很有用,无论是否有异常,都会执行finally的代码,常用于xx.close()。
                if(in != null){ 
                    try{ 
                        in.close(); //关闭BufferedReader,同时也关闭了底层的HTTP connection
                    }catch(Exception e){ 
                        e.printStackTrace();  
                        Log.d("PRO","error in finally: " + e.toString()); 
                    } 
                } 
            }         
        }  
        
    }

    出现异常NetworkOnMainThreadException

    这是很简单的例子,但是运行的时候却报错:

    例子很简单,代码没有什么为题,何故?根据文档,这个错误会在应用尝试在主线程(Main)中进行网络操作而产生,只在Honeycomb SDK或更高版本出现。也就是说在Android 3.0及以上版本,如果在主线程进行网络访问,会扔出NetworkOnMainThreadException。而检查AndroidManifest.xml文件,发现:

    <uses-sdk  android:minSdkVersion="14" …… />

    即运行在Android 4.0及以上的版本。Android 3.0对应为API level 10,我们只需简单地改为:

    <uses-sdk  android:minSdkVersion="9" />

    Android这样的处理是有道理的,我们注意到代码当中有一行:

    /* 建立HTTP的TCP连接(包括之前对网址的DNS解析),发送HTTP GET请求,等待HTTP response消息。这一语句执行了太多内容,有些步骤,可能会因为网络问题,出现长时间的等待才能连接到(或最终不能连接)网站。因此这语句的执行时间可能会很长,建议放在线程中进行后台处理,而不是主线程(同时也是UI线程)中,否则会造成activity因执行该语句造成的UI无响应问题。另外如果网页很大,需要读取很久,在main thread会由于执行该语句导致UI暂时无响应(我不太确定读取网页是在execute,还是在后面in中作为流的方式读取读取,但是我倾向于在execute中读完,因为已经获得HttpResponse对象)*/
    HttpResponse response = client.execute(request);

    通过StrictMode进行处理

    对NetworkOnMainThreadException的合理处理就是将网络访问放置在线程中,本例为了演示直接放置在activity中,在正常情况下,不应如此处理。

    处理修改API Level之外,要避免异常,同时也需要指定最小运行版本在Android 3.0以上,例如本例最初指定android:minSdkVersion="14"。还可以对代码进行以下处理:

        …… 
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 
        StrictMode.setThreadPolicy(policy); 
        ……         
        BufferedReader in = null; 
        try{ … }catch(Exception e){ … }finally{…}   

    StrictMode我们在Pro Android学习笔记(五五):调试和分析(3):adb命令、模拟器控制台和StrictMode中介绍过,不禁止运行线程的某些策略,上面的代码不做任何策略检查,当然也可以只放开网络,即也可以用permitNetwork()。

    相关的参考BUG处理可参见:http://www.lucazanini.eu/2012/android/the-android-os-networkonmainthreadexception-exception/?lang=en

    当然,我们应该明白尽量不要在activity中(main thread)有网络访问代码。

    URL带键值对

    对于CGI,URL是带有键值对的,最常见的就是搜索网站,网站根据URL携带的信息来确定用户所要搜索的内容。例如:

    HttpClient client = new DefaultHttpClient(); 
    HttpGet request = new HttpGet("http://www.google.com.hk/#newwindow=1&q=android&safe=strict");
    HttpResponse response = client.execute(request); 

    更多的可以使用HTTP POST方式,我们将继续学习。

    本博文涉及的例子代码,可以在Pro Android学习:Http service小例子中下载。

    相关链接: 我的Android开发相关文章

  • 相关阅读:
    (第七周)评论alpha发布
    (第六周)工作总结
    (第六周)团队项目6
    (第六周)团队项目5
    (第六周)团队项目4
    (第六周)团队项目燃尽图
    (第六周)团队项目3
    (第六周)课上Scrum站立会议演示
    Java第二次作业第五题
    Java第二次作业第四题
  • 原文地址:https://www.cnblogs.com/blongfree/p/5048039.html
Copyright © 2011-2022 走看看