【发布时间】:2014-08-17 16:23:21
【问题描述】:
我创建了一个使用扩展文件的 Android 应用程序。当扩展文件与 apk 一起下载时,它运行良好。但是如果没有,并且应用程序需要下载扩展包本身,它就会变得复杂。
DownloadService.java - 我在这里从 Developer Console 复制了 *Base64 编码的 RSA 公钥,并将完全随机的字节插入到 SALT(我自己编造的)。
public class DownloadService extends DownloaderService {
// TODO You must use the public key belonging to your publisher account
public static final String BASE64_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl0rC8XLNwlpDn0Ezc7LBF08eds9VLvbT6Bbl3B7h6uSqa703HXEv44LLBLAmBz2QM2iwzrf3WH7Tjp80II9rQxaVsUIukBHtnE5r9CBHn/pQl4OkZplmI3/Fvl2WPWyvXqVi2BungmW29FBqIWVQED0UepT1eXVr8X8sPAhcDwfI2WERIWHzm32oiz/a2dpMBs1DA/ERO1kWgtDKJuwjik9tHTeo2xfRBC+ytZQ5jqKFlmLqlDXpcDCUXVXhV2idtujV9cPD1PdEgElPTbqro7LQdrsMm4hn0olPK2Iy6hhdzO/Tll/viH03GtUkMOjpFA+OAVsA+b+oM1MfHiHTbwIDAQAB";
// TODO You should also modify this salt
public static final byte[] SALT = new byte[] { 7, 23, -47, -8, 24, 72,
-28, -83, 47, 1, -12, -8, 28, 3, -101, -109, -20, 47, -2, 92
};
@Override
public String getPublicKey() {
return BASE64_PUBLIC_KEY;
}
@Override
public String getAlarmReceiverClassName() {
return BroadCastReceiver.class.getName();
}
@Override
public byte[] getSALT() {
return SALT;
}
}
BroadcastReceiver.java
public class BroadCastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent, DownloadService.class);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}
SplashActity.java - 以应用程序开头的第一个活动,这里是我实现下载过程的地方
public class SplashActivity extends Activity implements IDownloaderClient {
int SPLASH_DURATION = 2000;
TextView title1, title2, loading;
// APK EXPANSIONS
private IStub mDownloaderClientStub;
private IDownloaderService mRemoteService;
private ProgressDialog mProgressDialog;
private static final String LOG_TAG = "LOG";
// The shared path to all app expansion files
private final static String EXP_PATH = "/Android/obb/";
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;
}
}
private static final XAPKFile[] xAPKS = {
new XAPKFile(
true, // true signifies a main file
2, // the version of the APK that the file was uploaded against
52948873L // the length of the file in bytes
)
};
boolean expansionFilesDelivered() {
for (XAPKFile xf : xAPKS) {
String fileName = Helpers.getExpansionAPKFileName(this, xf.mIsMain, xf.mFileVersion);
// Log.v(LOG_TAG, "XAPKFile name : " + fileName);
if (!Helpers.doesFileExist(this, fileName, xf.mFileSize, false)) {
Log.e(LOG_TAG, "ExpansionAPKFile doesn't exist or has a wrong size (" + fileName + ").");
return false;
}
}
return true;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
// Views
title1 = (TextView) findViewById(R.id.textView2);
title2 = (TextView) findViewById(R.id.textView3);
loading = (TextView) findViewById(R.id.textView);
// Font
Typeface tf = Typeface.createFromAsset(getApplicationContext().getAssets(), "aressence.ttf");
title1.setTypeface(tf);
title2.setTypeface(tf);
loading.setTypeface(tf);
// Check if expansion files are available before going any further
if (!expansionFilesDelivered()) {
try {
Intent launchIntent = this.getIntent();
// Build an Intent to start this activity from the Notification
Intent notifierIntent = new Intent(SplashActivity.this, SplashActivity.this.getClass());
notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
notifierIntent.setAction(launchIntent.getAction());
if (launchIntent.getCategories() != null) {
for (String category : launchIntent.getCategories()) {
notifierIntent.addCategory(category);
}
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Start the download service (if required)
Log.v(LOG_TAG, "Start the download service");
int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this, pendingIntent, DownloadService.class);
// If download has started, initialize activity to show progress
if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
Log.v(LOG_TAG, "initialize activity to show progress");
// Instantiate a member instance of IStub
mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this, DownloadService.class);
// Shows download progress
mProgressDialog = new ProgressDialog(SplashActivity.this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setMessage(getResources().getString(R.string.state_downloading));
mProgressDialog.setCancelable(false);
mProgressDialog.show();
return;
}
// If the download wasn't necessary, fall through to start the app
else {
Log.v(LOG_TAG, "No download required");
}
}
catch (PackageManager.NameNotFoundException e) {
Log.e(LOG_TAG, "Cannot find own package! MAYDAY!");
e.printStackTrace();
}
catch (Exception e) {
Log.e(LOG_TAG, e.getMessage());
e.printStackTrace();
}
}
else
{
// 2sec handler
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
startActivity(new Intent(SplashActivity.this, MainActivity.class));
finish();
}
}, SPLASH_DURATION);
}
// Set by <content src="index.html" /> in config.xml
//super.loadUrl(Config.getStartUrl());
//super.loadUrl("file:///android_asset/www/index.html")
}
@Override
protected void onStart() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.connect(this);
}
super.onStart();
}
@Override
protected void onResume() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.connect(this);
}
super.onResume();
}
@Override
protected void onStop() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.disconnect(this);
}
super.onStop();
}
@Override
public void onServiceConnected(Messenger m) {
mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
}
@Override
public void onDownloadStateChanged(int newState) {
Log.v(LOG_TAG, "DownloadStateChanged : " + getString(Helpers.getDownloaderStringResourceIDFromState(newState)));
switch (newState) {
case STATE_DOWNLOADING:
Log.v(LOG_TAG, "Downloading...");
break;
case STATE_COMPLETED: // The download was finished
// validateXAPKZipFiles();
mProgressDialog.setMessage("");
// dismiss progress dialog
mProgressDialog.dismiss();
// Load url
//super.loadUrl(Config.getStartUrl());
break;
case STATE_FAILED_UNLICENSED:
case STATE_FAILED_FETCHING_URL:
case STATE_FAILED_SDCARD_FULL:
case STATE_FAILED_CANCELED:
case STATE_FAILED:
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("error");
alert.setMessage("download failed");
alert.setNeutralButton("close", null);
alert.show();
break;
}
}
@Override
public void onDownloadProgress(DownloadProgressInfo progress) {
long percents = progress.mOverallProgress * 100 / progress.mOverallTotal;
Log.v(LOG_TAG, "DownloadProgress:"+Long.toString(percents) + "%");
mProgressDialog.setProgress((int) percents);
}
}
在应用尝试下载扩展文件后,我发现这与 LogCat 中的许可有关。
08-19 23:39:16.641 25920-25920/com.mhacinapps.sleepwithnaturesounds I/LicenseChecker﹕ Binding to licensing service.
08-19 23:39:16.758 25920-25920/com.mhacinapps.sleepwithnaturesounds I/LicenseChecker﹕ Calling checkLicense on service for com.mhacinapps.sleepwithnaturesounds
08-19 23:39:16.758 25920-25920/com.mhacinapps.sleepwithnaturesounds I/LicenseChecker﹕ Start monitoring timeout.
08-19 23:39:26.766 25920-25939/com.mhacinapps.sleepwithnaturesounds I/LicenseChecker﹕ Check timed out.
当设备上没有扩展文件时,下载栏在 0/100 几秒钟,然后它说它没有找到资源并且下载失败。
有人可以帮助我,让我知道我哪里出错了吗?
谢谢!
【问题讨论】:
-
遗憾的是,这无济于事。这家伙的问题是它无法识别他设备上的 obb 文件。如果我的设备上有 obb 文件,一切正常。只是下载部分是问题。
-
在添加此功能时,您是否确保对清单文件进行了所有必要的更改?另外,当您在设备上安装应用程序时,您是通过 Google Play 进行的吗?
标签: android apk-expansion-files