Android入门学习:简单的联网app编写
在上次学习了Android的基本开发环境搭建、基本GUI编写之后,最近开始做移动互联的大作业了。这里记录下自己的学习历程,包括以下内容:
- 访问网站获取资源
- 在子线程中更新ui
访问网站获取资源
访问网站的方法我用的是最基础的HttpURLConnection。访问中要设置以下参数:
URL,访问方式(POST,GET),时间限制,请求头部,是否进行输入输出操作。
以下操作皆以json数据类型为对象。
public void JsonPost(final String path, final JSONObject json) {
new Thread(new Runnable() {
@Override
public void run() {
OutputStream os = null;
BufferedReader in = null;
String result = "";
try {
URL url = new URL(path);
String content = String.valueOf(json);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);//设置超时时间
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");//设置请求头部,一般用于身份验证什么的
os = conn.getOutputStream();
os.write(content.getBytes("utf-8"));
os.flush();
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
if (conn.getResponseCode() == 200) {
while ((line = in.readLine()) != null) {
result += line;//结果存于result中以String保存
}
}
} catch (SocketTimeoutException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (os != null) {
os.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
Message ms=new Message();
ms.obj=result;
handler.sendMessage(ms);
}
}).start();
}
这里将访问网站的地址,需要传入的json作为参数(必须都标注为final否则报错),通过 HttpURLConnection conn = (HttpURLConnection) url.openConnection();打开连接,由于这里是POST传入参数,故要加一句conn.setDoOutput(true);,这样边允许向内传入参数。访问网站的整个过程都需要在一个子线程内执行。
还有别忘了建立完子线程要启动,一开始忘了加start()半天没反应。。
下面是GET方法的例子,添加了更多的请求头部:
public void getGroup(final String path,final String token) {
new Thread(new Runnable() {
@Override
public void run() {
String base64Token = Base64.encodeToString(token.getBytes(), Base64.DEFAULT);
OutputStream os = null;
BufferedReader in = null;
String result = "";
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setDoOutput(false);
// conn.setDoInput(true);
conn.setRequestMethod("GET");
// conn.setRequestProperty("Content-Type", "application/json");
String auth="Basic"+" "+base64Token;
conn.setRequestProperty("Authorization",auth);
conn.setRequestProperty("Charset", "UTF-8");
Log.d("token",auth);
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
if (conn.getResponseCode() == 200) {
while ((line = in.readLine()) != null) {
result += line;
}
}
} catch (SocketTimeoutException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
if (os != null) {
os.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
Message ms=new Message();
ms.obj=result;
handler.sendMessage(ms);
}
}).start();
}
这里与前面不同的是,由于是GET方法,必须加一句conn.setDoOutput(false);,否则即使设置为GET方法也会成为POST,调用会出现java.io.filenotfoundexception错误。
在子线程中更新ui
如果在子线程里直接根据网站返回的信息更新UI,APP会直接崩溃,这是因为子线程是不被允许更改UI控件的,只有主线程才行,这里我用的是添加一个Handle,他是属于主线程的一部分故不会出现上面的问题。
private Handler handler=new Handler(){
public void handleMessage(Message message){
text.setText((String)message.obj);
}
};
在子线程中调用:
Message ms=new Message();
ms.obj=result;
handler.sendMessage(ms);
这里通过message.obj属性将字符串result传入,然后在handle内再取出转换类型。
注意传入时用sendMessage,处理是用handleMessage,一开始没注意两个都用handleMessage,然后就报错了。。
附上最后效果