Read content from APK expansion file (from obb file)

…衆ロ難τιáo~ 提交于 2019-11-27 04:32:09

问题


I have implemented APK expansion file download service and all from http://developer.android.com/google/play/expansion-files.html

I can download APK expansion file and I can see that file using below code

try {
        ZipResourceFile expansionFile = APKExpansionSupport
                .getAPKExpansionZipFile(this, 3, 0);

        ZipEntryRO[] zip = expansionFile.getAllEntries();
        Log.e("", "" + zip[0].mFile.getAbsolutePath());
        Log.e("", "" + zip[0].mFileName);
        Log.e("", "" + zip[0].mZipFileName);
        Log.e("", "" + zip[0].mCompressedLength);

        AssetFileDescriptor fd = expansionFile
                .getAssetFileDescriptor(zip[0].mFileName);

        if (fd != null && fd.getFileDescriptor() != null) {
            MediaPlayer mp = new MediaPlayer();
            mp.setDataSource(fd.getFileDescriptor());
            mp.start();
        } else {
            Log.e("", "fd or fd.getFileDescriptor() is null");
        }

    } catch (IOException e) {
        e.printStackTrace();
    }

My obb is having file test.mp4 and my code Log.e("", "" + zip[0].mFileName); prints test.mp4.

My fd is null. Why is it null? I am trying to resolve but failed to resolve.

I just can not read any file inside obb file.

Unanswered Accessing to files inside obb expansion file suggesting idea but it does not work for me.

Steps to create APK expansion file tells unzip content from obb and then read it. Is it reliable and good?

I need an opinion on best practice.

Edit

My log

03-01 10:36:40.848: E/(27836): zip[0].isUncompressed() : false
03-01 10:36:40.848: E/(27836): mFile.getAbsolutePath() : /storage/sdcard0/Android/obb/smart.trigger/main.3.smart.trigger.obb
03-01 10:36:40.848: E/(27836): mFileName : test.mp4
03-01 10:36:40.848: E/(27836): mZipFileName : /storage/sdcard0/Android/obb/smart.trigger/main.3.smart.trigger.obb
03-01 10:36:40.848: E/(27836): mCompressedLength : 21657598

回答1:


i have googled and found that we shold have to make .zip with 0% (No compression) that is mention in http://developer.android.com/google/play/expansion-files.html

Tip: If you're packaging media files into a ZIP, you can use media playback calls on the files with offset and length controls (such as MediaPlayer.setDataSource() and SoundPool.load()) without the need to unpack your ZIP. In order for this to work, you must not perform additional compression on the media files when creating the ZIP packages. For example, when using the zip tool, you should use the -n option to specify the file suffixes that should not be compressed: zip -n .mp4;.ogg main_expansion media_files

OR How to make 0% compression zip using winrar?

here see the compression method

0% compression zip in mac

Create zip without compression on OS X from Terminal:
zip -r0 zipfilename.zip files-to-zip

so we should have to upload this zip in play store.

so you not need to use ZipHelper.java

just simply use

ZipResourceFile expansionFile=null;

            try {
                expansionFile = APKExpansionSupport.getAPKExpansionZipFile(getApplicationContext(),3,0);

                     AssetFileDescriptor fd = expansionFile.getAssetFileDescriptor("test.mp4");
                     MediaPlayer mPlayer = new MediaPlayer();
                     mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                     mPlayer.setDataSource(fd.getFileDescriptor(),fd.getStartOffset(),fd.getLength());
                     mPlayer.prepare();
                     mPlayer.start();

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }



回答2:


I have solved using unzipping..

ZipHelper.java

public class ZipHelper {
static boolean zipError = false;

public static boolean isZipError() {
    return zipError;
}

public static void setZipError(boolean zipError) {
    ZipHelper.zipError = zipError;
}

public static void unzip(String archive, File outputDir) {
    try {
        Log.d("control", "ZipHelper.unzip() - File: " + archive);
        ZipFile zipfile = new ZipFile(archive);
        for (Enumeration<? extends ZipEntry> e = zipfile.entries(); e
                .hasMoreElements();) {
            ZipEntry entry = (ZipEntry) e.nextElement();
            unzipEntry(zipfile, entry, outputDir);

        }
    } catch (Exception e) {
        Log.d("control", "ZipHelper.unzip() - Error extracting file "
                + archive + ": " + e);
        setZipError(true);
    }
}

private static void unzipEntry(ZipFile zipfile, ZipEntry entry,
        File outputDir) throws IOException {
    if (entry.isDirectory()) {
        createDirectory(new File(outputDir, entry.getName()));
        return;
    }

    File outputFile = new File(outputDir, entry.getName());
    if (!outputFile.getParentFile().exists()) {
        createDirectory(outputFile.getParentFile());
    }

    Log.d("control", "ZipHelper.unzipEntry() - Extracting: " + entry);
    BufferedInputStream inputStream = new BufferedInputStream(
            zipfile.getInputStream(entry));
    BufferedOutputStream outputStream = new BufferedOutputStream(
            new FileOutputStream(outputFile));

    try {
        IOUtils.copy(inputStream, outputStream);
    } catch (Exception e) {
        Log.d("control", "ZipHelper.unzipEntry() - Error: " + e);
        setZipError(true);
    } finally {
        outputStream.close();
        inputStream.close();
    }
}

private static void createDirectory(File dir) {
    Log.d("control",
            "ZipHelper.createDir() - Creating directory: " + dir.getName());
    if (!dir.exists()) {
        if (!dir.mkdirs())
            throw new RuntimeException("Can't create directory " + dir);
    } else
        Log.d("control",
                "ZipHelper.createDir() - Exists directory: "
                        + dir.getName());
}
}

Usage

try {
        ZipResourceFile expansionFile = APKExpansionSupport
                .getAPKExpansionZipFile(this, 3, 0);

        ZipEntryRO[] zip = expansionFile.getAllEntries();
        Log.e("", "zip[0].isUncompressed() : " + zip[0].isUncompressed());
        Log.e("",
                "mFile.getAbsolutePath() : "
                        + zip[0].mFile.getAbsolutePath());
        Log.e("", "mFileName : " + zip[0].mFileName);
        Log.e("", "mZipFileName : " + zip[0].mZipFileName);
        Log.e("", "mCompressedLength : " + zip[0].mCompressedLength);

        File file = new File(Environment.getExternalStorageDirectory()
                .getAbsolutePath() + "");
        ZipHelper.unzip(zip[0].mZipFileName, file);

        if (file.exists()) {
            Log.e("", "unzipped : " + file.getAbsolutePath());
        }

    } catch (Exception e) {
        e.printStackTrace();
    }



回答3:


Are your files inside a folder in the zip file? I ask because I had the same problem and my solution was to include the folder name when getting the file descriptor.

For instance, my expansion file contained a single folder named "Videos". So to get a file descriptor I had to do this:

AssetFileDescriptor fd = expansionFile.getAssetFileDescriptor("Videos/" + videoName + ".mp4");



回答4:


If you use setDataSource() you are not supposed to compress your files when zipping them in the first place as it says in the docs (http://developer.android.com/google/play/expansion-files.html#ZipLib):

In order for this to work, you must not perform additional compression on the media files when creating the ZIP packages.



来源:https://stackoverflow.com/questions/14495483/read-content-from-apk-expansion-file-from-obb-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!