前言
最近老板给了个小任务,要求写一个android功能模块,用于校友信息查询。
需要用到简单的 http post向后端请求数据。
踩了几个坑,查了许多博客,总算是写完了。
代码
Talk is cheap, show me the code.
AndroidManifest.xml 授予权限
<manifest --->
---
<!-- 授予权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
---
</manifest>
布局文件 activity_main.xml 生成一个按钮
<LinearLayout>
---
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_search"
android:onClick="searchName" />
---
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.name_message);
}
/** Called when the user clicks the Search button */
public void searchName(View view){
// Get the message of name in response to button
EditText editText = (EditText) findViewById(R.id.edit_name);
final String name = editText.getText().toString();
//check the available of internet
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
// fetch data
//开发机(后端)ip 10.0.2.2
Log.d("test","Internet connected.");
post("http://10.0.2.2:8080/android/",name);//此处使用了http链接,则targetSdkVersion不能超过27,否则应改用https链接
}
/** Post the name to the server */
public void post(final String ur, final String name){
Log.d("test","Into the function named post.");
final Handler handler = new Handler();
new Thread() {//注意此处 在Android4.0以后,网络请求需要开子线程,否则报错
@Override
public void run(){
Log.d("test","Thread running.");
try {
URL url = new URL(ur);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
Log.d("test","Create http connection.");
connection.setConnectTimeout(3000);
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
//添加header参数
connection.setRequestProperty("Accept-Charset","UTF-8");
connection.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
Log.d("test", "connection setting over.");
connection.connect();
Log.d("test","HttpConnected.");
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
//添加body参数
//如有多个参数用&隔开
//如"name=" + name + "&age=" + age;
String content = "name=" + name;
outputStream.writeBytes(content);
outputStream.flush();
outputStream.close();
//接受数据
if(connection.getResponseCode()==HttpURLConnection.HTTP_OK){
// 获取来自网络的输入流
// 使用缓冲字符输入流
// 字节流转字符流
BufferedReader br = null;
br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
json="";
// 使用缓冲流读取到的每一行数据
String line = "";
while ((line = br.readLine()) != null) {
json += line.trim();
}
Log.d("test","Receive " + json);
// json数据产生完毕,该解析了
//由于子线程中不能安全的操作TextView
//故采用此法将服务器返回的数据显示于TextView
handler.post(runnableUi);
}
} catch (MalformedURLException e) {
Log.d("test","url error.");
e.printStackTrace();
} catch (IOException e) {
Log.d("test","io error.");
e.printStackTrace();
}
}
}.start();
}
Runnable runnableUi = new Runnable(){
@Override
public void run() {
//更新界面
textView.setText(json);
}
};
}
坑
-
权限问题
注意在AndroidManifest.xml中加入如下语句
<uses-permission android:name="android.permission.INTERNET" />
-
线程问题
Android4.0(sdk 14)以后,网络请求 需要开子线程,否则报错
-
明文链接问题
sdk 28 以后,Android禁止使用明文链接(http)
故而targetSdkVersion不得超过27 或 后端改用https