編輯:關於Android編程
該博文中內容通過老師上課的內容對於Android下的網絡通信編程等內容進行總結;
1、Android網絡編程初識
2、Android實現HTML源碼查看
3、Android實現網絡圖片查看
4、Android實現與服務器上JavaWeb項目交互
1、Android網絡編程初識
Android手機終端作為客戶端發送Http請求到終端服務器上,並且當發送請求到服務器,如果請求成功,響應碼:200;服務器會通過客戶端返回請求並且處理後的信息數據,一般情況下,在正式項目中多用JSON,不會使用沒有規定格式的文本信息; 注意事項:Android的網絡操作在Android4之後,就不能夠將Android的網絡操作寫在主線程中除了會直接造成應用崩潰之外,還因為一旦造成主線程阻塞,應用會停止刷新界面,停止響應用戶任何操作,用戶體驗非常差,所以耗時操作不要寫在主線程中; 將於網路連接部分寫在子線程中,再通過handler實現了通信的相關操作。
2、Html源文件查看器(掌握)
發送GET請求
public class MainActivity extends Activity {
private Handler handler;
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) this.findViewById(R.id.tv);
handler = new Handler() {
//重寫消息隊列方法
@Override
public void handleMessage(Message msg) {
tv.setText((String) msg.obj);
}
};
}
public void click(View view) {
final String path = "http://192.168.1.109:8080/baidu.html";
Thread thread = new Thread() {
@Override
public void run() {
try {
//使用網址創建URL
URL url = new URL(path);
//獲取連接對象做設置
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//設置請求方式
conn.setRequestMethod("GET");
//設置超時時間
conn.setConnectTimeout(8000);
//設置讀取超時的時間
conn.setReadTimeout(8000);
//連接
conn.connect();
//連接成功
if(conn.getResponseCode() == 200) {
System.out.println("Connected======");
InputStream is = conn.getInputStream();
String text = StreamTool.getTextFromStream(is);
Message msg = handler.obtainMessage();
msg.obj = text;
handler.sendMessage(msg);
} else if(conn.getResponseCode() == 404) {
}
} catch (MalformedURLException e) {
System.out.println("MalFormed Exception=");
} catch (IOException e) {
System.out.println("IOException");
}
}
};
thread.start();
}
}
在上面的代碼中獲取服務器返回的流,從流中把html源碼讀取出來
InputStream is = conn.getInputStream();
String text = StreamTool.getTextFromStream(is);
Message msg = handler.obtainMessage();
msg.obj = text;
handler.sendMessage(msg);
////////////////////////
handler = new Handler() {
//重寫消息隊列方法
@Override
public void handleMessage(Message msg) {
tv.setText((String) msg.obj);
}
};
亂碼的處理 亂碼的出現是因為服務器和客戶端碼之間的編碼表的不一致所導致的,所以自己寫一個專門處理亂碼的工具類方便調用
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class StreamTool {
public static String getTextFromStream(InputStream is) {
byte[] buffer = new byte[1024];
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
while((len = is.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
//利用字節數組輸出流轉換成字節數組,然後用字節數組構造成為一個字符串
String text = new String(bos.toByteArray());
return text;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}
3、Android實現網絡圖片查看
確定圖片的網址 實現功能
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
/**
* 幾個知識點必須要掌握的:
* 1、4.3版本以上的編程規范,否則谷歌會強制不予執行,應為為了用戶體驗不會讓主線程出現長時間的阻塞,否則會造成用戶體驗變差;
* 2、在新創建出來的線程中不可以直接使用UI否則會出現
* 11-25 02:27:08.884: E/AndroidRuntime(7093): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
* 錯誤,是因為在子線程中會丟失對於UI的相關的參數設置
* 3、消息隊列相關的概念必須要很好的掌握,在主線程開始創建的是會提供對應的詳細隊列的機制,並且會用Logger消息輪詢器進行檢索訪問
* @author DELL
*
*/
public class MainActivity extends Activity {
private ImageView iv;
private Bitmap bm;
@SuppressLint("HandlerLeak")
Handler handler = new Handler() {
//只要消息隊列中有消息,此方法就會在主線程中執行
public void handleMessage(android.os.Message msg) {
//在這裡進行消息隊列的刷新,從而達到刷新UI的目的
switch (msg.what) {
case 1:
iv = (ImageView) findViewById(R.id.iv);
iv.setImageBitmap((Bitmap)msg.obj);
break;
case 2:
Toast.makeText(MainActivity.this, "加載視圖失敗", Toast.LENGTH_SHORT).show();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//版本在4.0以上必須要使用的兩個操作
//1、事件添加的時候需要新建線程
//2、設置builder
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
}
/**
* 注意一點只有主線程可以刷新UI
* @param view
*/
public void clickload(View view) {
final String path = "http://192.168.2.197:8080/img/e.jpg";
final File file = new File(getCacheDir(),getFileNameFromPath(path));
if(file.exists()) {
System.out.println("============緩存獲取==============");
bm = BitmapFactory.decodeFile(file.getAbsolutePath());
Message msg = new Message();
msg.obj = bm;
msg.what = 1;
handler.sendMessage(msg);
} else {
System.out.println("============網絡獲取==============");
Thread thread = new Thread(){
@Override
public void run() {
try { //發送http請求的操作步驟
//1、創建URL對象
URL url = new URL(path);
//2、獲取連接對象
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//3、設置一些屬性
//設置請求方式,注意大寫
conn.setRequestMethod("GET");
//設置請求超時
conn.setConnectTimeout(8000);
//設置讀取超時
conn.setReadTimeout(8000);
//4、發送請求建立連接
conn.connect(); /*可能阻塞的位置*/
//5、判斷請求是否成功
if(conn.getResponseCode() == 200) { /*可能阻塞的位置*/
//獲取服務器返回的劉,流中就是客戶端的請求數據
System.out.println("====true");
InputStream is = conn.getInputStream();
//現在需要我們自己讀取流中的數據,讀取1K,就可以把1K寫到本地文件緩存起來
byte[] buffer = new byte[1024];
int len ;
FileOutputStream fos = new FileOutputStream(file);
while((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
fos.close();
//緩存時候已經將緩存中的數據讀取完了,所以流中取不到任何數據
// bm = BitmapFactory.decodeStream(is);
bm = BitmapFactory.decodeFile(file.getAbsolutePath());
//當子線程需要刷新UI的時候,只需要發送一條消息到消息隊列
//發送消息的方法,在另一端接受消息隊列
Message msg = new Message();
//消息對象本身是可以攜帶數據的
msg.obj = bm;
//使用what標注消息是什麼類型
msg.what = 1;//我自身定義1表示成功
handler.sendMessage(msg);
} else {
//創建消息對象
//如果消息池中有消息,取出消息池中第一條消息
//返回,如果沒有,就new一個消息返回
Message msg = handler.obtainMessage();
msg.what = 2;//我自身定義2表示加載失敗
handler.sendMessage(msg);
System.out.println("====false");
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.e("MalformedURLException", "URL創建過程出錯");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("IOException", "HttpURLConnection出錯");
}
}
};
thread.start();
}
}
//路徑獲取圖片文件名稱
public String getFileNameFromPath(String path) {
int index = path.lastIndexOf("/");
return path.substring(index+1);
}
}
4、Android實現與服務器上JavaWeb項目交互
普通方式:使用GET方式提交表單 首先實現一個工具類:
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
public class Tools {
public static String getTextFromStream(InputStream is) {
byte[] buffer = new byte[1024];
int len;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
while((len = is.read(buffer))!=-1) {
bos.write(buffer,0,len);
}
String text = new String(bos.toByteArray(),"utf-8");
return text;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
服務端
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
System.out.println("======GET======");
String username = request.getParameter("username");
String password = request.getParameter("password");
username = new String(username.getBytes("ISO-8859-1"),"utf-8");
password = new String(password.getBytes("ISO-8859-1"),"utf-8");
username = username.trim();
password = password.trim();
System.out.println(username + " " + password);
if("admin".equalsIgnoreCase(username)) {
response.getWriter().print("登陸成功");
} else {
response.getWriter().print("登陸失敗");
}
}
Android 客戶端
public class MainActivity extends Activity {
private EditText et_username;
private EditText et_password;
private String username;
private String password;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Toast.makeText(MainActivity.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(MainActivity.this, "網絡異常", Toast.LENGTH_SHORT).show();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_username = (EditText) this.findViewById(R.id.username);
et_password = (EditText) this.findViewById(R.id.password);
}
public void login(View view) {
username = et_username.getText().toString().trim();
password = et_password.getText().toString().trim();
Thread thread = new Thread() {
String path = "http://192.168.1.105:8080/AndroidWebServerDemo/Login?username=+"+URLDecoder.decode(username)+"+&password=+"+URLDecoder.decode(password);
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(8000);
conn.setReadTimeout(8000);
conn.setRequestMethod("GET");
conn.connect();
if(conn.getResponseCode() == 200) {
InputStream is = conn.getInputStream();
String text = Tools.getTextFromStream(is);
System.out.println(text);
Message msg = new Message();
msg.obj = text;
msg.what = 1;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
}
}
普通方式:使用POST方式提交表單 服務端
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
System.out.println("======POST======");
String username = request.getParameter("username");
String password = request.getParameter("password");
// username = new String(username.getBytes("ISO-8859-1"),"utf-8");
// password = new String(password.getBytes("ISO-8859-1"),"utf-8");
username = username.trim();
password = password.trim();
System.out.println(username + " " + password);
if("admin".equalsIgnoreCase(username)) {
response.getWriter().print("登陸成功");
} else {
response.getWriter().print("登陸失敗");
}
}
Android 客戶端 readTool類與上文中GET方式的Tool相同
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.android.getmethod.R;
import com.android.postmethod.read.tools.Tools;
public class MainActivity extends Activity {
private EditText et_username;
private EditText et_password;
private String username;
private String password;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Toast.makeText(MainActivity.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(MainActivity.this, "網絡異常", Toast.LENGTH_SHORT).show();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_username = (EditText) this.findViewById(R.id.username);
et_password = (EditText) this.findViewById(R.id.password);
}
public void login(View view) {
username = et_username.getText().toString().trim();
password = et_password.getText().toString().trim();
Thread thread = new Thread() {
String path = "http://192.168.1.105:8080/AndroidWebServerDemo1/Login";
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(8000);
conn.setReadTimeout(8000);
conn.setRequestMethod("POST");
//添加POST請求頭中自動添加的屬性
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
//方便服務器端的程序員,通過程序的這個數據知道數據的大小
//實現動態的大小長度
String content_text = "username="+ URLEncoder.encode(username) + "&password=" + password;
//流中數據的長度
conn.setRequestProperty("Content-Length", content_text.length()+"");
//打開連接對象的輸出流
conn.setDoOutput(true);
//把數據寫入到輸入流中
OutputStream os = conn.getOutputStream();
//將數據寫入到輸出流中
os.write(content_text.getBytes());
conn.connect();
if(conn.getResponseCode() == 200) {
InputStream is = conn.getInputStream();
String text = Tools.getTextFromStream(is);
System.out.println(text);
Message msg = new Message();
msg.obj = text;
msg.what = 1;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
thread.start();
}
}
使用HTTPClient的方式實現與服務器的數據交互 GET方式(HTTPClient)
public class MainActivity extends Activity {
private EditText et_username;
private EditText et_password;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
String text = (String) msg.obj;
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_username = (EditText) this.findViewById(R.id.username);
et_password = (EditText) this.findViewById(R.id.password);
}
public void login(View view) {
//獲取用戶輸入的賬號密碼
Thread thread = new Thread() {
String username = et_username.getText().toString();
String password = et_password.getText().toString();
final String path = "http://192.168.1.105:8080/AndroidWebServerDemo1/Login?" +
"username="+username+"&password="+password;
public void run() {
System.out.println("=============================================="+path);
//創建HttpClient對象
HttpClient client = new DefaultHttpClient();
//創建get請求對象
HttpGet get = new HttpGet(path);
try {
//使用client發送get請求
HttpResponse response = client.execute(get);
//獲取狀態行
StatusLine line = response.getStatusLine();
//獲取狀態碼
if(line.getStatusCode() == 200) {
System.out.println("==============================================200");
//獲取實體對象
InputStream is = response.getEntity().getContent();
String text = Tools.getTextFromStream(is);
Message msg = handler.obtainMessage();
msg.obj = text;
handler.sendMessage(msg);
} else {
System.out.println("=============================================="+line.getStatusCode());
}
} catch (Exception e) {
System.out.println("==============================================錯誤");
e.printStackTrace();
}
};
};
thread.start();
}
}
POST 方式(HTTPClient)
public class MainActivity extends Activity {
private EditText et_username;
private EditText et_password;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
String text = (String) msg.obj;
Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT).show();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_username = (EditText) this.findViewById(R.id.username);
et_password = (EditText) this.findViewById(R.id.password);
}
public void login(View view) {
//獲取用戶輸入的賬號密碼
Thread thread = new Thread() {
String username = et_username.getText().toString();
String password = et_password.getText().toString();
final String path = "http://192.168.1.105:8080/AndroidWebServerDemo1/Login";
public void run() {
System.out.println("====="+path);
//創建HttpClient對象
HttpClient client = new DefaultHttpClient();
//創建post請求對象
HttpPost post = new HttpPost(path);
//將數據封裝到post中
List parameters = new ArrayList();
//arg0:表單的名字
//arg1:表單中的值
BasicNameValuePair bnvp1 = new BasicNameValuePair("username", username);
BasicNameValuePair bnvp2 = new BasicNameValuePair("password", password);
parameters.add(bnvp1);
parameters.add(bnvp2);
//創建實體對象
UrlEncodedFormEntity entity = null;
try {
//將集合對象封裝到實體中
entity = new UrlEncodedFormEntity(parameters,"utf-8");
post.setEntity(entity);
//數據響應
HttpResponse response = client.execute(post);
if(response.getStatusLine().getStatusCode() == 200) {
InputStream is = response.getEntity().getContent();
String text = Tools.getTextFromStream(is);
Message msg = handler.obtainMessage();
msg.obj = text;
msg.what = 1;
handler.sendMessage(msg);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
};
};
thread.start();
}
}
WeTest導讀說起Android的自動化測試,相信有很多小伙伴都接觸過或者有所耳聞,本文從框架最基本的功能介紹及API的使用入手,結合簡單的項目實戰來幫忙大家對該框架進
在Android開發中,我們經常會遇到這樣一種情況:在UI界面上進行某項操作後要執行一段很耗時的代碼,比如我們在界面上點擊了一個”下載“按鈕,那麼我們需要執行網絡請求,這
信自己也是一種信仰。寫在前面的話3月初我在自定義控件概述中挖下的幾個坑,前一段時間已經基本填完了,自定義控件的幾種實現方式也分別寫了demo來進行說明。今天我們來聊一聊
開發一個需要常住後台的App其實是一件非常頭疼的事情,不僅要應對國內各大廠商的ROM,還需要應對各類的安全管家...雖然不斷的研究各式各樣的方法,但是效果並不好,比如任務