Back to project page Android-Universal-Notifier.
The source code is released under:
Apache License
If you think the Android project Android-Universal-Notifier listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.mairos.universalnotifier.model; /*from w w w . j a v a 2 s. com*/ import java.text.Format; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; import com.mairos.universalnotifier.network.SMSSender; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.os.Handler; import android.preference.PreferenceManager; import android.telephony.SmsManager; import android.util.Log; import android.webkit.ConsoleMessage; import android.webkit.WebChromeClient; import android.webkit.WebView; // core functions here - Update tasks list, schedule task execution via AlarmSevice and Execute tasks // calls from GUI and AlarmManagerBroadcastReceiver // it works in UI thread, because there's no way to run WebView (which // is interpreter for Task actions description) in other thread public class TasksQueue { private static String m_tasksURL = "http://4lessons.ru/tmp/sample_tasks.xml"; public static String getTasksURL(){ return m_tasksURL; } public static void setTasksURL(String f_tasksURL){ m_tasksURL = f_tasksURL; } private Context m_context = null; private ConcurrentHashMap<String, NotificationTask> m_tasks_map = new ConcurrentHashMap<String, NotificationTask>(); private List<Runnable> m_activeTasks = new ArrayList<Runnable>(); public NotificationTask[] getTasksArray() { if (m_tasks_map.size() == 0) return null; return m_tasks_map.values().toArray(new NotificationTask[m_tasks_map.size()]); } public ConcurrentHashMap<String, NotificationTask> getTasksMap() { return m_tasks_map; } // Singleton usage private static TasksQueue m_instance; private TasksQueue(Context f_context){ m_context = f_context; // TODO - move registerReceiver away from here // ---when the SMS has been sent--- m_context.registerReceiver(new BroadcastReceiver() { public void onReceive(Context arg0, Intent arg1) { String sentToPhoneNumber = arg1.getStringExtra("phoneNumber"); switch (getResultCode()) { case Activity.RESULT_OK: Logger.addToLog("SMS sent to " + sentToPhoneNumber, m_context); break; case SmsManager.RESULT_ERROR_GENERIC_FAILURE: Logger.addToLog("Generic failure " + sentToPhoneNumber, m_context); break; case SmsManager.RESULT_ERROR_NO_SERVICE: Logger.addToLog("No service " + sentToPhoneNumber, m_context); break; case SmsManager.RESULT_ERROR_NULL_PDU: Logger.addToLog("Null PDU " + sentToPhoneNumber, m_context); break; case SmsManager.RESULT_ERROR_RADIO_OFF: Logger.addToLog("Radio off " + sentToPhoneNumber, m_context); break; } } }, new IntentFilter(SMSSender.SMS_SENT)); // ---when the SMS has been delivered--- m_context.registerReceiver(new BroadcastReceiver() { public void onReceive(Context arg0, Intent arg1) { String sentToPhoneNumber = arg1.getStringExtra("phoneNumber"); switch (getResultCode()) { case Activity.RESULT_OK: Logger.addToLog("SMS delivered to " + sentToPhoneNumber, m_context); break; case Activity.RESULT_CANCELED: Logger.addToLog("SMS not delivered to " + sentToPhoneNumber, m_context); break; } } }, new IntentFilter(SMSSender.SMS_DELIVERED)); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(m_context); if (prefs.getBoolean("http_update", false)) loadAndScheduleCurrentTasks(Const.FROM_WEB); else loadAndScheduleCurrentTasks(Const.FROM_FOLDER); } public synchronized static TasksQueue getInstance(Context f_context){ if (m_instance == null){ m_instance = new TasksQueue(f_context); } return m_instance; } public String toString(){ String res = ""; for (NotificationTask entry: m_tasks_map.values()) res += "################" + "\n" + entry.toString() + "\n"; return res; } public static Date getNearestTime(Date f_from, int f_interval){ long now = (new Date()).getTime(); long from = f_from.getTime(); while(from < now) { from += f_interval; } return new Date(from); } public void loadAndScheduleCurrentTasks(final String f_source){ new Thread(new Runnable() { public void run() { ArrayList<NotificationTask> nts = null; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(m_context); if (f_source.equals(Const.FROM_FOLDER)){ nts = TasksXMLLoader.loadAndParseFromFolder(prefs.getString("tasks_folder", "default"), m_context); } else if (f_source.equals(Const.FROM_WEB)){ if (prefs.getBoolean("http_update", false)) nts = TasksXMLLoader.loadAndParseFromWeb(m_tasksURL, m_context); } AlarmManager am = (AlarmManager) m_context.getSystemService(Context.ALARM_SERVICE); if (nts != null && nts.size() > 0) { // clear old tasks Collection <NotificationTask> old_nts = m_tasks_map.values(); for (NotificationTask item : old_nts) { if (item.isScheduled()){ Intent intentAM = new Intent(m_context, AlarmManagerBroadcastReceiver.class); PendingIntent pi = PendingIntent.getBroadcast(m_context, item.hashCode(), intentAM, 0); am.cancel(pi); item.setSheduled(false); } } m_tasks_map.clear(); NotificationTask tmpNT = null; // add new tasks for (int i = 0; i < nts.size(); i++) { tmpNT = nts.get(i); // tasks execution time hasn't passed yet if ((!tmpNT.getRepeatable() && tmpNT.getStartTime().getTime() > (new Date()).getTime()) || (tmpNT.getRepeatable() && tmpNT.getFinishTime().getTime() > (new Date()).getTime())) { if (tmpNT.getRepeatable() && tmpNT.getStartTime().getTime() < (new Date()).getTime()) tmpNT.setStartTime(getNearestTime(tmpNT.getStartTime(), tmpNT.getInterval())); Intent unit_intent = new Intent(m_context, AlarmManagerBroadcastReceiver.class); unit_intent.putExtra(AlarmManagerBroadcastReceiver.ALARM_MODE, AlarmManagerBroadcastReceiver.ALARM_MODE_EXECUTE_TASK); unit_intent.putExtra(NotificationTask.TASK_NAME, tmpNT.getName()); PendingIntent pi = PendingIntent.getBroadcast(m_context, tmpNT.hashCode(), unit_intent, 0); if (!tmpNT.getRepeatable()) am.set(AlarmManager.RTC_WAKEUP, tmpNT.getStartTime().getTime(), pi); else am.setRepeating(AlarmManager.RTC_WAKEUP, tmpNT.getStartTime().getTime(), tmpNT.getInterval(), pi); tmpNT.setSheduled(true); } m_tasks_map.put(tmpNT.getName(), tmpNT); } if (nts.size() > 0) { Intent intentCT = new Intent(); intentCT.setAction(Const.ACTION_SHOW_CURRENT_TASKS); StringBuilder msgStr = new StringBuilder(); Format formatter = new SimpleDateFormat("hh:mm:ss", Locale.US); msgStr.append(formatter.format(new Date())); String add = ""; if (f_source.equals(Const.FROM_FOLDER)){ add = "Tasks updated from " + prefs.getString("tasks_folder", "default") + " at " + msgStr + ":"; } else if (f_source.equals(Const.FROM_WEB)){ add = "Tasks updated from " + TasksQueue.getTasksURL() + " at " + msgStr + ":"; } intentCT.putExtra(Const.TF_MESSAGE, add); m_context.sendBroadcast(intentCT); } } } }).start(); } public void executeTask(String f_task_name) { Logger.addToLog("========>>>>>>>>>>\n" + "Task '" + f_task_name + "' execution started!", m_context); final String task_name = f_task_name; Handler handler = new Handler(); final Runnable newTaskCode = new Runnable() { private NotificationTask nt = null; private WebView executor = null; @Override protected void finalize() throws Throwable { Log.d(Const.LOG_TAG, task_name + " Runnable from TasksQueue.executeTask() finalized"); super.finalize(); } @SuppressLint({ "SetJavaScriptEnabled", "JavascriptInterface" }) public void run() { if (m_tasks_map.containsKey(task_name)) { nt = m_tasks_map.get(task_name); executor = new WebView(m_context); Log.d(Const.LOG_TAG, task_name + " WebView 'executor' created"); executor.setWebChromeClient(new WebChromeClient() { @SuppressWarnings("deprecation") @Override public boolean onJsTimeout() { Logger.addToLog("'" + task_name + "' - JsTimeout", m_context); return super.onJsTimeout(); } @Override public boolean onConsoleMessage(ConsoleMessage consoleMessage) { Logger.addToLog("JSMessage: at line " + consoleMessage.lineNumber() + ", " + consoleMessage.message() /*+ ", sourceId = " + consoleMessage.sourceId()*/, m_context); return super.onConsoleMessage(consoleMessage); } }); executor.getSettings().setJavaScriptEnabled(true); executor.addJavascriptInterface(new JSInterpreter(m_context, nt, task_name), "Java"); executor.loadData("<script type=\"text/javascript\">" + nt.getJS_script() + "</script>", "text/html", "en_US"); } } }; // in order GC not to finalize this task code m_activeTasks.add(newTaskCode); handler.post(newTaskCode); handler.postDelayed(new Runnable() { @Override public void run() { Log.d(Const.LOG_TAG, "'" + task_name + "' task runnable reference removed"); // TODO the way to stop WebViewCoreThread - not needed any more //Class.forName("android.webkit.WebView").getMethod("onPause", (Class[]) null).invoke(newTaskCode.executor, (Object[]) null); // allow GC to remove this task m_activeTasks.remove(newTaskCode); } }, m_tasks_map.get(task_name).getLifetime()); } }