diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 44f0711759..795a683e4b 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -420,6 +420,10 @@ android:name="com.mapswithme.maps.background.WorkerService" android:exported="false"/> + + diff --git a/android/jni/CMakeLists.txt b/android/jni/CMakeLists.txt index 32aa1bcc2e..8564079615 100644 --- a/android/jni/CMakeLists.txt +++ b/android/jni/CMakeLists.txt @@ -48,6 +48,7 @@ set( com/mapswithme/maps/editor/Editor.cpp com/mapswithme/maps/editor/OsmOAuth.cpp com/mapswithme/maps/Framework.cpp + com/mapswithme/maps/LightFramework.cpp com/mapswithme/maps/LocationState.cpp com/mapswithme/maps/LocationHelper.cpp com/mapswithme/maps/MapFragment.cpp diff --git a/android/jni/com/mapswithme/maps/LightFramework.cpp b/android/jni/com/mapswithme/maps/LightFramework.cpp new file mode 100644 index 0000000000..6e97e07f01 --- /dev/null +++ b/android/jni/com/mapswithme/maps/LightFramework.cpp @@ -0,0 +1,22 @@ +#include "map/framework_light.hpp" + +#include "com/mapswithme/core/jni_helper.hpp" + +using namespace lightweight; + +extern "C" +{ +JNIEXPORT jboolean JNICALL +Java_com_mapswithme_maps_LightFramework_nativeIsAuthenticated(JNIEnv * env, jclass clazz) +{ + Framework const framework(REQUEST_TYPE_USER_AUTH_STATUS); + return static_cast(framework.Get()); +} + +JNIEXPORT jint JNICALL +Java_com_mapswithme_maps_LightFramework_nativeGetNumberUnsentUGC(JNIEnv * env, jclass clazz) +{ + Framework const framework(REQUEST_TYPE_NUMBER_OF_UNSENT_UGC); + return static_cast(framework.Get()); +} +} // extern "C" diff --git a/android/jni/com/mapswithme/platform/Platform.cpp b/android/jni/com/mapswithme/platform/Platform.cpp index c166ef5026..cc70af3a1d 100644 --- a/android/jni/com/mapswithme/platform/Platform.cpp +++ b/android/jni/com/mapswithme/platform/Platform.cpp @@ -129,8 +129,6 @@ void Platform::Initialize(JNIEnv * env, jobject functorProcessObject, jstring ap m_sendPushWooshTagsMethod = env->GetMethodID(functorProcessClass, "sendPushWooshTags", "(Ljava/lang/String;[Ljava/lang/String;)V"); m_myTrackerTrackMethod = env->GetStaticMethodID(g_myTrackerClazz, "trackEvent", "(Ljava/lang/String;)Z"); - m_secureStorage.Init(); - m_guiThread = my::make_unique(m_functorProcessObject); std::string const flavor = jni::ToNativeString(env, flavorName); @@ -249,10 +247,9 @@ void Platform::SetGuiThread(unique_ptr guiThread) m_guiThread = std::move(guiThread); } -void Platform::AndroidSecureStorage::Init() +void Platform::AndroidSecureStorage::Init(JNIEnv * env) { - JNIEnv * env = jni::GetEnv(); - if (env == nullptr) + if (m_secureStorageClass != nullptr) return; m_secureStorageClass = jni::GetGlobalClassRef(env, "com/mapswithme/util/SecureStorage"); @@ -265,6 +262,8 @@ void Platform::AndroidSecureStorage::Save(std::string const & key, std::string c if (env == nullptr) return; + Init(env); + static jmethodID const saveMethodId = jni::GetStaticMethodID(env, m_secureStorageClass, "save", "(Ljava/lang/String;Ljava/lang/String;)V"); @@ -279,6 +278,8 @@ bool Platform::AndroidSecureStorage::Load(std::string const & key, std::string & if (env == nullptr) return false; + Init(env); + static jmethodID const loadMethodId = jni::GetStaticMethodID(env, m_secureStorageClass, "load", "(Ljava/lang/String;)Ljava/lang/String;"); @@ -297,6 +298,8 @@ void Platform::AndroidSecureStorage::Remove(std::string const & key) if (env == nullptr) return; + Init(env); + static jmethodID const removeMethodId = jni::GetStaticMethodID(env, m_secureStorageClass, "remove", "(Ljava/lang/String;)V"); diff --git a/android/jni/com/mapswithme/platform/Platform.hpp b/android/jni/com/mapswithme/platform/Platform.hpp index b4db7b4662..73e8d6c9d6 100644 --- a/android/jni/com/mapswithme/platform/Platform.hpp +++ b/android/jni/com/mapswithme/platform/Platform.hpp @@ -48,12 +48,13 @@ public: class AndroidSecureStorage { public: - void Init(); void Save(std::string const & key, std::string const & value); bool Load(std::string const & key, std::string & value); void Remove(std::string const & key); private: + void Init(JNIEnv * env); + jclass m_secureStorageClass = nullptr; }; diff --git a/android/src/com/mapswithme/maps/LightFramework.java b/android/src/com/mapswithme/maps/LightFramework.java new file mode 100644 index 0000000000..c3586a6a6c --- /dev/null +++ b/android/src/com/mapswithme/maps/LightFramework.java @@ -0,0 +1,7 @@ +package com.mapswithme.maps; + +public class LightFramework +{ + public static native boolean nativeIsAuthenticated(); + public static native int nativeGetNumberUnsentUGC(); +} diff --git a/android/src/com/mapswithme/maps/MwmActivity.java b/android/src/com/mapswithme/maps/MwmActivity.java index 613e1fbb89..558782b6a0 100644 --- a/android/src/com/mapswithme/maps/MwmActivity.java +++ b/android/src/com/mapswithme/maps/MwmActivity.java @@ -38,6 +38,8 @@ import com.mapswithme.maps.api.ParsedRoutingData; import com.mapswithme.maps.api.ParsedSearchRequest; import com.mapswithme.maps.api.ParsedUrlMwmRequest; import com.mapswithme.maps.api.RoutePoint; +import com.mapswithme.maps.auth.PassportAuthDialogFragment; +import com.mapswithme.maps.background.Notifier; import com.mapswithme.maps.base.BaseMwmFragmentActivity; import com.mapswithme.maps.base.OnBackPressListener; import com.mapswithme.maps.bookmarks.BookmarkCategoriesActivity; @@ -51,7 +53,6 @@ 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.editor.AuthDialogFragment; import com.mapswithme.maps.editor.Editor; import com.mapswithme.maps.editor.EditorActivity; import com.mapswithme.maps.editor.EditorHostFragment; @@ -101,6 +102,8 @@ import com.mapswithme.util.ThemeUtils; import com.mapswithme.util.UiUtils; import com.mapswithme.util.Utils; import com.mapswithme.util.concurrency.UiThread; +import com.mapswithme.util.log.Logger; +import com.mapswithme.util.log.LoggerFactory; import com.mapswithme.util.permissions.PermissionsResult; import com.mapswithme.util.sharing.ShareOption; import com.mapswithme.util.sharing.SharingHelper; @@ -131,6 +134,9 @@ public class MwmActivity extends BaseMwmFragmentActivity DiscoveryFragment.DiscoveryListener, FloatingSearchToolbarController.SearchToolbarListener { + private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.MISC); + private static final String TAG = MwmActivity.class.getSimpleName(); + public static final String EXTRA_TASK = "map_task"; public static final String EXTRA_LAUNCH_BY_DEEP_LINK = "launch_by_deep_link"; private static final String EXTRA_CONSUMED = "mwm.extra.intent.processed"; @@ -321,6 +327,14 @@ public class MwmActivity extends BaseMwmFragmentActivity return new Intent(context, DownloadResourcesLegacyActivity.class) .putExtra(DownloadResourcesLegacyActivity.EXTRA_COUNTRY, countryId); } + + public static Intent createAuthenticateIntent() + { + return new Intent(MwmApplication.get(), MwmActivity.class) + .addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION) + .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + .putExtra(MwmActivity.EXTRA_TASK, + new MwmActivity.ShowDialogTask(PassportAuthDialogFragment.class.getName())); } @Override @@ -1192,6 +1206,11 @@ public class MwmActivity extends BaseMwmFragmentActivity if (intent == null) return false; + if (intent.hasExtra(SplashActivity.EXTRA_INTENT)) + intent = intent.getParcelableExtra(SplashActivity.EXTRA_INTENT); + + Notifier.processNotificationExtras(intent); + if (intent.hasExtra(EXTRA_TASK)) { addTask(intent); @@ -1299,8 +1318,6 @@ public class MwmActivity extends BaseMwmFragmentActivity } } - - @Override protected void onPause() { @@ -2389,13 +2406,21 @@ public class MwmActivity extends BaseMwmFragmentActivity showSearch(query); } - public static class ShowAuthorizationTask implements MapTask + public static class ShowDialogTask implements MapTask { + @NonNull + private String mDialogName; + + public ShowDialogTask(@NonNull String dialogName) + { + mDialogName = dialogName; + } + @Override public boolean run(MwmActivity target) { - final DialogFragment fragment = (DialogFragment) Fragment.instantiate(target, AuthDialogFragment.class.getName()); - fragment.show(target.getSupportFragmentManager(), AuthDialogFragment.class.getName()); + final DialogFragment fragment = (DialogFragment) Fragment.instantiate(target, mDialogName); + fragment.show(target.getSupportFragmentManager(), mDialogName); return true; } } diff --git a/android/src/com/mapswithme/maps/SplashActivity.java b/android/src/com/mapswithme/maps/SplashActivity.java index 64e7b0b46b..7f5bdca676 100644 --- a/android/src/com/mapswithme/maps/SplashActivity.java +++ b/android/src/com/mapswithme/maps/SplashActivity.java @@ -33,6 +33,7 @@ public class SplashActivity extends AppCompatActivity { public static final String EXTRA_INTENT = "extra_intent"; private static final String EXTRA_ACTIVITY_TO_START = "extra_activity_to_start"; + private static final String EXTRA_INITIAL_INTENT = "extra_initial_intent"; private static final int REQUEST_PERMISSIONS = 1; private static final long FIRST_START_DELAY = 1000; private static final long DELAY = 100; @@ -82,10 +83,14 @@ public class SplashActivity extends AppCompatActivity }; public static void start(@NonNull Context context, - @Nullable Class activityToStart) + @Nullable Class activityToStart, + @Nullable Intent initialIntent) { Intent intent = new Intent(context, SplashActivity.class); - intent.putExtra(EXTRA_ACTIVITY_TO_START, activityToStart); + if (activityToStart != null) + intent.putExtra(EXTRA_ACTIVITY_TO_START, activityToStart); + if (initialIntent != null) + intent.putExtra(EXTRA_INITIAL_INTENT, initialIntent); context.startActivity(intent); } @@ -306,15 +311,21 @@ public class SplashActivity extends AppCompatActivity private void processNavigation() { Intent input = getIntent(); - Intent intent = new Intent(this, DownloadResourcesLegacyActivity.class); + Intent result = new Intent(this, DownloadResourcesLegacyActivity.class); if (input != null) { - Class type = (Class) input.getSerializableExtra(EXTRA_ACTIVITY_TO_START); - if (type != null) - intent = new Intent(this, type); - intent.putExtra(EXTRA_INTENT, input); + if (input.hasExtra(EXTRA_ACTIVITY_TO_START)) + { + result = new Intent(this, + (Class) input.getSerializableExtra(EXTRA_ACTIVITY_TO_START)); + } + + Intent extraIntent = input.hasExtra(EXTRA_INITIAL_INTENT) ? + input.getParcelableExtra(EXTRA_INITIAL_INTENT) : + input; + result.putExtra(EXTRA_INTENT, extraIntent); } - startActivity(intent); + startActivity(result); finish(); } } diff --git a/android/src/com/mapswithme/maps/auth/PassportAuthDialogFragment.java b/android/src/com/mapswithme/maps/auth/PassportAuthDialogFragment.java new file mode 100644 index 0000000000..e09fd19be8 --- /dev/null +++ b/android/src/com/mapswithme/maps/auth/PassportAuthDialogFragment.java @@ -0,0 +1,38 @@ +package com.mapswithme.maps.auth; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.mapswithme.maps.base.BaseMwmDialogFragment; + +public class PassportAuthDialogFragment extends BaseMwmDialogFragment +{ + private Authorizer mAuthorizer = new Authorizer(this); + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) + { + mAuthorizer.authorize(); + return null; + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) + { + super.onActivityResult(requestCode, resultCode, data); + + mAuthorizer.onActivityResult(requestCode, resultCode, data); + dismiss(); + } + + @Override + protected int getStyle() + { + return STYLE_NO_TITLE; + } +} diff --git a/android/src/com/mapswithme/maps/background/ConnectivityChangedReceiver.java b/android/src/com/mapswithme/maps/background/ConnectivityChangedReceiver.java index 28cfe153b2..f8f9ad51ff 100644 --- a/android/src/com/mapswithme/maps/background/ConnectivityChangedReceiver.java +++ b/android/src/com/mapswithme/maps/background/ConnectivityChangedReceiver.java @@ -28,5 +28,6 @@ public class ConnectivityChangedReceiver extends BroadcastReceiver + !backgroundTracker().isForeground(); LOGGER.i(TAG, msg); CrashlyticsUtils.log(Log.INFO, TAG, msg); + NotificationService.startOnConnectivityChanged(context); } } diff --git a/android/src/com/mapswithme/maps/background/NotificationService.java b/android/src/com/mapswithme/maps/background/NotificationService.java new file mode 100644 index 0000000000..2aacb655ae --- /dev/null +++ b/android/src/com/mapswithme/maps/background/NotificationService.java @@ -0,0 +1,120 @@ +package com.mapswithme.maps.background; + +import android.app.IntentService; +import android.content.Context; +import android.content.Intent; +import android.support.annotation.Nullable; + +import com.mapswithme.maps.LightFramework; +import com.mapswithme.maps.MwmApplication; +import com.mapswithme.maps.routing.RoutingController; +import com.mapswithme.util.NetworkPolicy; +import com.mapswithme.util.PermissionsUtils; +import com.mapswithme.util.log.Logger; +import com.mapswithme.util.log.LoggerFactory; + +import static com.mapswithme.maps.MwmApplication.prefs; + +public class NotificationService extends IntentService +{ + private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.MISC); + private static final String TAG = NotificationService.class.getSimpleName(); + private static final String LAST_AUTH_NOTIFICATION_TIMESTAMP = "DownloadOrUpdateTimestamp"; + private static final int MIN_COUNT_UNSENT_UGC = 2; + private static final long MIN_AUTH_EVENT_DELTA_MILLIS = 5 * 24 * 60 * 60 * 1000; // 5 days + private static final String CONNECTIVITY_CHANGED = + "com.mapswithme.maps.notification_service.action.connectivity_changed"; + + private interface NotificationExecutor + { + boolean tryToNotify(); + } + + static void startOnConnectivityChanged(Context context) + { + final Intent intent = new Intent(context, NotificationService.class); + intent.setAction(NotificationService.CONNECTIVITY_CHANGED); + context.startService(intent); + } + + private static boolean notifyIsNotAuthenticated() + { + if (!PermissionsUtils.isExternalStorageGranted() || + !NetworkPolicy.getCurrentNetworkUsageStatus() || + LightFramework.nativeIsAuthenticated() || + LightFramework.nativeGetNumberUnsentUGC() < MIN_COUNT_UNSENT_UGC) + { + LOGGER.d(TAG, "Authentication nofification is rejected. External storage granted: " + + PermissionsUtils.isExternalStorageGranted() + ". Is user authenticated: " + + LightFramework.nativeIsAuthenticated() + ". Current network usage status: " + + NetworkPolicy.getCurrentNetworkUsageStatus() + ". Number of unsent UGC: " + + LightFramework.nativeGetNumberUnsentUGC()); + return false; + } + + // Do not show push when user is in the navigation mode. + if (MwmApplication.get().arePlatformAndCoreInitialized() && + RoutingController.get().isNavigating()) + { + LOGGER.d(TAG, "Authentication nofification is rejected. The user is in navigation mode."); + return false; + } + + final long lastEventTimestamp = prefs().getLong(LAST_AUTH_NOTIFICATION_TIMESTAMP, 0); + + if (System.currentTimeMillis() - lastEventTimestamp > MIN_AUTH_EVENT_DELTA_MILLIS) + { + LOGGER.d(TAG, "Authentication nofification will be sent."); + + prefs().edit() + .putLong(LAST_AUTH_NOTIFICATION_TIMESTAMP, System.currentTimeMillis()) + .apply(); + + Notifier.notifyIsNotAuthenticated(); + + return true; + } + LOGGER.d(TAG, "Authentication nofification is rejected. Last event timestamp: " + + lastEventTimestamp + "Current time milliseconds: " + System.currentTimeMillis()); + return false; + } + + public NotificationService() + { + super(NotificationService.class.getSimpleName()); + } + + @Override + protected void onHandleIntent(@Nullable Intent intent) + { + if (intent == null) + return; + + final String action = intent.getAction(); + + if (action == null) + return; + + switch(action) + { + case CONNECTIVITY_CHANGED: + onConnectivityChanged(); + break; + } + } + + private static void onConnectivityChanged() + { + final NotificationExecutor notifyOrder[] = + { + NotificationService::notifyIsNotAuthenticated, + }; + + // Only one notification should be shown at a time. + for (NotificationExecutor executor : notifyOrder) + { + if (executor.tryToNotify()) + return; + } + } +} diff --git a/android/src/com/mapswithme/maps/background/Notifier.java b/android/src/com/mapswithme/maps/background/Notifier.java index 4d6990c132..e235e19146 100644 --- a/android/src/com/mapswithme/maps/background/Notifier.java +++ b/android/src/com/mapswithme/maps/background/Notifier.java @@ -5,6 +5,8 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.support.annotation.IntDef; +import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import com.mapswithme.maps.MwmActivity; @@ -13,20 +15,36 @@ import com.mapswithme.maps.R; import com.mapswithme.util.StringUtils; import com.mapswithme.util.statistics.Statistics; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + public final class Notifier { - private final static int ID_DOWNLOAD_FAILED = 2; + private static final String EXTRA_CANCEL_NOTIFICATION = "mwm.extra.intent.cancel_notification"; + private static final String EXTRA_NOTIFICATION_CLICKED = "mwm.extra.intent.notification_clicked"; + + public final static int ID_NONE = 0; + public final static int ID_DOWNLOAD_FAILED = 1; + public final static int ID_IS_NOT_AUTHENTICATED = 2; + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ ID_NONE, ID_DOWNLOAD_FAILED, ID_IS_NOT_AUTHENTICATED }) + public @interface NotificationId + { + } private static final MwmApplication APP = MwmApplication.get(); - private Notifier() { } + private Notifier() + { + } public static void notifyDownloadFailed(String id, String name) { String title = APP.getString(R.string.app_name); String content = APP.getString(R.string.download_country_failed, name); - PendingIntent pi = PendingIntent.getActivity(APP, 0, MwmActivity.createShowMapIntent(APP, id, false) + PendingIntent pi = PendingIntent.getActivity(APP, 0, MwmActivity.createShowMapIntent(APP, id) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), PendingIntent.FLAG_UPDATE_CURRENT); @@ -34,12 +52,56 @@ public final class Notifier Statistics.INSTANCE.trackEvent(Statistics.EventName.DOWNLOAD_COUNTRY_NOTIFICATION_SHOWN); } - public static void cancelDownloadFailed() + public static void notifyIsNotAuthenticated() { - getNotificationManager().cancel(ID_DOWNLOAD_FAILED); + Intent authIntent = MwmActivity.createAuthenticateIntent(); + authIntent.putExtra(EXTRA_CANCEL_NOTIFICATION, Notifier.ID_IS_NOT_AUTHENTICATED); + authIntent.putExtra(EXTRA_NOTIFICATION_CLICKED, + Statistics.EventName.UGC_NOT_AUTH_NOTIFICATION_CLICKED); + + PendingIntent pi = PendingIntent.getActivity(APP, 0, authIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + + NotificationCompat.Builder builder = + getBuilder(APP.getString(R.string.notification_unsent_reviews_title), + APP.getString(R.string.notification_unsent_reviews_message), pi); + + builder.addAction(0, APP.getString(R.string.authorization_button_sign_in), pi); + + getNotificationManager().notify(ID_IS_NOT_AUTHENTICATED, builder.build()); + + Statistics.INSTANCE.trackEvent(Statistics.EventName.UGC_NOT_AUTH_NOTIFICATION_SHOWN); } - private static void placeNotification(String title, String content, PendingIntent pendingIntent, int notificationId) + public static void cancelNotification(@NotificationId int id) + { + if (id == ID_NONE) + return; + + getNotificationManager().cancel(id); + } + + public static void processNotificationExtras(@Nullable Intent intent) + { + if (intent == null) + return; + + if (intent.hasExtra(Notifier.EXTRA_CANCEL_NOTIFICATION)) + { + @Notifier.NotificationId + int notificationId = intent.getIntExtra(Notifier.EXTRA_CANCEL_NOTIFICATION, Notifier.ID_NONE); + cancelNotification(notificationId); + } + + if (intent.hasExtra(Notifier.EXTRA_NOTIFICATION_CLICKED)) + { + String eventName = intent.getStringExtra(Notifier.EXTRA_NOTIFICATION_CLICKED); + Statistics.INSTANCE.trackEvent(eventName); + } + } + + private static void placeNotification(String title, String content, PendingIntent pendingIntent, + int notificationId) { final Notification notification = getBuilder(title, content, pendingIntent) .build(); @@ -47,7 +109,8 @@ public final class Notifier getNotificationManager().notify(notificationId, notification); } - private static NotificationCompat.Builder getBuilder(String title, String content, PendingIntent pendingIntent) + private static NotificationCompat.Builder getBuilder(String title, String content, + PendingIntent pendingIntent) { return new NotificationCompat.Builder(APP) .setAutoCancel(true) diff --git a/android/src/com/mapswithme/maps/base/BaseMwmFragmentActivity.java b/android/src/com/mapswithme/maps/base/BaseMwmFragmentActivity.java index 783318d414..367a5d98f1 100644 --- a/android/src/com/mapswithme/maps/base/BaseMwmFragmentActivity.java +++ b/android/src/com/mapswithme/maps/base/BaseMwmFragmentActivity.java @@ -58,7 +58,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity || !PermissionsUtils.isExternalStorageGranted()) { super.onCreate(savedInstanceState); - goToSplashScreen(); + goToSplashScreen(getIntent()); return; } mInitializationCompleted = true; @@ -178,7 +178,7 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity super.onResume(); if (!PermissionsUtils.isExternalStorageGranted()) { - goToSplashScreen(); + goToSplashScreen(null); return; } @@ -266,12 +266,12 @@ public abstract class BaseMwmFragmentActivity extends AppCompatActivity return android.R.id.content; } - private void goToSplashScreen() + private void goToSplashScreen(@Nullable Intent initialIntent) { Class type = null; - if (!(this instanceof MwmActivity)) + if (!(this instanceof MwmActivity) || initialIntent != null) type = getClass(); - SplashActivity.start(this, type); + SplashActivity.start(this, type, initialIntent); finish(); } } diff --git a/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java b/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java index a2af0e37ff..f7c60c3dbd 100644 --- a/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java +++ b/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java @@ -397,7 +397,7 @@ class DownloaderAdapter extends RecyclerView.Adapter