commit c44c865fcad3bfeb11f66172058d16bc3dfb881d Author: Nir Yariv Date: Sun Oct 3 20:11:48 2010 -0400 init under new name diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..0af7a82 --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..4274f51 --- /dev/null +++ b/README @@ -0,0 +1,5 @@ +KalSMS is an simple Android SMS gateway application. + +Info & setup here: http://wiki.github.com/niryariv/kalsms/ + +Please contact niryariv@gmail.com with any questions or feedback. \ No newline at end of file diff --git a/default.properties b/default.properties new file mode 100644 index 0000000..9d6f70d --- /dev/null +++ b/default.properties @@ -0,0 +1,13 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-4 +# Indicates whether an apk should be generated for each density. +split.density=false diff --git a/res/drawable-hdpi/icon.png b/res/drawable-hdpi/icon.png new file mode 100644 index 0000000..8074c4c Binary files /dev/null and b/res/drawable-hdpi/icon.png differ diff --git a/res/drawable-ldpi/icon.png b/res/drawable-ldpi/icon.png new file mode 100644 index 0000000..1095584 Binary files /dev/null and b/res/drawable-ldpi/icon.png differ diff --git a/res/drawable-mdpi/icon.png b/res/drawable-mdpi/icon.png new file mode 100644 index 0000000..a07c69f Binary files /dev/null and b/res/drawable-mdpi/icon.png differ diff --git a/res/layout/main.xml b/res/layout/main.xml new file mode 100644 index 0000000..22272f0 --- /dev/null +++ b/res/layout/main.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100644 index 0000000..a734339 --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,5 @@ + + + SMS Gateway Running.\n + KalSMS + diff --git a/res/xml/prefs.xml b/res/xml/prefs.xml new file mode 100644 index 0000000..2692eac --- /dev/null +++ b/res/xml/prefs.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/src/kalsms/niryariv/itp/Main.java b/src/kalsms/niryariv/itp/Main.java new file mode 100644 index 0000000..3f5328f --- /dev/null +++ b/src/kalsms/niryariv/itp/Main.java @@ -0,0 +1,86 @@ +package kalsms.niryariv.itp; + +import kalsms.niryariv.itp.R; +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceActivity; +import android.preference.Preference; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.text.Html; +import android.util.Log; +import android.view.Menu; +import android.widget.TextView; + +public class Main extends Activity { + +// public static final String PREFS_NAME = "KalPrefsFile"; + + public String identifier = ""; + public String targetUrl = ""; + + + public void onResume() { + Log.d("KALSMS", "RESUME"); + super.onResume(); + + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this); + + this.identifier = settings.getString("pref_identifier", ""); + this.targetUrl = settings.getString("pref_target_url", ""); + + Log.d("KALSMS", "onResume ident:" + this.identifier +"\ntarget:" + this.targetUrl); + + String infoText = new String(); + + infoText = "All SMS messages"; + + if (this.identifier.trim() != "") { + infoText += " starting with " + this.identifier + ""; + } + + infoText += " are now sent to " + this.targetUrl +" in the following format:"; + infoText += "

GET " + this.targetUrl + "?sender=<phone#>&msg=<message>

"; + infoText += "If the response body contains text, it will SMSed back to the sender."; + + infoText += "

Press Menu to set SMS identifier or target URL."; + + infoText += "


Questions/feedback: niryariv@gmail.com"; + + TextView info = (TextView) this.findViewById(R.id.info); + info.setText(Html.fromHtml(infoText)); + + } + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + PreferenceManager.setDefaultValues(this, R.xml.prefs, false); + + Log.d("KALSMS", "STARTED"); + } + + + // first time the Menu key is pressed + public boolean onCreateOptionsMenu(Menu menu) { + startActivity(new Intent(this, Prefs.class)); + return(true); + } + + // any other time the Menu key is pressed + public boolean onPrepareOptionsMenu(Menu menu) { + startActivity(new Intent(this, Prefs.class)); + return(true); + } + + + @Override + protected void onStop(){ + // dont do much with this, atm.. + super.onStop(); + } + +} diff --git a/src/kalsms/niryariv/itp/Prefs.java b/src/kalsms/niryariv/itp/Prefs.java new file mode 100644 index 0000000..10b3fa1 --- /dev/null +++ b/src/kalsms/niryariv/itp/Prefs.java @@ -0,0 +1,31 @@ +package kalsms.niryariv.itp; + +import kalsms.niryariv.itp.R; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.EditTextPreference; +import android.preference.Preference; +import android.preference.PreferenceActivity; +import android.util.Log; + + +public class Prefs extends PreferenceActivity { + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + addPreferencesFromResource(R.xml.prefs); + } + + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + Preference pref = findPreference(key); + + if (pref instanceof EditTextPreference) { + EditTextPreference textPref = (EditTextPreference) pref; + pref.setSummary(textPref.getSummary()); + Log.d("KALSMS", "textPref.getSummary(): " + textPref.getSummary()); + } + } +} + diff --git a/src/kalsms/niryariv/itp/SMSReceiver.java b/src/kalsms/niryariv/itp/SMSReceiver.java new file mode 100644 index 0000000..207774c --- /dev/null +++ b/src/kalsms/niryariv/itp/SMSReceiver.java @@ -0,0 +1,225 @@ +package kalsms.niryariv.itp; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.database.Cursor; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.telephony.SmsManager; +import android.telephony.SmsMessage; +import android.util.Log; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.utils.URLEncodedUtils; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +public class SMSReceiver extends BroadcastReceiver { + + + @Override + // source: http://www.devx.com/wireless/Article/39495/1954 + public void onReceive(Context context, Intent intent) { + if (!intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) { + return; + } + + // get settings + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context); + + String identifier = settings.getString("pref_identifier", ""); + String targetUrl = settings.getString("pref_target_url", ""); + + SmsMessage msgs[] = getMessagesFromIntent(intent); + + for (int i = 0; i < msgs.length; i++) { + SmsMessage mesg = msgs[i]; + String message = mesg.getDisplayMessageBody(); + String sender = mesg.getDisplayOriginatingAddress(); + + if (message != null && message.length() > 0 + && (message.toLowerCase().startsWith(identifier) || identifier.trim() == "")) { + + Log.d("KALSMS", "MSG RCVD:\"" + message + "\" from: " + sender); + + // send the message to the URL + String resp = openURL(sender, message, targetUrl).toString(); + + Log.d("KALSMS", "RESP:\"" + resp); + + // SMS back the response + if (resp.trim().length() > 0) { + ArrayList> items = parseXML(resp); + + SmsManager smgr = SmsManager.getDefault(); + + for (int j = 0; j < items.size(); j++) { + String sendTo = items.get(j).get(0); + if (sendTo.toLowerCase() == "sender") sendTo = sender; + String sendMsg = items.get(j).get(1); + + try { + Log.d("KALSMS", "SEND MSG:\"" + sendMsg + "\" TO: " + sendTo); + smgr.sendTextMessage(sendTo, null, sendMsg, null, null); + } catch (Exception ex) { + Log.d("KALSMS", "SMS FAILED"); + } + } + } + + // delete SMS from inbox, to prevent it from filling up + DeleteSMSFromInbox(context, mesg); + + } + } + + } + + private void DeleteSMSFromInbox(Context context, SmsMessage mesg) { + Log.d("KALSMS", "try to delete SMS"); + + try { + Uri uriSms = Uri.parse("content://sms/inbox"); + + StringBuilder sb = new StringBuilder(); + sb.append("address='" + mesg.getOriginatingAddress() + "' AND "); + sb.append("body='" + mesg.getMessageBody() + "'"); + Cursor c = context.getContentResolver().query(uriSms, null, sb.toString(), null, null); + c.moveToFirst(); + int thread_id = c.getInt(1); + context.getContentResolver().delete(Uri.parse("content://sms/conversations/" + thread_id), null, null); + c.close(); + } catch (Exception ex) { + // deletions don't work most of the time since the timing of the + // receipt and saving to the inbox + // makes it difficult to match up perfectly. the SMS might not be in + // the inbox yet when this receiver triggers! + Log.d("SmsReceiver", "Error deleting sms from inbox: " + ex.getMessage()); + } + } + + + // from http://github.com/dimagi/rapidandroid + // source: http://www.devx.com/wireless/Article/39495/1954 + private SmsMessage[] getMessagesFromIntent(Intent intent) { + SmsMessage retMsgs[] = null; + Bundle bdl = intent.getExtras(); + try { + Object pdus[] = (Object[]) bdl.get("pdus"); + retMsgs = new SmsMessage[pdus.length]; + for (int n = 0; n < pdus.length; n++) { + byte[] byteData = (byte[]) pdus[n]; + retMsgs[n] = SmsMessage.createFromPdu(byteData); + } + + } catch (Exception e) { + Log.e("KALSMS", "GetMessages ERROR\n" + e); + } + return retMsgs; + } + + + public String openURL(String sender, String message, String targetUrl) { + + List qparams = new ArrayList(); + qparams.add(new BasicNameValuePair("sender", sender)); + qparams.add(new BasicNameValuePair("msg", message)); + String url = targetUrl + "?" + URLEncodedUtils.format(qparams, "UTF-8"); + + try { + HttpClient client = new DefaultHttpClient(); + HttpGet get = new HttpGet(url); + + HttpResponse responseGet = client.execute(get); + HttpEntity resEntityGet = responseGet.getEntity(); + if (resEntityGet != null) { + String resp = EntityUtils.toString(resEntityGet); + Log.e("KALSMS", "HTTP RESP" + resp); + return resp; + } + } catch (Exception e) { + Log.e("KALSMS", "HTTP REQ FAILED:" + url); + e.printStackTrace(); + } + + return ""; + } + + + public static ArrayList> parseXML(String xml) { + ArrayList> output = new ArrayList>(); + + try { + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + + Document doc = dBuilder.parse(new InputSource(new StringReader(xml))); + + NodeList rnodes = doc.getElementsByTagName("reply"); + + NodeList nodes = rnodes.item(0).getChildNodes(); + + for (int i=0; i < nodes.getLength(); i++) { + try { + List item = new ArrayList(); + + Node node = nodes.item(i); + if (node.getNodeType() != Node.ELEMENT_NODE) continue; + + Element e = (Element) node; + String nodeName = e.getNodeName(); + + if (nodeName.equalsIgnoreCase("sms")) { + if (!e.getAttribute("phone").equals("")) { + item.add(e.getAttribute("phone")); + item.add(e.getFirstChild().getNodeValue()); + output.add((ArrayList) item); + } + } else if (nodeName.equalsIgnoreCase("sms-to-sender")) { + item.add("sender"); + item.add(e.getFirstChild().getNodeValue()); + output.add((ArrayList) item); + } else { + continue; + } + } catch (Exception e){ + Log.e("KALSMS", "FAILED PARSING XML NODE# " + i ); + } + } + Log.e("KALSMS", "PARSING XML RETURNS " + output ); + return (output); + + } catch (Exception e) { + Log.e("KALSMS", "PARSING XML FAILED: " + xml ); + e.printStackTrace(); + return (output); + } + } +} diff --git a/src/kalsms/niryariv/itp/URLopen.java b/src/kalsms/niryariv/itp/URLopen.java new file mode 100644 index 0000000..4aa8c1f --- /dev/null +++ b/src/kalsms/niryariv/itp/URLopen.java @@ -0,0 +1,74 @@ +package kalsms.niryariv.itp; +//package txtgate.niryariv.itp; +// +//import java.io.BufferedInputStream; +//import java.io.InputStream; +//import java.net.URL; +//import java.net.URLConnection; +// +//import org.apache.http.util.ByteArrayBuffer; +// +//public class URLopen { +// private Thread checkUpdate = new Thread() { +// public void run() { +// try { +// URL updateURL = new URL("http://iconic.4feets.com/update"); +// URLConnection conn = updateURL.openConnection(); +// InputStream is = conn.getInputStream(); +// BufferedInputStream bis = new BufferedInputStream(is); +// ByteArrayBuffer baf = new ByteArrayBuffer(50); +// +// int current = 0; +// while((current = bis.read()) != -1){ +// baf.append((byte)current); +// } +// +// /* Convert the Bytes read to a String. */ +// final String s = new String(baf.toByteArray()); +//// mHandler.post(showUpdate); +// } catch (Exception e) { +// // +// } +// } +// }; +//} +// +////public class Iconic extends Activity { +//// private String html = ""; +//// private Handler mHandler; +//// +//// public void onCreate(Bundle savedInstanceState) { +//// super.onCreate(savedInstanceState); +//// setContentView(R.layout.main); +//// mHandler = new Handler(); +//// checkUpdate.start(); +//// } +//// +//// private Thread checkUpdate = new Thread() { +//// public void run() { +//// try { +//// URL updateURL = new URL("http://iconic.4feets.com/update"); +//// URLConnection conn = updateURL.openConnection(); +//// InputStream is = conn.getInputStream(); +//// BufferedInputStream bis = new BufferedInputStream(is); +//// ByteArrayBuffer baf = new ByteArrayBuffer(50); +//// +//// int current = 0; +//// while((current = bis.read()) != -1){ +//// baf.append((byte)current); +//// } +//// +//// /* Convert the Bytes read to a String. */ +//// html = new String(baf.toByteArray()); +//// mHandler.post(showUpdate); +//// } catch (Exception e) { +//// } +//// } +//// }; +//// +//// private Runnable showUpdate = new Runnable(){ +//// public void run(){ +//// Toast.makeText(Iconic.this, "HTML Code: " + html, Toast.LENGTH_SHORT).show(); +//// } +//// }; +////} \ No newline at end of file