5
0
mirror of https://github.com/cwinfo/envayasms.git synced 2024-12-04 20:45:32 +00:00

avoid exceeding Android limit of 100 outgoing SMS/app/hour; allow effectively increasing limit via expansion packs; revert Sms -> sms in XML response

This commit is contained in:
Jesse Young 2011-09-18 15:29:30 -07:00
parent 7bc88cfde1
commit e834488d29
14 changed files with 461 additions and 133 deletions

View File

@ -4,9 +4,10 @@
android:versionCode="1" android:versionCode="1"
android:versionName="1.0"> android:versionName="1.0">
<uses-sdk android:minSdkVersion="4" />
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS" /> <uses-permission android:name="android.permission.RECEIVE_MMS" />
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
<uses-permission android:name="android.permission.SEND_SMS" /> <uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" /> <uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.WRITE_SMS" /> <uses-permission android:name="android.permission.WRITE_SMS" />
@ -39,7 +40,18 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".receiver.MessageStatusNotifier"> <receiver android:name=".receiver.OutgoingSmsReceiver">
<intent-filter>
<action android:name="org.envaya.kalsms.OUTGOING_SMS" />
<data android:scheme="content" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.MessageStatusNotifier" android:exported="true">
<intent-filter>
<action android:name="org.envaya.kalsms.MESSAGE_STATUS" />
<data android:scheme="content" />
</intent-filter>
</receiver> </receiver>
<receiver android:name=".receiver.OutgoingMessagePoller"> <receiver android:name=".receiver.OutgoingMessagePoller">
@ -57,7 +69,17 @@
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".receiver.ExpansionPackInstallReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
<service android:name=".CheckMmsInboxService"> <service android:name=".CheckMmsInboxService">
</service> </service>
</application> </application>
</manifest> </manifest>

5
CONTRIBUTORS Executable file
View File

@ -0,0 +1,5 @@
Current Maintainer:
Jesse Young <youngj@envaya.org>
Initial Developer:
Nir Yariv <niryariv@gmail.com>

View File

@ -1,4 +1,10 @@
Copyright (C) 2011 by Nir Yariv
Except for the parts noted otherwise (see Third-Party Libraries section below),
KalSMS' source code is licensed under the MIT license:
-----
Copyright (C) 2011 by Nir Yariv, Jesse Young
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@ -17,3 +23,21 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
=====================
Third-Party Libraries
=====================
libs/httpmime-4.1.2.jar is (c) Apache Software Foundation
released under Apache License, Version 2.0
org.envaya.kalsms.Base64Coder is (c) 2003-2010 Christian d'Heureuse,
released under MIT License (and others)
org.envaya.kalsms.ui.InertCheckBox and org.envaya.kalsms.ui.CheckableRelativeLayout
is (c) Cédric Caron, released presumably into the public domain at
http://www.marvinlabs.com/2010/10/custom-listview-ability-check-items/
org.envaya.kalsms.App.chooseOutgoingSmsPackage includes code from Android,
Copyright 2005-2008 The Android Open Source Project
See NOTICE

189
NOTICE Executable file
View File

@ -0,0 +1,189 @@
=========================================================================
== NOTICE file corresponding to the section 4 d of ==
== the Apache License, Version 2.0, ==
== in this case for the Android-specific code. ==
=========================================================================
This product includes software developed as part of
The Android Open Source Project (http://source.android.com).
=============================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -13,7 +13,7 @@ Contents
About KalSMS About KalSMS
============ ============
KalSMS is an Android app that acts as a SMS/MMS gateway. KalSMS is an Android app that acts as a SMS and MMS gateway.
For more information, see http://youngj.github.com/KalSMS/ For more information, see http://youngj.github.com/KalSMS/
======== ========
@ -23,6 +23,8 @@ Features
* Can be deployed almost anywhere in the world * Can be deployed almost anywhere in the world
* Designed to allow non-technical users to do all setup/maintenance * Designed to allow non-technical users to do all setup/maintenance
of deployed phones of deployed phones
* Can send outgoing SMS in excess of Android's limit of 100 messages
per app per hour by installing expansion packs
* Many different phones running KalSMS can be connected to a single server * Many different phones running KalSMS can be connected to a single server
(each phone could forward messages for a different mobile network) (each phone could forward messages for a different mobile network)
* Authenticates with password shared between phone and server * Authenticates with password shared between phone and server
@ -253,4 +255,3 @@ License
======= =======
The code is released under the MIT license; see LICENSE.txt The code is released under the MIT license; see LICENSE.txt

View File

@ -1,77 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>youngj/KalSMS @ GitHub</title>
<style type="text/css">
body {
margin-top: 1.0em;
background-color: #98740f;
font-family: Helvetica, Arial, FreeSans, san-serif;
color: #ffffff;
}
#container {
margin: 0 auto;
width: 700px;
}
h1 { font-size: 3.8em; color: #678bf0; margin-bottom: 3px; }
h1 .small { font-size: 0.4em; }
h1 a { text-decoration: none }
h2 { font-size: 1.5em; color: #678bf0; }
h3 { text-align: center; color: #678bf0; }
a { color: #678bf0; }
.description { font-size: 1.2em; margin-bottom: 30px; margin-top: 30px; font-style: italic;}
.download { float: right; }
pre { background: #000; color: #fff; padding: 15px;}
hr { border: 0; width: 80%; border-bottom: 1px solid #aaa}
.footer { text-align:center; padding-top:30px; font-style: italic; }
</style>
</head>
<body>
<a href="http://github.com/youngj/KalSMS"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
<div id="container">
<div class="download">
<a href="http://github.com/youngj/KalSMS/zipball/master">
<img border="0" width="90" src="http://github.com/images/modules/download/zip.png"></a>
<a href="http://github.com/youngj/KalSMS/tarball/master">
<img border="0" width="90" src="http://github.com/images/modules/download/tar.png"></a>
</div>
<h1><a href="http://github.com/youngj/KalSMS">KalSMS</a>
<span class="small">by <a href="http://github.com/youngj">youngj</a></span></h1>
<div class="description">
SImple SMS gateway running on Android
</div>
<h2>Authors</h2>
<p>Nir Yariv (niryariv@gmail.com) <br/>Jesse Young (youngj@envaya.org) <br/> <br/> </p>
<h2>Contact</h2>
<p>Jesse Young (adunar@gmail.com) <br/> </p>
<h2>Download</h2>
<p>
You can download this project in either
<a href="http://github.com/youngj/KalSMS/zipball/master">zip</a> or
<a href="http://github.com/youngj/KalSMS/tarball/master">tar</a> formats.
</p>
<p>You can also clone the project with <a href="http://git-scm.com">Git</a>
by running:
<pre>$ git clone git://github.com/youngj/KalSMS</pre>
</p>
<div class="footer">
get the source code on GitHub : <a href="http://github.com/youngj/KalSMS">youngj/KalSMS</a>
</div>
</div>
</body>
</html>

View File

@ -138,12 +138,12 @@ class KalSMS_Action_Incoming extends KalSMS_Action
{ {
ob_start(); ob_start();
echo "<?xml version='1.0' encoding='UTF-8'?>\n"; echo "<?xml version='1.0' encoding='UTF-8'?>\n";
echo "<Response>"; echo "<messages>";
foreach ($messages as $message) foreach ($messages as $message)
{ {
echo "<Sms id='".KalSMS::escape($message->id)."'>".KalSMS::escape($message->message)."</Sms>"; echo "<sms id='".KalSMS::escape($message->id)."'>".KalSMS::escape($message->message)."</sms>";
} }
echo "</Response>"; echo "</messages>";
return ob_get_clean(); return ob_get_clean();
} }
} }
@ -160,13 +160,13 @@ class KalSMS_Action_Outgoing extends KalSMS_Action
{ {
ob_start(); ob_start();
echo "<?xml version='1.0' encoding='UTF-8'?>\n"; echo "<?xml version='1.0' encoding='UTF-8'?>\n";
echo "<Messages>"; echo "<messages>";
foreach ($messages as $message) foreach ($messages as $message)
{ {
echo "<Sms id='".KalSMS::escape($message->id)."' to='".KalSMS::escape($message->to)."'>". echo "<sms id='".KalSMS::escape($message->id)."' to='".KalSMS::escape($message->to)."'>".
KalSMS::escape($message->message)."</Sms>"; KalSMS::escape($message->message)."</sms>";
} }
echo "</Messages>"; echo "</messages>";
return ob_get_clean(); return ob_get_clean();
} }
} }

View File

@ -1,16 +1,15 @@
package org.envaya.kalsms; package org.envaya.kalsms;
import org.envaya.kalsms.task.PollerTask;
import org.envaya.kalsms.task.HttpTask;
import org.envaya.kalsms.receiver.OutgoingMessagePoller;
import android.app.Activity; import android.app.Activity;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.Application; import android.app.Application;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock; import android.os.SystemClock;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.telephony.SmsManager; import android.telephony.SmsManager;
@ -18,10 +17,15 @@ import android.text.Html;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.util.Log; import android.util.Log;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
import org.envaya.kalsms.receiver.OutgoingMessagePoller;
import org.envaya.kalsms.task.HttpTask;
import org.envaya.kalsms.task.PollerTask;
public final class App extends Application { public final class App extends Application {
@ -37,9 +41,24 @@ public final class App extends Application {
public static final String MESSAGE_TYPE_SMS = "sms"; public static final String MESSAGE_TYPE_SMS = "sms";
public static final String LOG_NAME = "KALSMS"; public static final String LOG_NAME = "KALSMS";
// intent to signal to Main activity (if open) that log has changed
public static final String LOG_INTENT = "org.envaya.kalsms.LOG"; public static final String LOG_INTENT = "org.envaya.kalsms.LOG";
public static final int MAX_DISPLAYED_LOG = 15000; public static final String QUERY_EXPANSION_PACKS_INTENT = "org.envaya.kalsms.QUERY_EXPANSION_PACKS";
public static final String QUERY_EXPANSION_PACKS_EXTRA_PACKAGES = "packages";
// Interface for sending outgoing messages to expansion packs
public static final String OUTGOING_SMS_INTENT_SUFFIX = ".OUTGOING_SMS";
public static final String OUTGOING_SMS_EXTRA_TO = "to";
public static final String OUTGOING_SMS_EXTRA_BODY = "body";
public static final int OUTGOING_SMS_UNHANDLED = Activity.RESULT_FIRST_USER;
// intent for MessageStatusNotifier to receive status updates for outgoing SMS
// (even if sent by an expansion pack)
public static final String MESSAGE_STATUS_INTENT = "org.envaya.kalsms.MESSAGE_STATUS";
public static final int MAX_DISPLAYED_LOG = 4000;
public static final int LOG_TIMESTAMP_INTERVAL = 60000; public static final int LOG_TIMESTAMP_INTERVAL = 60000;
// Each QueuedMessage is identified within our internal Map by its Uri. // Each QueuedMessage is identified within our internal Map by its Uri.
@ -49,6 +68,12 @@ public final class App extends Application {
public static final Uri INCOMING_URI = Uri.withAppendedPath(CONTENT_URI, "incoming"); public static final Uri INCOMING_URI = Uri.withAppendedPath(CONTENT_URI, "incoming");
public static final Uri OUTGOING_URI = Uri.withAppendedPath(CONTENT_URI, "outgoing"); public static final Uri OUTGOING_URI = Uri.withAppendedPath(CONTENT_URI, "outgoing");
// max per-app outgoing SMS rate used by com.android.internal.telephony.SMSDispatcher
// with a slightly longer check period to account for variance in the time difference
// between when we prepare messages and when SMSDispatcher receives them
public static int OUTGOING_SMS_CHECK_PERIOD = 3605000; // one hour plus 5 sec (in ms)
public static int OUTGOING_SMS_MAX_COUNT = 100;
private Map<Uri, IncomingMessage> incomingMessages = new HashMap<Uri, IncomingMessage>(); private Map<Uri, IncomingMessage> incomingMessages = new HashMap<Uri, IncomingMessage>();
private Map<Uri, OutgoingMessage> outgoingMessages = new HashMap<Uri, OutgoingMessage>(); private Map<Uri, OutgoingMessage> outgoingMessages = new HashMap<Uri, OutgoingMessage>();
@ -57,6 +82,11 @@ public final class App extends Application {
private SpannableStringBuilder displayedLog = new SpannableStringBuilder(); private SpannableStringBuilder displayedLog = new SpannableStringBuilder();
private long lastLogTime; private long lastLogTime;
private List<String> outgoingMessagePackages = new ArrayList<String>();
private int outgoingMessageCount = -1;
private HashMap<String, ArrayList<Long>> outgoingTimestamps
= new HashMap<String, ArrayList<Long>>();
private MmsUtils mmsUtils; private MmsUtils mmsUtils;
@Override @Override
@ -67,6 +97,10 @@ public final class App extends Application {
settings = PreferenceManager.getDefaultSharedPreferences(this); settings = PreferenceManager.getDefaultSharedPreferences(this);
mmsUtils = new MmsUtils(this); mmsUtils = new MmsUtils(this);
outgoingMessagePackages.add(getPackageName());
updateExpansionPacks();
log(Html.fromHtml( log(Html.fromHtml(
isEnabled() ? "<b>SMS gateway running.</b>" : "<b>SMS gateway disabled.</b>")); isEnabled() ? "<b>SMS gateway running.</b>" : "<b>SMS gateway disabled.</b>"));
@ -79,6 +113,100 @@ public final class App extends Application {
setOutgoingMessageAlarm(); setOutgoingMessageAlarm();
} }
public synchronized String chooseOutgoingSmsPackage()
{
outgoingMessageCount++;
int numPackages = outgoingMessagePackages.size();
// round robin selection of packages that are under max sending rate
for (int i = 0; i < numPackages; i++)
{
int packageIndex = (outgoingMessageCount + i) % numPackages;
String packageName = outgoingMessagePackages.get(packageIndex);
// implement rate-limiting algorithm from
// com.android.internal.telephony.SMSDispatcher.SmsCounter
if (!outgoingTimestamps.containsKey(packageName)) {
outgoingTimestamps.put(packageName, new ArrayList<Long>());
}
ArrayList<Long> sent = outgoingTimestamps.get(packageName);
Long ct = System.currentTimeMillis();
//log(packageName + " SMS send size=" + sent.size());
// remove old timestamps
while (sent.size() > 0 && (ct - sent.get(0)) > OUTGOING_SMS_CHECK_PERIOD )
{
sent.remove(0);
}
if ( (sent.size() + 1) <= OUTGOING_SMS_MAX_COUNT)
{
sent.add(ct);
return packageName;
}
}
log("Can't send outgoing SMS: maximum limit of "
+ getOutgoingMessageLimit() + " in 1 hour reached");
log("To increase this limit, install an expansion pack.");
return null;
}
private synchronized void setExpansionPacks(List<String> packages)
{
int prevLimit = getOutgoingMessageLimit();
if (packages == null)
{
packages = new ArrayList<String>();
}
packages.add(getPackageName());
outgoingMessagePackages = packages;
int newLimit = getOutgoingMessageLimit();
if (prevLimit != newLimit)
{
log("Outgoing SMS limit: " + newLimit + " messages/hour");
}
}
public int getOutgoingMessageLimit()
{
return outgoingMessagePackages.size() * OUTGOING_SMS_MAX_COUNT;
}
public void updateExpansionPacks()
{
ArrayList<String> packages = new ArrayList<String>();
Bundle extras = new Bundle();
extras.putStringArrayList(App.QUERY_EXPANSION_PACKS_EXTRA_PACKAGES, packages);
sendOrderedBroadcast(
new Intent(App.QUERY_EXPANSION_PACKS_INTENT),
"android.permission.SEND_SMS",
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent resultIntent) {
setExpansionPacks(this.getResultExtras(false)
.getStringArrayList(App.QUERY_EXPANSION_PACKS_EXTRA_PACKAGES));
}
},
null,
Activity.RESULT_OK,
null,
extras);
}
public void checkOutgoingMessages() public void checkOutgoingMessages()
{ {
String serverUrl = getServerUrl(); String serverUrl = getServerUrl();
@ -266,7 +394,7 @@ public final class App extends Application {
public synchronized void sendOutgoingMessage(OutgoingMessage sms) { public synchronized void sendOutgoingMessage(OutgoingMessage sms) {
Uri uri = sms.getUri(); Uri uri = sms.getUri();
if (outgoingMessages.containsKey(uri)) { if (outgoingMessages.containsKey(uri)) {
log(sms.getLogName() + " already sent, skipping"); log("Duplicate outgoing " + sms.getLogName() + ", skipping");
return; return;
} }

View File

@ -26,7 +26,6 @@ final class MmsObserver extends ContentObserver {
*/ */
app.getContentResolver().registerContentObserver( app.getContentResolver().registerContentObserver(
MmsUtils.OBSERVER_URI, true, this); MmsUtils.OBSERVER_URI, true, this);
app.log("MMS content observer registered");
MmsUtils mmsUtils = app.getMmsUtils(); MmsUtils mmsUtils = app.getMmsUtils();

View File

@ -1,12 +1,12 @@
package org.envaya.kalsms; package org.envaya.kalsms;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import org.envaya.kalsms.receiver.OutgoingMessageRetry; import org.envaya.kalsms.receiver.OutgoingMessageRetry;
import org.envaya.kalsms.receiver.MessageStatusNotifier;
import android.app.PendingIntent;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.telephony.SmsManager;
public class OutgoingMessage extends QueuedMessage { public class OutgoingMessage extends QueuedMessage {
@ -87,18 +87,19 @@ public class OutgoingMessage extends QueuedMessage {
public void trySend() public void trySend()
{ {
SmsManager smgr = SmsManager.getDefault(); String packageName = app.chooseOutgoingSmsPackage();
Intent intent = new Intent(app, MessageStatusNotifier.class); if (packageName == null)
intent.setData(this.getUri()); {
// todo... schedule retry
return;
}
PendingIntent sentIntent = PendingIntent.getBroadcast( Intent intent = new Intent(packageName + App.OUTGOING_SMS_INTENT_SUFFIX, this.getUri());
app, intent.putExtra(App.OUTGOING_SMS_EXTRA_TO, getTo());
0, intent.putExtra(App.OUTGOING_SMS_EXTRA_BODY, getMessageBody());
intent,
PendingIntent.FLAG_ONE_SHOT);
smgr.sendTextMessage(getTo(), null, getMessageBody(), sentIntent, null); app.sendBroadcast(intent, "android.permission.SEND_SMS");
} }
protected Intent getRetryIntent() { protected Intent getRetryIntent() {

View File

@ -0,0 +1,22 @@
package org.envaya.kalsms.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.envaya.kalsms.App;
public class ExpansionPackInstallReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
App app = (App) context.getApplicationContext();
String packageName = intent.getData().getSchemeSpecificPart();
if (packageName != null && packageName.startsWith(context.getPackageName() + ".pack"))
{
app.updateExpansionPacks();
}
}
}

View File

@ -0,0 +1,31 @@
package org.envaya.kalsms.receiver;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsManager;
import org.envaya.kalsms.App;
public class OutgoingSmsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent)
{
Bundle extras = intent.getExtras();
String to = extras.getString(App.OUTGOING_SMS_EXTRA_TO);
String body = extras.getString(App.OUTGOING_SMS_EXTRA_BODY);
SmsManager smgr = SmsManager.getDefault();
Intent statusIntent = new Intent(App.MESSAGE_STATUS_INTENT, intent.getData());
PendingIntent sentIntent = PendingIntent.getBroadcast(
context,
0,
statusIntent,
PendingIntent.FLAG_ONE_SHOT);
smgr.sendTextMessage(to, null, body, sentIntent, null);
}
}

View File

@ -190,7 +190,7 @@ public class HttpTask extends AsyncTask<String, Void, HttpResponse> {
DocumentBuilder xmlBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); DocumentBuilder xmlBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document xml = xmlBuilder.parse(responseStream); Document xml = xmlBuilder.parse(responseStream);
NodeList smsNodes = xml.getElementsByTagName("Sms"); NodeList smsNodes = xml.getElementsByTagName("sms");
for (int i = 0; i < smsNodes.getLength(); i++) { for (int i = 0; i < smsNodes.getLength(); i++) {
Element smsElement = (Element) smsNodes.item(i); Element smsElement = (Element) smsNodes.item(i);

View File

@ -1,7 +1,3 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.envaya.kalsms.ui; package org.envaya.kalsms.ui;
import android.app.Activity; import android.app.Activity;
@ -11,13 +7,8 @@ import android.view.Menu;
import android.widget.TextView; import android.widget.TextView;
import org.envaya.kalsms.R; import org.envaya.kalsms.R;
/**
*
* @author Jesse
*/
public class Help extends Activity { public class Help extends Activity {
/** Called when the activity is first created. */
@Override @Override
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
@ -29,8 +20,7 @@ public class Help extends Activity {
String html = "<b>KalSMS</b> is a SMS gateway.<br /><br /> " String html = "<b>KalSMS</b> is a SMS gateway.<br /><br /> "
+ "It forwards all incoming SMS messages received by this phone to a server on the internet, " + "It forwards all incoming SMS messages received by this phone to a server on the internet, "
+ "and also sends outgoing SMS messages from that server to other phones.<br /><br />" + "and also sends outgoing SMS messages from that server to other phones.<br /><br />"
+ "(See https://github.com/youngj/KalSMS/wiki " + "(See https://kalsms.net for information about setting up a server.)<br /><br />"
+ "for information about setting up a server.)<br /><br />"
+ "The Settings screen allows you configure KalSMS to work with a particular server, " + "The Settings screen allows you configure KalSMS to work with a particular server, "
+ "by entering the server URL, your phone number, " + "by entering the server URL, your phone number, "
+ "and the password assigned to your phone on the server.<br /><br />" + "and the password assigned to your phone on the server.<br /><br />"
@ -39,11 +29,4 @@ public class Help extends Activity {
help.setText(Html.fromHtml(html)); help.setText(Html.fromHtml(html));
} }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
this.finish();
return(true);
}
} }