标签:
---恢复内容开始---
上个月月底把模拟登陆的问题解决了,现在有时间就正好记录并复习一下。
主要使用httpclient 来进行模拟登陆
首先做一个登陆布局 一直以来都是简单拖几个控件 没有啥特效 这次我想使用一点 Material Design设计风格 查了一下 TextInputLayout这个控件 还不错
TextInputLayout 来自于 Android Design Support Library 可以让edittext的hint在用户输入的时候 自动跳到上方 效果挺好看的
用法也很简单 TextInputLayout 在布局文件中 直接包裹住 edittext就行了 TextInputLayout 也要起个id 在activity里要设置hint 此时在edittext里面设置hint没有用
<android.support.design.widget.TextInputLayout android:id="@+id/usernameWrapper" android:layout_width="match_parent" android:layout_height="wrap_content" > <EditText android:id="@+id/username" android:layout_width="match_parent" android:layout_height="wrap_content" android:maxLines="1" /> </android.support.design.widget.TextInputLayout>
登陆界面代码
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 android:paddingBottom="@dimen/activity_vertical_margin" 7 android:paddingLeft="@dimen/activity_horizontal_margin" 8 android:paddingRight="@dimen/activity_horizontal_margin" 9 android:paddingTop="@dimen/activity_vertical_margin" 10 tools:context=".LoginActivity" 11 android:orientation="vertical" 12 > 13 14 15 16 <RelativeLayout 17 android:layout_width="match_parent" 18 android:layout_height="wrap_content" 19 android:layout_weight="0.4" 20 > 21 22 <TextView 23 android:layout_width="match_parent" 24 android:layout_height="wrap_content" 25 android:text="网络舆情防控处置系统" 26 android:gravity="center" 27 android:layout_centerInParent="true" 28 android:textSize="30sp" 29 android:textColor="#333333" 30 /> 31 </RelativeLayout> 32 33 34 <LinearLayout 35 android:layout_width="match_parent" 36 android:layout_height="wrap_content" 37 android:layout_weight="0.7" 38 android:orientation="vertical" 39 > 40 41 <android.support.design.widget.TextInputLayout 42 android:id="@+id/usernameWrapper" 43 android:layout_width="match_parent" 44 android:layout_height="wrap_content" > 45 <EditText 46 android:id="@+id/username" 47 android:layout_width="match_parent" 48 android:layout_height="wrap_content" 49 android:maxLines="1" 50 /> 51 </android.support.design.widget.TextInputLayout> 52 53 <android.support.design.widget.TextInputLayout 54 android:id="@+id/passwordWrapper" 55 android:layout_width="match_parent" 56 android:layout_height="wrap_content" 57 android:layout_marginTop="4dp" > 58 <EditText 59 android:id="@+id/password" 60 android:layout_width="match_parent" 61 android:layout_height="wrap_content" 62 android:inputType="textPassword" 63 android:maxLines="1" 64 /> 65 </android.support.design.widget.TextInputLayout> 66 67 <CheckBox 68 android:id="@+id/cb" 69 android:text="记住账号密码" 70 android:layout_width="wrap_content" 71 android:layout_height="wrap_content" /> 72 73 <Button 74 android:id="@+id/btn" 75 android:layout_width="match_parent" 76 android:layout_height="wrap_content" 77 android:text="登陆" 78 /> 79 </LinearLayout> 80 </LinearLayout>
在activity中 sethint就行了 运行起来就能看到效果了
usernameWrapper=(TextInputLayout) findViewById(R.id.usernameWrapper);
passwordWrapper=(TextInputLayout) findViewById(R.id.passwordWrapper);
usernameWrapper.setHint("账号");
passwordWrapper.setHint("密码");
登陆按钮判断一下输入框是否为空
if (TextUtils.isEmpty(str_username.trim())||TextUtils.isEmpty((str_password).trim()) ){
Toast.makeText(getApplicationContext(), "用户名或密码不能为空", Toast.LENGTH_LONG).show();
}else {
Login(str_username,str_password);
}
新建login方法
HttpClient是一个接口 先要创建一个实例 DefaultHttpClient defaultclient = new DefaultHttpClient();
创建一个HttpPost对象,传入目标的网络地址 HttpPost httpPost = new HttpPost("网络地址");
最后就是 访问的结果 HttpResponse httpResponse = defaultclient.execute(httpPost);
由于这里要登陆 所以账号密码必须作为参数传递过去 通过一个NameValuePair集合来存放
把这个参数集合传入到一个UrlEncodedFormEntity中 然后调用HttpPost的setEntity()方法将构建好的UrlEncodedFormEntity传入
List<NameValuePair>params=newArrayList<NameValuePair>();
Params.add(new BasicNameValuePair(“username”,”admin”));
Params.add(new BasicNameValuePair(“password”,”123456”));
httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
或者:
UrlEncodedFormEntity entity=newUrlEncodedFormEntity(params,”utf-8”);
httpPost.setEntity(entity);
访问网站会产生cookies 它就相当于人的身份证 没有它 就无法证明自己是谁 这在后面是有用处的 HttpClient 有方法可以取出它
List mCookies = defaultclient.getCookieStore().getCookies();
cookies 的两个必要值 name value 是我的目标 我取出来的方法是 先打印出来看看cookies 看清楚值的位置 用substring取出
String cook=mCookies.toString();
cookname = cook.substring(cook.indexOf("name: ")+6,cook.indexOf("][value"));
cookvalue = cook.substring(cook.indexOf("value: ")+7,cook.indexOf("][domain"));
请求发送成功之后 取得返回结果
if (httpResponse.getStatusLine().getStatusCode() == 200){
HttpEntity entity = httpResponse.getEntity();
String MAINBODYHTML = EntityUtils.toString(entity);
IsLoginSuccessful(MAINBODYHTML);
}
1 private void Login(final String username, final String password){ 2 new Thread(new Runnable() { 3 4 @Override 5 public void run() { 6 DefaultHttpClient defaultclient = new DefaultHttpClient(); 7 HttpPost httpPost = new HttpPost("登陆网站"); 8 HttpResponse httpResponse; 9 10 List<NameValuePair> params = new ArrayList<NameValuePair>(); 11 params.add(new BasicNameValuePair("username", username)); 12 params.add(new BasicNameValuePair("password", password)); 13 14 try { 15 httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); 16 httpResponse = defaultclient.execute(httpPost); 17 Log.i("xyz", String.valueOf(httpResponse.getStatusLine().getStatusCode())); 18 19 List mCookies = defaultclient.getCookieStore().getCookies(); 20 Log.d("cookies", mCookies.toString() ); 21 // List<Cookie> cookies = defaultclient.getCookieStore().getCookies(); 22 // Log.d("cookies", cookies.toString() ); 23 24 String cook=mCookies.toString(); 25 cookname = cook.substring(cook.indexOf("name: ")+6,cook.indexOf("][value")); 26 cookvalue = cook.substring(cook.indexOf("value: ")+7,cook.indexOf("][domain")); 27 28 Log.d("cookies", cookname +"++++"+ cookvalue); 29 30 if (httpResponse.getStatusLine().getStatusCode() == 200){ 31 StringBuffer sb = new StringBuffer(); 32 HttpEntity entity = httpResponse.getEntity(); 33 String MAINBODYHTML = EntityUtils.toString(entity); 34 IsLoginSuccessful(MAINBODYHTML); 35 } 36 } catch (UnsupportedEncodingException e) { 37 e.printStackTrace(); 38 } catch (ClientProtocolException e) { 39 e.printStackTrace(); 40 } catch (IOException e) { 41 e.printStackTrace(); 42 } 43 44 45 } 46 }).start(); 47 }
如何判断登陆成功失败 IsLoginSuccessful方法 思路如下:网页上登陆失败会跳转到一开始的登陆页面,成功的话会进入系统,前者的网页源代码中 肯定会 “账号” “密码”等字段,同理后者的网页源代码中也一定会成功页面的那些特有字段,我就来判断登陆成功的网页源代码中是否有成功时才有的“有害信息”,如果有 说明登陆成功,没有就说明失败
这里就要使用Jsoup了
Jsoup.parse方法可以解析HTML字符串 而我们都知道网页源代码都是 html 标签打头的 所以直接select html 就可以得到网页源代码
再用indexOf 判断是否有证明登陆成功的字段 没有就提示登陆失败 有就sendMessage 跳转activity 并带上 cookies的两个必要值 这里不能直接跳转 而且Toast前后都要加上Looper.prepare();和Looper.loop();
1 private void IsLoginSuccessful(String result){ 2 Document doc= Jsoup.parse(result); 3 4 Element masthead = doc.select("html").first(); 5 6 if (masthead.toString().indexOf("有害信息")!=-1){ 7 if (checkBox.isChecked()){ 8 editor.putString("username",str_username); 9 editor.putString("password",str_password); 10 editor.commit(); 11 } 12 13 Message msg=new Message(); 14 msg.arg1=1; 15 handler.sendMessageDelayed(msg,200); 16 17 }else{ 18 Looper.prepare(); 19 Toast.makeText(getApplicationContext(),"登陆失败",Toast.LENGTH_LONG).show(); 20 Looper.loop(); 21 22 } 23 24 }
1 private Handler handler=new Handler(){ 2 public void handleMessage(android.os.Message msg){ 3 Toast.makeText(getApplicationContext(),"登陆成功",Toast.LENGTH_SHORT).show(); 4 Intent in=new Intent(LoginActivity.this,MainActivity.class); 5 in.putExtra("name",cookname); 6 in.putExtra("value",cookvalue); 7 startActivity(in); 8 finish(); 9 }; 10 };
如果没有cookies 在模拟点击系统里面的链接的话 会直接跳转到登陆界面 有了cookies 之后才能保证登陆状态
后面的网络访问 我直接用的 jsoup 这个一定要带cookies参数 方法如下
Document doc = Jsoup.connect("访问网址").cookie(name, value).timeout(5000).get();
现在就写到这里 此方法在android开发中不常用 常规开发肯定有接口 所以还是记下来 以免忘了难找
标签:
原文地址:http://www.cnblogs.com/demon9/p/5491250.html