• cocoscreator3.X 强更 游戏内下载APK和安装APK


    本文环境3.6.0,目测3.7, 3.8都可以用

    强制更新是强制用户下载整包并覆盖安装,因为android部分代码不方便热更,所以游戏内采用服务器推送下载通知,游戏执行下载后再安装的形式.

    下载完全可在ts层完成,可采用cocoscreator的native.Downloader类,此类功能非常强大,只要给出apk的服务器地址就可以执行下载操作,还返回onProgress(进度反馈)和onError和onSuccess回调,你可以方便的用一个进度条展示出下载进度,并获得下载失败的原因和成功回调,代码如下:

    1. //下载Apk
    2. downloadApk() {
    3. if(!native || !native.AssetsManager ) {
    4. return;
    5. }
    6. let filePath = this._storagePath + "/bigwinner.apk"; //下载成功后的存放地址,为本地可写路径下的XX.apk
    7. if(!this._downloader)
    8. this._downloader = new native.Downloader();
    9. //下载失败回调
    10. this._downloader.onError = (task:native.DownloaderTask, errorCode: number, errorCodeInternal: number, errorStr: string)=> {
    11. console.log(errorStr);
    12. };
    13. //进度回调
    14. this._downloader.onProgress = (task, bytesReceived, totalBytesReceived, totalBytesExpected)=> {
    15. let progress:number = totalBytesReceived / totalBytesExpected; //已经下载的字节数 / 需要下载的总字节数
    16. this.getProgress(progress);
    17. let bKReceived:string = (totalBytesReceived / 1024).toFixed(1);
    18. let totalReceived:string = (totalBytesExpected / 1024).toFixed(1);
    19. var strProgress:string = "Download APK:" + bKReceived + "kb / " + totalReceived + "kb";
    20. this.updateLabel.string = strProgress;
    21. };
    22. //下载成功回调
    23. this._downloader.onSuccess = (task) => {
    24. this.updateLabel.string = "Download success!";
    25. this.installApk(filePath); //下载成功,执行安装apk操作
    26. };
    27. //开始执行下载操作,参数1:服务器的下载地址 如:http://192.168.0.101/game.apk 参数2:下载完成后的apk文件本地存放地址
    28. this._downloader.createDownloadTask(this.apkUrl, filePath);
    29. }

    安装APK需要用到android底层,所以应该在android层写代码

    ts层代码:

    1. //安装APK
    2. installApk(apkPath:string) {
    3. if (native.reflection) {
    4. native.reflection.callStaticMethod("com/cocos/game/AppActivity", "installAPK", "(Ljava/lang/String;)V", apkPath);
    5. }
    6. }

    此处调用com.cocos.game.AppActivity下的installApk静态方法

    安卓代码:

    1. //安装APK
    2. public static void installAPK(String path) {
    3. try {
    4. File apk = new File(path);
    5. if(!apk.exists()) {
    6. Log.e(TAG, "apk:" + path + " not found!");
    7. return;
    8. }
    9. Intent intent = new Intent(Intent.ACTION_VIEW);
    10. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    11. intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    12. Uri uri;
    13. if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N) { //新版本android 24以后执行下面方法
    14. String packageName = myContext.getApplicationContext().getPackageName();//pkgName;
    15. String authority = new StringBuilder(packageName).append(".fileprovider").toString();
    16. uri = FileProvider.getUriForFile(myContext, authority, apk);
    17. intent.setDataAndType(uri, "application/vnd.android.package-archive");
    18. }
    19. else { //老版本执行下面方法
    20. uri = Uri.fromFile(apk);
    21. intent.setDataAndType(uri, "application/vnd.android.package-archive");
    22. }
    23. myContext.startActivity(intent);
    24. }
    25. catch (Exception ex) {
    26. ex.printStackTrace();
    27. }
    28. }

    注意现在的android版本一般是大于android24的,即代码里的Build.VERSION_CODES.N,所以需要像代码里所写,在AndroidManfeist.xml里配置一个fileprovider,否则程序无法执行,具体是:

    首先在AndroidManfiest文件里加入可安装的权限,以及读写内部存储的权限:

    
    
    
    
    

    结点下添加一个provider配置,这个配置可放在所有的activity后面,如下:

    1. <provider
    2. android:name="androidx.core.content.FileProvider"
    3. android:authorities="com.goldenbulked.hyfbw.india.fileprovider"
    4. android:exported="false"
    5. android:grantUriPermissions="true"
    6. >
    7. <meta-data
    8. android:name="android.support.FILE_PROVIDER_PATHS"
    9. android:resource="@xml/file_paths" />
    10. provider>

    注意这里有两个要点,andrioid:authorities是"你的包名"+"fileprovider"写法,这是刚才installApk代码里写的,你可以再回头看一眼那个代码,还有那个meta-data里要配置可读写的路径,即 android:resource = "@xml/file_paths"里的配置,如果配置不对程序还是会报错的。
    所以在res目录下新建个xml文件夹,在里面新建个file_paths.xml文件,如图所示:

    file_paths.xml内容如下:
     

    1. "1.0" encoding="utf-8"?>
    2. <paths>
    3. <files-path
    4. name="apk"
    5. path="bigwinner-remote-asset/" />
    6. <external-path
    7. name="app_update_external"
    8. path="/" />
    9. <external-cache-path
    10. name="app_update_cache"
    11. path="/" />
    12. <external-path
    13. name="camera_pictures"
    14. path="." />
    15. <external-path
    16. name="external"
    17. path="/" />
    18. paths>

    其实也就第一条有用,我下载apk存放的路径是游戏可写路径下/bigwinner-remote-asset/内,这样配置游戏就能正常安装了

    网上说需要动态申请安装和读取存储权限,我代码里面没有动态申请也能执行成功,安装时自动会问用户是否要安装,不知道那个动态申请代码有何用?

  • 相关阅读:
    Android R.fraction
    16:00面试,16:08就出来了,问的问题有点变态。。。
    【原创】CentOS9安装Zabbix6.4
    多目标优化算法:多目标圆圈搜索算法(Multi-Objective Circle Search Algorithm,MOCSA)
    Modbus动态链接库供多语言使用 | Go
    Android垃圾分类助手APP(Java+Android Studio+SQLite)
    常见的加密算法和类型
    Python机器视觉--OpenCV入门--OpenCV鼠标绘制图形
    java基础-并发编程-ReentrantLock源码学习
    Presto (一) --------- Presto 简介
  • 原文地址:https://blog.csdn.net/qiou2719/article/details/133141246