Egret社区
周末写了一个简单的DIY热更新的实现方式,想按照自己的逻辑进行热更新的同学可以参考一下:
代码:
[mw_shl_code=java,true]package org.egret.java.test_android;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.logging.Handler;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.egret.egretframeworknative.EgretRuntime;
import org.egret.egretframeworknative.engine.EgretGameEngine;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONTokener;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

public class test_android extends Activity {
    private interface IRuntimeInterface {
        public void callback(String message);
        // 因为遗留问题 callBack 也是接受的
    }
   
    private static final String EGRET_ROOT = "egret";
    //TODO: egret publish之后,修改以下常量为生成的game_code名
    private static final String EGRET_PUBLISH_ZIP = "game_code_0123456789.zip";
    protected static final String TAG = "test_android";
   
           //若bUsingPlugin为true,开启插件
    private boolean bUsingPlugin = false;

    private EgretGameEngine gameEngine;
    private String egretRoot;
    private String gameId;
    private String loaderUrl;
    private String updateUrl;

    public static boolean initEnable = false;

    public class GetGameRes implements Runnable {

        private String jsonUrl = "";
        private String saveRootPath = "";
        private String gameRootPath = "";

        public GetGameRes(String jurl) {
            jsonUrl = jurl;

            String filePath = getApplicationContext().getFilesDir().getAbsolutePath();
            saveRootPath = filePath;
            gameRootPath = filePath + "/egret/local/game";
        }

        @Override
        public void run() {
            // get game json info
            String jsonInfo = getGameJson();

            String _loaderUrl = "";
            String _updateUrl = "";

            // update loaderUrl and updateUrl
            try {
                JSONObject jsonObject = new JSONObject(jsonInfo);
                _loaderUrl = jsonObject.getString("code_url");
                _updateUrl = jsonObject.getString("update_url");

                Log.d("===== 11", _loaderUrl);
                Log.d("===== 11", _updateUrl);
            } catch (Exception e) {
                Log.i("===== 11", "Exception " + e.toString());
            }

            String saveFilePath = getGameZip(_loaderUrl);

            unzip(saveFilePath, gameRootPath);

            final String sUpdateUrl = _updateUrl;

            loaderUrl = "";
            updateUrl = sUpdateUrl;
            test_android.initEnable = true;
        }

        public String getGameJson() {
            String jsonInfo = "";

            try {
                HttpClient getClient = new DefaultHttpClient();
                HttpGet request = new HttpGet(jsonUrl);
                HttpResponse response = getClient.execute(request);
                if(response.getStatusLine().getStatusCode()==HttpStatus.SC_OK){
                    Log.i("=====", "请求服务器端成功");
                    InputStream inStrem = response.getEntity().getContent();
                    int result = inStrem.read();
                    while (result != -1){
                        jsonInfo += (char)result;
                        result = inStrem.read();
                    }
                    inStrem.close();
                } else {
                    Log.i("=====", "请求服务器端失败");
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Log.i("=====", "Exception");
            }

            Log.d("=====", "[" + jsonInfo + "]");
            return jsonInfo;
        }

        public String getGameZip(String loaderUrl) {
            HttpURLConnection conn = null;
            FileOutputStream out = null;
            String saveFilePath = "";
            try {
                URL url = new URL(loaderUrl);
                conn = (HttpURLConnection)url.openConnection();
                conn.setConnectTimeout(30 * 1000);
                conn.setReadTimeout(30 * 1000);

                conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

                int length = conn.getContentLength();
                int progress = 0;

                InputStream inputStream = conn.getInputStream();
                byte[] buffer = new byte[8 * 1024];
                int read;

                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

                saveFilePath = saveRootPath + "/temp.zip";
                File saveFile = new File(saveFilePath);
                out = new FileOutputStream(saveFile);

                while ((read = inputStream.read(buffer)) > 0) {
                    progress += read;
                    out.write(buffer, 0, read);
                    Log.d("=====       ", "" + progress + " " + length);
                }

                out.close();

            } catch (Exception e) {
                Log.e("=====", e.toString());
            } finally {
                if (conn != null) {
                    conn.disconnect();
                }
            }

            return saveFilePath;
        }

        public void unzip(String filePath, String gamePath) {
            ZipFile zipFile = null;
            int length = 0;
            int prograss = 0;
            try {
                zipFile = new ZipFile(filePath);
                Enumeration<? extends ZipEntry> enumeration = zipFile.entries();
                while (enumeration.hasMoreElements()) {
                    length += (enumeration.nextElement()).getSize();
                }
                enumeration = zipFile.entries();
                while (enumeration.hasMoreElements()) {
                    ZipEntry zipEntry = enumeration.nextElement();
                    prograss += unzipEntry(zipFile, zipEntry);
                    Log.d("===== unzip", "" + prograss + " / " + length);
                }
            } catch (Exception e) {
                Log.e("===== unzip", e.toString());
            }

            Log.d("=====", "unzip success");
        }

        private int unzipEntry(ZipFile zipFile, ZipEntry zipEntry) {
            InputStream inputStream = null;
            FileOutputStream out = null;
            int result = 0;
            try {
                File target = new File(gameRootPath, androidPath(zipEntry.getName()));
                if (zipEntry.isDirectory()) {
                    makeRoot(target);
                    return 0;
                }
                makeRoot(target.getParentFile());

                inputStream = zipFile.getInputStream(zipEntry);
                out = new FileOutputStream(target);
                byte data[] = new byte[4 * 1024];
                int read = 0;
                while ((read = inputStream.read(data, 0, 4 * 1024)) != -1) {
                    out.write(data, 0, read);
                    result += read;
                }

                inputStream.close();
                out.close();
            } catch (Exception e) {
                Log.e("===== unzipEntry", e.toString());
            }

            return result;
        }

        private String androidPath(String name) {
            return name.replace('\\', '/');
        }

        private void makeRoot(File root) throws Exception {
            if (!root.exists() && !root.mkdirs()) {
                throw new Exception("");
            }
        }
    }

    private void doSomething(String jsonUrl) {
        String filePath = getApplicationContext().getFilesDir().getAbsolutePath();
        String gameFilePath = filePath + "/egret/local/game";

        GetGameRes getGameJson = new GetGameRes(jsonUrl);
        new Thread(getGameJson).start();

        Log.d("=====", filePath);
        Log.d("=====", gameFilePath);
    }

    public void initEgret() {
        initEnable = true;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        
        egretRoot = new File(getFilesDir(), EGRET_ROOT).getAbsolutePath();
        gameId = "local";

        // download zip and set loaderUrl and update the game
        doSomething("http://10.0.4.103/app1/info.json");

//        //TODO: DEBUG 使用 2
//        // we do not need this
//        setLoaderUrl(2);

        // 等待另一个线程进行的的热更新结束
        // Waiting for annother thread to finish hot updating
        // 如果zip包太大的话还是改成通知玩家重启的形式比较好.
        // Tell players to restart the game is a better way if the game resource zip is big.
        while (!initEnable) {
            try {
                Thread.sleep(1000);
                Log.d("=====", "waiting");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        gameEngine = new EgretGameEngine();
        // 设置游戏的选项  (set game options)
        HashMap<String, Object> options = getGameOptions();
        gameEngine.game_engine_set_options(options);
        // 设置加载进度条  (set loading progress bar)
        gameEngine.game_engine_set_loading_view(new GameLoadingView(this));
        // 创建Egret<->Runtime的通讯 (create pipe between Egret and Runtime)
        setInterfaces();
        // 初始化并获得渲染视图 (initialize game engine and obtain rendering view)
        gameEngine.game_engine_init(this);
        View gameEngineView = gameEngine.game_engine_get_view();

        setContentView(gameEngineView);
    }
   
    private void setInterfaces() {
        // Egret(TypeScript)-Runtime(Java)通讯
        // setRuntimeInterface(String name, IRuntimeInterface interface) 用于设置一个runtime的目标接口
        // callEgretInterface(String name, String message) 用于调用Egret的接口,并传递消息
        gameEngine.setRuntimeInterface("RuntimeInterface", new IRuntimeInterface() {
           @Override
            public void callback(String message) {
                Log.d(TAG, message);
                gameEngine.callEgretInterface("EgretInterface", "A message from runtime");
            }
        });
    }

    private HashMap<String, Object> getGameOptions() {
        HashMap<String, Object> options = new HashMap<String, Object>();
        options.put(EgretRuntime.OPTION_EGRET_GAME_ROOT, egretRoot);
        options.put(EgretRuntime.OPTION_GAME_ID, gameId);
        options.put(EgretRuntime.OPTION_GAME_LOADER_URL, loaderUrl);
        options.put(EgretRuntime.OPTION_GAME_UPDATE_URL, updateUrl);
        if(bUsingPlugin){
                String pluginConf = "{'plugins':[{'name':'androidca','class':'org.egret.egretframeworknative.CameraAudio','types':'jar,so'}]}";
                                        options.put(EgretRuntime.OPTION_GAME_GLVIEW_TRANSPARENT, "true");
                options.put(EgretRuntime.OPTION_EGRET_PLUGIN_CONF, pluginConf);
        }
        return options;
    }

    private void setLoaderUrl(int mode) {
        switch (mode) {
        case 2:
            // local DEBUG mode
            // 本地DEBUG模式,发布请使用0本地zip,或者1网络获取zip
            loaderUrl = "";
            updateUrl = "";
            break;
        case 1:
            // http request zip RELEASE mode, use permission INTERNET
            // 请求网络zip包发布模式,需要权限 INTERNET
            loaderUrl = "http://www.example.com/" + EGRET_PUBLISH_ZIP;
            updateUrl = "http://www.example.com/";
            break;
        default:
            // local zip RELEASE mode, default mode, `egret publish -compile --runtime native`
            // 私有空间zip包发布模式, 默认模式, `egret publish -compile --runtime native`
            loaderUrl = EGRET_PUBLISH_ZIP;
            updateUrl = "";
            break;
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        gameEngine.game_engine_onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
        gameEngine.game_engine_onResume();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_BACK:
            gameEngine.game_engine_onStop();
            finish();
            return true;
        default:
            return super.onKeyDown(keyCode, event);
        }
    }
}
[/mw_shl_code]
参与人数 1银子 +5 收起 理由
KnightCast2Leg + 5 很给力!

查看全部评分

分享到 :
4 人收藏

2 个回复

倒序浏览
yjtx  官方团队 | 2016-12-5 15:07:27
yung  初窥堂奥 | 2016-12-8 17:34:56
这个可以有!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|京网文[2014]0791-191号|京ICP证150115号|Egret社区 ( 京ICP备14025619号 )

Powered by Discuz! X3.4 © 2001-2019 Comsenz Inc.

返回顶部