diff --git a/android/jni/com/mapswithme/core/jni_helper.cpp b/android/jni/com/mapswithme/core/jni_helper.cpp index d892537260..db103b7081 100644 --- a/android/jni/com/mapswithme/core/jni_helper.cpp +++ b/android/jni/com/mapswithme/core/jni_helper.cpp @@ -198,7 +198,8 @@ bool HandleJavaException(JNIEnv * env) const jthrowable e = env->ExceptionOccurred(); env->ExceptionDescribe(); env->ExceptionClear(); - LOG(LERROR, (ToNativeString(env, e))); + //LOG(LERROR, (ToNativeString(env, e))); + LOG(LWARNING, (ToNativeString(env, e))); return true; } return false; diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 9f42f9cc06..22eeddb754 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -751,6 +751,19 @@ Java_com_mapswithme_maps_Framework_nativeGetOutdatedCountriesString(JNIEnv * env return jni::ToJavaString(env, g_framework->GetOutdatedCountriesString()); } +JNIEXPORT jobjectArray JNICALL +Java_com_mapswithme_maps_Framework_nativeGetOutdatedCountries(JNIEnv * env, jclass) +{ + vector countries; + vector ids; + class Storage const & storage = g_framework->GetStorage(); + storage.GetOutdatedCountries(countries); + for (auto country: countries) + ids.push_back(country->Name()); + + return jni::ToJavaStringArray(env, ids); +} + JNIEXPORT jboolean JNICALL Java_com_mapswithme_maps_Framework_nativeIsDataVersionChanged(JNIEnv * env, jclass) { diff --git a/android/res/layout/fragment_updater.xml b/android/res/layout/fragment_updater.xml new file mode 100644 index 0000000000..fe03701a93 --- /dev/null +++ b/android/res/layout/fragment_updater.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + diff --git a/android/src/com/mapswithme/maps/Framework.java b/android/src/com/mapswithme/maps/Framework.java index b5793f0430..e1a941c442 100644 --- a/android/src/com/mapswithme/maps/Framework.java +++ b/android/src/com/mapswithme/maps/Framework.java @@ -139,6 +139,9 @@ public class Framework @UiThread public static native String nativeGetOutdatedCountriesString(); + @UiThread + public static native String[] nativeGetOutdatedCountries(); + public static native boolean nativeIsDataVersionChanged(); public static native void nativeUpdateSavedDataVersion(); diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index c0cd823450..263e62e4f3 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -46,6 +46,7 @@ import com.mapswithme.maps.downloader.DownloaderFragment; import com.mapswithme.maps.downloader.MapManager; import com.mapswithme.maps.downloader.MigrationFragment; import com.mapswithme.maps.downloader.OnmapDownloader; +import com.mapswithme.maps.downloader.UpdaterDialogFragment; import com.mapswithme.maps.editor.AuthDialogFragment; import com.mapswithme.maps.editor.Editor; import com.mapswithme.maps.editor.EditorActivity; @@ -1031,9 +1032,16 @@ public class MwmActivity extends BaseMwmFragmentActivity if (!NewsFragment.showOn(this)) { if (ViralFragment.shouldDisplay()) + { new ViralFragment().show(getSupportFragmentManager(), ""); + } else + { + if (UpdaterDialogFragment.showOn(this)) + return; + LikesManager.INSTANCE.showDialogs(this); + } } } diff --git a/android/src/com/mapswithme/maps/downloader/UpdaterDialogFragment.java b/android/src/com/mapswithme/maps/downloader/UpdaterDialogFragment.java new file mode 100644 index 0000000000..299482265d --- /dev/null +++ b/android/src/com/mapswithme/maps/downloader/UpdaterDialogFragment.java @@ -0,0 +1,289 @@ +package com.mapswithme.maps.downloader; + +import android.app.Dialog; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; +import android.view.View; +import android.view.Window; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.mapswithme.maps.Framework; +import com.mapswithme.maps.R; +import com.mapswithme.maps.base.BaseMwmDialogFragment; +import com.mapswithme.util.ConnectionState; +import com.mapswithme.util.Constants; +import com.mapswithme.util.StringUtils; +import com.mapswithme.util.UiUtils; +import com.mapswithme.util.statistics.Statistics; + +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +import static com.mapswithme.util.statistics.Statistics.EventName.DOWNLOADER_DIALOG_CANCEL; +import static com.mapswithme.util.statistics.Statistics.EventName.DOWNLOADER_DIALOG_DOWNLOAD; +import static com.mapswithme.util.statistics.Statistics.EventName.DOWNLOADER_DIALOG_LATER; +import static com.mapswithme.util.statistics.Statistics.EventName.DOWNLOADER_DIALOG_MANUAL_DOWNLOAD; +import static com.mapswithme.util.statistics.Statistics.EventName.DOWNLOADER_DIALOG_SHOW; + +public class UpdaterDialogFragment extends BaseMwmDialogFragment +{ + + private static final String ARG_UPDATE_IMMEDIATELY = "arg_update_immediately"; + private static final String ARG_TOTAL_SIZE = "arg_total_size"; + private static final String ARG_TOTAL_SIZE_MB = "arg_total_size_mb"; + private static final String ARG_OUTDATED_MAPS = "arg_outdated_maps"; + private static final int AUTO_UPDATE_THRESHOLD = 100; + + private TextView mTitle; + private TextView mUpdateBtn; + private ProgressBar mProgressBar; + private TextView mCancelBtn; + + private int mListenerSlot; + @Nullable + private String mTotalSize; + private long mTotalSizeMb; + private boolean mAutoUpdate; + @NonNull + private final Map mOutdatedMaps = new HashMap<>(); + + @NonNull + private final MapManager.StorageCallback mStorageCallback = new MapManager.StorageCallback() + { + + @Override + public void onStatusChanged(List data) + { + for (MapManager.StorageCallbackData item : data) + { + if (item.isLeafNode && item.newStatus == CountryItem.STATUS_FAILED) + { + String text; + switch (item.errorCode) + { + case CountryItem.ERROR_NO_INTERNET: + text = getString(R.string.common_check_internet_connection_dialog); + break; + + case CountryItem.ERROR_OOM: + text = getString(R.string.downloader_no_space_title); + break; + + default: + text = String.valueOf(item.errorCode); + } + Statistics.INSTANCE.trackDownloaderDialogError(mTotalSizeMb, text); + MapManager.showError(getActivity(), item, null); + dismiss(); + return; + } + + CountryItem country = mOutdatedMaps.get(item.countryId); + if (country != null) + country.update(); + } + + for (CountryItem country : mOutdatedMaps.values()) + { + if (country.status != CountryItem.STATUS_DONE) + return; + } + + dismiss(); + } + + @Override + public void onProgress(String countryId, long localSize, long remoteSize) + { + CountryItem country = mOutdatedMaps.get(countryId); + if (country == null) + return; + + country.update(); + float progress = 0; + for (CountryItem item : mOutdatedMaps.values()) + progress += item.progress / mOutdatedMaps.size(); + +// TODO string resources + mTitle.setText(String.format(Locale.getDefault(), "%s %d%%", "Updating maps", (int) progress)); + } + }; + + @NonNull + private final View.OnClickListener mCancelClickListener = new View.OnClickListener() + { + @Override + public void onClick(View v) + { + Statistics.INSTANCE.trackDownloaderDialogEvent(MapManager.nativeIsDownloading() + ? DOWNLOADER_DIALOG_LATER + : DOWNLOADER_DIALOG_CANCEL, + mTotalSizeMb); + dismiss(); + } + }; + + @NonNull + private final View.OnClickListener mUpdateClickListener = new View.OnClickListener() + { + @Override + public void onClick(View v) + { + MapManager.nativeUpdate(CountryItem.getRootId()); + UiUtils.show(mProgressBar); + UiUtils.hide(mUpdateBtn); +// TODO string resources + mTitle.setText(String.format(Locale.getDefault(), "%s %d%%", "Updating maps", 0)); + mCancelBtn.setText(R.string.cancel); + + Statistics.INSTANCE.trackDownloaderDialogEvent(DOWNLOADER_DIALOG_MANUAL_DOWNLOAD, + mTotalSizeMb); + } + }; + + @SuppressWarnings("TryWithIdenticalCatches") + public static boolean showOn(@NonNull FragmentActivity activity) + { + if (!ConnectionState.isWifiConnected() || MapManager.nativeIsLegacyMode()) + return false; + + UpdateInfo info = MapManager.nativeGetUpdateInfo(null); + if (info == null || info.filesCount == 0) + return false; + + FragmentManager fm = activity.getSupportFragmentManager(); + if (fm.isDestroyed()) + return false; + + Fragment f = fm.findFragmentByTag(UpdaterDialogFragment.class.getName()); + if (f != null) + return false; + + Bundle args = new Bundle(); + long size = info.totalSize / Constants.MB; + args.putBoolean(ARG_UPDATE_IMMEDIATELY, size < AUTO_UPDATE_THRESHOLD); + args.putString(ARG_TOTAL_SIZE, StringUtils.getFileSizeString(info.totalSize)); + args.putLong(ARG_TOTAL_SIZE_MB, size); + args.putStringArray(ARG_OUTDATED_MAPS, Framework.nativeGetOutdatedCountries()); + try + { + final UpdaterDialogFragment fragment = UpdaterDialogFragment.class.newInstance(); + fragment.setArguments(args); + fragment.show(activity.getSupportFragmentManager(), UpdaterDialogFragment.class.getName()); + } catch (java.lang.InstantiationException ignored) + {} + catch (IllegalAccessException ignored) + {} + + Statistics.INSTANCE.trackDownloaderDialogEvent(DOWNLOADER_DIALOG_SHOW, size); + + return true; + } + + @Override + protected int getCustomTheme() + { + return super.getFullscreenTheme(); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + readArguments(); + mListenerSlot = MapManager.nativeSubscribe(mStorageCallback); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) + { + Dialog res = super.onCreateDialog(savedInstanceState); + res.requestWindowFeature(Window.FEATURE_NO_TITLE); + + View content = View.inflate(getActivity(), R.layout.fragment_updater, null); + res.setContentView(content); + + mTitle = (TextView) content.findViewById(R.id.title); + mUpdateBtn = (TextView) content.findViewById(R.id.update_btn); + mProgressBar = (ProgressBar) content.findViewById(R.id.progress); + mCancelBtn = (TextView) content.findViewById(R.id.cancel_btn); + + initViews(); + + if (mAutoUpdate) + { + MapManager.nativeUpdate(CountryItem.getRootId()); + Statistics.INSTANCE.trackDownloaderDialogEvent(DOWNLOADER_DIALOG_DOWNLOAD, + mTotalSizeMb); + } + + return res; + } + + @Override + public void onDestroy() + { + MapManager.nativeUnsubscribe(mListenerSlot); + super.onDestroy(); + } + + @Override + public void onDismiss(DialogInterface dialog) + { + if (MapManager.nativeIsDownloading()) + MapManager.nativeCancel(CountryItem.getRootId()); + + super.onDismiss(dialog); + } + + private void readArguments() + { + Bundle args = getArguments(); + if (args == null) + return; + + mAutoUpdate = args.getBoolean(ARG_UPDATE_IMMEDIATELY); + if (!mAutoUpdate && MapManager.nativeIsDownloading()) + mAutoUpdate = true; + + mTotalSize = args.getString(ARG_TOTAL_SIZE); + mTotalSizeMb = args.getLong(ARG_TOTAL_SIZE_MB, 0L); + + mOutdatedMaps.clear(); + String[] ids = args.getStringArray(ARG_OUTDATED_MAPS); + if (ids != null) + { + for (String id : ids) + { + CountryItem item = new CountryItem(id); + item.update(); + mOutdatedMaps.put(id, item); + } + } + } + + private void initViews() + { + UiUtils.showIf(mAutoUpdate, mProgressBar); + UiUtils.showIf(!mAutoUpdate, mUpdateBtn); + + mUpdateBtn.setText(String.format(Locale.US, "%s (%s)", getString(R.string.downloader_update_all_button), + mTotalSize)); + mUpdateBtn.setOnClickListener(mUpdateClickListener); + mCancelBtn.setText(mAutoUpdate ? R.string.cancel : R.string.later); + mCancelBtn.setOnClickListener(mCancelClickListener); +// TODO string resources + mTitle.setText(mAutoUpdate ? String.format(Locale.getDefault(), "%s %d%%", "Updating maps", 0) + : "Update your downloaded maps"); + } +} diff --git a/android/src/com/mapswithme/util/statistics/Statistics.java b/android/src/com/mapswithme/util/statistics/Statistics.java index d42fce9288..e2e7bfb70d 100644 --- a/android/src/com/mapswithme/util/statistics/Statistics.java +++ b/android/src/com/mapswithme/util/statistics/Statistics.java @@ -20,7 +20,6 @@ import com.mapswithme.maps.PrivateVariables; import com.mapswithme.maps.ads.MwmNativeAd; import com.mapswithme.maps.ads.NativeAdError; import com.mapswithme.maps.api.ParsedMwmRequest; -import com.mapswithme.maps.ads.Banner; import com.mapswithme.maps.bookmarks.data.MapObject; import com.mapswithme.maps.downloader.MapManager; import com.mapswithme.maps.editor.Editor; @@ -35,6 +34,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import static com.mapswithme.util.statistics.Statistics.EventName.DOWNLOADER_DIALOG_ERROR; import static com.mapswithme.util.statistics.Statistics.EventName.PP_BANNER_BLANK; import static com.mapswithme.util.statistics.Statistics.EventName.PP_BANNER_ERROR; import static com.mapswithme.util.statistics.Statistics.EventName.PP_SPONSORED_BOOK; @@ -45,10 +45,12 @@ import static com.mapswithme.util.statistics.Statistics.EventParam.ERROR_MESSAGE import static com.mapswithme.util.statistics.Statistics.EventParam.HOTEL; import static com.mapswithme.util.statistics.Statistics.EventParam.HOTEL_LAT; import static com.mapswithme.util.statistics.Statistics.EventParam.HOTEL_LON; +import static com.mapswithme.util.statistics.Statistics.EventParam.MAP_DATA_SIZE; import static com.mapswithme.util.statistics.Statistics.EventParam.PROVIDER; import static com.mapswithme.util.statistics.Statistics.EventParam.RESTAURANT; import static com.mapswithme.util.statistics.Statistics.EventParam.RESTAURANT_LAT; import static com.mapswithme.util.statistics.Statistics.EventParam.RESTAURANT_LON; +import static com.mapswithme.util.statistics.Statistics.EventParam.TYPE; import static com.mapswithme.util.statistics.Statistics.ParamValue.BOOKING_COM; import static com.mapswithme.util.statistics.Statistics.ParamValue.OPENTABLE; import static com.mapswithme.util.statistics.Statistics.EventName.PP_HOTEL_REVIEWS_LAND; @@ -72,6 +74,12 @@ public enum Statistics public static final String DOWNLOADER_ERROR = "Downloader_Map_error"; public static final String DOWNLOADER_ACTION = "Downloader_Map_action"; public static final String DOWNLOADER_CANCEL = "Downloader_Cancel_downloading"; + public static final String DOWNLOADER_DIALOG_SHOW = "Downloader_OnStartScreen_show"; + public static final String DOWNLOADER_DIALOG_MANUAL_DOWNLOAD = "Downloader_OnStartScreen_manual_download"; + public static final String DOWNLOADER_DIALOG_DOWNLOAD = "Downloader_OnStartScreen_auto_download"; + public static final String DOWNLOADER_DIALOG_LATER = "Downloader_OnStartScreen_select_later"; + public static final String DOWNLOADER_DIALOG_CANCEL = "Downloader_OnStartScreen_cancel_download"; + static final String DOWNLOADER_DIALOG_ERROR = "Downloader_OnStartScreen_error"; // bookmarks public static final String BMK_DESCRIPTION_CHANGED = "Bookmark. Description changed"; @@ -260,6 +268,7 @@ public enum Statistics static final String BANNER_STATE = "state"; static final String ERROR_CODE = "error_code"; static final String ERROR_MESSAGE = "error_message"; + static final String MAP_DATA_SIZE = "map_data_size:"; private EventParam() {} } @@ -556,6 +565,19 @@ public enum Statistics .get()); } + public void trackDownloaderDialogEvent(@NonNull String eventName, long size) + { + trackEvent(eventName, Statistics.params() + .add(MAP_DATA_SIZE, size)); + } + + public void trackDownloaderDialogError(long size, @NonNull String error) + { + trackEvent(DOWNLOADER_DIALOG_ERROR, Statistics.params() + .add(MAP_DATA_SIZE, size) + .add(TYPE, error)); + } + public static ParameterBuilder params() { return new ParameterBuilder();