com.baxtern.android.websms.connector.exetel.ConnectorExetel.java Source code

Java tutorial

Introduction

Here is the source code for com.baxtern.android.websms.connector.exetel.ConnectorExetel.java

Source

/*
 * Copyright (C) 2010 Nathaniel Baxter
 * This program is based off and uses WebSMS. Copyright (C) 2010 Felix Bechstein
 * 
 * This file is part of WebSMS Connector: Exetel.
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program; If not, see <http://www.gnu.org/licenses/>.
 */
package com.baxtern.android.websms.connector.exetel;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.apache.http.message.BasicNameValuePair;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import de.ub0r.android.websms.connector.common.Connector;
import de.ub0r.android.websms.connector.common.ConnectorCommand;
import de.ub0r.android.websms.connector.common.ConnectorSpec;
import de.ub0r.android.websms.connector.common.Log;
import de.ub0r.android.websms.connector.common.Utils;
import de.ub0r.android.websms.connector.common.WebSMSException;
import de.ub0r.android.websms.connector.common.ConnectorSpec.SubConnectorSpec;

/**
 * Receives commands coming as broadcasts from WebSMS.
 * 
 * @author Nathaniel Baxter
 */
public class ConnectorExetel extends Connector {
    /** Tag for output. */
    private static final String TAG = "WebSMS.exetel";

    /** API url */
    private static final String URL = "https://smsgw.exetel.com.au/sendsms/";
    /** API url for sending an sms */
    private static final String URL_SEND = URL + "api_sms.php";
    /** API url for sending a scheduled SMS */
    // private static final String URL_SEND_SCHEDULED = URL +
    // "api_sms_schedule.php";
    /**
     * Use POST seeing as this is the HTTPS protocal. We might as well send the
     * username/password/message using encryption.
     */
    private static final boolean USE_POST = true;

    /** Username parameter key. */
    private static final String PARAM_USERNAME = "username";
    /** Password parameter key. */
    private static final String PARAM_PASSWORD = "password";
    /** Sender parameter key. */
    private static final String PARAM_SENDER = "sender";
    /** To parameter key. */
    private static final String PARAM_TO = "mobilenumber";
    /** Text parameter key. */
    private static final String PARAM_TEXT = "message";
    /** Message type parameter key. */
    private static final String PARAM_TYPE = "messagetype";

    /** The delimer for the API's response text. */
    private static final String HTTP_RESPONSE_TEXT_DELIMITER = "\\|";
    /** The recipients delimer for the url query. */
    private static final String RECIPIENTS_DELIMTER = ",";
    /** The message type to use. */
    private static final String HTTP_MESSAGE_TYPE = "Text";
    /** The encoding to use. Only used for GET requests. */
    private static final String HTTP_REQUEST_ENCODING = "Unicode";

    /** The parameters returned by the API. */
    private static final int RETURN_PARAM_STATUS = 0;
    // private static final int RETURN_PARAM_MOBILENUMBER = 1;
    // private static final int RETURN_PARAM_REFERENCENUMBER = 2;
    // private static final int RETURN_PARAM_ID = 3;
    private static final int RETURN_PARAM_NOTES = 4;

    /** The status response codes given by the API. */
    // private static final int STATUS_SMS_REQUEST_FAILED = 0;
    // private static final int STATUS_SMS_FAILED = 2;
    private static final int STATUS_SMS_SENT = 1;

    /** Max. length of the message. */
    private static final int MAX_MESSAGE_LENGTH = 612;

    /**
     * {@inheritDoc}
     */
    @Override
    public final ConnectorSpec initSpec(final Context context) {
        final String name = context.getString(R.string.connector_exetel_name);
        final ConnectorSpec c = new ConnectorSpec(name);

        c.setAuthor(context.getString(R.string.connector_exetel_author));
        c.setBalance(null);
        c.setLimitLength(MAX_MESSAGE_LENGTH);
        c.setCapabilities(ConnectorSpec.CAPABILITIES_UPDATE | ConnectorSpec.CAPABILITIES_SEND
                | ConnectorSpec.CAPABILITIES_PREFS);
        // The Connector supports multiple receipients and custom senders.
        c.addSubConnector(TAG, name,
                SubConnectorSpec.FEATURE_MULTIRECIPIENTS | SubConnectorSpec.FEATURE_CUSTOMSENDER);
        // TODO: Implement the sendlater feature.
        // | SubConnectorSpec.FEATURE_SENDLATER);
        return c;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final ConnectorSpec updateSpec(final Context context, final ConnectorSpec connectorSpec) {
        final SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(context);
        if (p.getBoolean(Preferences.PREFS_ENABLED, false)) {
            if (p.getString(Preferences.PREFS_USER, "").length() > 0
                    && p.getString(Preferences.PREFS_PASSWORD, "").length() > 0) {
                connectorSpec.setReady();
            } else {
                connectorSpec.setStatus(ConnectorSpec.STATUS_ENABLED);
            }
        } else {
            connectorSpec.setStatus(ConnectorSpec.STATUS_INACTIVE);
        }
        return connectorSpec;
    }

    /**
     * Send some data! (ie. the SMS)
     * 
     * @param context
     *            Context
     * @param command
     *            ConnectorCommand
     * @throws WebSMSException
     *             WebSMSException
     */
    private void sendData(final Context context, final ConnectorCommand command) throws WebSMSException {
        try {
            // Get the preferences.
            final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

            // The request url. Used for single or multiple receipients.
            String url = URL_SEND;

            // Create an array of GET data.
            ArrayList<BasicNameValuePair> data = new ArrayList<BasicNameValuePair>();

            // Username.
            data.add(new BasicNameValuePair(PARAM_USERNAME, prefs.getString(Preferences.PREFS_USER, "")));
            // Password.
            data.add(new BasicNameValuePair(PARAM_PASSWORD, prefs.getString(Preferences.PREFS_PASSWORD, "")));
            // Destination/Recipients.
            // This code could validate the recipients so that they are numbers
            // of length maximum 15.
            data.add(new BasicNameValuePair(PARAM_TO,
                    Utils.joinRecipientsNumbers(command.getRecipients(), RECIPIENTS_DELIMTER, true)));
            // Sender.
            final String customSender = command.getCustomSender();
            // Default sender.
            if (customSender == null) {
                String sender = Utils.national2international(command.getDefPrefix(),
                        Utils.getSender(context, command.getDefSender()));

                // Remove the + from the start of the sender's number.
                if (sender.charAt(0) == '+') {
                    sender = sender.substring(1);
                }

                data.add(new BasicNameValuePair(PARAM_SENDER, sender));
            }
            // A custom sender.
            else {
                String sender = customSender;

                // Remove the + from the start of the sender's number.
                if (sender.charAt(0) == '+') {
                    sender = sender.substring(1);
                }

                data.add(new BasicNameValuePair(PARAM_SENDER, sender));
            }
            // Message.
            data.add(new BasicNameValuePair(PARAM_TEXT, command.getText()));
            // Message type.
            data.add(new BasicNameValuePair(PARAM_TYPE, HTTP_MESSAGE_TYPE));

            // Only if we have to make a GET request.
            if (!USE_POST) {
                // Create a string of the data for the url.
                StringBuilder data_string = new StringBuilder();
                data_string.append("?");

                for (int i = 0; i < data.size(); i++) {
                    BasicNameValuePair nv = data.get(i);
                    data_string.append(nv.getName());
                    data_string.append("=");
                    data_string.append(URLEncoder.encode(nv.getValue(), HTTP_REQUEST_ENCODING));
                    data_string.append("&");
                }

                // Add the data to the end of the url.
                url.concat(data_string.toString());
            }

            // Log that we're making a Http request.
            Log.d(TAG, "HTTP REQUEST: " + url);

            // Do the Http request.
            HttpResponse response = Utils.getHttpClient(url, null, data, null, null, true);

            // Get the http response text and status code.
            int response_code = response.getStatusLine().getStatusCode();
            String response_text = Utils.stream2str(response.getEntity().getContent()).trim();
            // Log the http response.
            Log.d(TAG, "HTTP RESPONSE (" + Integer.toString(response_code) + "): " + response_text);

            // Time to inspect the results of all our hard work!
            String[] response_data = response_text.split(HTTP_RESPONSE_TEXT_DELIMITER);

            // Deal with the response data provided by the api.
            try {
                // Check that the status is okay.
                int status = Integer.parseInt(response_data[RETURN_PARAM_STATUS]);
                if (status != STATUS_SMS_SENT) {
                    // Give the user the api's error message.
                    throw new WebSMSException(response_data[RETURN_PARAM_NOTES]);
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                throw new WebSMSException(context, R.string.error_exetel_invalid_return);
            } catch (NumberFormatException e) {
                throw new WebSMSException(context, R.string.error_exetel_invalid_return);
            }
            // Catch any annoying IO errors.
        } catch (IOException e) {
            Log.e(TAG, null, e);
            throw new WebSMSException(e.getMessage());
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected final void doUpdate(final Context context, final Intent intent) throws WebSMSException {
        this.sendData(context, new ConnectorCommand(intent));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected final void doSend(final Context context, final Intent intent) throws WebSMSException {
        this.sendData(context, new ConnectorCommand(intent));
    }
}