Android网络技术

来源:互联网 发布:时间简史 知乎 编辑:程序博客网 时间:2024/05/20 10:54

一.WebView用法

public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);WebView webView = (WebView) findViewById(R.id.web_view);webView.getSettings().setJavaScriptEnabled(true);//getSettings()设置浏览器属性,这里只设置了支持JavaScript脚本的属性webView.setWebViewClient(new WebViewClient());//当从一个网页跳到另一个网页时,在当前WebView中显示,不打开其他浏览器webView.loadUrl("http://wwww.baidu.com");}}
记得在AndroidManifest.xml中添加访问网络的权限
<span style="font-size:24px;"><uses-permission android:name="android.permission.INTERNET"/></span>

二.在android上发送http请求有两种方式

  • HttpURLConnection
  • HttpClient
<pre name="code" class="java">public class MainActivity extends Activity implements OnClickListener{public static final int SHOW_RESPONSE = 0;private Button sendRequest;private TextView responseText;private Handler handler = new Handler(){public void handleMessage(Message msg){switch(msg.what){case SHOW_RESPONSE:String response = (String)msg.obj;//Handler的handlerMessage()方法中对这条Message进行处理,最终取出结果设置到TextView上responseText.setText(response);}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);sendRequest = (Button) findViewById(R.id.send_request);responseText = (TextView) findViewById(R.id.response_text);sendRequest.setOnClickListener(this);}@Overridepublic void onClick(View v) {if(v.getId() == R.id.send_request){//sendRequestWithHttpURLConnection();使用HttpURLConnectionsendRequestWithHttpClient();}}//使用HttpURLConnection发送http请求private void sendRequestWithHttpURLConnection(){//开启线程来发起网络请求new Thread(new Runnable(){@Overridepublic void run() {HttpURLConnection connection = null;try{URL url = new URL("http://www.baidu.com");//1.打开url连接connection = (HttpURLConnection) url.openConnection();//2.选择url提交(POST)还是(GET)?connection.setRequestMethod("GET");//3.设置连接状态(eg:超时,服务器获取消息头等)connection.setConnectTimeout(8000);connection.setReadTimeout(8000);//4.Inputstream对象的getInputStream()方法获取输入流InputStream in = connection.getInputStream();//5.利用BufferedReader对服务器的返回流进行读取BufferedReader reader = new BufferedReader(new InputStreamReader(in));StringBuilder response = new StringBuilder();String line;while((line = reader.readLine()) != null){response.append(line);}Message message = new Message();message.what = SHOW_RESPONSE;//6.将服务器返回的结果存放到Message中,子线程无法对UI进行操作,所以创建一个Message对象来存放服务器返回内容来显示到界面上message.obj = response.toString();handler.sendMessage(message);}catch(Exception e){e.printStackTrace();}finally{if(connection != null){//7.关闭连接connection.disconnect();}}}}).start();}//使用HttpClient发送http请求private void sendRequestWithHttpClient(){new Thread(new Runnable(){@Overridepublic void run() {try{//1.HttpClient是一个接口,因此无法创建实例,通常是创建DefaultHttpClient的实例HttpClient httpClient = new DefaultHttpClient(); //2.HttpGet对象是发起一条GET请求HttpGet httpGet = new HttpGet("http://www.baidu.com");//3.执行execute()方法会返回一个HttpResponse对象HttpResponse httpResponse = httpClient.execute(httpGet);//4.请求和响应都成功了if(httpResponse.getStatusLine().getStatusCode() == 200){//5.取出服务返回的具体内容。调用getEntity()得到一个HtttpEntity实例HttpEntity entity = httpResponse.getEntity();//6.用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串即可。中文乱码,只要指定字符集为“utf-8”即可。String response = EntityUtils.toString(entity,"utf-8");Message message = new Message();message.what = SHOW_RESPONSE;//7.将服务结果存放在Message中handler.sendMessage(message);}}catch(Exception e){e.printStackTrace();}}}).start();}}

三.XML文件解析
  • PULL解析方式
xml文件:
<apps><app><id>1</id><name>Google Maps</name><version>1.0</version></app><app><id>2</id><name>Chrome</name><version>2.1</version></app><app><id>3</id><name>Google Play</name><version>2.3</version></app></apps>

解析代码:
//使用HttpClient发送http请求private void sendRequestWithHttpClient(){new Thread(new Runnable(){@Overridepublic void run() {try{//1.HttpClient是一个接口,因此无法创建实例,通常是创建DefaultHttpClient的实例HttpClient httpClient = new DefaultHttpClient(); //2.HttpGet对象是发起一条GET请求HttpGet httpGet = new HttpGet("http://localhost:8080/get_data.xml");//3.执行execute()方法会返回一个HttpResponse对象HttpResponse httpResponse = httpClient.execute(httpGet);//4.请求和响应都成功了if(httpResponse.getStatusLine().getStatusCode() == 200){//5.取出服务返回的具体内容。调用getEntity()得到一个HtttpEntity实例HttpEntity entity = httpResponse.getEntity();//6.用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串即可。中文乱码,只要指定字符集为“utf-8”即可。String response = EntityUtils.toString(entity,"utf-8");//Message message = new Message();//message.what = SHOW_RESPONSE;//7.将服务结果存放在Message中//message.obj = response.toString();//handler.sendMessage(message);parseXMLWithPull(response);}}catch(Exception e){e.printStackTrace();}}}).start();}private void parseXMLWithPull(String xmlData){try{//1.获取一个XmlPullParserFactory实例,借助这个实例获得XmlPullParser对象,然后调用XmlPullParser的setInput方法将服务器返回的xml数据放进去解析就好了XmlPullParserFactory factory = XmlPullParserFactory.newInstance();XmlPullParser xmlPullParser = factory.newPullParser();xmlPullParser.setInput(new StringReader(xmlData));//2.通过getEventType()获取当前解析事件int eventType = xmlPullParser.getEventType();String id = "";String name = "";String version = "";//3.解析事件不等于XmlPullParser.END_DOCUMENT,说明解析工作还没有完成,调用next()方法后可以获取下一个解析事件//4.在while循环中,getName()获取当前的结点名字,如果发现结点名字等于id、name、version,就调用nextText()来获取具体内容,每解析完一个app就将获取的内容打印出来while(eventType != XmlPullParser.END_DOCUMENT){String nodeName = xmlPullParser.getName();switch(eventType){//开始解析某个结点case XmlPullParser.START_TAG:{if("id".equals(nodeName)){id = xmlPullParser.nextText();}else if("name".equals(nodeName)){name = xmlPullParser.nextText();}else if("version".equals(nodeName)){version = xmlPullParser.nextText();}break;}case XmlPullParser.END_TAG:{if("app".equals(nodeName)){Log.d("PULL解析", "id is" + id);Log.d("PULL解析", "name is" + name);Log.d("PULL解析", "version is" + version);}break;}default:break;}eventType = xmlPullParser.next();}}catch(Exception e){e.printStackTrace();}}

  • SAX解析方式
解析代码:
新建继承DefaultHandller的类
public class ContentHandler extends DefaultHandler{private String nodeName;private StringBuilder id;private StringBuilder name;private StringBuilder version;@Overridepublic void startDocument() throws SAXException {//开始XML解析的时候调用id = new StringBuilder();name = new StringBuilder();version = new StringBuilder();}@Overridepublic void endDocument() throws SAXException {// 完成整个XML解析的时候调用super.endDocument();}@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {// 1.开始解析某个结点的时候调用//记录当前结点名nodeName = localName;}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {// 完成解析某个结点的时候调用if("app".equals(localName)){Log.d("ContentHandler", "id is " + id.toString().trim());Log.d("ContentHandler", "name is " + name.toString().trim());Log.d("ContentHandler", "version is " + version.toString().trim());//最后要将StringBuilder清空掉id.setLength(0);name.setLength(0);version.setLength(0);}}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {// 获取结点中内容的时候调用//2.根据当前结点名判断将内容添加到哪一个StringBuilder对象中if("id".equals(nodeName)){id.append(ch,start,length);}else if("name".equals(nodeName)){name.append(ch,start,length);}else if("version".equals(nodeName)){version.append(ch,start,length);}}}

MainActivity.java
private void parseXMLWithSAX(String xmlData){try{SAXParserFactory factory = SAXParserFactory.newInstance();XMLReader xmlReader = factory.newSAXParser().getXMLReader();ContentHandler handler = new ContentHandler();//将ContentHandler的实例设置到XMLReader中xmlReader.setContentHandler(handler);//开始执行解析xmlReader.parse(new InputSource(new StringReader(xmlData)));}catch(Exception e){e.printStackTrace();}}


四.JSON格式数据解析
比起xml,json主要优势在于它体积更小,在网络上传输的时候可以更省流量。但缺点在于,它语义性较差。

  • 使用JSONObject
json文件:
[    {"id":"5","version":"5.5","name":"Angry Birds"},    {"id":"6","version":"7.0","name":"Clash of Clans"},    {"id":"7","version":"3.5","name":"Hey Day"}]
private void parseJSONWithJSONObject(String jsonData){    try{        JSPNArray jsonArray = new JSPNArray(jsonData);        for(int i = 0; i < jsonArray.length(); i++){            JSONObject jsonObject = jsonArray.getJSONObject(i);            String id = jsonObject.getString("id");            String name = jsonObject.getString("name");            String version = jsonObject.getString("version");            log.d("MainActivity","id is " + id);            log.d("MainActivity","name is " + name);            log.d("MainActivity","version is " + version);        }    }catch(Exception e){        e.printStackTrace();    }}
  • 使用GSON(Android API没有集成,所以要在项目中自己添加个GSON的Jar包)
将json数据转变成对象

public class APP{    private String id;    private String name;    private String version;    public String getId(){        return id;    }    public void setId(String id){        this.id = id;    }    public String getName(){        return name;    }    public void setName(String name){        this.name = name;    }    public String getVersion(){        return version;    }    public void setVersion(String version){        this.version = version;    }}

MainActivity.java
//parseJSONWithGSON(response);private void parseJSONWithGSON(String jsonData){    Gson gson = new Gson();    List<App> appList = gson.fromJson(jsonData,new TypeToken<List<App>>(){}.getType());    for(App app : appList){        log.d("MainActivity","id is " + app.getId());        log.d("MainActivity","name is " + app.getName());        log.d("MainActivity","version is " + app.getVersion());    }}

四.网络编程在实际操作中

通常情况下,应该将通用的网络操作提取到一个公共的类里,并提供一个静态方法。
public class HttpUtil{    public static String sendHttpRequest(String address){        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));            StringBuilder response = new StringBuilder();            String line;            while((line = reader.readLine()) != null){                response.append(line);            }            return response.toString();        }catch(Exception e){            e.printStackTrace();            return e.getMessage();        }finally{            if(connection != null);            connection.disconnect();        }    }}//以后每发起一条HTTP请求的时候就可以这样写String address = "http://www.baidu.com";String response = HttpUtil.sendHttpRequest(address);

网络请求一般都是耗时操作,而sndHttpRequest()方法没有开启线程操作,调用此方法时,可能导致主线程被阻塞,使用java的回调机制来解决
public interface HtttpCallbackListener{void onFinish(String response);void onError(Exception e);}public class HttpUtil{    public static void sendHttpRequest(final String address,final HttpCallbackListener listener){        new Thread(new Runnable(){        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));            StringBuilder response = new StringBuilder();            String line;            while((line = reader.readLine()) != null){                response.append(line);            }            if(listener != null){            //回调onFinish()方法            listener.onFinish(response.toString());            }        }catch(Exception e){        if(listener != null){        //回调onError()方法        listener.onError(e);        }        }finally{            if(connection != null){            connection.disconnect();        }          }        }    }).start();    }}HttpUtil.sendHttpRequest(address, new HttpCallbackListener(){public void onFinish(String response){//在这里根据返回的内容执行具体的逻辑}public void onError(Exception e){//在这里对异常情况进行处理}});
这样处理是无法更新UI操作的,因为子线程里面不能执行任何UI操作做,如果要用返回的结果来更新UI,则要用异步消息处理机制。

提交登入账号密码实例:
public class MainActivity extends Activity {Handler handler = new Handler(){public void handleMessage(android.os.Message msg) {Toast.makeText(MainActivity.this, (String)msg.obj, 0).show();}};    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    public void click1(View v){    //获取用户输入的账号密码    EditText et_name = (EditText) findViewById(R.id.et_name);    EditText et_pass = (EditText) findViewById(R.id.et_pass);        String name = et_name.getText().toString();    String pass = et_pass.getText().toString();        final String path = "http://169.254.244.136/Web2/servlet/Login?name=" + URLEncoder.encode(name) + "&pass=" + pass;        Thread t = new Thread(){    @Override    public void run() {    //使用httpClient框架提交    //1.创建client对象    HttpClient client = new DefaultHttpClient();    //2.创建get请求对象    HttpGet get = new HttpGet(path);    try {    //3.使用client发送get请求HttpResponse response = client.execute(get);//获取状态行StatusLine line = response.getStatusLine();//获取状态码int code = line.getStatusCode();if(code == 200){//获取实体HttpEntity entity = response.getEntity();InputStream is = entity.getContent();String text = Tools.getTextFromStream(is);Message msg = handler.obtainMessage();msg.obj = text;handler.sendMessage(msg);}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}    }    };    t.start();    }        public void click2(View v){    //获取用户输入的账号密码    EditText et_name = (EditText) findViewById(R.id.et_name);    EditText et_pass = (EditText) findViewById(R.id.et_pass);        final String name = et_name.getText().toString();    final String pass = et_pass.getText().toString();        final String path = "http://169.254.244.136/Web2/servlet/Login";        Thread t = new Thread(){    @Override    public void run() {    HttpClient client = new DefaultHttpClient();    HttpPost post = new HttpPost(path);        //把要提交的数据封装至post中    List<NameValuePair> parameters = new ArrayList<NameValuePair>();    //arg0:表单的名字    //arg1:表单中的值    BasicNameValuePair bnvp1 = new BasicNameValuePair("name", name);    BasicNameValuePair bnvp2 = new BasicNameValuePair("pass", pass);    //把BasicNameValuePair对象放入集合    parameters.add(bnvp1);    parameters.add(bnvp2);    //创建实体对象    UrlEncodedFormEntity entity = null;try {//把集合对象封装到实体中entity = new UrlEncodedFormEntity(parameters, "utf-8");} catch (Exception e1) {e1.printStackTrace();}//把实体对象封装至post对象中    post.setEntity(entity);    try {HttpResponse response = client.execute(post);if(response.getStatusLine().getStatusCode() == 200){InputStream is = response.getEntity().getContent();String text = Tools.getTextFromStream(is);Message msg = handler.obtainMessage();msg.obj = text;handler.sendMessage(msg);}} catch (Exception e) {e.printStackTrace();}     }    };    t.start();    }    }



0 0