From c87cf5b08d59c41b9c25c73bb9cc3b1db754d7cd Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Sun, 29 Jul 2012 19:47:00 +0400 Subject: [PATCH] Initial release --- AndroidManifest.xml | 22 +++ ant.properties | 17 ++ build.xml | 92 +++++++++ icon.svg | 135 +++++++++++++ icon512.png | Bin 0 -> 25939 bytes local.properties | 10 + proguard-project.txt | 20 ++ project.properties | 14 ++ res/drawable-hdpi/ic_launcher.png | Bin 0 -> 2768 bytes res/drawable-ldpi/ic_launcher.png | Bin 0 -> 1249 bytes res/drawable-mdpi/ic_launcher.png | Bin 0 -> 1776 bytes res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 3712 bytes res/layout/main.xml | 101 ++++++++++ res/menu/main.xml | 7 + res/values/strings.xml | 8 + src/org/traccar/client/Connection.java | 153 ++++++++++++++ src/org/traccar/client/Protocol.java | 70 +++++++ src/org/traccar/client/TraccarActivity.java | 209 ++++++++++++++++++++ src/org/traccar/client/TraccarService.java | 141 +++++++++++++ 19 files changed, 999 insertions(+) create mode 100644 AndroidManifest.xml create mode 100644 ant.properties create mode 100644 build.xml create mode 100644 icon.svg create mode 100644 icon512.png create mode 100644 local.properties create mode 100644 proguard-project.txt create mode 100644 project.properties create mode 100644 res/drawable-hdpi/ic_launcher.png create mode 100644 res/drawable-ldpi/ic_launcher.png create mode 100644 res/drawable-mdpi/ic_launcher.png create mode 100644 res/drawable-xhdpi/ic_launcher.png create mode 100644 res/layout/main.xml create mode 100644 res/menu/main.xml create mode 100644 res/values/strings.xml create mode 100644 src/org/traccar/client/Connection.java create mode 100644 src/org/traccar/client/Protocol.java create mode 100644 src/org/traccar/client/TraccarActivity.java create mode 100644 src/org/traccar/client/TraccarService.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..3db264f --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/ant.properties b/ant.properties new file mode 100644 index 0000000..b0971e8 --- /dev/null +++ b/ant.properties @@ -0,0 +1,17 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked into Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..bbe6c90 --- /dev/null +++ b/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..7845bfb --- /dev/null +++ b/icon.svg @@ -0,0 +1,135 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icon512.png b/icon512.png new file mode 100644 index 0000000000000000000000000000000000000000..fe37b282ef14f41928cbc723eaebff6d057f5e98 GIT binary patch literal 25939 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 F{|Cc<>*xRg literal 0 HcmV?d00001 diff --git a/local.properties b/local.properties new file mode 100644 index 0000000..450fd33 --- /dev/null +++ b/local.properties @@ -0,0 +1,10 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. + +# location of the SDK. This is only used by Ant +# For customization when using a Version Control System, please read the +# header note. +sdk.dir=/home/user/Documents/android-sdk-linux diff --git a/proguard-project.txt b/proguard-project.txt new file mode 100644 index 0000000..f2fe155 --- /dev/null +++ b/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/project.properties b/project.properties new file mode 100644 index 0000000..9b84a6b --- /dev/null +++ b/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-16 diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..0cdb54e3d4eba6f26a6b610d3988c40ebc19a2b6 GIT binary patch literal 2768 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 RJD4p3C{rtwnv1UY{{z6!**yRN literal 0 HcmV?d00001 diff --git a/res/layout/main.xml b/res/layout/main.xml new file mode 100644 index 0000000..8df7a59 --- /dev/null +++ b/res/layout/main.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/menu/main.xml b/res/menu/main.xml new file mode 100644 index 0000000..c5391c5 --- /dev/null +++ b/res/menu/main.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100644 index 0000000..1070fbe --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,8 @@ + + + Traccar Client + Invalid input parameters. + About + Android software GPS tracker. For more information visit:\n\nhttp://www.traccar.org + Close + diff --git a/src/org/traccar/client/Connection.java b/src/org/traccar/client/Connection.java new file mode 100644 index 0000000..6c7e536 --- /dev/null +++ b/src/org/traccar/client/Connection.java @@ -0,0 +1,153 @@ +/* + * Copyright 2012 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.client; + +import java.io.*; +import java.net.*; +import java.util.*; +import android.os.Handler; +import android.content.Intent; +import android.content.Context; + +/** + * Connection with autoreconnect + */ +public class Connection { + + private String address; + private int port; + + private String connectMessage; + + private Socket socket; + private OutputStream socketStream; + + private String status; + + private Context context; + + /** + * Initialize connection parameters + */ + public Connection(String address, int port, String message) { + this.address = address; + this.port = port; + connectMessage = message; + setStatus(Traccar.STATUS_DISCONNECTED); + } + + /** + * Get address + */ + public String getAddress() { + return address; + } + + /** + * Get port + */ + public int getPort() { + return port; + } + + /** + * Set context + */ + public void setContext(Context context) { + this.context = context; + } + + /** + * Set connection status + */ + private void setStatus(String status) { + if (!status.equals(this.status)) { + this.status = status; + if (context != null) { + Intent intent = new Intent(Traccar.MSG_CONNECTION_STATUS); + intent.putExtra(Traccar.EXTRA_STATUS, status); + context.sendBroadcast(intent); + } + } + } + + /** + * Get connection status + */ + public String getStatus() { + return status; + } + + /** + * Establish connection + */ + public void connect() { + try { + socket = new Socket(address, port); + socket.setSoTimeout(Traccar.SOCKET_TIMEOUT); + socketStream = socket.getOutputStream(); + setStatus(Traccar.STATUS_CONNECTED); + send(connectMessage); + } catch (Exception e) { + reconnect(); + } + } + + /** + * Send message + */ + public void send(String message) { + try { + if (socketStream != null) { + socketStream.write(message.getBytes()); + socketStream.flush(); + } + } catch (Exception e) { + reconnect(); + } + } + + /** + * Close connection + */ + public void close() { + handler.removeCallbacks(task); + if (socket != null) { + try { + socket.close(); + } catch (Exception e) { + } + socket = null; + } + socketStream = null; + setStatus(Traccar.STATUS_DISCONNECTED); + } + + private void reconnect() { + close(); + handler.postDelayed(task, Traccar.RECONNECT_DELAY); + } + + private Handler handler = new Handler(); + private ReconnectTask task = new ReconnectTask(); + + class ReconnectTask implements Runnable { + @Override + public void run() { + connect(); + } + } +} diff --git a/src/org/traccar/client/Protocol.java b/src/org/traccar/client/Protocol.java new file mode 100644 index 0000000..0ec52ab --- /dev/null +++ b/src/org/traccar/client/Protocol.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.client; + +import java.util.Formatter; +import android.location.Location; + +/** + * Protocol formatting + */ +public class Protocol { + + /** + * Format device id message + */ + public static String createId(String id) { + StringBuilder s = new StringBuilder("$PGID,"); + Formatter f = new Formatter(s); + + s.append(id); + + byte checksum = 0; + for (byte b : s.substring(1).getBytes()) { + checksum ^= b; + } + f.format("*%02x\r\n", (int) checksum); + + return s.toString(); + } + + /** + * Format location message + */ + public static String createNmea(Location l) { + StringBuilder s = new StringBuilder("$GPRMC,"); + Formatter f = new Formatter(s); + + f.format("%1$tH%1$tM%1$tS.%1$tL,A,", l.getTime()); + + double lat = l.getLatitude(); + double lon = l.getLongitude(); + f.format("%02d%07.4f,%c,", (int) Math.abs(lat), Math.abs(lat) % 1 * 60, lat < 0 ? 'S' : 'N' ); + f.format("%03d%07.4f,%c,", (int) Math.abs(lon), Math.abs(lon) % 1 * 60, lon < 0 ? 'W' : 'E' ); + + f.format("%.2f,%.2f,", l.getSpeed(), l.getBearing()); + f.format("%1$td%1$tm%1$ty,,", l.getTime()); + + byte checksum = 0; + for (byte b : s.substring(1).getBytes()) { + checksum ^= b; + } + f.format("*%02x\r\n", (int) checksum); + + return s.toString(); + } +} + diff --git a/src/org/traccar/client/TraccarActivity.java b/src/org/traccar/client/TraccarActivity.java new file mode 100644 index 0000000..0f43901 --- /dev/null +++ b/src/org/traccar/client/TraccarActivity.java @@ -0,0 +1,209 @@ +/* + * Copyright 2012 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.client; + +import java.util.*; +import android.app.*; +import android.content.*; +import android.os.*; +import android.text.*; +import android.text.method.*; +import android.text.util.*; +import android.view.*; +import android.widget.*; + +/** + * Global parameters + */ +class Traccar { + public static final String EXTRA_ADDRESS = "address"; + public static final String EXTRA_PORT = "port"; + public static final String EXTRA_PERIOD = "period"; + public static final String EXTRA_STATUS = "status"; + + public static final String DEFAULT_ADDRESS = "193.193.165.166"; + public static final String DEFAULT_PORT = "20100"; + public static final String DEFAULT_PERIOD = "60"; + + public static final String TRACCAR_SETTINGS = "traccar_settings"; + + public static final long RECONNECT_DELAY = 10 * 1000; + public static final int SOCKET_TIMEOUT = 2000; + + public static final String MSG_UPDATE = "org.traccar.client.MSG_UPDATE"; + public static final String MSG_SERVICE_CONFIG = "org.traccar.client.MSG_SERVICE_CONFIG"; + public static final String MSG_SERVICE_STATUS = "org.traccar.client.SERVICE_STATUS"; + public static final String MSG_CONNECTION_STATUS = "org.traccar.client.CONNECTION_STATUS"; + + public static final String STATUS_STOPPED = "Stopped"; + public static final String STATUS_RUNNING = "Running"; + + public static final String STATUS_CONNECTED = "Connected"; + public static final String STATUS_DISCONNECTED = "Disconnected"; +} + +/** + * Main user interface + */ +public class TraccarActivity extends Activity { + + private EditText editAddress; + private EditText editPort; + private EditText editPeriod; + private EditText editService; + private EditText editConnection; + private ToggleButton button; + + public boolean isServiceRunning() { + ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); + List services = activityManager.getRunningServices(Integer.MAX_VALUE); + for (ActivityManager.RunningServiceInfo runningServiceInfo : services) { + if (runningServiceInfo.service.getClassName().equals(TraccarService.class.getName())){ + return true; + } + } + return false; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + // Bind elements + editAddress = (EditText) findViewById(R.id.edit_address); + editPort = (EditText) findViewById(R.id.edit_port); + editPeriod = (EditText) findViewById(R.id.edit_period); + editService = (EditText) findViewById(R.id.edit_service); + editConnection = (EditText) findViewById(R.id.edit_connection); + button = (ToggleButton) findViewById(R.id.button); + + editService.setText(Traccar.STATUS_STOPPED); + editConnection.setText(Traccar.STATUS_DISCONNECTED); + button.setChecked(isServiceRunning()); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + //super.onCreateOptionsMenu(menu); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if(item.getItemId() == R.id.about){ + showAboutDialog(); + return true; + } + return false; + } + + public void showAboutDialog() { + TextView message = new TextView(this); + SpannableString str = new SpannableString(getString(R.string.about_text)); + Linkify.addLinks(str, Linkify.WEB_URLS); + message.setText(str); + message.setMovementMethod(LinkMovementMethod.getInstance()); + int padding = (int) (10 * getResources().getDisplayMetrics().scaledDensity); + message.setPadding(padding, padding, padding, padding); + + AlertDialog.Builder dialog = new AlertDialog.Builder(this); + dialog.setTitle(R.string.about_option); + dialog.setView(message); + dialog.setPositiveButton(R.string.about_close, null); + dialog.show(); + } + + private BroadcastReceiver serviceConfigReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + editAddress.setText(intent.getStringExtra(Traccar.EXTRA_ADDRESS)); + editPort.setText(String.valueOf(intent.getIntExtra(Traccar.EXTRA_PORT, 0))); + editPeriod.setText(String.valueOf(intent.getIntExtra(Traccar.EXTRA_PERIOD, 0))); + } + }; + + private BroadcastReceiver serviceStatusReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + editService.setText(intent.getStringExtra(Traccar.EXTRA_STATUS)); + } + }; + + private BroadcastReceiver connectionStatusReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + editConnection.setText(intent.getStringExtra(Traccar.EXTRA_STATUS)); + } + }; + + @Override + protected void onStart() { + super.onStart(); + loadSettings(); + + // Register receivers + registerReceiver(serviceConfigReceiver, new IntentFilter(Traccar.MSG_SERVICE_CONFIG)); + registerReceiver(serviceStatusReceiver, new IntentFilter(Traccar.MSG_SERVICE_STATUS)); + registerReceiver(connectionStatusReceiver, new IntentFilter(Traccar.MSG_CONNECTION_STATUS)); + + // Request update + sendBroadcast(new Intent(Traccar.MSG_UPDATE)); + } + + @Override + protected void onStop() { + super.onStop(); + saveSettings(); + + // Unregister receivers + unregisterReceiver(serviceConfigReceiver); + unregisterReceiver(serviceStatusReceiver); + unregisterReceiver(connectionStatusReceiver); + } + + public void onButtonClick(View v) { + if (button.isChecked()) { + try { + Intent serviceIntent = new Intent(this, TraccarService.class); + serviceIntent.putExtra(Traccar.EXTRA_ADDRESS, editAddress.getText().toString()); + serviceIntent.putExtra(Traccar.EXTRA_PORT, Integer.parseInt(editPort.getText().toString())); + serviceIntent.putExtra(Traccar.EXTRA_PERIOD, Integer.parseInt(editPeriod.getText().toString())); + startService(serviceIntent); + } catch (NumberFormatException e) { + Toast.makeText(this, R.string.error_input, Toast.LENGTH_SHORT).show(); + button.setChecked(false); + } + } else { + stopService(new Intent(this, TraccarService.class)); + } + } + + public void saveSettings() { + SharedPreferences settings = getSharedPreferences(Traccar.TRACCAR_SETTINGS, 0); + SharedPreferences.Editor editor = settings.edit(); + editor.putString(Traccar.EXTRA_ADDRESS, editAddress.getText().toString()); + editor.putString(Traccar.EXTRA_PORT, editPort.getText().toString()); + editor.putString(Traccar.EXTRA_PERIOD, editPeriod.getText().toString()); + editor.commit(); + } + + public void loadSettings() { + SharedPreferences settings = getSharedPreferences(Traccar.TRACCAR_SETTINGS, 0); + editAddress.setText(settings.getString(Traccar.EXTRA_ADDRESS, Traccar.DEFAULT_ADDRESS)); + editPort.setText(settings.getString(Traccar.EXTRA_PORT, Traccar.DEFAULT_PORT)); + editPeriod.setText(settings.getString(Traccar.EXTRA_PERIOD, Traccar.DEFAULT_PERIOD)); + } +} diff --git a/src/org/traccar/client/TraccarService.java b/src/org/traccar/client/TraccarService.java new file mode 100644 index 0000000..26fa7e3 --- /dev/null +++ b/src/org/traccar/client/TraccarService.java @@ -0,0 +1,141 @@ +/* + * Copyright 2012 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.client; + +import java.io.*; +import java.net.*; +import java.util.*; +import android.app.Service; +import android.content.*; +import android.location.*; +import android.os.*; +import android.telephony.TelephonyManager; +import android.widget.Toast; + +/** + * Background service + */ +public class TraccarService extends Service implements LocationListener { + + private int period; + private String deviceId; + private Connection connection; + private LocationManager locationManager; + + /* + * Location methods + */ + + @Override + public void onLocationChanged(Location location) { + connection.send(Protocol.createNmea(location)); + } + + @Override + public void onProviderDisabled(String provider) { + } + + @Override + public void onProviderEnabled(String provider) { + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + } + + /* + * Status methods + */ + + private String status; + + private void setStatus(String status) { + if (!status.equals(this.status)) { + this.status = status; + Intent intent = new Intent(Traccar.MSG_SERVICE_STATUS); + intent.putExtra(Traccar.EXTRA_STATUS, status); + sendBroadcast(intent); + } + } + + private BroadcastReceiver updateReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + // Send config + intent = new Intent(Traccar.MSG_SERVICE_CONFIG); + intent.putExtra(Traccar.EXTRA_ADDRESS, connection.getAddress()); + intent.putExtra(Traccar.EXTRA_PORT, connection.getPort()); + intent.putExtra(Traccar.EXTRA_PERIOD, period); + sendBroadcast(intent); + + // Send service status + intent = new Intent(Traccar.MSG_SERVICE_STATUS); + intent.putExtra(Traccar.EXTRA_STATUS, status); + sendBroadcast(intent); + + // Send connection status + intent = new Intent(Traccar.MSG_CONNECTION_STATUS); + intent.putExtra(Traccar.EXTRA_STATUS, connection.getStatus()); + sendBroadcast(intent); + } + }; + + /* + * Service methods + */ + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // Read device id + TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); + deviceId = telephonyManager.getDeviceId(); + + // Create connection + connection = new Connection( + intent.getStringExtra(Traccar.EXTRA_ADDRESS), + intent.getIntExtra(Traccar.EXTRA_PORT, 0), + Protocol.createId(deviceId)); + connection.setContext(this); + connection.connect(); + + // Request location updates + locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); + period = intent.getIntExtra(Traccar.EXTRA_PERIOD, 0); + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, period * 1000, 0, this); + + // Report status + registerReceiver(updateReceiver, new IntentFilter(Traccar.MSG_UPDATE)); + setStatus(Traccar.STATUS_RUNNING); + return START_STICKY; + } + + @Override + public void onDestroy() { + // Close connection + connection.close(); + + // Stop location updates + locationManager.removeUpdates(this); + + // Report status + unregisterReceiver(updateReceiver); + setStatus(Traccar.STATUS_STOPPED); + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } +}