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<ContactEntry> 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<ContactEntry>();
}
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<Void, Integer, Void> {
@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<? extends Service> 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;
}
}