PepClient终端
一、android基础知识(四大组件)
1、Activity
一个Activity通常展现为一个可视化的用户界面。例如,一个activity可能展现为一个用户可以选择的菜单项列
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
或者展现一些图片以及图片的标题。一个消息服务应用程序可能包含一个显示联系人列表的activity,一个编写信息的activity,以及其它一些查看信息和修改应用程序设置的activity。虽然这些activity一起工作,共同组成了一个应用程序,但每一个activity都是相对独立的。每一个activity都是Activity(android.app.Activity)的子类。
一个应用程序可能只包含一个activity,或者像上面提到的消息服务程序一样有多个activity。一个应用程序包含几个activity以及各个activity完成什么样的功能完全取决于应用程序以及它的设计。通常每个应用程序都包含一个在应用程序启动后第一个展现给用户的activity。在当前展现给用户的activity中启动一个新的activity,可以实现从一个activity转换到另外一个activity
每个activity都会有一个用于绘制用户界面的窗口。通常这样一个窗口会填充整个屏幕,当然这个窗口也可以比屏幕小并漂浮在其他窗口之上。activity还可以使用一些额外的窗口,例如一个要求用户响应的弹出式对话框,或者是当用户在屏幕上选择一个条目后向用户展现一些重要信息的窗口。
展示activity窗口的可视化
内容
财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容
区域是一些具有层次关系(很像数据结构中的树)的视图,而视图则是由类View的子类表示的。每个视图控制窗口中的一个矩形区域。父视图包含一些子视图并管理子视图的布局。位于叶节点的视图直接控制并响应用户的动作。因此视图就是activity与用户交互的接口。例如,一个显示图片的视图,当用户单击的时候它可能会启动一个动作。Android有许多开发人员可以直接使用的视图,包括按钮,文本域,滚动条,菜单,复选框等。
通过调用Activity.setContentView()方法来设置展现activity的窗口的视图。内容视图则是视图层次结构中的根节点视图。
2、Service
service没有用户界面,但它会在后台一直运行。例如,service可能在用户处理其它事情的时候播放背景音乐,或者从网络上获取数据,或者执行一些运算,并把运算结构提供给activity展示给用户。每个service都扩展自类Serivce。
多媒体播放器播放音乐是应用service的一个非常好的例子。多媒体播放器程序可能含有一个或多个activity,用户通过这些activity选择并播放音乐。然而,音乐回放并不需要一个activity来处理,因为用户可能会希望音乐一直播放下去,即使退出了播放器去执行其它程序。为了让音乐一直播放,多媒体播放器activity可能会启动一个service在后台播放音乐。Android系统会使音乐回放service一直运行,即使在启动这个service的activity退出之后。
应用程序可以连接到一个正在运行中的service。当连接到一个service后,可以使用这个service向外暴露的接口与这个service进行通信。对于上面提到的播放音乐的service,这个接口可能允许用户暂停,停止或重新播放音乐。
与activity以及其它组件一样,service同样运行在应用程序进程的主线程中。所以它们不能阻塞其它组件或用户界面,通常需要为这些service派生一个线程执行耗时的任务。
3、Broadcase receiver
broadcase receiver不执行任何任务,仅仅是接受并响应广播通知的一类组件。大部分广播通知是由系统产生的,例如改变时区,电池电量低,用户选择了一幅图片或者用户改变了语言首选项。应用程序同样也可以发送广播通知,例如通知其他应用程序某些数据已经被下载到设备上可以使用。
一个应用程序可以包含任意数量的boradcase reveiver来响应它认为很重要的通知。所有的broadcast receiver都扩展自类BroadcastReceiver。
broadcast receiver不包含任何用户界面。然而它们可以启动一个activity以响应接受到的信息,或者通过NotificationManager通知用户。可以通过多种方式使用户知道有新的通知产生:闪动背景灯、震动设备、发出声音等等。通常程序会在状态栏上放置一个持久的图标,用户可以打开这个图标并读取通知信息。
4、Content provider
应用程序可以通过content provider访问其它应用程序的一些私有数据,这是Android提供的一种
标准
excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载
的共享数据的机制。共享的数据可以是存储在文件系统中、SQLite数据库中或其它的一些媒体中。content provider扩展自ContentProvider类,通过实现此类的一组标准的接口可以使其它应用程序存取由它控制的数据。然而应用程序并不会直接调用ContentProvider中的方法,而是通过类ContentResolver。ContentResolver能够与任何一个ContentProvider通信,它与ContentProvider合作管理进程间的通信。
任何时候当Android系统收到一个需要某个组件进行处理的请求的时候,Android会确保处理此请求的组件的宿主进程是否已经在运行,如果没有,则立即启动这个进程,当请求的组件的宿主进程已经在运行,它会继续查看请求的组件是否可以使用,如果不能立即使用,它会创建一个请求的组件的实例来响应请求。
5、参考资料:
1> 四大组件介绍
http://my.eoe.cn/elvnxuan/archive/1369.html
2> android基础视频
http://yunpan.cn/Qbk5d2TX3uuUG
3> android API
http://developer.android.com/guide/index.html
二 项目实战
1、项目简介
这个项目是基于http通信的应用程序,主要涉及的技术有http通信,android四大组件使用,界面布局,以及基本的java语法。
2、项目总览
整个项目 图片样式文件 动画样式文件
布局文件 开发包 剩下文件
3、项目制作步骤:
1、新建一个android项目:PepClients,SDK版本选择Android2.2(建议)
2、写一个欢迎界面
1)新建MainActivity
在src目录下新建一个packet:cn.edu.cqut.ui,在该packet下新建一个Activity:MainActivity(新建一个工程时,默认添加一个Activity——>MainActivity)
在该packet下新建一个MainActivity,并在里面写如下代码,完成欢迎界面
和上一页一起
2)MainActivity布局文件
新建main.xml
涉及图片:ic_pep.png 效果图如下:
3、登录界面
1)在cn.edu.cqut.ui这个packet下新建LoginActivity,并且继承BaseAcivity
2)BaseAcivity介绍
3)LoginActivity简介
1. LoginActivity的oncreate()方法,完成界面的加载,及数据初始化
2. 父类BaseAcivity方法的实现
3. ui(界面)更新线程
4. 接送数据解析
5. 登录按钮监听,发送登录请求信息
6. 对发送的数据检查
7. 对返回键的监听响应
4)新建login.xml
1. 布局
2. login.xml里面涉及的样式文件
@drawable/title_btn_back.xml @drawable/login_editbox.xml @drawable/btn_style_green
注:新建一个drawable文件,将这些样式文件放在里面
下面是样式表:
title_btn_back.xml源码如下:
login_editbox.xm源码:
btn_style_green源码:
5)效果图:
做完上面步骤,LoginActivity里面会发现缺少很多类和方法,主要是通信类,下面我就来讲通信类主要实现方法
4、通信模块:
1)新建packetc cn.edu.cqut.util
1. 新建NetWorkUtils.class
并在该包下创建NetWorkUtils.class 这个类是一个网络通信助手类,源码如下:
package cn.edu.cqut.util;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.telephony.TelephonyManager;
import android.util.Log;
public class NetWorkUtils {
/**
* 判断网络状况是否可用
*
* @param context
* @return boolean true:网络状况可用 false:网络状况不可用
*/
public static boolean isNetWorks(Context context) {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm == null)
return false;
NetworkInfo[] infos = cm.getAllNetworkInfo();
for (NetworkInfo info : infos) {
if (info.isConnected())
return true;
}
return false;
}
/**
* 获取本机IP地址
*/
public static String getLocalIpToString() {
try {
for (Enumeration
en = NetworkInterface
.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration enumIpAddr = intf
.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress.getHostAddress().toString();
}
}
}
} catch (SocketException ex) {
Log.e("WifiPreference IpAddress", ex.toString());
}
return null;
}
/**
* 获取本机MAC地址
*
* @param context
* @return
*/
public static String getIMEI(Context context) {
String imei = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId();
return imei;
}
public static String getMac(Context context) {
String macAddress = null;
WifiManager wifiMgr = null;
Object obj = context.getSystemService(Context.WIFI_SERVICE);
if (null != obj) {
wifiMgr = (WifiManager)obj;
}
WifiInfo info = (null == wifiMgr ? null : wifiMgr.getConnectionInfo());
if (null != info) {
macAddress = info.getMacAddress();
}
return macAddress;
}
}
2. 新建HttpRequestUtil.class
package cn.edu.cqut.util;
import android.content.Context;
import cn.edu.cqut.network.WebServiceUtil;
/**
* 这个类是对webservice的封装,主要包括几个方法
* 用户登录:Login();
* 用户注销:LoginOut();
* 提交数据:SubmitData();
* 自动请求信息:autoRequestData();
* @author wxq
*
*/
public class HttpRequestUtil {
private String LOGIN = "Login";//登录
private String LOGINOUT = "LoginOut";//注销
private String SUBMITDATA = "SubmitData";//提交数据
private String ARQ = "AutoRequestData";//自动请求
public static HttpRequestUtil instance;
public static HttpRequestUtil getInstance(Context context) {
if (instance == null)
instance = new HttpRequestUtil();
return instance;
}
private HttpRequestUtil() {
}
/**
* 登录请求
* @param username
* @param password
* @return result
* @throws Exception
*/
public String Login(String data) throws Exception
{
return WebServiceUtil.method(LOGIN, data);
}
/**
* 发送注销请求 (需要 mac 和 用户名)
* @param user
* @return result
* @throws Exception
*/
public String LoginOut(String data) throws Exception
{
return WebServiceUtil.method(LOGINOUT, data);
}
/**
* 提交数据
* @param pram
* @return result
* @throws Exception
*/
public String SubmitData(String data) throws Exception
{
return WebServiceUtil.method(SUBMITDATA, data);
}
}
2)新建packet cn.edu.cqut.network
1. 新建类WebServiceUtil
package cn.edu.cqut.network;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
public class WebServiceUtil
{
private static final String URL = "http://218.70.163.87:8181/client/webclientRequest.asmx";
private static final String NAMESPACE = "http://tempuri.org/";
public static String method(String method, String data)throws Exception
{
String result = "";
String soapAction = NAMESPACE + method ;
try {
// 指定WebService的命名空间和调用的方法名
SoapObject request = new SoapObject(NAMESPACE, method);
// 设置需调用WebService接口需要传入的参数
if (data != null ) {
request.addProperty("data" , data);
}
// 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER10);
envelope.dotNet = true;// 访问.NET的webservice
//等价于envelope.bodyOut = request;
envelope.setOutputSoapObject(request);
HttpTransportSE ht = new HttpTransportSE(URL);
ht.call(soapAction, envelope);// 调用call方法,访问webservice
Object resp = envelope.bodyIn;
if (envelope.getResponse() != null) {
//等价于: SoapObject response = envelope.bodyIn;
// response.getProperty(0).toString();
SoapPrimitive response = (SoapPrimitive) envelope.getResponse();
result = response.toString();// 这里获得了webService的返回值
System.out.println("result: " + result);
}
} catch (Exception e) {
result = e.getMessage();
return null;
}
return result;
}
}
3)新建packet cn.edu.cqut.task
1. 新建类AsyncTaskRequest
package cn.edu.cqut.task;
import org.json.JSONException;
import android.app.Activity;
import android.os.AsyncTask;
import android.widget.Toast;
import cn.edu.cqut.dialog.MyProgressDialog;
import cn.edu.cqut.ui.BaseActivity;
import cn.edu.cqut.util.HttpRequestUtil;
/**
* 说明:
* 在开发Android移动客户端的时候往往要使用多线程来进行操作,我们通常会将耗时的操作放在单独的线程执行,
* 避免其占用主线程而给用户带来不好的用户体验。但是在子线程中无法去操作主线程(UI 线程),在子线程中操作UI线程会出现错误。
* 因此android提供了一个类Handler来在子线程中来更新UI线程,用发消息的机制更新UI界面,呈现给用户。这样就解决了子线程
* 更新UI的问题。但是费时的任务操作总会启动一些匿名的子线程,太多的子线程给系统带来巨大的负担,随之带来一些性能问题。
* 因此android提供了一个工具类AsyncTask,顾名思义异步执行任务。这个AsyncTask生来就是处理一些后台的比较耗时的任务,
* 给用户带来良好用户体验的,从编程的语法上显得优雅了许多,不再需要子线程和Handler就可以完成异步操作并且刷新用户界面。
*
* AsyncTaskRequest这个类继承AsyncTask,以异步的方式实现向服务器发送请求并对响应做出处理
* @author wxq
*
*/
public class AsyncTaskRequest extends AsyncTask {
private Activity mContext;
private HttpRequestUtil httpRequest;
private MyProgressDialog progressDialog;
/**
* 自定义ProgressDialog
*/
private String REQUESTINFO = "";
private String HttpRequestFail = "Http请求失败或出现异常";// Http请求失败
private String SUCCESS = "success";
private String ActivityName;//当前Activity名字
/**
*
* @param context 把activity context传递给AsyncTaskRequest,意味着AsyncTaskRequest拥有一个指向activity的引用,进而引用activity占有的资源:
* @param notice 任务的描述
* @param ActivityName 当前Activity名字
*/
public AsyncTaskRequest(Activity context,String notice,String ActivityName) {
super();
this.mContext = context;
this.REQUESTINFO = notice;
this.ActivityName = ActivityName;
httpRequest = HttpRequestUtil.getInstance(context);
progressDialog = new MyProgressDialog(context);
}
/**
* 该方法将在执行实际的后台操作前被UI 线程调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条,或者一些控件的实例化,
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
showProgressDialog(REQUESTINFO);
}
/**
* 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台处理工作。可以调用 publishProgress方法来更新实时的任务进度
*/
protected String doInBackground(String... params) {
try {
int taskId = Integer.parseInt(params[0]);
String response = "";
switch(taskId)
{
case 1:
response = httpRequest.Login(params[1]);
break;
case 2:
response = httpRequest.LoginOut(params[1]);
break;
case 3:
response = httpRequest.SubmitData(params[1]);
break;
}
return dealResponse(response);
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return HttpRequestFail;
}
/**
* 处理登录结果
*/
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
progressDialog.stopProgressDialog();
if (SUCCESS.equals(result)) {
// 处理登录界面刷新
} else
alertError(result);
}
/**
* 处理Http请求结果
* @param response
* Http 请求返回的字符串
* @return succes 表示成功登录
* @throws JSONException
*/
private String dealResponse(String response) throws JSONException {
if (response.equals("")==false)
{
getActivityByName(ActivityName).refresh(response);
return SUCCESS;// 登录失败,返回 失败原因
}
else
return HttpRequestFail;// Http请求失败
}
private void alertError(String str) {
Toast.makeText(mContext, str, Toast.LENGTH_SHORT).show();
}
/** 在界面上提示等待对话框 **/
private void showProgressDialog(String message) {
progressDialog.showProgressDialog(message);
}
/**
* 获得Activity
* @param activity
* @return
*/
public static BaseActivity getActivityByName(String activity) {
BaseActivity wa = null;
for (BaseActivity w : cn.edu.cqut.ui.BaseActivity.allActivity) {
if (w.getClass().getName().indexOf(activity) >= 0) {
wa = w;
break;
}
}
return wa;
}
}