0%

Android - obb拓展文件

Opaque Binary Blob,简称obb,为apk的拓展文件,下载的资源可以是视频,图片,资源等,常见于VR或者游戏中使用。

拓展文件大小不能超过2GB,格式可以是任意格式,可压缩,最多可以添加1-2个拓展文件。从概念上讲,每个拓展文件扮演者不同的角色

  • 主扩展(main):应用必须的额外资源
  • 布丁扩展:用于更新

https://developer.android.com/google/play/expansion-files

文件格式

用户上传的文件,最终会被更改为oob格式

[main|patch].versionCode.packageName.obb

举例:main.314159.com.example.app.obb

存储位置

api:getObbDir()

实际位置:/sdcard/Android/obb//

下载

下载library

复制下载的资源到我们项目

market_apk_expansion/downloader_library:下载资源

market_apk_expansion/zip_file: zip操作

market_licensing/library:licensing

  • 下载服务

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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();
    }
    }
  • 实施警报接收程序

1
2
3
4
5
6
7
8
9
10
11
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();
}
}
}
  • 下载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Override
public void onCreate(Bundle savedInstanceState) {
// 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
}


boolean expansionFilesDelivered() {
for (XAPKFile xf : xAPKS) {
String fileName = Helpers.getExpansionAPKFileName(this, xf.isBase,
xf.fileVersion);
if (!Helpers.doesFileExist(this, fileName, xf.fileSize, false))
return false;
}
return true;
}
  • 读取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// The shared path to all app expansion files
private final static String EXP_PATH = "/Android/obb/";

static String[] getAPKExpansionFiles(Context ctx, int mainVersion,
int patchVersion) {
String packageName = ctx.getPackageName();
Vector<String> ret = new Vector<String>();
if (Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED)) {
// Build the full path to the app's expansion files
File root = Environment.getExternalStorageDirectory();
File expPath = new File(root.toString() + EXP_PATH + packageName);

// Check that expansion file path exists
if (expPath.exists()) {
if ( mainVersion > 0 ) {
String strMainPath = expPath + File.separator + "main." +
mainVersion + "." + packageName + ".obb";
File main = new File(strMainPath);
if ( main.isFile() ) {
ret.add(strMainPath);
}
}
if ( patchVersion > 0 ) {
String strPatchPath = expPath + File.separator + "patch." +
mainVersion + "." + packageName + ".obb";
File main = new File(strPatchPath);
if ( main.isFile() ) {
ret.add(strPatchPath);
}
}
}
}
String[] retArray = new String[ret.size()];
ret.toArray(retArray);
return retArray;
}
  • zip读取,上面zip_file中api
1
2
3
4
5
6
7
// Get a ZipResourceFile representing a merger of both the main and patch files
ZipResourceFile expansionFile =
APKExpansionSupport.getAPKExpansionZipFile(appContext,
mainVersion, patchVersion);

// Get an input stream for a known file inside the expansion file ZIPs
InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);

测试

打包(jobb命令 )

参考:https://developer.android.com/studio/command-line/jobb

测试

可以手动复制到/sdcard/Android/obb/{package}目录运行测试