4.安卓基础之网络编程&json解析

1. ListView的使用步骤

  • 首先在layout文件中定义一个listview
  • 找到定义的listview控件,设置一个适配器(adapter)
  • 在适配器中将要绑定listview中的数据传递给adapter

MVC 的设计思想

  • M:数据
  • V:listview
  • C:adapter

2. AnimationDrawable 的使用:

  • 先在drawable准备好图片
  • xml文件里面设置根元素和子原始
  • 代码中调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
AnimationDrawable rocketAnimation;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
rocketAnimation.start();
return true;
}
return super.onTouchEvent(event);
}

3. Android的国际化相关

常见的有:
zh_cn: 简体中文
zh_hk: 繁体中文(中国香港)
zh_tw: 繁体中文(中国台湾地区)
en-hk: 英语(香港)
en_us: 英语(美国)
en_gb: 英语(英国)
en_ww: 英语(全球)
ja_jp: 日语(日本)
ko_kr: 韩文(韩国)

在Android工程的res目录下,通过定义特殊的文件夹名称就可以实现多语言支持.比如我们的程序兼容简体中文/英文,在values文件夹中建立默认strings.xml,再建立values-zh-rCN文件夹.

在每个文件夹里放置一个strings.xml,strings.xml里是各种语言字符串.如果涉及到参数配置类xml文件夹名称也要改成xml-zh/xml.这样在android的系统中进行语言切换,所开发的程序也会跟着切换语言.

1
2
3
4
5
Resources resources = getResources();//获得res资源对象
Configuration config = resources.getConfiguration();//获得设置对象
DisplayMetrics dm = resources .getDisplayMetrics();//获得屏幕参数:主要是分辨率,像素等.
config.locale = Locale.SIMPLIFIED_CHINESE; //简体中文
resources.updateConfiguration(config, dm);

4. Android 连接网络,获得数据

  • 先定义一个秘书:Handler handler = new Handler()
  • 获取到一个篮子:Message msg = Message.obtain();
  • 让篮子交给秘书处理:msg.obj = data;
    通过生活的例子融入代码的想法中,在耗时的事儿不允许放在主线程中去完成.

4.1 在线获得网址的图片

  • 需要在AndroidManifest.xml开启权限
1
<uses-permission android:name="android.permission.INTERNET"/>
  • 在主线程重写handler的handleMessage( )方法,在工作线程发送消息.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
public class MainActivity extends AppCompatActivity {
protected static final int SUCCESS = 0;
protected static final int NETWORK_ERROR = 1;
protected static final int ERROR = 2;
private EditText ed_path;
private ImageView iv;
private String path;
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case SUCCESS:
//取出消息中的数据
Bitmap bitmap = (Bitmap) msg.obj;
iv.setImageBitmap(bitmap);
break;
case NETWORK_ERROR:
Toast.makeText(MainActivity.this, "连接错误 ....", 0).show();
break;
case ERROR:
Toast.makeText(MainActivity.this, " 获得资源失败 ....", 0).show();
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed_path = (EditText) findViewById(R.id.ed_path);
iv = (ImageView) findViewById(R.id.iv);
}
public void gogetImage(View v){
path = ed_path.getText().toString().trim();
if(TextUtils.isEmpty(path)){
Toast.makeText(this, "路径有错误...", 0).show();
return;
}
new Thread(){
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
//设置请求的方式
conn.setRequestMethod("GET");
//拿到返回的数据的类型
String contentType = conn.getContentType();
//数据的长度
int length = conn.getContentLength();
// 获得服务器返回的状态码 , 根据状态码去判断是否成功
int code = conn.getResponseCode();
if(code==200){
InputStream in = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(in);
Message msg = Message.obtain();
msg.what=SUCCESS;
msg.obj = bitmap;
mHandler.sendMessage(msg);
in.close();
}else{
Message msg = Message.obtain();
msg.what=ERROR;
mHandler.sendMessage(msg);
}
} catch (Exception e) {
Message message = Message.obtain();
message.what= NETWORK_ERROR;
mHandler.sendMessage(message);
e.printStackTrace();
}
};
}.start();
}
}
  • activity_main.xml的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
tools:context=".MainActivity"
xmlns:android="http://schemas.android.com/apk/res/android">
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/ed_path"/>
<Button
android:onClick="gogetImage"
android:text="Get"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/iv"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>

4.2 网页源码查看器的实现

  • 需要在AndroidManifest.xml开启权限
1
<uses-permission android:name="android.permission.INTERNET"/>
  • 在主线程中重写hander的handleMessage()方法,让工作线程发送信息.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public class MainActivity extends AppCompatActivity {
protected static final int SUCCESS = 0;
protected static final int ERROR = 1;
protected static final int NETWORK_ERROR = 2;
private EditText ed_path;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed_path = (EditText) findViewById(R.id.ed_path);
tv = (TextView)findViewById(R.id.tv);
}
//定义一个秘书
Handler handler = new Handler(){
public void handleMessage(Message msg){
switch (msg.what){
case SUCCESS:
String value = (String) msg.obj;
tv.setText(value);
break;
case ERROR:
Toast.makeText(MainActivity.this,"ERROR",0).show();
break;
case NETWORK_ERROR:
Toast.makeText(MainActivity.this,"NETWORK_ERROR",0).show();
break;
default:
break;
}
}
};
String path = null;
public void viewPageSource(View view){
path = ed_path.getText().toString().trim();
if(TextUtils.isEmpty(path)){
Toast.makeText(MainActivity.this,"PATH NOT NOT!",0).show();
return;
}
//否则连接网络,启动一个新的线程
new Thread(){
public void run(){
try{
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//设置连接超时为5秒钟
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
//这句能伪装成电脑访问
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
String contentType = conn.getContentType();
int code = conn.getResponseCode();
if(code == 200){
InputStream in = conn.getInputStream();
String data = StreamTool.decodeStream(in);
//Message 称为篮子
Message msg = Message.obtain();
msg.what = SUCCESS;
msg.obj = data;
handler.sendMessage(msg);
}else{
Message msg = Message.obtain();
msg.what = ERROR;
handler.sendMessage(msg);
}
}catch (Exception e){
Message msg = Message.obtain();
msg.what = NETWORK_ERROR;
handler.sendMessage(msg);
}
}
}.start();
}
  • 定义一个底层流实现代码
1
2
3
4
5
6
7
8
9
10
11
public static String decodeStream(InputStream in) throws IOException{
//底层流
ByteArrayOutputStream bas = new ByteArrayOutputStream();
int len = 0;
byte[] buf = new byte[1024];
while ((len=in.read(buf))>0){
bas.write(buf,0,len);
}
String data = bas.toString();
return data;
  • activity_mail.xml的编写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<EditText
android:id="@+id/ed_path"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="http://www.itceo.net"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="viewPageSource"
android:text="显示"/>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</ScrollView>
</LinearLayout>

4.3 解析json格式的数据

  • 需要在AndroidManifest.xml开启权限
1
<uses-permission android:name="android.permission.INTERNET"/>
  • 在主线程中重写hander的handleMessage()方法,让工作线程发送信息.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
public class MainActivity extends AppCompatActivity {
private EditText ed_city;
private TextView city_result1;
private TextView city_result2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed_city = (EditText) findViewById(R.id.ed_city);
city_result1 = (TextView) findViewById(R.id.city_result1);
city_result2 = (TextView) findViewById(R.id.city_result2);
}
private final static String PATH = "http://wthrcdn.etouch.cn/weather_mini?city=";
protected static final int SUCCESS = 0;
protected static final int INVALID_CITY = 1;
protected static final int ERROR = 2;
private String city;
String ul;
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case SUCCESS:
try {
JSONArray data = (JSONArray) msg.obj;
String day01 = data.getString(0);
city_result1.setText(day01);
String day02 = data.getString(1);
city_result2.setText(day02);
} catch (Exception e) {
e.printStackTrace();
}
break;
case INVALID_CITY:
Toast.makeText(MainActivity.this, "城市无效", 0).show();
break;
case ERROR:
Toast.makeText(MainActivity.this, "网络问题", 0).show();
break;
default:
break;
}
};
};
public void searchCityWeather(View v){
city = ed_city.getText().toString().trim();
if(TextUtils.isEmpty(city)){
Toast.makeText(this, "路径错误...", 0).show();
return;
}
//http://wthrcdn.etouch.cn/weather_mini?city=%E6%B7%B1%E5%9C%B3
new Thread(){
public void run() {
try {
ul = PATH + URLEncoder.encode(city, "UTF-8");
URL url = new URL(ul);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置必要的参数信息
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
//判断响应码
int code = conn.getResponseCode();
if(code==200){
InputStream in = conn.getInputStream();
String data = StreamTool.decodeStream(in);
System.out.println(data);
//解析json格式的数据
JSONObject jsonObj = new JSONObject(data);
// 获得desc的值
String result = jsonObj.getString("desc");
if("OK".equals(result)){
//城市有效,返回了需要的数据
JSONObject dataObj = jsonObj.getJSONObject("data");
JSONArray jsonArray = dataObj.getJSONArray("forecast");
//通知更新ui
Message msg = Message.obtain();
msg.obj = jsonArray;
msg.what=SUCCESS;
mHandler.sendMessage(msg);
}else{
//城市无效
Message msg = Message.obtain();
msg.what=INVALID_CITY;
mHandler.sendMessage(msg);
}
}
} catch (Exception e) {
e.printStackTrace();
Message msg = Message.obtain();
msg.what=ERROR;
mHandler.sendMessage(msg);
}
};
}.start();
}
}
  • 定义一个底层流实现代码
1
2
3
4
5
6
7
8
9
10
public static String decodeStream(InputStream in) throws IOException{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = 0;
byte[] buf = new byte[1024];
while ((len=in.read(buf))>0){
baos.write(buf,0,len);
}
String data = buf.toString();
return data;
}
  • activity_mail.xml的编写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请输入要查询的城市"/>
<EditText
android:id="@+id/ed_city"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:onClick="searchCityWeather"
android:text="查询"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/city_result1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/city_result2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

4.4 联网解析xml格式的数据

  • 需要在AndroidManifest.xml开启权限
1
<uses-permission android:name="android.permission.INTERNET"/>
  • 在主线程重写handler的handleMessage( )方法,在工作线程发送消息.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
public class MainActivity extends AppCompatActivity {
protected static final int SUCCESS = 0;
protected static final int ERROR = 1;
private EditText ed_phone;
private TextView tv_phonenumber;
private TextView tv_phonelocation;
private TextView tv_phonejx;
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
dialog.dismiss();
switch (msg.what) {
case SUCCESS:
p = (Product) msg.obj;
if(p!=null){
tv_phonenumber.setText(p.getPhonenum());
tv_phonelocation.setText(p.getLocation());
tv_phonejx.setText(p.getPhoneJx());
}
break;
case ERROR:
Toast.makeText(MainActivity.this, "对不起, 俺比较忙, 稍后再来 ", 0).show();
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed_phone = (EditText) findViewById(R.id.ed_phone);
tv_phonenumber = (TextView) findViewById(R.id.tv_phonenumber);
tv_phonelocation = (TextView) findViewById(R.id.tv_phonelocation);
tv_phonejx = (TextView) findViewById(R.id.tv_phonejx);
}
String number;
Product p = null;
ProgressDialog dialog = null;
public void getPhoneJX(View v){
number = ed_phone.getText().toString().trim();
if(TextUtils.isEmpty(number)){
Toast.makeText(this, "手机号码 错误 ", 0).show();
return;
}
// http://www.096.me/api.php?phone=13691689110&mode=xml
final String path ="http://www.096.me/api.php?phone="+number+"&mode=xml";
dialog = new ProgressDialog(this);
dialog.setMessage("正在玩命加载中...");
dialog.show();
new Thread(){
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
if(code==200){
InputStream in = conn.getInputStream();
String data = StreamTool.decodeStream(in);
XmlPullParser parser = Xml.newPullParser();
if(data.contains("gbk")){
parser.setInput(in, "gbk");
}else if(data.contains("UTF-8")){
parser.setInput(in, "UTF-8");
}
//以后注意, 只要出现乱码, 确保 解析的 编码和 发过来的编码一致 , 就不会有什么问题了.
//获得事件的类型
int eventType = parser.getEventType();
//
while(eventType!=XmlPullParser.END_DOCUMENT){
// .. //准备 一个javabean ,封装数据到 bean 中 -- Product
/*
<smartresult>
<product type="mobile">
<phonenum>13691689110</phonenum>
<location>广东深圳移动神州行卡</location>
<phoneJx>惨淡经营,难免贫困,此数不吉,最好改名 凶</phoneJx>
</product>
</smartresult>
*/
if(eventType==XmlPullParser.START_TAG){
if("product".equals(parser.getName())){
// new 一个product ,准备封装数据
String type = parser.getAttributeValue(0);
p = new Product();
p.setType(type);
}else if("phonenum".equals(parser.getName())){
p.setPhonenum(parser.nextText());
}else if("location".equals(parser.getName())){
p.setLocation(parser.nextText());
}else if("phoneJx".equals(parser.getName())){
p.setPhoneJx(parser.nextText());
}
}
eventType =parser.next();
}
//发消息 , 通知秘书去更新UI
Message msg = Message.obtain();
msg.what=SUCCESS;
msg.obj = p;
mHandler.sendMessage(msg);
in.close();
}
} catch (Exception e) {
e.printStackTrace();
Message msg = Message.obtain();
msg.what=ERROR;
mHandler.sendMessage(msg);
}
};
}.start();
}
}
  • 定义一个底层流实现代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.javami.unitls;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by 诸葛亮 on 2016/10/30.
*/
public class StreamTool {
public static String decodeStream(InputStream in) throws IOException{
//底层流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = 0;
byte[] buf = new byte[1024];
while((len=in.read(buf))>0){
baos.write(buf,0,len);
}
String data = baos.toString();
if (data.contains("gbk")){
return baos.toString("gbk");
}else if(data.contains("utf-8")){
return baos.toString("utf-8");
}else{
return data;
}
}
}
  • 定义Product封装数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.javami.unitls;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by 诸葛亮 on 2016/10/30.
*/
public class StreamTool {
public static String decodeStream(InputStream in) throws IOException{
//底层流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = 0;
byte[] buf = new byte[1024];
while((len=in.read(buf))>0){
baos.write(buf,0,len);
}
String data = baos.toString();
if (data.contains("gbk")){
return baos.toString("gbk");
}else if(data.contains("utf-8")){
return baos.toString("utf-8");
}else{
return data;
}
}
}
  • activity_mail.xml的编写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请输入手机号码" />
<EditText
android:inputType="phone"
android:id="@+id/ed_phone"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:onClick="getPhoneJX"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_phonenumber"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/tv_phonelocation"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/tv_phonejx"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>