Java tutorial
/* * Copyright (C) 2010 Nullbyte <http://nullbyte.eu> * * 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 com.liato.bankdroid.appwidget; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.AsyncTask; import android.os.IBinder; import android.os.SystemClock; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.util.Log; import com.crashlytics.android.Crashlytics; import com.liato.bankdroid.Helpers; import com.liato.bankdroid.MainActivity; import com.liato.bankdroid.R; import com.liato.bankdroid.banking.Account; import com.liato.bankdroid.banking.Bank; import com.liato.bankdroid.banking.BankFactory; import com.liato.bankdroid.banking.exceptions.BankChoiceException; import com.liato.bankdroid.banking.exceptions.BankException; import com.liato.bankdroid.banking.exceptions.LoginException; import com.liato.bankdroid.db.DBAdapter; import com.liato.bankdroid.liveview.LiveViewService; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; public class AutoRefreshService extends Service { public final static String BROADCAST_WIDGET_REFRESH = "com.liato.bankdroid.WIDGET_REFRESH"; public final static String BROADCAST_MAIN_REFRESH = "com.liato.bankdroid.MAIN_REFRESH"; public final static String BROADCAST_REMOTE_NOTIFIER = "org.damazio.notifier.service.UserReceiver.USER_MESSAGE"; public final static String BROADCAST_OPENWATCH_TEXT = "com.smartmadsoft.openwatch.action.TEXT"; public final static String BROADCAST_OPENWATCH_VIBRATE = "com.smartmadsoft.openwatch.action.VIBRATE"; public final static String ACTION_MAIN_SHOW_TRANSACTIONS = "com.liato.bankdroid.action.MAIN_SHOW_TRANSACTIONS"; public final static String BROADCAST_TRANSACTIONS_UPDATED = "com.liato.bankdroid.action.TRANSACTIONS"; private final static String TAG = "AutoRefreshService"; public static void showNotification(final Bank bank, final Account account, final BigDecimal diff, Context context) { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); if (!prefs.getBoolean("notify_on_change", true)) { return; } String text = String.format("%s: %s%s", account.getName(), ((diff.compareTo(new BigDecimal(0)) == 1) ? "+" : ""), Helpers.formatBalance(diff, account.getCurrency())); if (!prefs.getBoolean("notify_delta_only", false)) { text = String.format("%s (%s)", text, Helpers.formatBalance(account.getBalance(), account.getCurrency())); } final NotificationManager notificationManager = (NotificationManager) context .getSystemService(NOTIFICATION_SERVICE); final NotificationCompat.Builder notification = new NotificationCompat.Builder(context) .setSmallIcon(bank.getImageResource()).setContentTitle(bank.getDisplayName()).setContentText(text); // Remove notification from statusbar when clicked notification.setAutoCancel(true); // http://www.freesound.org/samplesViewSingle.php?id=75235 // http://www.freesound.org/samplesViewSingle.php?id=91924 if (prefs.getString("notification_sound", null) != null) { notification.setSound(Uri.parse(prefs.getString("notification_sound", null))); } if (prefs.getBoolean("notify_with_vibration", true)) { final long[] vib = { 0, 90, 130, 80, 350, 190, 20, 380 }; notification.setVibrate(vib); } if (prefs.getBoolean("notify_with_led", true)) { notification.setLights(prefs.getInt("notify_with_led_color", context.getResources().getColor(R.color.default_led_color)), 700, 200); } final PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0); notification.setContentIntent(contentIntent); String numNotifications = prefs.getString("num_notifications", "total"); int notificationId = (int) (numNotifications.equals("total") ? 0 : numNotifications.equals("bank") ? bank.getDbId() : numNotifications.equals("account") ? account.getId().hashCode() : SystemClock.elapsedRealtime()); notificationManager.notify(notificationId, notification.build()); // Broadcast to Remote Notifier if enabled // http://code.google.com/p/android-notifier/ if (prefs.getBoolean("notify_remotenotifier", false)) { final Intent i = new Intent(BROADCAST_REMOTE_NOTIFIER); i.putExtra("title", String.format("%s (%s)", bank.getName(), bank.getDisplayName())); i.putExtra("description", text); context.sendBroadcast(i); } // Broadcast to OpenWatch if enabled // http://forum.xda-developers.com/showthread.php?t=554551 if (prefs.getBoolean("notify_openwatch", false)) { Intent i; if (prefs.getBoolean("notify_openwatch_vibrate", false)) { i = new Intent(BROADCAST_OPENWATCH_VIBRATE); } else { i = new Intent(BROADCAST_OPENWATCH_TEXT); } i.putExtra("line1", String.format("%s (%s)", bank.getName(), bank.getDisplayName())); i.putExtra("line2", text); context.sendBroadcast(i); } // Broadcast to LiveView if enabled // http://www.sonyericsson.com/cws/products/accessories/overview/liveviewmicrodisplay if (prefs.getBoolean("notify_liveview", false)) { final Intent i = new Intent(context, LiveViewService.class); i.putExtra(LiveViewService.INTENT_EXTRA_ANNOUNCE, true); i.putExtra(LiveViewService.INTENT_EXTRA_TITLE, String.format("%s (%s)", bank.getName(), bank.getDisplayName())); i.putExtra(LiveViewService.INTENT_EXTRA_TEXT, text); context.startService(i); } } public static void broadcastTransactionUpdate(final Context context, final long bankId, final String accountId) { final Intent i = new Intent(BROADCAST_TRANSACTIONS_UPDATED); i.putExtra("accountId", Long.toString(bankId) + "_" + accountId); context.sendBroadcast(i); } public static void sendWidgetRefresh(final Context context) { // Send intent to BankdroidWidgetProvider final Intent updateIntent = new Intent(BROADCAST_WIDGET_REFRESH); final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, updateIntent, PendingIntent.FLAG_UPDATE_CURRENT); try { pendingIntent.send(); } catch (final CanceledException e) { // TODO Auto-generated catch block Log.e("", e.getMessage(), e); } } @Override public void onCreate() { } @Override public void onStart(Intent intent, int startId) { handleStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { handleStart(intent, startId); return START_NOT_STICKY; } private void handleStart(Intent intent, int startId) { ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); NetworkInfo ni = cm.getActiveNetworkInfo(); if (ni != null && ni.isConnected() && shouldUpdateOnRoaming(ni)) { if (InsideUpdatePeriod()) { new DataRetrieverTask().execute(); } else { Log.v(TAG, "Skipping update due to not in update period."); stopSelf(); } } } private boolean shouldUpdateOnRoaming(NetworkInfo ni) { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); if (prefs.getBoolean("disable_during_roaming", false) && ni.isRoaming()) { return false; } return true; } private boolean InsideUpdatePeriod() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); int start = prefs.getInt("refresh_start_minutes", 0); int stop = prefs.getInt("refresh_stop_minutes", 0); // If start is bigger than stop we always update. It should perhaps // be possible to set start to 17:00 and stop to 07:00 and have to // updates working from 17 to 07 around midnight if (start >= stop) { return true; } Date now = new Date(); int minutesSinceMidnight = now.getHours() * 60 + now.getMinutes(); return minutesSinceMidnight > start && minutesSinceMidnight < stop; } @Override public void onDestroy() { } @Override public IBinder onBind(final Intent intent) { return null; } private class DataRetrieverTask extends AsyncTask<String, String, Void> { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(AutoRefreshService.this); private ArrayList<String> errors; private Resources res; public DataRetrieverTask() { } @Override protected void onPreExecute() { } @Override protected Void doInBackground(final String... args) { errors = new ArrayList<String>(); Boolean refreshWidgets = false; final ArrayList<Bank> banks = BankFactory.banksFromDb(AutoRefreshService.this, true); if (banks.isEmpty()) { return null; } final DBAdapter db = new DBAdapter(AutoRefreshService.this); BigDecimal currentBalance; BigDecimal diff; BigDecimal minDelta = new BigDecimal(prefs.getString("notify_min_delta", "0")); final HashMap<String, Account> accounts = new HashMap<String, Account>(); for (final Bank bank : banks) { if (prefs.getBoolean("debug_mode", false) && prefs.getBoolean("debug_only_testbank", false)) { Log.d(TAG, "Debug::Only_Testbank is ON. Skipping update for " + bank.getName()); continue; } if (bank.isDisabled()) { continue; } try { currentBalance = bank.getBalance(); accounts.clear(); for (final Account account : bank.getAccounts()) { accounts.put(account.getId(), account); } bank.update(); diff = currentBalance.subtract(bank.getBalance()); if (diff.compareTo(new BigDecimal(0)) != 0 && diff.abs().compareTo(minDelta) != -1) { Account oldAccount; for (final Account account : bank.getAccounts()) { oldAccount = accounts.get(account.getId()); if (oldAccount != null) { if (account.getBalance().compareTo(oldAccount.getBalance()) != 0) { boolean notify = false; switch (account.getType()) { case Account.REGULAR: notify = prefs.getBoolean("notify_for_deposit", true); break; case Account.FUNDS: notify = prefs.getBoolean("notify_for_funds", false); break; case Account.LOANS: notify = prefs.getBoolean("notify_for_loans", false); break; case Account.CCARD: notify = prefs.getBoolean("notify_for_ccards", true); break; case Account.OTHER: notify = prefs.getBoolean("notify_for_other", false); break; } if (account.isHidden() || !account.isNotify()) { notify = false; } if (notify) { diff = account.getBalance().subtract(oldAccount.getBalance()); showNotification(bank, account, diff, AutoRefreshService.this); } refreshWidgets = true; } } } if (prefs.getBoolean("autoupdates_transactions_enabled", true)) { bank.updateAllTransactions(); } } bank.closeConnection(); db.updateBank(bank); // Send update for all accounts since we're overwriting the // database transaction history if (prefs.getBoolean("content_provider_enabled", false)) { for (final Account account : bank.getAccounts()) { broadcastTransactionUpdate(getBaseContext(), bank.getDbId(), account.getId()); } } } catch (final BankException e) { // Refresh widgets if an update fails Log.e(TAG, "Error while updating bank '" + bank.getDbId() + "'; BankException: " + e.getMessage()); Crashlytics.logException(e); } catch (final LoginException e) { Log.e(TAG, "Error while updating bank '" + bank.getDbId() + "'; LoginException: " + e.getMessage()); refreshWidgets = true; db.disableBank(bank.getDbId()); } catch (BankChoiceException e) { } catch (Exception e) { Log.e(TAG, "Error while updating bank '" + bank.getDbId() + "'; Exception: " + e.getMessage()); } } if (refreshWidgets) { final Intent updateIntent = new Intent(BROADCAST_MAIN_REFRESH); sendBroadcast(updateIntent); sendWidgetRefresh(AutoRefreshService.this); } return null; } @Override protected void onProgressUpdate(final String... args) { } @Override protected void onPostExecute(final Void unused) { if ((this.errors != null) && !this.errors.isEmpty()) { final StringBuilder errormsg = new StringBuilder(); errormsg.append(res.getText(R.string.accounts_were_not_updated) + ":\n"); for (final String err : errors) { errormsg.append(err); errormsg.append("\n"); } } Editor edit = prefs.edit(); edit.putLong("autoupdates_last_update", System.currentTimeMillis()); edit.commit(); AutoRefreshService.this.stopSelf(); } } }