mirror of
https://github.com/cwinfo/envayasms.git
synced 2024-12-04 12:35:32 +00:00
use POST in http requests; use different url for outgoing sms; poll for outgoing sms more frequently; notify server when sms messages are sent
This commit is contained in:
parent
448eafecd8
commit
9473ab1610
28
AndroidManifest.xml
Normal file → Executable file
28
AndroidManifest.xml
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="kalsms.niryariv.itp"
|
package="org.envaya.kalsms"
|
||||||
android:versionCode="1"
|
android:versionCode="1"
|
||||||
android:versionName="1.0">
|
android:versionName="1.0">
|
||||||
|
|
||||||
@ -19,18 +19,24 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<receiver android:name=".SMSReceiver">
|
<receiver android:name=".IncomingMessageForwarder">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
|
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name=".SMSSender">
|
<receiver android:name=".OutgoingMessagePoller">
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<activity android:name=".Prefs"
|
<receiver android:name=".MessageStatusNotifier">
|
||||||
android:label="@string/app_name">
|
<intent-filter>
|
||||||
</activity>
|
<action android:name="org.envaya.kalsms.SEND_STATUS" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<activity android:name=".Prefs"
|
||||||
|
android:label="@string/app_name">
|
||||||
|
</activity>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
17
build.properties
Executable file
17
build.properties
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
# This file is used to override default values used by the Ant build system.
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems, as it is
|
||||||
|
# integral to the build system of your project.
|
||||||
|
|
||||||
|
# This file is only used by the Ant script.
|
||||||
|
|
||||||
|
# You can use this to override default values such as
|
||||||
|
# 'source.dir' for the location of your java source folder and
|
||||||
|
# 'out.dir' for the location of your output folder.
|
||||||
|
|
||||||
|
# You can also use it define how the release builds are signed by declaring
|
||||||
|
# the following properties:
|
||||||
|
# 'key.store' for the location of your keystore and
|
||||||
|
# 'key.alias' for the name of the key to use.
|
||||||
|
# The password will be asked during the build when you use the 'release' target.
|
||||||
|
|
79
build.xml
Executable file
79
build.xml
Executable file
@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project name="KalSMS" default="help">
|
||||||
|
|
||||||
|
<!-- The local.properties file is created and updated by the 'android'
|
||||||
|
tool.
|
||||||
|
It contains the path to the SDK. It should *NOT* be checked into
|
||||||
|
Version Control Systems. -->
|
||||||
|
<property file="local.properties" />
|
||||||
|
|
||||||
|
<!-- The build.properties file can be created by you and is never touched
|
||||||
|
by the 'android' tool. This is the place to change some of the
|
||||||
|
default property values used by the Ant rules.
|
||||||
|
Here are some properties you may want to change/update:
|
||||||
|
|
||||||
|
source.dir
|
||||||
|
The name of the source directory. Default is 'src'.
|
||||||
|
out.dir
|
||||||
|
The name of the output directory. Default is 'bin'.
|
||||||
|
|
||||||
|
Properties related to the SDK location or the project target should
|
||||||
|
be updated using the 'android' tool with the 'update' action.
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<property file="build.properties" />
|
||||||
|
|
||||||
|
<!-- The default.properties file is created and updated by the 'android'
|
||||||
|
tool, as well as ADT.
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems. -->
|
||||||
|
<property file="default.properties" />
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Required pre-setup import -->
|
||||||
|
<import file="${sdk.dir}/tools/ant/pre_setup.xml" />
|
||||||
|
|
||||||
|
|
||||||
|
<!-- extension targets. Uncomment the ones where you want to do custom work
|
||||||
|
in between standard targets -->
|
||||||
|
<!--
|
||||||
|
<target name="-pre-build">
|
||||||
|
</target>
|
||||||
|
<target name="-pre-compile">
|
||||||
|
</target>
|
||||||
|
|
||||||
|
[This is typically used for code obfuscation.
|
||||||
|
Compiled code location: ${out.classes.absolute.dir}
|
||||||
|
If this is not done in place, override ${out.dex.input.absolute.dir}]
|
||||||
|
<target name="-post-compile">
|
||||||
|
</target>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Execute the Android Setup task that will setup some properties
|
||||||
|
specific to the target, and import the build rules files.
|
||||||
|
|
||||||
|
The rules file is imported from
|
||||||
|
<SDK>/tools/ant/
|
||||||
|
Depending on the project type it can be either:
|
||||||
|
- main_rules.xml
|
||||||
|
- lib_rules.xml
|
||||||
|
- test_rules.xml
|
||||||
|
|
||||||
|
To customize existing targets, there are two options:
|
||||||
|
- Customize only one target:
|
||||||
|
- copy/paste the target into this file, *before* the
|
||||||
|
<setup> task.
|
||||||
|
- customize it to your needs.
|
||||||
|
- Customize the whole script.
|
||||||
|
- copy/paste the content of the rules files (minus the top node)
|
||||||
|
into this file, *after* the <setup> task
|
||||||
|
- disable the import of the rules by changing the setup task
|
||||||
|
below to <setup import="false" />.
|
||||||
|
- customize to your needs.
|
||||||
|
-->
|
||||||
|
<setup />
|
||||||
|
|
||||||
|
</project>
|
10
local.properties
Executable file
10
local.properties
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must *NOT* be checked in Version Control Systems,
|
||||||
|
# as it contains information specific to your local configuration.
|
||||||
|
|
||||||
|
# location of the SDK. This is only used by Ant
|
||||||
|
# For customization when using a Version Control System, please read the
|
||||||
|
# header note.
|
||||||
|
sdk.dir=C:\\android-sdk
|
40
proguard.cfg
Executable file
40
proguard.cfg
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
-optimizationpasses 5
|
||||||
|
-dontusemixedcaseclassnames
|
||||||
|
-dontskipnonpubliclibraryclasses
|
||||||
|
-dontpreverify
|
||||||
|
-verbose
|
||||||
|
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||||
|
|
||||||
|
-keep public class * extends android.app.Activity
|
||||||
|
-keep public class * extends android.app.Application
|
||||||
|
-keep public class * extends android.app.Service
|
||||||
|
-keep public class * extends android.content.BroadcastReceiver
|
||||||
|
-keep public class * extends android.content.ContentProvider
|
||||||
|
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||||
|
-keep public class * extends android.preference.Preference
|
||||||
|
-keep public class com.android.vending.licensing.ILicensingService
|
||||||
|
|
||||||
|
-keepclasseswithmembernames class * {
|
||||||
|
native <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclasseswithmembers class * {
|
||||||
|
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers class * extends android.app.Activity {
|
||||||
|
public void *(android.view.View);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keepclassmembers enum * {
|
||||||
|
public static **[] values();
|
||||||
|
public static ** valueOf(java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
-keep class * implements android.os.Parcelable {
|
||||||
|
public static final android.os.Parcelable$Creator *;
|
||||||
|
}
|
12
res/layout/main.xml
Normal file → Executable file
12
res/layout/main.xml
Normal file → Executable file
@ -3,11 +3,11 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="fill_parent" android:background="#333333">
|
android:layout_height="fill_parent" android:background="#333333">
|
||||||
<TextView
|
<TextView
|
||||||
|
android:scrollbars="vertical"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="fill_parent"
|
||||||
android:text="@string/hello"
|
android:id="@+id/info"
|
||||||
android:textColor="#FFFFFF" android:textSize="30px" android:layout_margin="2px"/>
|
android:textColor="#FFFFFF"
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/info" android:textColor="#FFFFFF" android:layout_margin="5px"></TextView>
|
android:layout_margin="5px"></TextView>
|
||||||
<!--<Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:id="@+id/settingsButton" android:text="Edit Settings" android:layout_marginRight="50px" android:layout_marginLeft="50px"></Button>-->
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
3
res/values/strings.xml
Normal file → Executable file
3
res/values/strings.xml
Normal file → Executable file
@ -1,5 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="hello">SMS Gateway Running.\n</string>
|
<string name="app_name">KalSMS Envaya</string>
|
||||||
<string name="app_name">KalSMS</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
43
res/xml/prefs.xml
Normal file → Executable file
43
res/xml/prefs.xml
Normal file → Executable file
@ -1,26 +1,27 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen
|
<PreferenceScreen
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<EditTextPreference
|
||||||
|
android:key="server_url"
|
||||||
|
android:title="Server URL"
|
||||||
|
android:defaultValue="http://192.168.70.1:3000/"
|
||||||
|
></EditTextPreference>
|
||||||
|
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="pref_target_url"
|
android:key="phone_number"
|
||||||
android:title="Target URL"
|
android:title="Your Phone Number"
|
||||||
android:summary="URL to load when the SMS is received"
|
android:defaultValue="16507993371"
|
||||||
android:defaultValue="http://qkhack.appspot.com/kalsms_demo"
|
></EditTextPreference>
|
||||||
></EditTextPreference>
|
|
||||||
|
<EditTextPreference
|
||||||
<EditTextPreference
|
android:key="password"
|
||||||
android:key="pref_identifier"
|
android:title="Password"
|
||||||
android:title="SMS Identifier"
|
android:password="true"
|
||||||
android:summary="Handle only SMS messages starting with this string (leave empty to handle all messages)"
|
></EditTextPreference>
|
||||||
android:defaultValue="kal "
|
|
||||||
></EditTextPreference>
|
<CheckBoxPreference
|
||||||
|
android:key="detailed_log"
|
||||||
<CheckBoxPreference
|
android:title="Detailed log messages?"
|
||||||
android:key="pref_poll_switch"
|
android:disableDependentsState="false"
|
||||||
android:title="Server Polling"
|
></CheckBoxPreference>
|
||||||
android:disableDependentsState="false"
|
|
||||||
android:summary="Poll target URL every 15 minutes (Note: increases power usage)"
|
|
||||||
></CheckBoxPreference>
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
@ -1,91 +0,0 @@
|
|||||||
package kalsms.niryariv.itp;
|
|
||||||
|
|
||||||
import kalsms.niryariv.itp.R;
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
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 Boolean polling = false;
|
|
||||||
|
|
||||||
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", "");
|
|
||||||
this.polling = settings.getBoolean("pref_poll_switch", false);
|
|
||||||
|
|
||||||
Log.d("KALSMS", "onResume ident:" + this.identifier +"\ntarget:" + this.targetUrl);
|
|
||||||
|
|
||||||
String infoText = new String();
|
|
||||||
|
|
||||||
// Home Screen text
|
|
||||||
infoText = "All SMS messages";
|
|
||||||
|
|
||||||
if (this.identifier.trim() != "") {
|
|
||||||
infoText += " starting with <b>" + this.identifier + "</b>";
|
|
||||||
}
|
|
||||||
|
|
||||||
infoText += " are now sent to <b>" + this.targetUrl +"</b> in the following format:";
|
|
||||||
infoText += "<p><tt>GET " + this.targetUrl + "?sender=<phone#>&msg=<message></tt></p>";
|
|
||||||
infoText += "If the response body contains text, it will SMS back to the originating phone.";
|
|
||||||
|
|
||||||
if (this.polling) {
|
|
||||||
infoText += "<p>The target URL will be polled every 15 minutes (<i>note that polling increases power consumption</i>)</p>";
|
|
||||||
}
|
|
||||||
|
|
||||||
infoText += "<br /><br /><b>Press Menu to set SMS identifier or target URL.</b>";
|
|
||||||
|
|
||||||
infoText += "<p>Questions/feedback: niryariv@gmail.com</p>";
|
|
||||||
// END Home Screen text
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
package kalsms.niryariv.itp;
|
|
||||||
|
|
||||||
import kalsms.niryariv.itp.R;
|
|
||||||
import android.app.AlarmManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.SystemClock;
|
|
||||||
import android.preference.CheckBoxPreference;
|
|
||||||
import android.preference.EditTextPreference;
|
|
||||||
import android.preference.Preference;
|
|
||||||
import android.preference.PreferenceActivity;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Menu;
|
|
||||||
|
|
||||||
|
|
||||||
public class Prefs extends PreferenceActivity implements OnSharedPreferenceChangeListener {
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
addPreferencesFromResource(R.xml.prefs);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
// Set up a listener whenever a key changes
|
|
||||||
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
// Unregister the listener whenever a key changes
|
|
||||||
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
if(pref instanceof CheckBoxPreference) {
|
|
||||||
CheckBoxPreference checkbox = (CheckBoxPreference) pref;
|
|
||||||
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
|
||||||
Intent pintent = new Intent(this, SMSSender.class);
|
|
||||||
PendingIntent pIntent = PendingIntent.getBroadcast(this,0,pintent, 0);
|
|
||||||
if(checkbox.isChecked()) {
|
|
||||||
alarm.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pIntent);
|
|
||||||
Log.d("KALSMS", "alarm manager turned on");
|
|
||||||
} else {
|
|
||||||
alarm.cancel(pIntent);
|
|
||||||
Log.d("SMS_GATEWAY", "alarm manager turned off");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
|||||||
package kalsms.niryariv.itp;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
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.SmsMessage;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
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);
|
|
||||||
TargetUrlRequest url = new TargetUrlRequest();
|
|
||||||
|
|
||||||
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 = url.openURL(sender, message, targetUrl, false).toString();
|
|
||||||
Log.d("KALSMS", "RESP:\"" + resp);
|
|
||||||
|
|
||||||
// SMS back the response
|
|
||||||
if (resp.trim().length() > 0) {
|
|
||||||
ArrayList<ArrayList<String>> items = url.parseXML(resp);
|
|
||||||
url.sendMessages(items);
|
|
||||||
}
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
package kalsms.niryariv.itp;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.PowerManager;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class SMSSender extends BroadcastReceiver {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
|
|
||||||
// acquiring the wake clock to prevent device from sleeping while request is processed
|
|
||||||
final PowerManager pm = (PowerManager) context.getApplicationContext().getSystemService(Context.POWER_SERVICE);
|
|
||||||
PowerManager.WakeLock wake = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "http_request");
|
|
||||||
wake.acquire();
|
|
||||||
|
|
||||||
// get settings
|
|
||||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
String targetUrl = settings.getString("pref_target_url", "");
|
|
||||||
Log.d("KALSMS", "url:\"" + targetUrl);
|
|
||||||
TargetUrlRequest url = new TargetUrlRequest();
|
|
||||||
// send the message to the URL
|
|
||||||
String resp = url.openURL("","",targetUrl, true).toString();
|
|
||||||
|
|
||||||
Log.d("KALSMS", "RESP:\"" + resp);
|
|
||||||
|
|
||||||
// SMS back the response
|
|
||||||
if (resp.trim().length() > 0) {
|
|
||||||
ArrayList<ArrayList<String>> items = url.parseXML(resp);
|
|
||||||
url.sendMessages(items);
|
|
||||||
}
|
|
||||||
wake.release();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,131 +0,0 @@
|
|||||||
package kalsms.niryariv.itp;
|
|
||||||
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
|
||||||
|
|
||||||
import org.apache.http.HttpEntity;
|
|
||||||
import org.apache.http.HttpResponse;
|
|
||||||
import org.apache.http.NameValuePair;
|
|
||||||
import org.apache.http.client.HttpClient;
|
|
||||||
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;
|
|
||||||
|
|
||||||
import android.telephony.SmsManager;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class TargetUrlRequest {
|
|
||||||
|
|
||||||
private String sender = "";
|
|
||||||
|
|
||||||
public String openURL(String sender, String message, String targetUrl, Boolean isPollRequest) {
|
|
||||||
|
|
||||||
this.sender = sender;
|
|
||||||
|
|
||||||
List<NameValuePair> qparams = new ArrayList<NameValuePair>();
|
|
||||||
|
|
||||||
if(sender.trim().length() > 0 && message.trim().length() > 0) {
|
|
||||||
qparams.add(new BasicNameValuePair("sender", sender));
|
|
||||||
qparams.add(new BasicNameValuePair("msg", message));
|
|
||||||
} else if (isPollRequest) {
|
|
||||||
qparams.add(new BasicNameValuePair("poll", "true"));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ArrayList<ArrayList<String>> parseXML(String xml) {
|
|
||||||
ArrayList<ArrayList<String>> output = new ArrayList<ArrayList<String>>();
|
|
||||||
|
|
||||||
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<String> item = new ArrayList<String>();
|
|
||||||
|
|
||||||
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<String>) item);
|
|
||||||
}
|
|
||||||
} else if (nodeName.equalsIgnoreCase("sms-to-sender")) {
|
|
||||||
item.add("sender");
|
|
||||||
item.add(e.getFirstChild().getNodeValue());
|
|
||||||
output.add((ArrayList<String>) 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void sendMessages(ArrayList<ArrayList<String>> items) {
|
|
||||||
SmsManager smgr = SmsManager.getDefault();
|
|
||||||
for (int j = 0; j < items.size(); j++) {
|
|
||||||
String sendTo = items.get(j).get(0);
|
|
||||||
if (sendTo.toLowerCase() == "sender") sendTo = this.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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
158
src/org/envaya/kalsms/App.java
Executable file
158
src/org/envaya/kalsms/App.java
Executable file
@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
* To change this template, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.envaya.kalsms;
|
||||||
|
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.telephony.SmsManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jesse
|
||||||
|
*/
|
||||||
|
public class App {
|
||||||
|
|
||||||
|
public static final int OUTGOING_POLL_SECONDS = 30;
|
||||||
|
|
||||||
|
public static final String LOG_NAME = "KALSMS";
|
||||||
|
public static final String LOG_INTENT = "org.envaya.kalsms.LOG";
|
||||||
|
public static final String SEND_STATUS_INTENT = "org.envaya.kalsms.SEND_STATUS";
|
||||||
|
|
||||||
|
public Context context;
|
||||||
|
public SharedPreferences settings;
|
||||||
|
|
||||||
|
public App(Context context)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void debug(String msg)
|
||||||
|
{
|
||||||
|
Log.d(LOG_NAME, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(String msg)
|
||||||
|
{
|
||||||
|
Log.d(LOG_NAME, msg);
|
||||||
|
|
||||||
|
Intent broadcast = new Intent(App.LOG_INTENT);
|
||||||
|
broadcast.putExtra("message", msg);
|
||||||
|
context.sendBroadcast(broadcast);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logError(Throwable ex)
|
||||||
|
{
|
||||||
|
logError("ERROR", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logError(String msg, Throwable ex)
|
||||||
|
{
|
||||||
|
logError(msg, ex, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logError(String msg, Throwable ex, boolean detail)
|
||||||
|
{
|
||||||
|
log(msg + ": " + ex.getClass().getName() + ": " + ex.getMessage());
|
||||||
|
|
||||||
|
if (detail)
|
||||||
|
{
|
||||||
|
for (StackTraceElement elem : ex.getStackTrace())
|
||||||
|
{
|
||||||
|
log(elem.getClassName() + ":" + elem.getMethodName() + ":" + elem.getLineNumber());
|
||||||
|
}
|
||||||
|
Throwable innerEx = ex.getCause();
|
||||||
|
if (innerEx != null)
|
||||||
|
{
|
||||||
|
logError("Inner exception:", innerEx, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIncomingUrl()
|
||||||
|
{
|
||||||
|
return getServerUrl() + "/pg/receive_sms";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOutgoingUrl()
|
||||||
|
{
|
||||||
|
return getServerUrl() + "/pg/dequeue_sms";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSendStatusUrl()
|
||||||
|
{
|
||||||
|
return getServerUrl() + "/pg/sms_sent";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServerUrl()
|
||||||
|
{
|
||||||
|
return settings.getString("server_url", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPhoneNumber()
|
||||||
|
{
|
||||||
|
return settings.getString("phone_number", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword()
|
||||||
|
{
|
||||||
|
return settings.getString("password", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private SQLiteDatabase db;
|
||||||
|
public SQLiteDatabase getWritableDatabase()
|
||||||
|
{
|
||||||
|
if (db == null)
|
||||||
|
{
|
||||||
|
db = new DBHelper(context).getWritableDatabase();
|
||||||
|
}
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendSMS(OutgoingSmsMessage sms)
|
||||||
|
{
|
||||||
|
String serverId = sms.getServerId();
|
||||||
|
|
||||||
|
if (serverId != null)
|
||||||
|
{
|
||||||
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
|
Cursor cursor =
|
||||||
|
db.rawQuery("select 1 from sent_sms where server_id=?", new String[] { serverId });
|
||||||
|
|
||||||
|
boolean exists = (cursor.getCount() > 0);
|
||||||
|
cursor.close();
|
||||||
|
if (exists)
|
||||||
|
{
|
||||||
|
log(sms.getLogName() + " already sent, skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put("server_id", serverId);
|
||||||
|
db.insert("sent_sms", null, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
SmsManager smgr = SmsManager.getDefault();
|
||||||
|
|
||||||
|
Intent intent = new Intent(App.SEND_STATUS_INTENT);
|
||||||
|
intent.putExtra("serverId", serverId);
|
||||||
|
|
||||||
|
PendingIntent sentIntent = PendingIntent.getBroadcast(
|
||||||
|
this.context,
|
||||||
|
0,
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_ONE_SHOT);
|
||||||
|
|
||||||
|
log("Sending " +sms.getLogName() + " to " + sms.getTo());
|
||||||
|
smgr.sendTextMessage(sms.getTo(), null, sms.getMessage(), sentIntent, null);
|
||||||
|
}
|
||||||
|
}
|
37
src/org/envaya/kalsms/DBHelper.java
Executable file
37
src/org/envaya/kalsms/DBHelper.java
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* To change this template, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.envaya.kalsms;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jesse
|
||||||
|
*/
|
||||||
|
public class DBHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
|
private static final int DATABASE_VERSION = 1;
|
||||||
|
private static final String DATABASE_NAME = "org.envaya.kalsms.db";
|
||||||
|
|
||||||
|
private static final String SENT_SMS_TABLE_CREATE =
|
||||||
|
"CREATE TABLE sent_sms (server_id text);"
|
||||||
|
+ "CREATE INDEX server_id_index ON sent_sms (server_id);";
|
||||||
|
|
||||||
|
public DBHelper(Context context) {
|
||||||
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(SQLiteDatabase db) {
|
||||||
|
db.execSQL(SENT_SMS_TABLE_CREATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
161
src/org/envaya/kalsms/IncomingMessageForwarder.java
Executable file
161
src/org/envaya/kalsms/IncomingMessageForwarder.java
Executable file
@ -0,0 +1,161 @@
|
|||||||
|
package org.envaya.kalsms;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.telephony.SmsManager;
|
||||||
|
import android.telephony.SmsMessage;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
|
||||||
|
public class IncomingMessageForwarder extends BroadcastReceiver {
|
||||||
|
|
||||||
|
private App app;
|
||||||
|
|
||||||
|
public List<OutgoingSmsMessage> sendMessageToServer(SmsMessage sms) {
|
||||||
|
|
||||||
|
String message = sms.getDisplayMessageBody();
|
||||||
|
String sender = sms.getDisplayOriginatingAddress();
|
||||||
|
String recipient = app.getPhoneNumber();
|
||||||
|
|
||||||
|
app.log("Received SMS from " + sender);
|
||||||
|
|
||||||
|
if (message == null || message.length() == 0) {
|
||||||
|
return new ArrayList<OutgoingSmsMessage>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<OutgoingSmsMessage> replies = new ArrayList<OutgoingSmsMessage>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
List<NameValuePair> params = new ArrayList<NameValuePair>();
|
||||||
|
params.add(new BasicNameValuePair("from", sender));
|
||||||
|
params.add(new BasicNameValuePair("to", recipient));
|
||||||
|
params.add(new BasicNameValuePair("message", message));
|
||||||
|
params.add(new BasicNameValuePair("secret", app.getPassword()));
|
||||||
|
|
||||||
|
HttpClient client = new DefaultHttpClient();
|
||||||
|
HttpPost post = new HttpPost(app.getIncomingUrl());
|
||||||
|
post.setEntity(new UrlEncodedFormEntity(params));
|
||||||
|
|
||||||
|
app.log("Forwarding incoming SMS to server");
|
||||||
|
|
||||||
|
HttpResponse response = client.execute(post);
|
||||||
|
|
||||||
|
InputStream responseStream = response.getEntity().getContent();
|
||||||
|
DocumentBuilder xmlBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
|
Document xml = xmlBuilder.parse(responseStream);
|
||||||
|
|
||||||
|
NodeList smsNodes = xml.getElementsByTagName("Sms");
|
||||||
|
for (int i = 0; i < smsNodes.getLength(); i++) {
|
||||||
|
Element smsElement = (Element) smsNodes.item(i);
|
||||||
|
|
||||||
|
OutgoingSmsMessage reply = new OutgoingSmsMessage();
|
||||||
|
|
||||||
|
reply.setFrom(recipient);
|
||||||
|
reply.setTo(sender);
|
||||||
|
reply.setMessage(smsElement.getFirstChild().getNodeValue());
|
||||||
|
|
||||||
|
replies.add(reply);
|
||||||
|
}
|
||||||
|
} catch (SAXException ex) {
|
||||||
|
app.logError("Error parsing response from server while forwarding incoming message", ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
app.logError("Error forwarding incoming message to server", ex);
|
||||||
|
} catch (ParserConfigurationException ex) {
|
||||||
|
app.logError("Error configuring XML parser", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return replies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void smsReceived(Intent intent) {
|
||||||
|
|
||||||
|
for (SmsMessage sms : getMessagesFromIntent(intent)) {
|
||||||
|
List<OutgoingSmsMessage> replies = sendMessageToServer(sms);
|
||||||
|
|
||||||
|
for (OutgoingSmsMessage reply : replies)
|
||||||
|
{
|
||||||
|
app.sendSMS(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
//DeleteSMSFromInbox(context, mesg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// source: http://www.devx.com/wireless/Article/39495/1954
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
try {
|
||||||
|
this.app = new App(context);
|
||||||
|
|
||||||
|
String action = intent.getAction();
|
||||||
|
|
||||||
|
if (action.equals("android.provider.Telephony.SMS_RECEIVED")) {
|
||||||
|
smsReceived(intent);
|
||||||
|
}
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
app.logError("Unexpected error in IncomingMessageForwarder", ex, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return retMsgs;
|
||||||
|
}
|
||||||
|
}
|
102
src/org/envaya/kalsms/Main.java
Executable file
102
src/org/envaya/kalsms/Main.java
Executable file
@ -0,0 +1,102 @@
|
|||||||
|
package org.envaya.kalsms;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlarmManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.text.method.ScrollingMovementMethod;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
public class Main extends Activity {
|
||||||
|
|
||||||
|
private BroadcastReceiver logReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
showLogMessage(intent.getExtras().getString("message"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void showLogMessage(String message)
|
||||||
|
{
|
||||||
|
TextView info = (TextView) Main.this.findViewById(R.id.info);
|
||||||
|
if (message != null)
|
||||||
|
{
|
||||||
|
info.append(message + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onResume() {
|
||||||
|
App.debug("RESUME");
|
||||||
|
super.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Called when the activity is first created. */
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
App.debug("STARTED");
|
||||||
|
|
||||||
|
setContentView(R.layout.main);
|
||||||
|
PreferenceManager.setDefaultValues(this, R.xml.prefs, false);
|
||||||
|
|
||||||
|
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||||
|
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,
|
||||||
|
0,
|
||||||
|
new Intent(this, OutgoingMessagePoller.class),
|
||||||
|
0);
|
||||||
|
|
||||||
|
alarm.setRepeating(
|
||||||
|
AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||||
|
SystemClock.elapsedRealtime(),
|
||||||
|
App.OUTGOING_POLL_SECONDS * 1000,
|
||||||
|
pendingIntent);
|
||||||
|
|
||||||
|
App app = new App(this.getApplication());
|
||||||
|
|
||||||
|
TextView info = (TextView) this.findViewById(R.id.info);
|
||||||
|
|
||||||
|
info.setText(Html.fromHtml("<b>SMS Gateway running.</b><br />"));
|
||||||
|
|
||||||
|
showLogMessage("Server URL is: " + app.getServerUrl());
|
||||||
|
showLogMessage("Your phone number is: " + app.getPhoneNumber());
|
||||||
|
showLogMessage("Checking for outgoing messages every " + App.OUTGOING_POLL_SECONDS + " sec");
|
||||||
|
|
||||||
|
info.append(Html.fromHtml("<b>Press Menu to edit settings.</b><br />"));
|
||||||
|
|
||||||
|
info.setMovementMethod(new ScrollingMovementMethod());
|
||||||
|
|
||||||
|
IntentFilter logReceiverFilter = new IntentFilter();
|
||||||
|
|
||||||
|
logReceiverFilter.addAction(App.LOG_INTENT);
|
||||||
|
registerReceiver(logReceiver, logReceiverFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
82
src/org/envaya/kalsms/MessageStatusNotifier.java
Executable file
82
src/org/envaya/kalsms/MessageStatusNotifier.java
Executable file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* To change this template, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.envaya.kalsms;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.telephony.SmsManager;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
|
||||||
|
public class MessageStatusNotifier extends BroadcastReceiver {
|
||||||
|
|
||||||
|
private App app;
|
||||||
|
|
||||||
|
public void notifySuccess(String serverId)
|
||||||
|
{
|
||||||
|
if (serverId != null)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
app.log("Notifying server of sent SMS id=" + serverId);
|
||||||
|
List<NameValuePair> params = new ArrayList<NameValuePair>();
|
||||||
|
params.add(new BasicNameValuePair("from", app.getPhoneNumber()));
|
||||||
|
params.add(new BasicNameValuePair("secret", app.getPassword()));
|
||||||
|
params.add(new BasicNameValuePair("id", serverId));
|
||||||
|
|
||||||
|
HttpClient client = new DefaultHttpClient();
|
||||||
|
HttpPost post = new HttpPost(app.getSendStatusUrl());
|
||||||
|
post.setEntity(new UrlEncodedFormEntity(params));
|
||||||
|
|
||||||
|
client.execute(post);
|
||||||
|
}
|
||||||
|
catch (IOException ex)
|
||||||
|
{
|
||||||
|
app.logError("Error while notifying server of outgoing message", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
app = new App(context);
|
||||||
|
|
||||||
|
String serverId = intent.getExtras().getString("serverId");
|
||||||
|
|
||||||
|
String desc = serverId == null ? "SMS reply" : ("SMS id=" + serverId);
|
||||||
|
|
||||||
|
switch (getResultCode()) {
|
||||||
|
case Activity.RESULT_OK:
|
||||||
|
app.log(desc + " sent successfully");
|
||||||
|
this.notifySuccess(serverId);
|
||||||
|
break;
|
||||||
|
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
|
||||||
|
app.log(desc + " could not be sent (generic failure)");
|
||||||
|
break;
|
||||||
|
case SmsManager.RESULT_ERROR_RADIO_OFF:
|
||||||
|
app.log(desc + " could not be sent (radio off)");
|
||||||
|
break;
|
||||||
|
case SmsManager.RESULT_ERROR_NO_SERVICE:
|
||||||
|
app.log(desc + " could not be sent (no service)");
|
||||||
|
break;
|
||||||
|
case SmsManager.RESULT_ERROR_NULL_PDU:
|
||||||
|
app.log(desc + " could not be sent (null PDU");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
app.log("SMS could not be sent (unknown error)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
89
src/org/envaya/kalsms/OutgoingMessagePoller.java
Executable file
89
src/org/envaya/kalsms/OutgoingMessagePoller.java
Executable file
@ -0,0 +1,89 @@
|
|||||||
|
package org.envaya.kalsms;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
public class OutgoingMessagePoller extends BroadcastReceiver {
|
||||||
|
|
||||||
|
private App app;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
app = new App(context);
|
||||||
|
|
||||||
|
app.log("Checking for outgoing messages");
|
||||||
|
|
||||||
|
for (OutgoingSmsMessage sms : getOutgoingMessages())
|
||||||
|
{
|
||||||
|
app.sendSMS(sms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable ex)
|
||||||
|
{
|
||||||
|
app.logError("Unexpected error in OutgoingMessagePoller", ex, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<OutgoingSmsMessage> getOutgoingMessages() {
|
||||||
|
List<OutgoingSmsMessage> messages = new ArrayList<OutgoingSmsMessage>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<NameValuePair> params = new ArrayList<NameValuePair>();
|
||||||
|
params.add(new BasicNameValuePair("from", app.getPhoneNumber()));
|
||||||
|
params.add(new BasicNameValuePair("secret", app.getPassword()));
|
||||||
|
|
||||||
|
HttpClient client = new DefaultHttpClient();
|
||||||
|
HttpPost post = new HttpPost(app.getOutgoingUrl());
|
||||||
|
post.setEntity(new UrlEncodedFormEntity(params));
|
||||||
|
|
||||||
|
HttpResponse response = client.execute(post);
|
||||||
|
|
||||||
|
InputStream responseStream = response.getEntity().getContent();
|
||||||
|
DocumentBuilder xmlBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||||
|
Document xml = xmlBuilder.parse(responseStream);
|
||||||
|
|
||||||
|
NodeList smsNodes = xml.getElementsByTagName("Sms");
|
||||||
|
for (int i = 0; i < smsNodes.getLength(); i++) {
|
||||||
|
Element smsElement = (Element) smsNodes.item(i);
|
||||||
|
OutgoingSmsMessage sms = new OutgoingSmsMessage();
|
||||||
|
|
||||||
|
sms.setFrom(app.getPhoneNumber());
|
||||||
|
sms.setTo(smsElement.getAttribute("to"));
|
||||||
|
sms.setMessage(smsElement.getFirstChild().getNodeValue());
|
||||||
|
sms.setServerId(smsElement.getAttribute("id"));
|
||||||
|
|
||||||
|
messages.add(sms);
|
||||||
|
}
|
||||||
|
} catch (SAXException ex) {
|
||||||
|
app.logError("Error parsing response from server while retreiving outgoing messages", ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
app.logError("Error retreiving outgoing messages from server", ex);
|
||||||
|
} catch (ParserConfigurationException ex) {
|
||||||
|
app.logError("Error configuring XML parser", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
60
src/org/envaya/kalsms/OutgoingSmsMessage.java
Executable file
60
src/org/envaya/kalsms/OutgoingSmsMessage.java
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
package org.envaya.kalsms;
|
||||||
|
|
||||||
|
public class OutgoingSmsMessage {
|
||||||
|
|
||||||
|
private String serverId;
|
||||||
|
private String message;
|
||||||
|
private String from;
|
||||||
|
private String to;
|
||||||
|
|
||||||
|
public OutgoingSmsMessage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLogName()
|
||||||
|
{
|
||||||
|
return (serverId == null) ? "SMS reply" : ("SMS id=" + serverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServerId()
|
||||||
|
{
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServerId(String id)
|
||||||
|
{
|
||||||
|
this.serverId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage()
|
||||||
|
{
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message)
|
||||||
|
{
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrom()
|
||||||
|
{
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrom(String from)
|
||||||
|
{
|
||||||
|
this.from = from;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTo()
|
||||||
|
{
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTo(String to)
|
||||||
|
{
|
||||||
|
this.to = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
71
src/org/envaya/kalsms/Prefs.java
Executable file
71
src/org/envaya/kalsms/Prefs.java
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
package org.envaya.kalsms;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceActivity;
|
||||||
|
import android.view.Menu;
|
||||||
|
|
||||||
|
public class Prefs extends PreferenceActivity implements OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
addPreferencesFromResource(R.xml.prefs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
// Set up a listener whenever a key changes
|
||||||
|
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
// Unregister the listener whenever a key changes
|
||||||
|
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
if(pref instanceof CheckBoxPreference) {
|
||||||
|
CheckBoxPreference checkbox = (CheckBoxPreference) pref;
|
||||||
|
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
|
||||||
|
Intent pintent = new Intent(this, SMSSender.class);
|
||||||
|
PendingIntent pIntent = PendingIntent.getBroadcast(this,0,pintent, 0);
|
||||||
|
if(checkbox.isChecked()) {
|
||||||
|
alarm.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
|
||||||
|
SystemClock.elapsedRealtime(),
|
||||||
|
AlarmManager.INTERVAL_FIFTEEN_MINUTES, pIntent);
|
||||||
|
Log.d("KALSMS", "alarm manager turned on");
|
||||||
|
} else {
|
||||||
|
alarm.cancel(pIntent);
|
||||||
|
Log.d("SMS_GATEWAY", "alarm manager turned off");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// first time the Menu key is pressed
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
startActivity(new Intent(this, Prefs.class));
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// any other time the Menu key is pressed
|
||||||
|
@Override
|
||||||
|
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||||
|
startActivity(new Intent(this, Prefs.class));
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user