cocos2dx 3.0 Google使用obb扩展包

cocos2dx 3.16 已经支持使用Google obb扩展包

首先项目支持Google play service

AndroidManifest.xml相关权限和工程配置

    <uses-permission android:name="com.android.vending.CHECK_LICENSE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /
        <activity
            android:name="com.cocos2d.plugin.downloader.UnityDownloaderActivity"
            android:configChanges="keyboardHidden|orientation|screenSize"
            android:theme="@style/AppTheme" >
        </activity>
        <service android:name="com.cocos2d.plugin.downloader.UnityDownloaderService" />
        <receiver android:name="com.cocos2d.plugin.downloader.UnityAlarmReceiver" />
Cocos2dxActivity增加变量和方法如下:
public static String FATE_OBB_PATH = "";
public static String FATE_OBB_Name = "";
@Override
    protected void onCreate(final Bundle savedInstanceState) {
        FATE_OBB_Name = getObbFileName();
        FATE_OBB_PATH = getVirtualObbFileFullpath();
        super.onCreate(savedInstanceState);
        ....
    }

private String getObbFileName() {
        PackageInfo info = null;
        try {
            info = getPackageManager().getPackageInfo(getPackageName(), 0);
            String fileName = "main." + info.versionCode + "." + getPackageName() + ".obb";
            Log.e("obb===fileName===", fileName);
            return fileName;
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return "";
    }
    private String getVirtualObbFileFullpath(){
        String _path = "";
        File file = getObbDir();
        if(file == null || !file.exists()){
            file.mkdirs();
        }
        _path = file.getPath() + "/" + getObbFileName();
        Log.e("obb===_path===", _path);
      return _path;    
  }

Cocos2dxHelper增加代码如下:

public static ZipResourceFile obbzip = null;
public static void init(final Activity activity) {
...
// begin--------------------添加代码----------------------------
// //检查obb文件是否存在
if (fileIsExists(Cocos2dxActivity.FATE_OBB_PATH)) {
     // 存在添加obb路径到cocos中 注意 nativeSetObbPath 方法是需要新添加的 下方会介绍
     Cocos2dxHelper.nativeSetObbPath(Cocos2dxActivity.FATE_OBB_PATH);
}
// end--------------------添加代码----------------------------
...
//设置压缩包 
 PackageInfo info = null;
 try {
     info = activity.getPackageManager().getPackageInfo(
            activity.getPackageName(), 0);
     Cocos2dxHelper.obbzip = APKExpansionSupport
                        .getAPKExpansionZipFile(activity, info.versionCode, 0);
  } catch (PackageManager.NameNotFoundException e1) {
     e1.printStackTrace();
  } catch (IOException e1) {
     e1.printStackTrace();
  }

...
}

// 检查obb文件是否存在
    public static boolean fileIsExists(String strFile) {
        if(strFile.isEmpty()){
            return false;
        }
        try {
            File f = new File(strFile);
            if (!f.exists()) {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
        Log.d("obb", "file exit");
        return true;
    }

    // nativeSetObbPath 设置obb路径方法
    private static native void nativeSetObbPath(final String pObbPath);



Cocos2dxSound中:

soundID = this.mSoundPool.load(this.mContext.getAssets().openFd(path), 0);

替换为

final AssetFileDescriptor assetFileDescritor = Cocos2dxHelper.obbzip
                        .getAssetFileDescriptor("assets/" + path);
                if (assetFileDescritor == null) {
                    final AssetFileDescriptor assetFileDescritor1 = this.mContext
                            .getAssets().openFd(path);
                    soundID = this.mSoundPool.load(assetFileDescritor1, 0);
                } else {
                    soundID = this.mSoundPool.load(assetFileDescritor, 0);

                }

Cocos2dxMusic中:

mediaPlayer.setDataSource(assetFileDescritor.getFileDescriptor(),assetFileDescritor.getStartOffset(), assetFileDescritor.getLength());

替换为

final AssetFileDescriptor assetFileDescritor = Cocos2dxHelper.obbzip.getAssetFileDescriptor("assets/"+path);
                if(assetFileDescritor == null){
                    final AssetFileDescriptor assetFileDescritor1 = this.mContext.getAssets().openFd(path);
                    mediaPlayer.setDataSource(assetFileDescritor1.getFileDescriptor(), assetFileDescritor1.getStartOffset(), assetFileDescritor1.getLength());
                }else{
                    mediaPlayer.setDataSource(assetFileDescritor.getFileDescriptor(), assetFileDescritor.getStartOffset(), assetFileDescritor.getLength());                    
                }


接下来就是改造c++中调用assets里资源的方式,只需要修改Java_org_cocos2dx_lib_Cocos2dxHelper和CCFileUtils-android两个文件

Java_org_cocos2dx_lib_Cocos2dxHelper.cpp中

//添加obb path

string g_obbPath;

//添加设置obbpath 方法
    JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxHelper_nativeSetObbPath(JNIEnv* env, jobject thiz, jstring obbPath) {
        g_obbPath = JniHelper::jstring2string(obbPath);

    }

//添加获取obbpath 方法
const char * getObbPath() {
    return g_obbPath.c_str();
}


Java_org_cocos2dx_lib_Cocos2dxHelper.h中

//添加方法

extern const char * getObbPath();

CCFileUtils-android.cpp中

isFileExistInternal方法

bool FileUtilsAndroid::isFileExistInternal(const std::string& strFilePath) const
{
    if (strFilePath.empty())
    {
        return false;
    }

    // if (cocosplay::isEnabled() && !cocosplay::isDemo())
    // {
    //     return cocosplay::fileExists(strFilePath);
    // }

    bool bFound = false;
    
    // Check whether file exists in apk.
    if (strFilePath[0] != '/')
    {
        const char* s = strFilePath.c_str();

        // Found "assets/" at the beginning of the path and we don't want it
        if (strFilePath.find(_defaultResRootPath) == 0) s += strlen("assets/");

        if (FileUtilsAndroid::assetmanager) {
            AAsset* aa = AAssetManager_open(FileUtilsAndroid::assetmanager, s, AASSET_MODE_UNKNOWN);
            if (aa)
            {
                bFound = true;
                AAsset_close(aa);
            } else if(getObbPath() != nullptr){
                // CCLOG("[AssetManager] ... in APK %s,%s, found = false! \n obbPath=%s", strFilePath.c_str(),s, getObbPath());
                ZipFile obbFile(getObbPath());
                if ( obbFile.fileExists(strFilePath.c_str()) ) {
                    // CCLOG("obb ... in APK %s, found = true!", strFilePath.c_str());
                    bFound = true;
                }else{
                    // CCLOG("obb ... in APK %s, found = false!", strFilePath.c_str());
                }
            }
        }
    }
    else
    {
        FILE *fp = fopen(strFilePath.c_str(), "r");
        if(fp)
        {
            bFound = true;
            fclose(fp);
        }
    }
    return bFound;
}

getData方法
Data FileUtilsAndroid::getData(const std::string& filename, bool forString)
{
    if (filename.empty())
    {
        return Data::Null;
    }
    
    unsigned char* data = nullptr;
    ssize_t size = 0;
    string fullPath = fullPathForFilename(filename);
    // cocosplay::updateAssets(fullPath);

    if (fullPath[0] != '/')
    {
        string relativePath = string();

        size_t position = fullPath.find("assets/");
        if (0 == position) {
            // "assets/" is at the beginning of the path and we don't want it
            relativePath += fullPath.substr(strlen("assets/"));
        } else {
            relativePath += fullPath;
        }
        CCLOGINFO("relative path = %s", relativePath.c_str());

        if (nullptr == FileUtilsAndroid::assetmanager) {
            LOGD("... FileUtilsAndroid::assetmanager is nullptr");
            return Data::Null;
        }

        // read asset data
        AAsset* asset =
            AAssetManager_open(FileUtilsAndroid::assetmanager,
                               relativePath.c_str(),
                               AASSET_MODE_UNKNOWN);
        if (nullptr != asset) {
            off_t fileSize = AAsset_getLength(asset);

            if (forString)
            {
                data = (unsigned char*) malloc(fileSize + 1);
                data[fileSize] = '\0';
            }
            else
            {
                data = (unsigned char*) malloc(fileSize);
            }

            int bytesread = AAsset_read(asset, (void*)data, fileSize);
            size = bytesread;

            // CCLOG("obb size test: size=%d;fileSize=%d", size, fileSize);
            AAsset_close(asset);
            // return Data::Null;
        }else{
            // CCLOG("asset is nullptr");
            ZipFile zipFile(getApkPath());
            // CCLOG("guok special read: %s;forString=%d", relativePath.c_str(), forString);
            string zFileNamePath = "assets/" + relativePath;
            if ( zipFile.fileExists(zFileNamePath.c_str()) ) {
                ssize_t fsize = 0;
                unsigned char* content = zipFile.getFileData(zFileNamePath.c_str(), &fsize);
                if( fsize > 0) {
                    // CCLOG("guok read success %d", fsize);
                    memcpy( data, content, fsize);
                    size = fsize;
                }
                else {
                    // CCLOG("guok read error %d",  fsize);
                }
                if(content)free(content);
            }
            else if(getObbPath() != nullptr){
                ZipFile obbFile(getObbPath());
                if ( obbFile.fileExists(zFileNamePath.c_str()) ) {
                    ssize_t fsize = 0;
                    unsigned char* content = obbFile.getFileData(zFileNamePath.c_str(), &fsize);
                    if( fsize > 0) {
                        if (forString)
                        {
                            data = (unsigned char*) malloc(fsize + 1);
                            data[fsize] = '\0';
                        }else{
                            data = (unsigned char*) malloc(fsize);
                        }
                        memcpy( data, content, fsize);
                        size = fsize;
                        // CCLOG("obb getdata success %d", fsize);
                    } else {
                        CCLOG("obb getdata error %d",  fsize);
                    }
                    if(content)free(content);
                }
            }
            if (size <= 0)
            {
                CCLOG("obb null size %d", size);
                return Data::Null;
            }
        }
    }
    else
    {
        do
        {
            // read rrom other path than user set it
            //CCLOG("GETTING FILE ABSOLUTE DATA: %s", filename);
            const char* mode = nullptr;
            if (forString)
                mode = "rt";
            else
                mode = "rb";

            FILE *fp = fopen(fullPath.c_str(), mode);
            CC_BREAK_IF(!fp);
            
            long fileSize;
            fseek(fp,0,SEEK_END);
            fileSize = ftell(fp);
            fseek(fp,0,SEEK_SET);
            if (forString)
            {
                data = (unsigned char*) malloc(fileSize + 1);
                data[fileSize] = '\0';
            }
            else
            {
                data = (unsigned char*) malloc(fileSize);
            }
            fileSize = fread(data,sizeof(unsigned char), fileSize,fp);
            fclose(fp);
            
            size = fileSize;
        } while (0);
    }
    
    Data ret;
    if (data == nullptr || size == 0)
    {
        std::string msg = "Get data from file(";
        msg.append(filename).append(") failed!");
        CCLOG("%s", msg.c_str());
    }
    else
    {
        ret.fastSet(data, size);
        // cocosplay::notifyFileLoaded(fullPath);
    }
    return ret;
}

getFileData方法

unsigned char* FileUtilsAndroid::getFileData(const std::string& filename, const char* mode, ssize_t * size)
{    
    unsigned char * data = 0;
    // CCLOG("obb getFileData:%s",filename.c_str());
    if ( filename.empty() || (! mode) )
    {
        return 0;
    }
    
    string fullPath = fullPathForFilename(filename);
    // cocosplay::updateAssets(fullPath);

    if (fullPath[0] != '/')
    {
        string relativePath = string();

        size_t position = fullPath.find("assets/");
        if (0 == position) {
            // "assets/" is at the beginning of the path and we don't want it
            relativePath += fullPath.substr(strlen("assets/"));
        } else {
            relativePath += fullPath;
        }
        LOGD("relative path = %s", relativePath.c_str());

        if (nullptr == FileUtilsAndroid::assetmanager) {
            LOGD("... FileUtilsAndroid::assetmanager is nullptr");
            return nullptr;
        }

        // read asset data
        AAsset* asset =
            AAssetManager_open(FileUtilsAndroid::assetmanager,
                               relativePath.c_str(),
                               AASSET_MODE_UNKNOWN);
        if (nullptr != asset) {
            // LOGD("asset is nullptr");
            
            off_t fileSize = AAsset_getLength(asset);

            data = (unsigned char*) malloc(fileSize);

            int bytesread = AAsset_read(asset, (void*)data, fileSize);
            if (size)
            {
                *size = bytesread;
            }

            AAsset_close(asset);
        } else {
            ZipFile zipFile(getApkPath());
            // CCLOG(" special read: %s", relativePath.c_str());
            string zFileNamePath = "assets/" + relativePath;
            if ( zipFile.fileExists(zFileNamePath.c_str()) ) {
                ssize_t fsize = 0;
                unsigned char* content = zipFile.getFileData(zFileNamePath.c_str(), &fsize);
                if( fsize > 0) {
                    // CCLOG("getfiledata success %d", fsize);
                    data = (unsigned char*) malloc(fsize);
                    memcpy( data, content, fsize);
                    if (size)
                    {
                        *size = fsize;
                    }
                }
                else {
                    CCLOG("getfiledata error %d",  fsize);
                }
                if(content)free(content);
            } else if(getObbPath() != nullptr){
                ZipFile obbFile(getObbPath());
                if ( obbFile.fileExists(zFileNamePath.c_str()) ) {
                    ssize_t fsize = 0;
                    unsigned char* content = obbFile.getFileData(zFileNamePath.c_str(), &fsize);
                    if( fsize > 0) {
                        // CCLOG("obb getfiledata success %d", fsize);
                        data = (unsigned char*) malloc(fsize);
                        memcpy( data, content, fsize);
                        if (size)
                        {
                            *size = fsize;
                        }
                    } else {
                        CCLOG("obb getfiledata error %d",  fsize);
                    }
                    if(content)free(content);
                }
            }
        }

        if (!data)
        {
            // CCLOG("getFileData error: %s", relativePath.c_str());
            return nullptr;
        }
        
    }
    else
    {
        do
        {
            // read rrom other path than user set it
            //CCLOG("GETTING FILE ABSOLUTE DATA: %s", filename);
            FILE *fp = fopen(fullPath.c_str(), mode);
            CC_BREAK_IF(!fp);
            
            long fileSize;
            fseek(fp,0,SEEK_END);
            fileSize = ftell(fp);
            fseek(fp,0,SEEK_SET);
            data = (unsigned char*) malloc(fileSize);
            fileSize = fread(data,sizeof(unsigned char), fileSize,fp);
            fclose(fp);
            
            if (size)
            {
                *size = fileSize;
            }
        } while (0);
    }
    
    if (! data)
    {
        std::string msg = "Get data from file(";
        msg.append(filename).append(") failed!");
        CCLOG("%s", msg.c_str());
    }
    else
    {
        // cocosplay::notifyFileLoaded(fullPath);
    }
    return data;
}

主activity的oncreate方法添加一下代码检测是否已经下载到了obb包

if (Cocos2dxActivity.FATE_OBB_PATH.isEmpty() || !Cocos2dxHelper.fileIsExists(Cocos2dxActivity.FATE_OBB_PATH)) {
				
				Intent intent = new Intent(GameContext.getGameInstance(), UnityDownloaderActivity.class);
				GameContext.getGameInstance().startActivity(intent);

有部分代码和工程需要下载,请https://download.csdn.net/download/bibi333/10324625

https://download.csdn.net/download/bibi333/10324619

这些准备之后,就是上传Google beta包测试了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值