diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..b9412ba --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/icon.png b/res/drawable/icon.png new file mode 100644 index 0000000..67d5d7b Binary files /dev/null and b/res/drawable/icon.png differ diff --git a/res/layout/about.xml b/res/layout/about.xml new file mode 100644 index 0000000..dbce45d --- /dev/null +++ b/res/layout/about.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/res/layout/main.xml b/res/layout/main.xml new file mode 100644 index 0000000..a31ec84 --- /dev/null +++ b/res/layout/main.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/res/values/arrays.xml b/res/values/arrays.xml new file mode 100644 index 0000000..4ea0b65 --- /dev/null +++ b/res/values/arrays.xml @@ -0,0 +1,77 @@ + + + + Search + Web Snippets + Local Search + Local Movies + Local Weather + Airports + Area Codes + Calculator + Currency Conversion + Directions + Flights + Glossary + METAR + Maps + Movies + Products + Q&A + Sports + Stocks + Translation + Weather + Zip Codes + + + + %s + web %s + %s %l + movies %%s %l + weather %l + %s airport + area code %s + %s + %s + directions %s + flight %s + define %s + metar %s + map %s + movies %s + price %s + %s + score %s + stock %s + translate %s + weather %s + zip code %s + + + + blockbuster seattle wa + search terms, e.g.: t-mobile g1 + business listing, sushi, pizza, etc. + No query or current movie name + No query required + airport code, e.g.: sfo + area code, e.g.: 650 + 1 us pint in liters, 5+2/2, etc. + 8 usd in yen + pasadena ca to 94043 + aa 2111, ua 14, etc. + word to define, e.g.: zenith + ICAO airport code, e.g.: khio + 5th avenue new york + current movie name boston, ma + ipod 40gb, UPC/ISBN, etc. + india population + NBA/NHL/MLB/NFL/NCAA team + ticker symbol, e.g.: goog + hello in french + new york, ny + 90210 + + diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100644 index 0000000..9156f9d --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,27 @@ + + + Hello World, GoogSMS + GoogSMS + Query: + Type: + Send via SMS + Your message was sent. + Please enter a query... + Please set your location... + 466453 + © 2008 Erik C. Thauvin\nAll Rights Reserved\n\nerik@thauvin.net\n\nhttp://mobile.thauvin.net + About + Preferences + OK + Preferences + Set Your Location... + Location + Your current city and state or zip. + e.g.: san francisco ca or 94123 + Set SMS Number... + Google SMS + The short code or number of the Google SMS service. + e.g.: 466453 + prefs_sms + prefs_loc + diff --git a/res/xml/prefs.xml b/res/xml/prefs.xml new file mode 100644 index 0000000..c422559 --- /dev/null +++ b/res/xml/prefs.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/screenshots/1.psd b/screenshots/1.psd new file mode 100644 index 0000000..78a4f09 Binary files /dev/null and b/screenshots/1.psd differ diff --git a/screenshots/2.psd b/screenshots/2.psd new file mode 100644 index 0000000..52f6b7e Binary files /dev/null and b/screenshots/2.psd differ diff --git a/screenshots/googsms.gif b/screenshots/googsms.gif new file mode 100644 index 0000000..4e6e6f8 Binary files /dev/null and b/screenshots/googsms.gif differ diff --git a/sign.bat b/sign.bat new file mode 100644 index 0000000..6809692 --- /dev/null +++ b/sign.bat @@ -0,0 +1,10 @@ +@echo off +"%JAVA_HOME%\bin\jarsigner" -verbose -keystore "%USERPROFILE%\personal\android.keystore" "%1" android +if errorlevel 1 goto ERROR +"%JAVA_HOME%\bin\jarsigner" -verify "%1" +if errorlevel 1 goto ERROR +goto DONE +:ERROR +@pause +:DONE +@echo on \ No newline at end of file diff --git a/src/net/thauvin/erik/android/googsms/GoogSMS.java b/src/net/thauvin/erik/android/googsms/GoogSMS.java new file mode 100644 index 0000000..534ca47 --- /dev/null +++ b/src/net/thauvin/erik/android/googsms/GoogSMS.java @@ -0,0 +1,390 @@ +/* + * @(#)GoogSMS.java + * + * Copyright (c) 2008, Erik C. Thauvin (http://erik.thauvin.net/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the authors nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + * + */ +package net.thauvin.erik.android.googsms; + +import java.util.ArrayList; +import java.util.List; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; +import android.telephony.gsm.SmsManager; +import android.text.ClipboardManager; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.AutoCompleteTextView; +import android.widget.Button; +import android.widget.Spinner; +import android.widget.Toast; + +/** + * The GoogSMS class implements a simple front-end for Google SMS. + * + * @author Erik C. Thauvin + * @version $Revision$, $Date$ + * @created Nov 2, 2008 + * @since 1.0 + */ +public class GoogSMS extends Activity +{ + private static final int MAX_HISTORY_SIZE = 15; + private static final int MENU_ABOUT = 0; + private static final int MENU_PREFS = 1; + private static final String PREFS_HISTORY = "history"; + + private final List mHistory = new ArrayList(MAX_HISTORY_SIZE); + + private String mLocation; + private String mSmsNumber; + + /** + * Adds to the history. + * + * @param entry The entry to add. + */ + private void addHistory(String entry) + { + if (!mHistory.contains(entry)) + { + if (mHistory.size() >= MAX_HISTORY_SIZE) + { + mHistory.remove(0); + } + + mHistory.add(entry); + + final SharedPreferences settings = getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE); + final SharedPreferences.Editor editor = settings.edit(); + editor.putString(PREFS_HISTORY, TextUtils.join(",", mHistory)); + editor.commit(); + } + } + + /** + * Returns the location. + * + * @return the location + */ + private String getLocation() + { + return mLocation; + } + + /** + * Returns the SMS service number. + * + * @return the SMS number + */ + private String getSmsNumber() + { + return mSmsNumber; + } + + /** + * Returns the current version number. + * + * @return The current version number or empty. + */ + private String getVersionNumber() + { + try + { + return getPackageManager().getPackageInfo(getPackageName(), 0).versionName; + } + catch (final NameNotFoundException e) + { + return ""; + } + } + + /** + * Returns whether the location has been set. + * + * @return true if set, false otherwise. + */ + private boolean hasLocation() + { + return !TextUtils.isEmpty(mLocation); + } + + /** + * Initializes the various controls. + */ + private void init() + { + loadPrefs(); + + final AutoCompleteTextView queryFld = (AutoCompleteTextView) findViewById(R.id.main_query_fld); + final Spinner typeSpin = (Spinner) findViewById(R.id.main_type_spin); + final Button sendBtn = (Button) findViewById(R.id.main_send_btn); + + final SharedPreferences settings = getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE); + setHistory(settings.getString(PREFS_HISTORY, "")); + setAutoComplete(queryFld); + + final ArrayAdapter typeAdapter = ArrayAdapter.createFromResource(this, R.array.main_type_array, + android.R.layout.simple_spinner_item); + typeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + typeSpin.setAdapter(typeAdapter); + + final ClipboardManager clip = (ClipboardManager) getSystemService(android.content.Context.CLIPBOARD_SERVICE); + if (clip.hasText()) + { + queryFld.setText(clip.getText()); + } + + final String[] hints = getResources().getStringArray(R.array.main_hint_array); + final String[] cmds = getResources().getStringArray(R.array.main_cmd_array); + + typeSpin.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() + { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) + { + queryFld.setHint(hints[position]); + } + + @Override + public void onNothingSelected(AdapterView parent) + { + ; // do nothing + } + }); + + sendBtn.setOnClickListener(new Button.OnClickListener() + { + public void onClick(View view) + { + final String localToken = "%l"; + final String searchToken = "%s"; + final String optSearchToken = "%%s"; + + final String cmd = cmds[typeSpin.getSelectedItemPosition()]; + final String query = queryFld.getText().toString(); + + final boolean isLocal = (cmd.indexOf(localToken) != -1); + final boolean isQuery = (cmd.indexOf(searchToken) != -1); + final boolean isOptQuery = (cmd.indexOf(optSearchToken) != -1); + + if ((!isOptQuery) && TextUtils.isEmpty(query) && isQuery) + { + Toast.makeText(GoogSMS.this, R.string.main_query_err_txt, Toast.LENGTH_SHORT).show(); + } + else if (!hasLocation() && isLocal) + { + Toast.makeText(GoogSMS.this, R.string.main_location_err_txt, Toast.LENGTH_SHORT).show(); + launchPrefs(); + } + else + { + final String s1; + + if (isLocal) + { + s1 = cmd.replace(localToken, getLocation()); + } + else + { + s1 = cmd; + } + + final String s2; + + if (isOptQuery) + { + if (TextUtils.isEmpty(query)) + { + s2 = s1.replace(' ' + optSearchToken, ""); + } + else + { + s2 = s1.replace(optSearchToken, query); + } + } + else if (isQuery) + { + s2 = s1.replace(searchToken, query); + } + else + { + s2 = s1; + } + + final SmsManager sms = SmsManager.getDefault(); + sms.sendTextMessage(getSmsNumber(), null, s2, null, null); + + addHistory(query); + setAutoComplete(queryFld); + + Toast.makeText(GoogSMS.this, R.string.main_sms_sent_txt, Toast.LENGTH_SHORT).show(); + + Log.v("SMS SENT: ", s2); + } + } + + }); + } + + /** + * Launches the preferences screen. + */ + private void launchPrefs() + { + startActivity(new Intent(this, PrefsScreen.class)); + } + + /** + * Loads the preferences. + * + * @param isFirst The first call flag. + */ + public void loadPrefs() + { + final SharedPreferences settings = getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE); + setLocation(settings.getString(getString(R.string.prefs_key_loc), "")); + setSmsNumber(settings.getString(getString(R.string.prefs_key_sms), getString(R.string.default_google_sms))); + } + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + init(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) + { + menu.add(0, MENU_ABOUT, 0, R.string.about_menu_txt).setIcon(android.R.drawable.ic_menu_info_details); + menu.add(0, MENU_PREFS, 0, R.string.prefs_menu_txt).setIcon(android.R.drawable.ic_menu_preferences); + return super.onCreateOptionsMenu(menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) + { + if (item.getItemId() == MENU_ABOUT) + { + final LayoutInflater factory = LayoutInflater.from(this); + final View aboutView = factory.inflate(R.layout.about, null); + + new AlertDialog.Builder(this).setView(aboutView).setIcon(android.R.drawable.ic_dialog_info).setTitle( + getString(R.string.app_name) + ' ' + getVersionNumber()).setPositiveButton(R.string.alert_dialog_ok, + new DialogInterface.OnClickListener() + { + public void onClick(DialogInterface dialog, int whichButton) + { + // do nothing + } + }).show(); + + return true; + } + else if (item.getItemId() == MENU_PREFS) + { + launchPrefs(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onResume() + { + super.onResume(); + + loadPrefs(); + } + + /** + * Sets the auto-complete values of the specified field. + * + * @param field The field to the auto-complete for. + */ + private void setAutoComplete(AutoCompleteTextView field) + { + final ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_dropdown_item_1line, mHistory); + field.setAdapter(adapter); + } + + /** + * Sets the history. + * + * @param history The comma-delimited history string. + */ + private void setHistory(String history) + { + final String[] entries = TextUtils.split(history, ","); + for (final String entry : entries) + { + mHistory.add(entry); + } + } + + /** + * Sets the location. + * + * @param location the location to set + */ + private void setLocation(String location) + { + mLocation = location; + } + + /** + * Sets the SMS service number. + * + * @param smsNumber the SMS number to set + */ + private void setSmsNumber(String smsNumber) + { + mSmsNumber = smsNumber; + } +} \ No newline at end of file diff --git a/src/net/thauvin/erik/android/googsms/PrefsScreen.java b/src/net/thauvin/erik/android/googsms/PrefsScreen.java new file mode 100644 index 0000000..7b4618f --- /dev/null +++ b/src/net/thauvin/erik/android/googsms/PrefsScreen.java @@ -0,0 +1,65 @@ +/* + * @(#)PrefsScreen.java + * + * Copyright (c) 2008, Erik C. Thauvin (http://erik.thauvin.net/) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the authors nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + * + */ +package net.thauvin.erik.android.googsms; + +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.widget.TextView; + +/** + * The GoogSMS class implements a the preferences screen for Google SMS. + * + * @author Erik C. Thauvin + * @version $Revision$, $Date$ + * @created Nov 2, 2008 + * @since 1.0 + */ +public class PrefsScreen extends PreferenceActivity +{ + public TextView mLocationHint; + + /** + * Called when the activity is first created. + */ + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + getPreferenceManager().setSharedPreferencesName(getString(R.string.app_name)); + addPreferencesFromResource(R.xml.prefs); + } +} diff --git a/src/net/thauvin/erik/android/googsms/R.java b/src/net/thauvin/erik/android/googsms/R.java new file mode 100644 index 0000000..7d16384 --- /dev/null +++ b/src/net/thauvin/erik/android/googsms/R.java @@ -0,0 +1,62 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package net.thauvin.erik.android.googsms; + +public final class R { + public static final class array { + public static final int main_cmd_array=0x7f050001; + public static final int main_hint_array=0x7f050002; + public static final int main_type_array=0x7f050000; + } + public static final class attr { + } + public static final class drawable { + public static final int icon=0x7f020000; + } + public static final class id { + public static final int about_text_fld=0x7f070000; + public static final int main_query_fld=0x7f070002; + public static final int main_query_lbl=0x7f070001; + public static final int main_send_btn=0x7f070005; + public static final int main_type_lbl=0x7f070003; + public static final int main_type_spin=0x7f070004; + } + public static final class layout { + public static final int about=0x7f030000; + public static final int main=0x7f030001; + } + public static final class string { + public static final int about_menu_txt=0x7f06000a; + public static final int about_txt=0x7f060009; + public static final int alert_dialog_ok=0x7f06000c; + public static final int app_name=0x7f060001; + public static final int default_google_sms=0x7f060008; + public static final int hello=0x7f060000; + public static final int main_location_err_txt=0x7f060007; + public static final int main_query_err_txt=0x7f060006; + public static final int main_query_lbl_txt=0x7f060002; + public static final int main_send_btn_txt=0x7f060004; + public static final int main_sms_sent_txt=0x7f060005; + public static final int main_type_lbl_txt=0x7f060003; + public static final int prefs_dialog_title=0x7f06000d; + public static final int prefs_key_loc=0x7f060017; + public static final int prefs_key_sms=0x7f060016; + public static final int prefs_location_dialog_title=0x7f06000e; + public static final int prefs_location_hint=0x7f060011; + public static final int prefs_location_summary=0x7f060010; + public static final int prefs_location_title=0x7f06000f; + public static final int prefs_menu_txt=0x7f06000b; + public static final int prefs_sms_dialog_title=0x7f060012; + public static final int prefs_sms_hint=0x7f060015; + public static final int prefs_sms_summary=0x7f060014; + public static final int prefs_sms_title=0x7f060013; + } + public static final class xml { + public static final int prefs=0x7f040000; + } +}