diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 892b0db323..ab8ad51523 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -33,7 +33,7 @@ LOCAL_SRC_FILES := \ com/mapswithme/maps/MWMActivity.cpp \ com/mapswithme/maps/MWMApplication.cpp \ com/mapswithme/maps/Lifecycle.cpp \ - com/mapswithme/maps/CopyResourcesActivity.cpp \ + com/mapswithme/maps/DownloadResourcesActivity.cpp \ com/mapswithme/platform/Platform.cpp \ com/mapswithme/platform/HttpThread.cpp \ com/mapswithme/platform/Language.cpp \ diff --git a/android/jni/com/mapswithme/maps/CopyResourcesActivity.cpp b/android/jni/com/mapswithme/maps/CopyResourcesActivity.cpp deleted file mode 100644 index 16b3fce11b..0000000000 --- a/android/jni/com/mapswithme/maps/CopyResourcesActivity.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include -// To get free disk space -#include - -#include "../../../../../defines.hpp" - -#include "../../../../../base/logging.hpp" - -#include "../../../../../coding/zip_reader.hpp" - -#include "../../../../../platform/platform.hpp" - -#include "../../../../../std/vector.hpp" -#include "../../../../../std/string.hpp" -#include "../../../../../std/bind.hpp" - -// Special error codes to notify GUI about free space -//@{ -#define ERR_COPIED_SUCCESSFULLY 0 -#define ERR_NOT_ENOUGH_MEMORY -1 -#define ERR_NOT_ENOUGH_FREE_SPACE -2 -#define ERR_STORAGE_DISCONNECTED -3 -//@} - -struct FileToCopy -{ - string m_pathInZip; - string m_pathInSdcard; - uint64_t m_uncompressedSize; -}; - -static string g_apkPath; -static string g_sdcardPath; -static vector g_filesToCopy; -static jint g_copiedBytesProgress = 0; - -extern "C" -{ - JNIEXPORT jint JNICALL - Java_com_mapswithme_maps_CopyResourcesActivity_nativeGetBytesToCopy(JNIEnv * env, jobject thiz, - jstring apkPath, jstring sdcardPath) - { - { - char const * strApkPath = env->GetStringUTFChars(apkPath, 0); - if (!strApkPath) - return ERR_NOT_ENOUGH_MEMORY; - g_apkPath = strApkPath; - env->ReleaseStringUTFChars(apkPath, strApkPath); - - char const * strSdcardPath = env->GetStringUTFChars(sdcardPath, 0); - if (!strSdcardPath) - return ERR_NOT_ENOUGH_MEMORY; - g_sdcardPath = strSdcardPath; - env->ReleaseStringUTFChars(sdcardPath, strSdcardPath); - } - - jint totalSizeToCopy = 0; - Platform::FilesList zipFiles = ZipFileReader::FilesList(g_apkPath); - // Check which assets/* files are compressed and copy only these files - string const ASSETS_PREFIX = "assets/"; - for (Platform::FilesList::iterator it = zipFiles.begin(); it != zipFiles.end(); ++it) - { - // Ignore non-assets files - if (it->find(ASSETS_PREFIX) != 0) - continue; - - uint64_t compressed, uncompressed; - { - ZipFileReader fileInZip(g_apkPath, *it); - compressed = fileInZip.Size(); - uncompressed = fileInZip.UncompressedSize(); - // Skip files which are not compressed inside zip - if (compressed == uncompressed) - continue; - } - - FileToCopy f; - f.m_pathInSdcard = g_sdcardPath + it->substr(ASSETS_PREFIX.size()); - - uint64_t realSizeInSdcard = 0; - Platform::GetFileSizeByFullPath(f.m_pathInSdcard, realSizeInSdcard); - if (uncompressed != realSizeInSdcard) - { - f.m_pathInZip = *it; - f.m_uncompressedSize = uncompressed; - g_filesToCopy.push_back(f); - totalSizeToCopy += uncompressed; - } - } - - return totalSizeToCopy; - } - - void CopyFileProgress(JNIEnv * env, jobject obj, jmethodID method, int size, int pos) - { - env->CallVoidMethod(obj, method, size, pos); - } - - JNIEXPORT jint JNICALL - Java_com_mapswithme_maps_CopyResourcesActivity_nativeCopyNextFile(JNIEnv * env, - jobject thiz, jobject observer) - { - if (g_filesToCopy.empty()) - return ERR_COPIED_SUCCESSFULLY; - - vector::iterator it = g_filesToCopy.begin() + g_filesToCopy.size() - 1; - // Check for free space available on the device - struct statfs st; - if (statfs(g_sdcardPath.c_str(), &st) != 0) - { - LOG(LWARNING, ("External filesystem is not available")); - return ERR_STORAGE_DISCONNECTED; - } - if (st.f_bsize * st.f_bavail <= it->m_uncompressedSize) - { - LOG(LERROR, ("Not enough free space to extract file", it->m_pathInSdcard)); - return ERR_NOT_ENOUGH_FREE_SPACE; - } - - jmethodID method = env->GetMethodID(env->GetObjectClass(observer), "onFileProgress", "(II)V"); - CHECK(method, ("Not existing method: void onFileProgress(int,int)")); - - // Perform copying - try - { - ZipFileReader::UnzipFile(g_apkPath, it->m_pathInZip, it->m_pathInSdcard, - bind(CopyFileProgress, env, observer, method, _1, _2)); - } - catch (std::exception const & e) - { - LOG(LERROR, ("Error while extracting", it->m_pathInZip, "from apk to", it->m_pathInSdcard)); - return ERR_NOT_ENOUGH_FREE_SPACE; - } - - g_copiedBytesProgress += it->m_uncompressedSize; - g_filesToCopy.erase(it); - return g_copiedBytesProgress; - } - - // Move downloaded maps from /sdcard/Android/data/com.mapswithme.maps/files/ to /sdcard/MapsWithMe - JNIEXPORT void JNICALL - Java_com_mapswithme_maps_CopyResourcesActivity_nativeMoveMaps(JNIEnv * env, jobject thiz, - jstring fromPath, jstring toPath) - { - string from, to; - { - char const * strFrom = env->GetStringUTFChars(fromPath, 0); - if (!strFrom) - return; - from = strFrom; - env->ReleaseStringUTFChars(fromPath, strFrom); - - char const * strTo = env->GetStringUTFChars(toPath, 0); - if (!strTo) - return; - to = strTo; - env->ReleaseStringUTFChars(toPath, strTo); - } - - Platform & pl = GetPlatform(); - Platform::FilesList files; - // Move *.mwm files - pl.GetFilesInDir(from, "*" DATA_FILE_EXTENSION, files); - for (size_t i = 0; i < files.size(); ++i) - { - LOG(LINFO, (from + files[i], to + files[i])); - rename((from + files[i]).c_str(), (to + files[i]).c_str()); - } - - // Delete not finished *.downloading files - files.clear(); - pl.GetFilesInDir(from, "*" DOWNLOADING_FILE_EXTENSION, files); - pl.GetFilesInDir(from, "*" RESUME_FILE_EXTENSION, files); - for (size_t i = 0; i < files.size(); ++i) - remove((from + files[i]).c_str()); - } -} diff --git a/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp b/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp new file mode 100644 index 0000000000..ca79de45c0 --- /dev/null +++ b/android/jni/com/mapswithme/maps/DownloadResourcesActivity.cpp @@ -0,0 +1,296 @@ +#include +// To get free disk space +#include + +#include "../../../../../defines.hpp" + +#include "../../../../../platform/http_request.hpp" + +#include "../../../../../base/logging.hpp" +#include "../../../../../base/string_utils.hpp" + +#include "../../../../../coding/zip_reader.hpp" +#include "../../../../../coding/url_encode.hpp" + +#include "../../../../../platform/platform.hpp" +#include "../../../../../platform/http_request.hpp" + +#include "../../../../../std/vector.hpp" +#include "../../../../../std/string.hpp" +#include "../../../../../std/bind.hpp" + +#include "../core/jni_helper.hpp" + +#include "Framework.hpp" + + +// Special error codes to notify GUI about free space +//@{ +#define ERR_DOWNLOAD_SUCCESS 0 +#define ERR_NOT_ENOUGH_MEMORY -1 +#define ERR_NOT_ENOUGH_FREE_SPACE -2 +#define ERR_STORAGE_DISCONNECTED -3 +#define ERR_DOWNLOAD_ERROR -4 +#define ERR_NO_MORE_FILES -5 +#define ERR_FILE_IN_PROGRESS -6 +//@} + +struct FileToDownload +{ + vector m_urls; + string m_fileName; + string m_pathOnSdcard; + uint64_t m_fileSize; +}; + +static string g_apkPath; +static string g_sdcardPath; +static vector g_filesToDownload; +static int g_totalDownloadedBytes; +static int g_totalBytesToDownload; + +extern "C" +{ + int HasSpaceForFiles(size_t fileSize) + { + struct statfs st; + + if (statfs(g_sdcardPath.c_str(), &st) != 0) + return ERR_STORAGE_DISCONNECTED; + + if (st.f_bsize * st.f_bavail <= fileSize) + return ERR_NOT_ENOUGH_FREE_SPACE; + + return fileSize; + } + + JNIEXPORT jint JNICALL + Java_com_mapswithme_maps_DownloadResourcesActivity_nativeGetBytesToDownload(JNIEnv * env, jobject thiz, + jstring apkPath, jstring sdcardPath) + { + { + char const * strApkPath = env->GetStringUTFChars(apkPath, 0); + if (!strApkPath) + return ERR_NOT_ENOUGH_MEMORY; + g_apkPath = strApkPath; + env->ReleaseStringUTFChars(apkPath, strApkPath); + + char const * strSdcardPath = env->GetStringUTFChars(sdcardPath, 0); + if (!strSdcardPath) + return ERR_NOT_ENOUGH_MEMORY; + g_sdcardPath = strSdcardPath; + env->ReleaseStringUTFChars(sdcardPath, strSdcardPath); + } + + jint totalBytesToDownload = 0; + + string buffer; + ReaderPtr(GetPlatform().GetReader("external_resources.txt")).ReadAsString(buffer); + + stringstream in(buffer); + + string name; + int size; + + while (true) + { + in >> name; + + if (!in.good()) + break; + + in >> size; + + if (!in.good()) + break; + + FileToDownload f; + + f.m_pathOnSdcard = g_sdcardPath + name; + f.m_fileName = name; + + uint64_t sizeOnSdcard = 0; + Platform::GetFileSizeByFullPath(f.m_pathOnSdcard, sizeOnSdcard); + + if (size != sizeOnSdcard) + { + LOG(LINFO, ("should check : ", name, "sized", size, "bytes")); + f.m_fileSize = size; + g_filesToDownload.push_back(f); + totalBytesToDownload += size; + } + } + + g_totalDownloadedBytes = 0; + + int res = HasSpaceForFiles(totalBytesToDownload); + + switch (res) + { + case ERR_STORAGE_DISCONNECTED: + LOG(LWARNING, ("External file system is not available")); + break; + case ERR_NOT_ENOUGH_FREE_SPACE: + LOG(LWARNING, ("Not enough space to extract files")); + break; + }; + + g_totalBytesToDownload = totalBytesToDownload; + + return res; + } + + void DownloadFileFinished(shared_ptr obj, downloader::HttpRequest & req) + { + int errorCode = 0; + + CHECK(req.Status() != downloader::HttpRequest::EInProgress, ("should be either Completed or Failed")); + + switch (req.Status()) + { + case downloader::HttpRequest::ECompleted: + errorCode = ERR_DOWNLOAD_SUCCESS; + break; + case downloader::HttpRequest::EFailed: + errorCode = ERR_DOWNLOAD_ERROR; + break; + }; + + FileToDownload & curFile = g_filesToDownload.back(); + + LOG(LINFO, ("finished downloading", curFile.m_fileName, "sized", curFile.m_fileSize, "bytes")); + + /// slight hack, check manually for Maps extension and AddMap accordingly + if (curFile.m_fileName.find(".mwm") != string::npos) + { + LOG(LINFO, ("adding it as a map")); + g_framework->AddMap(curFile.m_fileName); + } + + g_totalDownloadedBytes += curFile.m_fileSize; + + LOG(LINFO, ("totalDownloadedBytes:", g_totalDownloadedBytes)); + + g_filesToDownload.pop_back(); + + JNIEnv * env = jni::GetEnv(); + + jmethodID onFinishMethod = env->GetMethodID(env->GetObjectClass(*obj.get()), "onDownloadFinished", "(I)V"); + CHECK(onFinishMethod, ("Not existing method: void onDownloadFinished(int)")); + + env->CallVoidMethod(*obj.get(), onFinishMethod, errorCode); + } + + void DownloadFileProgress(shared_ptr obj, downloader::HttpRequest & req) + { + LOG(LINFO, (req.Progress().first, "bytes for", g_filesToDownload.back().m_fileName, "was downloaded")); + + JNIEnv * env = jni::GetEnv(); + + jmethodID onProgressMethod = env->GetMethodID(env->GetObjectClass(*obj.get()), "onDownloadProgress", "(IIII)V"); + CHECK(onProgressMethod, ("Not existing method: void onDownloadProgress(int, int, int, int)")); + + FileToDownload & curFile = g_filesToDownload.back(); + + jint curTotal = req.Progress().second; + jint curProgress = req.Progress().first; + jint glbTotal = g_totalBytesToDownload; + jint glbProgress = g_totalDownloadedBytes + req.Progress().first; + + env->CallVoidMethod(*obj.get(), onProgressMethod, + curTotal, curProgress, + glbTotal, glbProgress); + } + + void DownloadURLListFinished(downloader::HttpRequest & req, + downloader::HttpRequest::CallbackT onFinish, + downloader::HttpRequest::CallbackT onProgress) + { + if (req.Status() == downloader::HttpRequest::EFailed) + onFinish(req); + else + { + FileToDownload & curFile = g_filesToDownload.back(); + + LOG(LINFO, ("finished URL list download for", curFile.m_fileName)); + + downloader::ParseServerList(req.Data(), curFile.m_urls); + + for (size_t i = 0; i < curFile.m_urls.size(); ++i) + { + curFile.m_urls[i] = curFile.m_urls[i] + OMIM_OS_NAME "/" + + strings::to_string(g_framework->Storage().GetCurrentVersion()) + "/" + + UrlEncode(curFile.m_fileName); + LOG(LINFO, (curFile.m_urls[i])); + } + + downloader::HttpRequest::GetFile(curFile.m_urls, + curFile.m_pathOnSdcard, + curFile.m_fileSize, + onFinish, + onProgress); + } + } + + JNIEXPORT int JNICALL + Java_com_mapswithme_maps_DownloadResourcesActivity_nativeDownloadNextFile(JNIEnv * env, + jobject thiz, jobject observer) + { + if (g_filesToDownload.empty()) + return ERR_NO_MORE_FILES; + + FileToDownload & curFile = g_filesToDownload.back(); + + LOG(LINFO, ("downloading", curFile.m_fileName, "sized", curFile.m_fileSize, "bytes")); + + downloader::HttpRequest::CallbackT onFinish(bind(&DownloadFileFinished, jni::make_global_ref(observer), _1)); + downloader::HttpRequest::CallbackT onProgress(bind(&DownloadFileProgress, jni::make_global_ref(observer), _1)); + + downloader::HttpRequest::PostJson(GetPlatform().MetaServerUrl(), + curFile.m_fileName, + bind(&DownloadURLListFinished, _1, + onFinish, + onProgress)); + + return ERR_FILE_IN_PROGRESS; + } + + // Move downloaded maps from /sdcard/Android/data/com.mapswithme.maps/files/ + // to /sdcard/MapsWithMe + JNIEXPORT void JNICALL + Java_com_mapswithme_maps_DownloadResourcesActivity_nativeMoveMaps(JNIEnv * env, jobject thiz, + jstring fromPath, jstring toPath) + { + string from, to; + { + char const * strFrom = env->GetStringUTFChars(fromPath, 0); + if (!strFrom) + return; + from = strFrom; + env->ReleaseStringUTFChars(fromPath, strFrom); + + char const * strTo = env->GetStringUTFChars(toPath, 0); + if (!strTo) + return; + to = strTo; + env->ReleaseStringUTFChars(toPath, strTo); + } + + Platform & pl = GetPlatform(); + Platform::FilesList files; + // Move *.mwm files + pl.GetFilesInDir(from, "*" DATA_FILE_EXTENSION, files); + for (size_t i = 0; i < files.size(); ++i) + { + LOG(LINFO, (from + files[i], to + files[i])); + rename((from + files[i]).c_str(), (to + files[i]).c_str()); + } + + // Delete not finished *.downloading files + files.clear(); + pl.GetFilesInDir(from, "*" DOWNLOADING_FILE_EXTENSION, files); + pl.GetFilesInDir(from, "*" RESUME_FILE_EXTENSION, files); + for (size_t i = 0; i < files.size(); ++i) + remove((from + files[i]).c_str()); + } +} diff --git a/android/src/com/mapswithme/maps/CopyResourcesActivity.java b/android/src/com/mapswithme/maps/CopyResourcesActivity.java deleted file mode 100644 index eba93bb727..0000000000 --- a/android/src/com/mapswithme/maps/CopyResourcesActivity.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.mapswithme.maps; - -import java.io.File; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.Dialog; -import android.app.ProgressDialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.os.AsyncTask; -import android.os.Bundle; - -// MWM resources are zipped in the apk inside /assets folder. -// MWM code currently can't randomly read zip files, so they're copied -// on the first start to the sdcard and used from there -public class CopyResourcesActivity extends Activity -{ - private ProgressDialog m_dialog = null; - - // Error codes, should match the same codes in JNI - private static final int ERR_COPIED_SUCCESSFULLY = 0; - private static final int ERR_NOT_ENOUGH_MEMORY = -1; - private static final int ERR_NOT_ENOUGH_FREE_SPACE = -2; - private static final int ERR_STORAGE_DISCONNECTED = -3; - - // Copies assets files to external folder on sdcard in the background - public class CopyResourcesTask extends AsyncTask - { - private final String m_apkPath; - private final String m_sdcardPath; - - CopyResourcesTask(String apkPath, String sdcardPath) - { - m_apkPath = apkPath; - m_sdcardPath = sdcardPath; - } - - @Override - protected void onPreExecute() - { - // Check if we need to perform any copying - final int bytes = nativeGetBytesToCopy(m_apkPath, m_sdcardPath); - if (bytes > 0) - { - // Display copy progress dialog - CopyResourcesActivity.this.showDialog(bytes); - } - else if (bytes == 0) - { - // All files are in place, continue with UI initialization - cancel(true); - } - else - { - // Display error dialog in UI, very rare case - CopyResourcesActivity.this.onCopyTaskFinished(ERR_NOT_ENOUGH_MEMORY); - } - } - - @Override - protected void onPostExecute(Integer result) - { - CopyResourcesActivity.this.onCopyTaskFinished(result); - } - - @Override - protected void onCancelled() - { - // In our logic cancelled means that files shouldn't be copied, - // So we just proceed to main UI initialization - CopyResourcesActivity.this.onCopyTaskFinished(ERR_COPIED_SUCCESSFULLY); - } - - @Override - protected void onProgressUpdate(Integer... copiedBytes) - { - CopyResourcesActivity.this.onCopyResourcesProgress(copiedBytes[0]); - } - - // If negative, stores error code - // Total number of copied bytes - int m_bytesCopied = 0; - - protected void onFileProgress(int size, int pos) - { - publishProgress(m_bytesCopied + pos); - } - - @Override - protected Integer doInBackground(Void... p) - { - do - { - m_bytesCopied = nativeCopyNextFile(this); - if (m_bytesCopied > 0) - publishProgress(m_bytesCopied); - else if (m_bytesCopied < 0) - return m_bytesCopied; - } while (m_bytesCopied != 0); - - return ERR_COPIED_SUCCESSFULLY; - } - } - - @Override - protected void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - // Set the same layout as for MWMActivity - setContentView(R.layout.map); - - final String extPath = MWMActivity.getDataStoragePath(); - // Create sdcard folder if it doesn't exist - new File(extPath).mkdirs(); - // Used to migrate from v2.0.0 to 2.0.1 - nativeMoveMaps(MWMActivity.getExtAppDirectoryPath("files"), extPath); - // All copy checks are made in the background task - new CopyResourcesTask(MWMActivity.getApkPath(this), extPath).execute(); - } - - public void onCopyTaskFinished(int result) - { - if (result == ERR_COPIED_SUCCESSFULLY) - { - // Continue with Main UI initialization (MWMActivity) - Intent mwmActivityIntent = new Intent(this, MWMActivity.class); - // Disable animation because MWMActivity should appear exactly over this one - mwmActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - startActivity(mwmActivityIntent); - } - else - { - // Hide loading progress - if (m_dialog != null) - m_dialog.dismiss(); - - int errMsgId; - switch (result) - { - case ERR_NOT_ENOUGH_FREE_SPACE: errMsgId = R.string.not_enough_free_space_on_sdcard; break; - case ERR_STORAGE_DISCONNECTED: errMsgId = R.string.disconnect_usb_cable; break; - default: errMsgId = R.string.not_enough_memory; - } - // Display Error dialog with close button - new AlertDialog.Builder(this).setMessage(errMsgId) - .setPositiveButton(R.string.close, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int whichButton) { - CopyResourcesActivity.this.finish(); - CopyResourcesActivity.this.moveTaskToBack(true); - }}) - .create().show(); - } - } - - private String cutProgressString(final String str, int current, int total) - { - int len = current * str.length() / total; - if (len <= 0) - len = 0; - else if (len > str.length()) - len = str.length(); - return str.substring(0, len); - } - - private String m_progressString; - - @Override - protected Dialog onCreateDialog(int totalBytesToCopy) - { - m_progressString = getString(R.string.loading); - - m_dialog = new ProgressDialog(this); - m_dialog.setMessage(cutProgressString(m_progressString, 0, totalBytesToCopy)); - m_dialog.setCancelable(false); - m_dialog.setIndeterminate(true); - m_dialog.setMax(totalBytesToCopy); - return m_dialog; - } - - public void onCopyResourcesProgress(int copiedBytes) - { - if (m_dialog != null) - { - m_dialog.setMessage(cutProgressString(m_progressString, copiedBytes, m_dialog.getMax())); - m_dialog.setProgress(copiedBytes); - } - } - - private native void nativeMoveMaps(String fromFolder, String toFolder); - private native int nativeGetBytesToCopy(String m_apkPath, String m_sdcardPath); - private native int nativeCopyNextFile(Object observer); -} diff --git a/android/src/com/mapswithme/maps/DownloadResourcesActivity.java b/android/src/com/mapswithme/maps/DownloadResourcesActivity.java new file mode 100644 index 0000000000..766967880e --- /dev/null +++ b/android/src/com/mapswithme/maps/DownloadResourcesActivity.java @@ -0,0 +1,186 @@ +package com.mapswithme.maps; + +import java.io.File; + +import android.app.Activity; +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; +import android.util.Log; + +public class DownloadResourcesActivity extends Activity +{ + private static final String TAG = "DownloadResourcesActivity"; + + private ProgressDialog mDialog = null; + + // Error codes, should match the same codes in JNI + + private static final int ERR_DOWNLOAD_SUCCESS = 0; + private static final int ERR_NOT_ENOUGH_MEMORY = -1; + private static final int ERR_NOT_ENOUGH_FREE_SPACE = -2; + private static final int ERR_STORAGE_DISCONNECTED = -3; + private static final int ERR_DOWNLOAD_ERROR = -4; + private static final int ERR_NO_MORE_FILES = -5; + private static final int ERR_FILE_IN_PROGRESS = -6; + + MWMApplication mApplication; + + protected void prepareFilesDownload() + { + // Check if we need to perform any downloading + final int bytes = nativeGetBytesToDownload( + mApplication.getApkPath(), + mApplication.getDataStoragePath()); + + /// disabling screen + disableAutomaticStandby(); + + if (bytes > 0) + { + // Display copy progress dialog + Log.w(TAG, "prepareFilesDownload, bytesToDownload:" + bytes); + + showDialog(bytes); + + if (nativeDownloadNextFile(this) == ERR_NO_MORE_FILES) + finishFilesDownload(ERR_NO_MORE_FILES); + } + else if (bytes == 0) + { + // All files are in place, continue with UI initialization + finishFilesDownload(ERR_DOWNLOAD_SUCCESS); + } + else + { + // Display error dialog in UI, very rare case + finishFilesDownload(ERR_NOT_ENOUGH_MEMORY); + } + } + + private WakeLock mWakeLock = null; + + private void disableAutomaticStandby() + { + if (mWakeLock == null) + { + PowerManager pm = (PowerManager) mApplication.getSystemService( + android.content.Context.POWER_SERVICE); + mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG); + mWakeLock.acquire(); + } + } + + private void enableAutomaticStandby() + { + if (mWakeLock != null) + { + mWakeLock.release(); + mWakeLock = null; + } + } + + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + // Set the same layout as for MWMActivity + setContentView(R.layout.map); + + mApplication = (MWMApplication)getApplication(); + + // Create sdcard folder if it doesn't exist + new File(mApplication.getDataStoragePath()).mkdirs(); + // Used to migrate from v2.0.0 to 2.0.1 + nativeMoveMaps(mApplication.getExtAppDirectoryPath("files"), + mApplication.getDataStoragePath()); + + prepareFilesDownload(); + } + + public void finishFilesDownload(int result) + { + enableAutomaticStandby(); + if (result == ERR_NO_MORE_FILES) + { + Log.w(TAG, "finished files download"); + + // Continue with Main UI initialization (MWMActivity) + Intent mwmActivityIntent = new Intent(this, MWMActivity.class); + // Disable animation because MWMActivity should appear exactly over this one + mwmActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + startActivity(mwmActivityIntent); + } + else + { + // Hide loading progress + if (mDialog != null) + mDialog.dismiss(); + + int errMsgId; + switch (result) + { + case ERR_NOT_ENOUGH_FREE_SPACE: errMsgId = R.string.not_enough_free_space_on_sdcard; break; + case ERR_STORAGE_DISCONNECTED: errMsgId = R.string.disconnect_usb_cable; break; + case ERR_DOWNLOAD_ERROR: errMsgId = R.string.download_has_failed; break; + default: errMsgId = R.string.not_enough_memory; + } + // Display Error dialog with close button + new AlertDialog.Builder(this).setMessage(errMsgId) + .setPositiveButton(R.string.close, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + finish(); + moveTaskToBack(true); + }}) + .create().show(); + } + } + + @Override + protected Dialog onCreateDialog(int totalBytesToDownload) + { + mDialog = new ProgressDialog(this); + + mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); + mDialog.setMessage(getString(R.string.loading)); + mDialog.setCancelable(true); + mDialog.setIndeterminate(false); + + Log.w(TAG, "progressMax:" + totalBytesToDownload); + + mDialog.setMax(totalBytesToDownload); + + return mDialog; + } + + public void onDownloadProgress(int currentTotal, int currentProgress, int globalTotal, int globalProgress) + { + Log.w(TAG, "curTotal:" + currentTotal + ", curProgress:" + currentProgress + + ", glbTotal:" + globalTotal + ", glbProgress:" + globalProgress); + + if (mDialog != null) + mDialog.setProgress(globalProgress); + } + + public void onDownloadFinished(int errorCode) + { + if (errorCode == ERR_DOWNLOAD_SUCCESS) + { + int res = nativeDownloadNextFile(this); + if (res == ERR_NO_MORE_FILES) + finishFilesDownload(res); + } + else + finishFilesDownload(errorCode); + } + + private native void nativeMoveMaps(String fromFolder, String toFolder); + private native int nativeGetBytesToDownload(String m_apkPath, String m_sdcardPath); + private native int nativeDownloadNextFile(Object observer); +} diff --git a/data/external_resources.txt b/data/external_resources.txt new file mode 100644 index 0000000000..f7b6d59af7 --- /dev/null +++ b/data/external_resources.txt @@ -0,0 +1,9 @@ +World.mwm 21694121 +WorldCoasts.mwm 6315418 +01_dejavusans.ttf 633604 +02_wqy-microhei.ttf 5177387 +03_jomolhari-id-a3d.ttf 1817160 +04_padauk.ttf 248076 +05_khmeros.ttf 265552 +06_code2000.ttf 3155104 +packed_polygons.bin 1854515 diff --git a/storage/storage.cpp b/storage/storage.cpp index b418b6dd61..b5b0187341 100644 --- a/storage/storage.cpp +++ b/storage/storage.cpp @@ -461,4 +461,9 @@ namespace storage bind(&Storage::OnMapDownloadFinished, this, _1), bind(&Storage::OnMapDownloadProgress, this, _1))); } + + int64_t Storage::GetCurrentVersion() const + { + return m_currentVersion; + } } diff --git a/storage/storage.hpp b/storage/storage.hpp index 606596a23f..05bd2c604d 100644 --- a/storage/storage.hpp +++ b/storage/storage.hpp @@ -146,6 +146,8 @@ namespace storage void CheckForUpdate(); void NotifyStatusChanhed(TIndex const & index) const; + + int64_t GetCurrentVersion() const; }; diff --git a/tools/android/update_assets.sh b/tools/android/update_assets.sh index 76442c395b..8584c4e9cd 100755 --- a/tools/android/update_assets.sh +++ b/tools/android/update_assets.sh @@ -8,12 +8,10 @@ DST=../../android/assets rm -rf $DST mkdir $DST -files=(01_dejavusans.ttf 02_wqy-microhei.ttf 03_jomolhari-id-a3d.ttf 04_padauk.ttf \ - 05_khmeros.ttf 06_code2000.ttf WorldCoasts.mwm about.html \ - basic_ldpi.skn basic_mdpi.skn basic_hdpi.skn basic_xhdpi.skn categories.txt classificator.txt +files=(about.html basic_ldpi.skn basic_mdpi.skn basic_hdpi.skn basic_xhdpi.skn categories.txt classificator.txt types.txt fonts_blacklist.txt fonts_whitelist.txt languages.txt \ symbols_ldpi.png symbols_mdpi.png symbols_hdpi.png symbols_xhdpi.png unicode_blocks.txt \ - visibility.txt drules_proto.txt drules_proto.bin packed_polygons.bin) + visibility.txt drules_proto.txt drules_proto.bin external_resources.txt) for item in ${files[*]} do @@ -21,5 +19,4 @@ do done # Separate case for World and countries list files without search support -ln -s $SRC/World.mwm.nosearch $DST/World.mwm ln -s $SRC/countries.txt.nosearch $DST/countries.txt