|
感谢大家支持,请关注我的博客大陆刀客
前几天有私事,耽搁了几天,所以源码没有按计划发布.今天一大早就起来发帖。今晚,我将把平台的所有源码发布到Google code上。希望能给大家带来一定帮助。相关代码的详细解析,我将会陆续发帖。
言归正传,今天和大家讨论一下如何加载sd中的jar包。在我刚研究这个问题时,许多前辈给我的回答是“不能加载sd中的jar包”。但随着我对api的深度dig,终于挖掘出了加载sd中jar包的方法。说起来,哈哈,很简单的,使用DexClassLoader.该类是这样描述的:
Class OverviewProvides a simple [url=]ClassLoader[/url] implementation that operates on a list of jar/apk files with classes.dex entries. The directory that holds the optimized form of the files is specified explicitly. This can be used to execute code not installed as part of an application. The best place to put the optimized DEX files is in app-specific storage, so that removal of the app will automatically remove the optimized DEX files. If other storage is used (e.g. /sdcard), the app may not have an opportunity to remove them.
从描述可以看到:DexClassLoader是用来加载安装程序之外的代码。android加载的jar包是经过特殊处理的,里面要含有class.dex文件。推荐的位置是应用的专属目录(一般通过getCasheDir获得),这样可以在删除应用时删除外部代码。
下面我们就依据这样的思路详解android对战平台是如何加载地图文件的。
package org.engine;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import org.config.ConfigConst;
import org.core.MsgConst.ConstClient;
import org.net.Request;
import org.views.ListInterface;
import org.views.ListObject;
import org.views.ViewManager;
import android.graphics.Color;
import android.os.Environment;
import android.view.KeyEvent;
/**
* 地图列表类,登录成功后进入地图列表
**/
class EngineLoader implements StateInterface {
private static final String TAG = "EngineLoader";
protected static final int OFFSET_X=0;
protected static final int OFFSET_Y=0;
protected static final int RECT_WIDTH=Manager.getScreenWidth();
protected static final int RECT_HEIGHT=Manager.getScreenHeight();
protected static final int DEFAULT_LINE_NUM=1;
protected static final int DEFAULT_ROW_NUM=6;
private int _lineNum;
private int _rowNum;
private boolean _hasSD;// 是否加载sd
private int _screenWidth = Manager.getScreenWidth();
private int _screenHeight = Manager.getScreenHeight();
private ArrayList<ListObject> _appList = new ArrayList<ListObject>();
private StateLoader _loader;// 类加载器
private ListInterface _mapList;//地图列表
private MapManager _mapManager;//地图管理器
@Override
public void init() {
// TODO Auto-generated method stub
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
return;// 没有sd
}
_hasSD = true;
//创建地图列表
_lineNum=DEFAULT_LINE_NUM;
_rowNum=DEFAULT_ROW_NUM;
_mapList=ViewManager.makeList(OFFSET_X, OFFSET_Y, RECT_WIDTH, RECT_HEIGHT, ViewManager.LIST_DIRECTION_VERTICAL);
_mapList.setLayoutNum(_lineNum, _rowNum);
//解析地图
File file = new File(ConfigConst.ROOT_PATH);
if (!file.exists()) {
file.mkdirs();
Debug.warn(TAG, "createPath" + file.getAbsolutePath());
}
parseApp(findMap(ConfigConst.ROOT_PATH));
_mapManager=new MapManager(this);
soundUp();
sendRequestMap(_appList);
}
/**
* 发送请求地图 ID:1000
*
* @param idList
*/
private void sendRequestMap(ArrayList<ListObject> mapList) {
Request request = new Request(ConstClient.REQUEST_MAP);
int num = mapList.size();
request.writeShort(num);
for (int i = 0; i < num; i++) {
request.writeInt(((Map) mapList.get(i)).getVersion());
}
request.flushAndSend();
}
@Override
public void paint(Graphics g) {
// TODO Auto-generated method stub
g.clearScreen(Color.BLACK);
if (!_hasSD)// 没有加载sd
{
g.drawString("无法加载SD卡!", _screenWidth >> 1, _screenHeight >> 1,
Graphics.ANCHOR_CENTER, Color.RED, 20);
} else // 地图顺利加载
{
paintList(g);
}
}
/**
* 绘制应用列表
*
* @param g
*/
private void paintList(Graphics g) {
_mapList.paint(g);
}
@Override
public void processPointer() {
// TODO Auto-generated method stub
_mapList.processPointer();
}
@Override
public void processKey(int keyCode) {
// TODO Auto-generated method stub
if (keyCode == KeyEvent.KEYCODE_BACK) {
Debug.warn(TAG, "back is pressed...");
Manager.getInstance().destroyGame();
}
}
@Override
public void update() {
// TODO Auto-generated method stub
_mapList.update();
}
@Override
public void release() {
// TODO Auto-generated method stub
}
/**
* 进入地图
*
* @param app
*/
public void enterMap(Map app) {
//加载外部代码
_loader = new StateLoader(app.getFile().getAbsolutePath(),
app.getAppliactonPath(), null, Manager.getInstance()
.getContext().getClassLoader());
//设置状态加载器
Manager.getInstance().setStateLoader(_loader);
//设施地图路径,用于从地图目录加载资源
Manager.getInstance().setMapPath(app.getFile().getParent());
//发送进入地图消息
sendEnterMap(app.getMapId());
//切换游戏状态
Manager.getInstance().changeState((byte) 0, app.getEnterName(), false, true);
}
/**
* 进入地图
* @param mapId
*/
private void sendEnterMap(int mapId)
{
Debug.warn(TAG, "sendEnterMap....");
Request request = new Request(ConstClient.REQUEST_ENTER_MAP);
request.writeInt(mapId);
request.flushAndSend();
}
/**
* 解析应用包
*
* @param fileList
*/
private void parseApp(ArrayList<File> fileList) {
for (int i = fileList.size() - 1; i >= 0; i--) {
Map app = new Map(_mapList);
app.setEngineLoader(this);
//设置应用对应的地图文件
app.setFile(fileList.get(i));
addMap(app);
}
}
//搜索地图资源
private ArrayList<File> findMap(String path) {
FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
// TODO Auto-generated method stub
if (filename.endsWith(ConfigConst.MAP_SUFFIX))
return true;
return false;
}
};
ArrayList<File> target = new ArrayList<File>();
File parent = new File(path);
File[] fileList = parent.listFiles();
Debug.warn(TAG, "directory num is"+fileList.length);
for (int i = fileList.length - 1; i >= 0; i--) {
File temp = fileList;
if (!temp.isDirectory())
continue;
File[] list = temp.listFiles(filter);
Debug.warn(TAG, "map num is"+list.length);
for (int m = list.length - 1; m >= 0; m--)
{
Debug.warn(TAG, "addd");
target.add(list[m]);
}
}
return target;
}
/**
* 添加地图
* @param map
*/
protected void addMap(Map map) {
_appList.add(map);
_mapList.addItem(map);
}
/**
* 获得地图
* @return
*/
protected ArrayList<ListObject> getMaps() {
return _appList;
}
/**
* 获得地图管理器
* @return
*/
protected MapManager getMapManager() {
return _mapManager;
}
protected void soundUp()
{
LongSoundInterface longsound=Manager.getInstance().getLongSoundPlayer();
longsound.loadSound(R.raw.main);
longsound.setLoop(true);
longsound.playSound();
}
/**
* 获得地图列表
* @return
*/
protected ListInterface getMapListView() {
return _mapList;
}
}
复制代码StateLoader:状态加载器,哈哈,这个是从源代码中拷贝的DexClassLoader源码,为了程序员那点小小的虚荣心,可以直接用DexClassLoader替代。
package org.engine;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.zip.ZipFile;
import dalvik.system.DexFile;
/***
* 状态加载
* @author Administrator
*
*/
class StateLoader extends ClassLoader {
private static final boolean VERBOSE_DEBUG = true;
private final String mRawDexPath;
private final String mRawLibPath;
private final String mDexOutputPath;
private boolean mInitialized;
private File[] mFiles;
private ZipFile[] mZips;
private DexFile[] mDexs;
private String[] mLibPaths;
public StateLoader(String dexPath, String dexOutputDir, String libPath,
ClassLoader parent) {
super(parent);
if (dexPath == null || dexOutputDir == null)
throw new NullPointerException();
mRawDexPath = dexPath;
mDexOutputPath = dexOutputDir;
mRawLibPath = libPath;
}
private synchronized void ensureInit() {
if (mInitialized) {
return;
}
String[] dexPathList;
mInitialized = true;
dexPathList = mRawDexPath.split(":");
int length = dexPathList.length;
mFiles = new File[length];
mZips = new ZipFile[length];
mDexs = new DexFile[length];
for (int i = 0; i < length; i++) {
File pathFile = new File(dexPathList);
mFiles = pathFile;
if (pathFile.isFile()) {
try {
mZips = new ZipFile(pathFile);
} catch (IOException ioex) {
System.out.println("Failed opening '" + pathFile
+ "': " + ioex);
}
try {
String outputName =
generateOutputName(dexPathList, mDexOutputPath);
mDexs = DexFile.loadDex(dexPathList, outputName, 0);
} catch (IOException ioex) {
System.out.println("Failed loadDex '" + pathFile
+ "': " + ioex);
}
} else {
if (VERBOSE_DEBUG)
System.out.println("Not found: " + pathFile.getPath());
}
}
String pathList = System.getProperty("java.library.path", ".");
String pathSep = System.getProperty("path.separator", ":");
String fileSep = System.getProperty("file.separator", "/");
if (mRawLibPath != null) {
if (pathList.length() > 0) {
pathList += pathSep + mRawLibPath;
}
else {
pathList = mRawLibPath;
}
}
mLibPaths = pathList.split(pathSep);
length = mLibPaths.length;
for (int i = 0; i < length; i++) {
if (!mLibPaths.endsWith(fileSep))
mLibPaths += fileSep;
if (VERBOSE_DEBUG)
System.out.println("Native lib path " +i+ ": " + mLibPaths);
}
}
private static String generateOutputName(String sourcePathName,
String outputDir) {
StringBuilder newStr = new StringBuilder(80);
newStr.append(outputDir);
if (!outputDir.endsWith("/"))
newStr.append("/");
String sourceFileName;
int lastSlash = sourcePathName.lastIndexOf("/");
if (lastSlash < 0)
sourceFileName = sourcePathName;
else
sourceFileName = sourcePathName.substring(lastSlash+1);
int lastDot = sourceFileName.lastIndexOf(".");
if (lastDot < 0)
newStr.append(sourceFileName);
else
newStr.append(sourceFileName, 0, lastDot);
newStr.append(".dex");
if (VERBOSE_DEBUG)
System.out.println("Output file will be " + newStr.toString());
return newStr.toString();
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
ensureInit();
if (VERBOSE_DEBUG)
System.out.println("DexClassLoader " + this
+ ": findClass '" + name + "'");
byte[] data = null;
int length = mFiles.length;
for (int i = 0; i < length; i++) {
if (VERBOSE_DEBUG)
System.out.println(" Now searching: " + mFiles.getPath());
if (mDexs != null) {
String slashName = name.replace('.', '/');
Class clazz = mDexs.loadClass(slashName, this);
if (clazz != null) {
if (VERBOSE_DEBUG)
System.out.println(" found");
return clazz;
}
}
}
throw new ClassNotFoundException(name + " in loader " + this);
}
@Override
protected URL findResource(String name) {
ensureInit();
int length = mFiles.length;
for (int i = 0; i < length; i++) {
File pathFile = mFiles;
ZipFile zip = mZips;
if (zip.getEntry(name) != null) {
if (VERBOSE_DEBUG)
System.out.println(" found " + name + " in " + pathFile);
try {
return new URL("jar:" + pathFile.toURL() + "!/" + name);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
if (VERBOSE_DEBUG)
System.out.println(" resource " + name + " not found");
return null;
}
@Override
protected String findLibrary(String libname) {
ensureInit();
String fileName = System.mapLibraryName(libname);
for (int i = 0; i < mLibPaths.length; i++) {
String pathName = mLibPaths + fileName;
File test = new File(pathName);
if (test.exists()) {
if (VERBOSE_DEBUG)
System.out.println(" found " + libname);
return pathName;
}
}
if (VERBOSE_DEBUG)
System.out.println(" library " + libname + " not found");
return null;
}
@Override
protected Package getPackage(String name) {
if (name != null && !"".equals(name)) {
synchronized(this) {
Package pack = super.getPackage(name);
if (pack == null) {
pack = definePackage(name, "Unknown", "0.0", "Unknown",
"Unknown", "0.0", "Unknown", null);
}
return pack;
}
}
return null;
}
}
复制代码 |
|