forked from organicmaps/organicmaps
Compare commits
10 commits
master
...
alpha/2024
Author | SHA1 | Date | |
---|---|---|---|
|
bac234b277 | ||
|
f05ed2564d | ||
|
624ca8c1f1 | ||
174cc4a9bc | |||
36527bd34a | |||
|
16a0a6c22a | ||
|
adfd2fb96d | ||
|
ff436c1ec0 | ||
|
7868516222 | ||
|
31359b9110 |
44 changed files with 2776 additions and 2536 deletions
|
@ -384,6 +384,7 @@ dependencies {
|
|||
implementation 'androidx.car.app:app-projected:1.7.0-beta01'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.fragment:fragment:1.8.2'
|
||||
implementation 'androidx.media:media:1.7.0'
|
||||
implementation 'androidx.preference:preference:1.2.1'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
||||
implementation 'androidx.work:work-runtime:2.9.1'
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#include "base/math.hpp"
|
||||
#include "base/sunrise_sunset.hpp"
|
||||
|
||||
#include "ge0/url_generator.hpp"
|
||||
|
||||
#include "3party/open-location-code/openlocationcode.h"
|
||||
|
||||
#include <memory>
|
||||
|
@ -954,7 +956,16 @@ Java_app_organicmaps_Framework_nativeGetGe0Url(JNIEnv * env, jclass, jdouble lat
|
|||
{
|
||||
::Framework * fr = frm();
|
||||
double const scale = (zoomLevel > 0 ? zoomLevel : fr->GetDrawScale());
|
||||
string const url = fr->CodeGe0url(lat, lon, scale, jni::ToNativeString(env, name));
|
||||
string const url = ge0::GenerateShortShowMapUrl(lat, lon, scale, jni::ToNativeString(env, name));
|
||||
return jni::ToJavaString(env, url);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_app_organicmaps_Framework_nativeGetGeoUri(JNIEnv * env, jclass, jdouble lat, jdouble lon, jdouble zoomLevel, jstring name)
|
||||
{
|
||||
::Framework * fr = frm();
|
||||
double const scale = (zoomLevel > 0 ? zoomLevel : fr->GetDrawScale());
|
||||
string const url = ge0::GenerateGeoUri(lat, lon, scale, jni::ToNativeString(env, name));
|
||||
return jni::ToJavaString(env, url);
|
||||
}
|
||||
|
||||
|
|
|
@ -194,6 +194,7 @@ public class Framework
|
|||
public static native String nativeFormatSpeed(double speed);
|
||||
|
||||
public static native String nativeGetGe0Url(double lat, double lon, double zoomLevel, String name);
|
||||
public static native String nativeGetGeoUri(double lat, double lon, double zoomLevel, String name);
|
||||
|
||||
public static native String nativeGetAddress(double lat, double lon);
|
||||
|
||||
|
|
|
@ -156,7 +156,11 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
EditorHostFragment.class.getName(),
|
||||
ReportFragment.class.getName() };
|
||||
|
||||
public static final int REQ_CODE_DRIVING_OPTIONS = 6;
|
||||
public final ActivityResultLauncher<Intent> startDrivingOptionsForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult ->
|
||||
{
|
||||
if( activityResult.getResultCode() == Activity.RESULT_OK)
|
||||
rebuildLastRoute();
|
||||
});
|
||||
|
||||
private static final String MAIN_MENU_ID = "MAIN_MENU_BOTTOM_SHEET";
|
||||
private static final String LAYERS_MENU_ID = "LAYERS_MENU_BOTTOM_SHEET";
|
||||
|
@ -624,7 +628,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
|
||||
if (!mIsTabletLayout)
|
||||
{
|
||||
mRoutingPlanInplaceController = new RoutingPlanInplaceController(this, this, this);
|
||||
mRoutingPlanInplaceController = new RoutingPlanInplaceController(this, startDrivingOptionsForResult, this, this);
|
||||
removeCurrentFragment(false);
|
||||
}
|
||||
|
||||
|
@ -701,6 +705,16 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
}
|
||||
}
|
||||
|
||||
/** Hides/shows UI while keeping state
|
||||
* @param isUiHidden True to hide the UI
|
||||
**/
|
||||
public void hideOrShowUIWithoutClosingPlacePage(boolean isUiHidden)
|
||||
{
|
||||
// Used instead of closeBottomSheet to preserve state and hide instantly
|
||||
UiUtils.showIf(!isUiHidden, findViewById(R.id.place_page_container_fragment));
|
||||
mMapButtonsViewModel.setButtonsHidden(isUiHidden);
|
||||
}
|
||||
|
||||
private void showSearchToolbar()
|
||||
{
|
||||
mSearchController.show();
|
||||
|
@ -1030,18 +1044,6 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
mPowerSaveDisclaimerState = PowerSaveDisclaimerState.SHOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (resultCode != Activity.RESULT_OK)
|
||||
return;
|
||||
|
||||
if (requestCode == REQ_CODE_DRIVING_OPTIONS)
|
||||
rebuildLastRoute();
|
||||
}
|
||||
|
||||
private void rebuildLastRoute()
|
||||
{
|
||||
RoutingController.get().attach(this);
|
||||
|
@ -1695,7 +1697,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
|
|||
mAlertDialog = new MaterialAlertDialogBuilder(this, R.style.MwmTheme_AlertDialog)
|
||||
.setTitle(R.string.unable_to_calc_alert_title)
|
||||
.setMessage(R.string.unable_to_calc_alert_subtitle)
|
||||
.setPositiveButton(R.string.settings, (dialog, which) -> DrivingOptionsActivity.start(this))
|
||||
.setPositiveButton(R.string.settings, (dialog, which) -> DrivingOptionsActivity.start(this, startDrivingOptionsForResult))
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setOnDismissListener(dialog -> mAlertDialog = null)
|
||||
.show();
|
||||
|
|
|
@ -13,6 +13,7 @@ import android.view.View;
|
|||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -55,9 +56,6 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
|
|||
{
|
||||
private static final String TAG = BookmarkCategoriesFragment.class.getSimpleName();
|
||||
|
||||
static final int REQ_CODE_DELETE_CATEGORY = 102;
|
||||
static final int REQ_CODE_IMPORT_DIRECTORY = 103;
|
||||
|
||||
private static final int MAX_CATEGORY_NAME_LENGTH = 60;
|
||||
|
||||
public static final String BOOKMARKS_CATEGORIES_MENU_ID = "BOOKMARKS_CATEGORIES_BOTTOM_SHEET";
|
||||
|
@ -73,6 +71,22 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
|
|||
@NonNull
|
||||
private DataChangedListener mCategoriesAdapterObserver;
|
||||
|
||||
private final ActivityResultLauncher<Intent> startBookmarkListForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
|
||||
if( activityResult.getResultCode() == Activity.RESULT_OK)
|
||||
onDeleteActionSelected(getSelectedCategory());
|
||||
});
|
||||
|
||||
private final ActivityResultLauncher<Intent> startImportDirectoryForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult ->
|
||||
{
|
||||
if( activityResult.getResultCode() == Activity.RESULT_OK)
|
||||
onImportDirectoryResult(activityResult.getData());
|
||||
});
|
||||
|
||||
private final ActivityResultLauncher<Intent> startBookmarkSettingsForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
|
||||
// not handled at the moment
|
||||
});
|
||||
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
protected int getLayoutRes()
|
||||
|
@ -254,14 +268,14 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
|
|||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
intent.putExtra(DocumentsContract.EXTRA_EXCLUDE_SELF, true);
|
||||
startActivityForResult(intent, REQ_CODE_IMPORT_DIRECTORY);
|
||||
startImportDirectoryForResult.launch(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(@NonNull View v, @NonNull BookmarkCategory category)
|
||||
{
|
||||
mSelectedCategory = category;
|
||||
BookmarkListActivity.startForResult(this, category);
|
||||
BookmarkListActivity.startForResult(this, startBookmarkListForResult, category);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -289,54 +303,42 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment<Bookmark
|
|||
|
||||
private void onSettingsActionSelected(@NonNull BookmarkCategory category)
|
||||
{
|
||||
BookmarkCategorySettingsActivity.startForResult(this, category);
|
||||
BookmarkCategorySettingsActivity.startForResult(this, startBookmarkSettingsForResult, category);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
private void onImportDirectoryResult(Intent data)
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (resultCode != Activity.RESULT_OK)
|
||||
return;
|
||||
switch (requestCode)
|
||||
{
|
||||
case REQ_CODE_DELETE_CATEGORY -> onDeleteActionSelected(getSelectedCategory());
|
||||
case REQ_CODE_IMPORT_DIRECTORY ->
|
||||
{
|
||||
if (data == null)
|
||||
throw new AssertionError("Data is null");
|
||||
if (data == null)
|
||||
throw new AssertionError("Data is null");
|
||||
|
||||
final Context context = requireActivity();
|
||||
final Uri rootUri = data.getData();
|
||||
final ProgressDialog dialog = new ProgressDialog(context, R.style.MwmTheme_ProgressDialog);
|
||||
dialog.setMessage(getString(R.string.wait_several_minutes));
|
||||
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
dialog.setIndeterminate(true);
|
||||
dialog.setCancelable(false);
|
||||
dialog.show();
|
||||
Logger.d(TAG, "Importing bookmarks from " + rootUri);
|
||||
MwmApplication app = MwmApplication.from(context);
|
||||
final File tempDir = new File(StorageUtils.getTempPath(app));
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
ThreadPool.getStorage().execute(() -> {
|
||||
AtomicInteger found = new AtomicInteger(0);
|
||||
StorageUtils.listContentProviderFilesRecursively(
|
||||
final Context context = requireActivity();
|
||||
final Uri rootUri = data.getData();
|
||||
final ProgressDialog dialog = new ProgressDialog(context, R.style.MwmTheme_ProgressDialog);
|
||||
dialog.setMessage(getString(R.string.wait_several_minutes));
|
||||
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
|
||||
dialog.setIndeterminate(true);
|
||||
dialog.setCancelable(false);
|
||||
dialog.show();
|
||||
Logger.d(TAG, "Importing bookmarks from " + rootUri);
|
||||
MwmApplication app = MwmApplication.from(context);
|
||||
final File tempDir = new File(StorageUtils.getTempPath(app));
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
ThreadPool.getStorage().execute(() -> {
|
||||
AtomicInteger found = new AtomicInteger(0);
|
||||
StorageUtils.listContentProviderFilesRecursively(
|
||||
resolver, rootUri, uri -> {
|
||||
if (BookmarkManager.INSTANCE.importBookmarksFile(resolver, uri, tempDir))
|
||||
found.incrementAndGet();
|
||||
});
|
||||
UiThread.run(() -> {
|
||||
if (dialog.isShowing())
|
||||
dialog.dismiss();
|
||||
int found_val = found.get();
|
||||
String message = context.getResources().getQuantityString(
|
||||
UiThread.run(() -> {
|
||||
if (dialog.isShowing())
|
||||
dialog.dismiss();
|
||||
int found_val = found.get();
|
||||
String message = context.getResources().getQuantityString(
|
||||
R.plurals.bookmarks_detect_message, found_val, found_val);
|
||||
Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show();
|
||||
});
|
||||
});
|
||||
}
|
||||
default -> throw new AssertionError("Invalid requestCode: " + requestCode);
|
||||
}
|
||||
Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,6 +2,7 @@ package app.organicmaps.bookmarks;
|
|||
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
|
@ -11,7 +12,6 @@ import app.organicmaps.bookmarks.data.BookmarkCategory;
|
|||
|
||||
public class BookmarkCategorySettingsActivity extends BaseMwmFragmentActivity
|
||||
{
|
||||
public static final int REQUEST_CODE = 107;
|
||||
public static final String EXTRA_BOOKMARK_CATEGORY = "bookmark_category";
|
||||
|
||||
@Override
|
||||
|
@ -32,11 +32,11 @@ public class BookmarkCategorySettingsActivity extends BaseMwmFragmentActivity
|
|||
return BookmarkCategorySettingsFragment.class;
|
||||
}
|
||||
|
||||
public static void startForResult(@NonNull Fragment fragment,
|
||||
public static void startForResult(@NonNull Fragment fragment, ActivityResultLauncher<Intent> startBookmarkSettingsForResult,
|
||||
@NonNull BookmarkCategory category)
|
||||
{
|
||||
android.content.Intent intent = new Intent(fragment.requireActivity(), BookmarkCategorySettingsActivity.class)
|
||||
.putExtra(EXTRA_BOOKMARK_CATEGORY, category);
|
||||
fragment.startActivityForResult(intent, REQUEST_CODE);
|
||||
startBookmarkSettingsForResult.launch(intent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package app.organicmaps.bookmarks;
|
|||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StyleRes;
|
||||
|
@ -57,11 +58,11 @@ public class BookmarkListActivity extends BaseToolbarActivity
|
|||
return R.layout.bookmarks_activity;
|
||||
}
|
||||
|
||||
static void startForResult(@NonNull Fragment fragment, @NonNull BookmarkCategory category)
|
||||
static void startForResult(@NonNull Fragment fragment, ActivityResultLauncher<Intent> startBookmarkListForResult, @NonNull BookmarkCategory category)
|
||||
{
|
||||
Bundle args = new Bundle();
|
||||
Intent intent = new Intent(fragment.requireActivity(), BookmarkListActivity.class);
|
||||
intent.putExtra(BookmarksListFragment.EXTRA_CATEGORY, category);
|
||||
fragment.startActivityForResult(intent, BookmarkCategoriesFragment.REQ_CODE_DELETE_CATEGORY);
|
||||
startBookmarkListForResult.launch(intent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -66,6 +67,15 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
|
|||
private static final String OPTIONS_MENU_ID = "OPTIONS_MENU_BOTTOM_SHEET";
|
||||
|
||||
private ActivityResultLauncher<SharingUtils.SharingIntent> shareLauncher;
|
||||
private final ActivityResultLauncher<Intent> startBookmarkListForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
|
||||
System.out.println("resultCode: " + activityResult.getResultCode());
|
||||
handleActivityResult();
|
||||
});
|
||||
|
||||
private final ActivityResultLauncher<Intent> startBookmarkSettingsForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
|
||||
System.out.println("resultCode: " + activityResult.getResultCode());
|
||||
handleActivityResult();
|
||||
});
|
||||
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
@NonNull
|
||||
|
@ -132,7 +142,9 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
|
|||
|
||||
BookmarkCollectionAdapter adapter = new BookmarkCollectionAdapter(getCategoryOrThrow(),
|
||||
mCategoryItems);
|
||||
adapter.setOnClickListener((v, item) -> BookmarkListActivity.startForResult(this, item));
|
||||
adapter.setOnClickListener((v, item) -> {
|
||||
BookmarkListActivity.startForResult(this, startBookmarkListForResult, item);
|
||||
});
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
@ -227,7 +239,6 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
|
|||
private void configureBookmarksListAdapter()
|
||||
{
|
||||
BookmarkListAdapter adapter = getBookmarkListAdapter();
|
||||
adapter.registerAdapterDataObserver(mCategoryDataSource);
|
||||
adapter.setOnClickListener((v, position) -> onItemClick(position));
|
||||
adapter.setOnLongClickListener((v, position) -> onItemMore(position));
|
||||
adapter.setMoreListener((v, position) -> onItemMore(position));
|
||||
|
@ -603,6 +614,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
|
|||
private void onDeleteTrackSelected(long trackId)
|
||||
{
|
||||
BookmarkManager.INSTANCE.deleteTrack(trackId);
|
||||
mCategoryDataSource.invalidate();
|
||||
getBookmarkListAdapter().onDelete(mSelectedPosition);
|
||||
getBookmarkListAdapter().notifyDataSetChanged();
|
||||
}
|
||||
|
@ -676,6 +688,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
|
|||
BookmarkInfo info = (BookmarkInfo) getBookmarkListAdapter().getItem(mSelectedPosition);
|
||||
adapter.onDelete(mSelectedPosition);
|
||||
BookmarkManager.INSTANCE.deleteBookmark(info.getBookmarkId());
|
||||
mCategoryDataSource.invalidate();
|
||||
adapter.notifyDataSetChanged();
|
||||
if (mSearchMode)
|
||||
mNeedUpdateSorting = true;
|
||||
|
@ -697,7 +710,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
|
|||
|
||||
private void onSettingsOptionSelected()
|
||||
{
|
||||
BookmarkCategorySettingsActivity.startForResult(this, mCategoryDataSource.getData());
|
||||
BookmarkCategorySettingsActivity.startForResult(this, startBookmarkSettingsForResult, mCategoryDataSource.getData());
|
||||
}
|
||||
|
||||
private void onDeleteOptionSelected()
|
||||
|
@ -745,11 +758,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment<ConcatAdapter
|
|||
BookmarksSharingHelper.INSTANCE.onPreparedFileForSharing(requireActivity(), shareLauncher, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation") // https://github.com/organicmaps/organicmaps/issues/3630
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
private void handleActivityResult()
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
getAdapter().notifyDataSetChanged();
|
||||
ActionBar actionBar = ((AppCompatActivity) requireActivity()).getSupportActionBar();
|
||||
actionBar.setTitle(mCategoryDataSource.getData().getName());
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
package app.organicmaps.bookmarks.data;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import app.organicmaps.content.DataSource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CategoryDataSource extends RecyclerView.AdapterDataObserver implements
|
||||
DataSource<BookmarkCategory>
|
||||
public class CategoryDataSource implements DataSource<BookmarkCategory>
|
||||
{
|
||||
@NonNull
|
||||
private BookmarkCategory mCategory;
|
||||
|
@ -25,10 +23,8 @@ public class CategoryDataSource extends RecyclerView.AdapterDataObserver impleme
|
|||
return mCategory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged()
|
||||
public void invalidate()
|
||||
{
|
||||
super.onChanged();
|
||||
List<BookmarkCategory> categories = BookmarkManager.INSTANCE.getCategories();
|
||||
int index = categories.indexOf(mCategory);
|
||||
if (index >= 0)
|
||||
|
|
|
@ -5,6 +5,8 @@ import android.os.Bundle;
|
|||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -38,6 +40,8 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapte
|
|||
|
||||
private int mSubscriberSlot;
|
||||
|
||||
final ActivityResultLauncher<Intent> startVoiceRecognitionForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> mToolbarController.onVoiceRecognitionResult(activityResult));
|
||||
|
||||
private final RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState)
|
||||
|
@ -206,13 +210,6 @@ public class DownloaderFragment extends BaseMwmRecyclerFragment<DownloaderAdapte
|
|||
return mAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation") // https://github.com/organicmaps/organicmaps/issues/3630
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
mToolbarController.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
|
|
|
@ -58,10 +58,9 @@ class DownloaderToolbarController extends SearchToolbarController
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecated") // https://github.com/organicmaps/organicmaps/issues/3630
|
||||
protected void startVoiceRecognition(Intent intent, int code)
|
||||
protected void startVoiceRecognition(Intent intent)
|
||||
{
|
||||
mFragment.startActivityForResult(intent, code);
|
||||
mFragment.startVoiceRecognitionForResult.launch(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package app.organicmaps.routing;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.IdRes;
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -77,6 +79,7 @@ public class RoutingPlanController extends ToolbarController
|
|||
}
|
||||
|
||||
RoutingPlanController(View root, Activity activity,
|
||||
ActivityResultLauncher<Intent> startDrivingOptionsForResult,
|
||||
@NonNull RoutingPlanInplaceController.RoutingPlanListener routingPlanListener,
|
||||
@Nullable RoutingBottomMenuListener listener)
|
||||
{
|
||||
|
@ -102,7 +105,7 @@ public class RoutingPlanController extends ToolbarController
|
|||
View btn = mDrivingOptionsBtnContainer.findViewById(R.id.driving_options_btn);
|
||||
mDrivingOptionsImage = mFrame.findViewById(R.id.driving_options_btn_img);
|
||||
|
||||
btn.setOnClickListener(v -> DrivingOptionsActivity.start(requireActivity()));
|
||||
btn.setOnClickListener(v -> DrivingOptionsActivity.start(requireActivity(), startDrivingOptionsForResult));
|
||||
mDriverOptionsLayoutListener = new SelfTerminatedDrivingOptionsLayoutListener();
|
||||
mAnimToggle = MwmApplication.from(activity.getApplicationContext())
|
||||
.getResources().getInteger(R.integer.anim_default);
|
||||
|
|
|
@ -7,9 +7,9 @@ import android.view.ViewGroup;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import app.organicmaps.Framework;
|
||||
import app.organicmaps.MwmActivity;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.base.BaseMwmFragment;
|
||||
|
||||
|
@ -21,15 +21,9 @@ public class RoutingPlanFragment extends BaseMwmFragment
|
|||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
|
||||
{
|
||||
final FragmentActivity activity = requireActivity();
|
||||
final MwmActivity activity = (MwmActivity) requireActivity();
|
||||
View res = inflater.inflate(R.layout.fragment_routing, container, false);
|
||||
RoutingBottomMenuListener listener = null;
|
||||
if (activity instanceof RoutingBottomMenuListener)
|
||||
listener = (RoutingBottomMenuListener) activity;
|
||||
|
||||
RoutingPlanInplaceController.RoutingPlanListener planListener =
|
||||
(RoutingPlanInplaceController.RoutingPlanListener) activity;
|
||||
mPlanController = new RoutingPlanController(res, activity, planListener, listener);
|
||||
mPlanController = new RoutingPlanController(res, activity, activity.startDrivingOptionsForResult, activity, activity);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,10 @@ package app.organicmaps.routing;
|
|||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
|
@ -20,10 +22,11 @@ public class RoutingPlanInplaceController extends RoutingPlanController
|
|||
private Animator mAnimator;
|
||||
|
||||
public RoutingPlanInplaceController(@NonNull MwmActivity activity,
|
||||
ActivityResultLauncher<Intent> startDrivingOptionsForResult,
|
||||
@NonNull RoutingPlanListener routingPlanListener,
|
||||
@NonNull RoutingBottomMenuListener listener)
|
||||
{
|
||||
super(activity.findViewById(R.id.routing_plan_frame), activity, routingPlanListener, listener);
|
||||
super(activity.findViewById(R.id.routing_plan_frame), activity, startDrivingOptionsForResult, routingPlanListener, listener);
|
||||
mRoutingPlanListener = routingPlanListener;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
@ -112,10 +114,9 @@ public class SearchFragment extends BaseMwmFragment
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation") // https://github.com/organicmaps/organicmaps/issues/3630
|
||||
protected void startVoiceRecognition(Intent intent, int code)
|
||||
protected void startVoiceRecognition(Intent intent)
|
||||
{
|
||||
startActivityForResult(intent, code);
|
||||
startVoiceRecognitionForResult.launch(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -167,6 +168,11 @@ public class SearchFragment extends BaseMwmFragment
|
|||
private String mInitialLocale;
|
||||
private boolean mInitialSearchOnMap = false;
|
||||
|
||||
private final ActivityResultLauncher<Intent> startVoiceRecognitionForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult ->
|
||||
{
|
||||
mToolbarController.onVoiceRecognitionResult(activityResult);
|
||||
});
|
||||
|
||||
private final LocationListener mLocationListener = new LocationListener()
|
||||
{
|
||||
@Override
|
||||
|
@ -521,14 +527,6 @@ public class SearchFragment extends BaseMwmFragment
|
|||
mToolbarController.showProgress(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation") // https://github.com/organicmaps/organicmaps/issues/3630
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
mToolbarController.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onBackPressed()
|
||||
{
|
||||
|
|
|
@ -3,10 +3,9 @@ package app.organicmaps.settings;
|
|||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import app.organicmaps.MwmActivity;
|
||||
import app.organicmaps.base.BaseMwmFragmentActivity;
|
||||
|
||||
public class DrivingOptionsActivity extends BaseMwmFragmentActivity
|
||||
|
@ -17,9 +16,9 @@ public class DrivingOptionsActivity extends BaseMwmFragmentActivity
|
|||
return DrivingOptionsFragment.class;
|
||||
}
|
||||
|
||||
public static void start(@NonNull Activity activity)
|
||||
public static void start(@NonNull Activity activity, ActivityResultLauncher<Intent> startDrivingOptionsForResult)
|
||||
{
|
||||
Intent intent = new Intent(activity, DrivingOptionsActivity.class);
|
||||
activity.startActivityForResult(intent, MwmActivity.REQ_CODE_DRIVING_OPTIONS);
|
||||
startDrivingOptionsForResult.launch(intent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package app.organicmaps.settings;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
|
@ -11,6 +12,8 @@ import android.text.style.ForegroundColorSpan;
|
|||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
@ -35,7 +38,6 @@ import java.util.Map;
|
|||
|
||||
public class VoiceInstructionsSettingsFragment extends BaseXmlSettingsFragment
|
||||
{
|
||||
private static final int REQUEST_INSTALL_DATA = 1;
|
||||
|
||||
@NonNull
|
||||
@SuppressWarnings("NotNullFieldNotInitialized")
|
||||
|
@ -67,6 +69,14 @@ public class VoiceInstructionsSettingsFragment extends BaseXmlSettingsFragment
|
|||
private LanguageData mCurrentLanguage;
|
||||
private String mSelectedLanguage;
|
||||
|
||||
private final ActivityResultLauncher<Intent> startInstallDataIntentForResult = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), activityResult -> {
|
||||
|
||||
if(activityResult.getResultCode() == Activity.RESULT_OK)
|
||||
{
|
||||
onInstallDataResult();
|
||||
}
|
||||
});
|
||||
|
||||
private final Preference.OnPreferenceChangeListener mEnabledListener = (preference, newValue) -> {
|
||||
final boolean set = (Boolean) newValue;
|
||||
if (!set)
|
||||
|
@ -107,8 +117,7 @@ public class VoiceInstructionsSettingsFragment extends BaseXmlSettingsFragment
|
|||
if (lang.downloaded)
|
||||
setLanguage(lang);
|
||||
else
|
||||
UiUtils.startActivityForResult(VoiceInstructionsSettingsFragment.this,
|
||||
new Intent(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA), REQUEST_INSTALL_DATA);
|
||||
UiUtils.startActivityForResult(startInstallDataIntentForResult, new Intent(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA));
|
||||
|
||||
return false;
|
||||
};
|
||||
|
@ -181,21 +190,13 @@ public class VoiceInstructionsSettingsFragment extends BaseXmlSettingsFragment
|
|||
updateTts();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation") // https://github.com/organicmaps/organicmaps/issues/3630
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
private void onInstallDataResult()
|
||||
{
|
||||
// Do not check resultCode here as it is always RESULT_CANCELED
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
updateTts();
|
||||
|
||||
if (requestCode == REQUEST_INSTALL_DATA)
|
||||
{
|
||||
updateTts();
|
||||
|
||||
LanguageData lang = mLanguages.get(mSelectedLanguage);
|
||||
if (lang != null && lang.downloaded)
|
||||
setLanguage(lang);
|
||||
}
|
||||
LanguageData lang = mLanguages.get(mSelectedLanguage);
|
||||
if (lang != null && lang.downloaded)
|
||||
setLanguage(lang);
|
||||
}
|
||||
|
||||
private void enableListeners(boolean enable)
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
package app.organicmaps.sound;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.AudioFocusRequest;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import static android.media.AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
|
||||
|
||||
public class AudioFocusManager
|
||||
{
|
||||
@Nullable
|
||||
private AudioManager mAudioManager = null;
|
||||
@Nullable
|
||||
private AudioManager.OnAudioFocusChangeListener mOnFocusChange = null;
|
||||
@Nullable
|
||||
private AudioFocusRequest mAudioFocusRequest = null;
|
||||
|
||||
public AudioFocusManager(@Nullable Context context)
|
||||
{
|
||||
if (context != null)
|
||||
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
if (Build.VERSION.SDK_INT < 26)
|
||||
mOnFocusChange = focusGain -> {};
|
||||
else
|
||||
mAudioFocusRequest = new AudioFocusRequest.Builder(AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK).setAudioAttributes(
|
||||
new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
|
||||
.build()
|
||||
).build();
|
||||
}
|
||||
|
||||
public boolean requestAudioFocus()
|
||||
{
|
||||
boolean isMusicActive = false;
|
||||
|
||||
if (mAudioManager != null)
|
||||
{
|
||||
isMusicActive = mAudioManager.isMusicActive();
|
||||
if (Build.VERSION.SDK_INT < 26)
|
||||
mAudioManager.requestAudioFocus(mOnFocusChange, AudioManager.STREAM_VOICE_CALL, AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
|
||||
else
|
||||
mAudioManager.requestAudioFocus(mAudioFocusRequest);
|
||||
}
|
||||
|
||||
return isMusicActive;
|
||||
}
|
||||
|
||||
public void releaseAudioFocus()
|
||||
{
|
||||
if (mAudioManager != null)
|
||||
{
|
||||
if (Build.VERSION.SDK_INT < 26)
|
||||
mAudioManager.abandonAudioFocus(mOnFocusChange);
|
||||
else
|
||||
mAudioManager.abandonAudioFocusRequest(mAudioFocusRequest);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package app.organicmaps.sound;
|
|||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
@ -11,6 +12,11 @@ import android.text.TextUtils;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.media.AudioAttributesCompat;
|
||||
import androidx.media.AudioFocusRequestCompat;
|
||||
import androidx.media.AudioManagerCompat;
|
||||
|
||||
import app.organicmaps.MwmApplication;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.util.Config;
|
||||
|
@ -47,7 +53,18 @@ public enum TtsPlayer
|
|||
|
||||
private TextToSpeech mTts;
|
||||
private boolean mInitializing;
|
||||
private AudioFocusManager mAudioFocusManager;
|
||||
|
||||
private final AudioFocusRequestCompat mAudioFocusRequest =
|
||||
new AudioFocusRequestCompat.Builder(AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK)
|
||||
.setAudioAttributes(
|
||||
new AudioAttributesCompat.Builder()
|
||||
.setUsage(AudioAttributesCompat.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
|
||||
.setContentType(AudioAttributesCompat.CONTENT_TYPE_SPEECH)
|
||||
.build()
|
||||
)
|
||||
.setOnAudioFocusChangeListener(focusChange -> {})
|
||||
.build();
|
||||
private AudioManager mAudioManager;
|
||||
|
||||
private final Bundle mParams = new Bundle();
|
||||
|
||||
|
@ -162,27 +179,27 @@ public enum TtsPlayer
|
|||
mTts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
|
||||
@Override
|
||||
public void onStart(String utteranceId) {
|
||||
mAudioFocusManager.requestAudioFocus();
|
||||
AudioManagerCompat.requestAudioFocus(mAudioManager, mAudioFocusRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDone(String utteranceId) {
|
||||
mAudioFocusManager.releaseAudioFocus();
|
||||
AudioManagerCompat.abandonAudioFocusRequest(mAudioManager, mAudioFocusRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecated") // abstract method must be implemented
|
||||
public void onError(String utteranceId)
|
||||
{
|
||||
mAudioFocusManager.releaseAudioFocus();
|
||||
AudioManagerCompat.abandonAudioFocusRequest(mAudioManager, mAudioFocusRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String utteranceId, int errorCode) {
|
||||
mAudioFocusManager.releaseAudioFocus();
|
||||
AudioManagerCompat.abandonAudioFocusRequest(mAudioManager, mAudioFocusRequest);
|
||||
}
|
||||
});
|
||||
mAudioFocusManager = new AudioFocusManager(context);
|
||||
mAudioManager = ContextCompat.getSystemService(context, AudioManager.class);
|
||||
mParams.putFloat(TextToSpeech.Engine.KEY_PARAM_VOLUME, Config.TTS.getVolume());
|
||||
mInitializing = false;
|
||||
}));
|
||||
|
@ -198,11 +215,10 @@ public enum TtsPlayer
|
|||
if (Config.TTS.isEnabled())
|
||||
try
|
||||
{
|
||||
boolean isMusicActive = mAudioFocusManager.requestAudioFocus();
|
||||
if (isMusicActive)
|
||||
delayHandler.postDelayed(() -> mTts.speak(textToSpeak, TextToSpeech.QUEUE_ADD, mParams, textToSpeak), TTS_SPEAK_DELAY_MILLIS);
|
||||
else
|
||||
mTts.speak(textToSpeak, TextToSpeech.QUEUE_ADD, mParams, textToSpeak);
|
||||
final boolean isMusicActive = mAudioManager.isMusicActive();
|
||||
AudioManagerCompat.requestAudioFocus(mAudioManager, mAudioFocusRequest);
|
||||
final long delay = isMusicActive ? TTS_SPEAK_DELAY_MILLIS : 0;
|
||||
delayHandler.postDelayed(() -> mTts.speak(textToSpeak, TextToSpeech.QUEUE_ADD, mParams, textToSpeak), delay);
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
|
@ -222,7 +238,7 @@ public enum TtsPlayer
|
|||
if (isReady())
|
||||
try
|
||||
{
|
||||
mAudioFocusManager.releaseAudioFocus();
|
||||
AudioManagerCompat.abandonAudioFocusRequest(mAudioManager, mAudioFocusRequest);
|
||||
mTts.stop();
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
|
|
|
@ -18,6 +18,8 @@ import android.view.WindowManager;
|
|||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.activity.result.ActivityResult;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.annotation.AnyRes;
|
||||
import androidx.annotation.AttrRes;
|
||||
import androidx.annotation.ColorInt;
|
||||
|
@ -32,7 +34,6 @@ import androidx.core.graphics.Insets;
|
|||
import androidx.core.view.WindowCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.core.view.WindowInsetsControllerCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
@ -384,10 +385,9 @@ public final class UiUtils
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // https://github.com/organicmaps/organicmaps/issues/3630
|
||||
public static void startActivityForResult(@NonNull Fragment fragment, @NonNull Intent intent, int requestCode)
|
||||
public static void startActivityForResult(ActivityResultLauncher<Intent> startForResult, @NonNull Intent intent)
|
||||
{
|
||||
fragment.startActivityForResult(intent, requestCode);
|
||||
startForResult.launch(intent);
|
||||
}
|
||||
|
||||
// utility class
|
||||
|
|
|
@ -10,6 +10,7 @@ import android.view.KeyEvent;
|
|||
import android.view.View;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
import androidx.activity.result.ActivityResult;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
|
@ -22,7 +23,6 @@ import com.google.android.material.textfield.TextInputEditText;
|
|||
|
||||
public class SearchToolbarController extends ToolbarController implements View.OnClickListener
|
||||
{
|
||||
private static final int REQUEST_VOICE_RECOGNITION = 0xCA11;
|
||||
@Nullable
|
||||
private final View mToolbarContainer;
|
||||
@NonNull
|
||||
|
@ -107,7 +107,7 @@ public class SearchToolbarController extends ToolbarController implements View.O
|
|||
clear();
|
||||
}
|
||||
|
||||
protected void startVoiceRecognition(Intent intent, int code)
|
||||
protected void startVoiceRecognition(Intent intent)
|
||||
{
|
||||
throw new RuntimeException("To be used startVoiceRecognition() must be implemented by descendant class");
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ public class SearchToolbarController extends ToolbarController implements View.O
|
|||
try
|
||||
{
|
||||
startVoiceRecognition(InputUtils.createIntentForVoiceRecognition(
|
||||
requireActivity().getString(getVoiceInputPrompt())), REQUEST_VOICE_RECOGNITION);
|
||||
requireActivity().getString(getVoiceInputPrompt())));
|
||||
}
|
||||
catch (ActivityNotFoundException e)
|
||||
{
|
||||
|
@ -210,14 +210,18 @@ public class SearchToolbarController extends ToolbarController implements View.O
|
|||
UiUtils.showIf(show, mSearchContainer);
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data)
|
||||
public void onVoiceRecognitionResult(ActivityResult activityResult)
|
||||
{
|
||||
if (requestCode == REQUEST_VOICE_RECOGNITION && resultCode == Activity.RESULT_OK)
|
||||
{
|
||||
String result = InputUtils.getBestRecognitionResult(data);
|
||||
if (!TextUtils.isEmpty(result))
|
||||
setQuery(result);
|
||||
}
|
||||
if(activityResult.getResultCode() == Activity.RESULT_OK)
|
||||
{
|
||||
if (activityResult.getData() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
String recognitionResult = InputUtils.getBestRecognitionResult(activityResult.getData());
|
||||
if (!TextUtils.isEmpty(recognitionResult))
|
||||
setQuery(recognitionResult);
|
||||
}
|
||||
}
|
||||
|
||||
public void setHint(@StringRes int hint)
|
||||
|
|
|
@ -11,6 +11,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
|
||||
import app.organicmaps.Framework;
|
||||
import app.organicmaps.MwmActivity;
|
||||
import app.organicmaps.R;
|
||||
import app.organicmaps.base.BaseMwmDialogFragment;
|
||||
import app.organicmaps.bookmarks.data.DistanceAndAzimut;
|
||||
|
@ -46,6 +47,7 @@ public class DirectionFragment extends BaseMwmDialogFragment
|
|||
{
|
||||
final View root = inflater.inflate(R.layout.fragment_direction, container, false);
|
||||
root.setOnTouchListener((v, event) -> {
|
||||
root.performClick();
|
||||
dismiss();
|
||||
return false;
|
||||
});
|
||||
|
@ -99,6 +101,7 @@ public class DirectionFragment extends BaseMwmDialogFragment
|
|||
super.onResume();
|
||||
LocationHelper.from(requireContext()).addListener(this);
|
||||
SensorHelper.from(requireContext()).addListener(this);
|
||||
((MwmActivity) requireActivity()).hideOrShowUIWithoutClosingPlacePage(true);
|
||||
refreshViews();
|
||||
}
|
||||
|
||||
|
@ -110,6 +113,13 @@ public class DirectionFragment extends BaseMwmDialogFragment
|
|||
SensorHelper.from(requireContext()).removeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop()
|
||||
{
|
||||
super.onStop();
|
||||
((MwmActivity) requireActivity()).hideOrShowUIWithoutClosingPlacePage(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationUpdated(@NonNull Location location)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@ package app.organicmaps.widget.placepage;
|
|||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
|
@ -238,6 +239,10 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
|
|||
|
||||
LinearLayout latlon = mFrame.findViewById(R.id.ll__place_latlon);
|
||||
latlon.setOnClickListener(this);
|
||||
LinearLayout openIn = mFrame.findViewById(R.id.ll__place_open_in);
|
||||
openIn.setOnClickListener(this);
|
||||
openIn.setOnLongClickListener(this);
|
||||
openIn.setVisibility(VISIBLE);
|
||||
mTvLatlon = mFrame.findViewById(R.id.tv__place_latlon);
|
||||
mWifi = mFrame.findViewById(R.id.ll__place_wifi);
|
||||
mTvWiFi = mFrame.findViewById(R.id.tv__place_wifi);
|
||||
|
@ -579,6 +584,12 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
|
|||
.apply();
|
||||
refreshLatLon();
|
||||
}
|
||||
else if (id == R.id.ll__place_open_in)
|
||||
{
|
||||
final String uri = Framework.nativeGetGeoUri(mMapObject.getLat(), mMapObject.getLon(),
|
||||
mMapObject.getScale(), mMapObject.getName());
|
||||
Utils.openUri(requireContext(), Uri.parse(uri));
|
||||
}
|
||||
else if (id == R.id.direction_frame)
|
||||
showBigDirection();
|
||||
}
|
||||
|
@ -614,6 +625,12 @@ public class PlacePageView extends Fragment implements View.OnClickListener,
|
|||
items.add(formatted);
|
||||
}
|
||||
}
|
||||
else if (id == R.id.ll__place_open_in)
|
||||
{
|
||||
final String uri = Framework.nativeGetGeoUri(mMapObject.getLat(), mMapObject.getLon(),
|
||||
mMapObject.getScale(), mMapObject.getName());
|
||||
PlacePageUtils.copyToClipboard(requireContext(), mFrame, uri);
|
||||
}
|
||||
else if (id == R.id.ll__place_operator)
|
||||
items.add(mTvOperator.getText().toString());
|
||||
else if (id == R.id.ll__place_network)
|
||||
|
|
11
android/app/src/main/res/drawable/ic_open_in.xml
Normal file
11
android/app/src/main/res/drawable/ic_open_in.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M200,840Q167,840 143.5,816.5Q120,793 120,760L120,200Q120,167 143.5,143.5Q167,120 200,120L480,120L480,200L200,200Q200,200 200,200Q200,200 200,200L200,760Q200,760 200,760Q200,760 200,760L760,760Q760,760 760,760Q760,760 760,760L760,480L840,480L840,760Q840,793 816.5,816.5Q793,840 760,840L200,840ZM388,628L332,572L704,200L560,200L560,120L840,120L840,400L760,400L760,256L388,628Z"/>
|
||||
</vector>
|
|
@ -73,6 +73,8 @@
|
|||
<!-- ToDo: Address is missing compared with iOS. It's shown in title but anyway .. -->
|
||||
|
||||
<include layout="@layout/place_page_latlon"/>
|
||||
|
||||
<include layout="@layout/place_page_open_in"/>
|
||||
</LinearLayout>
|
||||
|
||||
<include
|
||||
|
|
24
android/app/src/main/res/layout/place_page_open_in.xml
Normal file
24
android/app/src/main/res/layout/place_page_open_in.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/ll__place_open_in"
|
||||
style="@style/PlacePageItemFrame"
|
||||
android:tag="open_in"
|
||||
tools:background="#20FF0000"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv__place_open_in"
|
||||
style="@style/PlacePageMetadataIcon"
|
||||
app:srcCompat="@drawable/ic_open_in"
|
||||
app:tint="?colorAccent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv__place_open_in"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/open_in_app"
|
||||
android:textAppearance="@style/MwmTextAppearance.PlacePage.Accent"/>
|
||||
</LinearLayout>
|
|
@ -134,6 +134,7 @@
|
|||
<item name="android:colorPrimaryDark">@android:color/black</item>
|
||||
<item name="android:windowBackground">@color/bg_dialog_translucent</item>
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="MwmMain.DialogFragment.TimePicker" parent="Theme.MaterialComponents.Light.Dialog.Alert">
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
propMinSdkVersion=21
|
||||
propTargetSdkVersion=34
|
||||
propCompileSdkVersion=34
|
||||
propTargetSdkVersion=35
|
||||
propCompileSdkVersion=35
|
||||
|
||||
org.gradle.caching=true
|
||||
org.gradle.jvmargs=-Xmx1024m -Xms256m
|
||||
|
|
BIN
data/World.mwm
BIN
data/World.mwm
Binary file not shown.
Binary file not shown.
4614
data/countries.txt
4614
data/countries.txt
File diff suppressed because it is too large
Load diff
|
@ -596,6 +596,50 @@
|
|||
en = NULL
|
||||
nl = Neem
|
||||
|
||||
[route_recalculating]
|
||||
en = Recalculating the route
|
||||
af = Herbereken die roete
|
||||
ar = إعادة حساب المسار
|
||||
az = Marşrutun yenidən hesablanması
|
||||
be = Пераразлік маршруту
|
||||
bg = Преизчисляване на маршрута
|
||||
ca = Recalcular el recorregut
|
||||
cs = Přepočítání trasy
|
||||
da = Genberegning af ruten
|
||||
de = Neuberechnung der Route
|
||||
el = Επαναϋπολογισμός της διαδρομής
|
||||
es = Recalcular la ruta
|
||||
et = Marsruudi ümberarvutamine
|
||||
eu = Ibilbidea berriro kalkulatzea
|
||||
fa = محاسبه مجدد مسیر
|
||||
fi = Reitin uudelleenlaskenta
|
||||
fr = Recalcul de l'itinéraire
|
||||
he = חישוב מחדש של המסלול
|
||||
hi = मार्ग की पुनर्गणना
|
||||
hu = Az útvonal újraszámítása
|
||||
id = Menghitung ulang rute
|
||||
it = Ricalcolo del percorso
|
||||
ja = ルートの再計算
|
||||
ko = 경로 다시 계산하기
|
||||
lt = Maršruto perskaičiavimas
|
||||
mr = मार्गाची पुनर्गणना करत आहे
|
||||
nb = Beregner ruten på nytt
|
||||
nl = De route herberekenen
|
||||
pl = Ponowne obliczanie trasy
|
||||
pt = Recalcular o itinerário
|
||||
pt-BR = Recalcular a rota
|
||||
ro = Recalcularea traseului
|
||||
ru = Перерасчет маршрута
|
||||
sk = Prepočítanie trasy
|
||||
sv = Omberäkning av rutten
|
||||
sw = Kuhesabu upya njia
|
||||
th = การคำนวณเส้นทางใหม่
|
||||
tr = Rotanın yeniden hesaplanması
|
||||
uk = Перерахунок маршруту
|
||||
vi = Tính toán lại lộ trình
|
||||
zh-Hans = 重新计算路线
|
||||
zh-Hant = 重新計算路
|
||||
|
||||
[destination]
|
||||
en = You’ll arrive.
|
||||
ar = سوف تصل.
|
||||
|
|
|
@ -30853,7 +30853,7 @@
|
|||
|
||||
[open_in_app]
|
||||
comment = Title for the "Open In Another App" button on the PlacePage.
|
||||
tags = ios
|
||||
tags = android,ios
|
||||
en = Open In Another App
|
||||
af = Maak oop in 'n ander toepassing
|
||||
ar = فتح في تطبيق آخر
|
||||
|
|
|
@ -12855,6 +12855,9 @@
|
|||
af = Pad
|
||||
ar = مسار
|
||||
az = Yol
|
||||
be = Сцежка
|
||||
bg = Път
|
||||
ca = Camí
|
||||
cs = Cesta
|
||||
da = Sti
|
||||
de = Pfad
|
||||
|
@ -12872,16 +12875,17 @@
|
|||
it = Sentiero
|
||||
ja = 歩道
|
||||
ko = 길
|
||||
lt = Kelias
|
||||
mr = पथ
|
||||
nb = Sti
|
||||
nl = Pad
|
||||
pl = Ścieżka
|
||||
pt = Caminho
|
||||
pt-BR = Caminho
|
||||
ro = Cale
|
||||
ru = Тропа
|
||||
sk = Cesta
|
||||
sv = Gångväg
|
||||
sw = Njia
|
||||
th = เส้นทาง
|
||||
tr = Yol
|
||||
uk = Стежка
|
||||
|
@ -12893,19 +12897,93 @@
|
|||
comment = Hiking trail tagged as sac_scale=demanding_mountain_hiking (3 of 6) or trail_visibility=bad.
|
||||
ref = type.highway.path
|
||||
en = Difficult or Indistinct Trail
|
||||
af = Moeilike of swak sigbare roete
|
||||
ar = درب صعب أو ضعيف الرؤية
|
||||
az = Çətin və ya zəif görünən cığır
|
||||
be = Складаная ці дрэнна бачная сцежка
|
||||
bg = Трудна или слабо видима пътека
|
||||
ca = Ruta difícil o poc visible
|
||||
cs = Obtížná nebo špatně viditelná stezka
|
||||
da = Vanskelig eller dårligt synlig sti
|
||||
de = Schwieriger oder kaum erkennbarer Pfad
|
||||
he = רמה 3/6) שביל קשה או לא ברור)
|
||||
el = Δύσκολη ή ελάχιστα ορατή διαδρομή
|
||||
es = Sendero difícil o poco visible
|
||||
et = Raske või halvasti nähtav rada
|
||||
eu = Ibilbide zaila edo gaizki ikusten da
|
||||
fa = مسیر دشوار یا ضعیف قابل مشاهده است
|
||||
fi = Vaikea tai huonosti näkyvä reitti
|
||||
fr = Sentier difficile ou peu visibl
|
||||
he = שביל קשה או לא נראה לעין
|
||||
hi = कठिन या ख़राब दिखाई देने वाला मार्ग
|
||||
hu = Nehéz vagy rosszul látható nyomvonal
|
||||
id = Jejak yang sulit atau kurang terlihר)
|
||||
it = Sentiero difficile o poco tracciato
|
||||
ja = 困難な、または見通しの悪いトレイル
|
||||
ko = 어렵거나 잘 보이지 않는 트레일
|
||||
lt = Sudėtingas arba blogai matomas takas
|
||||
mr = अवघड किंवा खराब दृश्यमान पायवाट
|
||||
nb = Vanskelig eller dårlig synlig sti
|
||||
nl = Moeilijk of slecht zichtbaar pad
|
||||
pl = Trudny lub słabo widoczny szlak
|
||||
pt = Trilho difícil ou pouco visível
|
||||
pt-BR = Trilha difícil ou pouco visível
|
||||
ro = Traseu dificil sau puțin vizibil
|
||||
ru = Сложная или плохо видимая тропа
|
||||
sk = Náročná alebo zle viditeľná trasa
|
||||
sv = Svår eller dåligt synlig led
|
||||
sw = Njia ngumu au isiyoonekana vizuri
|
||||
th = เส้นทางที่ยากลำบากหรือมองเห็นได้ไม่ดี
|
||||
tr = Zor veya kötü görünür patika
|
||||
uk = Складна або погано видима стежка
|
||||
vi = Đường đi khó hoặc khó nhìn thấy
|
||||
zh-Hans = 难走或难见的小路
|
||||
zh-Hant = 困難或不明顯的小路
|
||||
|
||||
[type.highway.path.expert]
|
||||
comment = Hiking trail tagged as sac_scale=alpine_hiking (4+ of 6) or trail_visibility=horrible or more extreme.
|
||||
ref = type.highway.path
|
||||
en = Expert or Indiscernible Trail
|
||||
af = Baie moeilike of ononderskeibare roete
|
||||
ar = أثر صعب للغاية أو لا يمكن تمييزه
|
||||
az = Çox çətin və ya fərqlənməyən cığır
|
||||
be = Вельмі складаная ці неадметная сцежка
|
||||
bg = Много трудна или неразличима пътека
|
||||
ca = Sender molt difícil o indistingible
|
||||
cs = Velmi obtížná nebo nezřetelná stopa
|
||||
da = Meget svær eller umulig at skelne fra hinanden
|
||||
de = Alpinwanderweg oder wegloser Pfad
|
||||
he = רמה 4+/6) מסלול למומחים או ללא שבילים מסודרים)
|
||||
el = Πολύ δύσκολο ή δυσδιάκριτο μονοπάτι
|
||||
es = Sendero muy difícil o indistinguible
|
||||
et = Väga raske või eristamatu rada
|
||||
eu = Oso bide zaila edo bereiztezina
|
||||
fa = مسیر بسیار دشوار یا غیر قابل تشخیص
|
||||
fi = Erittäin vaikea tai erottamaton jälki
|
||||
fr = Sentier très difficile ou indiscernabl
|
||||
he = מסלול קשה מאוד או בלתי ניתן להבחנה
|
||||
hi = बहुत कठिन या अप्रभेद्य पथ
|
||||
hu = Nagyon nehéz vagy megkülönböztethetetlen nyomvonal
|
||||
id = Jejak yang sangat sulit atau tidak dapat dibedakם)
|
||||
it = Sentiero estremamente difficile o molto poco tracciato
|
||||
ja = 非常に難しい、または区別がつかないトレイル
|
||||
ko = 매우 어렵거나 구별하기 어려운 흔적
|
||||
lt = Labai sudėtingas arba neišsiskiriantis takas
|
||||
mr = अतिशय अवघड किंवा वेगळे न करता येणारी पायवाट
|
||||
nb = Svært vanskelig eller umulig å skille ut stien
|
||||
nl = Zeer moeilijk of niet te onderscheiden spoor
|
||||
pl = Bardzo trudny lub nierozróżnialny szlak
|
||||
pt = Trilho muito difícil ou indistinguível
|
||||
pt-BR = Trilha muito difícil ou indistinguível
|
||||
ro = Traseu foarte dificil sau imposibil de distins
|
||||
ru = Очень сложная или неразличимая тропа
|
||||
sk = Veľmi náročná alebo nezreteľná stopa
|
||||
sv = Mycket svår eller omöjlig att urskilja spår
|
||||
sw = Njia ngumu sana au isiyoweza kutofautishwa
|
||||
th = เส้นทางที่ยากมากหรือแยกไม่ออก
|
||||
tr = Çok zor veya ayırt edilemeyen iz
|
||||
uk = Дуже складна або невиразна стежка
|
||||
vi = Đường đi rất khó khăn hoặc không thể phân biệt được
|
||||
zh-Hans = 非常困难或难以分辨的路径
|
||||
zh-Hant = 非常困難或難以區分的路線
|
||||
|
||||
[type.highway.path.bicycle]
|
||||
ref = type.highway.path
|
||||
|
|
|
@ -396,7 +396,7 @@ This is important, otherwise the following menus won't be visible.
|
|||
Install Android SDK and NDK:
|
||||
|
||||
- Open "SDK Manager" (under "More Actions" in a welcome screen or a three-dot menu in a list of recent projects screen or "Tools" top menu item in an open project).
|
||||
- Select "Android 14.0 ("Upside Down Cake") / API Level 34" SDK.
|
||||
- Select "Android 15.0 ("Vanilla Ice Cream") / API Level 35" SDK.
|
||||
- Switch to "SDK Tools" tab.
|
||||
- Check "Show Package Details" checkbox.
|
||||
- Select "NDK (Side by side)" version **27.0.12077973**.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "ge0/url_generator.hpp"
|
||||
#include "ge0/geo_url_parser.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -9,6 +10,7 @@ using namespace std;
|
|||
namespace
|
||||
{
|
||||
int const kTestCoordBytes = 9;
|
||||
double const kEps = 1e-10;
|
||||
} // namespace
|
||||
|
||||
namespace ge0
|
||||
|
@ -339,4 +341,22 @@ UNIT_TEST(GenerateShortShowMapUrl_UnicodeMixedWithOtherChars)
|
|||
string res = GenerateShortShowMapUrl(0, 0, 19, "Back_in \xe2\x98\x84!\xd1\x8e\xd0\xbc");
|
||||
TEST_EQUAL("om://8wAAAAAAAA/Back%20in_\xe2\x98\x84%21\xd1\x8e\xd0\xbc", res, ());
|
||||
}
|
||||
|
||||
UNIT_TEST(GenerateGeoUri_SmokeTest)
|
||||
{
|
||||
string res = GenerateGeoUri(33.8904075, 35.5066454, 16.5, "Falafel M. Sahyoun");
|
||||
TEST_EQUAL("geo:33.8904075,35.5066454?z=16.5(Falafel%20M.%20Sahyoun)", res, ());
|
||||
|
||||
// geo:33.8904075,35.5066454?z=16.5(Falafel%20M.%20Sahyoun)
|
||||
// geo:33.890408,35.506645?z=16.5(Falafel%20M.%20Sahyoun)
|
||||
|
||||
geo::GeoURLInfo info;
|
||||
geo::GeoParser parser;
|
||||
TEST(parser.Parse(res, info), ());
|
||||
TEST_ALMOST_EQUAL_ABS(info.m_lat, 33.8904075, kEps, ());
|
||||
TEST_ALMOST_EQUAL_ABS(info.m_lon, 35.5066454, kEps, ());
|
||||
TEST_ALMOST_EQUAL_ABS(info.m_zoom, 16.5, kEps, ());
|
||||
TEST_EQUAL(info.m_label, "Falafel M. Sahyoun", ());
|
||||
}
|
||||
|
||||
} // namespace ge0
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#include "ge0/url_generator.hpp"
|
||||
|
||||
#include "coding/url.hpp"
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -83,8 +86,8 @@ namespace ge0
|
|||
{
|
||||
std::string GenerateShortShowMapUrl(double lat, double lon, double zoom, std::string const & name)
|
||||
{
|
||||
size_t constexpr schemaLength = 5; // strlen("om://")
|
||||
std::string urlSample = "om://ZCoordba64";
|
||||
size_t constexpr schemaLength = 18; // strlen("https://omaps.app/")
|
||||
std::string urlSample = "https://omaps.app/ZCoordba64";
|
||||
|
||||
int const zoomI = (zoom <= 4 ? 0 : (zoom >= 19.75 ? 63 : static_cast<int>((zoom - 4) * 4)));
|
||||
urlSample[schemaLength] = Base64Char(zoomI);
|
||||
|
@ -100,6 +103,17 @@ std::string GenerateShortShowMapUrl(double lat, double lon, double zoom, std::st
|
|||
return urlSample;
|
||||
}
|
||||
|
||||
std::string GenerateGeoUri(double lat, double lon, double zoom, std::string const & name)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "geo:" << std::fixed << std::setprecision(7) << lat << ',' << lon << "?z=" << std::setprecision(1) << zoom;
|
||||
|
||||
if (!name.empty())
|
||||
oss << '(' << url::UrlEncode(name) << ')';
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
char Base64Char(int x)
|
||||
{
|
||||
CHECK_GREATER_OR_EQUAL(x, 0, ());
|
||||
|
|
|
@ -19,6 +19,23 @@ inline static int const kMaxCoordBits = kMaxPointBytes * 3;
|
|||
// om://ZCoordba64/Name
|
||||
std::string GenerateShortShowMapUrl(double lat, double lon, double zoomLevel, std::string const & name);
|
||||
|
||||
// Generates a geo: uri.
|
||||
//
|
||||
// - https://datatracker.ietf.org/doc/html/rfc5870
|
||||
// - https://developer.android.com/guide/components/intents-common#Maps
|
||||
// - https://developers.google.com/maps/documentation/urls/android-intents
|
||||
//
|
||||
// URL format:
|
||||
//
|
||||
// +-------------------------------- lat
|
||||
// | +-------------------- lon
|
||||
// | | +---- zoom
|
||||
// | | | +-- url-encoded name
|
||||
// | | | |
|
||||
// | | | |
|
||||
// geo:54.683486138,25.289361259&z=14(Forto%20dvaras)
|
||||
std::string GenerateGeoUri(double lat, double lon, double zoom, std::string const & name);
|
||||
|
||||
// Exposed for testing.
|
||||
char Base64Char(int x);
|
||||
int LatToInt(double lat, int maxValue);
|
||||
|
|
|
@ -242,6 +242,10 @@ void RoutingSession::Reset()
|
|||
m_passedDistanceOnRouteMeters = 0.0;
|
||||
m_isFollowing = false;
|
||||
m_lastCompletionPercent = 0;
|
||||
|
||||
// reset announcement counters
|
||||
m_routingRebuildCount = -1;
|
||||
m_routingRebuildAnnounceCount = 0;
|
||||
}
|
||||
|
||||
void RoutingSession::SetState(SessionState state)
|
||||
|
@ -484,6 +488,14 @@ void RoutingSession::GenerateNotifications(std::vector<std::string> & notificati
|
|||
|
||||
ASSERT(m_route, ());
|
||||
|
||||
// Generate recalculating notification if needed and reset
|
||||
if (m_routingRebuildCount > m_routingRebuildAnnounceCount)
|
||||
{
|
||||
m_routingRebuildAnnounceCount = m_routingRebuildCount;
|
||||
notifications.emplace_back(m_turnNotificationsMgr.GenerateRecalculatingText());
|
||||
return;
|
||||
}
|
||||
|
||||
// Voice turn notifications.
|
||||
if (!m_routingSettings.m_soundDirection)
|
||||
return;
|
||||
|
|
|
@ -234,6 +234,7 @@ private:
|
|||
double m_passedDistanceOnRouteMeters = 0.0;
|
||||
// Rerouting count
|
||||
int m_routingRebuildCount = -1; // -1 for the first rebuild called in BuildRoute().
|
||||
int m_routingRebuildAnnounceCount = 0; // track TTS announcement state (ignore the first build)
|
||||
mutable double m_lastCompletionPercent = 0.0;
|
||||
|
||||
DECLARE_THREAD_CHECKER(m_threadChecker);
|
||||
|
|
|
@ -84,6 +84,11 @@ std::string NotificationManager::GenerateTurnText(uint32_t distanceUnits, uint8_
|
|||
return m_getTtsText.GetTurnNotification({distanceUnits, exitNum, useThenInsteadOfDistance, turn.m_pedestrianTurn, lengthUnits, nextStreetInfo});
|
||||
}
|
||||
|
||||
std::string NotificationManager::GenerateRecalculatingText() const
|
||||
{
|
||||
return m_getTtsText.GetRecalculatingNotification();
|
||||
}
|
||||
|
||||
std::string NotificationManager::GenerateSpeedCameraText() const
|
||||
{
|
||||
return m_getTtsText.GetSpeedCameraNotification();
|
||||
|
|
|
@ -49,6 +49,9 @@ public:
|
|||
measurement_utils::Units GetLengthUnits() const { return m_settings.GetLengthUnits(); }
|
||||
void SetLocaleWithJsonForTesting(std::string const & json, std::string const & locale);
|
||||
|
||||
/// \brief Generate text of route rebuild notification.
|
||||
std::string GenerateRecalculatingText() const;
|
||||
|
||||
/// \brief Generate text of speed camera notification.
|
||||
std::string GenerateSpeedCameraText() const;
|
||||
|
||||
|
|
|
@ -250,6 +250,11 @@ std::string GetTtsText::GetTurnNotification(Notification const & notification) c
|
|||
return out;
|
||||
}
|
||||
|
||||
std::string GetTtsText::GetRecalculatingNotification() const
|
||||
{
|
||||
return GetTextById("route_recalculating");
|
||||
}
|
||||
|
||||
std::string GetTtsText::GetSpeedCameraNotification() const
|
||||
{
|
||||
return GetTextById("unknown_camera");
|
||||
|
|
|
@ -25,6 +25,8 @@ public:
|
|||
|
||||
std::string GetTurnNotification(Notification const & notification) const;
|
||||
|
||||
std::string GetRecalculatingNotification() const;
|
||||
|
||||
std::string GetSpeedCameraNotification() const;
|
||||
|
||||
/// \brief Sets a locale.
|
||||
|
|
Loading…
Add table
Reference in a new issue