📄 enginemanager.java
字号:
package engine.kernel;
import javax.microedition.lcdui.*;
import java.util.*;
import java.io.*;
/**
* 引擎管理类<br>
* 引擎运行期间的主要数据、对象实例、基础的公用的方法全在这里定义。
* @author 贾永明
* @version 2.8.0
* @since HuoHouStudioEngine1.0
*/
public final class EngineManager{
/**
* constructor。<br>不可以产生EngineManager的实例。
*/
private EngineManager(){
}
/**
* startApp调用,用于load()中。
*/
public final static byte STARTAPP_CALLER = 0;
/**
* pauseApp调用,用于save()中。
*/
public final static byte PAUSEAPP_CALLER = 1;
/**
* destroyApp调用,用于save()中。
*/
public final static byte DESTROYAPP_CALLER = 2;
/**
* hideNotify调用,用于save()中。
*/
public final static byte HIDENOTIFY_CALLER = 3;
/**
* showNotify调用,用于load()中。
*/
public final static byte SHOWNOTIFY_CALLER = 4;
/**
* switchScreen中curScrOperation仅仅保留当前屏幕。
*/
public final static byte ONLY_SAVE_CURRENT = 0;
/**
* switchScreen中curScrOperation保留当前屏幕并用于后台运行。
*/
public final static byte BACKGROUND_RUN = 1;
/**
* switchScreen中curScrOperation不做任何操作。
*/
public final static byte NONE_OPERATE = -1;
/**
* switchScreen中fps维持不变。
*/
public final static byte KEEP_FPS = 0;
/**
* 引擎当前midlet实例。
*/
static EngineMIDlet engineMidlet;
/**
* 引擎主线程及低级屏幕实例。
*/
static EngineThread engineThread;
/**
* 引擎的屏幕接口实例。
*/
static Object scrListener;
/**
* 保留的旧屏幕,使用本引擎的开发人员通过{@link engine.kernel.EngineMIDlet#EngineMIDlet(boolean, int, int, boolean, int, int, int, String, int, int, boolean) EngineMIDlet(boolean continueAfterException, int scrWidthAdjust, int scrHeightAdjust, boolean isDoubleBuffered, int fps, int reservedScreenNormalCapacity, int backgroundCapacity, String keyMapURL, int maxCombineKey, int tbkh, boolean appendCommandSoftX)}的参数reservedScreenNormalCapacity调整程序运行期间保留的旧屏幕的容量。
*/
static Vector scrList;
/**
* 后台运行的屏幕的ID,后台根据这一参数按照保留的先后顺序运行对应的屏幕程序。
*/
static StringBuffer backgroundID;
/**
* 程序运行暂停标志量,true:表示程序处于暂停状态,false:表示程序在运行状态。
*/
static boolean isPause;
/**
* 程序运行启动标志量,true:表示程序在运行状态,false:表示程序处于结束状态。
*/
static boolean hasStarted;
/**
* 异常信息的内容。
*/
static String debugInfo;
/**
* 通知引擎进入关闭状态的方法。<br>该方法调用之后引擎就会进入关闭状态,进而退出整个应用程序。<br>
*/
public final static void quitApp(){
hasStarted = false;
}
/**
* 屏幕切换的方法。<br>本引擎能够实现保留旧屏幕实例,并且可以通过保留的旧屏幕的索引来控制后台运行的屏幕的索引。注意,屏幕实例用到的数据需要使用本引擎的开发人员自己保留。
* @param <b>target</b> 即将进入的新屏幕,必须是Screen、{@link engine.kernel.EventListener EventListener}或者{@link engine.kernel.DrawListener DrawListener}的实例。
* 使用注意事项:<br>
* ① 如果第一个target屏幕实例,即通过类{@link engine.kernel.EngineMIDlet EngineMIDlet}的扩展子类的方法{@link engine.kernel.EngineMIDlet#entrance(int, int) entrance(int scrWidth,int scrHeight)}产生的启动实例,是Alert实例,那么程序在显示完毕这个Alert之后,会处于假死状态。<br>
* ② 如果参数target是null或者既不是高级控件Screen的实例也不是接口{@link engine.kernel.EventListener EventListener}的实例或者{@link engine.kernel.DrawListener DrawListener}的实例,屏幕将得不到任何响应,程序处于假死状态。<br>
* ③ 如果进入的新屏幕是Alert,即参数target是Alert的实例,本引擎可以显示,但是对于其是否属于{@link engine.kernel.EventListener EventListener}的实例或{@link engine.kernel.DrawListener DrawListener}的实例的事实将被忽略。<br>
* @param <b>curScrOperation</b> 对当前屏幕的操作,0:仅仅保留当前屏幕,1:保留当前屏幕并将其放于后台运行,-1:不作任何操作。默认情况下除了0和1之外的数据都是不作任何操作。<br>
* 使用注意事项:<br>
* ① 如果后台运行的屏幕的空间达到了设定的空间,仍要求添加后台运行的屏幕的话,会抛出异常<br>IllegalArgumentException: the background is full<br>
* ② 本引擎保留的只是屏幕实例本身,至于屏幕实例用到的数据,除非是实例本身所有的,否则本引擎不作任何处理,即需要使用本引擎的开发人员自己保留或者销毁。如果当保留旧屏幕的空间达到了设定的空间,仍要求保留旧屏幕的话,会抛出异常<br>IllegalArgumentException: the stack is full
* ③ 当参数curScrOperation数值为1的时候,即保留当前屏幕并将其放于后台运行,如果当前保留的旧屏幕既不属于{@link engine.kernel.EventListener EventListener}的实例,又不属于{@link engine.kernel.DrawListener DrawListener}的实例,则会在运行期间抛出异常<br>ClassCastException
* @param <b>fps</b> 引擎的刷新频率,应该是正数。如果是负数或者0,会被认为是刷新率不变。
*/
public static void switchScreen(Object target, int curScrOperation, int fps){
if(curScrOperation == ONLY_SAVE_CURRENT || curScrOperation == BACKGROUND_RUN){//保留旧屏幕到屏幕队列的尾端
if(scrList.size() == scrList.capacity()){
throw new IllegalArgumentException("the stack is full");
}
if(scrListener == null){
scrList.addElement(Display.getDisplay(engineMidlet).getCurrent());
}else{
scrList.addElement(scrListener);
}
if(curScrOperation == BACKGROUND_RUN && !(scrList.isEmpty())){
if(backgroundID.length() == backgroundID.capacity()){
throw new IllegalArgumentException("the background is full");
}else{
backgroundID.append((char)(scrList.size() - 1));
}
}
}
//清空当前屏幕的Screen Listener实例
if(!(target instanceof Alert)){
scrListener = null;
}
//检查修改刷新率
if(fps > KEEP_FPS){
engineThread.mspf = 1000/fps;
}
//设置当前屏幕
Display.getDisplay(engineMidlet).setCurrent((Displayable)(target instanceof Screen ? target : (engineThread.isShown() ? null : engineThread)));//设置新的当前屏幕
//转换
if((target instanceof EventListener || target instanceof DrawListener) && !(target instanceof Alert)){
scrListener = target;
}
System.gc();
EngineKey.clrAllKeyState();
}
/**
* 从后台运行中清除指定的后台运行屏幕。
* @param <b>index</b> 欲清除的后台运行的屏幕的索引,该索引指的是在保留的屏幕队列中的索引,如果该索引不存在于保留的屏幕队列的索引范围则会被忽略。
*/
public final static void clearBackground(int index){
for(int j = backgroundID.length() - 1; j >= 0; j--){
if((int)(backgroundID.charAt(j)) == index){
backgroundID.deleteCharAt(j);
return;
}
}
}
/**
* 获取指定的被保留屏幕。
* @param <b>release</b> 是否将最后保留的屏幕的存储空间到当前欲获取的保留屏幕的存储空间释放。<br>true:释放,false:保留。
* @param <b>reservedScreenindex</b> 欲获取的保留屏幕的索引,如果索引没有在保留屏幕的数量范围内,会抛出异常<br>ArrayIndexOutOfBoundsException
* @return 指定的被保留屏幕。
*/
public final static Object getScreenAt(int index, boolean release){
Object reserved = scrList.elementAt(index);
if(release){
for(int i = scrList.size() - 1; i >= index; i--){
scrList.removeElementAt(i);
//从后台删除
clearBackground(i);
}
}
return reserved;
}
/**
* 获取上一级屏幕。<br>如果没有保留的屏幕,会抛出异常<br>NoSuchElementException
* @param <b>release</b> 是否将保留屏幕的空间释放。<br>true:释放,false:保留。
* @return 上一级屏幕。
*/
public final static Object getPreScreen(boolean release){
return getScreenAt(scrList.size() - 1, release);
}
/**
* 获取文件资源。
* @param <b>fileUrl</b> 文件所在路径。
* @return 返回由文件资源数据形成的byte数组。
*/
public final static byte[] getByteArrayFromFile(String fileUrl){
byte[] byteArrayData = null;
if(fileUrl != null){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
InputStream is = engineMidlet.getClass().getResourceAsStream(fileUrl);
DataInputStream dis = null;
try{
if(is != null){
dis = new DataInputStream(is);
int ch = 0;
while((ch = dis.read()) != -1){
dos.writeByte((byte)ch);
}
byteArrayData = baos.toByteArray();
}
}catch(Exception e){
debugEngine(e, null);
}finally{
if(dis != null){
try{
dis.close();
}catch(Exception e){
debugEngine(e, null);
}
dis = null;
}
if(dos != null){
try{
dos.close();
}catch(Exception e){
debugEngine(e, null);
}
dos = null;
}
if(baos != null){
try{
baos.close();
}catch(Exception e){
debugEngine(e, null);
}
baos = null;
}
}
}
return byteArrayData;
}
/**
* 处理调试信息的方法。
* @param <b>info</b> 调试信息。
* @param <b>additional</b> 调试信息的附加信息。
*/
public final static void debugEngine(Object info, String additional){
debugInfo = (additional == null ? "" : additional) + (info != null ? info.toString() : info);
if(info instanceof Throwable){
((Throwable)info).printStackTrace();
}else{
System.err.println(debugInfo);
}
}
/**
* 检测某一系统属性是否与给定的值相同。
* @param <b>property</b> 与检测的系统属性。
* @param <b>value</b> 给定的比较值。<br><br>
* 给出几个常用属性的数据:<br>
* <TABLE BORDER="1" WIDTH="80%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
* <TR BGCOLOR="#9988cc">
* <TD WIDTH="20%"><FONT SIZE="+1"><B>属性</B></FONT></TD>
* <TD WIDTH="8%"><FONT SIZE="+1"><B>默认值</B></FONT></TD>
* <TD WIDTH="40%"><FONT SIZE="+1"><B>参考值</B></FONT></TD>
* <TR BGCOLOR="#CCCCFF">
* <TD WIDTH="20%">microedition.platform</TD><TD WIDTH="8%">null</TD><TD WIDTH="40%">j2me、nokia3300</TD>
* </TR>
* <TR BGCOLOR="#CCCCFF">
* <TD WIDTH="20%">microedition.configuration</TD><TD WIDTH="8%">CLDC-1.0</TD><TD WIDTH="40%">CLDC-1.0、CLDC-1.1</TD>
* </TR>
* <TR BGCOLOR="#CCCCFF">
* <TD WIDTH="20%">microedition.profiles</TD><TD WIDTH="8%">null</TD><TD WIDTH="40%">MIDP-1.0、MIDP-2.0<FONT SIZE="-1">(如果是多个简表中间用空格分隔)</FONT></TD>
* </TR>
* <TR BGCOLOR="#CCCCFF">
* <TD WIDTH="20%">microedition.encoding</TD><TD WIDTH="8%">ISO8859_1</TD><TD WIDTH="40%">GBK、Unicode</TD>
* </TR>
* <TR BGCOLOR="#CCCCFF">
* <TD WIDTH="20%">microedition.locale</TD><TD WIDTH="8%">null</TD><TD WIDTH="40%">zh-CN、en-US</TD>
* </TR>
* </TABLE>
* @return 是否相同,true 代表相同,false 代表不相同。
*/
public final static boolean checkProperty(String property, String value){
String systemValue = System.getProperty(property);
return ((systemValue == null && value == null) || (systemValue != null && value != null && systemValue.toUpperCase().equals(value.toUpperCase())));
}
/**
* requests that the device handle (for example, display or install) the indicated url.<br>
* 请参考midp2.0文档的相关方法。需要说明的是为了适应midp1.0的需要,该方法内部会检测midp的版本,如果是midp1.0的将会抛出异常<br>Error: MIDP-1.0<br>
* 如果不是midp1.0的版本,当MIDlet本身的platformRequest方法返回true的时候,即请求某一url需要midlet处于关闭的状态的时候,该方法会通知引擎进入关闭状态,进而关闭运行的程序。
* @param <b>url</b> the url for the platform to load. an empty string (not null) cancels any pending requests.
* @throws Exception 一切可能产生的异常。
*/
public final static void platformRequest(String url) throws Exception{
if(checkProperty("microedition.profiles", "MIDP-1.0")){//检测当前简表的版本
throw new Error("MIDP-1.0");
}
if(engineMidlet.platformRequest(url)){
hasStarted = false;
}
}
/**
* get the status of the specified permission.<br>
* 请参考midp2.0文档的相关方法。需要说明的是为了适应midp1.0的需要,该方法内部会检测midp的版本,如果是midp1.0的将不会有任何权限检测,并且会返回0,既不可以使用,如果是midp2.0的版本,那么就会根据实际情况返回权限的结果。
* @param <b>permission</b> to check if denied, allowed, or unknown.
* @return 0 if the permission is denied; 1 if the permission is allowed; -1 if the status is unknown.
*/
public final static int checkPermission(String permission){
if(checkProperty("microedition.profiles", "MIDP-1.0")){//检测当前简表的版本
return 0;
}else{
return engineMidlet.checkPermission(permission);
}
}
/**
* 获得简表中定义的数据的方法。<br>如果没有匹配的或者keyWord本身为空则会抛出异常<br>IllegalArgumentException: miss the key of "<EM>keyWord</EM>" in jad<br>keyWord是简表中的关键字的具体信息。
* @param <b>keyWord</b> 定义数据在简表中的关键字。
* @return 返回简表中与关键字匹配的定义数据。
*/
public final static String getAppProperty(String keyWord){
String s = engineMidlet.getAppProperty(keyWord);
if(s == null){
throw new IllegalArgumentException("miss the key of \"" + keyWord + "\" in jad");
}
return s;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -