我想提取包含.zim文件zip文件的.obb文件内容,并希望将这些文件解压缩到我的SD卡中。我怎么能这样做我用java helperclass尝试了以下方法? 这是对的吗?
public class MainActivity extends Activity implements IDownloaderClient {
private static final String LOG_TAG = "LVLDownloader";
private ProgressBar mPB;
private TextView mStatusText;
private TextView mProgressFraction;
private TextView mProgressPercent;
private TextView mAverageSpeed;
private TextView mTimeRemaining;
private View mDashboard;
private View mCellMessage;
private Button mPauseButton;
private Button mWiFiSettingsButton;
private boolean mStatePaused;
private int mState;
private IDownloaderService mRemoteService;
private IStub mDownloaderClientStub;
private void setState(int newState) {
if (mState != newState) {
mState = newState;
mStatusText.setText(Helpers.getDownloaderStringResourceIDFromState(newState));
}
}
private void setButtonPausedState(boolean paused) {
mStatePaused = paused;
int stringResourceID = paused ? R.string.text_button_resume :
R.string.text_button_pause;
mPauseButton.setText(stringResourceID);
}
/**
* This is a little helper class that demonstrates simple testing of an
* Expansion APK file delivered by Market. You may not wish to hard-code
* things such as file lengths into your executable... and you may wish to
* turn this code off during application development.
*/
private static class XAPKFile {
public final boolean mIsMain;
public final int mFileVersion;
public final long mFileSize;
XAPKFile(boolean isMain, int fileVersion, long fileSize) {
mIsMain = isMain;
mFileVersion = fileVersion;
mFileSize = fileSize;
}
}
/**
* Here is where you place the data that the validator will use to determine
* if the file was delivered correctly. This is encoded in the source code
* so the application can easily determine whether the file has been
* properly delivered without having to talk to the server. If the
* application is using LVL for licensing, it may make sense to eliminate
* these checks and to just rely on the server.
*/
private static final XAPKFile[] xAPKS = {
new XAPKFile(
true, // true signifies a main file
4, // the version of the APK that the file was uploaded
// against
240000L // the length of the file in bytes
),
new XAPKFile(
true, // false signifies a patch file
3, // the version of the APK that the patch file was uploaded
// against
24000L // the length of the patch file in bytes
)
};
/**
* Go through each of the APK Expansion files defined in the structure above
* and determine if the files are present and match the required size. Free
* applications should definitely consider doing this, as this allows the
* application to be launched for the first time without having a network
* connection present. Paid applications that use LVL should probably do at
* least one LVL check that requires the network to be present, so this is
* not as necessary.
*
* @return true if they are present.
*/
boolean expansionFilesDelivered() {
for (XAPKFile xf : xAPKS) {
String fileName = Helpers.getExpansionAPKFileName(this, xf.mIsMain, xf.mFileVersion);
if (!Helpers.doesFileExist(this, fileName, xf.mFileSize, false))
return false;
}
return true;
}
/**
* Calculating a moving average for the validation speed so we don't get
* jumpy calculations for time etc.
*/
static private final float SMOOTHING_FACTOR = 0.005f;
/**
* Used by the async task
*/
private boolean mCancelValidation;
/**
* 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() {
AsyncTask<Object, DownloadProgressInfo, Boolean> validationTask = new AsyncTask<Object, DownloadProgressInfo, Boolean>() {
@Override
protected void onPreExecute() {
mDashboard.setVisibility(View.VISIBLE);
mCellMessage.setVisibility(View.GONE);
mStatusText.setText(R.string.text_verifying_download);
mPauseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCancelValidation = true;
}
});
mPauseButton.setText(R.string.text_button_cancel_verify);
super.onPreExecute();
}
@Override
protected Boolean doInBackground(Object... params) {
for (XAPKFile xf : xAPKS) {
String fileName = Helpers.getExpansionAPKFileName(
MainActivity.this,
xf.mIsMain, xf.mFileVersion);
if (!Helpers.doesFileExist(MainActivity.this, fileName,
xf.mFileSize, false))
return false;
fileName = Helpers
.generateSaveFileName(MainActivity.this, fileName);
ZipResourceFile zrf;
byte[] buf = new byte[1024 * 256];
try {
zrf = new ZipResourceFile(fileName);
ZipEntryRO[] entries = zrf.getAllEntries();
/**
* First calculate the total compressed length
*/
long totalCompressedLength = 0;
for (ZipEntryRO entry : entries) {
totalCompressedLength += entry.mCompressedLength;
}
float averageVerifySpeed = 0;
long totalBytesRemaining = totalCompressedLength;
long timeRemaining;
/**
* Then calculate a CRC for every file in the Zip file,
* comparing it to what is stored in the Zip directory.
* Note that for compressed Zip files we must extract
* the contents to do this comparison.
*/
for (ZipEntryRO entry : entries) {
if (-1 != entry.mCRC32) {
long length = entry.mUncompressedLength;
CRC32 crc = new CRC32();
DataInputStream dis = null;
try {
dis = new DataInputStream(
zrf.getInputStream(entry.mFileName));
long startTime = SystemClock.uptimeMillis();
while (length > 0) {
int seek = (int) (length > buf.length ? buf.length
: length);
dis.readFully(buf, 0, seek);
crc.update(buf, 0, seek);
length -= seek;
long currentTime = SystemClock.uptimeMillis();
long timePassed = currentTime - startTime;
if (timePassed > 0) {
float currentSpeedSample = (float) seek
/ (float) timePassed;
if (0 != averageVerifySpeed) {
averageVerifySpeed = SMOOTHING_FACTOR
* currentSpeedSample
+ (1 - SMOOTHING_FACTOR)
* averageVerifySpeed;
} else {
averageVerifySpeed = currentSpeedSample;
}
totalBytesRemaining -= seek;
timeRemaining = (long) (totalBytesRemaining / averageVerifySpeed);
this.publishProgress(
new DownloadProgressInfo(
totalCompressedLength,
totalCompressedLength
- totalBytesRemaining,
timeRemaining,
averageVerifySpeed)
);
}
startTime = currentTime;
if (mCancelValidation)
return true;
}
if (crc.getValue() != entry.mCRC32) {
Log.e(Constants.TAG,
"CRC does not match for entry: "
+ entry.mFileName);
Log.e(Constants.TAG,
"In file: " + entry.getZipFileName());
return false;
}
} finally {
if (null != dis) {
dis.close();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
return true;
}
@Override
protected void onProgressUpdate(DownloadProgressInfo... values) {
onDownloadProgress(values[0]);
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(Boolean result) {
if (result) {
mDashboard.setVisibility(View.VISIBLE);
mCellMessage.setVisibility(View.GONE);
mStatusText.setText(R.string.text_validation_complete);
mPauseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
mPauseButton.setText(android.R.string.ok);
} else {
mDashboard.setVisibility(View.VISIBLE);
mCellMessage.setVisibility(View.GONE);
mStatusText.setText(R.string.text_validation_failed);
mPauseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
mPauseButton.setText(android.R.string.cancel);
}
super.onPostExecute(result);
}
};
validationTask.execute(new Object());
}
/**
* If the download isn't present, we initialize the download UI. This ties
* all of the controls into the remote service calls.
*/
private void initializeDownloadUI() {
mDownloaderClientStub = DownloaderClientMarshaller.CreateStub
(this, ExpansionFileDownloaderService.class);
setContentView(R.layout.activity_main);
mPB = (ProgressBar) findViewById(R.id.progressBar);
mStatusText = (TextView) findViewById(R.id.statusText);
mProgressFraction = (TextView) findViewById(R.id.progressAsFraction);
mProgressPercent = (TextView) findViewById(R.id.progressAsPercentage);
mAverageSpeed = (TextView) findViewById(R.id.progressAverageSpeed);
mTimeRemaining = (TextView) findViewById(R.id.progressTimeRemaining);
mDashboard = findViewById(R.id.downloaderDashboard);
mCellMessage = findViewById(R.id.approveCellular);
mPauseButton = (Button) findViewById(R.id.pauseButton);
mWiFiSettingsButton = (Button) findViewById(R.id.wifiSettingsButton);
mPauseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mStatePaused) {
mRemoteService.requestContinueDownload();
} else {
mRemoteService.requestPauseDownload();
}
setButtonPausedState(!mStatePaused);
}
});
mWiFiSettingsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
}
});
Button resumeOnCell = (Button) findViewById(R.id.resumeOverCellular);
resumeOnCell.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mRemoteService.setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR);
mRemoteService.requestContinueDownload();
mCellMessage.setVisibility(View.GONE);
}
});
}
/**
* Called when the activity is first create; we wouldn't create a layout in
* the case where we have the file and are moving to another activity
* without downloading.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* Both downloading and validation make use of the "download" UI
*/
initializeDownloadUI();
/**
* Before we do anything, are the files we expect already here and
* delivered (presumably by Market) For free titles, this is probably
* worth doing. (so no Market request is necessary)
*/
if (!expansionFilesDelivered()) {
try {
Intent launchIntent = MainActivity.this
.getIntent();
Intent intentToLaunchThisActivityFromNotification = new Intent(
MainActivity
.this, MainActivity.this.getClass());
intentToLaunchThisActivityFromNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentToLaunchThisActivityFromNotification.setAction(launchIntent.getAction());
if (launchIntent.getCategories() != null) {
for (String category : launchIntent.getCategories()) {
intentToLaunchThisActivityFromNotification.addCategory(category);
}
}
// Build PendingIntent used to open this activity from
// Notification
PendingIntent pendingIntent = PendingIntent.getActivity(
MainActivity.this,
0, intentToLaunchThisActivityFromNotification,
PendingIntent.FLAG_UPDATE_CURRENT);
// Request to start the download
int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this,
pendingIntent, ExpansionFileDownloaderService.class);
if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
// The DownloaderService has started downloading the files,
// show progress
initializeDownloadUI();
return;
} // otherwise, download not needed so we fall through to
// starting the movie
} catch (NameNotFoundException e) {
Log.e(LOG_TAG, "Cannot find own package! MAYDAY!");
e.printStackTrace();
}
} else {
validateXAPKZipFiles();
}
}
/**
* Connect the stub to our service on start.
*/
@Override
protected void onStart() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.connect(this);
}
super.onStart();
}
/**
* Disconnect the stub from our service on stop
*/
@Override
protected void onStop() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.disconnect(this);
}
super.onStop();
}
/**
* Critical implementation detail. In onServiceConnected we create the
* remote service and marshaler. This is how we pass the client information
* back to the service so the client can be properly notified of changes. We
* must do this every time we reconnect to the service.
*/
@Override
public void onServiceConnected(Messenger m) {
mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
}
/**
* The download state should trigger changes in the UI --- it may be useful
* to show the state as being indeterminate at times. This sample can be
* considered a guideline.
*/
@Override
public void onDownloadStateChanged(int newState) {
setState(newState);
boolean showDashboard = true;
boolean showCellMessage = false;
boolean paused;
boolean indeterminate;
switch (newState) {
case IDownloaderClient.STATE_IDLE:
// STATE_IDLE means the service is listening, so it's
// safe to start making calls via mRemoteService.
paused = false;
indeterminate = true;
break;
case IDownloaderClient.STATE_CONNECTING:
case IDownloaderClient.STATE_FETCHING_URL:
showDashboard = true;
paused = false;
indeterminate = true;
break;
case IDownloaderClient.STATE_DOWNLOADING:
paused = false;
showDashboard = true;
indeterminate = false;
break;
case IDownloaderClient.STATE_FAILED_CANCELED:
case IDownloaderClient.STATE_FAILED:
case IDownloaderClient.STATE_FAILED_FETCHING_URL:
case IDownloaderClient.STATE_FAILED_UNLICENSED:
paused = true;
showDashboard = false;
indeterminate = false;
break;
case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION:
case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION:
showDashboard = false;
paused = true;
indeterminate = false;
showCellMessage = true;
break;
case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
paused = true;
indeterminate = false;
break;
case IDownloaderClient.STATE_PAUSED_ROAMING:
case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE:
paused = true;
indeterminate = false;
break;
case IDownloaderClient.STATE_COMPLETED:
showDashboard = false;
paused = false;
indeterminate = false;
validateXAPKZipFiles();
return;
default:
paused = true;
indeterminate = true;
showDashboard = true;
}
int newDashboardVisibility = showDashboard ? View.VISIBLE : View.GONE;
if (mDashboard.getVisibility() != newDashboardVisibility) {
mDashboard.setVisibility(newDashboardVisibility);
}
int cellMessageVisibility = showCellMessage ? View.VISIBLE : View.GONE;
if (mCellMessage.getVisibility() != cellMessageVisibility) {
mCellMessage.setVisibility(cellMessageVisibility);
}
mPB.setIndeterminate(indeterminate);
setButtonPausedState(paused);
}
/**
* Sets the state of the various controls based on the progressinfo object
* sent from the downloader service.
*/
@Override
public void onDownloadProgress(DownloadProgressInfo progress) {
mAverageSpeed.setText(getString(R.string.kilobytes_per_second,
Helpers.getSpeedString(progress.mCurrentSpeed)));
mTimeRemaining.setText(getString(R.string.time_remaining,
Helpers.getTimeRemaining(progress.mTimeRemaining)));
progress.mOverallTotal = progress.mOverallTotal;
mPB.setMax((int) (progress.mOverallTotal >> 8));
mPB.setProgress((int) (progress.mOverallProgress >> 8));
mProgressPercent.setText(Long.toString(progress.mOverallProgress
* 100 /
progress.mOverallTotal) + "%");
mProgressFraction.setText(Helpers.getDownloadProgressString
(progress.mOverallProgress,
progress.mOverallTotal));
try {
ZipResourceFile expansionFile = APKExpansionSupport
.getAPKExpansionZipFile(this, 4, 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();
}
}
@Override
protected void onDestroy() {
this.mCancelValidation = true;
super.onDestroy();
}
}
答案 0 :(得分:1)
使用此帮助程序类解压缩obb
package com.example.dummy;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import android.util.Log;
public class ZipHelper
{
boolean zipError=false;
public boolean isZipError() {
return zipError;
}
public void setZipError(boolean zipError) {
this.zipError = zipError;
}
public void unzip(String archive, File outputDir)
{
try {
ZipFile zipfile = new ZipFile(archive);
//AvazAppActivity.printLog("TOTAL ZIP ENTRIES",zipfile.size()+":");
for (Enumeration e = zipfile.entries(); e.hasMoreElements(); ) {
ZipEntry entry = (ZipEntry) e.nextElement();
unzipEntry(zipfile, entry, outputDir);
}
}
catch (Exception e) {
setZipError(true);
}
}
private 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());
}
//AvazAppActivity.printLog("control","ZipHelper.unzipEntry() - Extracting: " + entry);
BufferedInputStream inputStream = new BufferedInputStream(zipfile.getInputStream(entry));
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
try {
copy(inputStream, outputStream);
}
catch (Exception e) {
setZipError(true);
}
finally {
outputStream.close();
inputStream.close();
}
}
private void createDirectory(File dir)
{
if (!dir.exists()){
if(!dir.mkdirs()) throw new RuntimeException("Can't create directory "+dir);
}
else
Log.d("control","ZipHelper.createDir() - Exists directory: "+dir.getName());
}
private void copy(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
}
在您的课程中解压缩obb使用下面的代码段。
ZipHelper helper = new ZipHelper();
File file = new File("/sdcard/Android/data/"+PACKAGE_NAME+"/");
helper.unzip("/sdcard/Android/obb/"+PACKAGE_NAME+"/main."+ versionCode + "."+PACKAGE_NAME+".obb", file);
此代码将提取数据文件夹中的obb内容。
答案 1 :(得分:1)
try {
ZipResourceFile expansionFile = APKExpansionSupport
.getAPKExpansionZipFile(this, 4, 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();
}
}
@Override
protected void onDestroy() {
this.mCancelValidation = true;
super.onDestroy();
}
并使用java helper类。
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());
}
}