Stop Google maps navigation programmatically - android

I currently start Google navigation from my application using something like:
Intent navigationIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:q=" + latLong.getLatitude() + "," + latLong.getLongitude()));
Does anyone know how I can stop the navigation from my own application?
I have tried killing it but it seems I just do not have permission, is there any other way?

Does anyone know how I can stop the navigation from my own application?
You can't. Please allow the user to exit Navigation if and when they feel like it.

There is only one work around which I found,
Re-start the navigation with the current location, hence the navigation will automatically be finished.
public static void startNavigationIntent(Context activity, String destination)
{
Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse("google.navigation:q=" + destination));
activity.startActivity(intent);
}
And then bring your app to the foreground.
Intent bringToForegroundIntent = new Intent(BackgroundLocationService.this, DashboardActivity.class);
bringToForegroundIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(bringToForegroundIntent);

I'm ten years late to answer this question, but just in case someone, like me, was still looking for an answer, I came up with a slightly different solution than the one suggested by Osama Ashraf above.
I tried out restarting the navigation by passing the current location, and it works most of the times, but the solution is not super reliable, as it might be that the current location provided by your app differs a bit from the one shown in Google Maps, and when that happens, it will not detect that the navigation finished automatically.
In order to always stop the navigation, I found out that you can pass a destination that is in a place where it's not possible to calculate a route to, like in the middle of the ocean. For example, using "0.0,0.0" as the coordinates will do the job.
val uriString = "google.navigation:q=0.0,0.0&mode=d"
val intent = Intent(ACTION_VIEW, Uri.parse(uriString)).apply {
addFlags(FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TOP)
}
activity.startActivity(intent)
This will open Google Maps app again, so if you want to go back to your app you will need to launch another Intent to do so, probably after a couple of seconds delay, so it has time to handle the Google Maps Intent first. This is the code I use to do so:
Handler(Looper.getMainLooper()).postDelayed({
val intent = Intent(this, MainActivity::class.java)
intent.flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_REORDER_TO_FRONT
startActivity(intent)
}, 2000)

Related

Calling startActivity from my app to return to Pokemon Go causes Pokemon Go to restart

I'm wondering if there is another way to switch to a different app? The built-in task switcher doesn't cause Pokemon Go to restart. Is there a way to invoke that?
I have been using this to switch from my app and open Pokemon Go
PackageManager manager = context.getPackageManager();
Intent intent = manager.getLaunchIntentForPackage("com.nianticlabs.pokemongo");
intent.addCategory(Intent.CATEGORY_LAUNCHER);
A few months ago, this started Pokemon Go to open to a black screen. The workaround for this was to close Pokemon go, and start Pokemon Go by switching to it through my app. The first time would start with Pokemon Go's loading screen as expected, but would properly switch between apps after that.
The latest release of Pokemon Go seems to have fixed the black screen problem by always restarting Pokemon Go everytime it is switch to. I found this other intent filter in their AndroidManifest.xml and it works, but it also causes the app to restart.
Uri uri = Uri.parse("http://pokemongolive.com/launchapp");
Intent pokemonGoIntent = new Intent(Intent.ACTION_VIEW, uri);
if (pokemonGoIntent.resolveActivity(getPackageManager()) != null)
startActivity(pokemonGoIntent);
Is another way to switch to another app? Even when my app is loaded and running, the built-in task switcher doesn't cause Pokemon Go to restart.
I finally managed to find a solution, after a whole day of testing.
It works for me:
Intent poGoIntent = activity.getPackageManager().getLaunchIntentForPackage("com.nianticlabs.pokemongo");
poGoIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
activity.startActivity(poGoIntent);
Let me know if it helps!
After taking a look at some log files, I saw some suspicious messages. I found the corresponding API calls and this seems to be working for me.
Intent intent = new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(new ComponentName("com.nianticlabs.pokemongo", "com.nianticproject.holoholo.libholoholo.unity.UnityMainActivity"));
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(intent);

Android navigate back to Application from Android Settings

I am having an inconsistent user experience due to the way android navigates back from Android Settings.
In my application the user needs to give my app access to ACTION_USAGE_ACCESS_SETTINGS, which I access with the following:
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
After toggling the setting to on for my application, I need the user to return to my application. The only way to do this that I know of is for them to press the back button on the phone ( would love to know if it is possible to return automatically after the setting has been toggled!!!?!).
Now one of two things will happen:
1) The user has not used android settings recently, so it was not already open ( ie open in the open app drawer). The first press of the back button will take them to my application as desired.
2) The user had used android settings recently. Thus settings was already open in the application drawer. Now when the user presses back, Android will take them back through each setting page they had been using recently (ie the back button takes them through their history in the android settings pages). It may take 2, 3 or 4 presses of the back button to leave Android settings, and return to my application. This is obviously terrible UI/UX, and I was wondering if there is a better way?
I have noticed that when installing Google apps, after toggling the setting to ON, it automatically exits and returns to the application that called the setting. Being able to do that would be ideal, but I just cant work it out.
Thanks!
Ok, so after trying about a millions things, I have come up with 3 different ways to improve my problem.
1) Was provided by #CommonsWare, by removing the FLAG_ACTIVITY_NEW_TASK, it prevented an inconsistent number of back presses needed, and means every time the user would only have to press back twice.
2) Upon further research into the flags, I found that using three combined:
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivity(intent);
reduced the number of back presses required to 1 single back press. This is simple and reasonable user friendly.
3) Using a handler to continuously check for the required permission after the settings intent has fired. This seems a like a bit of a hack, and I can't believe there is not a better way to do this, but it works exactly as it works when using a Google App. Ie, as soon as you switch the toggle to on, it exits the Android Settings page, and returns to your application, where you left off. I am using:
Handler handler = new Handler();
Runnable checkSettingOn = new Runnable() {
#Override
//#TargetApi(23)
public void run() {
Log.d(TAG, "run: 1");
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
Log.d(TAG, "run: 2");
return;
}
if (isAccessGranted()) {
Log.d(TAG, "run: 3");
//You have the permission, re-launch MainActivity
Intent i = new Intent(MainActivity.this, MainActivity.class);
Log.d(TAG, "run: 4");
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
return;
}
handler.postDelayed(this, 200);
}
};
Then when you fire the intent to get to the Android settings page, just be sure to start the handler:
handler.postDelayed(checkSettingOn, 1000);
Hope this helps someone else with a similar issue.
After you have started Settings activity you can run periodical task, that is invoked every, for example 500ms, and checks if permission is granted.
Mark your setup activity with flag singleTask/singleInstance, and start it, if permission is granted. Existing instance of activity will be moved to top.
I did this for notifications access permission.
Extending upon Ufkoku's answer, I used a periodic check on the status of the permission. To get the user back, I used startActivityForResult and finishActivity.
Sample Code : I used this for the "USAGE_ACCESS_SETTINGS".
var intent = Intent("android.settings.USAGE_ACCESS_SETTINGS")
intent.data = Uri.fromParts("package", "com.example.app", null)
startActivityForResult(intent,101)
var timer = Timer(true)
timer.scheduleAtFixedRate(object: TimerTask(){
override fun run(){
if(checkUsageAccessPermission()){ // checkUsageAccessPermission() is a helper function
finishActivity(101)
cancel()
}
}
}, 0, 1000)
The solution from #Geordie Wicks was close to what I was looking for, but it seems like having the Android Settings open before launching your intent would cause the back button to take you to the previous Android Settings screen.
My solution involves two more flags, Intent.FLAG_ACTIVITY_CLEAR_TOP and Intent.FLAG_ACTIVITY_CLEAR_TASK.
You can define your intent as below:
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
From my experience, this will make it so that a back button press will take you back to your application regardless of whether or not the Android Settings were open beforehand.
You can do one thing here. you have to confirm that you only open the settings component that you require to be opened .... Do not open the main settings app. Open only a single component within settings app that you want. So in that way when ever you will press back, you will jump back to your application.
For example if i want to open bluetooth settings in settings
application, I wont open the main Settings app instead i will open
only bluetooth component of settings. In that way when i press back i
will return to my own app because i haven't open the main setting app so i do not need to navigate in it.
ComponentName cn = new ComponentName("com.android.settings",
"com.android.settings.bluetooth.BluetoothSettings");
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts("package", getPackageName(), null); intent.setData(uri); startActivity(intent);
This is also the simplest way to navigate it
Sorry if the answer was late but I left my answer here for others to overcome this problems. To me the problems might be ourself not from Android. For e.g I have a listener, which listen to the state of the switch
setOnCheckedChangeListener { _, _ ->
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data =
Uri.fromParts(
"package",
navigator.activeFragment?.activity?.packageName,
null
)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
navigator.activeFragment?.startActivity(intent)
}
What happened with this code?
The user go to Setting and then navigate back. If you have set something that update the UI like belows here after user go back, then this will cause multiple listener listen to the change of switch
override fun onResume() {
super.onResume()
if (!isFirst) {
// Notify that user might have change the notification setting
(binding.rvSetting2.adapter as SettingAdapter).notifyItemChanged(0)
}
isFirst = false
My solution
You may add this line inside the listener, this will remove the current switch listener, which can avoid go to Setting after and after when switch change.
setOnCheckedChangeListener { _, _ ->
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data =
Uri.fromParts(
"package",
navigator.activeFragment?.activity?.packageName,
null
)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
navigator.activeFragment?.startActivity(intent)
// Remove the current listener in case of user went back from Setting and call on bind view holder again
// This cause multiple listener listen to the change of this switch
setOnCheckedChangeListener(null)
}
I know that this is just my personal solution, but if you share similar ways, this might be help.
You have to confirm that you only open the settings of your app that you require to be opened. Do not open the main settings app. Open only your app settings that you want. So in that way whenever you will press back, you will jump back to your application.
Uri uri = Uri.fromParts("package", getPackageName(), null);
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(uri);
startActivity(intent);

Is it possible to programmatically access the Google Maps' navigation history?

I wonder if it possible to retrieve the Google Maps navigation history. In other words, is there a way of retrieving the recent routes taken/searched by the user of the Google Maps app?
Thanks
You can not finish Google Navigation App.
There is only one work around which I found,
Re-start the navigation with the current location, hence the navigation will automatically be finished.
public static void startNavigationIntent(Context activity, String destination)
{
Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse("google.navigation:q=" + destination));
activity.startActivity(intent);
}
And then bring your app to the foreground.
Intent bringToForegroundIntent = new Intent(BackgroundLocationService.this, DashboardActivity.class);
bringToForegroundIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(bringToForegroundIntent);
There is no API available to get information out of the Navigation App. But you can feed some data to Maps to request a route through an Intent / URI.
But I don't think that the Maps app will save the whole route anyway, only the destination. The user selects any saved destination and you can get there from any source.

Start Google Navigation from another Activity without setting a location

This is probably really stupid of me but how do I start google navigation WITHOUT setting a location as a lot of issues seem to come from... When I try to do this it actually starts to run Google Navigation but then just keeps restarting the Activity... Essentially I was it to run just like when you click on Navigation like you would from a home screen... So with the list of destinations etc... I presume this is a different activity maybe? I've no idea, the intent I'm using is below,
Intent i = new Intent(Intent.ACTION_VIEW);
i.setClassName("com.google.android.apps.maps", "com.google.android.maps.driveabout.app.NavigationActivity");
getContext().startActivity(i);
Finally found what Activity it is that needs starting!!!
Intent i = new Intent();
i.setClassName("com.google.android.apps.maps","com.google.android.maps.driveabout.app.DestinationActivity");
startActivity(i);

Problem launching Google Navigation

i tried since many hours to launch navigation from my app.
I want navigation without destination.
i tried with
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("google.navigation:q="));
startActivity(i);
That launches navigation but with destination not found
I tried too to launch processName, packageName with startIntent with com.google.android.apps.maps,
com.google.android.apps.maps:driveabout and
**com.google.android.maps.driveabout.app.DestinationActivity
with no succes too :/
an idea ?
Google Navigation does not have any documented and supported Intent filters. It is not designed to be integrated from third party apps.
The following code should work...
String url = "google.navigation:q="+startPos.getLatitude()+","+startPos.getLongitude();
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(i);
Take a closer look a the intent filter for Google Navigation. It could be that it is not designed to be started via Intent without a specified destination. Unfortunately, i don't know where to find information about Google Navigation's intent filter, but if you were to show me where you are looking i could help you figure it out.
Try using
google.navigation:fd=true
i don't want to integrate it, i just want to launch it like a click on the list of apps whith a home launcher.
I've tried the google home sample, and navigation can be launched.
but i don't understand why that doesn't work with my own app :/

Categories

Resources