Session是由应用服务器维持的一个服务器端的存储空间,用户在连接服务器时,会由服务器生成一个唯一的SessionID,用该SessionID为标识符来存取服务器端的Session存储空间。而SessionID这一数据则是保存到客户端,用Cookie保存的,用户提交页面时,会将这一SessionID提交到服务器端,来存取Session数据。所以一旦客户端禁用Cookie,那么Session也会失效。
由于目前有的手机不支持cookie,导致手机上session支持不了,于是乎就有了几种针对这些特殊情况而提出的。而最常见的就是url重写,而url重写又分几种,有jstl实现,struts实现,普通传参实现,而我用的也就是最普通最常见的一种实现方式。
其实我也是根据kaixin001中的方式来做的,kaixin001中的wap形式就是在链接后面直接传sessionId的方式(其中包括了用户的id,后面有串字符串,我猜想应该就是sessionId),比如:http://localhost:8080/project/MobileLogin.do?sessionId=xxxxxxxx;这个sessionId就是session的id,通过链接传参的方式传到后台,在后台,由于不支持session,故需要自己开发一套基于session的操作。
首先,先了解下Map的含义,在java中,我们都知道Map是一个用于存储键值对的一个集合,也就是我们常说的key、value对应值,并且每个键映射一个值,这个键是不能重复的。
上面了解了Map的含义,为什么要了解Map,是因为在接下来我需要在程序中用到Map。好了,言归正传,怎么才能实现sessionId取session的步骤呢,相信看了上面的Map,应该有人脑子里面有思路了,那就是利用Map的存储方式来操作sessionId,根据sessionId生成一个session,由于Map是key不能重复,所以就可以把sessionId设置成key,session设置为map的value,并且要保证这个sessionId永远都只需要创建一次,这就又用到了一个经典的设计模式:单例模式。第一次登录访问sessionId是新的,就往map中put一个,
public synchronized void sessionCreated(HttpSession session) { if(session != null) { map.put(session.getId(), session); } }
除非你登录失败,否则这个sessionId一直跟随你的程序在运行,直到你手动注销session(把session destroryed)或者重新登录一次(替换原有的sessionId)。
public synchronized void sessionDestroyed(HttpSession session) { if(session != null) { map.remove(session.getId()); } }
单例模式的session容器已经构建,最后就是在类中提供一个getSession的方法;
public synchronized HttpSession getSession(String sessionId) { if(sessionId == null) return null; return (HttpSession) map.get(sessionId); }
session容器的构建类已经写完,现在就是监听事件了,新建一个Listener监听器,实现HttpSessionListener,HttpSessionListener提供2个方式,一个是sesionCreated(session的创建方法),一个是sessionDistoryed(session的销毁方法),在created方法中,调用单例类中的sessionCreate方法,在destroyed方法中调用单例类中的sessionDistoryed方法,监听器需要在web.xml中进行配置.
<listener> <listener-class>xxx包下的xxx类</listener-class> </listener>
至此,就完成了一个session的构建,并且这个session是根据sessionId的变化而变化。下面看具体的代码:
//session容器单例类
import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpSession; public class SessionContext { private static SessionContext instance; private Map<String, HttpSession> map; private SessionContext() { map = new HashMap<String, HttpSession>(); } public static SessionContext getInstance() { if(instance == null) { instance = new SessionContext(); } return instance; } public synchronized void sessionCreated(HttpSession session) { if(session != null) { map.put(session.getId(), session); } } public synchronized void sessionDestroyed(HttpSession session) { if(session != null) { map.remove(session.getId()); } } public synchronized HttpSession getSession(String sessionId) { if(sessionId == null) return null; return (HttpSession) map.get(sessionId); } }
//session监听器
import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; public class SessionListener implements HttpSessionListener { private SessionContext sessionContext = SessionContext.getInstance(); public void sessionCreated(HttpSessionEvent httpSessionEvent) { sessionContext.sessionCreated(httpSessionEvent.getSession()); } public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { sessionContext.sessionDestroyed(httpSessionEvent.getSession()); } }
session容器构建好了,现在就是action的操作了,action中相对比较简单。
public String sessionId; public HttpSession getWapSession() throws Exception { HttpSession session = SessionContext.getInstance().getSession(sessionId); return session; } public void delSession() throws Exception { SessionContext.getInstance().sessionDestroyed(getWapSession()); } public void setWapAttribute(String key, Object value) throws Exception { this.getWapSession().setAttribute(key, value); } public String getSessionId() { return sessionId; } public void setSessionId(String sessionId) { this.sessionId = sessionId; }
通过session传值,setWapAttribute(key,value),在页面上同样还是用SessionContext.getInstance().getSession(sessionId)得到session,才能从session中getAttribute值,其中的sessionId从request请求中get出,目前我还在测试怎么让它支持EL表达式,所以页面上还是用的<%%>这种取值方法。
以上就是action的部分代码,sessionId指的是页面上session.getId(),通过URL参数的方式传到后台,http://localhost:8080/project/xxx.do?session=<%=session.getId()%>,链接是这样的。url是自己组装。这个url方式是仿照开心网中的手机版本(wml.kaixin001.com),至此,一个手机登录的session问题是完美解决了,这里没有加权限判断。只提供了处理手机的登录session问题,相信有了session,其余的对我们来说不是什么难点。后期有时间再来写权限验证。
wap开发,页面展示必须是符合wml规范的文件,可以是jsp文件,只不过头部要把头部的contentType类型改成wml形式的,
<%@ page contentType="text/vnd.wap.wml;charset=utf-8"%>
然后
<?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml"> <wml> <card id="" title=""> </card> </wml>
记住一点,wml语法的一点就是一定要有结束标签,哪怕是用这样的<br>,在wml语法中也是错误的,必须要有结束。<br/>或者<br></br>,而且wml中严格区分大小写。这些都是必须遵守的。
如果有比这个更好的方法,期待共同探讨。
重定向就这样写
String url= response.encodeRedirectURL(request.getContextPath(+"/wap/Index_input.action");
response.sendRedirect(url);
自动会检查浏览器是否支持,如果不支持就会重写url 自动带上sessionid
我现在wap就是这样做的。。 楼主你这样我感觉有多余。 而且你还要维护哪个map。
???
楼主你这样写 有点误入子弟。。。
url重写又分几种,有jstl实现,struts实现,普通传参实现
普通实现应该就是
response.encodeURL(/blog_article/url/index.html);
可以了 。
重定向就这样写
String url= response.encodeRedirectURL(request.getContextPath(+"/wap/Index_input.action");
response.sendRedirect(url);
自动会检查浏览器是否支持,如果不支持就会重写url 自动带上sessionid
我现在wap就是这样做的。。 楼主你这样我感觉有多余。 而且你还要维护哪个map。
???
楼主你这样写 有点误入子弟。。。
哦,弱弱的问下,请问你这种session要怎么管理呢?我看了你写的文章,90%是网络上抄袭的,还有就是没有写session的管理。我没有恶意,只是我想问下你session是怎么管理的,我还没用过项目中,只是在研究阶段,第一次做wap开发,没什么经验。既然你有这方面的经验,那么我虚心请教下你。
另外singleton的实现有点问题
恩,知道了,是我多此一举了,我想复杂了。
重定向就这样写
String url= response.encodeRedirectURL(request.getContextPath(+"/wap/Index_input.action");
response.sendRedirect(url);
自动会检查浏览器是否支持,如果不支持就会重写url 自动带上sessionid
我现在wap就是这样做的。。 楼主你这样我感觉有多余。 而且你还要维护哪个map。
???
楼主你这样写 有点误入子弟。。。
哦,弱弱的问下,请问你这种session要怎么管理呢?我看了你写的文章,90%是网络上抄袭的,还有就是没有写session的管理。我没有恶意,只是我想问下你session是怎么管理的,我还没用过项目中,只是在研究阶段,第一次做wap开发,没什么经验。既然你有这方面的经验,那么我虚心请教下你。
是的。我是网上找的资料,为了以后方便查阅,其实也就是一时兴起, 我原来考虑也和你一样,我是参考的网易是怎么做的,(wap.163.com opera访问的) 我发现在禁用cookie的时候url网易会自动带上这个sessionid。
综合我现在的项目实践 我是这样做的。
1.在jsp中涉及到url是用的是标签库 <c:url 标签 填写url(/blog_article/这个标签自动会检查浏览器是否支持cookie,支持就原样返回,不支持自动带上sessionid/index.html)
2。在涉及后台转发时候用 首先用response.encodeURL()方法重写,和上面的标签一样的功能;
3.后台重定向用response.encodeRedirectURL()方法重写后转发。
有时候发现别人手机里有一款 apk 挺好,想弄出来装自己手机上,可是却发现那个 apk 是残缺的,里面没有 classes.dex 文件,却有个跟 apk 同名的 odex 文件。残缺的 apk 是装不了的,只能把这个 apk 跟 odex 合并成一个完整的 apk 才能安装。
需要的工具:
1 . smali-1.2.2.jar 和 baksmali-1.2.2.jar
2 . 还需要这个 apk 所在的 rom 里面的一些 jar 文件,都在 /system/framework 里面: core.jar, ext. jar, framework. jar, android.policy. jar, services. Jar 。当然,这五个是最基本的,有可能还不够,这种情况下面会讲到。
总共分四步:
1 . 把下载好的 smali-1.2.2.jar 和 baksmali-1.2.2.jar ,还有 rom 里面抠出来的 5 个 jar ,放到工作目录,然后 apk 和 odex 也放到一起。
2 . 分解 odex 文件为 class 文件。
命令: java -jar baksmali-1.2.2.jar -x <a.odex>
<a.odex> 处是你要分解的 odex 文件的名字,命令完成之后,会生成一个 out 文件夹,里面就是所有的 class 文件。如果出现问题,比如什么异常,缺少包什么的,就更到 rom 里面把出错信息里面要求的包拿出来,放到当前目录下。
3. 将 class 生成为 classes.dex 文件。
命令: java -Xmx512M -jar smali-1.2.2.jar out -o classes.dex
这一步应该不会有什么问题,然后会生成 classes.dex 文件。
4. 把 classes.dex 放入 apk 里面,把盖子盖上。
最后这一步最简单了,用解压缩软件打开 apk ,然后把千辛万苦生成的 classes.dex 塞进去,就 ok 了。这个 apk 就能用了。如果想给他重新签个名的话,去找个 Auto Sign 签名工具签署一下就行。
花了整整一天时间,研究怎么通过在Android应用程序中添加Admob广告来赚钱。网上也有些教程,不过说得不够详细,自己还得花时间摸索。为了让后来者能更快开始Admob广告赚钱,所以写个详细一点的教程,供大家参考。
[b]例子工程源码下载地址: [b]下载源代码
[/b]
当然,我也参考了一些网上的资料,主要有:
[b] AdMob:在android应用中嵌入广告的方案
[b]如何在Android Market赚钱 part 2 - 免费app附带广告
Publisher Starter Kit
[b]面向开发者 Wiki 的 AdMob
好了,现在让我从头开始说起……在这之前,你不需要有任何的帐号,唯一需要的就是有一个有效的email邮箱。只要按照下面的步骤一步步来,你就能通过将Admob的广告插到自己的程序中赚钱啦!
首先,当然是需要注册一个Admob的帐号。Admob的主页是:http://www.admob.com/ 。 当然,如果你对于浏览英文网页还有些障碍的话,可以登录中文网站:http://zhcn.admob.com/ 。如果网站的文字还是英文,你可以在网站主页的右下角的“Language”处,选择“中文(简体)”。点击进入注册页面后,有一些栏目需要填写,不要太过疑虑,就像你注册一个论坛一样,随便填下就好了。最关键的是保证填写的email地址有效,另外就是填上姓名,选择语言。帐户类型我选择的“不确定”,语言“中文(简体)”~ 提交注册申请之后,不久你就会收到用于确认并激活帐号的电子邮件,点击激活链接,就可以了激活你的Admob帐号了~
第二步就是设置你的Android应用程序信息,并获得Admob的插入代码。登录你的Admob帐号后,在主页的左上方(Logo上面)点击“Marketplace(手机广告市场)”,进入页面后,在“Sites&Apps(站点和应用程序)”标签下,点击“Add Site/App”。选择我们熟悉的图标——" Android App ” 。这时会出现需要你填写一个“详细信息”,随便填上一些信息。(不要太过在意现在填写的东西,因为这些以后都是可以修改的)。比如“Android Package URL” 我到现在都还没有填写,描述之类的,想写就写点吧。填好详细信息后,点击“继续”,就可以到AdMob Android SDK 的下载页面了。下载这个SDK(当然,这个很重要)。
[b] The AdMob Android SDK includes: [/b]
README: Get started with AdMob Android ads!
AdMob Jar file: Required for publishing ads. Follow the documentation in javadoc/index.html and drop the AdMob Jar file into your project.
Sample Projects: Examples of AdMob Android ads shown in the LunarLander application.
[b][/b]
第三步获取你的应用程序对应的Publisher ID。在下载页面点击"Go to Sites/Apps"就可以到你应用程序的管理界面了。这时你会发现在这个页面醒目的位置会有一个叫你填写详细信息的提示:
在我们发送任何有待收入之前,您需要填写技术联系详细信息和付款首选项。
我们暂时可以不用管它,因为钱是会存在我们的Admob的账户上的,等我们需要提现的时候,或者你想填的时候再填就可以了。在下面的列表中,选择你的应用程序并进入。这个界面就是你的应用程序广告的管理界面了,里面有比较多的功能,以后可以慢慢了解,现在我们只需要知道两个东西,一个是发布者 ID(Publisher ID),一个是你程序的状态。Publisher ID是一个15个字符的字符串,而你程序的状态现在应该还是不活动(Inactive)。我们下面要做的就是怎么让它变为Active。
第四步代码编写——在你的应用程序中插入Admob广告。经过上面的步骤,我们在网站上的设置就告一个段落了,现在我们终于要进入主题了,如何在自己的Android应用程序中插入Admob广告。如果你不健忘的话,一定还记得我们之前下载的那个AdMob Android SDK 。解压它,看看里面有些什么东西。这里面最重要的就是那个名为“admob-sdk-android.jar”的包啦,Admob将如何把广告加载到Android应用程序中的代码集成在这个包里,我们编写程序的时候就需要将这个包导入到我们的工程里面去。另外,解压出来的文件夹中还有一个名为“javadoc”的文件夹,打开它里面的index.html。它是关于Admob Android SDK的帮助文档,在Package 下的Setup下,有详细完整的在自己的应用程序中插入广告的方法介绍,在这里我就偷懒,引用一下~
Including the Jar
Add the Jar file included with the SDK to your Android project as an external library. In your project's root directory create a subdirectory libs (this will already be done for you if you used Android's activitycreator). Copy the AdMob Jar file into that directory. For Eclipse projects:
Go to the Properties of your project (right-click on your project from the Package Explorer tab and select Properties)
Select "Java Build Path" from left panel
Select "Libraries" tab from the main window
Click on "Add JARs..."
Select the JAR copied to the libs directory
Click "OK" to add the SDK to your android project
注意:需要首先在你工程的根目录下新建一个叫做“libs”的文件夹,并把之前所说的最重要的东西“admob-sdk-android.jar”复制到里面。
AndroidManifest.xml
Your AdMob publisher ID was given to you when creating your publisher account on www.admob.com before downloading this code. It is a 15-character code like a1496ced2842262. Just before the closing tag add a line to set your publisher ID:
Set any permissions not already included just before the closing tag:
Only the INTERNET permission is required. Setting ACCESS_COARSE_LOCATION (and/or ACCESS_FINE_LOCATION) allows narrowly geo-targeted ads be shown.
这里需要注意的是,中,我们只需要改的是"YOUR_ID_HERE"。这里需要你填上的ID就是我们之前在Admob网站我们的应用程序管理页面上看到的Publisher ID,而name="ADMOB_PUBLISHER_ID"是不应该改的。程序需要这个Key来查找对应的Value。
attrs.xml
The attrs.xml file specifies custom AdView attributes in XML layout files. If your application does not already have an /res/values/attrs.xml file then create one and copy-and-paste the following into it. If you do have that file then just add the declare-styleable element:
这个,没什么说的。
Placing an AdView in a Layout
AdView widgets can be put into any XML layout now. The first step is to reference attrs.xml in your layout element by adding an xmlns line that includes your package name specified in AndroidManifest.xml:
xmlns:yourapp=http://schemas.android.com/apk/res/yourpackage
For example a simple screen with only an ad on it would look like:
这里好像也没什么需要特别注意的,注意加上xmlns,另外知道这里可以设置一个keywords。
Test Mode
When you start integrating AdMob ads into your application it is recommended to use test mode. This always returns the same ad. Normal ad requests are not deterministic making it harder to be sure the ad view looks like you want (e.g. ad requests can timeout or may not fill).
Once the ad shows up as you expect be sure to turn test mode off to get real ads. Never put your application into the Android Market with test mode enabled.
Test mode can be enabled either by calling AdManager.setInTestMode(true) or by adding a "admobsdk:testing="true"" property to the ad in your XML layout (where "admobsdk" is the XML namespace for your application).
设置Test Mode这个很关键,千万别将处于Test Mode的程序发布出去了,那样可赚不了钱啊~!如果在AdView的属性中不加上admobsdk:testing="false",似乎程序也是不处于Test Mode的,不过最好还是加上吧~
第五步编译运行,并激活程序。编译运行你的程序,在模拟器上就可以看到效果啦~(当然你的模拟器需要能上网,关于怎么让模拟器上网呢?用路由的应该可以直接上,如果不是用路由,那么可能需要设置下,具体方法大家自己网上搜吧,具体忘了)。如果你的应用程序能显示出广告,那么恭喜你,你的应用程序很快就会在Admob上被激活了(需要一定的时间,我的好像花了一个小时不到)!
第六步在Admob网站上查看应用程序赚了多少钱~“手机广告市场”—>“报告”—>“站点和应用程序报告”。选择你的应用程序,然后点击页面最下面的“创建报告”~ OK,赚钱啦~
最后,我把我自己写的一个例子工程上传上来,大家可以下载来参考下。另外,我的工程将广告作为移动的,并且改变了它默认的宽度和背景,希望对如何在应用程序中摆放广告,起到一个抛砖引玉的作用。效果图如下(哈哈,在模拟器跑的~):
[img]http://dl.iteye.com/upload/attachment/262857/5f9e2978-8191-3b74-83af-7abfb86f7ce6.bmp" alt="[/img]
[align=left;]转至:http://www.getideas.cn/?p=32 [/align]