记得上篇文章我还在为使用哪种开发语言开发android而发愁,最近使用了一下C#开发android,感觉不是那么爽。查资料也不方便,于是我决定使用java开发,毕竟java我也是学过的,eclipse环境也不陌生。开始吧,天很冷,先上图
这张图我是从真机上截取下来的,这是一个登陆界面。用户输入用户名和密码后,验证,验证通过之后,跳转至另一个Activity。那么我目前采取的方式是Android调用.net WebService的方式。
OK,先看一下Service端。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
namespace
GRLC.WebService
{
/// <summary>
/// Login 的摘要说明
/// </summary>
[WebService(Namespace =
"http://tempuri.org/"
)]
[WebServiceBinding(ConformsTo = WsiProfiles.None)]
[System.ComponentModel.ToolboxItem(
false
)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
// [System.Web.Script.Services.ScriptService]
public
class
LoginService : System.Web.Services.WebService
{
[WebMethod]
public
LoginResponse CheckLogin(
string
userNo,
string
pwd)
{
return
LoginBiz.GetInstance().CheckLogin(userNo, pwd);
}
}
}
|
没什么好说的,完了之后我们再看Biz层
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public
class
LoginBiz
{
static
LoginBiz loginBiz =
new
LoginBiz();
private
LoginBiz()
{ }
public
static
LoginBiz GetInstance()
{
return
loginBiz;
}
public
LoginResponse CheckLogin(
string
name,
string
pwd)
{
return
LoginDAL.GetInstance().CheckLogin(name, pwd);
}
}
|
也没啥说的,再看Dal层
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
|
public
class
LoginDAL
{
static
LoginDAL loginDAL =
new
LoginDAL();
private
LoginDAL()
{ }
public
static
LoginDAL GetInstance()
{
return
loginDAL;
}
const
string
moduleName =
"LoginModule"
;
BonusEntities bonusEntities =
new
BonusEntities();
private
string
PwdIsNotCorrect
{
get
{
return
this
.GetMessageByName(
"PwdNotCorrect"
);
}
}
private
string
UserNotExists
{
get
{
return
this
.GetMessageByName(
"UserNotExists"
);
}
}
private
string
GetMessageByName(
string
msgName)
{
return
CommonFunction.GetMessageByModuleAndName(moduleName, msgName);
}
public
LoginResponse CheckLogin(
string
name,
string
pwd)
{
User user = bonusEntities.User.SingleOrDefault(u => u.UseNo == name);
if
(user !=
null
)
{
string
passWord = Cryptor.Decrypt(user.Pwd);
if
(!passWord.Equals(pwd))
{
return
new
LoginResponse() { IsSuccess =
false
, FailMsg = PwdIsNotCorrect };
}
return
new
LoginResponse() { IsSuccess =
true
};
}
else
{
return
new
LoginResponse() { IsSuccess =
false
, FailMsg = UserNotExists };
}
}
}
|
在这里我们使用了EntityFrameWork作真正的数据访问层。我一次性把所有表都映射进来了,并设置了他们之间的关联关系。
在这里需要说的是这个GetMessageByModuleAndName方法。
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
|
public
class
CommonFunction
{
private
static
string
BaseDirectory
{
get
{
return
AppDomain.CurrentDomain.BaseDirectory;
}
}
private
static
List<ServiceMessage> GetMessageList()
{
List<ServiceMessage> messageList =
new
List<ServiceMessage>();
string
messageConfigFolder = Path.Combine(BaseDirectory, ConfigHelper.MessageConfigFolder);
if
(!Directory.Exists(messageConfigFolder))
return
null
;
string
[] files = Directory.GetFiles(messageConfigFolder,
"*.xml"
, SearchOption.TopDirectoryOnly);
foreach
(
string
file
in
files)
{
ServiceMessage message = SerializeHelper.XmlDeSerializeByFile<ServiceMessage>(file);
messageList.Add(message);
}
return
messageList;
}
public
static
string
GetMessageByModuleAndName(
string
moduleName,
string
msgName)
{
string
message =
string
.Empty;
ServiceMessage serviceMsg =
new
ServiceMessage();
List<ServiceMessage> serviceMessageList = CommonFunction.GetMessageList();
List<MessageEntityCollection> messageEntityCollection = serviceMessageList.Select(m => m.messageEntityCollection).ToList();
foreach
(
var
msgEntityCollection
in
messageEntityCollection)
{
MessageEntity messageEntity = msgEntityCollection.SingleOrDefault(msgEntity => msgEntity.Module == moduleName && msgEntity.Name == msgName);
if
(messageEntity !=
null
)
{
message = messageEntity.Content;
break
;
}
}
return
message;
}
}
|
首先这个方法会先从配置文件里面获取到提示信息的配置文件夹,然后遍历xml文件,将所有xml文件中的提示信息通过反序列化放到一个List中,也就是上面的GetMessageList()方法,其实在这里我们可以对代码进行优化,如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
private
static
List<ServiceMessage> _serviceMessageList;
private
static
List<ServiceMessage> ServiceMessageList
{
get
{
if
(_serviceMessageList ==
null
)
{
_serviceMessageList = GetMessageList();
return
_serviceMessageList;
}
else
{
return
_serviceMessageList;
}
}
}
|
那么每次在获取的时候,会先判断_serviceMessageList有没有,如果有,就不再读取文件了。
我们来看一下这个配置文件
1
2
3
4
5
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
ServiceMessages
>
<
Message
Module
=
"LoginModule"
Name
=
"PwdNotCorrect"
Content
=
"密码不正确!"
></
Message
>
<
Message
Module
=
"LoginModule"
Name
=
"UserNotExists"
Content
=
"用户名不存在!"
></
Message
>
</
ServiceMessages
>
|
它对应的实体如下
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
|
namespace
GRLC.Model.Config
{
[XmlRoot(
"ServiceMessages"
)]
public
class
ServiceMessage
{
[XmlElement(
"Message"
)]
public
MessageEntityCollection messageEntityCollection {
get
;
set
; }
}
public
class
MessageEntityCollection : KeyedCollection<
string
, MessageEntity>
{
protected
override
string
GetKeyForItem(MessageEntity messageEntity)
{
return
messageEntity.Name;
}
}
[XmlRoot(
"Message"
)]
public
class
MessageEntity
{
[XmlAttribute(
"Name"
)]
public
string
Name {
get
;
set
; }
[XmlAttribute(
"Module"
)]
public
string
Module {
get
;
set
; }
[XmlAttribute(
"Content"
)]
public
string
Content {
get
;
set
; }
}
}
|
所以在拿到这些msg以后,根据他的module和name就可以拿到对应content。好了上面就是.net的service端。完了之后我们部署一下
部署的时候需要注意如下
接下来我们看一下app端的开发
我们总共有两个Activity,一个是main,一个是index,main界面登成功跳转至index界面。
我们先看一下mai界面的代码
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
|
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
android:id
=
"@+id/layMain"
android:layout_width
=
"fill_parent"
android:layout_height
=
"fill_parent"
android:paddingLeft
=
"10dp"
android:paddingRight
=
"10dp"
android:orientation
=
"vertical"
android:gravity
=
"center_vertical"
>
<
LinearLayout
android:orientation
=
"horizontal"
android:gravity
=
"center_vertical"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
>
<
TextView
android:id
=
"@+id/labUserName"
android:text
=
"@string/labUserName"
android:layout_width
=
"70dp"
android:layout_height
=
"wrap_content"
android:textSize
=
"18dp"
android:textStyle
=
"bold"
></
TextView
>
<
EditText
android:id
=
"@+id/txtUserName"
android:hint
=
"@string/hintInputUserNo"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:singleLine
=
"true"
></
EditText
>
</
LinearLayout
>
<
LinearLayout
android:orientation
=
"horizontal"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
>
<
TextView
android:id
=
"@+id/labPwd"
android:text
=
"@string/labPwd"
android:layout_width
=
"70dp"
android:layout_height
=
"wrap_content"
android:textSize
=
"18dp"
android:textStyle
=
"bold"
></
TextView
>
<
EditText
android:id
=
"@+id/txtPwd"
android:hint
=
"@string/hintInputUserPwd"
android:layout_height
=
"wrap_content"
android:layout_width
=
"fill_parent"
android:singleLine
=
"true"
android:password
=
"true"
></
EditText
>
</
LinearLayout
>
<
LinearLayout
android:orientation
=
"horizontal"
android:layout_width
=
"fill_parent"
android:gravity
=
"center_horizontal"
android:layout_height
=
"wrap_content"
>
<
CheckBox
android:id
=
"@+id/chkDisplayPwd"
android:layout_width
=
"130dp"
android:layout_height
=
"wrap_content"
android:text
=
"@string/chkDisplayPwd"
>
</
CheckBox
>
<
Button
android:id
=
"@+id/btnLogin"
android:text
=
"@string/btnLoginText"
android:layout_width
=
"80dp"
android:layout_height
=
"wrap_content"
></
Button
>
<
Button
android:id
=
"@+id/btnCancel"
android:text
=
"@string/btnCancelText"
android:layout_width
=
"80dp"
android:layout_height
=
"wrap_content"
></
Button
>
</
LinearLayout
>
</
LinearLayout
>
|
采用的是线性布局。运行起来就是最开始我贴的那张图。OK,我们先看一下OnCreate
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
|
final
static
String NAMESPACE =
"http://tempuri.org/"
;
final
static
String METHOD_NAME =
"CheckLogin"
;
final
static
String SOAP_ACTION =
"http://tempuri.org/CheckLogin"
;
final
static
String URL =
"http://10.0.2.2:2000/LoginService.asmx?wsdl"
;
EditText txtUserno;
EditText txtPwd;
Button btnLogin;
Button btnCancel;
CheckBox chkDisplay;
/** Called when the activity is first created. */
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnLogin = (Button)
this
.findViewById(R.id.btnLogin);
btnCancel=(Button)
this
.findViewById(R.id.btnCancel);
txtUserno = (EditText)
this
.findViewById(R.id.txtUserName);
txtPwd = (EditText)
this
.findViewById(R.id.txtPwd);
chkDisplay = (CheckBox)
this
.findViewById(R.id.chkDisplayPwd);
btnLogin.setOnClickListener(
new
OnClickListener() {
public
void
onClick(View v) {
String userNo = txtUserno.getText().toString().trim();
String pwd = txtPwd.getText().toString().trim();
Login(userNo, pwd);
}
});
btnCancel.setOnClickListener(
new
OnClickListener() {
public
void
onClick(View v) {
txtUserno.setText(
""
);
txtPwd.setText(
""
);
}
});
chkDisplay.setOnCheckedChangeListener(
new
OnCheckedChangeListener() {
public
void
onCheckedChanged(CompoundButton cmpButton,
boolean
isChecked) {
if
(isChecked) {
txtPwd
.setTransformationMethod(HideReturnsTransformationMethod
.getInstance());
}
else
{
txtPwd.setTransformationMethod(PasswordTransformationMethod
.getInstance());
}
}
});
}
|
在页面的最顶端声明了我们需要调用的webservice的信息,注意10.0.2.2是android的内置IP,这个是android访问你本地电脑时使用的IP。如果使用127.0.0.1的话那是在访问你的手机。在Oncreate方法里,我们给按钮注册了事件响应。登录和取消,我们还看到一个checkBox,他的作用是是否让密码明文显示。如果未勾选,如下左所示,否则如右
OK,看完checkBox我们看登录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public
void
Login(String userNo, String passWord) {
if
(!CheckUserInput(userNo, passWord)) {
return
;
}
SoapObject response =
this
.GetServerResponse(userNo, passWord);
boolean
isSuccess = Boolean.valueOf(response.getProperty(
"IsSuccess"
)
.toString());
if
(!isSuccess) {
String failMsg = response.getProperty(
"FailMsg"
).toString();
new
AlertDialog.Builder(
this
)
.setTitle(R.string.WarningMsgTitle)
.setMessage(failMsg)
.setIcon(R.drawable.warning)
.setPositiveButton(
"确定"
,
null
).show();
}
else
{
Intent intent =
new
Intent();
Bundle bundle =
new
Bundle();
bundle.putString(
"userNo"
, userNo);
intent.putExtras(bundle);
intent.setClass(main.
this
, index.
class
);
startActivityForResult(intent,
0
);
finish();
}
}
|
登录的时候会先checkInput。
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
|
private
boolean
CheckUserInput(String userNo, String passWord) {
if
(userNo.equals(
""
)) {
new
AlertDialog.Builder(
this
).setTitle(R.string.WarningMsgTitle)
.setMessage(R.string.UserNoIsEmpty)
.setIcon(R.drawable.info)
.setPositiveButton(
"确定"
,
new
DialogInterface.OnClickListener() {
public
void
onClick(
DialogInterface dialoginterface,
int
i) {
txtUserno.requestFocus();
}
}).show();
return
false
;
}
if
(passWord.equals(
""
)) {
new
AlertDialog.Builder(
this
).setTitle(R.string.WarningMsgTitle)
.setMessage(R.string.UserPWdIsEmpty)
.setIcon(R.drawable.info)
.setPositiveButton(
"确定"
,
new
DialogInterface.OnClickListener() {
public
void
onClick(
DialogInterface dialoginterface,
int
i) {
txtPwd.requestFocus();
}
}).show();
return
false
;
}
return
true
;
}
|
checkInput非常简单,如果是空的话弹出提示,如下
OK,如果输入的不是空,那么调用WebService,需要传递两个参数
看一下代码
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
|
private
SoapObject GetServerResponse(String userNo, String passWord) {
SoapObject Request =
new
SoapObject(NAMESPACE, METHOD_NAME);
PropertyInfo pi =
new
PropertyInfo();
pi.setName(
"userNo"
);
pi.setType(String.
class
);
pi.setValue(userNo);
Request.addProperty(pi);
pi =
new
PropertyInfo();
pi.setName(
"pwd"
);
pi.setType(String.
class
);
pi.setValue(passWord);
Request.addProperty(pi);
SoapSerializationEnvelope soapEnvelope =
new
SoapSerializationEnvelope(
SoapEnvelope.VER11);
soapEnvelope.dotNet =
true
;
soapEnvelope.setOutputSoapObject(Request);
HttpTransportSE httpTS =
new
HttpTransportSE(URL);
try
{
httpTS.call(SOAP_ACTION, soapEnvelope);
}
catch
(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch
(XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SoapObject result =
null
;
try
{
result = (SoapObject) soapEnvelope.getResponse();
}
catch
(SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return
result;
}
|
在这里调用WebService并返回SoapObject对象,调用WebService不要忘记引用ksoap
如果没有的话,自己去下载一个。这里调用成功返回以后,如果IsSuccess为true的话,直接跳转至index,并将登陆成功的userNo传给index。如果登陆失败,弹出service端返回的提示信息。但悲剧的是我的真机报错,没有访问到webservice。后来我用手机连接了wlan,Ip地址也改了还是报错
电脑访问无线IP没有问题,如下
但是真机就是连不上,模拟器用10.0.2.2却可以正常访问。
后来查看了一下手机,尝试下面所有的ip都不行。
最后我查了一下电脑ip,使用172.18.73.39,结果调用成功。
调用成功了,哈哈
本文转自 BruceAndLee 51CTO博客,原文链接:http://blog.51cto.com/leelei/1345860,如需转载请自行联系原作者