Laya2.x安卓Native打包及自动更新功能

一、开发环境

系统:windows

IDE版本:2.8.0

Android Studio 版本:3.5.2

二、构建 LayaBox 项目

新建一个 LayaBox 项目,并且为了测试 APK 更新是否生效,故应当在游戏场景中放一个文本框,来显示当前游戏的版本号和 APK 的版本号:

在 LayaBox 项目中 Main.ts 中的构造函数中,你应当为资源版本文件加上 URL 参数来确保它每次都会加载,否则资源热更会不正常

constructor() {
    // ...
    Laya.alertGlobalError(true);

    //激活资源版本控制,version.json由IDE发布功能自动生成,如果没有也不影响后续流程
    Laya.ResourceVersion.enable("version.json?v=" + Date.now(), Laya.Handler.create(this, this.onVersionLoaded), Laya.ResourceVersion.FILENAME_VERSION);
}

添加 JS 与 Java 的交互代码:

export default class NativeApi {
    private $bridge: any = null;
    private $enabled: boolean = false;

    constructor() {
        try {
            var os = window["conchConfig"].getOS();

            // ...
            // 这部分代码请参考 Laya 官方教程 LayaNative原生服务 之 二次开发
            // ...

            this.$bridge = bridge;
            this.$enabled = true;
        }
        catch (error) {
            console.error(`NativeApi不可用`);
        }
    }

    getApkVersion(): string {
        if (this.$enabled === true) {
            return this.$bridge.call("getApkVersion");
        }
        return "0.0";
    }
}

场景初始化完成时获取并显示 APK 版本号:

import NativeApi from './NativeApi';

export default class TestScene extends Laya.Script {

    onAwake(): void {
        const label: Laya.Label = this.owner.getChildByName("txt_apkVer") as Laya.Label;
        label.text = "apk-" + NativeApi.getInstance().getApkVersion();
    }

}

三、构建 Android Studio 工程

构建 Android Studio 项目时,URL需要改一改,默认文件名为index.js,应当改为runtime.json(使用layadcc热更的除外)

完成这一步之后,还应当将MainAcitivity.java中的游戏资源网址后面加上版本号防止缓存问题:

public void initEngine() {
    // ...
    mPlugin.game_plugin_set_option("localize", "false");
    mPlugin.game_plugin_set_option("gameUrl", "http://checkapkupdate.xxxxx.com/runtime.json?v=" + System.currentTimeMillis());
    mPlugin.game_plugin_init(3);
    // ...
}

发布LayaBox项目,发布选项至少应该勾选“是否开启版本管理”,否则游戏热更会不正常(使用layadcc热更的除外)

发布完之后,将release/web下的所有文件都拷到构建Android Studio项目时指定的站点上,并且需要添加一个名字为runtime.json的文件,其内容为:

{
    "scripts": ["index-ed57e01127.js"],
    "screenOrientation": "landscape"
}

其中,scripts的值应当是LayaBox项目发布后release/web文件夹中index.js的文件名,是否横竖屏也必须在这个json里面指定,我己经忘了,抱歉,我这里是在这个json里指定了模屏模式。

二、接下来要改一些代码,因为 LayaBox 发布的 Android Studio 工程中有些代码是无效的

1. 修改 AutoUpdateAPK.java 中指定的 APK 下载后的存放路径

public AutoUpdateAPK(Context p_context, ValueCallback<Integer> callback) {
    // ...
    this.m_szDownloadAPKName = config.GetInstance().getProperty("UpdateAPKFileName");
    // 直接在 UpdateDownloadPath 中指定的地址没法直接用
    // this.m_szDownloadPath = config.GetInstance().getProperty("UpdateDownloadPath");
    this.m_szDownloadPath = Environment.getExternalStorageDirectory() + "/";
    setVersionCode(p_context);
    // ...
}

2. 修改 AutoUpdateAPK.java 中 APK 安装的实现以兼容安卓7.0

public void updateAPK() {
    Intent intent = new Intent(Intent.ACTION_VIEW);

    // 这个实现没有兼容7.0版本
    // intent.setDataAndType(
    //         Uri.fromFile(new File(m_szDownloadPath, m_szDownloadAPKName)),
    //         "application/vnd.android.package-archive");

    File file = new File(m_szDownloadPath, m_szDownloadAPKName);
    //判读版本是否在7.0以上
    if (Build.VERSION.SDK_INT >= 24) {
        Uri apkUri = FileProvider.getUriForFile(m_context, m_context.getPackageName() + ".fileprovider", file);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
    } else {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(
                Uri.fromFile(file),
                "application/vnd.android.package-archive");
    }
    m_context.startActivity(intent);
}

3. 在 AndroidManifest.xml 中添加 provider 属性,否则 FileProvider.getUriForFile 会报错

<application

    <!-- 兼容7.0 -->
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:grantUriPermissions="true"
        android:exported="false">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>

</application>

4. 在 app/res 目录中创建 xml 文件夹,并在 xml 文件夹中创建 file_paths.xml 文件,其内容为:

<paths>
    <external-path path="." name="external_storage_root" />
</paths>

关于这个 xml  的配置,可以自行度娘 file_paths.xml 来获取更多的了解。

5. 当然,我们还应当在 JSBridge.java 中添加 getApkVersion 方法来告诉 JS apk 的当前版本号:

public static String getApkVersion() {
    PackageManager packageManager = mMainActivity.getPackageManager();
    PackageInfo packageInfo;
    String versionName = "";
    try {
        packageInfo = packageManager.getPackageInfo(mMainActivity.getPackageName(), 0);
        versionName = packageInfo.versionName;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return versionName;
}

三、在引用了 androidx.core.content.FileProvider 之后会出现一大堆错误,所以我们要:

1. 在 Project/build.gradle 中将 classpath 'com.android.tools.build: gradle' 的版本从升级到 3.5.3

2. 在 Poject/gradle/wrapper/gradle-wrapper.properties 中 distributionUrl 指定的 gradle 版本升级到 5.4.1

3. 将 App/build.gradle 中的 buildToolsVersion 指定为 28.0.3,不然会有最小版本支持的警告

4. 在 Project/gradle.properties 中添加以下两行,否则 androidx.core.content.FileProvider 还是会引用不到

android.useAndroidX = true
android.enableJetifier = true

5. 这时候如果你运行工程会报 "程序包android.support.v4.content不存在" 的错误,没关系,我们回到 AudoUpdateAPK.java 文件中,将 FileProvider 重新引用一下,错误就没了

四、接下来要发布 APK 并测试 APK 的热更新,可能你在执行下面这些步骤的时候会碰到一些错误,没关系,错误我会在 五 中一一列举,请对照修正

1. 请注意 app/build.gradle 中 versionCode 的默认值为 1,versionName 的默认值为 "2.0"

2. 请按照 layabox 官方的指导来修改 app/assets/config.ini 文件,值得注意的是,在个文件中 UpdateAPKFileName 指定的名字应当为下个版本 APK 的文件名

3. 发布 2.0 版本的 APK 并安装至手机并运行,因为现在服务器上并没有新版本的 apk ,所以你应该直接能看到以下画面:

4. 将 app/build.gradle 中 defaultConfig 中的 versionCode 修改为 2 ,并将 versionName 修改为 "2.1" ,并将 app/assets/config.ini 的中下一个版本的 APK 文件名更改为 app-2.2.apk,然后再次发布 APK ,将其命名为 "app-2.1.apk",并放到服务器上,然后修改 version.xml 中的 apk 信息,使之与最新版的 apk 的信息一致:

<update>
  <versionCode>2</versionCode>
  <name>Laya自动更新</name>
  <version>2.1</version>
  <url>http://checkapkupdate.xxx.com/app-2.1.apk</url>
</update>

5. 将 app-2.1.apk 放置到 checkapkupdate.xxxxx.com 的站点中,重新运行 app-2.0 ,你将会看到下面几个画面:

6. 下载完并安装新的 APK 包之后,你将不会再看到 APK 更新的提示,进入游戏后,你将看到新的版本提示:(我没有重新发布 H5 的代码,所以第一个版本号还是2.0)

五、H5 游戏可能碰到的一些问题

1. 提示“加载游戏失败,可能由于您的网络不稳定,请退出重进”。引起这个问题的原因有很多,我碰到的有以下几种情况:

a) 有些 laya 的库被我删掉了但没有在 IDE 的 F9 设置中去掉打勾

b) runtime.json 中的 scripts 文件名指定错误了

c) MainActivity.java 中的 gameUrl 指定错误了

2. 如果是单机版本,则有可能是以下原因:

a) 构建 Android Studio 项目的时候,没有指定正确的资源路径,正确的资源路径应当指向 LayaBox 工程下的 bin 目录(不是 release 目录)

b) 游戏更新后,没有重新打 layadcc ,正确的做法是删除 Android Studio 中 app/src/main/assets/cache 中的资源,然后用 layadcc 重新将 bin 下的资源发布到 cache 目录中

c) 你的项目发布的时候勾选了版本管理,请取消这个勾选(手动狗头)

总的来说,这个问题发生的主要原因是游戏脚本或资源没找到,原因可能是忘记发布、更新、链接或文件名搞错了,包括将 https 和 http 搞错了都有可能。

六、Native 热更碰到的一些问题

1. 点击开始更新后闪退,这个主要有两个可能的原因:

a) 没有开启 STORAGE 权限

b) 没有 REQUEST_INSTALL_PACKAGES 权限

c) 你在服务器上配置了新的 apk 下载信息,但没有对应的 apk ,或 apk 的名字搞错了,laya 官方实现的下载代码就会 crash 。。。

2. 下载完新的 APK 包后闪退,这个原因也有很多,主要有以下几个方面:

a) AndroidManifest.xml 中 provider 的 authorities 搞错了,正确的 authorities 值应该是你的包名 + ".fileprovider",除此之外,你还要检查 AutoUpdateAPK.java 中 updateApk 方法中的实现

b) app/assets/config.ini 中的 ApkUpdateUrl 或 UpdateAPKFileName 搞错了,检查网址、路径和文件名,包括 http 和 https 是不是搞反了,我就曾粗心的把 app-2.1.apk 写成了 apk-2.1.apk 。。。

3. 不断地热更,这是因为你在 app/assets/config.ini 指定的 UpdateAPKFileName 是当前版本的 apk 名字而非下一个版本的,所以它不停的认为存在最新的 apk 所以不停的进行更新

七、Native 启动后进游戏之前的几秒黑屏问题,这个问题官方是有解决方案的,我也可以在这里重复下

1. 修改 Android Studio 项目中的 app/assets/scripts/config.js 中的代码,将 window.loadingView.loadingAutoClose 的值设为 false:

// ...
if(window.loadingView)
{
    window.loadingView.loadingAutoClose=false;//true代表当动画播放完毕,自动进入游戏。false为开发者手动控制
    window.loadingView.bgColor("#000000");//设置背景颜色
    // ...
}
// ...

2. 在 H5 游戏的启动页加载完成的下一帧,调用 window.loadingView.hideLoadingView(); 即可立即主动将原生的启动页移除:

export default class TestScene extends Laya.Script {

    onAwake(): void {
        // ...
        Laya.timer.frameOnce(1, this, this.$onHideNativeLoadingView);
    }

    private $onHideNativeLoadingView(): void {
        try {
            window["loadingView"].hideLoadingView();
        }
        catch (error) {

        }
    }
}

注意一定要在下一帧移除,否则界面还是会闪一下

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值