Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 1957|回复: 0

大陆刀客===android对战平台之加载SD中的jar包 - Android学习

[复制链接]

该用户从未签到

发表于 2011-10-26 19:01:49 | 显示全部楼层 |阅读模式
感谢大家支持,请关注我的博客大陆刀客
前几天有私事,耽搁了几天,所以源码没有按计划发布.今天一大早就起来发帖。今晚,我将把平台的所有源码发布到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;

    }

}
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-11 19:54 , Processed in 0.300032 second(s), 36 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表