安卓网络访问
点击获取完整APK资源下载地址
http://download.csdn.net/detail/mjdouble/9694686
本次实验基于一个如下网站
http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?op=getWeather
设置一个app界面,输入城市名,即查询该CityCode的天气情况,对返回的XML文件进行解析后,在app中显示。如下(这就是最后的结果啦,当然根据你输入的城市不同,结果不同,输入城市名和城市代号都是可以识别的)
T T理工男,请无视我的界面设计
XML文件内容如下所示(本是要就要解析xml文件获取string标签中的内容,按我们喜欢的格式在app中显示。)
APP开始界面如下所示(那啥,这些都是我初始默认的不用管,就这么个布局)
首先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进行操作,所以实时的吧,最后吧连接断掉,开启线程。
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();
DataOutputStream out=new DataOutputStream(connection.getOutputStream());
out.writeBytes("theCityCode="+request+"&theUserID=ecefcf4c81b847a189ff94a159d54dd0");//theUserID是本人在那个网站申请的ID,暂时应该还可以用
int back =connection.getResponseCode();
Log.d("Tag","The response is"+back);
InputStream in=connection.getInputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
StringBuilder response=new StringBuilder();
String line=new String();
while((line=reader.readLine())!=null)
{
response.append(line);
}
Message message=new Message();
//message.what=1;
//message.obj=parseXMLWithPull(response.toString());
handler.sendEmptyMessage(1);
r=new String();
r=response.toString();
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,来放到适配器里,动动咱们的小脑瓜应该挺简单的。
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);
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);
}
}