安卓
来源:互联网 发布:华为交换机查看端口ip 编辑:程序博客网 时间:2024/04/27 06:17
一、 实验题目
网络访问
1.熟练使用 HttpURLConnection 访问 WebService
2.熟悉使用多线程以及 Handler 更新 UI
3.熟悉使用 XmlPullParser 解析 xml 文档数据
4.了解 RecyclerView 控件的使用
二、 实现内容
实现一个简单的天气查询应用,具体要求如下:
三、 课堂实验结果
(1)实验步骤以及关键代码
本次实验基于一个如下网站
http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?op=getWeather
设置一个app界面,输入城市名,即查询该CityCode的天气情况,对返回的XML文件进行解析后,在app中显示。如下(这就是最后的结果啦,当然根据你输入的城市不同,结果不同,输入城市名和城市代号都是可以识别的)
XML文件内容如下所示(本是要就要解析xml文件获取string标签中的内容,按我们喜欢的格式在app中显示。)
APP开始界面如下所示(那啥,这些都是我初始默认的不用管,就这么个布局)
layout.xml
没什么特殊的,按照课件的格式布局,主要就是要应用RecyclerView,需要自己新建一个lib文件夹,放入存有RecyclerView的jar包,还不够,还要吧这个包Add As Library.才正确导入,可以调用RecyclerView空间,设置它的属性横行滚动
<android.support.v7.widget.RecyclerView android:layout_width="wrap_content" android:scrollbars="horizontal" android:id="@+id/recyclerview" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView>
MainActivity.java
首先AS新建一个工程network,布局啥的该设计就设计好,直接从MainActivity开始吧。首先,所有事件,都是基于点击search按钮来进行,点击按钮,首先要判断的是,有没有网络连接,网络连接正常,才回去访问这个url.
本次实验我们固定String url=”http://ws.webxml.com.cn/WebServices/WeatherWS.asmx/getWeather”;
这个跟上面是不同的,可以点击访问一下看看。我们最终需要的是http://ws.webxml.com.cn/WebServices/WeatherWS.asmx/getWeather?theCityCode=2350&theUserID=ecefcf4c81b847a189ff94a159d54dd0(试了好久。)比url多了俩个参数theCityCode和theUserID,就是根据我们的输入城市不同,会请求到不同的url
第一步在 manifest 中添加网络访问权限:
<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
检查网络连接是否正常:ConnectivityManager主要管理和网络连接相关的操作 。getActiveNetworkInfo() 方法返回一个 NetworkInfo实例,它表示可以找到的第一个已连接的网络接口,如果返回 null,则表示没有已连接的网络接口(意味着网络连接不可用)
在点击按钮后进行判断,网络访问,则用sendRequestWithHttpURLConnection();函数进行HTTP请求建立连接
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ConnectivityManager connMgr =(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);//获取管理和网络连接相关的操作对象 NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();//获取网络接口 if(networkInfo!= null && networkInfo.isConnected()) { Toast.makeText(MainActivity.this, "you 网络访问", Toast.LENGTH_SHORT).show(); sendRequestWithHttpURLConnection(); } else Toast.makeText(MainActivity.this, "无 网络访问", Toast.LENGTH_SHORT).show(); } }); }
对于HTTP函数,由于网络访问,是比较耗时的操作,所以开个线程慢慢的跑啊跑,不要影响到主线程的耗时,蓝后conection首先要做到就是对我们这次的URL尝试建立连接,然后设置你申请访问的时候的一些超时读取,超时请求的函数等,这些都在HttpURLConnection类中已经申明。然后用DataOutputStream 把我们在app中的输入citycode值,转为字节流传给网页,该网页会作为参数进行递交。后台会把这个参数和之前的URL结合一起组成一个有参数的URL访问。这样才是一个完整的connection。如果你单独访问URL会提示
缺少参数: theCityCode
访问一个网页,正确建立连接时返回的request=200,假如报错,根据request的数值自己百度报错类型解决即可。用InputStream来获取返回的xml文件的字节流吧,(应该是)然后一顿操作变成BufferedReader ,用StringBuilder 读取每一行,再转为字符串来给我们操作= =,这里懵逼了。这边获取了字符串形式的xml文件,主要用于来更新我们APP的UI界面,所以通过Handler来进行,handler.sendEmptyMessage(1);传给消息给他,你可以理解为类似广播的性质,其实是一个对于handler里面一个队列的无限的loop,队列中一有东西进来,就会触发handler进行操作,所以实时的吧,最后吧连接断掉,开启线程。而我们获取到的xml文件,就通过toString赋值给一个公有变量String r,给 字符串r 重新赋值后,handler不用传字符串参数,直接就可以调用改变后的r。
private void sendRequestWithHttpURLConnection() { new Thread(new Runnable() { @Override public void run() { HttpURLConnection connection=null; try{ Log.d("Tag","begin connectin"); connection=(HttpURLConnection)((new URL(url).openConnection())); connection.setRequestMethod("POST"); connection.setReadTimeout(8000); connection.setConnectTimeout(8000); String request=city.getText().toString(); request= URLEncoder.encode(request,"utf-8"); connection.connect();//发送Http请求,建立跟网页的连接 DataOutputStream out=new DataOutputStream(connection.getOutputStream()); out.writeBytes("theCityCode="+request+"&theUserID=ecefcf4c81b847a189ff94a159d54dd0");//theUserID是本人在那个网站申请的ID,暂时应该还可以用,out作为参数,连同URL一起,形成一个新的真正的url地址 int back =connection.getResponseCode(); Log.d("Tag","The response is"+back); InputStream in=connection.getInputStream();//获取http返回的xml文件的字节流 BufferedReader reader=new BufferedReader(new InputStreamReader(in));//转为BufferedReader StringBuilder response=new StringBuilder(); String line=new String(); while((line=reader.readLine())!=null)//按行读取,存入StringBuilder { response.append(line); } Message message=new Message(); //message.what=1; //message.obj=parseXMLWithPull(response.toString()); handler.sendEmptyMessage(1); r=new String(); r=response.toString();//r是一个公有有成员,相当于全局变量 Log.d("Tag",response.toString()); } catch (Exception e) { e.printStackTrace(); Log.d("Tag","err"); } finally { connection.disconnect(); } } }).start(); }
handler函数,就是接收到一个meeage后根据他是什么来选择操作类型,然后就是根据你电脑去访问,看看他的xml格式,按照格式,用你java学到的一系列字符串数组的方法来进行分割,提取想要的在界面中显示。
这里面有一个parseXMLWithPull函数,就是用来提取xml文件里的每个标签的之间的内容然后都扔到一个 ArrayList list=new ArrayList();里面。先要什么就去list里面提取就行,当然也可以用一个map设置,存的时候就处理好key-value,提取的时候就会比较简单,这边我写好了,也就不想改了 T T;然后你就把get到的字符串setText到你的view控件上就ok了。
listview其实也是根据你读到的String,来放到适配器里,动动咱们的小脑瓜应该挺简单的。
然后对于recyclerview的adapter,课件中有给出对应类的样例代码WeatherAdapter的class,我们只需要把那个类中存recyclerview的数据的容器,改为我们之前代码中用到的ArrayList
private Handler handler=new Handler() { public void handleMessage(Message message){ Log.d("Tag","handle begin"); switch(message.what) { case 1: { String a=r; Log.d("Tag","String a "+r); parseXMLWithPull(r); String t=list.get(0).toString(); cityout.setText(t); t=list.get(3).toString(); update.setText(t+" 更新"); t=list.get(4).toString(); String son= t.substring(7); String[] cut=son.split(";"); fengli.setText(cut[1]); shidu.setText(cut[2]); wendu.setText(cut[0]); //Log.d("Tag","arraylist "+son); t=list.get(13); bodong.setText(t); t=list.get(5); cut=t.split("。"); zhiliang.setText(cut[1]); t=list.get(6); cut=t.split("。"); List<Map<String, Object>> dataa= new ArrayList<>(); simpleAdapter=new SimpleAdapter(MainActivity.this,dataa,R.layout.item,new String[]{"name"},new int[]{R.id.name}); for(int i=0;i<cut.length;i++) { Map<String, Object> temp = new LinkedHashMap<>(); temp.put("name",cut[i]); dataa.add(temp); } listview.setAdapter(simpleAdapter); ArrayList<Map<String,String>> weather_list=new ArrayList<Map<String,String>>(); ArrayList<String> list2=new ArrayList<String>(); for(int i=0;i<7;i++) { String tt=list.get(7+5*i)+" "+list.get(8+5*i); Log.d("Tag","tt : "+tt); cut=tt.split(" "); Map<String, String> temp = new LinkedHashMap<>(); temp.put("date",cut[0].toString());temp.put("weather",cut[1].toString());temp.put("fromto",cut[2].toString()); weather_list.add(temp); } WeatherAdapter adapter=new WeatherAdapter(MainActivity.this,weather_list); recyclerview.setAdapter(adapter); break; } } } };
说一下parseXMLWithPull函数吧。对于我们现在一个字符串形式表示的xml文件内容,先用函数转为XmlPullParser 对象实例,然后XmlPullParser 里面有现成的函数调用,会根据标签来一个个读入parser.getEventType();就是读取标签类型,在后面的类中的文件都有申明,有兴趣alt+函数名,自己可以一级一级跳下去看。每次判断标签,我们这次只要标签名为string的具体内容。每次获取后,都add到 list 里面。所以我们申请访问的网页最好具有一定的格式,这样我们的代码针对这个网站才具有普遍性。否则,每次都需要修改我们对字符串处理代码。
private void parseXMLWithPull(String xmlData){ try{ Log.d("TAG", "parseXMLWithPull: begin"); XmlPullParserFactory factory=XmlPullParserFactory.newInstance(); XmlPullParser parser=factory.newPullParser(); parser.setInput(new StringReader(xmlData)); int eventType=parser.getEventType(); list=new ArrayList<String>(); //Log.d("Tag","eventType"+eventType); while(eventType!=XmlPullParser.END_DOCUMENT){ switch (eventType) { case XmlPullParser.START_TAG: if("string".equals(parser.getName())){ String str=parser.nextText(); list.add(str); //Log.d("Tag","Get String "+str); } break; case XmlPullParser.END_TAG: break; default:break; } eventType=parser.next(); //Log.d("Tag","eventType"+eventType); } } catch (Exception e) { Log.d("Tag ","ERR "+e); } }
(2)实验遇到困难以及解决思路
一个就是导入recyclerview的jar包的时候,一开始,只是简单的复制到文件夹中,没有Add As Library. 还有就是在connection和DataOutputStream的时候有点乱,按字面意思是connection,已经建立连接了,但是还缺少参数citycode 和userID,所以DataOutputStream设置好后,应该吧参数一同跟之前的URL结合在一起生成一个正确的由内容的URL。后来经过试验,似乎是在DataOutputStream后getResponseCode才会建立连接,没有DataOutputStream,返回的getResponseCode是500报错
四、 课后实验结果
主界面
默认城市搜索
输入城市名搜索
五、 实验思考及感想
网络访问,其实最关键的就是跟URL地址建立连接,然后设置编码类型,来通过返回值,类型转换,获取该网页可读的xml文件内容,通过读别人的xml文件,也给我们一个启示就是,我们自己以后在写网页的时候,同类型的网页也要尽量写成固定格式,方便解析,有一定的通性,然后对于recyclerview,百度了一些,似乎是一个功能很丰富的listview,说到底,大致功能跟listview类似,但更强大,多样,当特定需要的时候,去百度以下资料,应用应该不难。
- 安卓
- 安卓
- 安卓
- 安卓
- 【安卓】
- 安卓
- 安卓
- 安卓
- 安卓
- 安卓
- 安卓
- 安卓
- 安卓
- 安卓学习-安卓环境布置
- 安卓开发-安卓启动过程
- 安卓开发-安卓与sqlite
- 安卓开发工具安卓
- 安卓断点续传支持安卓6.0
- 聚类概述
- 基本概念及操作
- 32位/64位系统,jdk32位,64位,32/64位jdk编译出来的class和eclipse 32位和64位
- git hub push 失败解决方案
- STM32F103/<3>在IAR中搭建工程框架
- 安卓
- C语言实验——图形输出(字符常量练习)
- 1009. Product of Polynomials (25)
- 软件常见故障的现象、故障排除的方法
- 百度地图官方Demo的运行使用
- 循环数组的最大子段和
- 第三十二讲项目4-输出星号正三角(4)
- sh获取当前正在执行脚本的绝对路径
- 根据类和返回值★产生临时量的几种情况