Merge remote-tracking branch 'origin/master'

This commit is contained in:
Weblate 2018-03-08 10:09:22 +01:00
commit e1e61349d3
37 changed files with 10 additions and 6202 deletions

View file

@ -5,7 +5,7 @@ import net.osmand.render.RenderingRuleSearchRequest;
public class RenderingContext {
static enum ShadowRenderingMode {
public static enum ShadowRenderingMode {
// int shadowRenderingMode = 0; // no shadow (minumum CPU)
// int shadowRenderingMode = 1; // classic shadow (the implementaton in master)
// int shadowRenderingMode = 2; // blur shadow (most CPU, but still reasonable)

View file

@ -81,9 +81,9 @@ public class BinaryInspector {
// "-lang=ru",
// "-bbox=30.4981,50.4424,30.5195,50.4351",
// "-osm="+System.getProperty("maps.dir")+"/map_full_1.obf.osm",
System.getProperty("maps.dir")+"/diff/Bulgaria_europe_01_00.obf"
// System.getProperty("maps.dir")+"/diff/Bulgaria_europe_01_00.obf"
// System.getProperty("maps.dir")+"/diff/Diff.obf"
// System.getProperty("maps.dir")+"/Ukraine_kiev-city_europe_2.obf"
System.getProperty("maps.dir")+"/Map.obf"
});
} else {
in.inspector(args);

View file

@ -2061,7 +2061,7 @@ public class BinaryMapIndexReader {
private static boolean testAddressSearch = false;
private static boolean testAddressSearchName = false;
private static boolean testAddressJustifySearch = false;
private static boolean testPoiSearch = false;
private static boolean testPoiSearch = true;
private static boolean testPoiSearchOnPath = false;
private static boolean testTransportSearch = true;
@ -2227,7 +2227,7 @@ public class BinaryMapIndexReader {
private static void testPoiSearchByName(BinaryMapIndexReader reader) throws IOException {
println("Searching by name...");
SearchRequest<Amenity> req = buildSearchPoiRequest(0, 0, "Belar",
SearchRequest<Amenity> req = buildSearchPoiRequest(0, 0, "Art",
0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, null);
reader.searchPoiByName(req);
@ -2360,7 +2360,7 @@ public class BinaryMapIndexReader {
public boolean isCancelled() {
return false;
}
}, "Красноарм", StringMatcherMode.CHECK_ONLY_STARTS_WITH);
}, "Guy'", StringMatcherMode.CHECK_ONLY_STARTS_WITH);
// req.setBBoxRadius(52.276142, 4.8608723, 15000);
reader.searchAddressDataByName(req);
}

View file

@ -1,61 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:stretchColumns="1">
<TableRow>
<TextView
android:id="@+id/LabelTrackerId"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_connect_to_device_tracker_id" />
<EditText
android:id="@+id/TrackerId"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="textCapCharacters"
android:paddingLeft="3dp"
android:selectAllOnFocus="true" />
</TableRow>
<TableRow>
<TextView
android:id="@+id/LabelName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_connect_to_device_name" />
<EditText
android:id="@+id/Name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="textCapWords"
android:paddingLeft="3dp" />
</TableRow>
<TableRow
android:id="@+id/MyGroupName"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_connect_to_my_nickname" />
<EditText
android:id="@+id/NickName"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="textCapWords"
android:paddingLeft="3dp" />
</TableRow>
</TableLayout>

View file

@ -1,105 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingBottom="@dimen/dialog_content_bottom_margin"
android:paddingLeft="@dimen/dialog_content_margin"
android:paddingRight="@dimen/dialog_content_margin"
android:paddingTop="@dimen/dialog_content_bottom_margin">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingLeft="7dp"
android:paddingRight="7dp"
android:stretchColumns="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_group_name"/>
<EditText
android:id="@+id/Name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/textLengthAlert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_grop_name_length_alert"
android:textColor="@color/osmbug_closed"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_group_description"/>
<EditText
android:id="@+id/Description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_group_policy"/>
<EditText
android:id="@+id/Policy"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_group_by_invite"/>
<CheckBox
android:id="@+id/OnlyByInvite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/osmo_group_create_info"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:text="@string/osmo_group_information"
android:textSize="@dimen/default_list_text_size"/>
<ImageButton
android:id="@+id/info"
android:contentDescription="@string/osmo_group_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/dashboard_button"
android:src="@drawable/ic_action_gabout_dark"/>
</LinearLayout>
<TextView
android:id="@+id/osmo_group_create_dinfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_group_information_desc"
android:textSize="@dimen/default_desc_text_size"
android:visibility="gone"/>
</LinearLayout>
</ScrollView>

View file

@ -1,46 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/dialog_content_bottom_margin"
android:paddingTop="@dimen/dialog_content_bottom_margin"
android:paddingLeft="@dimen/dialog_content_margin"
android:paddingRight="@dimen/dialog_content_margin"
android:stretchColumns="1">
<TableRow>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_connect_to_device_name" />
<EditText
android:id="@+id/Name"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp">
<requestFocus />
</EditText>
</TableRow>
<TableRow
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/osmo_edit_color" />
<Spinner
android:id="@+id/ColorSpinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp" />
</TableRow>
</TableLayout>

View file

@ -1,47 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="5dp"
android:paddingLeft="3dp"
android:paddingRight="4dp"
android:paddingTop="5dp">
<CheckBox
android:id="@+id/settings"
android:contentDescription="@string/osmo_settings"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:layout_gravity="center_vertical"
android:focusable="false"/>
<ImageView
android:id="@+id/explist_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingLeft="6dp"/>
<TextView
android:id="@+id/category_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="8dp"
android:layout_marginTop="0dp"
android:layout_weight="1"
android:maxLines="1"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/default_list_text_size"
tools:text="@string/lorem_ipsum"/>
<include layout="@layout/check_item_rel"/>
</LinearLayout>

View file

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:id="@+id/memory_size"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="3dp"
android:text=""
android:visibility="gone" />
<ExpandableListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
android:layout_weight="1"
android:groupIndicator="@android:color/transparent"/>
<net.osmand.plus.activities.search.toolbar.SplitToolbar
android:id="@+id/bottomControls"
android:background="?attr/bottomToolBarColor"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

View file

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="?attr/expandable_list_item_background"
android:orientation="horizontal"
android:paddingBottom="5dp"
android:paddingLeft="8dp"
android:paddingRight="4dp"
android:paddingTop="5dp">
<ImageView
android:id="@+id/osmo_user_icon"
android:layout_width="26dp"
android:layout_height="26dp"
android:paddingRight="2dp"
android:paddingTop="2dp"/>
<TextView
android:id="@+id/osmo_label"
android:textSize="@dimen/default_list_text_size_large"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="1"
android:maxLines="7"
tools:text="@string/abc_action_bar_home_description"
android:textColor="?android:textColorPrimary"/>
<TextView
android:id="@+id/osmo_label_time"
android:textSize="@dimen/default_list_text_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"/>
<!-- <include layout="@layout/check_item" /> -->
</LinearLayout>

View file

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<include layout="@layout/osmo_groups_list_header" />
<ExpandableListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:layout_marginTop="0dp"
android:layout_weight="1"
android:groupIndicator="@android:color/transparent"/>
</LinearLayout>

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/osmo_no_connection_msg"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:autoLink="web"
android:linksClickable="true"
android:padding="10dp"
android:text="@string/osmo_no_connection_msg"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>

View file

@ -1,75 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="?attr/osmo_header_background"
android:orientation="vertical"
android:paddingRight="@dimen/list_content_padding">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/list_item_height"
android:orientation="horizontal">
<ImageView
android:id="@+id/osmo_status"
android:layout_width="@dimen/list_item_height"
android:layout_height="@dimen/list_item_height"
android:layout_gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/mon_osmo_conn_small"/>
<include
android:id="@+id/enable_service"
layout="@layout/check_item"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:focusable="false"
android:text="@string/osmo_start_service"
android:textColor="@color/color_white"/>
</LinearLayout>
<LinearLayout
android:id="@+id/share_my_location_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/list_item_height"
android:orientation="horizontal">
<ImageView
android:id="@+id/share_my_location"
android:contentDescription="@string/shared_string_share"
android:layout_width="@dimen/list_item_height"
android:layout_height="@dimen/list_item_height"
android:layout_gravity="center_vertical"
android:background="?attr/dashboard_button"
android:scaleType="centerInside"
android:src="@drawable/ic_action_gshare_dark"/>
<include
android:id="@+id/enable_tracker"
layout="@layout/check_item"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:checked="false"
android:focusable="false"
android:text="@string/osmo_enable_tracker"
/>
</LinearLayout>
<TextView
android:id="@+id/motd"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/list_content_padding"
android:autoLink="web"
android:gravity="center"
android:textColor="@color/color_white"
android:textSize="@dimen/default_desc_text_size"
android:visibility="gone"/>
</LinearLayout>

View file

@ -571,17 +571,6 @@
<string name="rendering_value_bold_name">Bold</string>
<string name="no_map_markers_found">Please add map markers via map</string>
<string name="no_waypoints_found">No waypoints found</string>
<string name="osmo_group_information_desc">
- Creating a group please give it a name and fill in description\n
- From the application group are created only with Simple type, read more on the website https://osmo.mobi/g/new \n
- Through a website you can manage a group, to place tracks and points available all\n
- We do not endorse the use of the group only one user, if this is not the POI group\n
- Private groups are limited to 8 persons \n
- Detailed terms and conditions always have an on website OsMo.mobi\n
- If you need special conditions - please contact support: osmo.mobi@gmail.com
</string>
<string name="osmo_specify_tracker_id">Please specify ID</string>
<string name="osmo_no_connection_msg">Cannot connect to the server OsMo:\n- check your Internet connection;\n- check the settings;\n- check out our Twitter: https://twitter.com/OsMomobi</string>
<string name="anonymous_user_hint">An anonymous user cannot:\n- create groups;\n- synchronize groups and devices with the server;\n- manage groups and devices in a personal dashboard on website.</string>
<string name="report">Report</string>
<string name="osmo_connect_to_device_tracker_id">Tracker ID</string>

View file

@ -1,10 +0,0 @@
package com.OsMoDroid;
interface IRemoteOsMoDroidListener {
void channelUpdated();
void channelsListUpdated();
void routeTo(float Lat, float Lon);
}

View file

@ -1,66 +0,0 @@
package com.OsMoDroid;
import com.OsMoDroid.IRemoteOsMoDroidListener;
interface IRemoteOsMoDroidService {
void registerListener(IRemoteOsMoDroidListener listener);
void unregisterListener(IRemoteOsMoDroidListener listener);
int getVersion();
int getBackwardCompatibleVersion();
void Deactivate();
void Activate();
boolean isActive();
int getNumberOfLayers();
int getLayerId(int pos);
String getLayerName(int layerId);
String getLayerDescription(int layerId);
int getNumberOfObjects(int layerId);
int getObjectId(int layerId, int pos);
float getObjectLat(int layerId, int objectId);
float getObjectLon(int layerId, int objectId);
String getObjectSpeed(int layerId, int objectId);
String getObjectName(int layerId, int objectId);
String getObjectDescription(int layerId, int objectId);
String getObjectColor(int layerId, int objectId);
int getNumberOfGpx(int layerId);
String getGpxFile (int layerId, int pos);
int getGpxColor (int layerId, int pos);
int getNumberOfPoints(int layerId);
int getPointId(int layerId, int pos);
float getPointLat(int layerId, int pointId);
float getPointLon(int layerId, int pointId);
String getPointName(int layerId, int pointId);
String getPointDescription(int layerId, int pointId);
String getPointColor(int layerId, int pointId);
void refreshChannels();
}

View file

@ -21,7 +21,6 @@ import android.widget.Toast;
import net.osmand.PlatformUtil;
import net.osmand.plus.notifications.OsmandNotification;
import net.osmand.plus.osmo.OsMoPlugin;
public class NavigationService extends Service implements LocationListener {
@ -267,12 +266,6 @@ public class NavigationService extends Service implements LocationListener {
app.getNotificationHelper().removeNotifications();
if (app.getNavigationService() != null &&
app.getSettings().DISABLE_RECORDING_ONCE_APP_KILLED.get()) {
OsMoPlugin plugin = OsmandPlugin.getEnabledPlugin(OsMoPlugin.class);
if (plugin != null) {
if (plugin.getTracker().isEnabledTracker()) {
plugin.getTracker().disableTracker();
}
}
NavigationService.this.stopSelf();
}
}

View file

@ -136,7 +136,6 @@ public abstract class OsmandPlugin {
allPlugins.add(new OsmandRasterMapsPlugin(app));
allPlugins.add(new OsmandMonitoringPlugin(app));
// allPlugins.add(new OsMoPlugin(app));
checkMarketPlugin(app, new SRTMPlugin(app), true, SRTM_PLUGIN_COMPONENT_PAID, SRTM_PLUGIN_COMPONENT);
// ? questionable - definitely not market plugin

View file

@ -1177,23 +1177,6 @@ public class OsmandSettings {
}
}
public final OsmandPreference<String> OSMO_DEVICE_KEY = new StringPreference("osmo_device_token", "").makeGlobal();
public final OsmandPreference<String> OSMO_USER_NAME = new StringPreference("osmo_user_name", "").makeGlobal();
public final OsmandPreference<String> OSMO_USER_PWD = new StringPreference("osmo_user_pwd", null).makeGlobal();
public final OsmandPreference<Boolean> OSMO_AUTO_CONNECT = new BooleanPreference("osmo_automatically_connect", false).makeGlobal();
public final OsmandPreference<Long> OSMO_LAST_PING = new LongPreference("osmo_last_ping", 0).makeGlobal().cache();
public final OsmandPreference<Boolean> OSMO_SEND_LOCATIONS_STATE = new BooleanPreference("osmo_send_locations", false).cache().makeGlobal();
public final OsmandPreference<Boolean> OSMO_SHOW_GROUP_NOTIFICATIONS = new BooleanPreference("osmo_show_toast_notifications", true).makeGlobal();
public final CommonPreference<Integer> OSMO_SAVE_TRACK_INTERVAL = new IntPreference("osmo_save_track_interval", 10000).makeGlobal().cache();
public final OsmandPreference<String> OSMO_GROUPS = new StringPreference("osmo_groups", "{}").makeGlobal();
public final OsmandPreference<Boolean> NO_DISCOUNT_INFO = new BooleanPreference("no_discount_info", false).makeGlobal();

View file

@ -66,8 +66,6 @@ import net.osmand.plus.osmedit.EditPOIMenuController;
import net.osmand.plus.osmedit.OsmBugMenuController;
import net.osmand.plus.osmedit.OsmBugsLayer.OpenStreetNote;
import net.osmand.plus.osmedit.OsmPoint;
import net.osmand.plus.osmo.OsMoGroupsStorage.OsMoDevice;
import net.osmand.plus.osmo.OsMoMenuController;
import net.osmand.plus.parkingpoint.ParkingPositionMenuController;
import net.osmand.plus.resources.ResourceManager;
import net.osmand.plus.transport.TransportStopRoute;
@ -181,8 +179,6 @@ public abstract class MenuController extends BaseMenuController implements Colla
menuController = new HistoryMenuController(mapActivity, pointDescription, (SearchHistoryHelper.HistoryEntry) object);
} else if (object instanceof TargetPoint) {
menuController = new TargetPointMenuController(mapActivity, pointDescription, (TargetPoint) object);
} else if (object instanceof OsMoDevice) {
menuController = new OsMoMenuController(mapActivity, pointDescription, (OsMoDevice) object);
} else if (object instanceof Recording) {
menuController = new AudioVideoNoteMenuController(mapActivity, pointDescription, (Recording) object);
} else if (object instanceof OsmPoint) {

View file

@ -31,7 +31,6 @@ public abstract class OsmandNotification {
public enum NotificationType {
NAVIGATION,
GPX,
OSMO,
GPS
}

View file

@ -1,346 +0,0 @@
package net.osmand.plus.osmo;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.plus.IconsCache;
import net.osmand.plus.NavigationService;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dashboard.DashLocationFragment;
import net.osmand.plus.dashboard.DashboardOnMap;
import net.osmand.plus.dashboard.tools.DashFragmentData;
import net.osmand.plus.osmo.OsMoGroupsStorage.OsMoDevice;
import net.osmand.util.MapUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
/**
* Created by Denis
* on 20.01.2015.
*/
public class DashOsMoFragment extends DashLocationFragment implements OsMoGroups.OsMoGroupsUIListener {
public static final String TAG = "DASH_OSMO_FRAGMENT";
private static final DashFragmentData.ShouldShowFunction SHOULD_SHOW_FUNCTION =
new DashboardOnMap.DefaultShouldShow() {
@Override
public int getTitleId() {
return R.string.osmo_plugin_name;
}
};
static final DashFragmentData FRAGMENT_DATA = new DashFragmentData(
DashOsMoFragment.TAG, DashOsMoFragment.class, SHOULD_SHOW_FUNCTION, 120, null);
private Handler uiHandler = new Handler();
OsMoPlugin plugin;
private CompoundButton trackr;
CompoundButton.OnCheckedChangeListener trackerCheckedChatgedListener = new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
plugin.getService().connect(true);
if (isChecked) {
if (plugin != null && plugin.getTracker() != null) {
plugin.getTracker().enableTracker();
}
getMyApplication().startNavigationService(NavigationService.USED_BY_LIVE, 0);
} else {
if (plugin != null && plugin.getTracker() != null) {
plugin.getTracker().disableTracker();
}
if (getMyApplication().getNavigationService() != null) {
getMyApplication().getNavigationService()
.stopIfNeeded(getMyApplication(), NavigationService.USED_BY_LIVE);
}
}
updateStatus();
}
};
@Override
public void onCloseDash() {
if (plugin != null && plugin.getGroups() != null) {
plugin.getGroups().removeUiListener(this);
}
}
@Override
public View initView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
plugin = OsmandPlugin.getEnabledPlugin(OsMoPlugin.class);
View view = getActivity().getLayoutInflater().inflate(R.layout.dash_osmo_fragment, container, false);
view.findViewById(R.id.manage).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
launchOsMoGroupsActivity();
}
});
if(plugin != null) {
plugin.setGroupsActivity(getActivity());
}
setupHader(view);
return view;
}
@Override
public void onOpenDash() {
plugin = OsmandPlugin.getEnabledPlugin(OsMoPlugin.class);
if (plugin != null) {
plugin.getGroups().addUiListeners(this);
plugin.setGroupsActivity(getActivity());
trackr.setChecked(plugin.getTracker().isEnabledTracker());
trackr.setOnCheckedChangeListener(trackerCheckedChatgedListener);
}
setupOsMoView();
}
@Override
public void onDetach() {
super.onDetach();
if (plugin != null) {
plugin.setGroupsActivity(null);
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (plugin != null) {
plugin.setGroupsActivity(null);
}
}
private void setupOsMoView() {
View mainView = getView();
if (plugin == null) {
mainView.setVisibility(View.GONE);
return;
} else {
mainView.setVisibility(View.VISIBLE);
}
updateStatus();
}
private void setupHader(final View header) {
trackr = (CompoundButton) header.findViewById(R.id.card_content).findViewById(R.id.toggle_item);
ImageButton share = (ImageButton) header.findViewById(R.id.share);
IconsCache cache = getMyApplication().getIconsCache();
share.setImageDrawable(cache.getThemedIcon(R.drawable.ic_action_gshare_dark));
share.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
OsMoGroupsActivity.shareSessionUrl(plugin, getActivity());
}
});
updateStatus();
}
private void updateStatus() {
View header = getView();
if (getView() == null ) {
return;
}
View cardContent = header.findViewById(R.id.card_content);
View enableOsmo = header.findViewById(R.id.header_layout).findViewById(R.id.toggle_item);
View manage = header.findViewById(R.id.manage);
if (plugin != null && plugin.getService().isEnabled() ) {
cardContent.setVisibility(View.VISIBLE);
enableOsmo.setVisibility(View.GONE);
manage.setVisibility(View.VISIBLE);
} else {
cardContent.setVisibility(View.GONE);
enableOsmo.setVisibility(View.VISIBLE);
manage.setVisibility(View.GONE);
getClearContentList(header);
return;
}
CompoundButton trackr = (CompoundButton) header.findViewById(R.id.toggle_item);
if (plugin != null && plugin.getTracker() != null) {
trackr.setChecked(plugin.getTracker().isEnabledTracker());
}
updateConnectedDevices(header);
}
private void updateConnectedDevices(View mainView) {
OsMoGroups grps = plugin.getGroups();
LinearLayout contentList = getClearContentList(mainView);
ArrayList<OsMoGroupsStorage.OsMoGroup> groups = new ArrayList<>(grps.getGroups());
List<OsMoGroupsStorage.OsMoDevice> devices = getOsMoDevices(groups);
setupDeviceViews(contentList, devices);
}
private List<OsMoGroupsStorage.OsMoDevice> getOsMoDevices(ArrayList<OsMoGroupsStorage.OsMoGroup> groups) {
String trackerId = plugin.getService().getMyGroupTrackerId();
List<OsMoGroupsStorage.OsMoDevice> devices = new ArrayList<>();
if (groups.size() > 0) {
for (OsMoGroupsStorage.OsMoGroup grp : groups) {
for (OsMoGroupsStorage.OsMoDevice device : grp.getVisibleGroupUsers(trackerId)) {
devices.add(device);
}
}
}
//remove all inactive devices
Iterator<OsMoDevice> it = devices.iterator();
while (it.hasNext()) {
if (devices.size() < 4) {
break;
}
OsMoGroupsStorage.OsMoDevice device = it.next();
if (!device.isActive() && !device.isEnabled() && devices.size() > 2) {
it.remove();
}
}
sortDevices(devices);
if (devices.size() > 3) {
while (devices.size() > 3) {
devices.remove(devices.size() - 1);
}
}
return devices;
}
private void sortDevices(List<OsMoGroupsStorage.OsMoDevice> devices) {
try {
Collections.sort(devices, new Comparator<OsMoDevice>() {
@Override
public int compare(OsMoDevice lhs, OsMoDevice rhs) {
Location ll = lhs.getLastLocation();
Location rl = rhs.getLastLocation();
double maxDist = 50000;
double ld = ll == null || lastUpdatedLocation == null ? maxDist :
MapUtils.getDistance(lastUpdatedLocation, ll.getLatitude(), ll.getLongitude());
double rd = ll == null || lastUpdatedLocation == null ? maxDist :
MapUtils.getDistance(lastUpdatedLocation, rl.getLatitude(), rl.getLongitude());
if(ld == rd) {
return lhs.getVisibleName().compareTo(rhs.getVisibleName());
}
return Double.compare(ld, rd);
}
});
} catch (RuntimeException e) {
// sorting could be unstable due to location change
e.printStackTrace();
}
}
private LinearLayout getClearContentList(View mainView) {
LinearLayout contentList = (LinearLayout) mainView.findViewById(R.id.items);
contentList.removeAllViews();
return contentList;
}
private void setupDeviceViews(LinearLayout contentList, List<OsMoGroupsStorage.OsMoDevice> devices) {
LayoutInflater inflater = getActivity().getLayoutInflater();
List<DashLocationFragment.DashLocationView> distances = new ArrayList<>();
for (final OsMoGroupsStorage.OsMoDevice device : devices) {
View v = inflater.inflate(R.layout.dash_osmo_item, null, false);
v.findViewById(R.id.people_icon).setVisibility(View.GONE);
v.findViewById(R.id.people_count).setVisibility(View.GONE);
v.findViewById(R.id.show_on_map).setVisibility(View.GONE);
final String name = device.getVisibleName();
final Location loc = device.getLastLocation();
ImageView direction = (ImageView) v.findViewById(R.id.direction_icon);
direction.setVisibility(View.VISIBLE);
TextView label = (TextView) v.findViewById(R.id.distance);
DashLocationFragment.DashLocationView dv = new DashLocationFragment.DashLocationView(direction, label, loc != null ? new LatLon(loc.getLatitude(),
loc.getLongitude()) : null);
distances.add(dv);
final CompoundButton enableDevice = (CompoundButton) v.findViewById(R.id.toggle_item);
enableDevice.setVisibility(View.GONE);
ImageView icon = (ImageView) v.findViewById(R.id.icon);
if (device.isEnabled()) {
icon.setImageDrawable(getMyApplication().getIconsCache().
getPaintedIcon(R.drawable.ic_person, device.getColor()));
} else {
icon.setImageDrawable(getMyApplication().getIconsCache().
getThemedIcon(R.drawable.ic_person));
}
((TextView) v.findViewById(R.id.name)).setText(name);
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (loc == null || !device.isEnabled()) {
launchOsMoGroupsActivity();
} else {
MapActivity.getSingleMapViewTrackingUtilities().setMapLinkedToLocation(false);
getMyApplication().getSettings().setMapLocationToShow(loc.getLatitude(), loc.getLongitude(), getMyApplication().getSettings().getLastKnownMapZoom(),
new PointDescription(PointDescription.POINT_TYPE_MARKER, device.getVisibleName()), false,
device);
OsMoPositionLayer.setFollowTrackerId(device, loc);
MapActivity.launchMapActivityMoveToTop(getActivity());
}
}
});
contentList.addView(v);
}
this.distances = distances;
}
private void launchOsMoGroupsActivity() {
Intent intent = new Intent(getActivity(), OsMoGroupsActivity.class);
getActivity().startActivity(intent);
closeDashboard();
}
@Override
public void groupsListChange(String operation, OsMoGroupsStorage.OsMoGroup group) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
updateStatus();
}
});
}
@Override
public void deviceLocationChanged(OsMoGroupsStorage.OsMoDevice device) {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
updateConnectedDevices(getView());
updateAllWidgets();
}
});
}
}

View file

@ -1,7 +0,0 @@
package net.osmand.plus.osmo;
public class OsMoConnectionException extends RuntimeException {
public OsMoConnectionException(String detailMessage) {
super(detailMessage);
}
}

View file

@ -1,144 +0,0 @@
package net.osmand.plus.osmo;
import java.util.List;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.plus.NavigationService;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.Version;
import net.osmand.plus.TargetPointsHelper.TargetPoint;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.Vibrator;
public class OsMoControlDevice implements OsMoReactor {
private OsMoService service;
private OsmandApplication app;
private OsMoTracker tracker;
private OsMoPlugin plugin;
public OsMoControlDevice(OsmandApplication app, OsMoPlugin plugin,
OsMoService service, OsMoTracker tracker) {
this.app = app;
this.plugin = plugin;
this.service = service;
this.tracker = tracker;
service.registerReactor(this);
}
public JSONObject getBatteryLevel() throws JSONException {
Intent batteryIntent = app.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
int plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
int temperature = batteryIntent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1);
int voltage = batteryIntent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
JSONObject postjson = new JSONObject();
postjson.put("batteryprocent", (level == -1 || scale == -1)? 50.0f : ((float)level / (float)scale) * 100.0f);
postjson.put("temperature", temperature);
postjson.put("voltage", voltage);
postjson.put("plugged", plugged);
return postjson;
}
@Override
public boolean acceptCommand(String command, String id, String data, JSONObject obj, OsMoThread tread) {
if(command.equals("REMOTE_CONTROL")) {
if(data.equals("PP")) {
service.pushCommand("PP");
} else if(data.equals("FF")) {
Location ll = app.getLocationProvider().getLastKnownLocation();
if(ll == null) {
service.pushCommand("FF|0");
} else {
service.pushCommand("FF|"+OsMoTracker.formatLocation(ll));
}
} else if(data.equals("BATTERY_INFO")) {
try {
service.pushCommand("BATTERY_INFO|"+getBatteryLevel().toString());
} catch(JSONException e) {
e.printStackTrace();
}
} else if(data.equals("VIBRATE")) {
Vibrator v = (Vibrator) app.getSystemService(Context.VIBRATOR_SERVICE);
// Vibrate for 500 milliseconds
v.vibrate(1000);
} else if(data.equals("STOP_TRACKING")) {
tracker.disableTracker();
if (app.getNavigationService() != null) {
app.getNavigationService().stopIfNeeded(app, NavigationService.USED_BY_LIVE);
}
} else if(data.equals("START_TRACKING")) {
tracker.enableTrackerCmd();
app.startNavigationService(NavigationService.USED_BY_LIVE, 0);
//interval setting not needed here, handled centrally in app.startNavigationService
//app.getSettings().SERVICE_OFF_INTERVAL.set(0);
} else if(data.equals("OSMAND_INFO")) {
JSONObject robj = new JSONObject();
try {
robj.put("full_version", Version.getFullVersion(app));
robj.put("version", Version.getAppVersion(app));
TargetPointsHelper tg = app.getTargetPointsHelper();
if(tg.getPointToNavigate() != null) {
addPoint(robj, "target_", tg.getPointToNavigate().point, tg.getPointToNavigate().getOriginalPointDescription());
}
List<TargetPoint> intermediatePoints = tg.getIntermediatePoints();
if (intermediatePoints.size() > 0) {
JSONArray ar = new JSONArray();
robj.put("intermediates", ar);
for (int i = 0; i < intermediatePoints.size(); i++) {
JSONObject js = new JSONObject();
ar.put(js);
addPoint(js, "", intermediatePoints.get(i).point, intermediatePoints.get(i).getOriginalPointDescription());
}
}
service.pushCommand("OSMAND_INFO|"+robj.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
return true;
} else if(command.equals("TP")) {
plugin.getDownloadGpxTask(true).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, obj);
} else if (command.equals("PP")) {
service.pushCommand("PP");
}
return false;
}
private void addPoint(JSONObject robj, String prefix, LatLon pointToNavigate, PointDescription pointNavigateDescription) throws JSONException {
robj.put(prefix+"lat", pointToNavigate.getLatitude());
robj.put(prefix+"lon", pointToNavigate.getLongitude());
if(pointNavigateDescription != null) {
robj.put(prefix+"name", pointNavigateDescription.getName());
}
}
@Override
public String nextSendCommand(OsMoThread tracker) {
return null;
}
@Override
public void onConnected() {
}
@Override
public void onDisconnected(String msg) {
}
}

View file

@ -1,498 +0,0 @@
package net.osmand.plus.osmo;
import android.os.AsyncTask;
import com.google.gson.Gson;
import net.osmand.Location;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.GpxSelectionHelper;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.osmo.OsMoGroupsStorage.OsMoDevice;
import net.osmand.plus.osmo.OsMoGroupsStorage.OsMoGroup;
import net.osmand.plus.osmo.OsMoTracker.OsmoTrackerListener;
import net.osmand.util.Algorithms;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class OsMoGroups implements OsMoReactor, OsmoTrackerListener {
private static final String GROUP_NAME = "name";
private static final String ACTIVE = "active";
private static final String GROUP_ID = "group_id";
private static final String EXPIRE_TIME = "expireTime";
private static final String DESCRIPTION = "description";
private static final String POLICY = "policy";
private static final String USERS = "users";
private static final String USER_NAME = "name";
private static final String USER_COLOR = "color";
private static final String DELETED = "deleted";
private static final String GROUP_TRACKER_ID = "group_tracker_id";
private static final String LAST_ONLINE = "last_online";
private static final String TRACK = "track";
private static final String POINT = "point";
private OsMoTracker tracker;
private OsMoService service;
private OsMoGroupsStorage storage;
private ArrayList<OsMoGroupsUIListener> uiListeners = new ArrayList<>();
private OsMoPlugin plugin;
private OsmandApplication app;
private Gson gson = new Gson();
public interface OsMoGroupsUIListener {
public void groupsListChange(String operation, OsMoGroup group);
public void deviceLocationChanged(OsMoDevice device);
}
public OsMoGroups(OsMoPlugin plugin, OsMoService service, OsMoTracker tracker, OsmandApplication app) {
this.plugin = plugin;
this.service = service;
this.tracker = tracker;
this.app = app;
service.registerReactor(this);
tracker.setTrackerListener(this);
storage = new OsMoGroupsStorage(this, app.getSettings().OSMO_GROUPS);
if (!service.isLoggedIn()) {
storage.load();
}
}
public void addUiListeners(OsMoGroupsUIListener uiListener) {
if (!uiListeners.contains(uiListener)) {
uiListeners.add(uiListener);
}
}
public void removeUiListener(OsMoGroupsUIListener uiListener) {
uiListeners.remove(uiListener);
}
private void connectDeviceImpl(OsMoDevice d) {
d.enabled = true;
d.active = true;
String mid = service.getMyTrackerId();
String mgid = service.getMyGroupTrackerId();
if ((mid == null || !mid.equals(d.getTrackerId()))
&& (mgid == null || !mgid.equals(d.getTrackerId()))) {
tracker.startTrackingId(d);
}
}
@Override
public void onConnected() {
if (service.isLoggedIn()) {
service.pushCommand("GROUP_GET_ALL");
}
}
@Override
public void onDisconnected(String msg) {
}
private String connectGroupImpl(OsMoGroup g) {
g.enabled = true;
String operation = "GROUP_CONNECT:" + g.groupId;
service.pushCommand("GROUP_CONNECT:" + g.groupId);
return operation;
}
public String connectGroup(OsMoGroup model) {
String op = connectGroupImpl(model);
storage.save();
return op;
}
public String disconnectGroup(OsMoGroup model) {
model.enabled = false;
String operation = "GROUP_DISCONNECT:" + model.groupId;
service.pushCommand(operation);
for (OsMoDevice d : model.getGroupUsers(null)) {
tracker.stopTrackingId(d);
}
storage.save();
return operation;
}
private void disconnectImpl(OsMoDevice model) {
model.active = false;
tracker.stopTrackingId(model);
}
public Collection<OsMoGroup> getGroups() {
return storage.getGroups();
}
public void showErrorMessage(String message) {
service.showErrorMessage(message);
}
@Override
public void locationChange(String trackerId, Location location) {
for (OsMoGroup g : getGroups()) {
OsMoDevice d = g.updateLastLocation(trackerId, location);
if (d != null && uiListeners != null) {
for (OsMoGroupsUIListener listener : uiListeners) {
listener.deviceLocationChanged(d);
}
}
}
}
@Override
public boolean acceptCommand(String command, String gid, String data, JSONObject obj, OsMoThread thread) {
boolean processed = false;
String operation = command + ":" + gid;
OsMoGroup group = null;
if (command.equalsIgnoreCase("GP")) {
group = storage.getGroup(gid);
if (group != null && gid.length() > 0) {
List<OsMoDevice> delta = mergeGroup(group, obj, false, false);
String mygid = service.getMyGroupTrackerId();
StringBuilder b = new StringBuilder();
for (OsMoDevice d : delta) {
if (d.getDeletedTimestamp() != 0 && d.isEnabled()) {
if (group.name != null && !d.getTrackerId().equals(mygid)) {
b.append(app.getString(R.string.osmo_user_left, d.getVisibleName(), group.getVisibleName(app))).append("\n");
}
disconnectImpl(d);
} else if (!d.isActive()) {
if (group.name != null && !d.getTrackerId().equals(mygid)) {
b.append(app.getString(R.string.osmo_user_joined, d.getVisibleName(), group.getVisibleName(app))).append("\n");
}
connectDeviceImpl(d);
}
}
if (b.length() > 0 && app.getSettings().OSMO_SHOW_GROUP_NOTIFICATIONS.get()) {
app.showToastMessage(b.toString().trim());
}
storage.save();
}
processed = true;
} else if (command.equalsIgnoreCase("GROUP_DISCONNECT")) {
group = storage.getGroup(gid);
if (group != null) {
if (obj == null || !obj.has("error")) {
disconnectAllGroupUsers(group);
disableGroupTracks(group, group.groupTracks);
disableGroupTracks(group, Collections.singleton(group.name + " points.gpx"));
}
processed = true;
}
} else if (command.equalsIgnoreCase("GROUP_CONNECT")) {
group = storage.getGroup(gid);
if (group != null) {
mergeGroup(group, obj, true, true);
group.active = true;
// connect to enabled devices in group
for (OsMoDevice d : group.getGroupUsers(null)) {
if (d.isEnabled()) {
d.active = false;
connectDeviceImpl(d);
}
}
storage.save();
}
processed = true;
} else if (command.equalsIgnoreCase("GROUP_CREATE") || command.equalsIgnoreCase("GROUP_JOIN")) {
if (command.equalsIgnoreCase("GROUP_CREATE")) {
operation = command;
try {
gid = obj.getString(GROUP_ID);
} catch (JSONException e) {
e.printStackTrace();
service.showErrorMessage(e.getMessage());
return true;
}
}
group = storage.getGroup(gid);
if (group == null) {
group = new OsMoGroup();
group.groupId = gid;
storage.addGroup(group);
}
connectGroupImpl(group);
storage.save();
processed = true;
} else if (command.equals("GROUP_LEAVE")) {
group = storage.getGroup(gid);
if (group != null) {
storage.deleteGroup(group);
}
storage.save();
processed = true;
} else if (command.equals("GROUP_GET_ALL")) {
try {
JSONArray arr = new JSONArray(data);
int arrLength = arr.length();
if (arrLength > 0) {
Map<String, OsMoGroup> receivedGroups = new HashMap<String, OsMoGroupsStorage.OsMoGroup>();
for (int i = 0; i < arrLength; i++) {
JSONObject o = arr.getJSONObject(i);
OsMoGroup parsedGroup = parseGroup(o);
receivedGroups.put(parsedGroup.getGroupId(), parsedGroup);
}
storage.mergeGroups(receivedGroups);
storage.save();
}
processed = true;
for (OsMoGroup g : storage.getGroups()) {
if (!g.isMainGroup() && g.isEnabled()) {
connectGroupImpl(g);
}
}
} catch (JSONException e) {
e.printStackTrace();
service.showErrorMessage(e.getMessage());
return processed;
}
}
if (processed && uiListeners != null) {
for (OsMoGroupsUIListener listener : uiListeners) {
listener.groupsListChange(operation, group);
}
}
return processed;
}
private void disableGroupTracks(OsMoGroup group, Collection<String> tracks) {
if (!tracks.isEmpty()) {
GpxSelectionHelper helper = app.getSelectedGpxHelper();
for (String t : tracks) {
SelectedGpxFile sg = helper.getSelectedFileByName("osmo/" + t);
if (sg != null && sg.getGpxFile() != null) {
helper.selectGpxFile(sg.getGpxFile(), false, false);
}
}
plugin.refreshMap();
}
}
private OsMoGroup parseGroup(JSONObject obj) throws JSONException {
OsMoGroup groupe = new OsMoGroup();
groupe.enabled = !(obj.has(ACTIVE) && ("0".equals(obj.getString(ACTIVE)) ||
"false".equals(obj.getString(ACTIVE))));
groupe.name = obj.optString(GROUP_NAME);
groupe.groupId = obj.getString(GROUP_ID);
groupe.description = obj.optString(DESCRIPTION);
groupe.policy = obj.optString(POLICY);
return groupe;
}
private void parseGroup(JSONObject obj, OsMoGroup gr) {
try {
if (obj.has(GROUP_NAME)) {
gr.name = obj.getString(GROUP_NAME);
}
if (obj.has(DESCRIPTION)) {
gr.description = obj.getString(DESCRIPTION);
}
if (obj.has(POLICY)) {
gr.policy = obj.getString(POLICY);
}
if (obj.has(EXPIRE_TIME)) {
gr.expireTime = obj.getLong(EXPIRE_TIME);
}
} catch (JSONException e) {
e.printStackTrace();
service.showErrorMessage(e.getMessage());
}
}
private void disconnectAllGroupUsers(OsMoGroup gr) {
gr.active = false;
for (OsMoDevice d : gr.getGroupUsers(null)) {
disconnectImpl(d);
}
}
private List<OsMoDevice> mergeGroup(OsMoGroup gr, JSONObject obj, boolean deleteUsers,
boolean isGroupConnect) {
List<OsMoDevice> delta = new ArrayList<OsMoDevice>();
try {
if (obj.has("group")) {
parseGroup(obj.getJSONObject("group"), gr);
}
Map<String, OsMoDevice> toDelete = new HashMap<String, OsMoDevice>(gr.users);
if (obj.has(USERS)) {
JSONArray arr = obj.getJSONArray(USERS);
for (int i = 0; i < arr.length(); i++) {
JSONObject o = (JSONObject) arr.get(i);
String tid = o.getString(GROUP_TRACKER_ID);
OsMoDevice device = toDelete.remove(tid);
if (device == null) {
device = new OsMoDevice();
device.group = gr;
device.trackerId = tid;
device.enabled = true;
gr.users.put(tid, device);
}
if (o.has(USER_NAME)) {
device.serverName = o.getString(USER_NAME);
}
if (o.has(DELETED)) {
device.deleted = System.currentTimeMillis();
} else {
device.deleted = 0;
}
if (o.has(LAST_ONLINE)) {
device.lastOnline = o.getLong(LAST_ONLINE);
}
if (o.has(USER_COLOR)) {
device.serverColor = net.osmand.util.Algorithms.parseColor(o.getString(USER_COLOR));
}
delta.add(device);
}
}
if (obj.has(TRACK)) {
JSONArray ar = obj.getJSONArray(TRACK);
List<JSONObject> a = new ArrayList<>(ar.length());
Set<String> toDeleteT = new HashSet<String>(gr.groupTracks);
gr.groupTracks.clear();
for (int i = 0; i < ar.length(); i++) {
JSONObject trackJson = (JSONObject) ar.get(i);
if (!trackJson.has(DELETED)) {
String track = trackJson.getString("name") + ".gpx";
gr.groupTracks.add(track);
toDeleteT.remove(track);
a.add(trackJson);
}
}
plugin.getDownloadGpxTask(true).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, a.toArray(new JSONObject[a.size()]));
disableGroupTracks(gr, toDeleteT);
}
if (obj.has(POINT)) {
JSONArray ar = obj.getJSONArray(POINT);
ArrayList<WptPt> points = new ArrayList<WptPt>();
long modify = obj.has("point_modify") ? obj.getLong("point_modify") : System.currentTimeMillis();
JSONObject[] a = new JSONObject[ar.length()];
for (int i = 0; i < a.length; i++) {
a[i] = (JSONObject) ar.get(i);
final JSONObject jobj = a[i];
WptPt pt = new WptPt();
if (jobj.has("deleted")) {
pt.deleted = true;
} else {
pt.lat = a[i].getDouble("lat");
pt.lon = a[i].getDouble("lon");
if (jobj.has("name")) {
pt.name = jobj.getString("name");
}
if (jobj.has("color")) {
pt.setColor(Algorithms.parseColor(jobj.getString("color")));
}
if (jobj.has("description")) {
pt.desc = jobj.getString("description");
}
if (jobj.has("created")) {
pt.getExtensionsToWrite().put("created", a[i].getLong("created") + "");
}
if (jobj.has("visible")) {
pt.getExtensionsToWrite().put("visible", a[i].getBoolean("visible") + "");
}
}
if (jobj.has("u")) {
pt.getExtensionsToWrite().put("u", String.valueOf(a[i].getLong("u")));
}
points.add(pt);
}
if (points.size() > 0) {
plugin.getSaveGpxTask(gr.name + " points", modify, false, isGroupConnect)
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, points.toArray(new WptPt[points.size()]));
}
}
if (deleteUsers) {
for (OsMoDevice s : toDelete.values()) {
s.deleted = System.currentTimeMillis();
delta.add(s);
}
}
} catch (JSONException e) {
e.printStackTrace();
service.showErrorMessage(e.getMessage());
}
return delta;
}
public String createGroup(String groupName, boolean onlyByInvite, String description, String policy) {
Protocol.CreateGroupData obj = new Protocol.CreateGroupData(groupName,
onlyByInvite, description, policy);
service.pushCommand("GROUP_CREATE|" + gson.toJson(obj));
return "GROUP_CREATE";
}
public void setGenColor(OsMoDevice device, int genColor) {
device.genColor = genColor;
storage.save();
}
public String joinGroup(String groupId, String userName, String nick) {
final String op = "GROUP_JOIN:" + groupId + "|" + nick;
OsMoGroup g = storage.getGroup(groupId);
if (g == null) {
g = new OsMoGroup();
g.groupId = groupId;
storage.addGroup(g);
}
g.userName = userName;
service.pushCommand(op);
return "GROUP_JOIN:" + groupId;
}
public String leaveGroup(OsMoGroup group) {
final String op = "GROUP_LEAVE:" + group.groupId;
storage.deleteGroup(group);
storage.save();
service.pushCommand(op);
if (group.isEnabled()) {
group.enabled = false;
disconnectAllGroupUsers(group);
}
return op;
}
public void setDeviceProperties(OsMoDevice model, String name, int color) {
model.userName = name;
model.userColor = color;
storage.save();
}
@Override
public String nextSendCommand(OsMoThread tracker) {
return null;
}
public void clearGroups() {
storage.clearGroups();
storage.save();
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,487 +0,0 @@
package net.osmand.plus.osmo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.plus.OsmandSettings.OsmandPreference;
import net.osmand.plus.R;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.graphics.Color;
public class OsMoGroupsStorage {
private static final String GROUPS = "groups";
private static final String USERS = "users";
private static final String TRACKS = "tracks";
private static final String SERVER_NAME = "serverName";
private static final String GROUP_ID = "group_id";
private static final String TRACKER_ID = "trackerId";
private static final String USER_NAME = "userName";
private static final String USER_COLOR = "userSetColor";
private static final String GEN_COLOR = "genColor";
private static final String SERVER_COLOR = "serverColor";
private static final String DESCRIPTION = "description";
private static final String POLICY = "policy";
private static final String NAME = "name";
private static final String ENABLED = "enabled";
private static final String EXPIRE_TIME = "expireTime";
private static final String DELETED = "deleted";
private OsmandPreference<String> pref;
private OsMoGroups service;
private ConcurrentHashMap<String, OsMoGroup> groups = new ConcurrentHashMap<String, OsMoGroup>();
public OsMoGroupsStorage(OsMoGroups service, OsmandPreference<String> pref) {
this.service = service;
this.pref = pref;
}
public Collection<OsMoGroup> getGroups() {
return groups.values();
}
public void load() {
String grp = pref.get();
try {
JSONObject obj = new JSONObject(grp);
if(!obj.has(GROUPS)) {
return;
}
JSONArray groups = obj.getJSONArray(GROUPS);
for (int i = 0; i < groups.length(); i++) {
JSONObject o = (JSONObject) groups.get(i);
OsMoGroup group = new OsMoGroup();
group.groupId = o.getString(GROUP_ID);
if(o.has(NAME)) {
group.name = o.getString(NAME);
}
if(o.has(EXPIRE_TIME)) {
group.expireTime = o.getLong(EXPIRE_TIME);
}
if(o.has(USER_NAME)) {
group.userName = o.getString(USER_NAME);
}
if(o.has(DESCRIPTION)) {
group.description = o.getString(DESCRIPTION);
}
if(o.has(POLICY)) {
group.policy = o.getString(POLICY);
}
if(o.has(ENABLED) && o.getBoolean(ENABLED)) {
group.enabled = true;
}
parseGroupUsers(group, o);
// parseGroupTracks(group, obj);
this.groups.put(group.groupId, group);
}
} catch (JSONException e) {
e.printStackTrace();
service.showErrorMessage(e.getMessage());
}
}
public void save() {
JSONObject mainObj = new JSONObject();
try {
JSONArray ar = new JSONArray();
for(OsMoGroup gr : groups.values()) {
if(gr.isMainGroup()) {
continue;
}
JSONObject obj = new JSONObject();
if (gr.userName != null) {
obj.put(USER_NAME, gr.userName);
}
if (gr.name != null) {
obj.put(NAME, gr.name);
}
if(gr.description != null) {
obj.put(DESCRIPTION, gr.description);
}
if(gr.policy != null) {
obj.put(POLICY, gr.policy);
}
if(gr.expireTime != 0) {
obj.put(EXPIRE_TIME, gr.expireTime);
}
if (gr.enabled) {
obj.put(ENABLED, true);
}
obj.put(GROUP_ID, gr.groupId);
ar.put(obj);
saveGroupUsers(gr, obj);
saveGroupTracks(gr, obj);
}
mainObj.put(GROUPS, ar);
} catch (JSONException e) {
e.printStackTrace();
service.showErrorMessage(e.getMessage());
}
pref.set(mainObj.toString());
}
private void saveGroupUsers(OsMoGroup gr, JSONObject grObj) throws JSONException {
JSONArray ar = new JSONArray();
for(OsMoDevice u : gr.users.values()) {
JSONObject obj = new JSONObject();
if (u.userName != null) {
obj.put(USER_NAME, u.userName);
}
if (u.serverName != null) {
obj.put(SERVER_NAME, u.serverName);
}
if (u.userColor != 0) {
obj.put(USER_COLOR, u.userColor);
}
if (u.genColor != 0) {
obj.put(GEN_COLOR, u.genColor);
}
if (u.serverColor != 0) {
obj.put(SERVER_COLOR, u.serverColor);
}
if (u.deleted != 0) {
obj.put(DELETED, u.deleted);
}
if(u.enabled) {
obj.put(ENABLED, u.enabled);
}
obj.put(TRACKER_ID, u.trackerId);
ar.put(obj);
}
grObj.put(USERS, ar);
}
private void saveGroupTracks(OsMoGroup gr, JSONObject grObj) throws JSONException {
if (gr.groupTracks.size() > 0) {
JSONArray ar = new JSONArray();
for (String u : gr.groupTracks) {
JSONObject obj = new JSONObject();
obj.put(NAME, u);
ar.put(obj);
}
grObj.put(TRACKS, ar);
}
}
protected void parseGroupUsers(OsMoGroup gr, JSONObject obj) throws JSONException {
if(!obj.has(USERS)) {
return;
}
JSONArray users = obj.getJSONArray(USERS);
for (int i = 0; i < users.length(); i++) {
JSONObject o = (JSONObject) users.get(i);
OsMoDevice user = new OsMoDevice();
user.group = gr;
if(o.has(SERVER_NAME)) {
user.serverName = o.getString(SERVER_NAME);
}
if(o.has(USER_NAME)) {
user.userName = o.getString(USER_NAME);
}
if(o.has(SERVER_COLOR)) {
user.serverColor = o.getInt(SERVER_COLOR);
}
if(o.has(USER_COLOR)) {
user.userColor = o.getInt(USER_COLOR);
}
if(o.has(GEN_COLOR)) {
user.genColor = o.getInt(GEN_COLOR);
}
if(o.has(DELETED)) {
user.deleted = o.getLong(DELETED);
}
if(o.has(ENABLED) && o.getBoolean(ENABLED)) {
user.enabled = true;
}
user.trackerId = o.getString(TRACKER_ID);
gr.users.put(user.trackerId, user);
}
}
protected void parseGroupTracks(OsMoGroup gr, JSONObject obj) throws JSONException {
if(!obj.has(TRACKS)) {
return;
}
JSONArray tracks = obj.getJSONArray(TRACKS);
for (int i = 0; i < tracks.length(); i++) {
JSONObject o = (JSONObject) tracks.get(i);
if(o.has(NAME)) {
gr.groupTracks.add(NAME);
}
}
}
public static class OsMoGroup {
protected String name;
protected String userName;
protected String description;
protected String policy;
protected String groupId;
protected boolean enabled;
protected long expireTime;
protected boolean active;
protected boolean deleted;
protected Map<String, OsMoDevice> users = new ConcurrentHashMap<String, OsMoDevice>();
protected List<String> groupTracks = new ArrayList<String>();
public List<OsMoDevice> getGroupUsers(String mygid) {
// filter deleted
List<OsMoDevice> dvs = new ArrayList<OsMoDevice>(users.size());
for(OsMoDevice d : users.values()) {
if(mygid != null && mygid.equals(d.trackerId)) {
continue;
}
if(d.getDeletedTimestamp() == 0) {
dvs.add(d);
}
}
return dvs;
}
public List<String> getGroupTracks() {
return groupTracks;
}
public List<OsMoDevice> getVisibleGroupUsers(String mygid) {
if(!isActive() && !isMainGroup()) {
return Collections.emptyList();
}
return getGroupUsers(mygid);
}
public boolean isDeleted() {
return deleted;
}
public String getDescription() {
return description;
}
public String getPolicy() {
return policy;
}
public long getExpireTime() {
return expireTime;
}
public boolean isMainGroup() {
return groupId == null;
}
public String getGroupId() {
return groupId;
}
public boolean isActive() {
return active;
}
public boolean isEnabled() {
return enabled;
}
public String getVisibleName(Context ctx){
if(isMainGroup()) {
return ctx.getString(R.string.osmo_connected_devices);
}
if(userName != null && userName.length() > 0) {
return userName;
}
if(name == null) {
return "";
}
return name;
}
public OsMoDevice updateLastLocation(String trackerId, Location location) {
OsMoDevice d = users.get(trackerId);
if(d != null) {
d.setLastLocation(location);
}
return d;
}
}
public static class OsMoMessage {
protected long timestamp;
protected LatLon location;
protected String text;
protected OsMoDevice user;
public String getText() {
return text;
}
public long getTimestamp() {
return timestamp;
}
public LatLon getLocation() {
return location;
}
public OsMoDevice getUser() {
return user;
}
}
public static class OsMoDevice {
protected String serverName;
protected String userName;
protected int serverColor;
protected int userColor;
protected int genColor;
protected String trackerId;
protected boolean enabled;
protected boolean active;
protected long deleted;
protected OsMoGroup group ;
protected ConcurrentLinkedQueue<Location> previousLocations = new java.util.concurrent.ConcurrentLinkedQueue<Location>();
protected List<OsMoMessage> messages = new ArrayList<OsMoMessage>();
protected long lastOnline;
protected Location lastLocation;
public List<OsMoMessage> getMessages() {
return messages;
}
public ConcurrentLinkedQueue<Location> getPreviousLocations(long threshold) {
while(!previousLocations.isEmpty() && previousLocations.peek().getTime() < threshold) {
previousLocations.poll();
}
return previousLocations;
}
public void setLastLocation(Location lastLocation) {
if(this.lastLocation != null) {
previousLocations.add(this.lastLocation);
}
this.lastLocation = lastLocation;
if (lastLocation != null) {
setLastOnline(lastLocation.getTime());
}
}
public Location getLastLocation() {
return lastLocation;
}
public void setLastOnline(long lastOnline) {
this.lastOnline = lastOnline;
}
public long getLastOnline() {
return lastOnline;
}
public boolean isEnabled() {
return enabled;
}
public boolean isActive() {
return active;
}
public long getDeletedTimestamp() {
return deleted;
}
public OsMoGroup getGroup() {
return group;
}
public String getTrackerId() {
return trackerId;
}
public int getColor() {
if(userColor != 0) {
return userColor;
}
if(serverColor != 0) {
return serverColor ;
}
return genColor;
}
public int getNonActiveColor() {
int color = getColor();
int alpha = Math.round(Color.alpha(color) * 0.3f);
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
return Color.argb(alpha, red, green, blue);
}
public String getVisibleName(){
if(userName != null && userName.length() > 0) {
return userName;
}
if(serverName == null || serverName.length() == 0) {
return trackerId;
}
return serverName;
}
}
public OsMoGroup getGroup(String gid) {
return groups.get(gid);
}
public void deleteGroup(OsMoGroup gr) {
groups.remove(gr.groupId);
gr.deleted = true;
}
public void addGroup(OsMoGroup g) {
groups.put(g.groupId, g);
g.deleted = false;
}
public void mergeGroups(Map<String, OsMoGroup> groupsToMerge) {
Set<String> toDelete = new HashSet<String>(groups.keySet());
if (groupsToMerge != null) {
Set<String> toMerge = groupsToMerge.keySet();
for (String id: toMerge) {
if (toDelete.contains(id)) {
toDelete.remove(id);
} else {
addGroup(groupsToMerge.get(id));
}
}
}
for (String id: toDelete) {
OsMoGroup group = getGroup(id);
if (group != null) {
deleteGroup(group);
}
}
}
public void clearGroups() {
groups.clear();
}
}

View file

@ -1,60 +0,0 @@
package net.osmand.plus.osmo;
import net.osmand.plus.OsmandApplication;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
public class OsMoIntentHandler extends AsyncTask<Intent, Void, String> {
private OsmandApplication app;
private OsMoPlugin plugin;
public OsMoIntentHandler(OsmandApplication app, OsMoPlugin plugin) {
this.app = app;
this.plugin = plugin;
}
@Override
protected String doInBackground(Intent... params) {
try {
while (app.isApplicationInitializing()) {
Thread.sleep(200);
}
for (Intent intent : params) {
String scheme = intent.getScheme();
Uri data = intent.getData();
if ("http".equals(scheme) && data.getHost().equals("z.osmo.mobi")) {
String path = data.getPath();
String lastPath = path.substring(path.lastIndexOf('/') + 1);
if(lastPath.equals("login")) {
String user = data.getQueryParameter("u");
String pwd = data.getQueryParameter("p");
app.getSettings().OSMO_USER_NAME.set(user);
app.getSettings().OSMO_USER_PWD.set(pwd);
plugin.getService().reconnectToServer();
} else if(lastPath.equals("join")) {
String gid = data.getQueryParameter("id");
String name = data.getQueryParameter("name");
if(name == null) {
name = "";
}
plugin.getGroups().joinGroup(gid, name, app.getSettings().OSMO_USER_NAME.get());
}
}
return null;
}
} catch (Exception e) {
return e.getMessage();
}
return null;
}
@Override
protected void onPostExecute(String result) {
if(result != null) {
}
}
}

View file

@ -1,128 +0,0 @@
package net.osmand.plus.osmo;
import android.graphics.drawable.Drawable;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.plus.OsmAndFormatter;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.mapcontextmenu.MenuBuilder;
import net.osmand.plus.mapcontextmenu.MenuController;
import net.osmand.plus.osmo.OsMoGroupsStorage.OsMoDevice;
public class OsMoMenuController extends MenuController {
private OsMoDevice device;
public OsMoMenuController(MapActivity mapActivity, PointDescription pointDescription, OsMoDevice device) {
super(new MenuBuilder(mapActivity), pointDescription, mapActivity);
this.device = device;
leftTitleButtonController = new TitleButtonController() {
@Override
public void buttonPressed() {
if (OsMoPositionLayer.getFollowDestinationId() != null) {
OsMoPositionLayer.setFollowDestination(null);
} else {
OsMoDevice dev = getDevice();
if(dev.getLastLocation() != null) {
TargetPointsHelper targets = getMapActivity().getMyApplication().getTargetPointsHelper();
targets.navigateToPoint(new LatLon(dev.getLastLocation().getLatitude(), dev.getLastLocation().getLongitude()), true, -1);
}
OsMoPositionLayer.setFollowDestination(dev);
}
getMapActivity().getContextMenu().updateMenuUI();
}
};
rightTitleButtonController = new TitleButtonController() {
@Override
public void buttonPressed() {
OsMoPlugin osMoPlugin = OsmandPlugin.getEnabledPlugin(OsMoPlugin.class);
if (osMoPlugin != null) {
OsMoGroupsActivity.showSettingsDialog(getMapActivity(), osMoPlugin, getDevice());
}
}
};
rightTitleButtonController.caption = getMapActivity().getString(R.string.shared_string_settings);
rightTitleButtonController.leftIconId = R.drawable.ic_action_settings;
updateData();
}
@Override
protected void setObject(Object object) {
if (object instanceof OsMoDevice) {
this.device = (OsMoDevice) object;
updateData();
}
}
@Override
protected Object getObject() {
return device;
}
public OsMoDevice getDevice() {
return device;
}
@Override
public void updateData() {
super.updateData();
if (OsMoPositionLayer.getFollowDestinationId() != null) {
leftTitleButtonController.caption = getMapActivity().getString(R.string.shared_string_cancel);
leftTitleButtonController.leftIconId = R.drawable.ic_action_remove_dark;
} else {
leftTitleButtonController.caption = getMapActivity().getString(R.string.mark_point);
leftTitleButtonController.leftIconId = R.drawable.ic_action_intermediate;
}
}
@Override
protected int getSupportedMenuStatesPortrait() {
return MenuState.HEADER_ONLY | MenuState.HALF_SCREEN;
}
@Override
public boolean needTypeStr() {
return true;
}
@Override
public Drawable getRightIcon() {
if (isLight()) {
return getIconOrig(R.drawable.widget_osmo_connected_location_day);
} else {
return getIconOrig(R.drawable.widget_osmo_connected_location_night);
}
}
@Override
public String getTypeStr() {
OsmandApplication app = getMapActivity().getMyApplication();
StringBuilder sb = new StringBuilder();
final Location l = device.getLastLocation();
if(l != null && l.hasSpeed()) {
sb.append(OsmAndFormatter.getFormattedSpeed(l.getSpeed(), app));
sb.append("");
}
Location myLocation = app.getLocationProvider().getLastKnownLocation();
if (myLocation != null) {
float dist = myLocation.distanceTo(l);
sb.append(OsmAndFormatter.getFormattedDistance(dist, app));
}
return sb.toString();
}
@Override
public boolean needStreetName() {
return false;
}
}

View file

@ -1,523 +0,0 @@
package net.osmand.plus.osmo;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.view.View;
import android.widget.ArrayAdapter;
import net.osmand.IndexConstants;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.plus.ApplicationMode;
import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuItem;
import net.osmand.plus.GPXUtilities;
import net.osmand.plus.GPXUtilities.GPXFile;
import net.osmand.plus.GPXUtilities.WptPt;
import net.osmand.plus.GpxSelectionHelper.SelectedGpxFile;
import net.osmand.plus.NavigationService;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.dashboard.tools.DashFragmentData;
import net.osmand.plus.download.DownloadFileHelper;
import net.osmand.plus.osmo.OsMoService.SessionInfo;
import net.osmand.plus.views.MapInfoLayer;
import net.osmand.plus.views.OsmandMapLayer.DrawSettings;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.plus.views.mapwidgets.TextInfoWidget;
import net.osmand.util.Algorithms;
import org.apache.commons.logging.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
public class OsMoPlugin extends OsmandPlugin implements OsMoReactor {
private OsmandApplication app;
public static final String ID = "osmand.osmo";
private OsMoService service;
private OsMoTracker tracker;
private OsMoGroups groups;
private TextInfoWidget osmoControl;
private OsMoPositionLayer olayer;
protected MapActivity mapActivity;
protected Activity groupsActivity;
protected OsMoControlDevice deviceControl;
private final static Log LOG = PlatformUtil.getLog(OsMoPlugin.class);
public OsMoPlugin(final OsmandApplication app) {
this.app = app;
}
@Override
public int getAssetResourceName() {
return R.drawable.osmo_monitoring;
}
@Override
public boolean init(final OsmandApplication app, Activity activity) {
if (service == null) {
service = new OsMoService(app, this);
tracker = new OsMoTracker(service, app.getSettings().OSMO_SAVE_TRACK_INTERVAL,
app.getSettings().OSMO_SEND_LOCATIONS_STATE);
deviceControl = new OsMoControlDevice(app, this, service, tracker);
groups = new OsMoGroups(this, service, tracker, app);
}
ApplicationMode.regWidgetVisibility("osmo_control", (ApplicationMode[]) null);
if (app.getSettings().OSMO_AUTO_CONNECT.get() ||
(System.currentTimeMillis() - app.getSettings().OSMO_LAST_PING.get() < 5 * 60 * 1000)) {
service.connect(true);
}
return true;
}
public Activity getGroupsActivity() {
return groupsActivity;
}
public void setGroupsActivity(Activity groupsActivity) {
this.groupsActivity = groupsActivity;
}
@Override
public void disable(OsmandApplication app) {
super.disable(app);
if (app.getNavigationService() != null) {
app.getNavigationService().stopIfNeeded(app, NavigationService.USED_BY_LIVE);
}
tracker.disableTracker();
service.disconnect();
}
@Override
public void updateLocation(Location location) {
tracker.sendCoordinate(location);
}
@Override
public String getDescription() {
return app.getString(R.string.osmo_plugin_description);
}
@Override
public String getName() {
return app.getString(R.string.osmo_plugin_name);
}
@Override
public int getLogoResourceId() {
return R.drawable.ic_osmo_dark;
}
@Override
public String getHelpFileName() {
return "feature_articles/osmo-plugin.html";
}
@Override
public void updateLayers(OsmandMapTileView mapView, MapActivity activity) {
if (isActive()) {
if (olayer == null) {
registerLayers(activity);
}
if (osmoControl == null) {
registerSideWidget(activity);
}
} else {
MapInfoLayer layer = activity.getMapLayers().getMapInfoLayer();
if (layer != null && osmoControl != null) {
layer.removeSideWidget(osmoControl);
osmoControl = null;
layer.recreateControls();
}
if (olayer != null) {
activity.getMapView().removeLayer(olayer);
olayer = null;
}
}
}
@Override
public void registerLayers(MapActivity activity) {
registerSideWidget(activity);
if (olayer != null) {
activity.getMapView().removeLayer(olayer);
}
olayer = new OsMoPositionLayer(activity, this);
activity.getMapView().addLayer(olayer, 5.5f);
}
private void registerSideWidget(MapActivity activity) {
MapInfoLayer layer = activity.getMapLayers().getMapInfoLayer();
if (layer != null) {
osmoControl = createOsMoControl(activity);
layer.registerSideWidget(osmoControl, R.drawable.ic_osmo_dark, R.string.osmo_control, "osmo_control",
false, 31);
layer.recreateControls();
}
}
@Override
public void mapActivityPause(MapActivity activity) {
groups.removeUiListener(olayer);
mapActivity = null;
}
@Override
public void mapActivityResume(MapActivity activity) {
if (olayer != null) {
groups.addUiListeners(olayer);
}
mapActivity = activity;
}
/**
* creates (if it wasn't created previously) the control to be added on a MapInfoLayer that shows a monitoring state (recorded/stopped)
*/
private TextInfoWidget createOsMoControl(final MapActivity map) {
final TextInfoWidget osmoControl = new TextInfoWidget(map) {
long lastUpdateTime;
private int blinkImg;
@Override
public boolean updateInfo(DrawSettings drawSettings) {
String txt = "OsMo";
String subtxt = "";
SessionInfo si = getService().getCurrentSessionInfo();
if (si != null) {
String uname = si.username;
if (uname != null && uname.length() > 0) {
if (uname.length() > 7) {
for (int k = 4; k < uname.length(); k++) {
if (!Character.isLetterOrDigit(uname.charAt(k)) &&
uname.charAt(k) != '.' && uname.charAt(k) != '-') {
uname = uname.substring(0, k);
break;
}
}
if (uname.length() > 12) {
uname = uname.substring(0, 12);
}
}
if (uname.length() > 4) {
txt = "";
subtxt = uname;
} else {
txt = uname;
}
}
}
boolean night = drawSettings != null && drawSettings.isNightMode();
int srcSignalinactive = !night ? R.drawable.widget_osmo_inactive_day : R.drawable.widget_osmo_inactive_night;
int small = srcSignalinactive; //tracker.isEnabledTracker() ? srcSignalinactive : srcinactive;
int big = srcSignalinactive; // tracker.isEnabledTracker() ? srcSignalinactive : srcinactive;
long last = service.getLastCommandTime();
if (service.isActive()) {
if (tracker.isEnabledTracker()) {
small = night ? R.drawable.widget_osmo_connected_location_night : R.drawable.widget_osmo_connected_location_day;
big = night ? R.drawable.widget_osmo_connected_location_night : R.drawable.widget_osmo_connected_location_day;
} else {
small = night ? R.drawable.widget_osmo_connected_night : R.drawable.widget_osmo_connected_day;
big = night ? R.drawable.widget_osmo_connected_night : R.drawable.widget_osmo_connected_day;
}
}
setText(txt, subtxt);
if (blinkImg != small) {
setImageDrawable(small);
}
if (last != lastUpdateTime) {
lastUpdateTime = last;
blink(big, small);
}
return true;
}
private void blink(int bigger, final int smaller) {
blinkImg = smaller;
setImageDrawable(bigger);
map.getMyApplication().runInUIThread(new Runnable() {
@Override
public void run() {
blinkImg = 0;
setImageDrawable(smaller);
}
}, 500);
}
};
osmoControl.updateInfo(null);
osmoControl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(map, OsMoGroupsActivity.class);
map.startActivity(intent);
}
});
return osmoControl;
}
@Override
public Class<? extends Activity> getSettingsActivity() {
return SettingsOsMoActivity.class;
}
@Override
public void registerOptionsMenuItems(final MapActivity mapActivity, ContextMenuAdapter helper) {
helper.addItem(new ContextMenuItem.ItemBuilder().setTitleId(R.string.osmo_groups, mapActivity)
.setIcon(R.drawable.ic_osmo_dark)
.setListener(new ContextMenuAdapter.ItemClickListener() {
@Override
public boolean onContextMenuClick(ArrayAdapter<ContextMenuItem> adapter, int itemId, int pos, boolean isChecked, int[] viewCoordinates) {
Intent intent = new Intent(mapActivity, OsMoGroupsActivity.class);
mapActivity.startActivity(intent);
return true;
}
})
.setPosition(6)
.createItem());
}
@Override
public String getId() {
return ID;
}
public OsMoGroups getGroups() {
return groups;
}
public OsMoTracker getTracker() {
return tracker;
}
public OsMoService getService() {
return service;
}
public AsyncTask<WptPt, String, String> getSaveGpxTask(final String name,
final long timestamp,
final boolean generateToast,
final boolean isGroupConnect) {
return new AsyncTask<WptPt, String, String>() {
protected void onProgressUpdate(String... values) {
if (values != null && generateToast) {
String t = "";
for (String s : values) {
t += s + "\n";
}
app.showToastMessage(t.trim());
}
}
@Override
protected String doInBackground(WptPt... params) {
final File fl = app.getAppPath(IndexConstants.GPX_INDEX_DIR + "/osmo");
if (!fl.exists()) {
fl.mkdirs();
}
File ps = new File(fl, name + ".gpx");
String errors = "";
boolean changed = false;
if (!ps.exists() || (ps.lastModified() / 1000) != (timestamp / 1000)) {
changed = true;
GPXFile g;
if (isGroupConnect) {
g = new GPXFile();
} else {
g = GPXUtilities.loadGPXFile(app, ps);
}
for (WptPt point : params) {
if (point.deleted) {
for (WptPt pointInTrack : g.getPoints()) {
if (pointInTrack.getExtensionsToRead().get("u").equals(
point.getExtensionsToRead().get("u"))) {
g.deleteWptPt(pointInTrack);
}
}
} else {
g.addPoint(point);
}
}
errors = GPXUtilities.writeGpxFile(ps, g, app);
ps.setLastModified(timestamp);
if (errors == null) {
errors = "";
}
if (generateToast) {
publishProgress(app.getString(R.string.osmo_gpx_points_downloaded, name));
}
}
SelectedGpxFile byPath = app.getSelectedGpxHelper().getSelectedFileByPath(ps.getAbsolutePath());
if (byPath == null || changed) {
GPXFile selectGPXFile = GPXUtilities.loadGPXFile(app, ps);
if (byPath != null) {
app.getSelectedGpxHelper().selectGpxFile(selectGPXFile, false, false);
}
app.getSelectedGpxHelper().setGpxFileToDisplay(selectGPXFile);
}
return errors;
}
@Override
protected void onPostExecute(String result) {
if (result.length() > 0 && generateToast) {
app.showToastMessage(app.getString(R.string.osmo_io_error) + result);
}
}
};
}
public AsyncTask<JSONObject, String, String> getDownloadGpxTask(final boolean makeVisible) {
return new AsyncTask<JSONObject, String, String>() {
@Override
protected String doInBackground(JSONObject... params) {
final File fl = app.getAppPath(IndexConstants.GPX_INDEX_DIR + "/osmo");
if (!fl.exists()) {
fl.mkdirs();
}
String errors = "";
for (JSONObject obj : params) {
try {
File f = new File(fl, obj.getString("name") + ".gpx");
long timestamp = obj.getLong("created") * 1000;
int color = 0;
if (obj.has("color")) {
try {
color = Algorithms.parseColor(obj.getString("color"));
} catch (RuntimeException e) {
LOG.warn("", e);
}
}
boolean visible = obj.has("visible");
boolean changed = false;
if (!f.exists() || (f.lastModified() != timestamp)) {
long len = !f.exists() ? -1 : f.length();
boolean sizeEqual = obj.has("size") && obj.getLong("size") == len;
boolean modifySupported = f.setLastModified(timestamp - 1);
if (!sizeEqual || modifySupported) {
changed = true;
String url = obj.getString("url");
LOG.info("Download gpx " + url);
DownloadFileHelper df = new DownloadFileHelper(app);
InputStream is = df.getInputStreamToDownload(new URL(url), false);
int av = is.available();
if (av > 0 && !modifySupported && len == av) {
// ignore
is.close();
} else {
redownloadFile(f, timestamp, color, is);
publishProgress(app.getString(R.string.osmo_gpx_track_downloaded, obj.getString("name")));
}
}
}
if (visible && (changed || makeVisible)) {
GPXFile selectGPXFile = GPXUtilities.loadGPXFile(app, f);
if (color != 0) {
selectGPXFile.setColor(color);
}
app.getSelectedGpxHelper().setGpxFileToDisplay(selectGPXFile);
}
} catch (JSONException | IOException e) {
e.printStackTrace();
errors += e.getMessage() + "\n";
}
}
return errors;
}
private void redownloadFile(File f, long timestamp, int color, InputStream is)
throws IOException {
FileOutputStream fout = new FileOutputStream(f);
byte[] buf = new byte[1024];
int k;
while ((k = is.read(buf)) >= 0) {
fout.write(buf, 0, k);
}
fout.close();
is.close();
if (!f.setLastModified(timestamp)) {
LOG.error("Timestamp updates are not supported");
}
}
protected void onProgressUpdate(String... values) {
if (values != null) {
String t = "";
for (String s : values) {
t += s + "\n";
}
app.showToastMessage(t.trim());
refreshMap();
}
}
@Override
protected void onPostExecute(String result) {
if (result.length() > 0) {
app.showToastMessage(app.getString(R.string.osmo_io_error) + result);
}
}
};
}
public void refreshMap() {
if (mapActivity != null) {
mapActivity.getMapView().refreshMap();
}
}
@Override
public boolean acceptCommand(String command, String id, String data, JSONObject obj, OsMoThread tread) {
return false;
}
@Override
public String nextSendCommand(OsMoThread tracker) {
return null;
}
@Override
public void onConnected() {
if (groupsActivity instanceof OsMoGroupsActivity) {
((OsMoGroupsActivity) groupsActivity).handleConnect();
}
}
@Override
public void onDisconnected(String msg) {
if (groupsActivity instanceof OsMoGroupsActivity) {
((OsMoGroupsActivity) groupsActivity).handleDisconnect(msg);
}
}
public boolean useHttps() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
}
@Override
public DashFragmentData getCardFragment() {
return DashOsMoFragment.FRAGMENT_DATA;
}
}

View file

@ -1,422 +0,0 @@
package net.osmand.plus.osmo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PointF;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import net.osmand.Location;
import net.osmand.data.LatLon;
import net.osmand.data.PointDescription;
import net.osmand.data.RotatedTileBox;
import net.osmand.plus.R;
import net.osmand.plus.TargetPointsHelper;
import net.osmand.plus.TargetPointsHelper.TargetPoint;
import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.osmo.OsMoGroups.OsMoGroupsUIListener;
import net.osmand.plus.osmo.OsMoGroupsStorage.OsMoDevice;
import net.osmand.plus.osmo.OsMoGroupsStorage.OsMoGroup;
import net.osmand.plus.routing.RoutingHelper;
import net.osmand.plus.views.ContextMenuLayer;
import net.osmand.plus.views.OsmandMapLayer;
import net.osmand.plus.views.OsmandMapTileView;
import net.osmand.util.Algorithms;
import net.osmand.util.MapUtils;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* Class represents a layer for osmo positions
*
*/
public class OsMoPositionLayer extends OsmandMapLayer implements ContextMenuLayer.IContextMenuProvider, OsMoGroupsUIListener,
ContextMenuLayer.IContextMenuProviderSelection{
private static int POINT_OUTER_COLOR = 0x88555555;
private static int PAINT_TEXT_ICON_COLOR = Color.BLACK;
private DisplayMetrics dm;
private final MapActivity map;
private OsmandMapTileView view;
private Paint pointInnerCircle;
private Paint pointOuter;
private OsMoPlugin plugin;
private final static float startZoom = 7;
private Handler uiHandler;
private Paint paintPath;
private Path pth;
private Paint paintTextIcon;
public OsMoPositionLayer(MapActivity map, OsMoPlugin plugin) {
this.map = map;
this.plugin = plugin;
}
@Override
public void initLayer(OsmandMapTileView view) {
this.view = view;
uiHandler = new Handler();
dm = new DisplayMetrics();
WindowManager wmgr = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
wmgr.getDefaultDisplay().getMetrics(dm);
pointInnerCircle = new Paint();
pointInnerCircle.setColor(view.getApplication().getResources().getColor(R.color.poi_background));
pointInnerCircle.setStyle(Style.FILL);
pointInnerCircle.setAntiAlias(true);
paintPath = new Paint();
paintPath.setStyle(Style.STROKE);
paintPath.setStrokeWidth(14);
paintPath.setAntiAlias(true);
paintPath.setStrokeCap(Cap.ROUND);
paintPath.setStrokeJoin(Join.ROUND);
paintTextIcon = new Paint();
paintTextIcon.setTextSize(10 * view.getDensity());
paintTextIcon.setTextAlign(Align.CENTER);
paintTextIcon.setFakeBoldText(true);
paintTextIcon.setColor(PAINT_TEXT_ICON_COLOR);
paintTextIcon.setAntiAlias(true);
pth = new Path();
pointOuter = new Paint();
pointOuter.setColor(POINT_OUTER_COLOR);
pointOuter.setAntiAlias(true);
pointOuter.setStyle(Style.FILL_AND_STROKE);
}
public Collection<OsMoDevice> getTrackingDevices() {
return plugin.getTracker().getTrackingDevices();
}
public int getRadiusPoi(RotatedTileBox tb){
int r = 0;
final double zoom = tb.getZoom();
if(zoom < startZoom){
r = 0;
} else if(zoom <= 11){
r = 10;
} else if(zoom <= 14){
r = 12;
} else {
r = 14;
}
return (int) (r * tb.getDensity());
}
@Override
public void onDraw(Canvas canvas, RotatedTileBox tileBox, DrawSettings nightMode) {
final int r = getRadiusPoi(tileBox);
long treshold = System.currentTimeMillis() - 15000;
for (OsMoDevice t : getTrackingDevices()) {
Location l = t.getLastLocation();
ConcurrentLinkedQueue<Location> plocations = t.getPreviousLocations(treshold);
if (!plocations.isEmpty() && l != null) {
int x = (int) tileBox.getPixXFromLonNoRot(l.getLongitude());
int y = (int) tileBox.getPixYFromLatNoRot(l.getLatitude());
pth.rewind();
Iterator<Location> it = plocations.iterator();
boolean f = true;
while (it.hasNext()) {
Location lo = it.next();
int xt = (int) tileBox.getPixXFromLonNoRot(lo.getLongitude());
int yt = (int) tileBox.getPixYFromLatNoRot(lo.getLatitude());
if (f) {
f = false;
pth.moveTo(xt, yt);
} else {
pth.lineTo(xt, yt);
}
}
pth.lineTo(x, y);
paintPath.setColor(t.getColor());
canvas.drawPath(pth, paintPath);
}
}
canvas.rotate(-tileBox.getRotate(), tileBox.getCenterPixelX(), tileBox.getCenterPixelY());
for (OsMoDevice t : getTrackingDevices()) {
Location l = t.getLastLocation();
if (l != null) {
int x = (int) tileBox.getPixXFromLatLon(l.getLatitude(), l.getLongitude());
int y = (int) tileBox.getPixYFromLatLon(l.getLatitude(), l.getLongitude());
pointInnerCircle.setColor(t.getColor());
pointOuter.setColor(POINT_OUTER_COLOR);
paintTextIcon.setColor(PAINT_TEXT_ICON_COLOR);
Location lastLocation = t.getLastLocation();
if (lastLocation != null) {
long now = System.currentTimeMillis();
boolean recent = Math.abs( now - lastLocation.getTime() ) < OsMoGroupsActivity.RECENT_THRESHOLD;
if (!recent) {
int color = t.getNonActiveColor();
pointInnerCircle.setColor(color);
pointOuter.setColor(Color.argb(Color.alpha(color),
Color.red(POINT_OUTER_COLOR), Color.green(POINT_OUTER_COLOR),
Color.blue(POINT_OUTER_COLOR)));
paintTextIcon.setColor(Color.argb(Color.alpha(color),
Color.red(PAINT_TEXT_ICON_COLOR), Color.green(PAINT_TEXT_ICON_COLOR),
Color.blue(PAINT_TEXT_ICON_COLOR)));
}
} else {
int color = t.getNonActiveColor();
pointInnerCircle.setColor(color);
pointOuter.setColor(Color.argb(Color.alpha(color),
Color.red(POINT_OUTER_COLOR), Color.green(POINT_OUTER_COLOR),
Color.blue(POINT_OUTER_COLOR)));
paintTextIcon.setColor(Color.argb(Color.alpha(color),
Color.red(PAINT_TEXT_ICON_COLOR), Color.green(PAINT_TEXT_ICON_COLOR),
Color.blue(PAINT_TEXT_ICON_COLOR)));
}
canvas.drawCircle(x, y, r + (float)Math.ceil(tileBox.getDensity()), pointOuter);
canvas.drawCircle(x, y, r - (float)Math.ceil(tileBox.getDensity()), pointInnerCircle);
paintTextIcon.setTextSize(r * 3 / 2);
canvas.drawText(t.getVisibleName().substring(0, 1).toUpperCase(), x, y + r / 2, paintTextIcon);
}
}
}
@Override
public void destroyLayer() {
}
@Override
public boolean drawInScreenPixels() {
return false;
}
@Override
public boolean disableSingleTap() {
return false;
}
@Override
public boolean disableLongPressOnMap() {
return false;
}
@Override
public boolean isObjectClickable(Object o) {
return o instanceof OsMoDevice;
}
@Override
public boolean runExclusiveAction(Object o, boolean unknownLocation) {
return false;
}
@Override
public void collectObjectsFromPoint(PointF point, RotatedTileBox tileBox, List<Object> o, boolean unknownLocation) {
getOsmoFromPoint(tileBox, point, o);
}
@Override
public LatLon getObjectLocation(Object o) {
if(o instanceof OsMoDevice) {
Location loc = ((OsMoDevice) o).getLastLocation();
if(loc != null) {
return new LatLon(loc.getLatitude(), loc.getLongitude());
}
}
return null;
}
@Override
public PointDescription getObjectName(Object o) {
if(o instanceof OsMoDevice) {
return new PointDescription(PointDescription.POINT_TYPE_MARKER, map.getString(R.string.osmo_user_name) + " " + ((OsMoDevice) o).getVisibleName());
} else {
return null;
}
//String desc = getObjectDescription(o);
//return desc == null ? null : new PointDescription(PointDescription.POINT_TYPE_MARKER, desc);
}
public void refresh() {
if (view != null) {
view.refreshMap();
}
}
private void getOsmoFromPoint(RotatedTileBox tb, PointF point, List<? super OsMoDevice> points) {
if (view != null) {
int ex = (int) point.x;
int ey = (int) point.y;
final int rp = getRadiusPoi(tb);
int compare = rp;
int radius = rp * 3 / 2;
for (OsMoDevice d : getTrackingDevices()) {
Location position = d.getLastLocation();
if (position != null) {
int x = (int) tb.getPixXFromLatLon(position.getLatitude(), position.getLongitude());
int y = (int) tb.getPixYFromLatLon(position.getLatitude(), position.getLongitude());
// the width of an image is 40 px, the height is 60 px -> radius = 20,
// the position of a parking point relatively to the icon is at the center of the bottom line of the
// image
if (Math.abs(x - ex) <= compare && Math.abs(y - ey) <= compare) {
compare = radius;
points.add(d);
}
}
}
}
}
@Override
public void groupsListChange(String operation, OsMoGroup group) {
}
private volatile boolean schedule = false;
// store between rotations
private static String followTrackerId;
private static LatLon followMapLocation;
private static String followDestinationId;
private static LatLon followTargetLocation;
public static void setFollowTrackerId(OsMoDevice d, Location l) {
if(d != null) {
followTrackerId = d.trackerId;
if(l != null) {
followMapLocation = new LatLon(l.getLatitude(), l.getLongitude());
}
} else {
followTrackerId = null;
}
}
public static void setFollowDestination(OsMoDevice followDestination) {
followDestinationId = followDestination == null ? null : followDestination.trackerId;
}
public static String getFollowDestinationId() {
return followDestinationId;
}
@Override
public void deviceLocationChanged(final OsMoDevice device) {
boolean sameDestId = Algorithms.objectEquals(followDestinationId, device.trackerId);
Location l = device.getLastLocation();
if(sameDestId && l != null) {
TargetPointsHelper targets = map.getMyApplication().getTargetPointsHelper();
final TargetPoint pn = targets.getPointToNavigate();
LatLon lt = new LatLon(l.getLatitude(), l.getLongitude());
boolean cancelDestinationId = false;
if(followTargetLocation != null ) {
if(pn == null || pn.point == null || MapUtils.getDistance(pn.point, followTargetLocation) > 10) {
cancelDestinationId = true;
}
}
if(cancelDestinationId) {
followTargetLocation = null;
followDestinationId = null;
} else {
RoutingHelper rh = map.getMyApplication().getRoutingHelper();
double dist = 1;
if (rh.isRouteBeingCalculated()) {
dist = 100;
} else if (rh.isRouteCalculated()) {
dist = 30;
}
if (pn == null || MapUtils.getDistance(pn.point, lt) > dist) {
followTargetLocation = lt;
targets.navigateToPoint(lt, true, -1);
}
}
}
boolean sameId = Algorithms.objectEquals(followTrackerId, device.trackerId);
if(sameId && !schedule && l != null) {
ContextMenuLayer cl = map.getMapLayers().getContextMenuLayer();
final boolean sameObject;
if (map.getContextMenu().getObject() instanceof OsMoDevice && cl.isVisible()) {
sameObject = Algorithms.objectEquals(device.trackerId,
((OsMoDevice) map.getContextMenu().getObject()).trackerId);
} else {
sameObject = false;
}
LatLon mapLoc = new LatLon(map.getMapView().getLatitude(), map.getMapView().getLongitude());
final boolean centered = followMapLocation != null && MapUtils.getDistance(mapLoc, followMapLocation) < 1;
if(sameObject || centered) {
final LatLon loc;
if(centered ) {
loc = new LatLon(l.getLatitude(), l.getLongitude());
} else if(!map.getMapView().getAnimatedDraggingThread().isAnimating()) {
// disable tracking
loc = null;
} else {
loc = followMapLocation;
}
followMapLocation = loc;
schedule = true;
uiHandler.postDelayed(new Runnable() {
@Override
public void run() {
schedule = false;
if (sameObject) {
Location l = device.getLastLocation();
if (centered) {
map.getContextMenu().updateMapCenter(loc);
}
map.getContextMenu().update(new LatLon(l.getLatitude(), l.getLongitude()),
getObjectName(device), device);
}
if (centered) {
map.getMapView().setLatLon(loc.getLatitude(), loc.getLongitude());
}
map.getMapView().refreshMap();
}
}, 150);
} else {
followTrackerId = null;
}
}
uiHandler.postDelayed(new Runnable() {
@Override
public void run() {
map.getMapView().refreshMap();
}
}, 350);
}
@Override
public int getOrder(Object o) {
return 0;
}
@Override
public void setSelectedObject(Object o) {
if(o instanceof OsMoDevice) {
followTrackerId = ((OsMoDevice) o).getTrackerId();
}
}
@Override
public void clearSelectedObject() {
LatLon mapLoc = new LatLon(map.getMapView().getLatitude(), map.getMapView().getLongitude());
final boolean centered = Algorithms.objectEquals(followMapLocation, mapLoc);
if(!centered && followTrackerId != null) {
followTrackerId = null;
}
}
}

View file

@ -1,15 +0,0 @@
package net.osmand.plus.osmo;
import org.json.JSONObject;
public interface OsMoReactor {
public boolean acceptCommand(String command, String id, String data, JSONObject obj, OsMoThread tread);
public String nextSendCommand(OsMoThread tracker);
public void onConnected();
public void onDisconnected(String msg);
}

View file

@ -1,483 +0,0 @@
package net.osmand.plus.osmo;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.os.Build;
import android.provider.Settings.Secure;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.notifications.OsmandNotification.NotificationType;
import org.apache.commons.logging.Log;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
public class OsMoService implements OsMoReactor {
private static final String HTTP_API_PREPARE = "http://api.osmo.mobi/prepare";
private static final String HTTPS_API_PREPARE = "https://api.osmo.mobi/prepare";
private static final String HTTP_AUTH = "http://api.osmo.mobi/auth";
private static final String HTTPS_AUTH = "https://api.osmo.mobi/auth";
public static final String REGENERATE_CMD = "TRACKER_REGENERATE_ID";
public static final String SIGN_IN_URL = "http://osmo.mobi/signin?key=";
private OsMoThread thread;
private List<OsMoReactor> listReactors = new java.util.concurrent.CopyOnWriteArrayList<OsMoReactor>();
private ConcurrentLinkedQueue<String> commands = new ConcurrentLinkedQueue<String>();
private OsmandApplication app;
private static final Log log = PlatformUtil.getLog(OsMoService.class);
public static final String SHARE_TRACKER_URL = "http://z.osmo.mobi/connect?id=";
public static final String SHARE_GROUP_URL = "http://z.osmo.mobi/join?id=";
public static final String SIGNED_IN_CONTAINS = "z.osmo.mobi/login";
public static final String TRACK_URL = "http://osmo.mobi/s/";
private String lastRegistrationError = null;
private OsMoPlugin plugin;
private boolean enabled = false;
private BroadcastReceiver broadcastReceiver;
private Notification notification;
public final static String OSMO_REGISTER_AGAIN = "OSMO_REGISTER_AGAIN"; //$NON-NLS-1$
private final static int SIMPLE_NOTFICATION_ID = 5;
private class HttpPostWriter {
BufferedWriter writer;
boolean first;
HttpPostWriter(OutputStream outputStream) {
this.writer = new BufferedWriter(new OutputStreamWriter(outputStream));
this.first = true;
}
void addPair(String key, String value) throws IOException {
if (this.first)
this.first = false;
else
this.writer.write("&");
this.writer.write(URLEncoder.encode(key, "UTF-8"));
this.writer.write("=");
this.writer.write(URLEncoder.encode(value, "UTF-8"));
}
void flush() throws IOException {
this.writer.flush();
this.writer.close();
}
}
public OsMoService(final OsmandApplication app, OsMoPlugin plugin) {
this.app = app;
this.plugin = plugin;
listReactors.add(this);
listReactors.add(plugin);
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
notification = null;
NotificationManager mNotificationManager = (NotificationManager) app
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(SIMPLE_NOTFICATION_ID);
registerAsync();
}
};
app.registerReceiver(broadcastReceiver, new IntentFilter(OSMO_REGISTER_AGAIN));
}
private void registerAsync() {
new AsyncTask<Void, Void, Void>() {
public Void doInBackground(Void... voids ) {
try {
registerOsmoDeviceKey();
onConnected();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void)null);
}
public boolean isConnected() {
return thread != null && thread.isConnected();
}
public boolean isActive() {
return thread != null && thread.isActive();
}
public long getLastCommandTime() {
if(isConnected()) {
return thread.getLastCommandTime();
}
return 0;
}
public List<String> getHistoryOfCommands() {
if(thread == null) {
return Collections.emptyList();
}
return new ArrayList<String>(thread.getLastCommands());
}
public long getConnectionTime() {
return thread == null || !thread.isConnected() ? System.currentTimeMillis() : thread.getConnectionTime();
}
protected List<OsMoReactor> getListReactors() {
return listReactors;
}
public String getLastRegistrationError() {
return lastRegistrationError;
}
public boolean connect(boolean forceReconnect) {
if(thread != null) {
if(!forceReconnect ) {
return isConnected();
}
thread.stopConnection();
}
thread = new OsMoThread(this);
enabled = true;
app.getNotificationHelper().refreshNotification(NotificationType.OSMO);
return true;
}
public boolean isEnabled() {
return enabled;
}
public void disconnect() {
if(thread != null) {
enabled = false;
thread.stopConnection();
app.getSettings().OSMO_LAST_PING.set(0l);
app.getNotificationHelper().refreshNotification(NotificationType.OSMO);
}
}
public void registerReactor(OsMoReactor reactor) {
if(!listReactors.contains(reactor)) {
ArrayList<OsMoReactor> lst = new ArrayList<OsMoReactor>(listReactors);
lst.add(reactor);
listReactors = lst;
}
}
public void removeReactor(OsMoReactor s) {
if(listReactors.contains(s)) {
ArrayList<OsMoReactor> lst = new ArrayList<OsMoReactor>(listReactors);
lst.remove(s);
listReactors = lst;
}
}
public String registerOsmoDeviceKey() throws IOException {
URL url = new URL(plugin.useHttps()? HTTPS_AUTH : HTTP_AUTH);
try {
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
// Add your data
HttpPostWriter postWriter = new HttpPostWriter(conn.getOutputStream());
postWriter.addPair("android_id", Secure.getString(app.getContentResolver(),
Secure.ANDROID_ID));
postWriter.addPair("android_model", Build.MODEL);
postWriter.addPair("imei", "0");
postWriter.addPair("android_product", Build.PRODUCT);
postWriter.addPair("client", Version.getFullVersion(app));
postWriter.addPair("osmand", Version.getFullVersion(app));
// Execute HTTP Post Request
postWriter.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String r = reader.readLine();
reader.close();
conn.disconnect();
log.info("Authorization key : " + r);
final JSONObject obj = new JSONObject(r);
if(obj.has("error")) {
lastRegistrationError = obj.getString("error");
throw new OsMoConnectionException(obj.getString("error"));
}
app.getSettings().OSMO_DEVICE_KEY.set(obj.getString("key"));
return obj.getString("key");
} catch (JSONException e) {
throw new IOException(e);
}
}
public static class SessionInfo {
public String hostName;
public String port;
public String token;
public String uid;
public String username;
// after auth
public String protocol = "";
public String groupTrackerId;
public String trackerId;
public long serverTimeDelta;
public long motdTimestamp;
public String motd = "";
}
public SessionInfo getCurrentSessionInfo() {
if(thread == null) {
return null;
}
return thread.getSessionInfo();
}
public String getRegisteredUserName() {
SessionInfo si = getCurrentSessionInfo();
if(si != null && si.username != null && si.username.length() > 0) {
return si.username;
}
return null;
}
public String getMyGroupTrackerId() {
String myGroupTrackerId = "";
SessionInfo currentSessionInfo = getCurrentSessionInfo();
if (currentSessionInfo != null) {
myGroupTrackerId = currentSessionInfo.groupTrackerId;
}
return myGroupTrackerId;
}
public String getMyTrackerId() {
String myGroupTrackerId = "";
SessionInfo currentSessionInfo = getCurrentSessionInfo();
if (currentSessionInfo != null) {
myGroupTrackerId = currentSessionInfo.trackerId;
}
return myGroupTrackerId;
}
public SessionInfo prepareSessionToken() throws IOException {
String deviceKey = app.getSettings().OSMO_DEVICE_KEY.get();
if (deviceKey.length() == 0) {
deviceKey = registerOsmoDeviceKey();
}
URL url = new URL(plugin.useHttps() ? HTTPS_API_PREPARE : HTTP_API_PREPARE);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
try {
conn.setDoOutput(true);
HttpPostWriter postWriter = new HttpPostWriter(conn.getOutputStream());
// Add your data
postWriter.addPair("app", Version.getFullVersion(app));
postWriter.addPair("key", deviceKey);
if (app.getSettings().OSMO_USER_PWD.get() != null) {
postWriter.addPair("auth", app.getSettings().OSMO_USER_PWD.get());
}
postWriter.addPair("protocol", "1");
// Execute HTTP Post Request
postWriter.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String r = reader.readLine();
reader.close();
conn.disconnect();
log.info("Authorization key : " + r);
final JSONObject obj = new JSONObject(r);
if (obj.has("error")) {
lastRegistrationError = obj.getString("error");
runNotification(lastRegistrationError);
return null;
}
if (!obj.has("address")) {
lastRegistrationError = "Host name not specified";
throw new RuntimeException("Host name not specified");
}
if (!obj.has("token")) {
lastRegistrationError = "Token not specified by server";
throw new RuntimeException("Token not specified by server");
}
SessionInfo si = new SessionInfo();
String a = obj.getString("address");
if (obj.has("name")) {
si.username = obj.getString("name");
}
if (obj.has("uid")) {
si.uid = obj.getString("uid");
}
int i = a.indexOf(':');
si.hostName = a.substring(0, i);
si.port = a.substring(i + 1);
si.token = obj.getString("token");
return si;
} catch (IOException e) {
throw e;
} catch (JSONException e) {
throw new IOException(e);
}
}
private void runNotification(final String error) {
final Activity ga = plugin.getGroupsActivity();
if(ga != null) {
app.runInUIThread(new Runnable() {
@Override
public void run() {
showRegisterAgain(ga, app.getString(R.string.osmo_auth_error, error));
}
});
} else if (notification == null) {
Intent notificationIntent = new Intent(OSMO_REGISTER_AGAIN);
PendingIntent intent = PendingIntent.getBroadcast(app, 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
android.support.v4.app.NotificationCompat.Builder bld = new NotificationCompat.Builder(app);
bld.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
bld.setContentInfo(app.getString(R.string.osmo_auth_error, error));
bld.setContentIntent(intent);
bld.setContentTitle(app.getString(R.string.osmo_auth_error_short));
bld.setSmallIcon(R.drawable.bgs_icon);
NotificationManager mNotificationManager = (NotificationManager) app
.getSystemService(Context.NOTIFICATION_SERVICE);
notification = bld.getNotification();
mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notification);
}
}
protected void showRegisterAgain(Activity ga, String msg) {
AlertDialog.Builder bld = new AlertDialog.Builder(ga);
bld.setMessage(msg);
bld.setPositiveButton(R.string.shared_string_ok, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
registerAsync();
}
});
bld.setNegativeButton(R.string.shared_string_cancel, null);
}
public void showErrorMessage(String string) {
app.showToastMessage(app.getString(R.string.osmo_io_error) + string);
}
public void pushCommand(String cmd) {
commands.add(cmd);
}
@Override
public String nextSendCommand(OsMoThread tracker) {
if(System.currentTimeMillis() - app.getSettings().OSMO_LAST_PING.get() > 30000) {
app.getSettings().OSMO_LAST_PING.set(System.currentTimeMillis());
}
if(!commands.isEmpty()) {
return commands.poll();
}
return null;
}
@Override
public boolean acceptCommand(String command, String id, String data, JSONObject obj, OsMoThread tread) {
if(command.equals("MOTD")) {
SessionInfo si = getCurrentSessionInfo();
if(si != null) {
if(data.startsWith("[")){
try {
data = new JSONArray(data).getString(0);
} catch (JSONException e) {
e.printStackTrace();
}
}
si.motd = data;
}
return true;
} else if(command.equals("TRACK_GET")) {
try {
JSONArray ar = new JSONArray(data);
AsyncTask<JSONObject, String, String> task = plugin.getDownloadGpxTask(false);
JSONObject[] a = new JSONObject[ar.length()];
for(int i = 0; i < a.length; i++) {
a[i] = (JSONObject) ar.get(i);
}
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, a);
} catch (JSONException e) {
e.printStackTrace();
showErrorMessage(e.getMessage());
}
}
return false;
}
@Override
public void onConnected() {
pushCommand("TRACK_GET");
}
@Override
public void onDisconnected(String msg) {
}
public void reconnectToServer() {
if(thread != null) {
thread.reconnect();
}
}
public boolean isLoggedIn() {
String psswd = app.getSettings().OSMO_USER_PWD.get();
String userName = app.getSettings().OSMO_USER_NAME.get();
return ((!TextUtils.isEmpty(psswd) && !TextUtils.isEmpty(userName)));
}
public OsmandApplication getMyApplication() {
return app;
}
}

View file

@ -1,488 +0,0 @@
package net.osmand.plus.osmo;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.widget.Toast;
import net.osmand.PlatformUtil;
import net.osmand.plus.osmo.OsMoService.SessionInfo;
import org.apache.commons.logging.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
public class OsMoThread {
// private static String TRACKER_SERVER = "srv.osmo.mobi";
// private static int TRACKER_PORT = 3245;
private static final String PING_CMD = "P";
protected final static Log log = PlatformUtil.getLog(OsMoThread.class);
private static final long HEARTBEAT_DELAY = 100;
private static final long HEARTBEAT_FAILED_DELAY = 10000;
private static final long TIMEOUT_TO_RECONNECT = 60 * 1000;
private static final int SOCKET_TIMEOUT = 60 * 1000;
private static final long TIMEOUT_TO_PING = 5 * 60 * 1000;
private static final long LIMIT_OF_FAILURES_RECONNECT = 10;
private static final long SELECT_TIMEOUT = 500;
private static int HEARTBEAT_MSG = 3;
private Handler serviceThread;
private int failures = 0;
private int activeConnectionId = 0;
private boolean stopThread;
private boolean reconnect;
private Selector selector;
private int authorized = 0; // 1 - send, 2 - authorized
private OsMoService service;
private SessionInfo sessionInfo = null;
private SocketChannel activeChannel;
private long connectionTime;
private long lastSendCommand = 0;
private long pingSent = 0;
private ByteBuffer pendingSendCommand;
private String readCommand = "";
private ByteBuffer pendingReadCommand = ByteBuffer.allocate(2048);
private LinkedList<String> queueOfMessages = new LinkedList<String>();
private SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss", Locale.US);
private ConcurrentLinkedQueue<String> lastCommands = new ConcurrentLinkedQueue<String>();
private final static int STACK_CMD = 30;
public OsMoThread(OsMoService service) {
this.service = service;
// start thread to receive events from OSMO
HandlerThread h = new HandlerThread("OSMo Service");
h.start();
serviceThread = new Handler(h.getLooper());
scheduleHeartbeat(HEARTBEAT_DELAY);
}
public void stopConnection() {
stopThread = true;
}
protected void initConnection() throws IOException {
// always ask session token
// if (sessionInfo == null) {
sessionInfo = service.prepareSessionToken();
// }
if(sessionInfo == null) {
return;
}
this.activeChannel = null;
authorized = 0;
reconnect = false;
pingSent = 0;
failures = 0;
lastSendCommand = 0;
selector = Selector.open();
SocketChannel activeChannel = SocketChannel.open();
activeChannel.configureBlocking(true);
activeChannel.connect(new InetSocketAddress(sessionInfo.hostName, Integer.parseInt(sessionInfo.port)));
activeChannel.configureBlocking(false);
activeChannel.socket().setSoTimeout(SOCKET_TIMEOUT);
SelectionKey key = activeChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
connectionTime = System.currentTimeMillis();
if (this.activeChannel != null) {
stopChannel();
}
this.activeChannel = activeChannel;
key.attach(new Integer(++activeConnectionId));
for(OsMoReactor sender : getReactors()) {
sender.onConnected();
}
}
private Collection<OsMoReactor> getReactors() {
return service.getListReactors();
}
public String format(String cmd, Map<String, Object> params) {
JSONObject json;
try {
json = new JSONObject();
Iterator<Entry<String, Object>> it = params.entrySet().iterator();
while(it.hasNext()) {
Entry<String, Object> e = it.next();
json.put(e.getKey(), e.getValue());
}
return cmd + "|"+json.toString();
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
public void scheduleHeartbeat(long delay) {
Message msg = serviceThread.obtainMessage();
msg.what = HEARTBEAT_MSG;
serviceThread.postDelayed(new Runnable() {
@Override
public void run() {
checkAsyncSocket();
}
}, delay);
}
public boolean isConnected() {
return activeChannel != null;
}
public boolean isActive() {
return activeChannel != null && pingSent == 0 && authorized == 2;
}
protected void checkAsyncSocket() {
long delay = HEARTBEAT_DELAY;
try {
// if (selector == null) {
// stopThread = true;
if(activeChannel == null || reconnect) {
initConnection();
if(activeChannel == null) {
delay = HEARTBEAT_FAILED_DELAY;
}
} else {
checkSelectedKeys();
}
} catch (Exception e) {
log.info("Exception selecting socket", e);
exc("ERROR HEARTBEAT : ", e);
e.printStackTrace();
if (activeChannel != null && !activeChannel.isConnected()) {
activeChannel = null;
}
final String msg = e.getMessage();
for(OsMoReactor sender : getReactors()) {
sender.onDisconnected(msg);
}
delay = HEARTBEAT_FAILED_DELAY;
if (e instanceof OsMoConnectionException) {
stopThread = true;
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
Toast.makeText(service.getMyApplication(), msg, Toast.LENGTH_LONG).show();
}
});
} else {
if (lastSendCommand != 0 && System.currentTimeMillis() - lastSendCommand > TIMEOUT_TO_RECONNECT) {
reconnect = true;
} else if (failures++ > LIMIT_OF_FAILURES_RECONNECT) {
reconnect = true;
}
}
}
if (stopThread) {
stopChannel();
for(OsMoReactor sender : getReactors()) {
sender.onDisconnected(null);
}
serviceThread.getLooper().quit();
} else {
scheduleHeartbeat(delay);
}
}
protected void exc(String header, Exception e) {
String eMsg = e.getMessage();
if(e.getStackTrace() != null && e.getStackTrace().length > 0) {
eMsg += " " + e.getStackTrace()[0].toString();
}
cmd(header + eMsg, true);
}
private void stopChannel() {
if (activeChannel != null) {
try {
activeChannel.close();
} catch (IOException e) {
}
}
activeChannel = null;
}
private void checkSelectedKeys() throws IOException {
/* int s = */selector.select(SELECT_TIMEOUT);
Set<SelectionKey> keys = selector.selectedKeys();
if (keys == null) {
return;
}
Iterator<SelectionKey> iterator = keys.iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
final boolean isActive = new Integer(activeConnectionId).equals(key.attachment());
// final boolean isActive = activeChannel == key.channel();
if (isActive) {
if (key.isWritable()) {
writeCommands();
}
if (key.isReadable()) {
readCommands();
}
} else {
try {
key.channel().close();
} catch (Exception e) {
log.info("Exception closing channel", e);
e.printStackTrace();
}
}
iterator.remove();
}
}
private void readCommands() throws IOException {
boolean hasSomethingToRead = true;
while (hasSomethingToRead) {
pendingReadCommand.clear();
int read = activeChannel.read(pendingReadCommand);
if (!pendingReadCommand.hasRemaining()) {
hasSomethingToRead = true;
} else {
hasSomethingToRead = false;
}
if(read == -1) {
reconnect = true;
} else if (read > 0) {
byte[] ar = pendingReadCommand.array();
String res = new String(ar, 0, read);
readCommand += res;
int i;
while ((i = readCommand.indexOf('\n')) != -1) {
String cmd = readCommand.substring(0, i);
readCommand = readCommand.substring(i + 1);
queueOfMessages.add(cmd.replace("\\n", "\n"));
}
}
}
if (queueOfMessages.size() > 0) {
processReadMessages();
}
}
private void processReadMessages() {
while(!queueOfMessages.isEmpty()){
String cmd = queueOfMessages.poll();
cmd(cmd, false);
int k = cmd.indexOf('|');
String header = cmd;
String id = "";
String data = "";
if(k >= 0) {
header = cmd.substring(0, k);
data = cmd.substring(k + 1);
}
int ks = header.indexOf(':');
if (ks >= 0) {
id = header.substring(ks + 1);
header = header.substring(0, ks);
}
JSONObject obj = null;
if(data.startsWith("{")) {
try {
obj = new JSONObject(data);
} catch (JSONException e) {
e.printStackTrace();
}
}
boolean error = false;
if(obj != null && obj.has("error")) {
error = true;
try {
String s = obj.getString("error");
if(obj.has("error_description")) {
s += " " +obj.getString("error_description");
}
service.showErrorMessage(s);
} catch (JSONException e) {
e.printStackTrace();
}
}
if(header.equalsIgnoreCase("TOKEN")) {
if(!error){
authorized = 2;
try {
parseAuthCommand(data, obj);
} catch (JSONException e) {
service.showErrorMessage(e.getMessage());
}
}
continue;
} else if(header.equalsIgnoreCase(OsMoService.REGENERATE_CMD)) {
reconnect = true;
continue;
} else if(header.equalsIgnoreCase(PING_CMD)) {
pingSent = 0;
continue;
// lastSendCommand = System.currentTimeMillis(); // not needed handled by send
}
boolean processed = false;
for (OsMoReactor o : getReactors()) {
try {
if (o.acceptCommand(header, id, data, obj, this)) {
processed = true;
break;
}
} catch (Exception e) {e.printStackTrace();
exc("ERROR REACTOR:", e);
}
}
if (!processed) {
log.warn("Command not processed '" + cmd + "'");
}
}
lastSendCommand = System.currentTimeMillis();
}
private void parseAuthCommand(String data, JSONObject obj) throws JSONException {
if(sessionInfo != null) {
if(obj.has("protocol")) {
sessionInfo.protocol = obj.getString("protocol");
}
if(obj.has("now")) {
sessionInfo.serverTimeDelta = obj.getLong("now") - System.currentTimeMillis();
}
if(obj.has("name")) {
sessionInfo.username = obj.getString("name");
}
if (obj.has("motd")) {
long l = obj.getLong("motd");
if(l != sessionInfo.motdTimestamp ){
sessionInfo.motdTimestamp = l;
service.pushCommand("MOTD");
}
}
if(obj.has("tracker_id")) {
sessionInfo.trackerId= obj.getString("tracker_id");
}
if(obj.has("group_tracker_id")) {
sessionInfo.groupTrackerId= obj.getString("group_tracker_id");
}
}
}
public long getConnectionTime() {
return connectionTime;
}
private void writeCommands() throws UnsupportedEncodingException, IOException {
if(authorized == 0) {
String auth = "TOKEN|"+ sessionInfo.token;
cmd(auth, true);
authorized = 1;
pendingSendCommand = ByteBuffer.wrap(prepareCommand(auth).toString().getBytes("UTF-8"));
}
if (pendingSendCommand == null) {
pendingSendCommand = getNewPendingSendCommand();
}
while (pendingSendCommand != null) {
activeChannel.write(pendingSendCommand);
if (!pendingSendCommand.hasRemaining()) {
lastSendCommand = System.currentTimeMillis();
pendingSendCommand = getNewPendingSendCommand();
} else {
break;
}
}
}
private ByteBuffer getNewPendingSendCommand() throws UnsupportedEncodingException {
if(authorized == 1) {
return null;
}
for (OsMoReactor s : getReactors()) {
String l = null;
try {
l = s.nextSendCommand(this);
} catch (Exception e) {
exc("ERROR SENDER:", e);
}
if (l != null) {
cmd(l, true);
return ByteBuffer.wrap(prepareCommand(l).toString().getBytes("UTF-8"));
}
}
final long interval = System.currentTimeMillis() - lastSendCommand;
if(interval > TIMEOUT_TO_PING) {
final long pingInterval = System.currentTimeMillis() - pingSent;
if(pingSent == 0 || pingInterval > TIMEOUT_TO_PING) {
pingSent = System.currentTimeMillis();
cmd(PING_CMD, true);
return ByteBuffer.wrap(prepareCommand(PING_CMD).toString().getBytes("UTF-8"));
}
} else if(pingSent != 0) {
pingSent = 0;
}
return null;
}
public ConcurrentLinkedQueue<String> getLastCommands() {
return lastCommands;
}
private void cmd(String cmd, boolean send) {
log.info("OsMO" + (send ? "> " : ">> ") + cmd);
lastCommands.add((send ? "> " : ">> ") + df.format(new Date()) + " " + cmd);
while(lastCommands.size() > STACK_CMD) {
lastCommands.poll();
}
}
public SessionInfo getSessionInfo() {
return sessionInfo;
}
private String prepareCommand(String l) {
StringBuilder res = new StringBuilder(l.length());
for (int i = 0; i < l.length(); i++) {
char c = l.charAt(i);
if (c == '\n' || c == '=' || c == '\\') {
res.append('\\');
}
res.append(c);
}
String finalCmd = res.toString().trim();
return finalCmd + "=\n";
}
public long getLastCommandTime() {
return lastSendCommand;
}
public void reconnect() {
sessionInfo = null;
reconnect = true;
}
}

View file

@ -1,264 +0,0 @@
package net.osmand.plus.osmo;
import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandSettings.OsmandPreference;
import net.osmand.plus.notifications.OsmandNotification;
import net.osmand.plus.notifications.OsmandNotification.NotificationType;
import net.osmand.plus.osmo.OsMoGroupsStorage.OsMoDevice;
import org.apache.commons.logging.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
public class OsMoTracker implements OsMoReactor {
// 130.5143667 Maximum is 8 digits and minimum 1
private static final DecimalFormat floatingPointFormat = new DecimalFormat("0.0#######");
private static final DecimalFormat twoDigitsFormat = new DecimalFormat("0.0#");
private static final DecimalFormat integerFormat = new DecimalFormat("0");
static {
DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
floatingPointFormat.setDecimalFormatSymbols(symbols);
twoDigitsFormat.setDecimalFormatSymbols(symbols);
integerFormat.setDecimalFormatSymbols(symbols);
}
private ConcurrentLinkedQueue<Location> bufferOfLocations = new ConcurrentLinkedQueue<>();
private OsMoService service;
private int locationsSent = 0;
private OsmoTrackerListener trackerListener = null;
private Location lastSendLocation;
private Location lastBufferLocation;
private OsmandPreference<Integer> pref;
private String sessionURL;
private Map<String, OsMoDevice> trackingDevices = new java.util.concurrent.ConcurrentHashMap<>();
private OsmandPreference<Boolean> stateSendLocation;
protected static final Log LOG = PlatformUtil.getLog(OsMoTracker.class);
public interface OsmoTrackerListener {
void locationChange(String trackerId, Location location);
}
public OsMoTracker(OsMoService service, OsmandPreference<Integer> interval,
OsmandPreference<Boolean> stateSendLocation) {
this.service = service;
this.pref = interval;
this.stateSendLocation = stateSendLocation;
service.registerReactor(this);
}
public String getSessionURL() {
if (!isEnabledTracker() || sessionURL == null) {
return null;
}
return OsMoService.TRACK_URL + sessionURL;
}
public boolean isEnabledTracker() {
return stateSendLocation.get();
}
public void enableTracker() {
if (!isEnabledTracker()) {
enableTrackerCmd();
service.getMyApplication().getNotificationHelper().refreshNotification(NotificationType.OSMO);
}
}
public void enableTrackerCmd() {
stateSendLocation.set(true);
service.pushCommand("TRACKER_SESSION_OPEN");
}
public void disableTracker() {
if (isEnabledTracker()) {
stateSendLocation.set(false);
service.pushCommand("TRACKER_SESSION_CLOSE");
}
service.getMyApplication().getNotificationHelper().refreshNotification(NotificationType.OSMO);
}
public void startTrackingId(OsMoDevice d) {
service.pushCommand("LISTEN:" + d.getTrackerId());
trackingDevices.put(d.getTrackerId(), d);
}
public void stopTrackingId(OsMoDevice d) {
service.pushCommand("UNLISTEN:" + d.getTrackerId());
trackingDevices.remove(d.getTrackerId());
}
@Override
public String nextSendCommand(OsMoThread thread) {
if (!bufferOfLocations.isEmpty()) {
Location loc = bufferOfLocations.poll();
lastSendLocation = loc;
locationsSent++;
if ((System.currentTimeMillis() - loc.getTime()) > 2 * 60000 && loc.getTime() != 0) {
return "B|" + formatLocation(loc);
} else {
return "T|" + formatLocation(loc);
}
}
return null;
}
public static String formatLocation(Location loc) {
StringBuffer cmd = new StringBuffer();
cmd.append("L");
floatingPointFormat.format(loc.getLatitude(), cmd, new FieldPosition(cmd.length()));
cmd.append(":");
floatingPointFormat.format(loc.getLongitude(), cmd, new FieldPosition(cmd.length()));
if (loc.hasAccuracy()) {
cmd.append("H");
integerFormat.format(loc.getAccuracy(), cmd, new FieldPosition(cmd.length()));
}
if (loc.hasAltitude()) {
cmd.append("A");
integerFormat.format(loc.getAltitude(), cmd, new FieldPosition(cmd.length()));
}
if (loc.hasSpeed() && (int) (loc.getSpeed() * 100) != 0) {
cmd.append("S");
twoDigitsFormat.format(loc.getSpeed(), cmd, new FieldPosition(cmd.length()));
}
if (loc.hasBearing()) {
cmd.append("C");
integerFormat.format(loc.getBearing(), cmd, new FieldPosition(cmd.length()));
}
if (loc.getTime() != 0) {
cmd.append("T");
integerFormat.format(loc.getTime(), cmd, new FieldPosition(cmd.length()));
}
LOG.debug("formatLocation cmd=" + cmd);
return cmd.toString();
}
public Location getLastSendLocation() {
return lastSendLocation;
}
public void sendCoordinate(Location location) {
if (stateSendLocation.get() && location != null) {
long ltime = lastBufferLocation == null ? 0 : lastBufferLocation.getTime();
if (location.getTime() - ltime > pref.get()) {
if (lastBufferLocation != null && (!lastBufferLocation.hasSpeed() || lastBufferLocation.getSpeed() < 1) &&
lastBufferLocation.distanceTo(location) < 20) {
if (lastBufferLocation != null && location.getTime() - ltime < 60000) {
// ignores
return;
}
}
lastBufferLocation = location;
bufferOfLocations.add(location);
}
}
}
public int getLocationsSent() {
return locationsSent;
}
public int getBufferLocationsSize() {
return bufferOfLocations.size();
}
public void sendCoordinate(double lat, double lon) {
Location l = new Location("test");
l.setTime(System.currentTimeMillis());
l.setLatitude(lat);
l.setLongitude(lon);
sendCoordinate(l);
}
@Override
public boolean acceptCommand(String command, String tid, String data, JSONObject obj, OsMoThread thread) {
switch (command) {
case "LISTEN":
return true;
case "UNLISTEN":
return true;
case "TRACKER_SESSION_CLOSE":
return true;
case "TRACKER_SESSION_OPEN":
try {
sessionURL = obj.getString("url");
} catch (JSONException e) {
service.showErrorMessage(e.getMessage());
e.printStackTrace();
}
return true;
case "LT":
double lat = 0;
double lon = 0;
double speed = 0;
int k = 0;
for (int i = 1; i <= data.length(); i++) {
boolean separator = i == data.length() ||
!(Character.isDigit(data.charAt(i)) ||
data.charAt(i) == ':' || data.charAt(i) == '.' || data.charAt(i) == '-');
if (separator) {
char ch = data.charAt(k);
String vl = data.substring(k + 1, i);
if (ch == 'L') {
int l = vl.indexOf(":");
lat = Double.parseDouble(vl.substring(0, l));
lon = Double.parseDouble(vl.substring(l + 1));
} else if (ch == 'S') {
speed = Double.parseDouble(vl);
}
k = i;
}
}
if (lat != 0 || lon != 0) {
Location loc = new Location("osmo");
loc.setTime(System.currentTimeMillis());
loc.setLatitude(lat);
loc.setLongitude(lon);
if (speed > 0) {
loc.setSpeed((float) speed);
}
if (trackerListener != null) {
trackerListener.locationChange(tid, loc);
}
}
return true;
}
return false;
}
public void setTrackerListener(OsmoTrackerListener trackerListener) {
this.trackerListener = trackerListener;
}
public OsmoTrackerListener getTrackerListener() {
return trackerListener;
}
public Collection<OsMoDevice> getTrackingDevices() {
return trackingDevices.values();
}
@Override
public void onConnected() {
if (stateSendLocation.get()) {
enableTrackerCmd();
}
}
@Override
public void onDisconnected(String msg) {
}
}

View file

@ -1,17 +0,0 @@
package net.osmand.plus.osmo;
public class Protocol {
public static class CreateGroupData {
public final String name;
public final boolean onlyByInvite;
public final String description;
public final String policy;
public CreateGroupData(String name, boolean onlyByInvite, String description, String policy) {
this.name = name;
this.onlyByInvite = onlyByInvite;
this.description = description;
this.policy = policy;
}
}
}

View file

@ -1,186 +0,0 @@
package net.osmand.plus.osmo;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.support.v7.app.AlertDialog;
import android.text.method.LinkMovementMethod;
import android.util.TypedValue;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.activities.SettingsBaseActivity;
import net.osmand.plus.activities.actions.ShareDialog;
import net.osmand.plus.osmo.OsMoService.SessionInfo;
import net.osmand.util.Algorithms;
import java.util.List;
public class SettingsOsMoActivity extends SettingsBaseActivity {
private Preference debugPref;
private Preference trackerId;
// private CheckBoxPreference sendLocationsref;
public static final int[] SECONDS = new int[] {0, 1, 2, 3, 5, 10, 15, 30, 60, 90};
public static final int[] MINUTES = new int[] {2, 3, 5};
@Override
public void onCreate(Bundle savedInstanceState) {
((OsmandApplication) getApplication()).applyTheme(this);
super.onCreate(savedInstanceState);
getToolbar().setTitle(R.string.osmo_settings);
PreferenceScreen grp = getPreferenceScreen();
trackerId = new Preference(this);
trackerId.setTitle(R.string.osmo_tracker_id);
trackerId.setSummary(R.string.osmo_tracker_id_descr);
trackerId.setOnPreferenceClickListener(this);
grp.addPreference(trackerId);
CheckBoxPreference autoConnectref = createCheckBoxPreference(settings.OSMO_AUTO_CONNECT);
autoConnectref.setTitle(R.string.osmo_auto_connect);
autoConnectref.setSummary(R.string.osmo_auto_connect_descr);
grp.addPreference(autoConnectref);
// sendLocationsref = createCheckBoxPreference(settings.OSMO_AUTO_SEND_LOCATIONS);
// sendLocationsref.setTitle(R.string.osmo_auto_send_locations);
// sendLocationsref.setSummary(R.string.osmo_auto_send_locations_descr);
// sendLocationsref.setEnabled(settings.OSMO_AUTO_CONNECT.get());
// grp.addPreference(sendLocationsref);
grp.addPreference(createTimeListPreference(settings.OSMO_SAVE_TRACK_INTERVAL, SECONDS,
MINUTES, 1000, R.string.osmo_track_interval, R.string.osmo_track_interval_descr));
CheckBoxPreference showGroupNotifiations = createCheckBoxPreference(settings.OSMO_SHOW_GROUP_NOTIFICATIONS);
showGroupNotifiations.setTitle(R.string.osmo_show_group_notifications);
showGroupNotifiations.setSummary(R.string.osmo_show_group_notifications_descr);
grp.addPreference(showGroupNotifiations);
// if (OsmandPlugin.isDevelopment()) {
debugPref = new Preference(this);
debugPref.setTitle(R.string.osmo_settings_debug);
debugPref.setOnPreferenceClickListener(this);
updateDebugPref();
grp.addPreference(debugPref);
// }
}
private void updateDebugPref() {
final OsMoPlugin plugin = OsMoPlugin.getEnabledPlugin(OsMoPlugin.class);
assert plugin != null;
OsMoService service = plugin.getService();
OsMoTracker tracker = plugin.getTracker();
StringBuilder s = new StringBuilder();
if(service.isConnected()) {
int seconds = (int) ((System.currentTimeMillis() - service.getConnectionTime()) / 1000);
s.append(getString(R.string.osmo_conn_successfull, Algorithms.formatDuration(seconds, getMyApplication().accessibilityEnabled()))).append("\n");
SessionInfo si = service.getCurrentSessionInfo();
if(si == null) {
s.append(getString(R.string.osmo_auth_pending)).append("\n");
} else {
s.append(getString(R.string.osmo_session_token, si.token)).append("\n");
}
} else {
String err = service.getLastRegistrationError();
if(err == null) {
err = "...";
}
s.append(getString(R.string.osmo_io_error)).append(err).append("\n");
}
s.append(getString(R.string.osmo_locations_sent,
tracker.getLocationsSent(),
tracker.getBufferLocationsSize())).append("\n");
s.append(getString(R.string.osmo_settings_uuid)).append(" : ")
.append(getMyApplication().getSettings().OSMO_DEVICE_KEY.get().toUpperCase()).append("\n");
debugPref.setSummary(s.toString().trim());
}
@Override
public boolean onPreferenceClick(Preference preference) {
final OsMoPlugin plugin = OsMoPlugin.getEnabledPlugin(OsMoPlugin.class);
assert plugin != null;
if (preference == debugPref) {
updateDebugPref();
AlertDialog.Builder bld = new AlertDialog.Builder(this);
StringBuilder bs = new StringBuilder();
List<String> hs = plugin.getService().getHistoryOfCommands();
if(hs != null) {
for(int i = hs.size() - 1 ; i >= 0; i--) {
bs.append(hs.get(i)).append("\n");
}
}
ScrollView sv = new ScrollView(this);
TextView tv = new TextView(this);
sv.addView(tv);
final String log = bs.toString();
tv.setText(log);
tv.setPadding(5, 0, 5, 5);
tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, 19);
tv.setMovementMethod(LinkMovementMethod.getInstance());
bld.setView(sv);
bld.setNegativeButton(R.string.shared_string_ok, null);
bld.setPositiveButton(R.string.shared_string_share, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_fav_subject));
sendIntent.putExtra(Intent.EXTRA_TEXT, log);
sendIntent.setType("text/plain");
startActivity(sendIntent);
}
});
bld.show();
return true;
} else if(preference == trackerId) {
OsMoService service = plugin.getService();
SessionInfo ci = service.getCurrentSessionInfo();
if(ci == null || ci.trackerId == null) {
Toast.makeText(this, R.string.osmo_auth_pending, Toast.LENGTH_SHORT).show();
} else {
ShareDialog dlg = new ShareDialog(this);
dlg.setTitle(getString(R.string.osmo_tracker_id));
dlg.viewContent(ci.trackerId);
String url = OsMoService.SHARE_TRACKER_URL+Uri.encode(ci.trackerId);
dlg.shareURLOrText(ci.trackerId, getString(R.string.osmo_tracker_id_share, ci.trackerId, "", url), null);
dlg.showDialog();
}
}
return super.onPreferenceClick(preference);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
boolean p = super.onPreferenceChange(preference, newValue);
String id = preference.getKey();
if (id.equals(settings.OSMO_AUTO_CONNECT.getId())) {
if ((Boolean) newValue) {
final OsMoPlugin plugin = OsMoPlugin.getEnabledPlugin(OsMoPlugin.class);
assert plugin != null;
plugin.getService().connect(false);
}
// sendLocationsref.setEnabled(settings.OSMO_AUTO_CONNECT.get());
}
return p;
}
public void updateAllSettings() {
super.updateAllSettings();
}
}

View file

@ -12,6 +12,7 @@ import java.util.Map;
import net.osmand.NativeLibrary;
import net.osmand.NativeLibrary.NativeSearchResult;
import net.osmand.RenderingContext.ShadowRenderingMode;
import net.osmand.PlatformUtil;
import net.osmand.binary.BinaryMapDataObject;
import net.osmand.binary.BinaryMapIndexReader.TagValuePair;
@ -786,7 +787,7 @@ public class OsmandRenderer {
p.setShader(getShader(resId));
}
// do not check shadow color here
if(rc.shadowRenderingMode == 1) {
if(rc.shadowRenderingMode == ShadowRenderingMode.ONE_STEP.value) {
int shadowColor = req.getIntPropertyValue(req.ALL.R_SHADOW_COLOR);
if(shadowColor == 0) {
shadowColor = rc.shadowRenderingColor;
@ -852,7 +853,7 @@ public class OsmandRenderer {
private void drawPolylineShadow(Canvas canvas, RenderingContext rc, Path path, int shadowColor, int shadowRadius) {
// blurred shadows
if (rc.shadowRenderingMode == 2 && shadowRadius > 0) {
if (rc.shadowRenderingMode == ShadowRenderingMode.BLUR_SHADOW.value && shadowRadius > 0) {
// simply draw shadow? difference from option 3 ?
// paint.setColor(shadowRadius);
// paint.setColor(0xffffffff);
@ -861,7 +862,7 @@ public class OsmandRenderer {
}
// option shadow = 3 with solid border
if (rc.shadowRenderingMode == 3 && shadowRadius > 0) {
if (rc.shadowRenderingMode == ShadowRenderingMode.SOLID_SHADOW.value && shadowRadius > 0) {
paint.clearShadowLayer();
paint.setStrokeWidth(paint.getStrokeWidth() + shadowRadius * 2);
ColorFilter cf = new PorterDuffColorFilter(shadowColor, Mode.SRC_IN);