@@ -0,0 +1,213 @@
/*
* Copyright 2010-2012 Vasily Romanikhin bac1ca89@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
*/

/*! ---------------------------------------------------------------
* PROJ: OSLL/geo2tag
* ---------------------------------------------------------------- */

package ru.spb.osll.tracker;

import ru.spb.osll.tracker.R;
import ru.spb.osll.tracker.exception.ExceptionHandler;
import ru.spb.osll.tracker.preferences.Settings;
import ru.spb.osll.tracker.preferences.SettingsActivity;
import ru.spb.osll.tracker.preferences.Settings.ITrackerAppSettings;
import ru.spb.osll.tracker.services.RequestService;
import ru.spb.osll.tracker.utils.TrackerUtil;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class TrackerActivity extends Activity {
public static String LOG = "Tracker";

private TextView mLogView;
private BroadcastReceiver mTrackerReceiver = new TrackerReceiver();

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
registerReceiver(mTrackerReceiver, new IntentFilter(TrackerReceiver.ACTION_MESS));

mLogView = (TextView) findViewById(R.id.TextField);
initialization();

Settings settings = new Settings(this);
if (settings.isSettingsEmpty()){
settings.setDefaultSettrings();
}
}

@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mTrackerReceiver);
}

private void initialization(){
Log.v(LOG, "TrackerActivity - initialization");

Button btnService = (Button) findViewById(R.id.start_button);
btnService.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startTracker();
}
});

final Button stopBtn = (Button) findViewById(R.id.stop_button);
stopBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopTracker();
}
});

final Button settingsBtn = (Button) findViewById(R.id.settings_button);
settingsBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (TrackerUtil.isServiceRunning(TrackerActivity.this, RequestService.class)) {
showToast(TrackerUtil.MESS_SETTINGS_NOT_AVAILABLE);
} else {
startActivity(new Intent(TrackerActivity.this, SettingsActivity.class));
}
}
});

final Button creenBtn = (Button) findViewById(R.id.screeen_down_button);
creenBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TrackerUtil.hideApplication(TrackerActivity.this);
}
});
}

private void startTracker(){
if (TrackerUtil.isServiceRunning(this, RequestService.class)){
showToast(TrackerUtil.MESS_TRACKER_ALREADY_RUNNING);
} else if (TrackerUtil.isOnline(this)){
showToast(TrackerUtil.MESS_TRACKER_START);
clearLogView();
TrackerUtil.notify(this);
startService(new Intent(this, RequestService.class));

if (Settings.getPreferences(this).getBoolean(ITrackerAppSettings.IS_HIDE_APP, true)){
TrackerUtil.hideApplication(TrackerActivity.this);
}
} else if (!TrackerUtil.isOnline(this)){
showToast(TrackerUtil.MESS_FAIL_CONNECTION);
}
}

private void stopTracker(){
if (TrackerUtil.isServiceRunning(this, RequestService.class)){
showToast(TrackerUtil.MESS_TRACKER_STOP);
TrackerUtil.disnotify(this);
stopService(new Intent(this, RequestService.class));
}
}

private void showToast(final String mess){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(TrackerActivity.this, mess, Toast.LENGTH_SHORT).show();
}
});
}

private static int lineCount = 0;
private static final int maxLines = 16;
public void appendToLogView(final String mess){
if (lineCount > maxLines){
clearLogView();
lineCount = 0;
}
appendToLogViewInternal(mess);
lineCount++;
}

private void appendToLogViewInternal(final String mess){
runOnUiThread(new Runnable() {
@Override
public void run() {
mLogView.append("\n" + mess);
}
});
}

private void clearLogView(){
runOnUiThread(new Runnable() {
@Override
public void run() {
mLogView.setText("");
}
});
}

public class TrackerReceiver extends BroadcastReceiver {
public static final String ACTION_MESS = "action.mess";
public static final String TYPE_MESS = "type.mess";
public static final String TYPE_OPEATION = "type.operation";
public static final int ID_SHOW_TOAST = 0;
public static final int ID_APPEND_TO_LOG = 1;
public static final int ID_LOG_AND_TOAST = 2;

@Override
public void onReceive(Context context, Intent intent) {
final String mess = intent.getStringExtra(TYPE_MESS);
final int type = intent.getIntExtra(TYPE_OPEATION, -1);
switch (type) {
case ID_SHOW_TOAST:
showToast(mess);
break;
case ID_APPEND_TO_LOG:
appendToLogView(mess);
break;
case ID_LOG_AND_TOAST:
showToast(mess);
appendToLogView(mess);
break;
}
}
}
}
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2012 Vasily Romanikhin bac1ca89@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
*/

/*! ---------------------------------------------------------------
* PROJ: OSLL/geo2tag
* ---------------------------------------------------------------- */

package ru.spb.osll.tracker.exception;

import ru.spb.osll.tracker.R;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.TextView;

public class ExceptionActivity extends Activity{
public static String STACKTRACE = "stacktrace";

public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.exception_view);
final String stackTrace = getIntent().getStringExtra(STACKTRACE);
final TextView exeptionTextView = (TextView)findViewById(R.id.exeption_text);

exeptionTextView.setMovementMethod(ScrollingMovementMethod.getInstance());
exeptionTextView.setClickable(false);
exeptionTextView.setLongClickable(false);

exeptionTextView.append("Tracker has been crached!");
exeptionTextView.append(stackTrace);

findViewById(R.id.send).setOnClickListener(
new View.OnClickListener() {
public void onClick(View view) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { "geo2tag@lists.osll.spb.ru" });
sendIntent.putExtra(Intent.EXTRA_TEXT, stackTrace);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "Tracker exception report");
sendIntent.setType("message/rfc822");
startActivity(sendIntent);
finish();
}
}
);

findViewById(R.id.cancel).setOnClickListener(
new View.OnClickListener() {
public void onClick(View view) {
finish();
}
}
);
}


}
@@ -0,0 +1,66 @@
/*
* Copyright 2010-2011 Vasily Romanikhin bac1ca89@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
*/

/*! ---------------------------------------------------------------
* PROJ: OSLL/geo2tag
* ---------------------------------------------------------------- */

package ru.spb.osll.tracker.exception;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;

import android.content.Context;
import android.content.Intent;
import android.os.Process;

public class ExceptionHandler implements UncaughtExceptionHandler {
private final Context m_context;

public ExceptionHandler(Context context) {
m_context = context;
}

public void uncaughtException(Thread thread, Throwable exception) {
StringWriter stackTrace = new StringWriter();
exception.printStackTrace(new PrintWriter(stackTrace));
System.err.println(stackTrace);

Intent intent = new Intent(m_context, ExceptionActivity.class);
intent.putExtra(ExceptionActivity.STACKTRACE, stackTrace.toString());
m_context.startActivity(intent);

Process.killProcess(Process.myPid());
System.exit(10);
}

}
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2011 Vasily Romanikhin bac1ca89@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
*/

/*! ---------------------------------------------------------------
* PROJ: OSLL/geo2tag
* ---------------------------------------------------------------- */

package ru.spb.osll.tracker.gui;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;

public class RadioButtonDialog{
protected Context myContext;
private String myTitle;
private String[] myItems;
private int mySelectedItem;

public RadioButtonDialog(Context context, String title, String[] items, int selectedItem){
myContext = context;
myTitle = title;
myItems = items;
mySelectedItem = selectedItem;
}

protected void itemSelected(DialogInterface dialog, int item){
dialog.dismiss();
}

public void show(){
AlertDialog.Builder builder = new AlertDialog.Builder(myContext);
builder.setTitle(myTitle);
builder.setSingleChoiceItems(myItems, mySelectedItem, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
itemSelected(dialog, item);
}
});
builder.create().show();
}
}
@@ -0,0 +1,101 @@
/*
* Copyright 2010-2012 Vasily Romanikhin bac1ca89@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
*/

/*! ---------------------------------------------------------------
* PROJ: OSLL/geo2tag
* ---------------------------------------------------------------- */

package ru.spb.osll.tracker.preferences;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import ru.spb.osll.tracker.preferences.Settings.ITrackerAppSettings;
import ru.spb.osll.tracker.preferences.Settings.ITrackerNetSettings;
import android.content.SharedPreferences.Editor;

public class ConfigFeedParser extends DefaultHandler implements IXMLSettrings {
private Editor m_configEditor;
private StringBuffer m_sb;

public ConfigFeedParser(Editor configEditor) {
m_configEditor = configEditor;
}

@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
super.startElement(uri, localName, qName, atts);
m_sb = new StringBuffer();
}

@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if (localName.equals(config)){
m_configEditor.commit();
} else if (localName.equals(login)){
m_configEditor.putString(ITrackerNetSettings.LOGIN, m_sb.toString());
} else if (localName.equals(password)){
m_configEditor.putString(ITrackerNetSettings.PASSWORD, m_sb.toString());
} else if (localName.equals(channel)){
m_configEditor.putString(ITrackerNetSettings.CHANNEL, m_sb.toString());
} else if (localName.equals(server_url)){
m_configEditor.putString(ITrackerNetSettings.SERVER_URL, m_sb.toString());
} else if (localName.equals(time_tick)){
m_configEditor.putInt(ITrackerNetSettings.TIME_TICK, Integer.parseInt(m_sb.toString()));
} else if (localName.equals(show_tick)){
boolean val = m_sb.toString().equals("true") ? true : false;
m_configEditor.putBoolean(ITrackerAppSettings.IS_SHOW_TICKS, val);
} else if (localName.equals(hide_app)){
boolean val = m_sb.toString().equals("true") ? true : false;
m_configEditor.putBoolean(ITrackerAppSettings.IS_HIDE_APP, val);
}
}

@Override
public void characters(char ch[], int start, int length) {
String str = new String(ch, start, length);
m_sb.append(str);
}
}

interface IXMLSettrings{
String config = "config";
String login = "login";
String password = "password";
String channel = "channel";
String server_url = "server_url";
String time_tick = "time_tick";
String show_tick = "show_tick";
String hide_app = "hide_app";
}

@@ -0,0 +1,114 @@
/*
* Copyright 2010-2012 Vasily Romanikhin bac1ca89@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
*/

/*! ---------------------------------------------------------------
* PROJ: OSLL/geo2tag
* ---------------------------------------------------------------- */

package ru.spb.osll.tracker.preferences;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import ru.spb.osll.tracker.R;
import ru.spb.osll.tracker.TrackerActivity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.util.Log;

public class Settings {
private Context m_context;
private static final String SETTINGS_STATUS = "settings_status";

public Settings(Context context){
m_context = context;
}

public SharedPreferences getPreferences(){
return m_context.getSharedPreferences(ITrackerNetSettings.TRACKER_SETTINGS, 0);
}

public Editor getPreferencesEditor(){
return getPreferences().edit();
}

public boolean isSettingsEmpty(){
return getPreferences().getBoolean(SETTINGS_STATUS, true);
}

public void setDefaultSettrings(){
Editor editor = getPreferencesEditor();
loadFromXMLFile(editor);
editor.putBoolean(SETTINGS_STATUS, false);
editor.commit();
}

private void loadFromXMLFile(Editor configEditor) {
try {
InputSource is =
new InputSource(m_context.getResources().openRawResource(R.raw.tracker));
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
xmlreader.setContentHandler(new ConfigFeedParser(configEditor));
xmlreader.parse(is);
} catch (Exception e) {
Log.v(TrackerActivity.LOG, "loadFromXMLFile - exception: " + e.getMessage());
}
}


public static SharedPreferences getPreferences(Context c){
return new Settings(c).getPreferences();
}

public interface ITrackerNetSettings{
String TRACKER_SETTINGS = "tracker_settings";

String LOGIN = "login";
String PASSWORD = "password";
String CHANNEL = "channel";
String SERVER_URL = "server_url";
String TIME_TICK = "time_request";
String RADIUS = "radius";
String URI = "uri";
}

public interface ITrackerAppSettings{
String IS_SHOW_TICKS = "is_show_ticks";
String IS_HIDE_APP = "is_hide_app";
}

}
@@ -0,0 +1,173 @@
/*
* Copyright 2010-2011 Vasily Romanikhin bac1ca89@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
*/

/*! ---------------------------------------------------------------
* PROJ: OSLL/geo2tag
* ---------------------------------------------------------------- */

package ru.spb.osll.tracker.preferences;

import ru.spb.osll.tracker.R;
import ru.spb.osll.tracker.gui.RadioButtonDialog;
import ru.spb.osll.tracker.preferences.Settings.ITrackerAppSettings;
import ru.spb.osll.tracker.preferences.Settings.ITrackerNetSettings;
import ru.spb.osll.tracker.utils.TrackerUtil;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;

public class SettingsActivity extends Activity implements ITrackerNetSettings, ITrackerAppSettings {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings);

setTitle("Tracker Settings");
initializeFields();
initializeTimeTickBtn();

Button btnOk = (Button) findViewById(R.id.button_ok);
btnOk.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
savePreferences();
runOnUiThread(m_saveToast);
finish();
}
});

Button btnCancel = (Button) findViewById(R.id.button_cancel);
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}

private int m_timeTick;
private void initializeFields(){
initField(LOGIN, R.id.edit_login);
initField(PASSWORD, R.id.edit_password);
initField(CHANNEL, R.id.edit_channel);
initField(SERVER_URL, R.id.edit_server_address);

initCheckBox(IS_HIDE_APP, R.id.checkbox_hide);
initCheckBox(IS_SHOW_TICKS, R.id.checkbox_tick);
}

private void initializeTimeTickBtn(){
m_timeTick = new Settings(this).getPreferences().getInt(TIME_TICK, 0);

Button btnTick = (Button) findViewById(R.id.button_settings_tick);
btnTick.setText(Integer.toString(m_timeTick));
btnTick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new TimeTickDialog(SettingsActivity.this, getIdx(m_timeTick)).show();
}
});

}

private void savePreferences(){
Editor prefEditor = new Settings(this).getPreferencesEditor();
saveField(LOGIN, R.id.edit_login, prefEditor);
saveField(PASSWORD, R.id.edit_password, prefEditor);
saveField(CHANNEL, R.id.edit_channel, prefEditor);
saveField(SERVER_URL, R.id.edit_server_address, prefEditor);
prefEditor.putInt(TIME_TICK, m_timeTick);

saveCheckBox(IS_HIDE_APP, R.id.checkbox_hide, prefEditor);
saveCheckBox(IS_SHOW_TICKS, R.id.checkbox_tick, prefEditor);

prefEditor.commit();
}

private Runnable m_saveToast = new Runnable() {
@Override
public void run() {
Toast.makeText(SettingsActivity.this, TrackerUtil.MESS_SETTINGS_SAVED, Toast.LENGTH_SHORT).show();
}
};

private void initField(String key, int idField){
SharedPreferences settings = new Settings(this).getPreferences();
String str = settings.getString(key, "?????");
((EditText) findViewById(idField)).setText(str);
}

private void initCheckBox(String key, int id){
SharedPreferences settings = new Settings(this).getPreferences();
((CheckBox) findViewById(id)).setChecked(settings.getBoolean(key, false));
}

private void saveField(String key, int idField, Editor prefEditor){
String str = ((EditText) findViewById(idField)).getText().toString().trim();
prefEditor.putString(key, str);
}

private void saveCheckBox(String key, int id, Editor prefEditor){
boolean status = ((CheckBox) findViewById(id)).isChecked();
prefEditor.putBoolean(key, status);
}


String[] args = {"1", "2", "3", "4", "5", "10", "20", "30", "40", "50", "60"};
private int getIdx(int val){
for (int i = 0; i < args.length; i++){
if (args[i].equals(Integer.toString(val)))
return i;
}
return 0;
}

class TimeTickDialog extends RadioButtonDialog{
public TimeTickDialog(Context context, int selectedItem) {
super(context, "Tick interval", args, selectedItem);
}
@Override
protected void itemSelected(DialogInterface dialog, int item) {
super.itemSelected(dialog, item);
m_timeTick = Integer.parseInt(args[item]);
((Button) findViewById(R.id.button_settings_tick)).setText(Integer.toString(m_timeTick));
}
}
}
@@ -0,0 +1,131 @@
/*
* Copyright 2010-2012 Vasily Romanikhin bac1ca89@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
* PROJ: OSLL/geo2tag
*/

package ru.spb.osll.tracker.services;

import java.util.List;

import ru.spb.osll.tracker.TrackerActivity;
import ru.spb.osll.tracker.exception.ExceptionHandler;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

class LocationService extends Service {

private boolean isDeviceReady = false;

@Override
public void onCreate() {
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(this));
}

@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d(TrackerActivity.LOG, "LocationService.onStart()");
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mLocationListener);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener);
}

@Override
public void onDestroy() {
Log.d(TrackerActivity.LOG, "LocationService.onDestroy()");
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(mLocationListener);
}

private LocationListener mLocationListener = new LocationListener() {
public void onLocationChanged(Location location) {
if (!isDeviceReady && location != null) {
isDeviceReady = true;
} else if (isDeviceReady && location == null) {
isDeviceReady = false;
}
}

public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d(TrackerActivity.LOG, "onStatusChanged: " + provider + ", " + status);
}

public void onProviderEnabled(String provider) {
Log.d(TrackerActivity.LOG, "onProviderEnabled: " + provider);
}

public void onProviderDisabled(String provider) {
Log.d(TrackerActivity.LOG, "onProviderDisabled: " + provider);
}
};

public boolean isDeviceReady(){
return isDeviceReady;
}

protected Location getLocation() {
Location bestResult = null;
long minTime = 30 * 1000; // 1 sec
float bestAccuracy = Float.MAX_VALUE;
long bestTime = Long.MIN_VALUE;

LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
List<String> matchingProviders = locationManager.getAllProviders();
for (String provider : matchingProviders) {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {
float accuracy = location.getAccuracy();
long time = location.getTime();
if ((time > minTime && accuracy < bestAccuracy)) {
bestResult = location;
bestAccuracy = accuracy;
bestTime = time;
} else if (time < minTime && bestAccuracy == Float.MAX_VALUE
&& time > bestTime) {
bestResult = location;
bestTime = time;
}
}
}
return bestResult;
}

@Override
public IBinder onBind(Intent intent) {
return null;
}
}
@@ -0,0 +1,248 @@
/*
* Copyright 2010-2012 Vasily Romanikhin bac1ca89@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
*/

package ru.spb.osll.tracker.services;

import java.util.Date;

import org.json.JSONObject;

import ru.spb.osll.json.*;
import ru.spb.osll.tracker.TrackerActivity;
import ru.spb.osll.tracker.TrackerActivity.TrackerReceiver;
import ru.spb.osll.tracker.preferences.Settings;
import ru.spb.osll.tracker.preferences.Settings.ITrackerAppSettings;
import ru.spb.osll.tracker.preferences.Settings.ITrackerNetSettings;
import ru.spb.osll.tracker.utils.AndroidJGeoLogger;
import ru.spb.osll.tracker.utils.TrackerUtil;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.IBinder;
import android.util.Log;

public class RequestService extends LocationService {

static {
ru.spb.osll.log.Log.setLogger(new AndroidJGeoLogger());
}

private String mAuthToken;
private SettingsCache mSCache;
private boolean mTrackerStatus = false;

@Override
public void onStart(Intent intent, int startId) {
Log.v(TrackerActivity.LOG, "RequestService.onStart()");
super.onStart(intent, startId);
mSCache = new SettingsCache(this);

mTrackerStatus = true;
new Thread(new Runnable() {
@Override
public void run() {
try {
mAuthToken = login();
applyChannel();
subscribeToChannel();
track();
} catch (TrackerException e) {
TrackerUtil.disnotify(RequestService.this);
sendToastAndLog(e.getMessage());
stopSelf();
}
}
}).start();
}

@Override
public void onDestroy() {
Log.v(TrackerActivity.LOG, "RequestService.onDestroy()");
mTrackerStatus = false;
super.onDestroy();
}

@Override
public IBinder onBind(Intent intent) {
return null;
}

/**
* login method
* @return authToken string if login successful, null - otherwise
*/
private String login() throws TrackerException {
final JsonBaseRequest req = new JsonLoginRequest(mSCache.login, mSCache.pass, mSCache.serverUrl);
final JsonLoginResponse res = new JsonLoginResponse();
safeSendingRequest(req, res, "Login is failed", Errno.SUCCESS);
sendToLog("Login successful");
return res.getAuthString();
}

/**
* @param authToken
* @return <code>TRUE</code> if new channel successefully added or channel already exists
*/
private void applyChannel() throws TrackerException {
final JsonBaseRequest req = new JsonApplyChannelRequest(mAuthToken, mSCache.channel,
"G2T tracker channel", "http://osll.spb.ru/", 3000, mSCache.serverUrl);
final JsonApplyChannelResponse res = new JsonApplyChannelResponse();
safeSendingRequest(req, res, "Channel preparation failed",
Errno.SUCCESS, Errno.CHANNEL_ALREADY_EXIST_ERROR);
sendToLog("Channel prepared");
}

private void subscribeToChannel() throws TrackerException {
final JsonBaseRequest req = new JsonSubscribeRequest(mAuthToken,
mSCache.channel, mSCache.serverUrl);
final JsonSubscribeResponse res = new JsonSubscribeResponse();
safeSendingRequest(req, res, "Channel preparation failed",
Errno.SUCCESS, Errno.CHANNEL_ALREADY_SUBSCRIBED_ERROR);
sendToLog("Channel successfully checked");
}

public void track() throws TrackerException {
int failCount = 0;
while (mTrackerStatus){
try {
boolean success = applyMark(mAuthToken);
failCount = success ? 0 : failCount + 1;
if (failCount > 20) {
throw new TrackerException("Connection failed");
}
Thread.sleep(mSCache.trackInterval*1000);
} catch (InterruptedException e) {
mTrackerStatus = false;
}
}
}

private boolean applyMark(String authToken){
if (!isDeviceReady()) {
return false;
}

final Location location = getLocation();
final double lat = location.getLatitude();
final double lon = location.getLongitude();
final double alt = 0.0;

JSONObject JSONResponse = new JsonApplyMarkRequest(
authToken, mSCache.channel, "title", "unknown",
"this tag was generated automaticaly by tracker application",
lat, lon, alt, TrackerUtil.getTime(new Date()), mSCache.serverUrl).doRequest();

if (JSONResponse != null){
Log.d(TrackerActivity.LOG, JSONResponse.toString());
JsonApplyMarkResponse response = new JsonApplyMarkResponse();
response.parseJson(JSONResponse);
sendToLog(TrackerUtil.convertLocation(lat, lon));
return response.getErrno() == Errno.SUCCESS;
}
return false;
}

private void sendToLog(String mess) {
sendMess(TrackerReceiver.ID_APPEND_TO_LOG, mess);
}

private void sendToastAndLog(String mess) {
sendMess(TrackerReceiver.ID_LOG_AND_TOAST, mess);
}

private void sendMess(int operationId, String mess) {
Intent intent = new Intent(TrackerReceiver.ACTION_MESS);
intent.putExtra(TrackerReceiver.TYPE_OPEATION, operationId);
intent.putExtra(TrackerReceiver.TYPE_MESS, mess);
sendBroadcast(intent);
}

/*
* Safe sending requests
* If after 3 attempts response is't received - throws TrackerException
*/
private final int ATTEMPTS = 3;
private void safeSendingRequest(JsonBaseRequest request,
JsonBaseResponse response, String errorMsg, int... possibleErrnos)
throws TrackerException {
JSONObject JSONResponse = null;
for (int i = 0; i < ATTEMPTS && JSONResponse == null; i++) {
JSONResponse = request.doRequest();
}
if (JSONResponse == null){
throw new TrackerException(errorMsg);
}
Log.d(TrackerActivity.LOG, JSONResponse.toString());
response.parseJson(JSONResponse);
int errno = response.getErrno();
Log.d(TrackerActivity.LOG, "Errno: " + Errno.getErrorByCode(errno));
for (int err : possibleErrnos) {
if (err == errno) return;
}

throw new TrackerException(errorMsg);
}

@SuppressWarnings("serial")
private static class TrackerException extends Exception {
public TrackerException(String error) {
super(error);
}
}

class SettingsCache {
public String login;
public String pass;
public String channel;
public String serverUrl;
public int trackInterval;
public boolean isShowTick;

public SettingsCache(Context c){
SharedPreferences settings = new Settings(c).getPreferences();
login = settings.getString(ITrackerNetSettings.LOGIN, "");
pass = settings.getString(ITrackerNetSettings.PASSWORD, "");
channel = settings.getString(ITrackerNetSettings.CHANNEL, "");
serverUrl = settings.getString(ITrackerNetSettings.SERVER_URL, "");
trackInterval = settings.getInt(ITrackerNetSettings.TIME_TICK, 30);
isShowTick = settings.getBoolean(ITrackerAppSettings.IS_SHOW_TICKS, false);
}

@Override
public String toString() {
return "SettingsCache [login=" + login + ", pass=" + pass
+ ", channel=" + channel + ", serverUrl=" + serverUrl
+ ", trackInterval=" + trackInterval + ", isShowTick="
+ isShowTick + "]";
}
}
}
@@ -0,0 +1,92 @@
/*
* Copyright 2012 Vasily Romanikhin vasily.romanikhin@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
*/

/*! ---------------------------------------------------------------
* PROJ: OSLL/geo2tag
* ---------------------------------------------------------------- */

package ru.spb.osll.tracker.utils;

import android.util.Log;
import ru.spb.osll.log.Logger;

public class AndroidJGeoLogger implements Logger {

@Override
public void println(int level, String tag, int v) {
log(level, tag, v);
}

@Override
public void println(int level, String tag, double v) {
log(level, tag, v);
}


@Override
public void println(int level, String tag, float v) {
log(level, tag, v);
}


@Override
public void println(int level, String tag, byte v) {
log(level, tag, v);
}


@Override
public void println(int level, String tag, boolean v) {
log(level, tag, v);
}


@Override
public void println(int level, String tag, String v) {
log(level, tag, v);
}


@Override
public void println(int level, String tag, Throwable t) {
t.printStackTrace();
Log.e(tag, "Throwable:", t);
}

private void log(int level, String tag, Object msg){
if (level == Logger.DEBUG) {
Log.d(tag, msg.toString());
} else {
Log.e(tag, msg.toString());
}
}

}
@@ -0,0 +1,160 @@
/*
* Copyright 2010-2012 Vasily Romanikhin bac1ca89@gmail.com
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* The advertising clause requiring mention in adverts must never be included.
*/

/*! ---------------------------------------------------------------
* PROJ: OSLL/geo2tag
* ---------------------------------------------------------------- */

package ru.spb.osll.tracker.utils;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import ru.spb.osll.tracker.R;
import ru.spb.osll.tracker.TrackerActivity;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;

public class TrackerUtil {

//
// TODO move to JGeo
//
private static DateFormat dateFormat = new SimpleDateFormat("dd MM yyyy HH:MM:ss.SSS");
public static String getTime(Date date){
return dateFormat.format(date);
}

public static final int TRACKER_NOTIFY_ID = 1;
public static void notify(Context c){
NotificationManager nm = (NotificationManager)c.getSystemService(Context.NOTIFICATION_SERVICE);
String title = "Geo2Tag Traker service";
String expandedText = "Geo2Tag Traker service is running";
Notification notification = new Notification(R.drawable.icon, title, System.currentTimeMillis());
Intent i = new Intent(c, TrackerActivity.class);
PendingIntent launchIntent = PendingIntent.getActivity(c, 0, i, 0);
notification.setLatestEventInfo(c, title, expandedText, launchIntent);
nm.notify(TRACKER_NOTIFY_ID,notification);
}

public static void disnotify(Context c){
NotificationManager nm = (NotificationManager)c.getSystemService(Context.NOTIFICATION_SERVICE);
nm.cancel(TRACKER_NOTIFY_ID);
}

public static String convertLocation(double latitude, double longitude){
StringBuffer strBuffer = new StringBuffer();
strBuffer.append("lat: ").append(Location.convert(latitude, Location.FORMAT_MINUTES)).
append(" lon: ").append(Location.convert(longitude, Location.FORMAT_MINUTES));
return strBuffer.toString();
}

public static void hideApplication(Context c){
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
c.startActivity(intent);
}

public static boolean isOnline(Context c) {
ConnectivityManager cm = (ConnectivityManager)c.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo nInfo = cm.getActiveNetworkInfo();
if (nInfo != null && nInfo.isConnected()) {
return true;
}
else {
return false;
}
}

@SuppressWarnings("static-access")
public static boolean isServiceRunning(Context c, Class<? extends Service> clazz){
ActivityManager manager = (ActivityManager) c.getSystemService(c.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (clazz.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}

public class Logger {
private PrintWriter m_logger;

public Logger(String logPath){
try {
m_logger = new PrintWriter(new OutputStreamWriter(new FileOutputStream(logPath, true), "UTF-8"));
m_logger.println(dateFormat.format(new Date()) + " \t -------------- START LOG -------------");
} catch (IOException e) {
e.printStackTrace();
}
}

public void println(String str){
m_logger.println(dateFormat.format(new Date()) + "\t\t:" + str);
}

public void destroy(){
if (m_logger != null)
m_logger.close();
}
}

/*
* TODO move message to loc files
*/
// messages
public static final String MESS_FAIL_CONNECTION = "Connection fail...";
public static final String MESS_FAIL_CONNECTION_TO_SERVER = "Fail connection to server...";
public static final String MESS_FAIL_ADDUSER = "add user fail:";
public static final String MESS_FAIL_APPLY_CHANNEL = "apply channel fail:";
public static final String MESS_FAIL_APPLY_MARK = "apply mark fail:";

public static final String MESS_TRACKER_ALREADY_RUNNING = "Tracker is already running...";
public static final String MESS_TRACKER_START = "Tracker is running...";
public static final String MESS_TRACKER_STOP = "Tracker stopped...";

public static final String MESS_SETTINGS_SAVED = "Settings saved!";
public static final String MESS_SETTINGS_NOT_AVAILABLE = "Settings are not available! Stop the tracker...";
}