Example #1
0
 /** {@inheritDoc} */
 @Override
 public Cursor query(
     final Uri uri,
     final String[] projection,
     final String selection,
     final String[] selectionArgs,
     final String sortOrder) {
   Log.d(TAG, "query(" + uri + ",..)");
   if (uri == null) {
     return null;
   }
   final String query = uri.getLastPathSegment();
   Log.d(TAG, "query: " + query);
   if (TextUtils.isEmpty(query) || query.equals(SearchManager.SUGGEST_URI_PATH_QUERY)) {
     return null;
   }
   final int limit = Utils.parseInt(uri.getQueryParameter("limit"), -1);
   Log.d(TAG, "limit: " + limit);
   final String[] proj =
       new String[] {
         "_id",
         "address as " + SearchManager.SUGGEST_COLUMN_TEXT_1,
         "body as " + SearchManager.SUGGEST_COLUMN_TEXT_2
       };
   final String where = "body like '%" + query + "%'";
   return new MergeCursor(
       new Cursor[] {
         this.getContext()
             .getContentResolver()
             .query(
                 SMS_URI, // .
                 proj, where, null, null)
       });
 }
Example #2
0
 /**
  * Get a {@link Conversation}.
  *
  * @param context {@link Context}
  * @param threadId threadId
  * @param forceUpdate force an update of that {@link Conversation}
  * @return {@link Conversation}
  */
 public static Conversation getConversation(
     final Context context, final int threadId, final boolean forceUpdate) {
   Log.d(TAG, "getConversation(" + threadId + ")");
   synchronized (CACHE) {
     Conversation ret = CACHE.get(threadId);
     if (ret == null || ret.getContact().getNumber() == null || forceUpdate) {
       Cursor cursor =
           context
               .getContentResolver()
               .query(
                   URI_SIMPLE,
                   PROJECTION_SIMPLE,
                   ID + " = ?",
                   new String[] {String.valueOf(threadId)},
                   null);
       if (cursor.moveToFirst()) {
         ret = getConversation(context, cursor, true);
       } else {
         Log.e(TAG, "did not found conversation: " + threadId);
       }
       cursor.close();
     }
     return ret;
   }
 }
 /**
  * Add or remove an entry to/from blacklist.
  *
  * @param context {@link Context}
  * @param addr address
  */
 private static void addToOrRemoveFromSpamlist(final Context context, final String addr) {
   final SpamDB db = new SpamDB(context);
   db.open();
   if (!db.isInDB(addr)) {
     db.insertNr(addr);
     Log.d(TAG, "Added " + addr + " to spam list");
   } else {
     db.removeNr(addr);
     Log.d(TAG, "Removed " + addr + " from spam list");
   }
   db.close();
 }
 /**
  * Show all rows of a particular {@link Uri}.
  *
  * @param context {@link Context}
  * @param u {@link Uri}
  */
 static void showRows(final Context context, final Uri u) {
   Log.d(TAG, "-----GET HEADERS-----");
   Log.d(TAG, "-- " + u.toString() + " --");
   Cursor c = context.getContentResolver().query(u, null, null, null, null);
   if (c != null) {
     int l = c.getColumnCount();
     StringBuilder buf = new StringBuilder();
     for (int i = 0; i < l; i++) {
       buf.append(i + ":");
       buf.append(c.getColumnName(i));
       buf.append(" | ");
     }
     Log.d(TAG, buf.toString());
   }
 }
 /** {@inheritDoc} */
 @Override
 public void onNewIntent(final Intent intent) {
   final Intent i = intent;
   if (i != null) {
     Log.d(TAG, "got intent: " + i.getAction());
     Log.d(TAG, "got uri: " + i.getData());
     final Bundle b = i.getExtras();
     if (b != null) {
       Log.d(TAG, "user_query: " + b.get("user_query"));
       Log.d(TAG, "got extra: " + b);
     }
     final String query = i.getStringExtra("user_query");
     Log.d(TAG, "user query: " + query);
     // TODO: do something with search query
   }
 }
Example #6
0
 /** {@inheritDoc} */
 @Override
 public final void onClick(final View v) {
   switch (v.getId()) {
     case R.id.add:
       Preferences.setDefaultPlan(this, false);
       Intent intent = new Intent(this, RuleEdit.class);
       this.startActivity(intent);
       break;
     case R.id.ok:
       Preferences.setDefaultPlan(this, false);
       this.finish();
       break;
     case R.id.import_default:
       intent = new Intent(Intent.ACTION_VIEW, Uri.parse(this.getString(R.string.url_rulesets)));
       try {
         this.startActivity(intent);
       } catch (ActivityNotFoundException e) {
         Log.e(TAG, "no activity to load url", e);
         Toast.makeText(
                 this, "no activity to load url: " + intent.getDataString(), Toast.LENGTH_LONG)
             .show();
       }
       break;
     default:
       break;
   }
 }
 /**
  * Delete messages with a given {@link Uri}.
  *
  * @param context {@link Context}
  * @param uri {@link Uri}
  * @param title title of Dialog
  * @param message message of the Dialog
  * @param activity {@link Activity} to finish when deleting.
  */
 static void deleteMessages(
     final Context context,
     final Uri uri,
     final int title,
     final int message,
     final Activity activity) {
   Log.i(TAG, "deleteMessages(..," + uri + " ,..)");
   final Builder builder = new Builder(context);
   builder.setTitle(title);
   builder.setMessage(message);
   builder.setNegativeButton(android.R.string.no, null);
   builder.setPositiveButton(
       android.R.string.yes,
       new DialogInterface.OnClickListener() {
         @Override
         public void onClick(final DialogInterface dialog, final int which) {
           final int ret = context.getContentResolver().delete(uri, null, null);
           Log.d(TAG, "deleted: " + ret);
           if (activity != null && !activity.isFinishing()) {
             activity.finish();
           }
           if (ret > 0) {
             Conversation.flushCache();
             Message.flushCache();
             SmsReceiver.updateNewMessageNotification(context, null);
           }
         }
       });
   builder.show();
 }
Example #8
0
 /**
  * Set {@link Setting}s name.
  *
  * @param postfix add this to the name
  */
 protected Setting(final String postfix) {
   if (postfix == null) {
     this.name = this.getClass().getSimpleName();
   } else {
     this.name = this.getClass().getSimpleName() + "_" + postfix;
   }
   Log.d(TAG, "new " + this.getName() + "()");
 }
 /**
  * Update all running widgets.
  *
  * @param context {@link Context}
  */
 public static void updateWidgets(final Context context) {
   Log.d(TAG, "updateWidgets()");
   final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
   final int[] appWidgetIds =
       appWidgetManager.getAppWidgetIds(new ComponentName(context, StatsAppWidgetProvider.class));
   final int count = appWidgetIds.length;
   for (int i = 0; i < count; i++) {
     updateWidget(context, appWidgetManager, appWidgetIds[i]);
   }
 }
 /**
  * Mark all messages with a given {@link Uri} as read.
  *
  * @param context {@link Context}
  * @param uri {@link Uri}
  * @param read read status
  */
 static void markRead(final Context context, final Uri uri, final int read) {
   Log.d(TAG, "markRead(" + uri + "," + read + ")");
   if (uri == null) {
     return;
   }
   String[] sel = Message.SELECTION_UNREAD;
   if (read == 0) {
     sel = Message.SELECTION_READ;
   }
   final ContentResolver cr = context.getContentResolver();
   final ContentValues cv = new ContentValues();
   cv.put(Message.PROJECTION[Message.INDEX_READ], read);
   try {
     cr.update(uri, cv, Message.SELECTION_READ_UNREAD, sel);
   } catch (IllegalArgumentException e) {
     Log.e(TAG, "failed update", e);
     Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
   }
   SmsReceiver.updateNewMessageNotification(context, null);
 }
  /** {@inheritDoc} */
  @Override
  public void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    final Intent i = this.getIntent();
    Log.d(TAG, "got intent: " + i.getAction());
    Log.d(TAG, "got uri: " + i.getData());
    Log.d(TAG, "got extra: " + i.getExtras());

    this.setTheme(PreferencesActivity.getTheme(this));
    Utils.setLocale(this);
    this.setContentView(R.layout.conversationlist);

    ChangelogHelper.showChangelog(this, true);
    final List<ResolveInfo> ri =
        this.getPackageManager()
            .queryBroadcastReceivers(new Intent("de.ub0r.android.websms.connector.INFO"), 0);
    if (ri.size() == 0) {
      final Intent intent =
          Market.getInstallAppIntent(this, "de.ub0r.android.websms", Market.ALT_WEBSMS);
      ChangelogHelper.showNotes(this, true, "get WebSMS", null, intent);
    } else {
      ChangelogHelper.showNotes(this, true, null, null, null);
    }

    showRows(this);

    final ListView list = this.getListView();
    this.adapter = new ConversationAdapter(this);
    this.setListAdapter(this.adapter);
    list.setOnItemClickListener(this);
    list.setOnItemLongClickListener(this);
    this.longItemClickDialog = new String[WHICH_N];
    this.longItemClickDialog[WHICH_ANSWER] = this.getString(R.string.reply);
    this.longItemClickDialog[WHICH_CALL] = this.getString(R.string.call);
    this.longItemClickDialog[WHICH_VIEW_CONTACT] = this.getString(R.string.view_contact_);
    this.longItemClickDialog[WHICH_VIEW] = this.getString(R.string.view_thread_);
    this.longItemClickDialog[WHICH_DELETE] = this.getString(R.string.delete_thread_);
    this.longItemClickDialog[WHICH_MARK_SPAM] = this.getString(R.string.filter_spam_);
  }
  /**
   * Default Constructor.
   *
   * @param c {@link ConversationListActivity}
   */
  public ConversationAdapter(final Activity c) {
    super(c, R.layout.conversationlist_item, null, true);
    activity = c;

    SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(activity);
    useGridLayout = PreferencesActivity.getGridlayoutEnabled(activity);
    if (useGridLayout) {
      super.setViewResource(R.layout.conversation_square);
    }
    final ContentResolver cr = c.getContentResolver();
    queryHandler = new BackgroundQueryHandler(cr);
    SpamDB spam = new SpamDB(c);
    spam.open();
    blacklist = spam.getAllEntries();
    spam.close();

    defaultContactAvatar = c.getResources().getDrawable(R.drawable.ic_contact_picture);

    convertNCR = PreferencesActivity.decodeDecimalNCR(c);
    showEmoticons = PreferencesActivity.showEmoticons(c);
    textSize = PreferencesActivity.getTextsize(c);
    textColor = PreferencesActivity.getTextcolor(c);

    Cursor cursor = null;
    try {
      cursor = cr.query(Conversation.URI_SIMPLE, Conversation.PROJECTION_SIMPLE, null, null, null);
    } catch (SQLiteException e) {
      Log.e(TAG, "error getting conversations", e);
    }
    /* {@link Cursor} to the original Content to listen for changes. */
    Cursor origCursor = cursor;

    if (origCursor != null) {
      origCursor.registerContentObserver(
          new ContentObserver(new Handler()) {
            @Override
            public void onChange(final boolean selfChange) {
              super.onChange(selfChange);
              if (!selfChange) {
                Log.d(TAG, "call startMsgListQuery();");
                ConversationAdapter.this.startMsgListQuery();
                Log.d(TAG, "invalidate cache");
                Conversation.invalidate();
              }
            }
          });
    }
    // startMsgListQuery();
  }
Example #13
0
 /**
  * Get a {@link Conversation}.
  *
  * @param context {@link Context}
  * @param cursor {@link Cursor} to read the data from
  * @param sync fetch of information
  * @return {@link Conversation}
  */
 public static Conversation getConversation(
     final Context context, final Cursor cursor, final boolean sync) {
   Log.d(TAG, "getConversation(" + sync + ")");
   synchronized (CACHE) {
     Conversation ret = CACHE.get(cursor.getInt(INDEX_SIMPLE_ID));
     if (ret == null) {
       ret = new Conversation(context, cursor, sync);
       CACHE.put(ret.getThreadId(), ret);
       Log.d(TAG, "cachesize: " + CACHE.size());
       while (CACHE.size() > CAHCESIZE) {
         Integer i = CACHE.keySet().iterator().next();
         Log.d(TAG, "rm con. from cache: " + i);
         Conversation cc = CACHE.remove(i);
         if (cc == null) {
           Log.w(TAG, "CACHE might be inconsistent!");
           break;
         }
       }
     } else {
       ret.update(context, cursor, sync);
     }
     return ret;
   }
 }
  /** {@inheritDoc} */
  @Override
  public void onUpdate(
      final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) {
    Log.d(TAG, "onUpdate()");
    Utils.setLocale(context);
    // Update logs and run rule matcher
    LogRunnerService.update(context, LogRunnerService.ACTION_RUN_MATCHER);

    final int count = appWidgetIds.length;

    // Perform this loop procedure for each App Widget that belongs to this
    // provider
    for (int i = 0; i < count; i++) {
      updateWidget(context, appWidgetManager, appWidgetIds[i]);
    }
  }
 /** {@inheritDoc} */
 @Override
 public boolean onOptionsItemSelected(final MenuItem item) {
   switch (item.getItemId()) {
     case R.id.item_compose:
       final Intent i = getComposeIntent(this, null);
       try {
         this.startActivity(i);
       } catch (ActivityNotFoundException e) {
         Log.e(TAG, "error launching intent: " + i.getAction() + ", " + i.getData());
         Toast.makeText(
                 this,
                 "error launching messaging app!\n" + "Please contact the developer.",
                 Toast.LENGTH_LONG)
             .show();
       }
       return true;
     case R.id.item_settings: // start settings activity
       if (Utils.isApi(Build.VERSION_CODES.HONEYCOMB)) {
         this.startActivity(
             new Intent(
                 this, // .
                 Preferences11Activity.class));
       } else {
         this.startActivity(new Intent(this, PreferencesActivity.class));
       }
       return true;
     case R.id.item_donate:
       DonationHelper.startDonationActivity(this, true);
       return true;
     case R.id.item_delete_all_threads:
       deleteMessages(
           this,
           Uri.parse("content://sms/"),
           R.string.delete_threads_,
           R.string.delete_threads_question,
           null);
       return true;
     case R.id.item_mark_all_read:
       markRead(this, Uri.parse("content://sms/"), 1);
       markRead(this, Uri.parse("content://mms/"), 1);
       return true;
     default:
       return super.onOptionsItemSelected(item);
   }
 }
 /** Start ConversationList query. */
 public final void startMsgListQuery() {
   // Cancel any pending queries
   queryHandler.cancelOperation(MESSAGE_LIST_QUERY_TOKEN);
   try {
     // Kick off the new query
     activity.setProgressBarIndeterminateVisibility(Boolean.TRUE);
     queryHandler.startQuery(
         MESSAGE_LIST_QUERY_TOKEN,
         null,
         Conversation.URI_SIMPLE,
         Conversation.PROJECTION_SIMPLE,
         null,
         null,
         SORT);
   } catch (SQLiteException e) {
     Log.e(TAG, "error starting query", e);
   }
 }
 /** {@inheritDoc} */
 public void onItemClick(
     final AdapterView<?> parent, final View view, final int position, final long id) {
   final Conversation c =
       Conversation.getConversation(this, (Cursor) parent.getItemAtPosition(position), false);
   final Uri target = c.getUri();
   final Intent i = new Intent(this, MessageListActivity.class);
   i.setData(target);
   try {
     this.startActivity(i);
   } catch (ActivityNotFoundException e) {
     Log.e(TAG, "error launching intent: " + i.getAction() + ", " + i.getData());
     Toast.makeText(
             this,
             "error launching messaging app!\n" + "Please contact the developer.",
             Toast.LENGTH_LONG)
         .show();
   }
 }
Example #18
0
 /**
  * Update data.
  *
  * @param context {@link Context}
  * @param cursor {@link Cursor} to read from.
  * @param sync fetch of information
  */
 private void update(final Context context, final Cursor cursor, final boolean sync) {
   Log.d(TAG, "update(" + this.threadId + "," + sync + ")");
   long d = cursor.getLong(INDEX_SIMPLE_DATE);
   if (d != this.date) {
     this.id = cursor.getInt(INDEX_SIMPLE_ID);
     this.date = d;
     this.body = cursor.getString(INDEX_SIMPLE_BODY);
   }
   this.count = cursor.getInt(INDEX_SIMPLE_COUNT);
   this.read = cursor.getInt(INDEX_SIMPLE_READ);
   final int nid = cursor.getInt(INDEX_SIMPLE_NID);
   if (nid != this.contact.getRecipientId()) {
     this.contact = new Contact(nid);
   }
   if (this.lastUpdate < validCache) {
     AsyncHelper.fillConversation(context, this, sync);
     this.lastUpdate = System.currentTimeMillis();
   }
 }
Example #19
0
  /** {@inheritDoc} */
  @Override
  public void onCreate() {
    super.onCreate();
    Log.init("SMSdroid");
    Log.i(TAG, "init SMSdroid v" + this.getString(R.string.app_version));

    final SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(this);
    int state = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
    if (p.getBoolean(PreferencesActivity.PREFS_ACTIVATE_SENDER, true)) {
      try {
        Cursor c =
            this.getContentResolver()
                .query(SenderActivity.URI_SENT, PROJECTION, null, null, "_id LIMIT 1");
        if (c == null) {
          Log.i(TAG, "disable .Sender: curor=null");
        } else if (SmsManager.getDefault() == null) {
          Log.i(TAG, "disable .Sender: SmsManager=null");
        } else {
          state = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
          Log.d(TAG, "enable .Sender");
        }
        if (c != null && !c.isClosed()) {
          c.close();
        }
      } catch (IllegalArgumentException e) {
        Log.e(TAG, "disable .Sender: " + e.getMessage(), e);
      } catch (SQLiteException e) {
        Log.e(TAG, "disable .Sender: " + e.getMessage(), e);
      }
    } else {
      Log.i(TAG, "disable .Sender");
    }
    this.getPackageManager()
        .setComponentEnabledSetting(
            new ComponentName(this, SenderActivity.class), state, PackageManager.DONT_KILL_APP);
  }
Example #20
0
  /**
   * Move item.
   *
   * @param from from
   * @param to to
   */
  private void move(final int from, final int to) {
    Log.d(TAG, "move(" + from + "," + to + ")");
    if (from == to) {
      return;
    }
    final ContentResolver cr = this.getContentResolver();
    final int l = this.adapter.getCount();
    Log.d(TAG, "move(): l=" + l);
    long[] ids = new long[l];
    int i = 0;
    int dir;
    if (from < to) {
      dir = 1;
    } else {
      dir = -1;
    }
    Log.d(TAG, "move(): dir=" + dir);
    for (i = 0; i < l; i++) {
      final long id = this.adapter.getItemId(i);
      ids[i] = id;
      Log.d(TAG, "move(): ids[" + i + "]=" + ids[i]);
    }

    final long oldid = ids[from];
    Log.d(TAG, "move(): oldid=" + oldid);
    for (i = from + dir; (from < to && i <= to) || (from > to && i >= to); i += dir) {
      ids[i - dir] = ids[i];
      Log.d(TAG, "move(): ids[" + (i - dir) + "]=" + ids[i - dir]);
    }
    ids[to] = oldid;
    Log.d(TAG, "move(): ids[" + to + "]=" + ids[to]);

    ContentValues cv = new ContentValues();
    for (i = 0; i < l; i++) {
      cv.clear();
      cv.put(DataProvider.Rules.ORDER, i);
      cr.update(ContentUris.withAppendedId(DataProvider.Rules.CONTENT_URI, ids[i]), cv, null, null);
    }
  }
Example #21
0
 /** {@inheritDoc} */
 @Override
 public String getType(final Uri uri) {
   Log.d(TAG, "getType(" + uri + ")");
   throw new UnsupportedOperationException("not implemented");
 }
  /**
   * Update a single widget.
   *
   * @param context {@link Context}
   * @param appWidgetManager {@link AppWidgetManager}
   * @param appWidgetId id of widget
   */
  static void updateWidget(
      final Context context, final AppWidgetManager appWidgetManager, final int appWidgetId) {
    Log.d(TAG, "updateWidget(" + appWidgetId + ")");
    final SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(context);
    final long pid = p.getLong(WIDGET_PLANID + appWidgetId, -1L);
    final boolean showShortname = p.getBoolean(WIDGET_SHORTNAME + appWidgetId, false);
    final boolean showCost = p.getBoolean(WIDGET_COST + appWidgetId, false);
    final boolean showBillPeriod = p.getBoolean(WIDGET_BILLPERIOD + appWidgetId, false);
    final boolean showIcon = p.getBoolean(WIDGET_ICON + appWidgetId, false);
    final boolean smallWidget = p.getBoolean(WIDGET_SMALL + appWidgetId, false);
    final Float statsTextSize =
        p.getFloat(WIDGET_STATS_TEXTSIZE + appWidgetId, StatsAppWidgetConfigure.DEFAULT_TEXTSIZE);
    final Float planTextSize =
        p.getFloat(WIDGET_PLAN_TEXTSIZE + appWidgetId, StatsAppWidgetConfigure.DEFAULT_TEXTSIZE);
    final int textColor =
        p.getInt(WIDGET_TEXTCOLOR + appWidgetId, StatsAppWidgetConfigure.DEFAULT_TEXTCOLOR);
    final int bgColor =
        p.getInt(WIDGET_BGCOLOR + appWidgetId, StatsAppWidgetConfigure.DEFAULT_BGCOLOR);
    Log.d(TAG, "planid: " + pid);
    final ContentResolver cr = context.getContentResolver();

    if (pid < 0L) {
      return;
    }
    final long ppid = DataProvider.Plans.getParent(cr, pid);
    long bid = -1L;
    String pname = null;
    float cpp = 0F;
    int ltype = DataProvider.LIMIT_TYPE_NONE;
    long limit = 0L;
    int ptype = -1;
    String where;
    int upc, upm, ups;
    boolean isMerger;
    String billdayWhere = null;
    Cursor cursor =
        cr.query(
            DataProvider.Plans.CONTENT_URI,
            DataProvider.Plans.PROJECTION,
            DataProvider.Plans.ID + " = ?",
            new String[] {String.valueOf(pid)},
            null);
    if (cursor.moveToFirst()) {
      if (showShortname) {
        pname = cursor.getString(DataProvider.Plans.INDEX_SHORTNAME);
      } else {
        pname = cursor.getString(DataProvider.Plans.INDEX_NAME);
      }
      ptype = cursor.getInt(DataProvider.Plans.INDEX_TYPE);
      bid = cursor.getLong(DataProvider.Plans.INDEX_BILLPERIOD_ID);
      ltype = cursor.getInt(DataProvider.Plans.INDEX_LIMIT_TYPE);
      limit =
          DataProvider.Plans.getLimit(ptype, ltype, cursor.getLong(DataProvider.Plans.INDEX_LIMIT));
      upc = cursor.getInt(DataProvider.Plans.INDEX_MIXED_UNITS_CALL);
      upm = cursor.getInt(DataProvider.Plans.INDEX_MIXED_UNITS_MMS);
      ups = cursor.getInt(DataProvider.Plans.INDEX_MIXED_UNITS_SMS);
      cpp = cursor.getFloat(DataProvider.Plans.INDEX_COST_PER_PLAN);

      final String s = cursor.getString(DataProvider.Plans.INDEX_MERGED_PLANS);
      where = DataProvider.Plans.parseMergerWhere(pid, s);
      if (s == null || s.length() == 0) {
        isMerger = false;
      } else {
        isMerger = true;
      }
    } else {
      return;
    }
    cursor.close();

    int bpos = 0;
    int bmax = -1;
    if (bid >= 0L) {
      cursor =
          cr.query(
              DataProvider.Plans.CONTENT_URI,
              DataProvider.Plans.PROJECTION,
              DataProvider.Plans.ID + " = ?",
              new String[] {String.valueOf(bid)},
              null);
      if (cursor.moveToFirst()) {
        final int bp = cursor.getInt(DataProvider.Plans.INDEX_BILLPERIOD);
        final long bday = cursor.getLong(DataProvider.Plans.INDEX_BILLDAY);
        billdayWhere = DataProvider.Plans.getBilldayWhere(bp, bday, null);
        if (showBillPeriod && bp != DataProvider.BILLPERIOD_INFINITE) {
          Calendar billDay = Calendar.getInstance();
          billDay.setTimeInMillis(bday);
          billDay = DataProvider.Plans.getBillDay(bp, billDay, null, false);
          final Calendar nextBillDay = DataProvider.Plans.getBillDay(bp, billDay, null, true);

          final long pr = billDay.getTimeInMillis() / CallMeter.MILLIS;
          final long nx =
              (nextBillDay.getTimeInMillis() // .
                      / CallMeter.MILLIS)
                  - pr;
          long nw = System.currentTimeMillis();
          nw = (nw / CallMeter.MILLIS) - pr;

          bmax = (int) nx;
          bpos = (int) nw;
        }
      }
      cursor.close();
    }
    Log.d(TAG, "bpos/bmax: " + bpos + "/" + bmax);
    billdayWhere = DbUtils.sqlAnd(billdayWhere, where);

    int used = 0;
    PlanStatus ps =
        PlanStatus.get(
            cr, billdayWhere, isMerger && ptype == DataProvider.TYPE_MIXED, upc, upm, ups);

    if (ps == null) {
      ps = new PlanStatus();
    } else {
      Log.d(TAG, "plan: " + pid);
      Log.d(TAG, "count: " + ps.count);
      Log.d(TAG, "cost: " + ps.cost);
      Log.d(TAG, "billedAmount: " + ps.billedAmount);
      used = DataProvider.Plans.getUsed(ptype, ltype, ps.billedAmount, ps.cost);
    }
    if (ppid >= 0L) {
      ps.cost = 0F;
    } else {
      ps.cost += cpp;
    }

    String stats =
        Plans.formatAmount(ptype, ps.billedAmount, p.getBoolean(Preferences.PREFS_SHOWHOURS, true));
    if (ptype == DataProvider.TYPE_CALL) {
      stats += " (" + ps.count + ")";
    }
    if (limit > 0) {
      stats += "\n" + (used * CallMeter.HUNDRET / limit) + "%";
    }
    if (showCost && ps.cost > 0F) {
      stats += "\n" + String.format(Preferences.getCurrencyFormat(context), ps.cost);
    }

    Log.d(TAG, "limit: " + limit);
    Log.d(TAG, "used: " + used);
    Log.d(TAG, "stats: " + stats);

    final int widgetLayout =
        smallWidget ? R.layout.stats_appwidget_small : R.layout.stats_appwidget;
    final RemoteViews views = new RemoteViews(context.getPackageName(), widgetLayout);
    views.setImageViewBitmap(R.id.widget_bg, getBackground(bgColor, bmax, bpos, limit, used));
    views.setTextViewText(R.id.plan, pname);
    views.setTextViewText(R.id.stats, stats);
    views.setFloat(R.id.plan, "setTextSize", planTextSize);
    views.setFloat(R.id.stats, "setTextSize", statsTextSize);
    views.setTextColor(R.id.plan, textColor);
    views.setTextColor(R.id.stats, textColor);
    views.setOnClickPendingIntent(
        R.id.widget, PendingIntent.getActivity(context, 0, new Intent(context, Plans.class), 0));
    if (showIcon) {
      views.setViewVisibility(R.id.widget_icon, android.view.View.VISIBLE);
      switch (ptype) {
        case DataProvider.TYPE_DATA:
          views.setImageViewResource(R.id.widget_icon, R.drawable.data);
          break;
        case DataProvider.TYPE_CALL:
          views.setImageViewResource(R.id.widget_icon, R.drawable.phone);
          break;
        case DataProvider.TYPE_SMS:
        case DataProvider.TYPE_MMS:
          views.setImageViewResource(R.id.widget_icon, R.drawable.message);
          break;
        case DataProvider.TYPE_MIXED:
          views.setImageViewResource(R.id.widget_icon, R.drawable.phone);
          break;
      }
    }

    appWidgetManager.updateAppWidget(appWidgetId, views);
  }
 /** {@inheritDoc} */
 public boolean onItemLongClick(
     final AdapterView<?> parent, final View view, final int position, final long id) {
   final Conversation c =
       Conversation.getConversation(this, (Cursor) parent.getItemAtPosition(position), true);
   final Uri target = c.getUri();
   Builder builder = new Builder(this);
   String[] items = this.longItemClickDialog;
   final Contact contact = c.getContact();
   final String a = contact.getNumber();
   Log.d(TAG, "p: " + a);
   final String n = contact.getName();
   if (TextUtils.isEmpty(n)) {
     builder.setTitle(a);
     items = items.clone();
     items[WHICH_VIEW_CONTACT] = this.getString(R.string.add_contact_);
   } else {
     builder.setTitle(n);
   }
   final SpamDB db = new SpamDB(this.getApplicationContext());
   db.open();
   if (db.isInDB(a)) {
     items = items.clone();
     items[WHICH_MARK_SPAM] = this.getString(R.string.dont_filter_spam_);
   }
   db.close();
   builder.setItems(
       items,
       new DialogInterface.OnClickListener() {
         @Override
         public void onClick(final DialogInterface dialog, final int which) {
           Intent i = null;
           switch (which) {
             case WHICH_ANSWER:
               ConversationListActivity.this.startActivity(
                   getComposeIntent(ConversationListActivity.this, a));
               break;
             case WHICH_CALL:
               i = new Intent(Intent.ACTION_VIEW, Uri.parse("tel:" + a));
               ConversationListActivity.this.startActivity(i);
               break;
             case WHICH_VIEW_CONTACT:
               if (n == null) {
                 i = ContactsWrapper.getInstance().getInsertPickIntent(a);
                 Conversation.flushCache();
               } else {
                 final Uri uri = c.getContact().getUri();
                 i = new Intent(Intent.ACTION_VIEW, uri);
               }
               ConversationListActivity.this.startActivity(i);
               break;
             case WHICH_VIEW:
               i =
                   new Intent(
                       ConversationListActivity.this, // .
                       MessageListActivity.class);
               i.setData(target);
               ConversationListActivity.this.startActivity(i);
               break;
             case WHICH_DELETE:
               ConversationListActivity.deleteMessages(
                   ConversationListActivity.this,
                   target,
                   R.string.delete_thread_,
                   R.string.delete_thread_question,
                   null);
               break;
             case WHICH_MARK_SPAM:
               ConversationListActivity.addToOrRemoveFromSpamlist(
                   ConversationListActivity.this, c.getContact().getNumber());
               break;
             default:
               break;
           }
         }
       });
   builder.create().show();
   return true;
 }