记得上篇文章我还在为使用哪种开发语言开发android而发愁,最近使用了一下C#开发android,感觉不是那么爽。查资料也不方便,于是我决定使用java开发,毕竟java我也是学过的,eclipse环境也不陌生。开始吧,天很冷,先上图

这张图我是从真机上截取下来的,这是一个登陆界面。用户输入用户名和密码后,验证,验证通过之后,跳转至另一个Activity。那么我目前采取的方式是Android调用.net WebService的方式。

OK,先看一下Service端。


很熟悉很简单的结构。我们简单看一下Service端的代码

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层

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层

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方法。

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()方法,其实在这里我们可以对代码进行优化,如下

private static List<ServiceMessage> _serviceMessageList;        private static List<ServiceMessage> ServiceMessageList        {            get            {                if (_serviceMessageList == null)                {                    _serviceMessageList = GetMessageList();                    return _serviceMessageList;                }                else                {                    return _serviceMessageList;                }            }        }

那么每次在获取的时候,会先判断_serviceMessageList有没有,如果有,就不再读取文件了。

我们来看一下这个配置文件

<?xml version="1.0" encoding="utf-8"?><ServiceMessages>  <Message Module="LoginModule" Name="PwdNotCorrect" Content="密码不正确!"></Message>  <Message Module="LoginModule" Name="UserNotExists" Content="用户名不存在!"></Message></ServiceMessages>

它对应的实体如下

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界面的代码

<?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


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我们看登录

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。

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,需要传递两个参数

看一下代码

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,结果调用成功。

调用成功了,哈哈


更多相关文章

  1. HTML5,js与Android(安卓)native通信
  2. Android(安卓)onTouchEvent, onClick及onLongClick的调用机制
  3. 关于使用Android(安卓)NDK编译ffmpeg
  4. 想抢先体验Android操作系统的魅力吗?那就使用Android(安卓)LiveCD
  5. 转!Android(安卓)onTouchEvent,onClick和onLongClick的调用机制
  6. Android学习——uses-sdk标签详解
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python list sort方法的具体使用

随机推荐

  1. 浅谈MySQL大表优化方案
  2. MySQL慢查询相关参数原理解析
  3. Mysql5.7定时备份的实现
  4. MySQL学习记录之KEY分区引发的血案
  5. MySQL5.7 mysqldump备份与恢复的实现
  6. MySQL如何解决DOS窗口乱码问题
  7. MySQL如何利用DCL管理用户和控制权限
  8. MySQL基于java实现备份表操作
  9. mysql中find_in_set函数的基本使用方法
  10. 在IntelliJ IDEA中使用Java连接MySQL数据