org.nsdev.smstweeter.SmsReceiver.java Source code

Java tutorial

Introduction

Here is the source code for org.nsdev.smstweeter.SmsReceiver.java

Source

/**
 * Copyright 2010 Neal Sanche
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.nsdev.smstweeter;

import java.util.Date;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.telephony.gsm.SmsManager;
import android.telephony.gsm.SmsMessage;
import android.util.Log;
import android.widget.Toast;

/**
 * @author Neal
 */
public class SmsReceiver extends BroadcastReceiver {

    static AsyncTask<String, String, String> mPoller = null;
    static Object mWaitLock = new Object();

    /*
     * (non-Javadoc)
     * 
     * @see android.content.BroadcastReceiver#onReceive(android.content.Context,
     * android.content.Intent)
     */
    @Override
    public void onReceive(final Context context, Intent intent) {
        // ---get the SMS message passed in---
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        final SmsMessage[] msgs = getMessagesFromIntent(intent);

        StringBuilder str = new StringBuilder();
        for (int i = 0; i < msgs.length; i++) {
            str.append(msgs[0].getOriginatingAddress());
            str.append(": ");
            str.append(msgs[i].getMessageBody().toString());
            str.append("\n");
        }
        // ---display the new SMS message---
        Toast.makeText(context, str, Toast.LENGTH_SHORT).show();

        final String msg = str.toString();

        SharedPreferences settings = context.getSharedPreferences(Main.PREFS_NAME, 0);

        final String twitterUser = settings.getString("twitterUser", "");
        final String twitterPassword = settings.getString("twitterPassword", "");
        final boolean forwardingEnabled = settings.getBoolean("forwardingEnabled", false);

        // Kick out if it's turned off
        if (twitterUser.length() == 0)
            return;
        if (twitterPassword.length() == 0)
            return;
        if (!forwardingEnabled)
            return;

        final int responsePollingLength = settings.getInt("responsePollingMinutes", 60);

        try {
            final Twitter twitter = new Twitter(twitterUser, twitterPassword);
            twitter.setSource("sms");

            // Update status with annotations specifying the receiver phone number
            String annotation = "[{\"sms\":{\"phone\":\"" + msgs[0].getOriginatingAddress() + "\"}}]";
            final Twitter.Status myMessage = twitter.updateStatus(msg, annotation, -1);

            Log.i("SMSRECIEVER", "Update: " + msg);

            if (mPoller == null) {
                mPoller = new AsyncTask<String, String, String>() {
                    @Override
                    protected String doInBackground(String... params) {
                        Log.i("SMSWaiter", "New poller created.");
                        try {
                            Date lastReplyDate = myMessage.getCreatedAt();
                            long cutoffTime = System.currentTimeMillis() + (responsePollingLength * 60000);
                            long pollingStarted = System.currentTimeMillis();

                            while (System.currentTimeMillis() < cutoffTime) {

                                synchronized (mWaitLock) {
                                    long pollInterval = CalculatePollInterval(pollingStarted,
                                            System.currentTimeMillis(), cutoffTime);
                                    long waitStarted = System.currentTimeMillis();

                                    Log.d("SMSWaiter", "Waiting for " + pollInterval + " ms");

                                    mWaitLock.wait(pollInterval);

                                    if (System.currentTimeMillis() - waitStarted < pollInterval) {
                                        Log.i("SMSWaiter", "Wait interrupted, resetting cutoffTime.");

                                        // Resetting cutoff date
                                        pollingStarted = System.currentTimeMillis();
                                        cutoffTime = pollingStarted + (responsePollingLength * 60000);
                                    }
                                }

                                Log.i("SMSWaiter", "Polling...");
                                try {
                                    for (Twitter.Status msg : twitter.getReplies()) {
                                        if (msg.getCreatedAt().after(lastReplyDate)) {
                                            Log.i("SMSWaiter", "New reply found...");

                                            // Found something newer
                                            lastReplyDate = msg.getCreatedAt();

                                            // Resetting cutoff date
                                            pollingStarted = System.currentTimeMillis();
                                            cutoffTime = pollingStarted + (responsePollingLength * 60000);

                                            // Ask twitter for the original message
                                            Twitter.Status originalStatus = twitter
                                                    .getStatus(msg.inReplyToStatusId);

                                            Log.i("SMSWaiter", "Retrieved original status: " + originalStatus.text);

                                            String messageText = msg.getText();

                                            if (messageText.startsWith("@" + twitterUser))
                                                messageText = messageText.substring(("@" + twitterUser).length());

                                            messageText = messageText.trim();

                                            Log.i("SMSWaiter", "Found reply message: " + messageText);

                                            String phoneNumber = null;

                                            try {
                                                String annotations = originalStatus.getAnnotations();
                                                annotations = annotations.substring(1, annotations.length() - 1);
                                                JSONObject annotationObject = new JSONObject(annotations);
                                                JSONObject sms = annotationObject.getJSONObject("sms");
                                                phoneNumber = (String) sms.get("phone");
                                                Log.i("SMSWaiter", "phone=" + phoneNumber);
                                            } catch (JSONException e) {
                                                // TODO Auto-generated catch block
                                                Log.e("SMSWaiter", e.toString());
                                            }

                                            if (phoneNumber != null) {
                                                try {
                                                    SmsManager sms = SmsManager.getDefault();
                                                    sms.sendTextMessage(phoneNumber, null, messageText, null, null);
                                                    Log.i("SMSWaiter", "Sent SMS message to " + phoneNumber + ": "
                                                            + messageText);
                                                } catch (Throwable ex) {
                                                    Log.e("SMSWaiter", ex.toString());
                                                }
                                            }
                                        }
                                    }
                                } catch (TwitterException ex) {
                                    if (ex.toString().contains("RateLimit")) {
                                        while (twitter.getRateLimitStatus() < 0) {
                                            Log.e("SMSWaiter", "Rate limited. Sleeping for a bit.");
                                            Thread.sleep(15000);
                                        }
                                    }
                                }
                            }
                            Log.i("SMSWaiter", "Timed out, quitting.");
                        } catch (InterruptedException ex) {
                            Log.e("SMSWaiter", "Interrupted.");
                        } catch (Throwable ex) {
                            Log.e("SMSWaiter", "Died: " + ex.toString());
                        }
                        mPoller = null;
                        return null;
                    }

                };
                mPoller.execute("DoIt!");
            } else {
                Log.i("SMSRECIEVER", "Poller already exists.");
                synchronized (mWaitLock) {
                    mWaitLock.notifyAll();
                }
            }
        } catch (Throwable ex) {
            Log.e("SMSRECIEVER", ex.toString());
        }
    }

    long intervalStep = 30000L;
    long[] pollIntervalLookupTable = { intervalStep, intervalStep * 2, intervalStep * 4, intervalStep * 10,
            intervalStep * 20 };

    private long CalculatePollInterval(long pollingStarted, long currentTimeMillis, long cutoffTime) {

        double percent = (currentTimeMillis - pollingStarted) / (double) (cutoffTime - pollingStarted);

        int index = (int) ((percent * 100) / (double) 20);

        Log.d("SMSWaiter", "percent = " + percent + " index=" + index);

        long interval = pollIntervalLookupTable[index];
        if (currentTimeMillis + interval > cutoffTime) {
            interval = cutoffTime - currentTimeMillis;
        }
        return interval;
    }

    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("GetMessages", "fail", e);
        }
        return retMsgs;
    }

}