安卓WebView可以通过JS对网页文档对象进行操作,实现自动填写账号和密码,这样下次就可以免手动输入了,比较方便。这儿使用QQ空间网页版进行模拟登陆
基于Android Studio3.0版本
首先需要为软件声明联网权限
1
|
<uses-permission android
:
name
=
"android.permission.INTERNET"
/>
|
因为WebView需要连接网络,所以这个是必须的。
创建界面,这儿为了演示,所以把软件分成两个部分,一个是填表输入文本,然后再模拟点击按钮。
首先创建界面,下面贴出代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<android.support.constraint.ConstraintLayout xmlns
:
android
=
"http://schemas.android.com/apk/res/android"
xmlns
:
app
=
"http://schemas.android.com/apk/res-auto"
xmlns
:
tools
=
"http://schemas.android.com/tools"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"match_parent"
tools
:
context
=
"com.ghboke.tbdl.MainActivity"
tools
:
layout_editor_absoluteY
=
"81dp"
>
<LinearLayout
android
:
id
=
"@+id/linearLayout"
android
:
layout_width
=
"0dp"
android
:
layout_height
=
"0dp"
android
:
layout_marginBottom
=
"8dp"
android
:
layout_marginEnd
=
"8dp"
android
:
layout_marginStart
=
"8dp"
android
:
layout_marginTop
=
"8dp"
android
:
orientation
=
"vertical"
app
:
layout_constraintBottom_toBottomOf
=
"parent"
app
:
layout_constraintEnd_toEndOf
=
"parent"
app
:
layout_constraintStart_toStartOf
=
"parent"
app
:
layout_constraintTop_toTopOf
=
"parent"
>
<WebView
android
:
id
=
"@+id/web"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"300dp"
>
</WebView>
<EditText
android
:
id
=
"@+id/editText_us"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"wrap_content"
android
:
ems
=
"10"
android
:
hint
=
"QQ"
android
:
inputType
=
"textPersonName"
android
:
text
=
"你的QQ号"
/>
<EditText
android
:
id
=
"@+id/editText_pw"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"wrap_content"
android
:
ems
=
"10"
android
:
hint
=
"密码"
android
:
inputType
=
"textPassword"
android
:
text
=
"你的密码"
/>
<Button
android
:
id
=
"@+id/button"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"wrap_content"
android
:
text
=
"填表"
/>
<Button
android
:
id
=
"@+id/button_login"
android
:
layout_width
=
"match_parent"
android
:
layout_height
=
"wrap_content"
android
:
text
=
"登陆"
/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
|
在Java代码中绑定他们
1
2
3
4
5
|
mWeb
=
(
WebView
)
findViewById
(
R
.
id
.
web
)
;
mEditTextUs
=
(
EditText
)
findViewById
(
R
.
id
.
editText_us
)
;
mEditTextPw
=
(
EditText
)
findViewById
(
R
.
id
.
editText_pw
)
;
mButton
=
(
Button
)
findViewById
(
R
.
id
.
button
)
;
mButtonLogin
=
(
Button
)
findViewById
(
R
.
id
.
button_login
)
;
|
绑定好以后,我们来分析一下这个软件。
首先是WebView浏览器,加载一个网页需要加载JS,而默认是不会加载的,所以我们要给他手动开启。
1
|
mWeb
.
getSettings
(
)
.
setJavaScriptEnabled
(
true
)
;
|
这句代码就是开启浏览器对JS的支持了,再来需要跳转到我们登陆的地址
这个地址就是QQ空间手机页面登陆的地址了。
要模拟操作网页的对象,首先要了解JS代码。
一个网页他就是一个docment对象,我们可以根据网页上元素的ID确定唯一的一个对象,因为ID是不重复的嘛,那么使用的代码就是
1
|
document
.
getElementById
(
'p'
)
|
其中,getElementById意为去网页对象中查找ID为p的那一个元素。那么现在就很明了了,打开谷歌浏览器,审查一下元素。
可以看到,元素代码的ID为,u,如果你对网页元素对象不太理解的话,请稍微看看JS部分即可。同理,找到下面密码框的ID为p,登陆按钮是一个DIV,ID为go。
那么现在我们就可以给安卓的WebView注入JS代码了。
WebView最简单的加载JS方法是loadUrl方法,他不仅仅可以跳转网址,只要内容开头为javascript即可注入JS代码
原生的JS代码进行填表是这样写的
1
2
3
|
document
.
getElementById
(
'u'
)
.
value
=
'填表内容'
;
//账号
document
.
getElementById
(
'p'
)
.
value
=
'填表内容'
;
//密码
document
.
getElementById
(
'go'
)
.
click
(
)
//登陆按钮点击
|
在Android 8.0上面直接执行这个JS代码会直接网页白屏,不知道是怎么回事,所以需要先注入,后加载的方式调用,方法如下
1
2
3
4
5
6
7
8
9
10
11
12
|
public
void
loadjs
(
)
{
String
jscode
=
StructureJs
(
mEditTextUs
.
getText
(
)
.
toString
(
)
,
mEditTextPw
.
getText
(
)
.
toString
(
)
)
;
mWeb
.
loadUrl
(
jscode
)
;
mWeb
.
loadUrl
(
"javascript:inputninandpw();"
)
;
}
public
String
StructureJs
(
String
uin
,
String
pw
)
{
StringBuffer
stringBuffer
=
new
StringBuffer
(
)
;
stringBuffer
.
append
(
"javascript:function inputninandpw(){document.getElementById('u').value='"
+
uin
+
"';"
)
;
stringBuffer
.
append
(
"document.getElementById('p').value='"
+
pw
+
"';}"
)
;
return
stringBuffer
.
toString
(
)
;
}
|
首先我声明了一个StructureJs函数,传入账号和密码,里面声明了一个StringBuffer ,你可以直接使用String拼接,JS代码是一个名为inputninandpw的函数,名字你可以自己起。接着,如果点击了填表按钮,就执行loadjs函数,这个函数中,把拼接好的JS代码先注入网页,再调用他,这样就可以成功的调用这个函数进行填表了,传入的账号和密码就是账号和密码文本框里面的内容了。
填表成功后,就可以模拟点击登陆按钮了
登陆按钮点击代码事件如下
1
2
3
|
public
void
clicklogin
(
)
{
mWeb
.
loadUrl
(
"javascript:document.getElementById('go').click();"
)
;
}
|
非常简单对吧,点击后就会进行登陆了。
如果隐藏了WebView,或者是让软件判断是否登陆成功怎么搞呢?总不能用户登陆成功以后,然后点击一个按钮告诉程序我已经登陆成功了吧,显然是不行的。那么,我们需要为浏览器写一个事件
本登陆页面如果登陆成功了,会跳到https://h5.qzone.qq.com/mqzone/index页面,如果没有登陆成功,是不会跳到这个页面的,所以我们可以在浏览器跳转完毕后进行判断。
为浏览器添加setWebChromeClient事件,本事件是浏览器的一个进度接口,那么只要进度到了100,那就说明网页已经加载完成了,接着我们获取网页的地址判断一下就可以知道用户是否登陆成功了。
1
2
3
4
5
6
7
8
9
10
11
|
mWeb
.
setWebChromeClient
(
new
WebChromeClient
(
)
{
public
void
onProgressChanged
(
WebView
view
,
int
progress
)
{
//加载完成
if
(
progress
==
100
)
{
if
(
mWeb
.
getUrl
(
)
.
equals
(
"https://h5.qzone.qq.com/mqzone/index"
)
)
{
Toast
.
makeText
(
getApplicationContext
(
)
,
"登陆成功"
,
Toast
.
LENGTH_LONG
)
.
show
(
)
;
}
}
}
}
)
;
|
很多网页用户登陆了以后,把cookies拿下来就可以做很多事了,那么在这个登陆成功判断后面再添加如下代码,就可以获取到cookies了
1
2
|
CookieManager
cookieManager
=
CookieManager
.
getInstance
(
)
;
String
CookieStr
=
cookieManager
.
getCookie
(
"https://h5.qzone.qq.com/mqzone/index"
)
;
|
getCookie传入需要获取cookie的url,这儿传入用户登陆成功的地址即可。