package text.androidad3; import java.util.ArrayList; import org.baole.core.ContactEntry; import org.baole.service.Service; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.database.Cursor; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.preference.PreferenceManager; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.text.method.ScrollingMovementMethod; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.CursorAdapter; import android.widget.EditText; import android.widget.Filterable; import android.widget.ProgressBar; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; public class SMSBomber extends Activity implements OnClickListener { private static final int DIALOG_CHANGLOGS = 1; private static final String PREFS_LAST_RUN = "lastrun"; private static final String MESSAGE = "message"; private static final String CONTACT = "contact"; private static final String COUNTER = "%c%"; private static final String NUMBER = "NUMBER"; private static final String NAME = "NAME"; public int recent_numberItems = 3; private Button btnSend; private Button btnCancel; private Button btnClear; private ProgressBar progressSend; private ArrayList contacts; private String message; private EditText txtMessage; private EditText txtMessageCount; private Spinner spdInterval; private TextView txtInfo; private TextView txtSelectedContact; private boolean isCancel = false; Service service; private boolean deliveryReport; private boolean isSaveSMS; private boolean isSplit; @Override protected void onCreate(Bundle inState) { super.onCreate(inState); setContentView(R.layout.compose); btnSend = (Button) findViewById(R.id.btnSend); btnSend.setOnClickListener(this); btnClear = (Button) findViewById(R.id.btnClear); btnClear.setOnClickListener(this); btnCancel = (Button) findViewById(R.id.btnCancel); btnCancel.setOnClickListener(this); btnCancel.setEnabled(false); progressSend = (ProgressBar) findViewById(R.id.progressSend); progressSend.setVisibility(View.GONE); txtMessage = (EditText) findViewById(R.id.txtMessage); txtMessageCount = (EditText) findViewById(R.id.txtMsgCount); spdInterval = (Spinner) findViewById(R.id.spnInterval); txtInfo = (TextView) findViewById(R.id.txtInfo); txtSelectedContact = (TextView) findViewById(R.id.txtSelectedContact); txtSelectedContact.setMovementMethod(new ScrollingMovementMethod()); if (inState != null) { txtMessage.setText(inState.getString(MESSAGE)); contacts = inState.getParcelableArrayList(CONTACT); } if (contacts == null) { contacts = new ArrayList(); } String name = getIntent().getStringExtra(NAME); String number = getIntent().getStringExtra(NUMBER); if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(number)) { contacts.add(new ContactEntry(name, number)); SharedPreferences settings = this .getSharedPreferences(SMSBOMBER, 0); Editor editor = settings.edit(); int msgCount = getIntent().getIntExtra(MESSAGE_COUNT, 10); editor.putString(MESSAGE_COUNT, "" + msgCount); editor.commit(); } adapter = new ContactListAdapter(this, ContactHelper.getInstance(this) .getContactCursor()); txtMessage.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { setMessageCharCount(); } }); loadPreference(); showContacts(); SharedPreferences preferences = PreferenceManager .getDefaultSharedPreferences(this); deliveryReport = preferences.getBoolean("delivery_report", true); isSaveSMS = preferences.getBoolean("save_sent_sms", true); isSplit = preferences.getBoolean("split_long_sms", true); StringBuffer buff = new StringBuffer(); buff.append("Split long SMS (> 160 chars): " + (isSplit ? "ON" : "OFF") + "\n"); buff.append("Save sent SMS to Inbox: " + (isSaveSMS ? "ON" : "OFF") + "\n"); buff.append("Delivery report: " + (deliveryReport ? "ON" : "OFF")); addReport(buff.toString()); final String v0 = preferences.getString(PREFS_LAST_RUN, ""); final String v1 = this.getString(R.string.app_version); if (!v0.equals(v1)) { SharedPreferences.Editor editor = preferences.edit(); editor.putString(PREFS_LAST_RUN, v1); editor.commit(); this.showDialog(DIALOG_CHANGLOGS); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putSerializable(MESSAGE, txtMessage.getText().toString()); outState.putParcelableArrayList(CONTACT, contacts); this.updatePreference(); } @Override protected void onPause() { super.onPause(); updatePreference(); } @Override protected void onResume() { super.onResume(); loadPreference(); } @Override protected Dialog onCreateDialog(int id) { switch (id) { case DIALOG_CHANGLOGS: return DialogUtil.createChangLogDialog(this); default: return null; } } protected void setMessageCharCount() { btnSend.setText(getString(R.string.send_prog, txtMessage.getText() .length())); } ContactListAdapter adapter; ContactEntry ceContact = null; private int delay; private int messageCount; public void onClick(View v) { if (btnSend.equals(v)) { send(); } else if (btnCancel.equals(v)) { isCancel = true; } else if (btnClear.equals(v)) { new AlertDialog.Builder(this).setIcon( android.R.drawable.ic_dialog_alert).setTitle( R.string.confirmation).setMessage( R.string.contact_remove_message).setPositiveButton( R.string.all, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { contacts.clear(); showContacts(); } }).setNeutralButton(R.string.last, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { int size = contacts.size(); if (size > 0) { contacts.remove(size - 1); showContacts(); } } }).setNegativeButton(R.string.cancel, null).show(); } } private void send() { message = txtMessage.getText().toString(); if (TextUtils.isEmpty(message)) { Toast.makeText(getApplicationContext(), R.string.enter_message, Toast.LENGTH_LONG).show(); return; } if (contacts.size() <= 0) { Toast.makeText(getApplicationContext(), R.string.select_contact, Toast.LENGTH_LONG).show(); return; } String msgCount = txtMessageCount.getText().toString(); try { messageCount = Integer.parseInt(msgCount); } catch (Exception e) { messageCount = 0; } if (messageCount <= 0) { Toast.makeText(getApplicationContext(), R.string.incorrect_message_count, Toast.LENGTH_LONG).show(); return; } InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(txtMessage.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); new SendTask().execute(); } @Override protected void onDestroy() { if (sentCount < messageCount && !isCancel) { SharedPreferences.Editor settingsEditor = getSharedPreferences( SMSBOMBER, 0).edit(); settingsEditor.putInt(FORCE_CLOSE_MAX, sentCount); settingsEditor.commit(); } super.onDestroy(); } private static String SMSBOMBER = "sms_bomber"; private static String INTERVAL = "interval"; private static String MESSAGE_COUNT = "message_count"; private static String FORCE_CLOSE_MAX = "force_close_max"; private void loadPreference() { SharedPreferences settings = this.getSharedPreferences(SMSBOMBER, 0); spdInterval.setSelection(settings.getInt(INTERVAL, 0)); int forceClose = settings.getInt(FORCE_CLOSE_MAX, 1000); int msgCount = Integer .parseInt(settings.getString(MESSAGE_COUNT, "10")); if (forceClose < msgCount) { addReport(getString(R.string.warning_force_close, forceClose)); msgCount = forceClose; } txtMessageCount.setText("" + msgCount); } private void updatePreference() { int intervalIndex = spdInterval.getSelectedItemPosition(); if (intervalIndex == Spinner.INVALID_POSITION) { intervalIndex = 0; } int[] intervalValues = getResources().getIntArray( R.array.interval_values); delay = intervalValues[intervalIndex]; SharedPreferences.Editor settingsEditor = getSharedPreferences( SMSBOMBER, 0).edit(); settingsEditor.putInt(INTERVAL, intervalIndex); settingsEditor.putString(MESSAGE_COUNT, "" + messageCount); settingsEditor.commit(); } // stats int sentOKCount[]; int sentFailedCount[]; public int sentCount; private void showContacts() { int size = contacts.size(); StringBuffer buff = new StringBuffer(getString(R.string.to, size)); for (int i = 0; i < size; i++) { buff.append(contacts.get(i).name).append( "(" + contacts.get(i).number + "), "); } txtSelectedContact.setText(buff.toString()); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main_menu, menu); return super.onCreateOptionsMenu(menu); } public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_blacklist: onMarketLaunch("org.baole.app.blacklist"); break; case R.id.menu_groupsms: onMarketLaunch("org.baole.app.groupsmsad2"); break; case R.id.menu_sms_limitremoval: onMarketLaunch("org.baole.smslimitremoval"); break; case R.id.menu_go_pro: openUrl("http://code.google.com/p/sms-bomber/"); break; case R.id.menu_anti_sms_bomber: onMarketLaunch("org.baole.antibomber"); break; case R.id.menu_counter: txtMessage.getEditableText().insert(txtMessage.getSelectionStart(), COUNTER); break; case R.id.menu_setting: startActivity(new Intent(this, Preferences.class)); break; case R.id.menu_help: showDialog(DIALOG_CHANGLOGS); break; } return true; } private void openUrl(String url) { Intent donate = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(donate); } private void onMarketLaunch(String url) { Intent donate = new Intent(Intent.ACTION_VIEW, Uri.parse(String.format( "market://details?id=%s", url))); startActivity(donate); } private class SendTask extends AsyncTask { @Override protected void onPreExecute() { final ProgressBar progress = progressSend; SharedPreferences settings = PreferenceManager .getDefaultSharedPreferences(SMSBomber.this); deliveryReport = settings.getBoolean("delivery_report", true); isSaveSMS = settings.getBoolean("save_sent_sms", true); isSplit = settings.getBoolean("split_long_sms", true); int size = contacts.size(); sentFailedCount = new int[size]; sentOKCount = new int[size]; sentCount = 0; isCancel = false; updatePreference(); // TODO service = getInstance(SMSBomber.this); service.setDeliveryReport(deliveryReport); service.setSplitLongSMS(isSplit); int status = service.init(); if (status == Service.STATUS_LOGGIN_FAILED) { String info = service.getReport(); txtInfo.setText(info); return; } progress.setVisibility(View.VISIBLE); progress.setMax(messageCount); progress.setProgress(0); btnSend.setEnabled(false); btnCancel.setEnabled(true); txtInfo.setText(""); } @Override protected Void doInBackground(Void... params) { boolean isContainCounter = message.contains(COUNTER); int size = contacts.size(); for (sentCount = 1; sentCount <= messageCount; sentCount++) { for (int i = 0; i < size; i++) { String msg = message; if (isContainCounter) msg = message.replaceAll(COUNTER, "" + sentCount); service.send(contacts.get(i).number, msg); try { Thread.sleep((delay == 1) ? 500 : delay * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } } return null; } } ContentValues values = new ContentValues(); private void addReport(String s) { txtInfo.setText(s + "\n" + txtInfo.getText()); } private void saveMessage(ContentResolver cr, ContactEntry ce, long date, int type, String message) { values.put(ADDRESS, ce.number); values.put(DATE, date); values.put(READ, 1); values.put(STATUS, -1); values.put(SMS_TYPE, type); values.put(BODY, message); // Uri inserted = cr.insert(Uri.parse("content://sms"), values); } public static class ContactListAdapter extends CursorAdapter implements Filterable { Activity ctx; public ContactListAdapter(Activity context, Cursor c) { super(context, c); ctx = context; } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { final LayoutInflater inflater = LayoutInflater.from(context); final TextView view = (TextView) inflater.inflate( android.R.layout.simple_dropdown_item_1line, parent, false); view.setText(cursor.getString(5) + "(" + cursor.getString(3) + ")"); return view; } @Override public void bindView(View view, Context context, Cursor cursor) { ((TextView) view).setText(cursor.getString(5) + "(" + cursor.getString(3) + ")"); } @Override public String convertToString(Cursor cursor) { return cursor.getString(5); } @Override public Cursor runQueryOnBackgroundThread(CharSequence constraint) { if (getFilterQueryProvider() != null) { return getFilterQueryProvider().runQuery(constraint); } return ContactHelper.getInstance(ctx).queryFilter(constraint); } // private ContentResolver mContent; } public static final String ADDRESS = "address"; public static final String PERSON = "person"; public static final String DATE = "date"; public static final String READ = "read"; public static final String STATUS = "status"; public static final String SMS_TYPE = "type"; public static final String BODY = "body"; public static final int TYPE_INBOX = 1; public static final int TYPE_SENT = 2; public static final int TYPE_DRAFT = 3; public static final int TYPE_OUTBOX = 4; private static Service sInstance; public static Service getInstance(Context ctx) { // if(true) return new MockService(); if (sInstance == null) { String className; int sdkVersion = Integer.parseInt(Build.VERSION.SDK); // Cupcake // style if (sdkVersion < Build.VERSION_CODES.DONUT) { className = "org.baole.service.SMSService34"; } else { className = "org.baole.service.SMSService"; } /* * Find the required class by name and instantiate it. */ try { Class clazz = Class.forName(className) .asSubclass(Service.class); sInstance = clazz.newInstance(); sInstance.setContext(ctx); } catch (Exception e) { Log.e("SMSWraper", "" + e.getMessage()); e.printStackTrace(); } } return sInstance; } }