David %!s(int64=9) %!d(string=hai) anos
pai
achega
33109a636c

+ 11 - 0
README.md

@@ -33,3 +33,14 @@ Supported Actions (and their parameters):
 - State:
 	- <String, Object>, set a state key to a value. Will trigger the 'State' special event if the value changed.
 
+
+For example you could do something like:
+
+- At 22:59 => Set Ringtone volume to 0%
+- At 7:59 => Set Ringtone volume to 100%
+
+or achieve the same thing with states:
+
+- Between 22:59 and 7:59 => Set state 'sleepy' to true
+- On 'sleepy' change to true => Set volume to 0% 
+- On 'sleepy' change to false => Set volume to 100%

+ 4 - 0
app/src/main/AndroidManifest.xml

@@ -6,6 +6,9 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.RECEIVE_SMS" />
+    <uses-permission android:name="android.permission.READ_SMS" />
+    <uses-permission android:name="android.permission.SEND_SMS" />
 
     <application
         android:allowBackup="true"
@@ -24,6 +27,7 @@
         <receiver android:name=".EventReceiver">
             <intent-filter>
                 <action android:name="android.intent.action.CONFIGURATION_CHANGED" />
+                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
             </intent-filter>
         </receiver>
         <receiver android:name=".BootReceiver">

+ 11 - 0
app/src/main/java/com/example/david/libretasker/EventReceiver.java

@@ -1,14 +1,20 @@
 package com.example.david.libretasker;
 
+import android.annotation.TargetApi;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Telephony;
+import android.telephony.SmsMessage;
 import android.util.Log;
 
 import com.example.david.libretasker.Actions.Actions;
 import com.example.david.libretasker.Events.Event;
 import com.example.david.libretasker.Events.NetworkEvent;
+import com.example.david.libretasker.Events.SMSEvent;
 import com.example.david.libretasker.Events.ScreenEvent;
 import com.example.david.libretasker.Events.StateEvent;
 import com.example.david.libretasker.Events.TimeEvent;
@@ -47,6 +53,10 @@ public class EventReceiver extends BroadcastReceiver {
                 e = new ScreenEvent();
                 data = UserData.getData("Screen");
                 break;
+            case Telephony.Sms.Intents.SMS_RECEIVED_ACTION:
+                e = new SMSEvent();
+                data = UserData.getData("SMS");
+                break;
             case Event.STATE_CHANGED:
                 e = new StateEvent();
                 String s = intent.getDataString();
@@ -61,6 +71,7 @@ public class EventReceiver extends BroadcastReceiver {
 
         actions = (ArrayList<HashMap<String, Object>>)data.get("Actions");
         eventData = (HashMap<String, Object>)data.get("Event");
+        eventData.put("Intent", intent);
         if (e.trigger(context, eventData)) {
             for (HashMap<String, Object> a : actions) {
                 Actions.Launch(context, (String) a.get("Type"), a.get("Value"));

+ 89 - 0
app/src/main/java/com/example/david/libretasker/Events/SMSEvent.java

@@ -0,0 +1,89 @@
+package com.example.david.libretasker.Events;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Telephony;
+import android.telephony.SmsMessage;
+
+import java.util.HashMap;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * Created by david on 03/01/17.
+ */
+
+public class SMSEvent implements Event {
+    private String failureReason = "";
+
+    @Override
+    public boolean trigger(Context ctx, HashMap<String, Object> hm) {
+        failureReason = "";
+        Intent intent = (Intent)hm.get("Intent");
+        SmsMessage[] messages = getIntentMessagesCompat(intent);
+
+        if ( messages == null ) {
+            failureReason = "Messages is null?";
+            return false;
+        }
+
+        if ( hm.get("BodyRegex") == null )
+            hm.put("BodyRegex", ".*");
+
+        String regex = (String)hm.get("BodyRegex");
+        Pattern p;
+        try {
+            p = Pattern.compile(regex);
+        } catch (PatternSyntaxException ex) {
+            failureReason = "Failed to compile regex";
+            return false;
+        }
+
+        for (SmsMessage s : messages) {
+            if ((String)hm.get("Sender") != null )
+                if ( ! s.getOriginatingAddress().equals((String)hm.get("Sender")) )
+                    continue;
+
+            if (!p.matcher(s.getMessageBody()).matches())
+                continue;
+
+            return true;
+        }
+
+        failureReason = "Couldn't match Sender nor body";
+        return false;
+    }
+
+    @Override
+    public String getFailureReason() {
+        return failureReason;
+    }
+
+    private SmsMessage[] getIntentMessagesCompat(Intent intent){
+        SmsMessage[] messages = null;
+
+        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+            messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
+            for (SmsMessage smsMessage : messages) {
+                String messageBody = smsMessage.getMessageBody();
+            }
+        } else { //FIXME: Never tested
+            Bundle bundle = intent.getExtras();
+            if (bundle != null) {
+                try {
+                    Object[] pdus = (Object[]) bundle.get("pdus");
+                    messages  = new SmsMessage[pdus.length];
+                    for (int i = 0; i < messages .length; i++) {
+                        messages [i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
+                    }
+                } catch (Exception ex) {
+                    ex.printStackTrace();
+                }
+            }
+        }
+
+        return messages;
+    }
+}