編輯:關於Android編程
兩周廢寢忘食的創作終於成功了,現在拿出來分享一下。
先不說別的看一下程序運行效果圖,我沒怎麼設計ui所以界面不是很好看但是能說明問題~~~
現在我們來看看實現這個功能需要些什麼准備工作,我們需要網絡信息抓取工具一般windows可以用httpwatch我是mac系統所以我詳細介紹一下mac上面的工具
1.Charles
2.Google Chrome
接下來就可以進行網頁信息抓包了,先看一下我們學校的教務網頁
然後我們開始進行對浏覽器抓包我使用的是Charles首先要配置成下圖這個樣子然後才可以抓包
首先對登錄信息抓包時要找下面這張截圖上的信息
然後對獲取驗證嗎抓包
我們在response中可以看到返回信息
然後我們需要下載一個解析HTML源碼的架構包叫Jsoup放到libs目錄下然後右鍵選擇
as library
這些就准備好了然後我們來看一小段HTML代碼方便解析時候講解
可以看到我們需要的信息都被一個一個的標簽包裹著,Jsoup所做的就是將我們需要的信息從標簽裡剝離出來。
然後我們來看代碼實現,我這裡分了兩個Activity來實現
1.MainActivity
public class MainActivity extends ActionBarActivity { //使用SharedPreferences進行用戶的用戶名密碼以及cookie的保存 SharedPreferences sharedPreferences; SharedPreferences.Editor editor; private EditText studentNumber; private EditText passWord; private EditText idCode; private Bitmap bitmap; private ImageView IdcodeImage; //注意這裡Handler使用的是import android.os.Handler;這個包 private Handler handler; private Button logIn; String StudentNumber; String PassWord; String IdCode; String groupId=""; String login="登錄"; //這條是解析出來進行獲取驗證碼的圖片的網址 String url2="http://jw.djtu.edu.cn/academic/getCaptcha.do"; //這條是解析出來進行提交登錄信息的網址 String url3="http://jw.djtu.edu.cn/academic/j_acegi_security_check"; //這裡使用HttpClient進行數據的獲取和提交 HttpClient client; @Override protected void onCreate(final Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //實例化HttpClient對象 client=new DefaultHttpClient(); //sharedPreferences第一個參數是給你保存的信息起個名字,第二個參數設置為Context.MODE_PRIVATE屬性, // 這樣會避免其他應用可以直接訪問我們保存的信息 sharedPreferences=getSharedPreferences("params", Context.MODE_PRIVATE); //實例化SharedPreferences.Editor對象 editor=sharedPreferences.edit(); studentNumber=(EditText)findViewById(R.id.studentNumber); passWord=(EditText)findViewById(R.id.key); IdcodeImage=(ImageView)findViewById(R.id.passImage); idCode=(EditText)findViewById(R.id.identifyingCode); logIn=(Button)findViewById(R.id.login); //實例化Handler對象方便線程之間通信 handler=new Handler(); //對我們的驗證碼綁定一個單擊響應事件,這是為了去實現驗證碼看不清時再更新一張驗證碼而用 IdcodeImage.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread() { @Override public void run() { //我們需要同步Cookie信息所以從驗證碼開始就需要獲取Cookie List2.Score_find Activitycookies1; //HttpGet來發送獲取驗證碼請求 HttpGet httpGet = new HttpGet(url2); //聲明一個HttpResponse HttpResponse httpResponse = null; try { //實例化HttpResponse httpResponse = client.execute(httpGet); } catch (IOException e) { e.printStackTrace(); } //如果服務器響應成功 if (httpResponse.getStatusLine().getStatusCode() == 200) { try { //使用輸入流來接受數據 InputStream in = httpResponse.getEntity().getContent(); //bitmap來獲取數據流中的圖片信息 bitmap = BitmapFactory.decodeStream(in); //關閉輸入流 in.close(); String Cookies; //獲取Cookie cookies1 = ((AbstractHttpClient) client).getCookieStore().getCookies(); Cookies = "JSESSIONID="+cookies1.get(0).getValue().toString(); //System.out.println(Cookies); //在SharedPreferences中保存cookie editor.putString("Cookies", Cookies); //提交保存數據 editor.commit(); //通過handler.post方法在線程中更新主線程中的驗證碼圖片信息 handler.post(new Runnable() { @Override public void run() { if (bitmap != null) { IdcodeImage.setImageBitmap(bitmap); } } }); } catch (IOException e) { e.printStackTrace(); } } } }.start(); } }); //初始化時獲取驗證碼圖片代碼與上面的一致 new Thread() { @Override public void run() { List cookies1; HttpGet httpGet = new HttpGet(url2); HttpResponse httpResponse = null; try { httpResponse = client.execute(httpGet); } catch (IOException e) { e.printStackTrace(); } if (httpResponse.getStatusLine().getStatusCode() == 200) { try { InputStream in = httpResponse.getEntity().getContent(); bitmap = BitmapFactory.decodeStream(in); in.close(); String Cookies; cookies1 = ((AbstractHttpClient) client).getCookieStore().getCookies(); Cookies = "JSESSIONID="+cookies1.get(0).getValue().toString(); System.out.println(Cookies); editor.putString("Cookies", Cookies); editor.commit(); handler.post(new Runnable() { @Override public void run() { if (bitmap != null) { IdcodeImage.setImageBitmap(bitmap); } } }); } catch (IOException e) { e.printStackTrace(); } } } }.start(); //對登錄按鈕綁定單擊響應事件 logIn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //獲取輸入信息 StudentNumber =studentNumber.getText().toString(); PassWord =passWord.getText().toString(); IdCode = idCode.getText().toString(); //這裡寫入StudentNumber和PassWord是為了做記住密碼登錄 editor.putString("StudentNumber", StudentNumber); editor.putString("PassWord", PassWord); editor.putString("IdCode", IdCode); editor.commit(); new Thread() { @Override public void run() { //提交數據用List 的方式 List params = new ArrayList (); //這裡的名稱不要有多余的符號,因為提交數據時httppost方法會幫你維護數據 //這裡表單的數據順序要按照剛剛解析所顯示的順序排列 params.add(new BasicNameValuePair("groupId", groupId)); params.add(new BasicNameValuePair("j_username", StudentNumber)); params.add(new BasicNameValuePair("login",login)); params.add(new BasicNameValuePair("j_password", PassWord)); params.add(new BasicNameValuePair("j_captcha", IdCode)); System.out.println(params); try { HttpPost httpPost = new HttpPost(url3); String Cookies; //獲取到剛剛在獲取驗證碼時得到的Cookie Cookies = sharedPreferences.getString("Cookies", null); //System.out.println(Cookies); //提交數據做准備 httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); //同步cookie httpPost.setHeader("Cookie", Cookies); //獲取返回的信息 HttpResponse httpResponse = client.execute(httpPost); //如果響應成功則進入Score_find的Activity if (httpResponse.getStatusLine().getStatusCode() == 200) { String result = EntityUtils.toString(httpResponse.getEntity()); //System.out.println(result); startActivity(new Intent(MainActivity.this, Score_find.class)); } else { System.out.println("登錄失敗!"); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } }); } }
public class Score_find extends ActionBarActivity{ private String Cookies; HttpClient client; private String url="http://jw.djtu.edu.cn/academic/manager/score/studentOwnScore.do?groupId=&moduleId=2021"; private String year=null; private String trem=null; private String para="0"; private String sortColumn=""; private String Submit="查詢"; private TextView showScore; private EditText InputYear; private EditText InputTrem; SharedPreferences sharedPreferences; StringBuffer sb=new StringBuffer(); private Handler handler=null; private Button searchButton; //這兩個標記是用於判斷用戶輸入的數據是否合法 private int mark1=0; private int mark2=0; @Override protected void onCreate(final Bundle saveInstanceState) { super.onCreate(saveInstanceState); setContentView(R.layout.score_find); InputTrem=(EditText)findViewById(R.id.InputTrem); InputYear=(EditText)findViewById(R.id.InputYear); searchButton=(Button)findViewById(R.id.searchButton); showScore=(TextView)findViewById(R.id.show_score); //設置showScore可以滾動 showScore.setMovementMethod(ScrollingMovementMethod.getInstance()); handler=new Handler() { @Override public void handleMessage(Message message) { //加載信息 showScore.setText(sb.toString()); } }; sharedPreferences = getSharedPreferences("params", Context.MODE_PRIVATE); Cookies=sharedPreferences.getString("Cookies", null); showScore=(TextView)findViewById(R.id.show_score); client=new DefaultHttpClient(); searchButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String years=null,trems=null; years=InputYear.getText().toString(); trems=InputTrem.getText().toString(); System.out.println(years+trems); //輸入信息的判斷 if("春".equals(trems)) { trem="1"; mark1=1; System.out.println(trems+"\t"+trem); }else if("秋".equals(trems)) { trem="2"; mark1=1; }else { mark1=0; Toast.makeText(Score_find.this,"輸入學期有誤請重新輸入!",Toast.LENGTH_SHORT).show(); } if("2014".equals(years)) { year="34"; mark2=1; System.out.println(years+"\t"+year); }else if("2015".equals(years)) { year="35"; mark2=1; } else { mark2=0; Toast.makeText(Score_find.this,"輸入年份有誤請重新輸入!",Toast.LENGTH_SHORT).show(); } //如果兩個信息都輸入合法則提交請求 if(mark1==1&&mark2==1) { //是耗時操作都要放到新線程裡執行 new Thread() { @Override public void run() { HttpResponse httpResponse; HttpPost httpPost = new HttpPost(url); List最後我用紅字強調一下做這個demo我一開始失敗了好多次的地方:params = new ArrayList (); params.add(new BasicNameValuePair("year", year)); params.add(new BasicNameValuePair("term", trem)); params.add(new BasicNameValuePair("para", para)); params.add(new BasicNameValuePair("sortColumn", sortColumn)); params.add(new BasicNameValuePair("Submit", Submit)); System.out.println(params); httpPost.setHeader("Cookie", Cookies); try { httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); httpResponse = client.execute(httpPost); if (httpResponse.getStatusLine().getStatusCode() == 200) { StringBuffer stringBuffer = new StringBuffer(); String result = null; InputStream inputStream = httpResponse.getEntity().getContent(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); String data = ""; //讀取得到的數據 while ((data = bufferedReader.readLine()) != null) { stringBuffer.append(data); stringBuffer.append("\n"); } result = stringBuffer.toString(); //判斷是否獲取到數據 if (result == null) { System.out.println("NULL!!!!"); } else { //這裡使用jsoup開源的解析包進行html源碼的解析 //獲取要解析的網址或者文檔或者網址 Document document = Jsoup.parse(result); //經過分析成績保存在datalist這個Class中因此要定位到這個類中 Elements elements = document.getElementsByClass("datalist"); //獲取他的第一個元素集合 Element element = elements.get(0); //再分析可以看到在tr標簽下有成績的詳細信息 Elements elements1 = element.getElementsByTag("tr"); Element element2; Elements elements3; Element element3; Element element4; for (int i = 0; i < elements1.size(); i++) { //剝離每一個標簽 element2 = elements1.get(i); //再重新定位td標簽下的內容 elements3 = element2.getElementsByTag("td"); for (int j = 0; j < elements3.size(); j++) { //這裡為了獲取td標簽中的子元素要進行一個循環 if (j == 0) { //我發現我要的課程名和成績分別在elements3集合中的第5個元素和第11個元素 element3 = elements3.get(4); element4 = elements3.get(10); sb.append(element3.text()).append(":").append("\t\t").append(element4.text()).append("\n"); } else { break; } } } //數據獲取完成通知組件重繪信息 handler.sendEmptyMessage(0); } } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } }); } }
1.Cookie信息獲取要在獲取驗證碼時同時獲取。
2.如果線程操作封裝成類的話會造成SharedPreferences綁定content失敗。
3.對HTML源碼進行解析的時候我嘗試將解析方法寫成一個函數,但是會出現一些未捕獲的錯誤而導致程序崩潰,因此我把解析步驟也放到了新線程中。
有什麼不足的地方可以留言給我我會盡快回復並改正!
1.首先找到你需要的jar包2.復制粘貼到下圖位置3.你的粘貼後可能是這樣的4.正確的方式是這樣的5.在粘貼後還需要操作2步(1.選中Add As Library)然後進
Android應用檢查版本更新後,在通知欄下載,更新下載進度,下載完成自動安裝,效果圖如下:•檢查當前版本號AndroidManifest文件中的versio
在android開發中,用戶能夠撥打電話是最基本的需求。俗話說“條條大路通羅馬”,實現撥打電話的方式有多種,今天,就提供最常用兩種。 首先,撥打電話,對於用戶來說,是一
在5.2.1節和5.2.2節介紹了<a>標簽以及TextView自動識別的特殊文本(網址、電話號、Email等),這些都可以通過單擊來觸發不同的動作。雖然這些