2024-01-10 18:54:00 +01:00
|
|
|
/* Copyright (C) 2021-2024 Andreas Shimokawa, Arjan Schrijver, Gordon
|
|
|
|
Williams, José Rebelo
|
|
|
|
|
|
|
|
This file is part of Gadgetbridge.
|
|
|
|
|
|
|
|
Gadgetbridge is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Affero General Public License as published
|
|
|
|
by the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Gadgetbridge is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Affero General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
2021-10-19 14:32:20 +02:00
|
|
|
package nodomain.freeyourgadget.gadgetbridge.externalevents;
|
|
|
|
|
|
|
|
import android.app.Application;
|
|
|
|
import android.content.ComponentName;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.ServiceConnection;
|
2023-11-02 17:33:01 +01:00
|
|
|
import android.content.pm.PackageManager;
|
2021-10-19 14:32:20 +02:00
|
|
|
import android.os.IBinder;
|
2023-05-22 12:57:15 +02:00
|
|
|
import android.os.PowerManager;
|
2021-10-19 14:32:20 +02:00
|
|
|
import android.os.RemoteException;
|
|
|
|
import android.view.KeyEvent;
|
|
|
|
|
|
|
|
import net.osmand.aidlapi.IOsmAndAidlCallback;
|
|
|
|
import net.osmand.aidlapi.IOsmAndAidlInterface;
|
|
|
|
import net.osmand.aidlapi.gpx.AGpxBitmap;
|
|
|
|
import net.osmand.aidlapi.navigation.ADirectionInfo;
|
|
|
|
import net.osmand.aidlapi.navigation.ANavigationUpdateParams;
|
2021-10-20 14:35:45 +02:00
|
|
|
import net.osmand.aidlapi.navigation.ANavigationVoiceRouterMessageParams;
|
2021-10-19 14:32:20 +02:00
|
|
|
import net.osmand.aidlapi.navigation.OnVoiceNavigationParams;
|
|
|
|
import net.osmand.aidlapi.search.SearchResult;
|
|
|
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2023-11-02 17:33:01 +01:00
|
|
|
import java.util.ArrayList;
|
2021-10-19 14:32:20 +02:00
|
|
|
import java.util.List;
|
|
|
|
|
2021-10-20 22:37:57 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
2023-11-02 17:33:01 +01:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.R;
|
2021-10-20 22:37:57 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.NavigationInfoSpec;
|
2023-05-22 12:57:15 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
2021-10-19 14:32:20 +02:00
|
|
|
|
|
|
|
public class OsmandEventReceiver {
|
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(OsmandEventReceiver.class);
|
|
|
|
|
|
|
|
private final Application app;
|
|
|
|
private IOsmAndAidlInterface mIOsmAndAidlInterface;
|
|
|
|
|
2021-10-20 22:37:57 +02:00
|
|
|
private NavigationInfoSpec navigationInfoSpec = new NavigationInfoSpec();
|
|
|
|
|
2021-10-19 14:32:20 +02:00
|
|
|
private final IOsmAndAidlCallback.Stub mIOsmAndAidlCallback = new IOsmAndAidlCallback.Stub() {
|
|
|
|
@Override
|
|
|
|
public void onSearchComplete(List<SearchResult> resultSet) {
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onUpdate() {
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onAppInitialized() {
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onGpxBitmapCreated(AGpxBitmap bitmap) {
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void updateNavigationInfo(ADirectionInfo directionInfo) {
|
2021-10-20 22:37:57 +02:00
|
|
|
navigationInfoSpec.nextAction = directionInfo.getTurnType();
|
2023-06-12 13:20:43 +02:00
|
|
|
navigationInfoSpec.distanceToTurn = directionInfo.getDistanceTo()+"m";
|
2021-10-20 22:37:57 +02:00
|
|
|
|
2023-05-22 12:57:15 +02:00
|
|
|
if (shouldSendNavigation()) {
|
|
|
|
GBApplication.deviceService().onSetNavigationInfo(navigationInfoSpec);
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG.debug("Distance: {}, turnType: {}", directionInfo.getDistanceTo(), directionInfo.getTurnType());
|
2021-10-19 14:32:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onContextMenuButtonClicked(int buttonId, String pointId, String layerId) {
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onVoiceRouterNotify(OnVoiceNavigationParams params) {
|
2021-10-20 22:37:57 +02:00
|
|
|
List<String> played = params.getPlayed();
|
|
|
|
for (String instuction : played) {
|
|
|
|
navigationInfoSpec.instruction = instuction;
|
2023-05-22 12:57:15 +02:00
|
|
|
LOG.debug("instruction: {}", instuction);
|
2021-10-20 22:37:57 +02:00
|
|
|
// only first one for now
|
|
|
|
break;
|
2021-10-20 14:35:45 +02:00
|
|
|
}
|
2021-10-19 14:32:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onKeyEvent(KeyEvent keyEvent) {
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
private final ServiceConnection mConnection = new ServiceConnection() {
|
|
|
|
public void onServiceConnected(ComponentName className,
|
|
|
|
IBinder service) {
|
|
|
|
mIOsmAndAidlInterface = IOsmAndAidlInterface.Stub.asInterface(service);
|
2023-05-22 12:57:15 +02:00
|
|
|
LOG.info("OsmAnd service connected");
|
2021-10-19 14:32:20 +02:00
|
|
|
registerForNavigationUpdates(true, 6666); // what is this id for?
|
2023-05-22 12:57:15 +02:00
|
|
|
registerForVoiceRouterMessages(true, 6667);
|
2021-10-20 14:35:45 +02:00
|
|
|
// Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("osmand.api://GET_INFO"));
|
|
|
|
// OsmandEventReceiver.this.startActivityForResult(intent,666);
|
2021-10-19 14:32:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void onServiceDisconnected(ComponentName className) {
|
|
|
|
mIOsmAndAidlInterface = null;
|
2023-05-22 12:57:15 +02:00
|
|
|
LOG.info("OsmAnd service disconnected");
|
2021-10-19 14:32:20 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
public OsmandEventReceiver(Application application) {
|
|
|
|
this.app = application;
|
|
|
|
if (!bindService()) {
|
|
|
|
LOG.warn("Could not bind to OsmAnd");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean bindService() {
|
|
|
|
if (mIOsmAndAidlInterface == null) {
|
2023-11-02 17:33:01 +01:00
|
|
|
List<CharSequence> installedOsmandPackages = findInstalledOsmandPackages();
|
|
|
|
if (installedOsmandPackages.isEmpty()) {
|
|
|
|
LOG.warn("OsmAnd is not installed");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
Prefs prefs = GBApplication.getPrefs();
|
|
|
|
String packageName = prefs.getString("pref_key_osmand_packagename", "autodetect");
|
|
|
|
if (packageName.equals("autodetect")) packageName = installedOsmandPackages.get(0).toString();
|
2021-10-19 14:32:20 +02:00
|
|
|
Intent intent = new Intent("net.osmand.aidl.OsmandAidlServiceV2");
|
2023-11-02 17:33:01 +01:00
|
|
|
intent.setPackage(packageName);
|
2021-10-19 14:32:20 +02:00
|
|
|
boolean res = app.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
|
|
|
if (res) {
|
2023-11-02 17:33:01 +01:00
|
|
|
LOG.info("Bound to OsmAnd service (package "+packageName+")");
|
2021-10-19 14:32:20 +02:00
|
|
|
return true;
|
|
|
|
} else {
|
2023-11-02 17:33:01 +01:00
|
|
|
LOG.warn("Could not bind to OsmAnd service (package "+packageName+")");
|
2021-10-19 14:32:20 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void cleanupResources() {
|
|
|
|
if (mIOsmAndAidlInterface != null) {
|
|
|
|
app.unbindService(mConnection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public long registerForNavigationUpdates(boolean subscribeToUpdates, long callbackId) {
|
|
|
|
if (mIOsmAndAidlInterface != null) {
|
|
|
|
try {
|
|
|
|
ANavigationUpdateParams params = new ANavigationUpdateParams();
|
|
|
|
params.setCallbackId(callbackId);
|
|
|
|
params.setSubscribeToUpdates(subscribeToUpdates);
|
|
|
|
|
|
|
|
return mIOsmAndAidlInterface.registerForNavigationUpdates(params, mIOsmAndAidlCallback);
|
|
|
|
} catch (RemoteException e) {
|
2023-11-02 17:33:01 +01:00
|
|
|
LOG.error("could not subscribe to navigation updates", e);
|
2021-10-19 14:32:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1L;
|
|
|
|
}
|
|
|
|
|
2023-05-22 12:57:15 +02:00
|
|
|
private boolean shouldSendNavigation() {
|
2023-11-19 21:08:22 +01:00
|
|
|
Prefs prefs = GBApplication.getPrefs();
|
2023-05-22 12:57:15 +02:00
|
|
|
|
2023-11-19 21:08:22 +01:00
|
|
|
boolean navigationForward = prefs.getBoolean("navigation_forward", true);
|
|
|
|
boolean navigationOsmAnd = prefs.getBoolean("navigation_app_osmand", true);
|
|
|
|
if (!navigationForward || !navigationOsmAnd) {
|
2023-05-22 12:57:15 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-11-19 21:08:22 +01:00
|
|
|
boolean navigationScreenOn = prefs.getBoolean("nagivation_screen_on", true);
|
2023-05-22 12:57:15 +02:00
|
|
|
if (!navigationScreenOn) {
|
2023-11-19 21:08:22 +01:00
|
|
|
PowerManager powermanager = (PowerManager) app.getSystemService(Context.POWER_SERVICE);
|
2023-05-22 12:57:15 +02:00
|
|
|
if (powermanager != null && powermanager.isScreenOn()) {
|
|
|
|
LOG.info("Not forwarding navigation instructions, screen seems to be on and settings do not allow this");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-11-02 17:33:01 +01:00
|
|
|
/**
|
|
|
|
* Method to register for Voice Router voice messages during navigation. Notifies user about voice messages.
|
|
|
|
*
|
|
|
|
* @param subscribeToUpdates (boolean) - boolean flag to subscribe or unsubscribe from messages
|
|
|
|
* @param callbackId (long) - id of callback, needed to unsubscribe from messages
|
|
|
|
*/
|
|
|
|
public long registerForVoiceRouterMessages(boolean subscribeToUpdates, long callbackId) {
|
|
|
|
ANavigationVoiceRouterMessageParams params = new ANavigationVoiceRouterMessageParams();
|
|
|
|
params.setCallbackId(callbackId);
|
|
|
|
params.setSubscribeToUpdates(subscribeToUpdates);
|
|
|
|
if (mIOsmAndAidlInterface != null) {
|
|
|
|
try {
|
|
|
|
return mIOsmAndAidlInterface.registerForVoiceRouterMessages(params, mIOsmAndAidlCallback);
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
LOG.error("could not register for voice router messages", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1L;
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<CharSequence> findInstalledOsmandPackages() {
|
|
|
|
List<CharSequence> installedPackages = new ArrayList<>();
|
|
|
|
for (String knownPackage : app.getBaseContext().getResources().getStringArray(R.array.osmand_package_names)) {
|
|
|
|
if (isPackageInstalled(knownPackage)) {
|
|
|
|
installedPackages.add(knownPackage);
|
2021-10-20 14:35:45 +02:00
|
|
|
}
|
|
|
|
}
|
2023-11-02 17:33:01 +01:00
|
|
|
return installedPackages;
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean isPackageInstalled(final String packageName) {
|
|
|
|
try {
|
|
|
|
return app.getBaseContext().getPackageManager().getApplicationInfo(packageName, 0).enabled;
|
|
|
|
} catch (PackageManager.NameNotFoundException e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2021-10-19 14:32:20 +02:00
|
|
|
}
|