AndroidObb文件编程中使用详解
Obb
文件是Google
提供的将占存储空间较大的图片资源影音资源等制作成的压缩文件包,Obb
文件可以在上架App
时同时上传。当用户下载App
时,Obb
文件会随之下载,但是也会有不下载的情况,需要自行处理。
1.制作Obb文件
使用Jobb制作Obb文件在Android SDK中, %ANDROID——HOME/tools%
中,在tools/bin
下有jobb
命令:
jobb -d [目录名称的完整路径] -o [输出目标文件的完整路径] -pn [软件包名] -pv [包版本]
EG:
源文件目录 D:contents 目标文件夹: D:\obb\output.obb 软件包名 com.my.test 包版本 1
jobb -d D:\contents -o D:\obb\output.obb -pn com.my.test -pv 1
- 注意:
- jobb -d,-o 需要指定完整路径。如果指定相对路径,
%ANDROID_HOME%/tools/
将作为相对路径 - JOBB工具如果不能输出有一定容量的.obb的文件的话,出现错误提示
- jobb -d,-o 需要指定完整路径。如果指定相对路径,
2.在代码中加入下载和读入Obb文件的逻辑
2.1 下载DownloaderLibrary需要的包
Google提供了一个DownloaderLibrary来下载Obb文件。想使用DownloaderLibrary,现在在Android SDK Manager(Tools > Android > SDK Manager)中下载以下两个包:
- Google Play Licenseing Library package
- Google Play APK Expansion Library package
2.2 将Google Play License Library 与 Google Play Downloader Library导入到项目中
- 在
<sdk>/extras/google/market_licensing
中存放的library对应为GooglePlayLicenseLibrary,将其作为Module导入到项目中 - 在
<sdk>/extras/google/market_apk_expansion
中存放的downloader_library对应为DownloaderLibrary,将其作为module导入到项目中。
注意:
downloader_library在导入时,需要删除downloader_library/project.properties
中的android.library.reference.1=../market_licensing
。当downloader_library导入之后,再将GooglePlayLicenseLibrary作为依赖项,加在downloader_library中。
3 在需要检查Obb文件的地方加入相关逻辑
以在MainActivity中判断为例:
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>
3.2 实现下载服务
自定义下载服务继承自DownloaderService
“`java
public class SampleDownloaderService extends DownloaderService {
// You must use the public key belonging to your publisher account
public static final String BASE64_PUBLIC_KEY = “YourLVLKey”;
// You should also modify this salt
public static final byte[] SALT = new byte[] { 1, 42, -12, -1, 54, 98,
-100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84
};@Override
public String getPublicKey() {
return BASE64_PUBLIC_KEY;
}@Override
public byte[] getSALT() {
return SALT;
}@Override
public String getAlarmReceiverClassName() {
return SampleAlarmReceiver.class.getName();
}
}
* 在Manifest文件中声明服务
```java
<application ...>
<service android:name=".SampleDownloaderService" />
...
</application>
3.3 实现AlarmReceiver
定义AlarmReceiver继承自BroadcastReceiver
“`java
public class SampleAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
DownloaderClientMarshaller.startDownloadServiceIfRequired(context,
intent, SampleDownloaderService.class);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
}
* 在Manifest文件中声明receiver
```java
<application ...>
<receiver android:name=".SampleAlarmReceiver" />
...
</application>
```
### 3.4 判断Obb文件是否已经存在
* 封住装Obb文件信息
```java
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;
}
}
```
* 定义Obb文件
```java
private static final XAPKFile[] xAPKS = {
new XAPKFile(
true, // true signifies a main file
3, // the version of the APK that the file was uploaded
// against
687801613L // the length of the file in bytes
),
new XAPKFile(
false, // false signifies a patch file
4, // the version of the APK that the patch file was uploaded
// against
512860L // the length of the patch file in bytes
)
};
判断Obb文件是否存在
“`java
boolean expansionFilesDelivered() {
for (XAPKFile xf : xAPKS) {
String fileName = Helpers.getExpansionAPKFileName(this, xf.mIsBase,
xf.mFileVersion);
if (!Helpers.doesFileExist(this, fileName, xf.mFileSize, false))
return false;
}
return true;
}
### 3.5 下载Obb文件
```java
// Check if expansion files are available before going any further
if (!expansionFilesDelivered()) {
// Build an Intent to start this activity from the Notification
Intent notifierIntent = new Intent(this, MainActivity.getClass());
notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP);
...
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Start the download service (if required)
int startResult =
DownloaderClientMarshaller.startDownloadServiceIfRequired(this,
pendingIntent, SampleDownloaderService.class);
// If download has started, initialize this activity to show
// download progress
if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
// This is where you do set up to display the download
// progress (next step)
...
return;
} // If the download wasn't necessary, fall through to start the app
}
startApp(); // Expansion files are available, start the app
<div class="se-preview-section-delimiter"></div>
3.6 如果加入Activity状态改变逻辑
@Override
protected void onResume() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.connect(this);
}
super.onResume();
}
@Override
protected void onStop() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.disconnect(this);
}
super.onStop();
}
<div class="se-preview-section-delimiter"></div>
3.7 接收下载进度
定义IDwonloaderService
private IDownloaderService mRemoteService; ... @Override public void onServiceConnected(Messenger m) { mRemoteService = DownloaderServiceMarshaller.CreateProxy(m); mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger()); }
接收下载进度
Activity需要实现IDownloaderClient接口“`java
onDownloadProgress(DownloadProgressInfo progress) {
//todo you can update your progress view
}
* 接收下载状态
Activity需要实现IDownloaderClient接口
```java
onDownloadStateChanged(int newState) {
//todo you can judge whether the obb download service is ok or other states
}
### 3.7 接收下载进度
* 定义IDwonloaderService
```java
private IDownloaderService mRemoteService;
...
@Override
public void onServiceConnected(Messenger m) {
mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
}
```
* 接收下载进度
Activity需要实现IDownloaderClient接口
```java
onDownloadProgress(DownloadProgressInfo progress) {
//todo you can update your progress view
}
接收下载状态
Activity需要实现IDownloaderClient接口onDownloadStateChanged(int newState) { //todo you can judge whether the obb download service is ok or other states }