getAPKExpansionZipFile() returns null

2019-07-12 15:29发布

问题:

Since my game has 100Mb I need to use expansion file. I put below code in the MainActivity in function onCreate()

    ZipResourceFile expansionFile = null;

    try {
        expansionFile = APKExpansionSupport.getAPKExpansionZipFile(getApplicationContext(),2,0);
    } catch (IOException e) {
        e.printStackTrace();
    }

I don't use patch expansion file, just main, so I guess putting 0 as a version is correct. When I log to check if expansionFile was successfully loaded I get null value.

    if(expansionFile == null)
        Gdx.app.log("EXPANSION_FILE", "NULL");
    else
        Gdx.app.log("EXPANSION_FILE", "NOT NULL");

I followed instructions on https://developer.android.com/google/play/expansion-files.html and I put manually main.2.com.my.game.obb file in folder on my Nexus device:

Internal storage\Android\obb\com.my.game\

There are other obb files in Android\obb folder from other games, so this has to be a correct place. Any clues of why it doesn't mount the obb expansion file?

UPDATE

I implemented DownloaderActivity and it downloads expansion file without any problems. It was giving me "Not a zip archive" log message. I found a way to avoid it. I zipped OBB file and uploaded it to Developer Console. It automatically converted into OBB anyway but this time when I downloaded it on my Nexus it no longer gives me null value for ZipResourceFile and it doesn't give me "Not a zip archive" message anymore. But still I can't access files from it since I'm using AssetManager from Libgdx.

I found another way, which I'm testing now.

回答1:

Solution to the problem where getAPKExpansionZipFile() returns null is to not use JOBB tool, but zip all the content and upload it. Google Play will convert it automatically to the OBB.

Complete solution to load images from expansion file:

I created a static variable in my own Game class which is an instance of ZipResourceFile . I made it static, because I wanted to load the expansion file in MainActivity class and use it in my FileHandle class to get images from it. If you find a different way it's up to you. This is how I did it.

public static ZipResourceFile expansionFile;

Then in your MainActivity class load expansion file. I did it in OnCreate() function.

    try {
        GameInfo.expansionFile = APKExpansionSupport.getAPKExpansionZipFile(getBaseContext(),22,0);     
    } catch (IOException e) {
        e.printStackTrace();
    }

Passed values to the function are these:

getAPKExpansionZipFile(Context ctx, int mainVersion, int patchVersion)

mainVersion needs to be exactly the same as declared in Manifest file :

android:versionCode="22"

Also your expansion file needs to have the same number in its name:

main.mainVersion.com.name.title

Create your own FileHandle class. This is where it looks for your specific file for example "image.png" in the expansion file.

public class CustomFileHandle extends FileHandle
{
    public CustomFileHandle (String fileName) {     
        super(fileName);
    }

    @Override
    public InputStream read()
    {
        InputStream input = null;

        try {           
            input = GameInfo.expansionFile.getInputStream(file.getPath().replace('\\', '/'));
        } catch (IOException e) {
            e.printStackTrace();
        }   
        return input;
    }
}

Create your own FileHandleResolver class. This is where you use your custom FileHandle.

public class CustomFileHandleResolver implements FileHandleResolver
{
    @Override
    public FileHandle resolve(String fileName) {
        return new CustomFileHandle(fileName);
    }
}

Create instance of AssetManager and pass your FileHandleResolver to constructor.

assetManager = new AssetManager(new CustomFileHandleResolver());

If I did not omit any step then this is what you need to do to load your files from expansion file. As I mentioned in the begining I found the problem with using JOBB Tool to pack the files into OBB file. It makes getAPKExpansionZipFile() to return null. So I just zipped all the files instead. Look here for more detailed explanation : https://developer.android.com/google/play/expansion-files.html



回答2:

For me it was the expansion file size in bytes. I rezipped and never changed the file size in code. Hence I was getting null value. I was off by only few bytes and that just took my entire day at workplace. Didn't realize it was that important :(

private static final XAPKFile[] xAPKS = {
        new XAPKFile(true, Constants.MAIN_OBB_VERSION, Constants.EXPANSION_FILE_SIZE) // right here expansion file size must match exactly.
};

//in Constants class

public static final int EXPANSION_FILE_SIZE = 285516838; //expansion file size in bytes