crosswalk之"瘦身"秘籍

上篇文章已经大概介绍了crosswalk的用法,现在就来看看一个嵌套了crosswalk的app究竟有怎么的构造。

在/data/data/myapp/目录下发现多了一个app_xwalkcoew目录,在里面保存了缓存文件已经runtime,说明它不能与webview共用缓存。
这里写图片描述

由图片可以知道,本来在raw目录下的8M多的libxwalkcore.so.armeabi_v7a已经被解压成了21M的文件。一个大概12m的包runtime就占了8M多,我突然觉得,在不使用share mode的情况下能不能把crosswalk”变小”,给用户一种很好的感觉呢?答案是可以的。
那就是把libxwalkcore.so提取出来,改为打开app的时候在后台下载,这样看起来安装包就感觉变小了,但是下载的这段时间是不能使用Crosswalk的,这时就只能使用webview,下载完成后再转换成crosswalk


首先定义一个抽象类实现crosswalk和webview的集成,通过子类继承它来实现


/**
* 实现crosswalk和webview的集成,游戏界面可以继承该类可直接调用xwalkview加载网页
*@author chenjiantian1992@gmail.com
*@time 2015-7-31
 */
public abstract class CrosswalkActivity extends Activity{

private CrosswalkUtil crosswalkUtil;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        crosswalkUtil = new CrosswalkUtil(this);
        //初始化crosswalk
        initCrossWalkEnv();
        //配置加载crosswalk还是webview
        configEnv();
    }

    private void configEnv() {
        //判断app中是否有crosswalk runtime 即libxwalkcore.so
        if(crosswalkUtil.haveCwModel()){
            initCrosswalk();
        }else{
            initSysWebView();
            loadCrosswalk();
        }
    }

    /**
     * 初始化crosswalk
     */
    public abstract void initCrosswalk();

    /**
     * 初始化系统webview
     */
    public abstract void initSysWebView();

    /**
     * 加载配置crosswalk环境
     */
    public abstract void loadCrosswalk();

    private void initCrossWalkEnv() {

        //如果有crosswalk模块,初始化crosswalk环境
        if(crosswalkUtil.haveCwModel()){
            onXWalkCoreReady();
        }

    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        //不为空,可以初始化crosswalk环境,必须调用该方法
        if(mActivityDelegate != null){
            mActivityDelegate.onResume()
        }
    }
    /**
     * 初始化crosswalk环境,才能调用XwalkView
     */
    protected void onXWalkCoreReady() { 
        mActivityDelegate = new XWalkActivityDelegate(this, cancelCommand, completeCommand);
    }

    Runnable cancelCommand = new Runnable() {
        @Override
        public void run() {
            finish();
        }
    };
    Runnable completeCommand = new Runnable() {
        @Override
        public void run() {
            onXWalkReady();
        }
    };
    private XWalkActivityDelegate mActivityDelegate;
    public abstract void onXWalkReady() ;
}

然后,在MainActivity中继承这个抽象类实现它

public class MainActivity extends CrosswalkActivity{

    XWalkView xWalkView;

    @Override
    public void onXWalkReady() {
        xWalkView.load("http://play.7724.com/olgames/hdcgbt/", null);
    }
    @Override
    public void initCrosswalk() {
        Logger.showI("系统Crosswalk");
        xWalkView = new XWalkView(this, (Activity)this);    
        setContentView(xWalkView);
    }

    @Override
    public void initSysWebView() {
        Logger.showI("系统webview");
        WebViewFactory viewFactory = new WebViewFactory(this);
        WebView webView = viewFactory.getWebView();
        webView.loadUrl("http://www.csdn.net/");
        setContentView(webView);
    }

    //调用webview说明没有runtime,加载它
    @Override
    public void loadCrosswalk() {
        CrosswalkModelDownloadUtil modelDownloadUtil = new CrosswalkModelDownloadUtil(this);
        //已经下载了runtime文件,下面将它解压放到指定位置
        if(modelDownloadUtil.haveFileInLocal()){
            Logger.showI("本地有so文件");
            File file = new File(modelDownloadUtil.getFilePath());
            new Thread(new DpRunnable(file)).start();
        }else if(NetWorkHelp.isWifiConnected(this)){
            Logger.showI("本地没有,下载");//开启一个服务下载runtime文件
            startService(new Intent(this, CrosswalkDownloadService.class));
        }
    }

    //线程解压crosswalk
    public class DpRunnable implements Runnable{

        File file = null;

        CrosswalkUtil crosswalkUtil = new CrosswalkUtil(BaseActivity.this);

        public DpRunnable(File filetmp) {
            super();
            file = filetmp;
        }

        @Override
        public void run() {
            Logger.showI("开始解压"+file.exists()+file.getAbsolutePath());
            try {
                FileInputStream inputStream = new FileInputStream(file);
                crosswalkUtil.decompress(BaseActivity.this, inputStream);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}

下面看一下CrosswalkUtil工具类,它提供压缩文件解压,判断app是否有runtime模块

/**
     * 判断默认目录有无libxwalkcore.so文件,有之后才能使用XwalkView
     * @return
     */
    public boolean haveCwModel(){
        File cwModelDir = context.getDir("xwalkcore", Context.MODE_PRIVATE);
        if(!cwModelDir.exists())
            return false;
        File soFile = new File(cwModelDir, "libxwalkcore.so");
        if(soFile.exists() && (soFile.length()>=MAX_COUNT))
            return true;

        return false;
    }
/**
     * 解压文件流,并放到默认的目录
     * @param context
     * @param inputStream
     * @return
     */
    public boolean decompress(Context context,InputStream inputStream) {
        ReentrantLock reentrantLock = new ReentrantLock();
        File libDir = context.getDir("xwalkcore", Context.MODE_PRIVATE);
        if (libDir.exists() && libDir.isFile()) libDir.delete();
        if (!libDir.exists() && !libDir.mkdirs()) return false;

        reentrantLock.lock();

        for (String library : MANDATORY_LIBRARIES) {
            File tmpfile = null;
            InputStream input = null;
            OutputStream output = null;

            try {
                File outfile = new File(libDir, library);
                tmpfile = new File(libDir, library + ".tmp");
                input = new BufferedInputStream(inputStream);
                output = new BufferedOutputStream(new FileOutputStream(tmpfile));
                decodeWithLzma(input, output);
                tmpfile.renameTo(outfile);
            } catch (Resources.NotFoundException e) {
                return false;
            } catch (Exception e) {
                return false;
            } finally {
                reentrantLock.unlock();

                if (output != null) {
                    try {
                        output.flush();
                    } catch (IOException e) {
                    }
                    try {
                        output.close();
                    } catch (IOException e) {
                    }
                }
                if (input != null) {
                    try {
                        input.close();
                    } catch (IOException e) {
                    }
                }
                tmpfile.delete();
            }
        }
        return true;
    }
private  void decodeWithLzma(InputStream input, OutputStream output) throws IOException {
        final int propSize = 5;
        final int outSizeLength = 8;

        byte[] properties = new byte[propSize];
        if (input.read(properties, 0, propSize) != propSize) {
            throw new EOFException("Input .lzma file is too short");
        }

        Decoder decoder = new Decoder();
        if (!decoder.SetDecoderProperties(properties)) {
            Log.w(TAG, "Incorrect stream properties");
        }

        long outSize = 0;
        for (int i = 0; i < outSizeLength; i++) {
            int v = input.read();
            if (v < 0) {
                Log.w(TAG, "Can't read stream size");
            }
            outSize |= ((long)v) << (8 * i);
        }

        if (!decoder.Code(input, output, outSize)) {
            Log.w(TAG, "Error in data stream");
        }
    }

上面两个方法中,通过查找app_xwalkcoew目录有无libxwalkcore.so文件来判断是否有加载runtime,而解压的方法是在源代码里面截取的,文件是以7zip提供的api解压的。

另外res\raw\libxwalkcore.so.armeabi_v7a删除的话,可能老版的crosswalk初始化的时候会报错,所以我们可以添加一个空的libxwalkcore.so.armeabi_v7a


总结一下

  • 可以通过删除runtime文件改为启动时下载来“减少”apk大小
  • 下载的文件解压到制定目录成功后才能调用crosswalk,故每次调用webview都需要判断
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值