Android sending lots of SMS messages-ThrowExceptions

Exception or error:

I have a app, which sends a lot of SMS messages to a central server. Each user will probably send ~300 txts/day. SMS messages are being used as a networking layer, because SMS is almost everywhere and mobile internet is not. The app is intended for use in a lot of 3rd world countries where mobile internet is not ubiquitous.

When I hit a limit of 100 messages, I get a prompt for each message sent. The prompt says “A large number of SMS messages are being sent”. This is not ok for the user to get prompted each time to ask if the app can send a text message. The user doesn’t want to get 30 consecutive prompts.

I found this android source file with google. It could be out of date, I can’t tell. It looks like there is a limit of 100 sms messages every 3600000ms(1 day) for each application.

http://www.netmite.com/android/mydroid/frameworks/base/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java

/** Default checking period for SMS sent without uesr permit */
private static final int DEFAULT_SMS_CHECK_PERIOD = 3600000;

/** Default number of SMS sent in checking period without uesr permit */
private static final int DEFAULT_SMS_MAX_ALLOWED = 100;

and

/**
 *  Implement the per-application based SMS control, which only allows
 *  a limit on the number of SMS/MMS messages an app can send in checking
 *  period.
 */
private class SmsCounter {
    private int mCheckPeriod;
    private int mMaxAllowed;
    private HashMap<String, ArrayList<Long>> mSmsStamp;

    /**
     * Create SmsCounter
     * @param mMax is the number of SMS allowed without user permit
     * @param mPeriod is the checking period
     */
    SmsCounter(int mMax, int mPeriod) {
        mMaxAllowed = mMax;
        mCheckPeriod = mPeriod;
        mSmsStamp = new HashMap<String, ArrayList<Long>> ();
    }

    boolean check(String appName) {
        if (!mSmsStamp.containsKey(appName)) {
            mSmsStamp.put(appName, new ArrayList<Long>());
        }

        return isUnderLimit(mSmsStamp.get(appName));
    }

    private boolean isUnderLimit(ArrayList<Long> sent) {
        Long ct =  System.currentTimeMillis();

        Log.d(TAG, "SMS send size=" + sent.size() + "time=" + ct);

        while (sent.size() > 0 && (ct - sent.get(0)) > mCheckPeriod ) {
                sent.remove(0);
        }

        if (sent.size() < mMaxAllowed) {
            sent.add(ct);
            return true;
        }
        return false;
    }
}

Is this even the real android code? It looks like it is in the package “com.android.internal.telephony.gsm”, I can’t find this package on the android website.

How can I disable/modify this limit? I’ve been googling for solutions, but I haven’t found anything.


So I was looking at the link that commonsware.com posted, and I found that the source had actually changed. And so I might still have a shot.

    int check_period = Settings.Gservices.getInt(mResolver,
            Settings.Gservices.SMS_OUTGOING_CEHCK_INTERVAL_MS,
            DEFAULT_SMS_CHECK_PERIOD);
    int max_count = Settings.Gservices.getInt(mResolver,
            Settings.Gservices.SMS_OUTGOING_CEHCK_MAX_COUNT,
            DEFAULT_SMS_MAX_COUNT);
    mCounter = new SmsCounter(max_count, check_period);

This is getting checkPeriod and maxCount from a settings table. But I don’t seem to have access to the same table. That source should be Android 1.1, which is the same I’m using. When I try to import android.provider.Settings.Gservices, I get an error saying that the import can’t be resolved.

What is going on?

How to solve:

Did you try using “import android.provider.Settings;” instead of “import android.provider.Settings.GServices”? (see line 36 of SMSDispatcher.java)

Also, not sure how much difference it makes, but 3600000 ms is one hour not one day.

###

Unfortunately I think you only have a few options

1) Get root access and alter the settings table directly by doing:

sqlite3 /data/data/com.android.providers.settings/databases/settings.db

sqlite> INSERT INTO gservices (name, value) VALUES
('sms_outgoing_check_interval_ms', 0);

2) Use multiple apps since it’s a per app limit

3) Perhaps take out the battery after you reach the limit? It looks like the limit is stored in memory. I haven’t tried this yet though.

###

This appears to be built into the Android source tree, so the only way to push this change down to the users would be the build your own ROM and have them install it.

As for ideas on getting around it, why not check for network connectivity first rather than just assuming it doesn’t exist. Even if it is not present on a significant majority of devices today, that certainly won’t always be the case. Let SMS be the fall back mechanism. If it is the fall back mechanism, you can then prompt the user letting them know that they will be prompted to confirm the level of SMS activity every 100 messages or so. Who knows, they may roam into a Wifi hotspot and have connectivity part of the day too.

Otherwise, you will get into a game of installing a bunch of other Activities+Intents that can act as silent SMS proxies to get around the limit. Of course, this has its own certain set of undesirable qualities as well and I can hardly believe I just typed/suggested something that evil.

Leave a Reply

Your email address will not be published. Required fields are marked *