This commit is contained in:
vshcherb 2014-05-16 13:34:13 +03:00
parent 04a2acf5a1
commit 656939390d
4 changed files with 159 additions and 110 deletions

View file

@ -1,55 +1,29 @@
package net.osmand.plus.osmo; package net.osmand.plus.osmo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import net.osmand.Location; import net.osmand.Location;
import net.osmand.PlatformUtil;
import net.osmand.plus.ContextMenuAdapter; import net.osmand.plus.ContextMenuAdapter;
import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick; import net.osmand.plus.ContextMenuAdapter.OnContextMenuClick;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.OsmandPlugin; import net.osmand.plus.OsmandPlugin;
import net.osmand.plus.R; import net.osmand.plus.R;
import net.osmand.plus.Version;
import net.osmand.plus.activities.MapActivity; import net.osmand.plus.activities.MapActivity;
import net.osmand.plus.activities.SettingsActivity; import net.osmand.plus.activities.SettingsActivity;
import net.osmand.plus.views.MonitoringInfoControl; import net.osmand.plus.views.MonitoringInfoControl;
import net.osmand.plus.views.MonitoringInfoControl.MonitoringInfoControlServices; import net.osmand.plus.views.MonitoringInfoControl.MonitoringInfoControlServices;
import net.osmand.plus.views.OsmandMapTileView; import net.osmand.plus.views.OsmandMapTileView;
import org.apache.commons.logging.Log;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.preference.Preference; import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener; import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.provider.Settings.Secure;
public class OsMoPlugin extends OsmandPlugin implements MonitoringInfoControlServices { public class OsMoPlugin extends OsmandPlugin implements MonitoringInfoControlServices {
private OsmandApplication app; private OsmandApplication app;
public static final String ID = "osmand.osmo"; public static final String ID = "osmand.osmo";
private static final Log log = PlatformUtil.getLog(OsMoPlugin.class);
private OsMoService service; private OsMoService service;
private OsMoTracker tracker; private OsMoTracker tracker;
@ -113,45 +87,11 @@ public class OsMoPlugin extends OsmandPlugin implements MonitoringInfoControlSer
@Override @Override
protected Exception doInBackground(Void... params) { protected Exception doInBackground(Void... params) {
return registerOsmoDeviceKey(); return service.registerOsmoDeviceKey();
} }
}; };
} }
private Exception registerOsmoDeviceKey() {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://api.osmo.mobi/auth");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("android_id", Secure.ANDROID_ID));
nameValuePairs.add(new BasicNameValuePair("android_model", Build.MODEL));
nameValuePairs.add(new BasicNameValuePair("imei", "0"));
nameValuePairs.add(new BasicNameValuePair("android_product", Build.PRODUCT));
nameValuePairs.add(new BasicNameValuePair("osmand", Version.getFullVersion(app)));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
InputStream cm = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(cm));
String r = reader.readLine();
reader.close();
log.info("Authorization key : " + r);
final JSONObject obj = new JSONObject(r);
if(obj.has("error")) {
return new RuntimeException(obj.getString("error"));
}
app.getSettings().OSMO_DEVICE_KEY.set(obj.getString("key"));
return null;
} catch (ClientProtocolException e) {
return e;
} catch (IOException e) {
return e;
} catch (JSONException e) {
return e;
}
}
@Override @Override

View file

@ -1,16 +1,38 @@
package net.osmand.plus.osmo; package net.osmand.plus.osmo;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import android.os.Build;
import android.provider.Settings.Secure;
import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication; import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.Version;
public class OsMoService { public class OsMoService {
private OsMoThread thread; private OsMoThread thread;
private List<OsMoSender> listSenders = new java.util.concurrent.CopyOnWriteArrayList<OsMoSender>(); private List<OsMoSender> listSenders = new java.util.concurrent.CopyOnWriteArrayList<OsMoSender>();
private List<OsMoReactor> listReactors = new java.util.concurrent.CopyOnWriteArrayList<OsMoReactor>(); private List<OsMoReactor> listReactors = new java.util.concurrent.CopyOnWriteArrayList<OsMoReactor>();
private OsmandApplication app; private OsmandApplication app;
private static final Log log = PlatformUtil.getLog(OsMoService.class);
public interface OsMoSender { public interface OsMoSender {
@ -38,7 +60,7 @@ public class OsMoService {
} }
thread.stopConnection(); thread.stopConnection();
} }
thread = new OsMoThread(app, listSenders, listReactors); thread = new OsMoThread(this, listSenders, listReactors);
return true; return true;
} }
@ -69,4 +91,95 @@ public class OsMoService {
} }
public Exception registerOsmoDeviceKey() {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://api.osmo.mobi/auth");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("android_id", Secure.ANDROID_ID));
nameValuePairs.add(new BasicNameValuePair("android_model", Build.MODEL));
nameValuePairs.add(new BasicNameValuePair("imei", "0"));
nameValuePairs.add(new BasicNameValuePair("android_product", Build.PRODUCT));
nameValuePairs.add(new BasicNameValuePair("osmand", Version.getFullVersion(app)));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
InputStream cm = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(cm));
String r = reader.readLine();
reader.close();
log.info("Authorization key : " + r);
final JSONObject obj = new JSONObject(r);
if(obj.has("error")) {
return new RuntimeException(obj.getString("error"));
}
app.getSettings().OSMO_DEVICE_KEY.set(obj.getString("key"));
return null;
} catch (ClientProtocolException e) {
return e;
} catch (IOException e) {
return e;
} catch (JSONException e) {
return e;
}
}
public static class SessionInfo {
public String hostName;
public String port;
public String token;
}
public SessionInfo getSessionToken() throws IOException {
String deviceKey = app.getSettings().OSMO_DEVICE_KEY.get();
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://api.osmo.mobi/prepare");
try {
// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("key", deviceKey));
nameValuePairs.add(new BasicNameValuePair("protocol", "1"));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
// Execute HTTP Post Request
HttpResponse response = httpclient.execute(httppost);
InputStream cm = response.getEntity().getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(cm));
String r = reader.readLine();
reader.close();
log.info("Authorization key : " + r);
final JSONObject obj = new JSONObject(r);
if(obj.has("error")) {
throw new RuntimeException(obj.getString("error"));
}
if(!obj.has("port")) {
throw new RuntimeException("Port not specified");
}
if(!obj.has("address")) {
throw new RuntimeException("Host name not specified");
}
if(!obj.has("token")) {
throw new RuntimeException("Token not specified");
}
SessionInfo si = new SessionInfo();
si.hostName = obj.getString("address");
si.port = obj.getString("port");
si.token = obj.getString("token");
return si;
} catch (ClientProtocolException e) {
throw new IOException(e);
} catch (IOException e) {
throw e;
} catch (JSONException e) {
throw new IOException(e);
}
}
public void showErrorMessage(String string) {
app.showToastMessage(app.getString(R.string.osmo_io_error) + string);
}
} }

View file

@ -13,13 +13,11 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.TreeMap;
import net.osmand.PlatformUtil; import net.osmand.PlatformUtil;
import net.osmand.plus.OsmandApplication;
import net.osmand.plus.R;
import net.osmand.plus.osmo.OsMoService.OsMoReactor; import net.osmand.plus.osmo.OsMoService.OsMoReactor;
import net.osmand.plus.osmo.OsMoService.OsMoSender; import net.osmand.plus.osmo.OsMoService.OsMoSender;
import net.osmand.plus.osmo.OsMoService.SessionInfo;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.json.JSONException; import org.json.JSONException;
@ -28,25 +26,21 @@ import org.json.JSONObject;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.Message; import android.os.Message;
import android.provider.Settings.Secure;
public class OsMoThread { public class OsMoThread {
private static String TRACKER_SERVER = "srv.osmo.mobi"; // private static String TRACKER_SERVER = "srv.osmo.mobi";
private static int TRACKER_PORT = 4242; // private static int TRACKER_PORT = 3245;
protected final static Log log = PlatformUtil.getLog(OsMoThread.class); protected final static Log log = PlatformUtil.getLog(OsMoThread.class);
private static final long HEARTBEAT_DELAY = 100; private static final long HEARTBEAT_DELAY = 100;
private static final long HEARTBEAT_FAILED_DELAY = 10000; private static final long HEARTBEAT_FAILED_DELAY = 10000;
private static final long LIMIT_OF_FAILURES_RECONNECT = 10; private static final long LIMIT_OF_FAILURES_RECONNECT = 10;
private static final long CONNECTION_DELAY = 25000;
private static final long SELECT_TIMEOUT = 500; private static final long SELECT_TIMEOUT = 500;
private static int HEARTBEAT_MSG = 3; private static int HEARTBEAT_MSG = 3;
private Handler serviceThread; private Handler serviceThread;
private int failures = 0; private int failures = 0;
private int activeConnectionId = 0; private int activeConnectionId = 0;
// -1 means connected, 0 needs to reconnect, > 0 when connection initiated
private long connectionStarted = 0;
private boolean stopThread; private boolean stopThread;
private Selector selector; private Selector selector;
@ -54,7 +48,8 @@ public class OsMoThread {
private List<OsMoReactor> listReactors; private List<OsMoReactor> listReactors;
private boolean authorized; private boolean authorized;
private OsmandApplication ctx; private OsMoService service;
private SessionInfo token = null;
private String authorizationCommand = null; private String authorizationCommand = null;
private SocketChannel activeChannel; private SocketChannel activeChannel;
private ByteBuffer pendingSendCommand; private ByteBuffer pendingSendCommand;
@ -63,8 +58,9 @@ public class OsMoThread {
private LinkedList<String> queueOfMessages = new LinkedList<String>(); private LinkedList<String> queueOfMessages = new LinkedList<String>();
public OsMoThread(OsmandApplication ctx, List<OsMoSender> listSenders, List<OsMoReactor> listReactors) {
this.ctx = ctx; public OsMoThread(OsMoService service, List<OsMoSender> listSenders, List<OsMoReactor> listReactors) {
this.service = service;
this.listSenders = listSenders; this.listSenders = listSenders;
this.listReactors = listReactors; this.listReactors = listReactors;
// start thread to receive events from OSMO // start thread to receive events from OSMO
@ -90,19 +86,22 @@ public class OsMoThread {
} }
protected void initConnection() throws IOException { protected void initConnection() throws IOException {
try { if (token == null) {
token = service.getSessionToken();
}
authorized = false; authorized = false;
authorizationCommand = getAuthorizationCmd();
selector = Selector.open(); selector = Selector.open();
connectionStarted = System.currentTimeMillis(); SocketChannel activeChannel = SocketChannel.open();
activeChannel = SocketChannel.open(); activeChannel.configureBlocking(true);
activeChannel.connect(new InetSocketAddress(token.hostName, Integer.parseInt(token.port)));
activeChannel.configureBlocking(false); activeChannel.configureBlocking(false);
SelectionKey key = activeChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); SelectionKey key = activeChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
key.attach(new Integer(++activeConnectionId)); if (this.activeChannel != null) {
activeChannel.connect(new InetSocketAddress(TRACKER_SERVER, TRACKER_PORT)); stopChannel();
} catch (IOException e) {
throw e;
} }
this.activeChannel = activeChannel;
key.attach(new Integer(++activeConnectionId));
} }
public String format(String cmd, Map<String, Object> params) { public String format(String cmd, Map<String, Object> params) {
@ -120,13 +119,6 @@ public class OsMoThread {
} }
} }
private String getAuthorizationCmd() {
Map<String, Object> params = new TreeMap<String, Object>();
params.put("protocol_version", 1);
params.put("key", ctx.getSettings().OSMO_DEVICE_KEY.get());
return format("AUTH", params);
}
public void scheduleHeartbeat(long delay) { public void scheduleHeartbeat(long delay) {
Message msg = serviceThread.obtainMessage(); Message msg = serviceThread.obtainMessage();
msg.what = HEARTBEAT_MSG; msg.what = HEARTBEAT_MSG;
@ -139,7 +131,7 @@ public class OsMoThread {
} }
public boolean isConnected() { public boolean isConnected() {
return connectionStarted == -1; return activeChannel != null;
} }
protected void checkAsyncSocket() { protected void checkAsyncSocket() {
@ -148,12 +140,7 @@ public class OsMoThread {
if (selector == null) { if (selector == null) {
stopThread = true; stopThread = true;
} else { } else {
if (activeChannel != null && connectionStarted != -1 && !activeChannel.isConnectionPending()) { if(activeChannel == null) {
// connection ready
connectionStarted = -1;
}
if ((connectionStarted != -1 && System.currentTimeMillis() - connectionStarted > CONNECTION_DELAY)
|| activeChannel == null) {
initConnection(); initConnection();
} else { } else {
checkSelectedKeys(); checkSelectedKeys();
@ -265,16 +252,20 @@ public class OsMoThread {
e.printStackTrace(); e.printStackTrace();
} }
} }
if(cmd.equalsIgnoreCase("AUTH")) { boolean error = false;
if(obj != null && !obj.has("error")) { if(obj != null && !obj.has("error")) {
error = true;
try { try {
ctx.showToastMessage(ctx.getString(R.string.osmo_io_error) + obj.getString("error")); service.showErrorMessage(obj.getString("error"));
} catch (JSONException e) { } catch (JSONException e) {
e.printStackTrace(); e.printStackTrace();
} }
} else { }
if(cmd.equalsIgnoreCase("TOKEN")) {
if(!error){
authorized = true; authorized = true;
ctx.showToastMessage("OSMo authorization successfull"); // TODO delete
service.showErrorMessage("OSMo authorization successfull");
} }
continue; continue;
} }

View file

@ -7,6 +7,7 @@ import net.osmand.plus.osmo.OsMoService.OsMoSender;
public class OsMoTracker implements OsMoSender { public class OsMoTracker implements OsMoSender {
private LinkedList<Location> bufferOfLocations = new LinkedList<Location>(); private LinkedList<Location> bufferOfLocations = new LinkedList<Location>();
private boolean start;
public OsMoTracker(OsMoService service) { public OsMoTracker(OsMoService service) {
service.registerSender(this); service.registerSender(this);
@ -14,6 +15,10 @@ public class OsMoTracker implements OsMoSender {
@Override @Override
public String nextSendCommand(OsMoThread thread) { public String nextSendCommand(OsMoThread thread) {
if(!start) {
start = true;
return "TRACKER_SESSION_OPEN";
}
if(!bufferOfLocations.isEmpty()){ if(!bufferOfLocations.isEmpty()){
Location loc = bufferOfLocations.poll(); Location loc = bufferOfLocations.poll();
StringBuilder cmd = new StringBuilder("T|"); StringBuilder cmd = new StringBuilder("T|");