站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2ME 专题如何让JAR文件成为试玩版?

如何让JAR文件成为试玩版?

摘要: 如何让JAR文件成为试玩版?


公司最近准备做收费游戏,,,现在遇到棘手的问题,,,如何将没有源代码的JAR文件做成试玩版,,,在用户试用一段时间后提示试用已到期,,,?求解决方案,,,


1、每次运行软件时联网验证

2、RMS,但是会有被破解的可能。。


很多是第三方的JAR软件,请问如何嵌入每次运行软件时联网验证的代码?是否可以通过J2SE里面的java.util.jar包直接修改JAR文件?但如何修改又是一个问题,,,


做成DRM文件


但是支持DRM的机型就更加有限了,,,我现在的想法是通过JarOutputStream和JarInputStream直接修改JAR文件,,,但是出来的Manifest文件内容始终为空,,,诸位大虾帮忙看一下,,,

//这些类在java的工具包中专门用于处理压缩包(当然也包括zip文件)代码如下:
byte[] buffer = new byte[2048];
int read = 0;
//读取jar文件流,这一步是读取需要更新的jar包.
JarInputStream zin = new JarInputStream(new FileInputStream("D://1583.jar"));
JarEntry entry = null;
//
Manifest manifest = zin.getManifest();
if (manifest == null) {
//通过下面的打印语句可以知道manifest对象不为空
System.out.println("manifest == null");
manifest = new Manifest();
}
//用JarOutputStream 建立输出文件
FileOutputStream fout = new FileOutputStream("D://1583_Copy.jar");
JarOutputStream zout = new JarOutputStream(fout , manifest);
//从原jar包中读取文件
while ((entry = zin.getNextJarEntry()) != null) {
zout.putNextEntry(entry);
while ((read = zin.read(buffer)) != -1) {
zout.write(buffer, 0, read);
}
zout.closeEntry();
}
//修改过后的class文件
File f = new File("D://HelloWorld.class");
FileInputStream fs = new FileInputStream(f);
JarEntry jare = new JarEntry("HelloWorld.class");
zout.putNextEntry(jare);
//写入输出流
while ((read = fs.read(buffer)) != -1) {
zout.write(buffer, 0, read);
}
//关闭流zout.closeEntry();
zout.close();
fs.close();
zin.close();

还有如何修改一个Manifest文件???Manifest对象似乎没有提供相关方法


还是做成RMS验证吧。。。


肯定是需要RMS验证的,,,现在的问题是如何把这段代码加进去,,,因为很多JAR不是我们自己开发我们是没有源代码的,,,


路过,友情up!


我要关注下,难道没有源代码的情况下还可以做RMS验证的吗?另:为什么不把源代码搞来呢?



没有源代码也可以增加新功能么?
严重关注.........


源代码如下

/**
*

Jar文件生成器类
*
*

描 述:这是JarCreator工程的Jar文件生成器类,将完成以下几个任务:
*

1、重新打包Jar文件;
*
* @version 1.00, 08/21/06
* @author 窦海宁, chong0660@sina.com
*/
public class JarCreator {

/**
*

创建Jar文件
*
* @param fromJar 源Jar文件
* @param toJar 目标Jar文件
* @param insertClassNames 插入类名称数组
* @param insertClassPaths 插入类路径数组
* @param mainClassName 带完整包名的主类名称
*
* @return Jar文件创建状态
*/
public int create(String fromJar , String toJar , String[] insertClassNames , String[] insertClassPaths , String mainClassName) {

Manifest manifest = null;
JarInputStream jarIn = null;
JarOutputStream jarOut = null;

//创建Jar文件输入流并获取Manifest文件信息
try {
jarIn = new JarInputStream(new FileInputStream(fromJar));
manifest = jarIn.getManifest();

if (manifest == null) {
manifest = new Manifest();
}

//修改Manifest文件
Attributes attribute = manifest.getMainAttributes();
String midletName = null;
StringBuffer midletNameSb = null;
attribute.putValue("Manifest-Version" , "1.0");
midletName = attribute.getValue("MIDlet-1");

if (midletName != null) {
midletNameSb = new StringBuffer();
midletNameSb.append(midletName.substring(0 , midletName.lastIndexOf(",") + 1));
midletNameSb.append(mainClassName);
midletName = midletName.substring(midletName.lastIndexOf(",") + 1);
attribute.putValue("Joyes-Start" , midletName);
}

//用Manifest对象创建新的Jar文件
jarOut = new JarOutputStream(new FileOutputStream(toJar) , manifest);

//循环插入指定文件
insertJar(jarOut , insertClassNames , insertClassPaths);

//循环读取源Jar文件数据至目标Jar文件中
copyJar(jarIn , jarOut);

//清空缓冲区
jarOut.flush();

//返回创建成功标识
return 0;

} catch (FileNotFoundException ex) {
//返回IO错误标识
return -1;
} catch (IOException ex) {
//返回IO错误标识
return -2;
} finally {
try {
if (jarOut != null) {
jarOut.close();
}
}
catch (IOException ex) {
ex.printStackTrace();
}

try {
if (jarIn != null) {
jarIn.close();
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}

/**
*

复制Jar文件
*
* @param fromJar 源Jar文件
* @param toJar 目标Jar文件
*
* @throws IOException
*/
private void copyJar(JarInputStream jarIn , JarOutputStream jarOut) throws IOException {
JarEntry entry = null;
while ((entry = jarIn.getNextJarEntry()) != null) {
jarOut.putNextEntry(entry);
int read = 0;
byte[] bytes = new byte[4096];
while ((read = jarIn.read(bytes)) != -1) {
jarOut.write(bytes , 0 , read);
}
jarOut.closeEntry();
}
}

/**
*

插入指定文件至Jar文件中
*
* @param jarOut 源Jar文件输出流
* @param insertClassNames 插入类名称数组
* @param insertClassPaths 插入类路径数组
*
* @throws FileNotFoundException , IOException
*/
private void insertJar(JarOutputStream jarOut , String[] insertClassNames , String[] insertClassPaths) throws FileNotFoundException , IOException {
for (int i = 0 ; i < insertClassNames.length ; i++) {
File file = new File(insertClassPaths[i]);
FileInputStream fs = new FileInputStream(file);
JarEntry jarEntry = new JarEntry(insertClassNames[i]);
jarOut.putNextEntry(jarEntry);
//写入输出流
int read = 0;
byte[] bytes = new byte[4096];
while ((read = fs.read(bytes)) != -1) {
jarOut.write(bytes , 0 , read);
}
jarOut.closeEntry();
}
}
}



此代码已能实现将CLASS文件嵌入JAR文件的功能,,,目前的难题是如何在一个MIDlet中调用另一个MIDlet,,,
我的想法是写一个使用代理模式的扩展CLASS对其功能进行扩展,,,但是J2ME中没有反射机制,,,我如何来实现这个功能???startApp等与MIDlet生命周期有关的方法都是protected级别的,,,如何应用代理模式,,,

我觉得就差一点点就走通了,,,请各位大虾指点,,,



就像百宝箱的二次打包一样,翻编译后在startApp最开始+上联网鉴权操作就成了


一个J2ME程序是不能有两个MIDlet的,可以尝试看看增加一个类,在主线程执行的最前面进行RMS验证;同时严重关注结果


to foxyou():

但是我们有几万个游戏,,,如果每个都这么手动操作是否有点不太现实,,,

to yanhan0615(炮炮):

我前天试过用上面那段程序往JAR文件里加入第二个Midlet,,,并修改MANIFEST文件中的启动入口,,,结果是可以运行,,,




经过试验,,,确实可以在一个Midlet中调用另一个Midlet,,,但是需要使用上面那段程序将编译好的class文件插入到原来的JAR包中,,,目前只能通过继承方式,,,而且只能硬编码,,,因为J2ME没有反射,,,请问如何能够解决这个问题???


经过试验,,,确实可以在一个Midlet中调用另一个Midlet --

确实长了回见识,汗....请令狐兄把代码详细介绍下

其实用foxyou()的办法也可以,把代码写好,反编 -> 加代码 -> 编译 -> 打包都使用程序或者批处理来实现



公司决定改变方案,,,炮炮兄要的在一个Midlet中调用另一个Midlet的代码周一回公司给你贴,,,我们现在决定向CP提供一套API,,,这样相对安全些,,,现在的思路是做一个基类的MIDlet,,,然后由CP来继承我们的MIDlet,,,


另请教,,,J2ME程序的命令行编译怎么做???在网上找了很多资料,,,并且试了多次均未成功,,,在下以前一直是做J2EE的,,,刚开始接触J2ME,,,公司就给了个这么重的任务,,,以后还请各位多多指教


J2ME程序的命令行编译我也不知道,我都是用jbuilder开发的


用任意压缩软件解压缩jar
用JAD反编译某midlet的class(原地址我忘记了,但cavaj等很多反编译软件都用这个做核心)
在midlet的构造函数里或者startApp里添加你的代码,控制流程。
编译打包。


这些步骤都可以自动化。


今天忙了点,,,差点把这忘了,,,晕死,,,

TO 泡泡:

package com.mot.j2me.midlets.jbombman;

import javax.microedition.lcdui.Display;
import javax.microedition.midlet.MIDletStateChangeException;

import util.game.LockGameMIDlet;

public class jBombMan extends LockGameMIDlet {

private Display oDisplay = null;
private BoardView oBoardView = null;
private Board oBoard = null;
private Player oPlayer = null;
private Enemy oEnemy = null;

public jBombMan() {
oDisplay = Display.getDisplay(this);

oBoard = new Board(11 , 11);
oBoardView = new BoardView(oBoard);
oPlayer = new Player(oBoard , oBoardView);
oEnemy = new Enemy(oBoard , oBoardView, oPlayer, 7);

oBoardView.setPlayer(oPlayer); // Keyin should call Player
oBoardView.setEnemy(oEnemy); // oEnemy.init()
oPlayer.setEnemy(oEnemy);
}

protected void pauseApp() {
oEnemy.stopThread();
}

protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
}

public void startGame() throws MIDletStateChangeException {
oDisplay.setCurrent(oBoardView);
oEnemy = new Enemy(oBoard, oBoardView, oPlayer, 7);
oEnemy.start();
}

public void quitGame() throws MIDletStateChangeException {
oEnemy.stopThread(); //结束游戏主线程
this.destroyApp(true); //释放游戏资源
oDisplay.setCurrent(lockUI); //设置游戏加解锁对象为当前显示对象
}

}

LockGameMIDlet里面实现了游戏加解密方法,


LockGameMIDlet 这个类能不能贴出来?


不好意思,,,那个涉及到公司机密了,,,这个项目现还在研发阶段,,,不过几个主要难点或解决或找到了别的替代方案,,,LockGameMIDlet类主要是用于控制游戏注册试玩等逻辑,,,主要是通过调用子类的startGame、quitGame等方法实现所控制游戏的启动与停止,,,然后处理自己的逻辑


连加了一周的班外加几乎两个通宵,,,累死我了,,,



qiang


楼主加油


↑返回目录
前一篇: 谁知道benq s88手机的键值对应吗?
后一篇: 关于Display.setCurrent的问题