2013年11月27日 星期三

[Cocos2D-X] 简述Cocos2D-X中的内部函数

http://502317120.blog.51cto.com/4062300/1191871

简述Cocos2D-X中的内部函数

    虽然,Cocos2D-X 已经火了很长一阵子了。但,还是有很多同学刚刚接触 Cocos2D-X ,他们对Cocos2D-X 中一些引擎内部的基础函数,还不是很了解,那么今天我们就来介绍一下这些函数。   
    virtual bool isVisible();    // 是否可见
    virtual void setVisible(bool visible);      // 设置是否可见
    bool isRunning();       // 节点是否允许
    bool isIgnoreAnchorPointForPosition();    // 如果为真,则节点锚点坐标为(0,0)
    void ignoreAnchorPointForPosition(bool isIgnoreAnchorPointForPosition);     // 设置是否忽略锚点坐标
    static CCNode * create(void);       // 创建一个CCNode对象,有自动释放对象功能
    virtual void onEnter();      // 节点进入舞台(stage)时的回调函数 
    virtual void onEnterTransitionDidFinish();  // 节点计入舞台后的回调函数
    virtual void onExit();    // 节点离开舞台后的回调函数
    virtual void onExitTransitionDidStart();    //节点离开舞台时的回调函数
    virtual void registerScriptHandler(int nHandler);     // 注册onEnter、onExit的脚本处理函数,onEnter运行后脚本处理函数自动取消注册
    virtual void unregisterScriptHandler(void);      // 取消注册脚本处理函数
    virtual void addChild(CCNode * child);     // 增加子节点,z坐标为0。如果子节点附加到一个运行中的节点,那么onEnter和onEnterTransitionDidFinish函数将立即被调用
    virtual void addChild(CCNode * child, int zOrder);    // 增加子节点,z坐标为zOrder。如附加到一个运行中节点,同上
    virtual void addChild(CCNode * child, int zOrder, int tag);   // 增加子节点,z坐标为zOrder,tag为标志。如附加到运行中节点,同上。
    void removeFromParentAndCleanup(bool cleanup);    // 从父节点中删除自己,若参数cleanup为真,同时删除所有动作和回调函数。若本节点无父节点,则不执行操作
    virtual void removeChild(CCNode* child, bool cleanup);     // 删除子节点。根据参数cleanup删除运行中的动作
    void removeChildByTag(int tag, bool cleanup);    // 通过tag值删除子节点,根据参数cleanup删除动作
    virtual void removeAllChildrenWithCleanup(bool cleanup);    // 删除所有子节点,根据参数cleanup删除动作*/
    CCNode * getChildByTag(int tag);     //根据tag值获取子节点,返回值是CCNode型
    virtual void reorderChild(CCNode * child, int zOrder);    // 根据参数zOrder对子节点重排序,子节点必须已经被附加至本节点
    virtual void sortAllChildren();    // 在被绘制前对子节点进行排序,而不是在每次增减子节点时排序。除非子节点在同一帧内附加后被删除,不然不要手动调用此方法
    virtual void cleanup(void);     // 停止所有运行的动作和定时器
    virtual void draw(void);      // 可重载此函数来绘制节点
    virtual void visit(void);     // 递归访问子节点并绘制它们
    CCAction* runAction(CCAction* action);     // 运行指定的动作
    void stopAllActions(void);     // 从运行动作列表中删除所有动作,即停止所有动作
    void stopAction(CCAction* action);     // 停止指定的动作
    void stopActionByTag(int tag);     // 停止参数tag指定的动作
    CCAction* getActionByTag(int tag);    // 获取参数tag指定的动作
    unsigned int numberOfRunningActions(void);     // 运行动作的数目,为运行中的动作数加上定时器计划将运行的动作数。组合动作如序列动作将被当成一个动作计算。
    bool isScheduled(SEL_SCHEDULE selector);     // 检测参数selector指定的选择器是否被计划定时
    void scheduleUpdate(void);     // 定时调度update方法,其序列号为0。定时后,每帧将调用一次update方法。序列号越小的定时器越先调度。每个节点只能定时一个update方法。
    void scheduleUpdateWithPriority(int priority);    // 定时调度update选择器,自定义优先级。每帧将调用一次update选择器。优先级越小越先调度。每个节点只能定时一个update选择器。
    void unscheduleUpdate(void);     // 取消定时update
    void schedule(SEL_SCHEDULE selector);     // 定时一个选择器,每帧调用一次
    void schedule(SEL_SCHEDULE selector, float interval);    // 定时一个自定义选择器,参数interval为时间间隔,单位为秒。若interval为0,则每帧调用一次(此时推荐使用scheduleUpdate 方法)。若选择器已被定时,则仅更新时间间隔,而不重复定时。
    void schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay);  // 重复执行动作repeat+1次,不断重复则设置repeat为kCCRepeatForever。参数delay指定动作执行前延迟的时间
    void scheduleOnce(SEL_SCHEDULE selector, float delay);     // 定时一个仅运行一次的选择器
    void unschedule(SEL_SCHEDULE selector);    // 取消定时一个选择器
    void unscheduleAllSelectors(void);    // 取消所有定时器,包括update选择器。动作不受影响
    void resumeSchedulerAndActions(void);    // 恢复所有定时器和动作,被onEnter内部调用
    void pauseSchedulerAndActions(void);    // 暂停所有定时器和动作,被onExit内部调用

    好了,今天就介绍到这里。如果,大家有什么不懂的,或者有什么想学习的,可以直接留言哦。
    CocoStudio 讨论学习群:141444261
    Cocos2D-X  讨论学习群:244959010


本文出自 “张鹏飞” 博客,请务必保留此出处http://502317120.blog.51cto.com/4062300/1191871

2013年11月21日 星期四

加菲猫 Just have a little faith. [Cocos2d-x For WP8]矩形碰撞检测

http://www.cnblogs.com/linzheng/p/3279517.html

   在游戏中我们通常会涉及到两个精灵之间的碰撞的计算,那么在Cocos2d-x里面我们通常会用矩形碰撞检测来计算两个精灵在运动的过程中是否碰撞到了。 原理很简单,就是当运动的时候通过精灵的矩形坐标进行遍历来计算精灵之间是否有重合,如果有重合那就证明是碰撞上了。
    下面看一下下面的例子:
Ball精灵会根据帧速率来进行运动的,下面是Ball精灵的实现代码:
复制代码
#ifndef _BALL_H_
#define _BALL_H_

#include "cocos2d.h"
/*
创建一个球的精灵
*/
class Paddle;

using namespace cocos2d;

class Ball : public CCSprite
{
    CCPoint m_velocity;
public:
    Ball(void);
    virtual ~Ball(void);

    float radius();
    //BOOL initWithTexture(CCTexture2D* aTexture);
    //virtual void setTexture(CCTexture2D* newTexture);
    void move(ccTime delta);
    void collideWithPaddle(Paddle* paddle);


public:
    void setVelocity(CCPoint velocity){m_velocity = velocity;}
    CCPoint getVelocity(){return m_velocity;}

public:
    static Ball* ballWithTexture(CCTexture2D* aTexture);
};

#endif


#include "pch.h"
#include "Ball.h"
#include "Paddle.h"

Ball::Ball(void)
{
}

Ball::~Ball(void)
{
}

float Ball::radius()
{
    return getTexture()->getContentSize().width / 2;
}
//使用CCTexture2D创建ball精灵
Ball* Ball::ballWithTexture(CCTexture2D* aTexture)
{
    Ball* pBall = new Ball();
    pBall->initWithTexture(aTexture);
    pBall->autorelease();

    return pBall;
}
//移动ball精灵
void Ball::move(ccTime delta)
{
    //根据m_velocity的数值设置ball精灵的位置
    this->setPosition( ccpAdd(getPosition(), ccpMult(m_velocity, delta)) );
    
    if (getPosition().x > 320 - radius()) 
    {
        setPosition( ccp( 320 - radius(), getPosition().y) );
        m_velocity.x *= -1;
    } 
    else if (getPosition().x < radius()) 
    {
        setPosition( ccp(radius(), getPosition().y) );
        m_velocity.x *= -1;
    }
}
//判断是否碰撞到paddle精灵
void Ball::collideWithPaddle(Paddle* paddle)
{
    //获取paddle精灵的矩形位置
    CCRect paddleRect = paddle->rect();
    //转化成绝对的位置
    paddleRect.origin.x += paddle->getPosition().x;
    paddleRect.origin.y += paddle->getPosition().y;
    //获取paddle精灵的矩形的相关数值
    float lowY = paddleRect.getMinY();  //CCRect::getMidY(paddleRect);
    float midY = paddleRect.getMidY(); //CCRect::CCRectGetMidY(paddleRect);
    float highY =paddleRect.getMaxY();// CCRect::CCRectGetMaxY(paddleRect);
    
    float leftX = paddleRect.getMinX();//CCRect::CCRectGetMinX(paddleRect);
    float rightX =paddleRect.getMaxX(); //CCRect::CCRectGetMaxX(paddleRect);
    
    if (getPosition().x > leftX && getPosition().x < rightX) {
    
        bool hit = false;
        float angleOffset = 0.0f; 
        //判断是否碰撞到paddle精灵
        if (getPosition().y > midY && getPosition().y <= highY + radius()) 
        {
            setPosition( CCPointMake(getPosition().x, highY + radius()) );
            hit = true;
            angleOffset = (float)M_PI / 2;
        }
        else if (getPosition().y < midY && getPosition().y >= lowY - radius()) 
        {
            setPosition( CCPointMake(getPosition().x, lowY - radius()) );
            hit = true;
            angleOffset = -(float)M_PI / 2;
        }
        
        if (hit) 
        {
            //碰撞到则调整方向
            float hitAngle = ccpToAngle(ccpSub(paddle->getPosition(), getPosition())) + angleOffset;
            
            float scalarVelocity = ccpLength(m_velocity) * 1.05f;
            float velocityAngle = -ccpToAngle(m_velocity) + 0.5f * hitAngle;
            
            m_velocity = ccpMult(ccpForAngle(velocityAngle), scalarVelocity);
        }
    }    
} 
复制代码

Paddle精灵相当于是挡板的意思,Paddle精灵是静止的,当Ball精灵碰撞到Paddle精灵的时候,运动的轨迹就会发生变化。
Paddle精灵的代码:
复制代码
#ifndef _PADDLE_H_
#define _PADDLE_H_

#include "cocos2d.h"

using namespace cocos2d;
/*
创建一个挡板精灵
*/
typedef enum tagPaddleState 
{
    kPaddleStateGrabbed,
    kPaddleStateUngrabbed
} PaddleState; 

class Paddle : public CCSprite, public CCTargetedTouchDelegate
{
    PaddleState        m_state;

public:
    Paddle(void);
    virtual ~Paddle(void);

    CCRect rect();
    bool initWithTexture(CCTexture2D* aTexture);
    virtual void onEnter();
    virtual void onExit();
    bool containsTouchLocation(CCTouch* touch);
    virtual bool ccTouchBegan(CCTouch* touch, CCEvent* event);
    virtual void ccTouchMoved(CCTouch* touch, CCEvent* event);
    virtual void ccTouchEnded(CCTouch* touch, CCEvent* event);

    virtual void touchDelegateRetain();
    virtual void touchDelegateRelease();

    static Paddle* paddleWithTexture(CCTexture2D* aTexture);
};

#endif


#include "pch.h"
#include "Paddle.h"

Paddle::Paddle(void)
{
}

Paddle::~Paddle(void)
{
}
//获取paddle精灵的矩形位置
CCRect Paddle::rect()
{
    CCSize s = getTexture()->getContentSize();
    return CCRectMake(-s.width / 2, -s.height / 2, s.width, s.height);
}

Paddle* Paddle::paddleWithTexture(CCTexture2D* aTexture)
{
    Paddle* pPaddle = new Paddle();
    pPaddle->initWithTexture( aTexture );
    pPaddle->autorelease();

    return pPaddle;
}

bool Paddle::initWithTexture(CCTexture2D* aTexture)
{
    if( CCSprite::initWithTexture(aTexture) ) 
    {
        m_state = kPaddleStateUngrabbed;
    }
    
    return true;
}

void Paddle::onEnter()
{
    CCTouchDispatcher* pDispatcher = CCDirector::sharedDirector()->getTouchDispatcher();
    pDispatcher->addTargetedDelegate(this, 0, true);
    CCSprite::onEnter();
}

void Paddle::onExit()
{
    CCTouchDispatcher* pDispatcher = CCDirector::sharedDirector()->getTouchDispatcher();
    pDispatcher->removeDelegate(this);
    CCSprite::onExit();
}    

bool Paddle::containsTouchLocation(CCTouch* touch)
{
    return rect().containsPoint(convertTouchToNodeSpaceAR(touch));;//CCRect::containsPoint(rect(), convertTouchToNodeSpaceAR(touch));
}

bool Paddle::ccTouchBegan(CCTouch* touch, CCEvent* event)
{
    if (m_state != kPaddleStateUngrabbed) return false;
    if ( !containsTouchLocation(touch) ) return false;
    
    m_state = kPaddleStateGrabbed;
    return true;
}
//移动paddle精灵
void Paddle::ccTouchMoved(CCTouch* touch, CCEvent* event)
{
    CCAssert(m_state == kPaddleStateGrabbed, L"Paddle - Unexpected state!");    
    
    CCPoint touchPoint = touch->getLocationInView();
    touchPoint = CCDirector::sharedDirector()->convertToGL( touchPoint );
    
    setPosition( CCPointMake(touchPoint.x, getPosition().y) );
}

void Paddle::ccTouchEnded(CCTouch* touch, CCEvent* event)
{
    CCAssert(m_state == kPaddleStateGrabbed, L"Paddle - Unexpected state!");    
    
    m_state = kPaddleStateUngrabbed;
} 

void Paddle::touchDelegateRetain()
{
    this->retain();
}

void Paddle::touchDelegateRelease()
{
    this->release();
}
复制代码
下面是实现碰撞的Layer:
复制代码
//------------------------------------------------------------------
//
// 初始化[碰撞的Layer
//
//------------------------------------------------------------------
PongLayer::PongLayer()
{
    m_ballStartingVelocity = CCPointMake(20.0f, -100.0f);
    //创建ball精灵
    m_ball = Ball::ballWithTexture( CCTextureCache::sharedTextureCache()->addImage("cat.png") );
    m_ball->setPosition( CCPointMake(160.0f, 240.0f) );
    m_ball->setVelocity( m_ballStartingVelocity );
    addChild( m_ball );
    m_ball->retain();
    
    //创建4个Paddle精灵
    CCTexture2D* paddleTexture = CCTextureCache::sharedTextureCache()->addImage("paddle.png");
    m_paddles = new CCArray(4);
    Paddle* paddle = Paddle::paddleWithTexture(paddleTexture);
    paddle->setPosition( CCPointMake(160, 15) );
    m_paddles->addObject( paddle );
    
    paddle = Paddle::paddleWithTexture( paddleTexture );
    paddle->setPosition( CCPointMake(160, 480 - kStatusBarHeight - 15) );
    m_paddles->addObject( paddle );
    
    paddle = Paddle::paddleWithTexture( paddleTexture );
    paddle->setPosition( CCPointMake(160, 100) );
    m_paddles->addObject( paddle );
    
    paddle = Paddle::paddleWithTexture( paddleTexture );
    paddle->setPosition( CCPointMake(160, 480 - kStatusBarHeight - 100) );
    m_paddles->addObject( paddle );

    CCObject* arrayItem;
    CCARRAY_FOREACH(m_paddles, arrayItem){
       paddle = (Paddle*)(arrayItem);
       if(!paddle)
                break;
            addChild(paddle);
    }
    //每一帧刷新ball精灵的运动
    schedule( schedule_selector(PongLayer::doStep) );
}

PongLayer::~PongLayer()
{
    m_ball->release();
    m_paddles->release();
}

void PongLayer::resetAndScoreBallForPlayer(int player)
{
    m_ballStartingVelocity = ccpMult(m_ballStartingVelocity, -1.1f);
    m_ball->setVelocity( m_ballStartingVelocity );
    m_ball->setPosition( CCPointMake(160.0f, 240.0f) );
}

void PongLayer::doStep(ccTime delta)
{
    //移动ball精灵
    m_ball->move(delta);
    Paddle* paddle;
    CCObject* arrayItem;
    CCARRAY_FOREACH(m_paddles, arrayItem){
       paddle = (Paddle*)(arrayItem);
       if(!paddle)
                break;
            //判断ball精灵是否碰到paddle精灵
            m_ball->collideWithPaddle( paddle );
    }
    //判断是否碰到边界
    if (m_ball->getPosition().y > 480 - kStatusBarHeight + m_ball->radius())
        resetAndScoreBallForPlayer( kLowPlayer );
    else if (m_ball->getPosition().y < -m_ball->radius())
        resetAndScoreBallForPlayer( kHighPlayer );
    m_ball->draw();
} 
复制代码
在helloworld项目中加入该Layer
复制代码
CCScene* HelloWorld::scene()
{
    CCScene * scene = NULL;
    do 
    {   // 'scene'是一个可以自动释放的对象
        scene = CCScene::create();
        //创建失败跳出循环
        CC_BREAK_IF(! scene);
        PongLayer *pongLayer = new PongLayer();
        scene->addChild(pongLayer);
    } while (0);

    // 返回scene
    return scene;
}
复制代码
运行的效果:

2013年11月18日 星期一

android获取web服务器端session并验证登陆

http://www.yoyong.com/archives/178

传统网页实现用户登陆一般采用session或cookie记录用户基本信息又或者两者结合起来使用。android也可以采用session 实现用户登陆验证并记录用户登陆状态时的基本信息,session是在服务器端的;而类似cookie的记录方式,则可以在客户端采用xml文件记录用户 基本信息,重要数据则可以加密存放客户端。android实现的session登陆功能与网页请求不同的是,网页形式的一次成功的登陆请求后,再点击其他 页面时,session一直是存在的,在一定时间内是有效的;而采用android客户端请求的一次成功登陆后,再次发送新的请求,则会产生新的 session,而不是原来的。这就需要记录session的id号,并在整个请求过程中都记录并传递这个id号,才能保证session的一致性。
以获取php session为例,主要思路实现分为客户端与服务器端3个步骤。

附件:源码下载


1.)客户端(Android)

建立一个名为GetWebSession的android项目,编写GetWebSession.java,LoginSuccessActivity.java,GetUserInfoActivity.java三个activity类。
1. GetWebSession.java主要是实现布局界面以及发送用户名和密码到php服务器端验证,如果验证成功则跳转到 LoginSuccessActivity.java类。GetWebSession.java主要涉及到与服务器端连接请求,对从服务器端返回的 json数据(如用户id,session等)进行解析,并存入HashMap,传递到LoginSuccessActivity.java
代码如下:
  1. package com.login.main;  
  2. import java.io.IOException;  
  3. import java.io.UnsupportedEncodingException;  
  4. import java.util.ArrayList;  
  5. import java.util.HashMap;  
  6. import java.util.List;  
  7. import org.apache.http.HttpEntity;  
  8. import org.apache.http.HttpResponse;  
  9. import org.apache.http.client.ClientProtocolException;  
  10. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  11. import org.apache.http.client.methods.HttpPost;  
  12. import org.apache.http.impl.client.DefaultHttpClient;  
  13. import org.apache.http.message.BasicNameValuePair;  
  14. import org.apache.http.protocol.HTTP;  
  15. import org.apache.http.util.EntityUtils;  
  16. import org.json.JSONException;  
  17. import org.json.JSONObject;  
  18. import android.app.Activity;  
  19. import android.content.Context;  
  20. import android.content.Intent;  
  21. import android.os.Bundle;  
  22. import android.view.View;  
  23. import android.view.View.OnClickListener;  
  24. import android.widget.Button;  
  25. import android.widget.EditText;  
  26. import android.widget.Toast;  
  27. public class GetWebSession extends Activity {  
  28. /** Called when the activity is first created. */  
  29. private EditText user;  
  30. private EditText password;  
  31. private Button loginBtn;  
  32. private Button logoutBtn;  
  33. //主要是记录用户会话过程中的一些用户的基本信息  
  34. private HashMap<String, String> session =new HashMap<String, String>();  
  35. @Override  
  36. public void onCreate(Bundle savedInstanceState) {  
  37. super.onCreate(savedInstanceState);  
  38. setContentView(R.layout.main);  
  39. user=(EditText)findViewById(R.id.user);  
  40. password=(EditText)findViewById(R.id.password);  
  41. loginBtn=(Button)findViewById(R.id.loginBtn);  
  42. loginBtn.setOnClickListener(loginClick);  
  43. logoutBtn=(Button)findViewById(R.id.logoutBtn);  
  44. logoutBtn.setOnClickListener(logoutClick);  
  45. }  
  46. OnClickListener loginClick=new OnClickListener() {  
  47. @Override  
  48. public void onClick(View v) {  
  49. // TODO Auto-generated method stub  
  50. if(checkUser()){  
  51. Toast.makeText(v.getContext(), "用户登录成功!", Toast.LENGTH_SHORT).show();  
  52. Context context = v.getContext();  
  53. Intent intent = new Intent(context,  
  54. LoginSuccessActivity.class);  
  55. //传递session参数,在用户登录成功后为session初始化赋值,即传递HashMap的值  
  56. Bundle map = new Bundle();  
  57. map.putSerializable("sessionid", session);  
  58. intent.putExtra("session", map);  
  59. context.startActivity(intent); // 跳转到成功页面  
  60. }  
  61. else  
  62. Toast.makeText(v.getContext(), "用户验证失败!", Toast.LENGTH_SHORT).show();  
  63. }  
  64. };  
  65. OnClickListener logoutClick=new OnClickListener() {  
  66. @Override  
  67. public void onClick(View v) {  
  68. // TODO Auto-generated method stub  
  69. System.exit(0);  
  70. }  
  71. };  
  72. private boolean checkUser(){  
  73. String username=user.getText().toString();  
  74. String pass=password.getText().toString();  
  75. DefaultHttpClient mHttpClient = new DefaultHttpClient();  
  76. HttpPost mPost = new HttpPost("http://10.0.2.2/web/php/login.php");  
  77. //传递用户名和密码相当于  
  78. //http://10.0.2.2/web/php/login.php?username=''&password=''  
  79. List<BasicNameValuePair> pairs = new ArrayList<BasicNameValuePair>();  
  80. pairs.add(new BasicNameValuePair("username", username));  
  81. pairs.add(new BasicNameValuePair("password", pass));  
  82. try {  
  83. mPost.setEntity(new UrlEncodedFormEntity(pairs, HTTP.UTF_8));  
  84. catch (UnsupportedEncodingException e) {  
  85. // TODO Auto-generated catch block  
  86. e.printStackTrace();  
  87. }  
  88. try {  
  89. HttpResponse response = mHttpClient.execute(mPost);  
  90. int res = response.getStatusLine().getStatusCode();  
  91. if (res == 200) {  
  92. HttpEntity entity = response.getEntity();  
  93. if (entity != null) {  
  94. String info = EntityUtils.toString(entity);  
  95. System.out.println("info-----------"+info);  
  96. //以下主要是对服务器端返回的数据进行解析  
  97. JSONObject jsonObject=null;  
  98. //flag为登录成功与否的标记,从服务器端返回的数据  
  99. String flag="";  
  100. String name="";  
  101. String userid="";  
  102. String sessionid="";  
  103. try {  
  104. jsonObject = new JSONObject(info);  
  105. flag = jsonObject.getString("flag");  
  106. name = jsonObject.getString("name");  
  107. userid = jsonObject.getString("userid");  
  108. sessionid = jsonObject.getString("sessionid");  
  109. catch (JSONException e) {  
  110. // TODO Auto-generated catch block  
  111. e.printStackTrace();  
  112. }  
  113. //根据服务器端返回的标记,判断服务端端验证是否成功  
  114. if(flag.equals("success")){  
  115. //为session传递相应的值,用于在session过程中记录相关用户信息  
  116. session.put("s_userid", userid);  
  117. session.put("s_username", name);  
  118. session.put("s_sessionid", sessionid);  
  119. return true;  
  120. }  
  121. else{  
  122. return false;  
  123. }  
  124. }  
  125. else{  
  126. return false;  
  127. }  
  128. }  
  129. catch (ClientProtocolException e) {  
  130. // TODO Auto-generated catch block  
  131. e.printStackTrace();  
  132. catch (IOException e) {  
  133. // TODO Auto-generated catch block  
  134. e.printStackTrace();  
  135. }  
  136. return false;  
  137. }  
  138. }  
2. LoginSuccessActivity.java主要获取php的session唯一的标识id以及用户的一些基本信息,session id则作为本次用户登录状态在服务器的唯一标识,即确定用户的唯一状态进行相关操作。LoginSuccessActivity.java类的方法与 GetWebSession.java类似。其主要功能是获取session id后再次发送session id到服务器进行验证,根据封装的session数据验证用户操作权限等。
代码如下:
  1. package com.login.main;  
  2. import java.io.IOException;  
  3. import java.io.UnsupportedEncodingException;  
  4. import java.util.ArrayList;  
  5. import java.util.HashMap;  
  6. import java.util.List;  
  7. import org.apache.http.HttpEntity;  
  8. import org.apache.http.HttpResponse;  
  9. import org.apache.http.client.ClientProtocolException;  
  10. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  11. import org.apache.http.client.methods.HttpPost;  
  12. import org.apache.http.impl.client.DefaultHttpClient;  
  13. import org.apache.http.message.BasicNameValuePair;  
  14. import org.apache.http.protocol.HTTP;  
  15. import org.apache.http.util.EntityUtils;  
  16. import org.json.JSONException;  
  17. import org.json.JSONObject;  
  18. import android.app.Activity;  
  19. import android.content.Context;  
  20. import android.content.Intent;  
  21. import android.os.Bundle;  
  22. import android.view.View;  
  23. import android.view.View.OnClickListener;  
  24. import android.widget.Button;  
  25. import android.widget.TextView;  
  26. import android.widget.Toast;  
  27. public class LoginSuccessActivity extends Activity{  
  28. private HashMap<String, String>session;  
  29. @SuppressWarnings("unchecked")  
  30. @Override  
  31. protected void onCreate(Bundle savedInstanceState) {  
  32. // TODO Auto-generated method stub  
  33. super.onCreate(savedInstanceState);  
  34. setContentView(R.layout.login_success);  
  35. //获取从登录成功后界面的传递的参数  
  36. session =  (HashMap<String, String>) this.getIntent()  
  37. .getBundleExtra("session").getSerializable("sessionid");  
  38. //读取session的基本信息,并显示相应的控件  
  39. String userid_info=session.get("s_userid");  
  40. String username_info=session.get("s_username");  
  41. String session_id=session.get("s_sessionid");  
  42. //显示相应的内容到控件  
  43. TextView userid_show=(TextView)findViewById(R.id.userid_show);  
  44. userid_show.setText(userid_info);  
  45. TextView username_show=(TextView)findViewById(R.id.username_show);  
  46. username_show.setText(username_info);  
  47. TextView sessionid_show=(TextView)findViewById(R.id.sessionid_show);  
  48. sessionid_show.setText(session_id);  
  49. //根据本次session再次获取用户信息  
  50. Button getInfo=(Button)findViewById(R.id.getinfo);  
  51. getInfo.setOnClickListener(getInfoClick);  
  52. }  
  53. OnClickListener getInfoClick=new OnClickListener() {  
  54. @Override  
  55. public void onClick(View v) {  
  56. // TODO Auto-generated method stub  
  57. if(getUserInfo()){  
  58. Context context = v.getContext();  
  59. Intent intent = new Intent(context,  
  60. GetUserInfoActivity.class);  
  61. //传递session参数,在用户登录成功后为session初始化赋值,即传递HashMap的值  
  62. Bundle map = new Bundle();  
  63. map.putSerializable("sessionid", session);  
  64. intent.putExtra("session", map);  
  65. context.startActivity(intent); // 跳转到成功页面  
  66. }else{  
  67. Toast.makeText(v.getContext(), "数据为空!", Toast.LENGTH_SHORT).show();  
  68. }  
  69. }  
  70. };  
  71. private boolean getUserInfo(){  
  72. String sess_username=session.get("s_username");  
  73. String sess_userid=session.get("s_userid");  
  74. String sess_id=session.get("s_sessionid");  
  75. DefaultHttpClient mHttpClient = new DefaultHttpClient();  
  76. HttpPost mPost = new HttpPost("http://10.0.2.2/web/php/getinfo.php");  
  77. List<BasicNameValuePair> pairs = new ArrayList<BasicNameValuePair>();  
  78. pairs.add(new BasicNameValuePair("sess_userid", sess_userid));  
  79. pairs.add(new BasicNameValuePair("sess_username", sess_username));  
  80. pairs.add(new BasicNameValuePair("sess_sessionid", sess_id));  
  81. try {  
  82. mPost.setEntity(new UrlEncodedFormEntity(pairs, HTTP.UTF_8));  
  83. catch (UnsupportedEncodingException e) {  
  84. // TODO Auto-generated catch block  
  85. e.printStackTrace();  
  86. }  
  87. try {  
  88. HttpResponse response = mHttpClient.execute(mPost);  
  89. int res = response.getStatusLine().getStatusCode();  
  90. if (res == 200) {  
  91. HttpEntity entity = response.getEntity();  
  92. if (entity != null) {  
  93. String info = EntityUtils.toString(entity);  
  94. System.out.println("info-----------"+info);  
  95. //以下主要是对服务器端返回的数据进行解析  
  96. JSONObject jsonObject=null;  
  97. //flag为登录成功与否的标记,从服务器端返回的数据  
  98. String flag="";  
  99. String userinfo="";  
  100. String level="";  
  101. String sessionid="";  
  102. try {  
  103. jsonObject = new JSONObject(info);  
  104. flag = jsonObject.getString("flag");  
  105. userinfo = jsonObject.getString("info");  
  106. level = jsonObject.getString("level");  
  107. sessionid = jsonObject.getString("sessionid");  
  108. catch (JSONException e) {  
  109. // TODO Auto-generated catch block  
  110. e.printStackTrace();  
  111. }  
  112. //根据服务器端返回的标记,判断服务端端验证是否成功  
  113. if(flag.equals("notempty")){  
  114. //为session传递相应的值,用于在session过程中记录相关用户信息  
  115. session.put("info_userinfo", userinfo);  
  116. session.put("info_level", level);  
  117. session.put("info_sessionid", sessionid);  
  118. return true;  
  119. }  
  120. else{  
  121. return false;  
  122. }  
  123. }  
  124. else{  
  125. return false;  
  126. }  
  127. }  
  128. catch (ClientProtocolException e) {  
  129. // TODO Auto-generated catch block  
  130. e.printStackTrace();  
  131. catch (IOException e) {  
  132. // TODO Auto-generated catch block  
  133. e.printStackTrace();  
  134. }  
  135. return false;  
  136. }  
  137. }  
3.GetUserInfoActivity.java类是根据用户登录后产生唯一session 标识进行操作获取用户详细信息的类。
代码如下:
  1. package com.login.main;  
  2. import java.util.HashMap;  
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.widget.TextView;  
  6. public class GetUserInfoActivity extends Activity{  
  7. private HashMap<String, String>session;  
  8. @SuppressWarnings("unchecked")  
  9. @Override  
  10. protected void onCreate(Bundle savedInstanceState) {  
  11. // TODO Auto-generated method stub  
  12. super.onCreate(savedInstanceState);  
  13. setContentView(R.layout.get_info);  
  14. //获取从登录成功后界面的再次传递的参数  
  15. session =  (HashMap<String, String>) this.getIntent().  
  16. getBundleExtra("session").getSerializable("sessionid");  
  17. //读取session的基本信息,并显示相应的控件  
  18. String session_info=session.get("info_userinfo");  
  19. String session_level=session.get("info_level");  
  20. String session_id=session.get("info_sessionid");  
  21. //显示相应的内容到控件  
  22. System.out.println("session_info--------"+session_info);  
  23. TextView get_info=(TextView)findViewById(R.id.get_info);  
  24. get_info.setText(session_info);  
  25. TextView get_level=(TextView)findViewById(R.id.get_level);  
  26. get_level.setText(session_level);  
  27. TextView get_sessionid=(TextView)findViewById(R.id.get_sessionid);  
  28. get_sessionid.setText(session_id);  
  29. }  
  30. }  
4.三个布局的xml文件
(1.)main.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3. android:orientation="vertical"  
  4. android:layout_width="fill_parent"  
  5. android:layout_height="fill_parent" >  
  6. <TextView android:layout_height="wrap_content"  
  7. android:layout_width="wrap_content"  
  8. android:text="用户"></TextView>  
  9. <EditText android:layout_height="wrap_content"  
  10. android:text="" android:layout_width="fill_parent"  
  11. android:singleLine="true" android:id="@+id/user"  ></EditText>  
  12. <TextView android:layout_height="wrap_content"   
  13. android:layout_width="wrap_content"  
  14. android:text="密码"></TextView>  
  15. <EditText android:id="@+id/password"  
  16. android:layout_height="wrap_content"  
  17. android:text="" android:layout_width="fill_parent"  
  18. android:password="true" android:singleLine="true"></EditText>  
  19. <LinearLayout android:layout_height="wrap_content"   
  20. android:layout_width="fill_parent"  
  21. android:orientation="horizontal"  
  22. android:paddingLeft="0dip">  
  23.   
  24. <TableRow android:layout_width="fill_parent"  
  25. android:layout_height="wrap_content">  
  26. <Button android:layout_height="fill_parent"  
  27. android:layout_width="fill_parent" android:text="登录"  
  28. android:id="@+id/loginBtn"  
  29. android:layout_weight="1"></Button>  
  30. <Button android:layout_height="fill_parent"  
  31. android:layout_width="fill_parent"  
  32. android:text="退出"   
  33. android:id="@+id/logoutBtn"  
  34. android:layout_weight="1"></Button>  
  35.   
  36. </TableRow> </LinearLayout> </LinearLayout>  

(2.)login_success.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.  android:layout_width="fill_parent" android:layout_height="fill_parent"  
  4.  android:orientation="vertical">  
  5. <LinearLayout android:layout_height="wrap_content"   
  6. android:layout_width="fill_parent"  
  7. android:orientation="horizontal"  
  8. android:paddingLeft="0dip">  
  9. <TextView  
  10. android:layout_height="fill_parent"  
  11. android:layout_width="wrap_content"  
  12. android:text="用户ID:"   >  
  13. </TextView>  
  14. <TextView android:layout_height="fill_parent"  
  15. android:layout_width="fill_parent"  
  16. android:text=""   
  17. android:id="@+id/userid_show" ></TextView>  
  18. </LinearLayout>  
  19. <LinearLayout android:layout_height="wrap_content"   
  20. android:layout_width="fill_parent"  
  21. android:orientation="horizontal"  
  22. android:paddingLeft="0dip">  
  23. <TextView android:layout_height="fill_parent"  
  24. android:layout_width="wrap_content"  
  25. android:text="用户名: "   ></TextView>  
  26. <TextView android:layout_height="fill_parent"  
  27. android:layout_width="fill_parent"  
  28. android:text=""   
  29. android:id="@+id/username_show" ></TextView>  
  30. </LinearLayout>  
  31. <LinearLayout android:layout_height="wrap_content"   
  32. android:layout_width="fill_parent"  
  33. android:orientation="horizontal"  
  34. android:paddingLeft="0dip">  
  35. <TextView android:layout_height="fill_parent"  
  36. android:layout_width="wrap_content"  
  37. android:text="本次会话:"   ></TextView>  
  38. <TextView android:layout_height="fill_parent"  
  39. android:layout_width="fill_parent"  
  40. android:text=""   
  41. android:id="@+id/sessionid_show" ></TextView>  
  42. </LinearLayout>  
  43. <LinearLayout android:layout_height="wrap_content"   
  44. android:layout_width="fill_parent"  
  45. android:orientation="horizontal"  
  46. android:paddingLeft="0dip">  
  47. <Button android:layout_height="fill_parent"  
  48. android:layout_width="wrap_content"  
  49. android:id="@+id/getinfo"  
  50. android:text="根据本次会话再次获取用户信息"    
  51. ></Button>  
  52. </LinearLayout>  
  53. </LinearLayout>  

(3.)get_info.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3. android:layout_width="fill_parent"  
  4. android:layout_height="fill_parent"  
  5. android:orientation="vertical">  
  6. <LinearLayout android:layout_height="wrap_content"   
  7. android:layout_width="fill_parent"  
  8. android:orientation="horizontal"  
  9. android:paddingLeft="0dip">  
  10. <TextView android:layout_height="fill_parent"  
  11. android:layout_width="wrap_content"  
  12. android:text="用户信息: "   >  
  13. </TextView>  
  14. <TextView android:layout_height="fill_parent"  
  15. android:layout_width="fill_parent"  
  16. android:text=""   
  17. android:id="@+id/get_info" ></TextView>  
  18. </LinearLayout>  
  19. <LinearLayout android:layout_height="wrap_content"   
  20. android:layout_width="fill_parent"  
  21. android:orientation="horizontal"  
  22. android:paddingLeft="0dip">  
  23. <TextView android:layout_height="fill_parent"  
  24. android:layout_width="wrap_content"  
  25. android:text="用户级别:"   ></TextView>  
  26. <TextView android:layout_height="fill_parent"  
  27. android:layout_width="fill_parent"  
  28. android:text=""   
  29. android:id="@+id/get_level" ></TextView>  
  30. </LinearLayout>  
  31.   
  32. <LinearLayout android:layout_height="wrap_content"  
  33. android:layout_width="fill_parent"  
  34. android:orientation="horizontal"  
  35. android:paddingLeft="0dip">  
  36. <TextView android:layout_height="fill_parent"  
  37. android:layout_width="wrap_content"  
  38. android:text="本次会话:"   ></TextView>  
  39. <TextView android:layout_height="fill_parent"  
  40. android:layout_width="fill_parent" android:text=""   
  41. android:id="@+id/get_sessionid" ></TextView>  
  42. </LinearLayout>  
  43. <LinearLayout android:layout_height="wrap_content"   
  44. android:layout_width="fill_parent"  
  45. android:orientation="horizontal"  
  46. android:paddingLeft="0dip"> </LinearLayout> </LinearLayout>  

2.)服务器端(php)

php服务器端主要有三个文件,conn.php,login.php和getinfo.php。
1. conn.php是连接数据库的配置文件。
2. login.php主要是用来验证android客户端发送的请求,请求成功则返回flag=’success’的状态标识,采用数组记录用户基本信息, 存储用户数据到session,并且记录本次产生的session id。用户基本数据及本次session产生的id均封装成json格式(json_encode($arr)),发送android客户端。产生本次 session id的方法
$sessionid=session_id();//注意没有参数
具体代码如下:
  1. <?php  
  2. header("Content-Type: text/html; charset=utf-8") ;  
  3. //包含数据库连接文件  
  4. include('conn.php');  
  5. session_start();  
  6. $username = htmlspecialchars($_POST["username"]);  
  7. $password=$_POST["password"];  
  8. mysql_query("set names utf8");  
  9. //检测用户名及密码是否正确  
  10. $check_query = mysql_query("select id ,name from user where name='$username' and 
  11. password='$password' limit 1");  
  12. $arr=array();//空的数组,该数组主要是格式化数据并封装成json格式发送到客户端  
  13. if($result = mysql_fetch_array($check_query)){  
  14. //登录成功  
  15. $_SESSION['username'] = $result['name'];  
  16. $_SESSION['userid'] = $result['id'];  
  17. //获取当前session id  
  18. $sessionid=session_id();  
  19. $_SESSION['$sessionid'] = $sessionid;  
  20. $arr = array(  
  21. 'flag'=>'success',  
  22. 'name'=>$result['name'],  
  23. 'userid'=>$result['id'],  
  24. 'sessionid'=>$sessionid  
  25. );  
  26. //封装json,如果php版本低于5.2,则不支持json_encode()方法,  
  27. //可以参考本文件夹中php_json_encode.php中php_json_encode()方法代替json_encode();  
  28. echo json_encode($arr);  
  29. else {  
  30. $arr = array(  
  31. 'flag'=>'error',  
  32. 'name'=>'',  
  33. 'userid'=>'',  
  34. 'sessionid'=>''  
  35. ); //封装json,如果php版本低于5.2,则不支持json_encode()方法,  
  36. //可以参考本文件夹中php_json_encode.php中php_json_encode()方法代替json_encode();  
  37. echo json_encode($arr);  
  38. }  
  39. ?>  
3. getinfo.php文件主要是用户再次查询信息验证session,而不是重新产生session,以记录用户状态。通过验证flag是否为empty判断数据是否显示。最后封装成json发送到客户端
获取本次session的方法:
$sessionid=$_POST["sess_sessionid"];//获取android客户端的sessionid
session_id($sessionid);//有参数
session_start();//启动session
具体代码如下:
  1. <?php  
  2. header("Content-Type: text/html; charset=utf-8") ;  
  3. include('conn.php');  
  4. //获取从客户端LoginSuccessActivity类传递的参数  
  5. $userid=$_POST["sess_userid"];  
  6. $username=$_POST["sess_username"];  
  7. //获取客户端传递的session标识  
  8. $sessionid=$_POST["sess_sessionid"];  
  9. session_id($sessionid);  
  10. //将会根据session id获得原来的session  
  11. session_start();  
  12. //获取服务器端原来session记录的username,并且根据客户端传过来的username比较进行验证操作  
  13. $sess_username=$_SESSION['username'];  
  14. if($username==$sess_username){  
  15. mysql_query("set names utf8");  
  16. //查询用户基本信息  
  17. $check_query = mysql_query("select userinfo,level from info where userid='$userid'  limit 1");  
  18. $arr=array();//空的数组  
  19. if($result = mysql_fetch_array($check_query)){  
  20. $arr = array(  
  21. 'flag'=>'notempty',  
  22. 'info'=>$result['userinfo'],  
  23. 'level'=>$result['level'],  
  24. 'sessionid'=>$sessionid  
  25. );  
  26. echo json_encode($arr);  
  27. }  
  28. else {  
  29. $arr = array(  
  30. 'flag'=>'empty',  
  31. 'name'=>'',  
  32. 'userid'=>'',  
  33. 'sessionid'=>$sessionid  
  34. );  
  35. echo json_encode($arr);  
  36. }  
  37. ?>  

3.)数据库端(mysql)

采用mysql建立数据库,建立两个简单的数据表:user和info。
  1. /*  
  2. MySQL Data Transfer  
  3. Source Host: localhost  
  4. Source Database: login  
  5. Target Host: localhost  
  6. Target Database: login  
  7. Date: 2011-6-14 11:10:46  
  8. */  
  9.   
  10. SET FOREIGN_KEY_CHECKS=0;  
  11. -- ----------------------------  
  12. -- Table structure for info  
  13. -- ----------------------------  
  14. CREATE TABLE `info` (  
  15. `id` int(12) NOT NULL AUTO_INCREMENT,  
  16. `userid` int(12) DEFAULT NULL,  
  17. `userinfo` varchar(100) DEFAULT NULL,  
  18. `levelint(2) DEFAULT NULL,  
  19. PRIMARY KEY (`id`),  
  20. KEY `useid` (`userid`),  
  21. CONSTRAINT `useid` FOREIGN KEY (`userid`) REFERENCES `user` (`id`)  
  22. ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;  
  23.   
  24. -- ----------------------------  
  25. -- Table structure for user  
  26. -- ----------------------------  
  27. CREATE TABLE `user` (  
  28. `id` int(12) NOT NULL AUTO_INCREMENT,  
  29. `namevarchar(20) DEFAULT NULL,  
  30. `passwordvarchar(20) DEFAULT NULL,  
  31. `status` int(2) DEFAULT NULL,  
  32. PRIMARY KEY (`id`)  
  33. ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;  
  34.   
  35. -- ----------------------------  
  36. -- Records  
  37. -- ----------------------------  
  38. INSERT INTO `info` VALUES ('1''1''charlie  is a developer.''1');  
  39. INSERT INTO `info` VALUES ('2''2''william is a boss.''20');  
  40. INSERT INTO `userVALUES ('1''charlie''password''1');  
  41. INSERT INTO `userVALUES ('2''william''mypassword''2');  

运行效果如图:

图 -1 GetWebSession.java类的布局

图 -2 LoginSuccessActivity.java类获取的session id以及用户基本信息

图 -3 GetWebSession.java获取用户详细信息及本次session的一致性