com.winsuk.pebbletype.WatchCommunication.java Source code

Java tutorial

Introduction

Here is the source code for com.winsuk.pebbletype.WatchCommunication.java

Source

/*    
 *  Twist Chat companion app
 *  Copyright (C) 2014 - WinSuk (winsuk@winsuk.net)
 * 
 *  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.winsuk.pebbletype;

import java.util.ArrayList;
import java.util.UUID;

import org.json.JSONException;

import com.getpebble.android.kit.PebbleKit;
import com.getpebble.android.kit.util.PebbleDictionary;

import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.PhoneLookup;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.telephony.SmsManager;
import android.util.Log;

public class WatchCommunication extends BroadcastReceiver {
    private static final UUID PEBBLE_APP_UUID = UUID.fromString("16bb858b-fdde-479a-acd6-9b7678c147b0");

    private static final int KEY_REQUEST_THREAD_LIST = 0;
    private static final int KEY_THREAD_LIST = 1;
    private static final int KEY_SEND_MESSAGE = 2;
    private static final int KEY_MESSAGE_SENT = 3;
    private static final int KEY_MESSAGE_NOT_SENT = 4;

    private static final int THREAD_LIMIT = 4;

    private static final String ACTION_PEBBLE_RECEIVE = "com.getpebble.action.app.RECEIVE";
    private static final String ACTION_SMS_REPLY = "com.winsuk.pebbletype.sms.REPLY";

    @Override
    public void onReceive(Context context, Intent intent) {
        if (ACTION_PEBBLE_RECEIVE.equals(intent.getAction())) {
            final UUID receivedUuid = (UUID) intent.getSerializableExtra("uuid");

            // Pebble-enabled apps are expected to be good citizens and only inspect broadcasts containing their UUID
            if (!PEBBLE_APP_UUID.equals(receivedUuid)) {
                return;
            }

            final int transactionId = intent.getIntExtra("transaction_id", -1);
            final String jsonData = intent.getStringExtra("msg_data");
            if (jsonData == null || jsonData.isEmpty()) {
                return;
            }

            try {
                final PebbleDictionary data = PebbleDictionary.fromJson(jsonData);
                receiveData(context, transactionId, data);
            } catch (JSONException e) {
                e.printStackTrace();
                return;
            }
        }

        if (ACTION_SMS_REPLY.equals(intent.getAction())) {
            boolean sent = getResultCode() == Activity.RESULT_OK;

            if (!sent)
                Log.w("com.winsuk.pebbletype", "Message failed to send. Result code: " + getResultCode());

            PebbleDictionary data = new PebbleDictionary();
            data.addUint8(sent ? KEY_MESSAGE_SENT : KEY_MESSAGE_NOT_SENT, (byte) 1);
            PebbleKit.sendDataToPebble(context, PEBBLE_APP_UUID, data);
        }
    }

    public void receiveData(final Context context, final int transactionId, final PebbleDictionary data) {
        PebbleKit.sendAckToPebble(context, transactionId);

        if (data.contains(KEY_REQUEST_THREAD_LIST)) {
            sendThreadList(context);
        }

        if (data.contains(KEY_SEND_MESSAGE)) {
            String str = data.getString(KEY_SEND_MESSAGE);
            boolean demoMode = str.startsWith(";");

            String address = str.substring(0, str.indexOf(";"));
            String message = str.substring(str.indexOf(";") + 1, str.length());

            if (!demoMode) {
                SmsManager sms = SmsManager.getDefault();

                // Tried to use getService here which makes more sense, but that didn't work
                PendingIntent pi = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_SMS_REPLY),
                        PendingIntent.FLAG_ONE_SHOT);

                sms.sendTextMessage(address, null, message, pi, null);
            }
        }
    }

    private void sendThreadList(Context context) {
        Cursor msgCursor = context.getContentResolver().query(Uri.parse("content://sms/inbox"), null, null, null,
                null);
        Activity act = new Activity();
        act.startManagingCursor(msgCursor);
        ArrayList<SMSThread> threads = new ArrayList<SMSThread>();

        if (msgCursor.moveToFirst()) {
            for (int i = 0; i < msgCursor.getCount(); i++) {
                int thread_id = msgCursor.getInt(msgCursor.getColumnIndexOrThrow("thread_id"));
                SMSThread th = null;
                for (int t = 0; t < threads.size(); t++) {
                    SMSThread existingTh = threads.get(t);
                    if (existingTh.thread_id == thread_id) {
                        th = existingTh;
                    }
                }

                if (th == null) {
                    String address = msgCursor.getString(msgCursor.getColumnIndexOrThrow("address")).toString();
                    String name = "";

                    Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, address);
                    Cursor contactCursor = context.getContentResolver().query(uri,
                            new String[] { PhoneLookup.DISPLAY_NAME }, null, null, null);
                    if (contactCursor.moveToFirst()) {
                        name = contactCursor.getString(contactCursor.getColumnIndex(PhoneLookup.DISPLAY_NAME));
                        contactCursor.close();
                    }

                    th = new SMSThread();
                    th.thread_id = thread_id;
                    th.address = address;
                    th.name = name;
                    //th.messages = new ArrayList<String>();
                    threads.add(th);
                }

                /* TODO: this line is causing crashes on select few devices
                String body = msgCursor.getString(msgCursor.getColumnIndexOrThrow("body")).toString();
                if (th.messages.size() < 5) {
                   th.messages.add(body);
                }
                */

                msgCursor.moveToNext();
            }
        }
        msgCursor.close();

        int limit = (threads.size() <= THREAD_LIMIT ? threads.size() : THREAD_LIMIT);
        String output = "";

        if (limit > 0) {
            // Calculate how many characters names can take up
            int availibleCharacters = 120;
            for (int i = 0; i < limit; i++) {
                availibleCharacters -= threads.get(i).address.length();
                availibleCharacters -= 2; //for ; and \n
            }
            int maxNameLength = availibleCharacters / limit - 3;

            for (int i = 0; i < limit; i++) {
                SMSThread thread = threads.get(i);

                String name = "";
                if (thread.name.length() < maxNameLength) {
                    name = thread.name;
                } else {
                    name = thread.name.substring(0, maxNameLength - 1);
                    name += "";
                }

                output = output + thread.address + ";" + name + "\n";

                /* List messages
                for (int ii = 0; ii < thread.messages.size(); ii++) {
                   output = output + thread.messages.get(ii) + "\n";
                }*/
            }
        }
        PebbleDictionary data = new PebbleDictionary();
        data.addString(KEY_THREAD_LIST, output);
        PebbleKit.sendDataToPebble(context, PEBBLE_APP_UUID, data);
    }

}

class SMSThread {
    public int thread_id;
    public String address;
    public String name;
    public ArrayList<String> messages;
}