Java tutorial
/* * Androzic - android navigation client that uses OziExplorer maps (ozf2, ozfx3). * Copyright (C) 2010-2013 Andrey Novikov <http://andreynovikov.info/> * * This file is part of Androzic application. * * Androzic is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Androzic is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Androzic. If not, see <http://www.gnu.org/licenses/>. */ package com.androzic.plugin.tracker; import java.text.SimpleDateFormat; import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; import android.os.RemoteException; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.telephony.SmsMessage; import android.util.Log; import com.androzic.data.Tracker; import com.androzic.util.CoordinateParser; public class SMSReceiver extends BroadcastReceiver { private static final String TAG = "SMSReceiver"; @SuppressLint("SimpleDateFormat") private static final SimpleDateFormat JointechDateFormatter = new SimpleDateFormat("MM-dd HH:mm:ss"); @SuppressLint("SimpleDateFormat") private static final SimpleDateFormat XexunDateFormatter = new SimpleDateFormat("dd/MM/yy HH:mm"); @SuppressLint("SimpleDateFormat") private static final SimpleDateFormat TK102Clone1DateFormatter = new SimpleDateFormat("yy/MM/dd HH:mm"); private static final Pattern realNumber = Pattern.compile("\\d+\\.\\d+"); @Override public void onReceive(Context context, Intent intent) { String Sender = ""; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); Log.e(TAG, "SMS received"); Bundle extras = intent.getExtras(); if (extras == null) return; StringBuilder messageBuilder = new StringBuilder(); Object[] pdus = (Object[]) extras.get("pdus"); for (int i = 0; i < pdus.length; i++) { SmsMessage msg = SmsMessage.createFromPdu((byte[]) pdus[i]); String text = msg.getMessageBody(); Sender = msg.getDisplayOriginatingAddress(); Log.w(TAG, "Sender: " + Sender); if (text == null) continue; messageBuilder.append(text); } String text = messageBuilder.toString(); boolean flexMode = prefs.getBoolean(context.getString(R.string.pref_tracker_use_flex_mode), context.getResources().getBoolean(R.bool.def_flex_mode)); Log.i(TAG, "SMS: " + text); Tracker tracker = new Tracker(); if (!parseXexunTK102(text, tracker) && !parseJointechJT600(text, tracker) && !parseTK102Clone1(text, tracker) && !(parseFlexMode(text, tracker) && flexMode)) return; if (tracker.message != null) { tracker.message = tracker.message.trim(); if ("".equals(tracker.message)) tracker.message = null; } tracker.sender = Sender; if (!"".equals(tracker.sender)) { // Save tracker data TrackerDataAccess dataAccess = new TrackerDataAccess(context); dataAccess.updateTracker(tracker); try { Application application = Application.getApplication(); tracker = dataAccess.getTracker(tracker.sender);//get latest positon of tracker application.sendTrackerOnMap(dataAccess, tracker); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } dataAccess.close(); context.sendBroadcast(new Intent(Application.TRACKER_DATE_RECEIVED_BROADCAST)); // Show notification boolean notifications = prefs.getBoolean(context.getString(R.string.pref_tracker_notifications), context.getResources().getBoolean(R.bool.def_notifications)); if (notifications) { Intent i = new Intent("com.androzic.COORDINATES_RECEIVED"); i.putExtra("title", tracker.message != null ? tracker.message : tracker.name); i.putExtra("sender", tracker.name); i.putExtra("origin", context.getApplicationContext().getPackageName()); i.putExtra("lat", tracker.latitude); i.putExtra("lon", tracker.longitude); String msg = context.getString(R.string.notif_text, tracker.name); NotificationCompat.Builder builder = new NotificationCompat.Builder(context); builder.setContentTitle(context.getString(R.string.app_name)); if (tracker.message != null) builder.setContentText(tracker.name + ": " + tracker.message); else builder.setContentText(msg); PendingIntent contentIntent = PendingIntent.getBroadcast(context, (int) tracker._id, i, PendingIntent.FLAG_ONE_SHOT); builder.setContentIntent(contentIntent); builder.setSmallIcon(R.drawable.ic_stat_tracker); builder.setTicker(msg); builder.setWhen(tracker.time); int defaults = Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND; boolean vibrate = prefs.getBoolean(context.getString(R.string.pref_tracker_vibrate), context.getResources().getBoolean(R.bool.def_vibrate)); if (vibrate) defaults |= Notification.DEFAULT_VIBRATE; builder.setDefaults(defaults); builder.setAutoCancel(true); Notification notification = builder.build(); NotificationManager notificationManager = (NotificationManager) context .getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify((int) tracker._id, notification); } // Conceal SMS boolean concealsms = prefs.getBoolean(context.getString(R.string.pref_tracker_concealsms), context.getResources().getBoolean(R.bool.def_concealsms)); if (concealsms) abortBroadcast(); } } private boolean parseFlexMode(String text, Tracker tracker) { Log.w(TAG, "parseFlexMode"); //Pattern pattern = Pattern.compile("(-?\\d{1,3},\\d{5,6}[SN]?).+(-?\\d{1,3},\\d{5,6}[WE]?)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); Pattern pattern = Pattern.compile("(-?\\d+(?:\\.|,)\\d{5,6}[SN]?)[^\\d-]+(-?\\d+(?:\\.|,)\\d{5,6}[WE]?)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); Matcher m = pattern.matcher(text); if (!m.find()) return false; Log.w(TAG, "parseFlexMode - match " + m.group(0)); String latitude = m.group(1); String longitude = m.group(2); double coords[] = CoordinateParser.parse(latitude + " " + longitude); if (Double.isNaN(coords[0]) || Double.isNaN(coords[1])) return false; if (coords[0] < -180 || coords[0] > 180 || coords[1] < -180 || coords[1] > 180) return false; tracker.latitude = coords[0]; tracker.longitude = coords[1]; pattern = Pattern.compile("speed[^\\d]{0,2}(\\d{1,3}(\\.\\d{1,4})?)[^\\d]", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); m = pattern.matcher(text); if (m.find()) { String speed = m.group(1); try { tracker.speed = Double.parseDouble(speed) / 3.6; } catch (NumberFormatException ignore) { } } pattern = Pattern.compile("imei[^\\d]{0,2}(\\d+)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); m = pattern.matcher(text); if (m.find()) { String imei = m.group(1); tracker.imei = imei; } pattern = Pattern.compile("bat(?:tery)?[^\\d]{0,2}(\\d{1,3})[^\\d]", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); m = pattern.matcher(text); if (m.find()) { String batter = m.group(1); try { tracker.battery = Integer.parseInt(batter); } catch (NumberFormatException ignore) { } } Log.w(TAG, "parseFlexMode OK " + tracker.latitude + ", " + tracker.longitude); return true; } private boolean parseTK102Clone1(String text, Tracker tracker) { /* Clone TK-102 help me! lat:50.123456 long:39.123456 speed:0.00 T:13/09/30 10:27 bat:100% http://maps.google.com/maps?f=q&q=50.... lat:50.123456lon:39.123456 speed:0.00 T:13/09/30 10:27 bat:100% 3597100123456789 http://maps.google.com/maps?f=q&q=50.... lat:51.123456lon:39.123456 speed:0.00 T:13/09/30 10:27 bat:100% 3597100123456789 http://maps.google.com */ Log.w(TAG, "parseTK102Clone1"); Pattern pattern = Pattern.compile( "(.*)?\\s?lat:\\s?([^\\sl]+)\\s?long?:\\s?([^\\s]+)\\s?speed:\\s?([\\d\\.]+)\\s?T:?([\\d/:\\.\\s]+)\\s?bat:([^%]+)%\\s?(\\d+)?(.+)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); Matcher m = pattern.matcher(text); if (!m.matches()) return false; String latitude = m.group(2); String longitude = m.group(3); double coords[] = CoordinateParser.parse(latitude + " " + longitude); if (Double.isNaN(coords[0]) || Double.isNaN(coords[1])) return false; tracker.latitude = coords[0]; tracker.longitude = coords[1]; try { tracker.speed = Double.parseDouble(m.group(4)) / 3.6; } catch (NumberFormatException ignore) { } String time = m.group(5); try { Date date = TK102Clone1DateFormatter.parse(time); tracker.time = date.getTime(); } catch (Exception e) { Log.e(TAG, "Date error", e); } String battery = m.group(6); try { tracker.battery = Integer.parseInt(battery); } catch (NumberFormatException ignore) { } String s_imei = m.group(7); if (s_imei != null) tracker.imei = s_imei; String message = m.group(1); if (!"".equals(message)) tracker.message = message; return true; } private boolean parseJointechJT600(String text, Tracker tracker) { // Jointech JT600 // jeson,09-28 12:11:02,Speed:32km/h,Battery:80%,GPS:13,STANDARD, // http://maps.google.com/?q=22.549737N,114.076685E // 3110701703,09-28 12:11:02,Speed:0km/h,Charging,Base Station,STANDARD,Cell ID:4195,LAC:230 // 3110701703,04-24 22:44:33,Speed:0km/h,Battery:90%,GPS:8,STANDARD, // http://maps.google.com/?q=60.010245N,30.288323E // ALM,SOS,3110701703,09-28 12:11:02,Speed:32km/h,Battery:80%,GPS:13,STANDARD,http://maps.google.com/?q=22.549737N,114.076685E // http://fiddle.re/yv1h6 Pattern pattern = Pattern.compile( "(?:ALM,)?(?:(.*),)?([^,]+),([\\d\\-:\\s]+),(?:Speed:(\\d+)km/h,)?(?:Battery:(\\d+)%|Charging),[^,]+,[^,]+,(?:\\r?\\n)?http://maps\\.google\\.com/\\?q=([^,]+),(.+)"); Matcher m = pattern.matcher(text); if (!m.matches()) return false; String latitude = m.group(6); String longitude = m.group(7); double coords[] = CoordinateParser.parse(latitude + " " + longitude); if (Double.isNaN(coords[0]) || Double.isNaN(coords[1])) return false; tracker.latitude = coords[0]; tracker.longitude = coords[1]; try { String speed = m.group(4); if (speed != null) tracker.speed = Double.parseDouble(speed) / 3.6; } catch (NumberFormatException ignore) { } String time = m.group(3); try { Date date = JointechDateFormatter.parse(time); Date now = new Date(); date.setYear(now.getYear()); tracker.time = date.getTime(); } catch (Exception e) { Log.e(TAG, "Date error", e); } String battery = m.group(5); try { tracker.battery = Integer.parseInt(battery); } catch (NumberFormatException ignore) { } tracker.imei = m.group(2); String message = m.group(1); if (!"".equals(message)) tracker.message = message; return true; } private boolean parseXexunTK102(String text, Tracker tracker) { // Xexun family and some clones // lat: 55.807693 long: 037.730640 speed: 000.0 03/03/13 16:18 bat:F signal:F imei:358948010446647 // lat:55.950468 long:035.867116 speed: 000.0 24/11/12 08:54 bat:F signal:F imei:358948010446647 // lat: 123.345678N long: 0.125621W speed: 001.2 17/07/11 21:34 F:3.92V,1,Signal:F help me imei:123456789012 07 83.8 234 15 006B 24C4 // lat: 22.566901 long: 114.051258 speed: 0.00 14/08/09 06.54 F:3.85V,1,Signal:F help me imei:354776031555474 05 43.5 460 01 2533 720B // help me! lat:123.45678 long:001.23456 speed:090.00 T:17/01/11 15:14 Bat:25% Signal:F imei:1234567 // http://fiddle.re/fpfa6 Pattern pattern = Pattern.compile( "(.*)?\\s?lat:\\s?([^\\s]+)\\slong:\\s?([^\\s]+)\\sspeed:\\s?([\\d\\.]+)\\s(?:T:)?([\\d/:\\.\\s]+)\\s(?:bat|F):([^\\s,]+)(?:V,\\d,)?\\s?signal:([^\\s]+)\\s(.*)?\\s?imei:(\\d+)", Pattern.CASE_INSENSITIVE); Matcher m = pattern.matcher(text); if (!m.matches()) return false; String latitude = m.group(2); String longitude = m.group(3); double coords[] = CoordinateParser.parse(latitude + " " + longitude); if (Double.isNaN(coords[0]) || Double.isNaN(coords[1])) return false; tracker.latitude = coords[0]; tracker.longitude = coords[1]; try { tracker.speed = Double.parseDouble(m.group(4)) / 3.6; } catch (NumberFormatException ignore) { } String time = m.group(5); try { Date date = XexunDateFormatter.parse(time); tracker.time = date.getTime(); } catch (Exception e) { Log.e(TAG, "Date error", e); } String battery = m.group(6); if ("F".equals(battery)) tracker.battery = Tracker.LEVEL_FULL; if ("L".equals(battery)) tracker.battery = Tracker.LEVEL_LOW; try { if (battery.endsWith("%")) tracker.battery = Integer.parseInt(battery.substring(0, battery.length() - 1)); if (realNumber.matcher(battery).matches()) tracker.battery = (int) (Float.parseFloat(battery) * 100); } catch (NumberFormatException ignore) { } String signal = m.group(7); if ("F".equals(signal)) tracker.signal = Tracker.LEVEL_FULL; if ("L".equals(signal) || "0".equals(signal)) tracker.signal = Tracker.LEVEL_LOW; tracker.imei = m.group(9); String message = m.group(1); if (!"".equals(message)) tracker.message = message; message = m.group(8); if (!"".equals(message)) tracker.message = message; return true; } }