网络技术的每日学习(第一行代码)


首先要知道的是在Android P中要求默认使用加密连接,否则会报错,通过http协议访问网络也是这样,在以前的版本中不受限。
所以要怎么做呢:现在res文件夹中创建一个xml文件夹,在里面然后创建一个network_security_config.xml文件

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true"/>
</network-security-config>

之后在AndroidManifest.xml中的application标签填写以下内容:

<application
    ...
    android:networkSecurityConfig="@xml/network_security_config"
    ...
    <activity android:name=".MainActivity">
        ....
    </activity>
</application>

或直接在AndroidManifest.xml:

<application
    ...
    android:usesCleartextTraffic="true"
    ...
    <activity android:name=".MainActivity">
        ....
    </activity>
</application>

我一开始因为这个问题总是不能给服务器发送请求,后来看了一篇博客后才了解的,这个地址是:
https://blog.csdn.net/gengkui9897/article/details/82863966

同样在AndroidManifest.xml申明权限:

<uses-permission android:name="android.permission.INTERNET"/>

WebView控件的简单用法
WebView控件可以实现在程序中展示网页,简单用法 getSetting().setJavaScriptEnabled()方法设置支持javascript脚本,同样通过getSetting()来设置其他属性;setWebView()方法作用是打开网页中的链接时仍在WebView中;loadUrl(String)方法进入相应的网页;其实WebView也是给服务器发送一个http请求,获取服务器传回来的html代码,解析,知识封装了起来。

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    WebView webView = (WebView) findViewById(R.id.first_webview);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.setWebViewClient(new WebViewClient());
    webView.loadUrl("http://www.bilibili.com");
}

}

使用HTTP协议访问网络

使用HttpURLConnection
先创建URL对象,通过url.openConnection()方法获取HttpURLConnection对象;然后调用HttpURLConnection对象的setReuqestMethod(“GET”)设置请求使用的方法(或Post),然后就是其他的设置如setConnectTimeout(int),setReadTimeout(int)设置连接超时,获取超时毫秒数,之后通过getInputStream()获得输入流,再创建流缓冲对象读取数据。发送网络请求是很耗时间的,所以要开一个子线程来进行操作,不过不能在子线程中执行UI操作,必须回到主线程才行即调用

public class MainActivity extends AppCompatActivity {
private Button sendrequest;
private TextView textView;

@Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textView = (TextView) findViewById(R.id.textView);
    sendrequest = (Button) findViewById(R.id.sendrequest_button);
    sendrequest.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //sendhttprequest();
            sendOkHttprequest();
        }
    });
  }
  private void sendhttprequest(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                URL url = new URL("http://www.youku.com");
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                //获取数据
                connection.setRequestMethod("GET");
                connection.setConnectTimeout(8000);
                connection.setReadTimeout(8000);
                
                //发送数据
                /*connection.setRequestMethod("POST");
                DataOutputStream out = new DataOutputStream(connection.getOutputStream());
                out.writeBytes("username=fds&password=123");*/


                InputStream inputStream = connection.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder result = new StringBuilder();
                String line;
                while((line=reader.readLine())!=null){
                    result.append(line);
                }
                showresponse(result.toString());
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();
  }
  //回到主线程执行UI操作
  private void showresponse(final String result){
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            textView.setText(result);
        }
    });
}
}

使用开源库OkHttp
OkHttp比起原生的HttpURLConnection不错。首先在build.gradle中添加依赖,之后会自动下载相应库。

implementation 'com.squareup.okhttp3:okhttp:3.12.0'

怎么用,首先先创建一个OkHttpClient对象;如果要发送http请求,创建Request对象通过
new Request.Builder.build(),可以在中间添加new Request.Builder.url(“String”).build()如.url指定地址等,然后调用OkHttpClient对象的newCall(request)方法创建Call对象,在调用Call对象的execute()方法获取Response对象为返回的数据;对Response对象.body.string()方法转为String类型;如果要发送数据则创建一个RequestBody对象,再在Request.Builder中调用post(requestbody)方法;

private void sendOkHttprequest(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                OkHttpClient client = new OkHttpClient();
                //获取数据
                Request request = new Request.Builder()
                        //.url("http://10.252.215.101/get_data.xml")
                        .url("http://10.252.215.101/get_data.json")
                        .build();
                //发送数据
                /**
                 * RequestBody requestbody = new FormBody.Builder()
                 *      .add("username","abc")
                 *      .add("password","123")
                 *      .build();
                 * Request request = new Request.Builder()
                 *      .url("http://www.bilibili.com")
                 *      .post(requestbody)
                 *      .build();
                 */
                Response response = client.newCall(request).execute();
                String result = response.body().string();
                //showresponse(result);
                //parsexmlwithpull(result);   通过pull方式解析xml数据
                //parsexmlwithsax(result);    通过sax方式解析xml数据
                //parsejsonwithjsonobject(result);  通过JSONObject方式解析json数据
                parsejsonwithgson(result);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();
}

解析XML格式数据

在网络上传输数据常用格式为xml,json;首先先来解析xml格式数据。首先获取一段xml数据,我是通过向自己的服务器发送http请求来获取一段xml数据,内容如下(get_data.xml):

<apps>
  <app>
    <id>1</id>
    <name>blue</name>
  </app>
  <app>
   <id>2</id>
   <name>red</name>
  </app>
  <app>
   <id>2</id>
   <name>green</name>
  </app>
</apps>

Pull方式解析:
先创建xmlPullParserFactory对象,再通过其创建XmlPullParser对象,调用XmlPullParser的setInput(new StringReader(String xml))方法将数据输入进去后可以开始解析;通过while循环解析数据并输出

private void parsexmlwithpull(String xmlresult){
    try {
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        XmlPullParser xmlPullParser = factory.newPullParser();
        xmlPullParser.setInput(new StringReader(xmlresult));
        int eventype = xmlPullParser.getEventType();
        String id = null;
        String name = null;
        while(eventype!=XmlPullParser.END_DOCUMENT){
            String nodename = xmlPullParser.getName();
            switch(eventype){
                case XmlPullParser.START_TAG:
                    if(nodename.equals("id")){
                        id = xmlPullParser.nextText();
                    }else if(nodename.equals("name")){
                        name = xmlPullParser.nextText();
                    }
                    break;
                case XmlPullParser.END_TAG:
                    if(nodename.equals("app")){
                        Log.d("MainActivity","id="+id);
                        Log.d("MainActivity","name="+name);
                    }
                    break;
                default:
                    break;
            }
            eventype = xmlPullParser.next();
        }
    } catch (XmlPullParserException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

SAX方式解析:
首先需创建一个类继承DefaultHandler,重写其中的五个方法,就是相关的解析方式,startDocument()开始解析xml时调用;startElement()开始解析某个节点时调用;characters()获取内容时调用,会被调用多次,换行符也会被解析出来;endElement()完成解析某个节点时调用;endDocument()完成解析xml时调用。

public class ContentHandler extends DefaultHandler {
private String nodename;
private StringBuilder id;
private StringBuilder name;

@Override
public void startDocument() throws SAXException {
    super.startDocument();
    id = new StringBuilder();
    name = new StringBuilder();
}

//解析xml节点时调用
@Override  
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    super.startElement(uri, localName, qName, attributes);
    nodename = localName;
}

//获取内容调用
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
    super.characters(ch, start, length);
    if(nodename.equals("id")){
        id.append(ch,start,length);
    }else if(nodename.equals("name")){
        name.append(ch,start,length);
    }
}

@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
    super.endElement(uri, localName, qName);
    if(localName.equals("app")){
        Log.d("MainActivity","id="+id);
        Log.d("MainActivity","name="+name);
        id.setLength(0);
        name.setLength(0);
    }
}

@Override
public void endDocument() throws SAXException {
    super.endDocument();
}
}

主函数中使用,先创建SAXParserFactory对象,通过其获取XMLReader对象,调用XMLReader对象的setContentHandler()方法,参数是DefaultHandler子类的对象(上面那个解析xml数据的类),再调用parse()方法解析数据:

private void parsexmlwithsax(String xmlresult){
    try {
        SAXParserFactory factory = SAXParserFactory.newInstance();
        XMLReader xmlReader = factory.newSAXParser().getXMLReader();
        xmlReader.setContentHandler(new ContentHandler());
        xmlReader.parse(new InputSource(new StringReader(xmlresult)));
    } catch (SAXException e) {
        e.printStackTrace();
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

解析JSON格式数据

相比于xml格式数据,json格式的数据体积更小,网络上传输更省流量;但语义性较差,不如xml直观。同样通过向自己的服务器发送http请求来获取一段json数据,内容如下(get_data.json):

[{"id":"4","name":"ren mushroom"},
{"id":"5","name":"blue mushroom"},
{"id":"6","name":"yellow mushroom"}]

JSONOBJECT方式解析
这是官方提供的,开源库的GSON方式也很好用。先创建JSONArray对象,把json数据传入;循环遍历这个对象,每次取出一个元素是JSONObject对象,在通过JSONObject对象的get…()方法取出数据:

private void parsejsonwithjsonobject(String jsonresult){
    try {
        JSONArray jsonArray = new JSONArray(jsonresult);
        for(int i=0;i<jsonArray.length();i++){
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            String id = jsonObject.getString("id");
            String name = jsonObject.getString("name");
            Log.d("MainActivity","id="+id);
            Log.d("MainActivity","name="+name);
        }
    } catch (JSONException e) {
        e.printStackTrace();
    }
}

GSON方式解析
因为是开源库中的,先在build.gradle中添加依赖来自动下载相应库:

implementation 'com.google.code.gson:gson:2.7'

GSON可以自动将一段json字符串映射成一个类对象,不需要去写代码解析,就像以下一段json数据:

  [{"id":"4","name":"ren mushroom"},

可以创建一个类Pokemon,有id和name两个属性,就可以直接通过以下将json数据转化为类对象(jsonresult为字符串类型):

GSON gson = new GSON();
Pokemon pokemon = gson.fromJson(jsonresult,Pokemon.class)

如果是一段json数组:

[{"id":"4","name":"ren mushroom"},
{"id":"5","name":"blue mushroom"},
{"id":"6","name":"yellow mushroom"}]

需要TypeToken来转化为List:

List<Pokemon> monsters = gson.fromJson(jsonresult,new TypeToken<List<Pokemon>>(){}.getType());

最后直接调用类方法获取相应数据:

private void parsejsonwithgson(String jsonresult){
    Gson gson = new Gson();
    List<Pokemon> monsters = gson.fromJson(jsonresult,new TypeToken<List<Pokemon>>(){}.getType());
    for(Pokemon pokemon : monsters){
        Log.d("MainActivity","id="+pokemon.getId());
        Log.d("MainActivity","name="+pokemon.getName());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值