GooglePlay - 文件上傳限制的擴展


前言

  Google Play應用商店在上傳限制100MB大小,超過該大小的應用必須將超過部分以擴展文件的形式進行上傳處理。 總共可上傳2個擴展文件,每個最大文件可為2GB,同時obb文件格式可自選。

官網地址:http://developer.android.com/google/play/expansion-files.html

 

准備

  1、在sdk Manager中下載對應的支持庫,play_licensing及play_apk_expansion如下:

    

  2、生成需要的obb文件,並在上傳apk包的同時選擇上傳擴展文件。

    obb文件生成可參考jobb工具生成(官網推薦), http://developer.android.com/tools/help/jobb.html

    也可以直接用參考stackoverflow上Sanket Kachhela的回答(個人推薦):http://stackoverflow.com/questions/14495483/read-content-from-apk-expansion-file-from-obb-file#answer-18953778,直接利用zip壓縮工具選擇存儲模式。

  3、如果上述采用zip壓縮的話,這里就還需要unzip准備,利用zipHelper直接解壓下載包並正常使用。

    參考stackoverflow上Bhavesh Hirpara的回答:http://stackoverflow.com/questions/14495483/read-content-from-apk-expansion-file-from-obb-file#answer-15150977

  

鏈接庫配置

  1、在eclipse打開需要的庫工程,如下:

    

  2、如果downloader_library出現錯誤 AESObfuscator cannot be resolved 則說明Eclipse沒有選擇自動編輯,勾選下project->build automatically即可。

  3、添加游戲項目,並添加對應的依賴項目如下圖:

    

項目配置

  1、添加對應的權限。

<manifest ...>
    <!-- Required to access Google Play Licensing -->
    <uses-permission android:name="com.android.vending.CHECK_LICENSE" />

    <!-- Required to download files from Google Play -->
    <uses-permission android:name="android.permission.INTERNET" />

    <!-- Required to keep CPU alive while downloading files
        (NOT to keep screen awake) -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <!-- Required to poll the state of the network connection
        and respond to changes -->
    <uses-permission
        android:name="android.permission.ACCESS_NETWORK_STATE" />

    <!-- Required to check whether Wi-Fi is enabled -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

    <!-- Required to read and write the expansion files on shared storage -->
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    ...
</manifest>

  2、從~sdk\play_apk_expansion\downloader_sample項目復制src\com\example\expansion\downloader下的sample文件到游戲目錄下,並對應修改包名的引用等。

    a、將onCreate下的判斷obb文件存在的注釋處理添加如下:

                // otherwise, download not needed so we fall through to
                // starting the movie
                validateXAPKZipFiles();

    b、修改  validateXAPKZipFiles 方法,去除驗證,直接添加解壓方法到對應的游戲下載目錄。

    // 解壓到游戲下載目錄
    private void upzipApkExFile(){
        try {
            
            ZipResourceFile expansionFile = APKExpansionSupport
                    .getAPKExpansionZipFile(this, VERSION_CODE, 0);

            ZipEntryRO[] zip = expansionFile.getAllEntries(); 
             Log.i("upzipApkExFile", "mZipFileName : " + zip[0].mZipFileName); 
             String path  = getApplicationContext().getFilesDir().getAbsolutePath();
            File file = new File(path + "");
            ZipHelper.unzip(zip[0].mZipFileName, file);
            
            if (file.exists()) {
                Log.e("", "unzipped : " + file.getAbsolutePath());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        
    } 
   /**
     * Go through each of the Expansion APK files and open each as a zip file.
     * Calculate the CRC for each file and return false if any fail to match.
     * 
     * @return true if XAPKZipFile is successful
     */
    void validateXAPKZipFiles() { 
        upzipApkExFile();
        Intent myIntent = new Intent(this, AppActivity.class); //跳轉到游戲Activity
        startActivity(myIntent);
        this.finish();
    }

    c、修改SampleDownloaderService文件下的BASE64_PUBLIC_KEY。將其改成對應的Google Play上申請的應用的Key。

 3、添加對應下載接受服務監聽。

<application ...>
    <service android:name="com.test123.expansion.downloader.SampleDownloaderService" />
    <receiver android:name="com.test123.expansion.downloader.SampleAlarmReceiver" />
    ...
</application>

  4、主游戲AppActivity處理。在啟動的Activity中進行判斷,如果已經下載並解壓了文件則進入游戲,否則跳轉到下載的Activity。

    protected void onCreate(final Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        String path  = getApplicationContext().getFilesDir().getAbsolutePath();
        File boolfile = new File(path + "/downloaded");
        if(!boolfile.exists())
        {
            Intent myIntent = new Intent(this, SampleDownloaderActivity.class);
            startActivity(myIntent);
            this.finish();
            return;
        }

        Log.i("upzipApkExFile", "already unziped!!");
  }

  

Cocos2dx處理

  為了讓下載的擴展文件直接應用到游戲中,我們要稍微修改下cocos2dx引擎的讀取文件處理。

首先,找到引擎目錄下cocos2d\cocos\platform\CCFileUtils.cpp文件。

其次,對方法進行如下修改,使其先在getWritablePath目錄下需找文件。

std::string FileUtils::fullPathForFilename(const std::string &filename) const
{
    if (filename.empty())
    {
        return "";
    }

    if (isAbsolutePath(filename))
    {
        return filename;
    }

    // Already Cached ?
    auto cacheIter = _fullPathCache.find(filename);
    if(cacheIter != _fullPathCache.end())
    {
        return cacheIter->second;
    }

    // Get the new file name.
    const std::string newFilename( getNewFilename(filename) );

    std::string fullpathWritablePath = getWritablePath() + newFilename;
    if (isFileExistInternal(fullpathWritablePath))
    {
        if (fullpathWritablePath.length() > 0)
        {
            // Using the filename passed in as key.
            //_fullPathCache.insert(std::make_pair(filename, fullpathWritablePath));
            _fullPathCache[filename] = fullpathWritablePath;
            return fullpathWritablePath;
        }
    }



    std::string fullpath;
    for (const auto& searchIt : _searchPathArray)
    {
        for (const auto& resolutionIt : _searchResolutionsOrderArray)
        {
            fullpath = this->getPathForFilename(newFilename, resolutionIt, searchIt);

            if (fullpath.length() > 0)
            {
                // Using the filename passed in as key.
                _fullPathCache.insert(std::make_pair(filename, fullpath));
                return fullpath;
            }

        }
    }

    if(isPopupNotify()){
        CCLOG("cocos2d: fullPathForFilename: No file found at %s. Possible missing file.", filename.c_str());
    }

    // The file wasn't found, return empty string.
    return "";
}

而這里getWritablePath獲取的目錄正是我們之前解壓obb文件的目錄getApplicationContext().getFilesDir().getAbsolutePath()。

因此,到這里就可以在游戲中跟使用在assert中文件一樣使用obb解壓出來的文件了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM