Finished activities. Fixed some bugs. Added scopes for preferences. Sill need to implement dynamic event activity.

This commit is contained in:
nightoftune 2019-01-18 18:43:21 +01:00
parent c6b20ea534
commit 85c3d40f52
38 changed files with 908 additions and 686 deletions

View File

@ -56,7 +56,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandPreferencesActivity;
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.TaskerActivity;
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
@ -498,7 +498,7 @@ public class SettingsActivity extends AbstractSettingsActivity {
}
});
findPreference(TaskerConstants.TASKER).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
findPreference(TaskerConstants.ACTIVITY_TASKER).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent enableIntent = new Intent(SettingsActivity.this, TaskerActivity.class);

View File

@ -16,21 +16,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.devices.xwatch;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.AbstractTaskerSpec;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.TaskerSettings;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerSpec;
public class XWatchService {
public static final UUID UUID_NOTIFY = UUID.fromString("0000fff7-0000-1000-8000-00805f9b34fb");
public static final UUID UUID_SERVICE = UUID.fromString("0000fff0-0000-1000-8000-00805f9b34fb");

View File

@ -7,7 +7,7 @@ import java.util.Arrays;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.AbstractTaskerSpec;
import nodomain.freeyourgadget.gadgetbridge.tasker.spec.AbstractTaskerSpec;
public class XWatchTaskerSpec extends AbstractTaskerSpec {

View File

@ -40,7 +40,6 @@ import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchConstants;
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchService;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
@ -60,12 +59,9 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSuppo
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceStateAction;
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.DeviceInfo;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerBleProfile;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.task.TaskerTaskProvider;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerService;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEvent;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerBleProfile;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerDevice;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class XWatchSupport extends AbstractBTLEDeviceSupport {
@ -82,7 +78,7 @@ public class XWatchSupport extends AbstractBTLEDeviceSupport {
addSupportedService(XWatchService.UUID_SERVICE);
addSupportedService(XWatchService.UUID_WRITE);
addSupportedService(XWatchService.UUID_NOTIFY);
addSupportedProfile(new TaskerBleProfile<>(this, TaskerConstants.TaskerDevice.XWATCH));
addSupportedProfile(new TaskerBleProfile<>(this, TaskerDevice.XWATCH));
}
public static byte[] crcChecksum(byte[] data) {

View File

@ -1,5 +1,14 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.event;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.TaskerSettings;
/**
* Tasker event that gets thrown if its corresponding {@link TaskerSettings#isEnabled()} is true.
* <p>
* Provides {@link TaskerEventType} and a count.
* <p>
* Count resets itself after {@link TaskerSettings#getThreshold()} is expired.
*/
public class TaskerEvent {
private TaskerEventType type;
@ -10,6 +19,11 @@ public class TaskerEvent {
this.count = count;
}
/**
* Tasker event type of this event.
*
* @return
*/
public TaskerEventType getType() {
return type;
}
@ -18,6 +32,11 @@ public class TaskerEvent {
this.type = type;
}
/**
* Count how often this event is thrown in the {@link TaskerSettings#getThreshold()}
*
* @return Fired times
*/
public int getCount() {
return count;
}

View File

@ -7,6 +7,14 @@ import java.util.Objects;
import nodomain.freeyourgadget.gadgetbridge.R;
/**
* Default set of tasker events.
* <p>
* Extend here if you want to add more events. Use {@link TaskerEventType#create(String)}
* and configure {@link TaskerEventType#withLocalization(int)} for {@link nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.TaskerEventsActivity}
* <p>
* Don't forget to add the new event to {@link #getTypes()} method.
*/
public class TaskerEventType implements Serializable {
public static TaskerEventType BUTTON = TaskerEventType.create("button").withLocalization(R.string.tasker_event_button);
@ -63,12 +71,11 @@ public class TaskerEventType implements Serializable {
if (o == null || getClass() != o.getClass()) return false;
TaskerEventType that = (TaskerEventType) o;
return index == that.index &&
type == that.type;
Objects.equals(type, that.type);
}
@Override
public int hashCode() {
return Objects.hash(type, index);
}
}

View File

@ -1,5 +1,10 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.service;
package nodomain.freeyourgadget.gadgetbridge.tasker.plugin;
/**
* Tasker action codes.
*
* @see <a herf="https://tasker.joaoapps.com/invoketasks.html">Tasker invoke tasks</a> for more information.
*/
public class TaskerActionCodes {
public static final int NONE = -1;

View File

@ -1,4 +1,4 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.service;
package nodomain.freeyourgadget.gadgetbridge.tasker.plugin;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
@ -6,7 +6,11 @@ import android.bluetooth.BluetoothGattCharacteristic;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.AbstractBleProfile;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.NoTaskDefinedException;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.SpecTaskerService;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerUtil;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.TaskerSettings;
import nodomain.freeyourgadget.gadgetbridge.tasker.spec.TaskerSpec;
/**
* Tasker plugin hook as BLE profile.
@ -18,9 +22,9 @@ import nodomain.freeyourgadget.gadgetbridge.tasker.settings.TaskerSettings;
public class TaskerBleProfile<T extends AbstractBTLEDeviceSupport> extends AbstractBleProfile<T> {
private SpecTaskerService taskerService;
private TaskerConstants.TaskerDevice taskerDevice;
private TaskerDevice taskerDevice;
public TaskerBleProfile(T support, TaskerConstants.TaskerDevice taskerDevice) {
public TaskerBleProfile(T support, TaskerDevice taskerDevice) {
super(support);
this.taskerDevice = taskerDevice;
taskerService = new SpecTaskerService(taskerDevice.getSpec());

View File

@ -0,0 +1,84 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.plugin;
import java.util.ArrayList;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
/**
* Tasker constants.
*/
public class TaskerConstants {
/**
* Tasker intent's between {@link nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity}'s.
*/
public static final String INTENT_DEVICE = "int_tasker_device";
public static final String INTENT_EVENT = "int_tasker_event";
/**
* Correspond to {@link nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.TaskerActivity}
*/
public static final String ACTIVITY_TASKER = "act_tasker";
public static final String ACTIVITY_TASKER_ENABLED = "act_tasker_enabled";
public static final String ACTIVITY_TASKER_GROUP = "act_tasker_group";
/**
* Correspond to {@link nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.TaskerEventsActivity}
*/
public static final String ACTIVITY_EVENT_GROUP = "act_event_group";
/**
* Correspond to {@link nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.TaskerEventActivity}.
*/
public static final String ACTIVITY_TASK_ADD = "act_tasker_task_add";
public static final ScopedString ACTIVITY_THRESHOLD = new ScopedString("act_tasker_threshold");
public static final ScopedString ACTIVITY_TASK = new ScopedString("act_tasker_task");
public static final ScopedString ACTIVITY_THRESHOLD_ENABLED = new ScopedString("act_tasker_threshold_enabled");
public static final ScopedString ACTIVITY_TASKS = new ScopedString("act_tasker_task_group");
public static final ScopedString ACTIVITY_EVENT_ENABLED = new ScopedString("act_tasker_event_enabled");
public static class ScopedString {
private String constant;
private List<String> scopes;
private ScopedString(String constant) {
this.constant = constant;
}
public ScopedString withScope(String scope) {
ScopedString scoped = new ScopedString(constant);
List<String> addScope;
if (scopes == null) {
addScope = new ArrayList<>();
} else {
addScope = new ArrayList<>(scopes);
}
addScope.add(scope);
scoped.scopes = addScope;
return scoped;
}
public String getConstant() {
return constant;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(constant);
if (scopes != null && !scopes.isEmpty()) {
for (String scope : scopes) {
if (!StringUtils.isEmpty(scope)) {
continue;
}
if (scopes.indexOf(scope) < scope.length() - 1) {
builder.append("_");
}
builder.append(scopes);
}
}
return builder.toString();
}
}
}

View File

@ -0,0 +1,33 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.plugin;
import java.io.Serializable;
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchTaskerSpec;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.tasker.spec.TaskerSpec;
/**
* Tasker devices with corresponding {@link nodomain.freeyourgadget.gadgetbridge.impl.GBDevice}.
* <p>
* Add new devices here! Provide a {@link TaskerSpec} and your ready to go.
*/
public enum TaskerDevice implements Serializable {
XWATCH(DeviceType.XWATCH, new XWatchTaskerSpec());
private DeviceType type;
private TaskerSpec spec;
TaskerDevice(DeviceType type, TaskerSpec spec) {
this.type = type;
this.spec = spec;
}
public DeviceType getType() {
return type;
}
public TaskerSpec getSpec() {
return spec;
}
}

View File

@ -0,0 +1,452 @@
// Version 1.3.3
// Changelog
// Version 1.3.3
// - increased MAX_NO_ARGS to 10
// Version 1.3.2
// - bug setting app arg
// - pulled provider column names out of function
// For usage examples see http://tasker.dinglisch.net/invoketasks.html
package nodomain.freeyourgadget.gadgetbridge.tasker.plugin;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.PatternMatcher;
import android.os.Process;
import android.util.Log;
/**
* Tasker {@link Intent}'s.
*
* @see <a herf="https://tasker.joaoapps.com/invoketasks.html">Tasker invoke tasks</a> for more information.
*/
public class TaskerIntent extends Intent {
// 3 Tasker versions
public final static String TASKER_PACKAGE = "net.dinglisch.android.tasker";
public final static String TASKER_PACKAGE_MARKET = TASKER_PACKAGE + "m";
public final static String TASKER_PACKAGE_CUPCAKE = TASKER_PACKAGE + "cupcake";
// Play Store download URLs
public final static String MARKET_DOWNLOAD_URL_PREFIX = "market://details?id=";
private final static String TASKER_MARKET_URL = MARKET_DOWNLOAD_URL_PREFIX + TASKER_PACKAGE_MARKET;
private final static String TASKER_MARKET_URL_CUPCAKE = MARKET_DOWNLOAD_URL_PREFIX + TASKER_PACKAGE_CUPCAKE;
// Direct-purchase version
private final static String TASKER_DOWNLOAD_URL = "http://tasker.dinglisch.net/download.html";
// Intent actions
public final static String ACTION_TASK = TASKER_PACKAGE + ".ACTION_TASK";
public final static String ACTION_TASK_COMPLETE = TASKER_PACKAGE + ".ACTION_TASK_COMPLETE";
public final static String ACTION_TASK_SELECT = TASKER_PACKAGE + ".ACTION_TASK_SELECT";
// Intent parameters
public final static String EXTRA_ACTION_INDEX_PREFIX = "action";
public final static String TASK_NAME_DATA_SCHEME = "task";
public final static String EXTRA_TASK_NAME = "task_name";
public final static String EXTRA_TASK_PRIORITY = "task_priority";
public final static String EXTRA_SUCCESS_FLAG = "success";
public final static String EXTRA_VAR_NAMES_LIST = "varNames";
public final static String EXTRA_VAR_VALUES_LIST = "varValues";
public final static String EXTRA_TASK_OUTPUT = "output";
// Content provider columns
public static final String PROVIDER_COL_NAME_EXTERNAL_ACCESS = "ext_access";
public static final String PROVIDER_COL_NAME_ENABLED = "enabled";
// DEPRECATED, use EXTRA_VAR_NAMES_LIST, EXTRA_VAR_VALUES_LIST
public final static String EXTRA_PARAM_LIST = "params";
// Intent data
public final static String TASK_ID_SCHEME = "id";
// For particular actions
public final static String DEFAULT_ENCRYPTION_KEY = "default";
public final static String ENCRYPTED_AFFIX = "tec";
public final static int MAX_NO_ARGS = 10;
// Bundle keys
// Only useful for Tasker
public final static String ACTION_CODE = "action";
public final static String APP_ARG_PREFIX = "app:";
public final static String ICON_ARG_PREFIX = "icn:";
public final static String ARG_INDEX_PREFIX = "arg:";
public static final String PARAM_VAR_NAME_PREFIX = "par";
// Misc
private final static String PERMISSION_RUN_TASKS = TASKER_PACKAGE + ".PERMISSION_RUN_TASKS";
public final static String ACTION_OPEN_PREFS = TASKER_PACKAGE + ".ACTION_OPEN_PREFS";
public final static String EXTRA_OPEN_PREFS_TAB_NO = "tno";
private final static int MISC_PREFS_TAB_NO = 3; // 0 based
// To query whether Tasker is enabled and external access is enabled
private final static String TASKER_PREFS_URI = "content://" + TASKER_PACKAGE + "/prefs";
private final static int CUPCAKE_SDK_VERSION = 3;
// result values for TestSend
// NotInstalled: Tasker package not found on device
// NoPermission: calling app does not have permission PERMISSION_RUN_TASKS
// NotEnabled: Tasker is not enabled
// AccessBlocked: user prefs disallow external access
// NoReceiver: Tasker has not created a listener for external access (probably a Tasker bug)
// OK: you should be able to send a task to run. Still need to listen for result
// for e.g. task not found
public static enum Status {NotInstalled, NoPermission, NotEnabled, AccessBlocked, NoReceiver, OK}
;
// -------------------------- PRIVATE VARS ---------------------------- //
private final static String TAG = "TaskerIntent";
private final static String EXTRA_INTENT_VERSION_NUMBER = "version_number";
private final static String INTENT_VERSION_NUMBER = "1.1";
// Inclusive values
private final static int MIN_PRIORITY = 0;
private final static int MAX_PRIORITY = 10;
// For generating random names
private static Random rand = new Random();
// Tracking state
private int actionCount = 0;
private int argCount;
// -------------------------- PUBLIC METHODS ---------------------------- //
public static int getMaxPriority() {
return MAX_PRIORITY;
}
public static boolean validatePriority(int pri) {
return (
(pri >= MIN_PRIORITY) ||
(pri <= MAX_PRIORITY)
);
}
// Tasker has different package names for Play Store and non- versions
// for historical reasons
public static String getInstalledTaskerPackage(Context context) {
String foundPackage = null;
try {
context.getPackageManager().getPackageInfo(TASKER_PACKAGE, 0);
foundPackage = TASKER_PACKAGE;
} catch (PackageManager.NameNotFoundException e) {
}
try {
context.getPackageManager().getPackageInfo(TASKER_PACKAGE_MARKET, 0);
foundPackage = TASKER_PACKAGE_MARKET;
} catch (PackageManager.NameNotFoundException e) {
}
return foundPackage;
}
// test we can send a TaskerIntent to Tasker
// use *before* sending an intent
// still need to test the *result after* sending intent
public static Status testStatus(Context c) {
Status result;
if (!taskerInstalled(c))
result = Status.NotInstalled;
else if (!havePermission(c))
result = Status.NoPermission;
else if (!TaskerIntent.prefSet(c, PROVIDER_COL_NAME_ENABLED))
result = Status.NotEnabled;
else if (!TaskerIntent.prefSet(c, PROVIDER_COL_NAME_EXTERNAL_ACCESS))
result = Status.AccessBlocked;
else if (!new TaskerIntent("").receiverExists(c))
result = Status.NoReceiver;
else
result = Status.OK;
return result;
}
// Check if Tasker installed
public static boolean taskerInstalled(Context context) {
return (getInstalledTaskerPackage(context) != null);
}
// Use with startActivity to retrieve Tasker from Android market
public static Intent getTaskerInstallIntent(boolean marketFlag) {
return new Intent(
Intent.ACTION_VIEW,
Uri.parse(
marketFlag ?
((SDKVersion() == CUPCAKE_SDK_VERSION) ? TASKER_MARKET_URL_CUPCAKE : TASKER_MARKET_URL) :
TASKER_DOWNLOAD_URL
)
);
}
public static int SDKVersion() {
try {
Field f = android.os.Build.VERSION.class.getField("SDK_INT");
return f.getInt(null);
} catch (Exception e) {
return CUPCAKE_SDK_VERSION;
}
}
public static IntentFilter getCompletionFilter(String taskName) {
IntentFilter filter = new IntentFilter(TaskerIntent.ACTION_TASK_COMPLETE);
filter.addDataScheme(TASK_NAME_DATA_SCHEME);
filter.addDataPath(taskName, PatternMatcher.PATTERN_LITERAL);
return filter;
}
public static Intent getTaskSelectIntent() {
return new Intent(ACTION_TASK_SELECT).
setFlags(
Intent.FLAG_ACTIVITY_NO_USER_ACTION |
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
Intent.FLAG_ACTIVITY_NO_HISTORY
);
}
// public access deprecated, use TaskerIntent.testSend() instead
public static boolean havePermission(Context c) {
return c.checkPermission(PERMISSION_RUN_TASKS, Process.myPid(), Process.myUid()) ==
PackageManager.PERMISSION_GRANTED;
}
// Get an intent that will bring up the Tasker prefs screen with the External Access control(s)
// Probably you want to use startActivity or startActivityForResult with it
public static Intent getExternalAccessPrefsIntent() {
return new Intent(ACTION_OPEN_PREFS).putExtra(EXTRA_OPEN_PREFS_TAB_NO, MISC_PREFS_TAB_NO);
}
// ------------------------------------- INSTANCE METHODS ----------------------------- //
public TaskerIntent() {
super(ACTION_TASK);
setRandomData();
putMetaExtras(getRandomString());
}
public TaskerIntent(String taskName) {
super(ACTION_TASK);
setRandomData();
putMetaExtras(taskName);
}
public TaskerIntent setTaskPriority(int priority) {
if (validatePriority(priority))
putExtra(EXTRA_TASK_PRIORITY, priority);
else
Log.e(TAG, "priority out of range: " + MIN_PRIORITY + ":" + MAX_PRIORITY);
return this;
}
// Sets subsequently %par1, %par2 etc
public TaskerIntent addParameter(String value) {
int index = 1;
if (getExtras().containsKey(EXTRA_VAR_NAMES_LIST))
index = getExtras().getStringArrayList(EXTRA_VAR_NAMES_LIST).size() + 1;
Log.d(TAG, "index: " + index);
addLocalVariable("%" + PARAM_VAR_NAME_PREFIX + index, value);
return this;
}
// Arbitrary specification of (local) variable names and values
public TaskerIntent addLocalVariable(String name, String value) {
ArrayList<String> names, values;
if (hasExtra(EXTRA_VAR_NAMES_LIST)) {
names = getStringArrayListExtra(EXTRA_VAR_NAMES_LIST);
values = getStringArrayListExtra(EXTRA_VAR_VALUES_LIST);
} else {
names = new ArrayList<String>();
values = new ArrayList<String>();
putStringArrayListExtra(EXTRA_VAR_NAMES_LIST, names);
putStringArrayListExtra(EXTRA_VAR_VALUES_LIST, values);
}
names.add(name);
values.add(value);
return this;
}
public TaskerIntent addAction(int code) {
actionCount++;
argCount = 1;
Bundle actionBundle = new Bundle();
actionBundle.putInt(ACTION_CODE, code);
// Add action bundle to intent
putExtra(EXTRA_ACTION_INDEX_PREFIX + Integer.toString(actionCount), actionBundle);
return this;
}
// string arg
public TaskerIntent addArg(String arg) {
Bundle b = getActionBundle();
if (b != null)
b.putString(ARG_INDEX_PREFIX + Integer.toString(argCount++), arg);
return this;
}
// int arg
public TaskerIntent addArg(int arg) {
Bundle b = getActionBundle();
if (b != null)
b.putInt(ARG_INDEX_PREFIX + Integer.toString(argCount++), arg);
return this;
}
// boolean arg
public TaskerIntent addArg(boolean arg) {
Bundle b = getActionBundle();
if (b != null)
b.putBoolean(ARG_INDEX_PREFIX + Integer.toString(argCount++), arg);
return this;
}
// Application arg
public TaskerIntent addArg(String pkg, String cls) {
Bundle b = getActionBundle();
if (b != null) {
StringBuilder builder = new StringBuilder();
builder.append(APP_ARG_PREFIX).
append(pkg).append(",").append(cls);
b.putString(ARG_INDEX_PREFIX + Integer.toString(argCount++), builder.toString());
}
return this;
}
public IntentFilter getCompletionFilter() {
return getCompletionFilter(getTaskName());
}
public String getTaskName() {
return getStringExtra(EXTRA_TASK_NAME);
}
public boolean receiverExists(Context context) {
List<ResolveInfo> recs = context.getPackageManager().queryBroadcastReceivers(this, 0);
return (
(recs != null) &&
(recs.size() > 0)
);
}
// -------------------- PRIVATE METHODS -------------------- //
private String getRandomString() {
return Long.toString(rand.nextLong());
}
// so that if multiple TaskerIntents are used in PendingIntents there's virtually no
// clash chance
private void setRandomData() {
setData(Uri.parse(TASK_ID_SCHEME + ":" + getRandomString()));
}
private Bundle getActionBundle() {
Bundle toReturn = null;
if (argCount > MAX_NO_ARGS)
Log.e(TAG, "maximum number of arguments exceeded (" + MAX_NO_ARGS + ")");
else {
String key = EXTRA_ACTION_INDEX_PREFIX + Integer.toString(actionCount);
if (this.hasExtra(key))
toReturn = getBundleExtra(key);
else
Log.e(TAG, "no actions added yet");
}
return toReturn;
}
private void putMetaExtras(String taskName) {
putExtra(EXTRA_INTENT_VERSION_NUMBER, INTENT_VERSION_NUMBER);
putExtra(EXTRA_TASK_NAME, taskName);
}
// for testing that Tasker is enabled and external access is allowed
private static boolean prefSet(Context context, String col) {
String[] proj = new String[]{col};
Cursor c = context.getContentResolver().query(Uri.parse(TASKER_PREFS_URI), proj, null, null, null);
boolean acceptingFlag = false;
if (c == null)
Log.w(TAG, "no cursor for " + TASKER_PREFS_URI);
else {
c.moveToFirst();
if (Boolean.TRUE.toString().equals(c.getString(0)))
acceptingFlag = true;
c.close();
}
return acceptingFlag;
}
}

View File

@ -6,8 +6,10 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.SettingSupplier;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.SettingSupplierImpl;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerIntent;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.SettingSupplier;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.SettingSupplierImpl;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.task.TaskerTask;
import nodomain.freeyourgadget.gadgetbridge.tasker.task.TaskerTaskProvider;
@ -28,17 +30,28 @@ public abstract class AbstractTaskerService {
this.enabled = new SettingSupplierImpl<Boolean>() {
@Override
public Boolean get() {
return GBApplication.getPrefs().getBoolean(TaskerConstants.TASKER_ENABLED, false);
return GBApplication.getPrefs().getBoolean(TaskerConstants.ACTIVITY_TASKER_ENABLED, false);
}
};
}
public boolean isActive() {
public boolean isEnabled() {
return enabled.get();
}
/**
* Schedules tasker task for {@link TaskerEventType} if
* {@link #isEnabled()},
* {@link #isReady()} and
* event type is not {@link TaskerEventType#NO_OP}.
* <p>
* Uses {@link #DEFAULT_THRESHOLD} of '50' milliseconds if threshold is not set.
*
* @param type
* @return
*/
public boolean runForType(TaskerEventType type) {
if (type != null && !TaskerEventType.NO_OP.equals(type) && isActive() && ready()) {
if (type != null && !TaskerEventType.NO_OP.equals(type) && isEnabled() && isReady()) {
if (!tasks.containsKey(type)) {
SettingSupplier<TaskerTaskProvider> taskProvider = taskProvider(type);
if (taskProvider.isPresent()) {
@ -56,7 +69,12 @@ public abstract class AbstractTaskerService {
protected abstract SettingSupplier<TaskerTaskProvider> taskProvider(TaskerEventType type);
public static boolean ready() {
/**
* Determines of tasker is installed and ready.
*
* @return True if installed and ready
*/
public static boolean isReady() {
return TaskerIntent.testStatus(GBApplication.getContext()).equals(TaskerIntent.Status.OK);
}

View File

@ -1,5 +1,8 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.service;
/**
* Gets thrown if tasker is enabled but no task name is defined. Triggers {@link TaskerUtil#noTaskDefinedInformation()}.
*/
public class NoTaskDefinedException extends RuntimeException {
public NoTaskDefinedException() {

View File

@ -1,11 +1,12 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.service;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.SettingSupplier;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.SettingSupplier;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.spec.TaskerSpec;
import nodomain.freeyourgadget.gadgetbridge.tasker.task.TaskerTaskProvider;
/**
* {@link TaskerSpec} impl for {@link AbstractTaskerService}.
* {@link TaskerSpec} implementation for {@link TaskerService}.
*/
public class SpecTaskerService extends AbstractTaskerService {

View File

@ -1,12 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.service;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.TaskerSettings;
public abstract class TaskerAbstractSpec implements TaskerSpec {
@Override
public TaskerSettings getSettings(TaskerEventType eventType) {
return null;
}
}

View File

@ -1,78 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.service;
import java.io.Serializable;
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchConstants;
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchService;
import nodomain.freeyourgadget.gadgetbridge.devices.xwatch.XWatchTaskerSpec;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class TaskerConstants {
private static final String tasker = "tasker";
public static final String TASKER = "pref_key_tasker";
public static final String TASKER_SETTINGS = "pref_key_tasker_settings";
public static final String TASKER_ENABLED = "tasker_enabled";
public static final String TASKER_PREFERENCES = "tasker_preferences";
public static final String TASKER_PREF_GROUP = "pref_key_tasker_group";
public static final String DEVICE_INTENT = "intent_tasker_device";
public static final String EVENT_INTENT = "intent_tasker_event";
public static final String TASKER_TASK = "tasker-task";
public static final String TASKER_PREFERENCE = "tasker_list";
public static final String PREF_EVENT_GROUP = "pref_key_tasker_event_group";
public static final String ACTIVITY_THRESHOLD = "act_tasker_threshold";
public static final String ACTIVITY_TASK_ADD = "act_tasker_task_add";
public static final String ACTIVITY_TASK = "act_tasker_task";
public static final String ACTIVITY_THESHOLD_ENABELD = "act_tasker_threshold_enabled";
public static final String ACTIVITY_TASKS = "act_tasker_task_group";
public enum TaskerDevice implements Serializable {
XWATCH(DeviceType.XWATCH, new XWatchTaskerSpec());
private DeviceType type;
private TaskerSpec spec;
TaskerDevice(DeviceType type, TaskerSpec spec) {
this.type = type;
this.spec = spec;
}
public DeviceType getType() {
return type;
}
public TaskerSpec getSpec() {
return spec;
}
}
// public static class Settings {
//
// private static final String setting = "setting";
// public static final String ENABLED = concate(tasker, setting, "enabled");
// public static final String ENABLED = "tasker_enabled";
//
// }
//
// public static class Preferences {
// private static final String prefKey = "pref_key";
// public static final String TASKER = concate(prefKey, "tasker");
// public static final String TASKER_SETTINGS = concate(prefKey, "tasker", "settings");
// }
private static String concate(String... parts) {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
builder.append(parts[i]);
if (i < parts.length - 1) {
builder.append("_");
}
}
return builder.toString();
}
}

View File

@ -1,449 +0,0 @@
// Version 1.3.3
// Changelog
// Version 1.3.3
// - increased MAX_NO_ARGS to 10
// Version 1.3.2
// - bug setting app arg
// - pulled provider column names out of function
// For usage examples see http://tasker.dinglisch.net/invoketasks.html
package nodomain.freeyourgadget.gadgetbridge.tasker.service;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.PatternMatcher;
import android.os.Process;
import android.util.Log;
public class TaskerIntent extends Intent {
// 3 Tasker versions
public final static String TASKER_PACKAGE = "net.dinglisch.android.tasker";
public final static String TASKER_PACKAGE_MARKET = TASKER_PACKAGE + "m";
public final static String TASKER_PACKAGE_CUPCAKE = TASKER_PACKAGE + "cupcake";
// Play Store download URLs
public final static String MARKET_DOWNLOAD_URL_PREFIX = "market://details?id=";
private final static String TASKER_MARKET_URL = MARKET_DOWNLOAD_URL_PREFIX + TASKER_PACKAGE_MARKET;
private final static String TASKER_MARKET_URL_CUPCAKE = MARKET_DOWNLOAD_URL_PREFIX + TASKER_PACKAGE_CUPCAKE;
// Direct-purchase version
private final static String TASKER_DOWNLOAD_URL = "http://tasker.dinglisch.net/download.html";
// Intent actions
public final static String ACTION_TASK = TASKER_PACKAGE + ".ACTION_TASK";
public final static String ACTION_TASK_COMPLETE = TASKER_PACKAGE + ".ACTION_TASK_COMPLETE";
public final static String ACTION_TASK_SELECT = TASKER_PACKAGE + ".ACTION_TASK_SELECT";
// Intent parameters
public final static String EXTRA_ACTION_INDEX_PREFIX = "action";
public final static String TASK_NAME_DATA_SCHEME = "task";
public final static String EXTRA_TASK_NAME = "task_name";
public final static String EXTRA_TASK_PRIORITY = "task_priority";
public final static String EXTRA_SUCCESS_FLAG = "success";
public final static String EXTRA_VAR_NAMES_LIST = "varNames";
public final static String EXTRA_VAR_VALUES_LIST = "varValues";
public final static String EXTRA_TASK_OUTPUT = "output";
// Content provider columns
public static final String PROVIDER_COL_NAME_EXTERNAL_ACCESS = "ext_access";
public static final String PROVIDER_COL_NAME_ENABLED = "enabled";
// DEPRECATED, use EXTRA_VAR_NAMES_LIST, EXTRA_VAR_VALUES_LIST
public final static String EXTRA_PARAM_LIST = "params";
// Intent data
public final static String TASK_ID_SCHEME = "id";
// For particular actions
public final static String DEFAULT_ENCRYPTION_KEY= "default";
public final static String ENCRYPTED_AFFIX = "tec";
public final static int MAX_NO_ARGS = 10;
// Bundle keys
// Only useful for Tasker
public final static String ACTION_CODE = "action";
public final static String APP_ARG_PREFIX = "app:";
public final static String ICON_ARG_PREFIX = "icn:";
public final static String ARG_INDEX_PREFIX = "arg:";
public static final String PARAM_VAR_NAME_PREFIX = "par";
// Misc
private final static String PERMISSION_RUN_TASKS = TASKER_PACKAGE + ".PERMISSION_RUN_TASKS";
public final static String ACTION_OPEN_PREFS = TASKER_PACKAGE + ".ACTION_OPEN_PREFS";
public final static String EXTRA_OPEN_PREFS_TAB_NO = "tno";
private final static int MISC_PREFS_TAB_NO = 3; // 0 based
// To query whether Tasker is enabled and external access is enabled
private final static String TASKER_PREFS_URI = "content://" + TASKER_PACKAGE + "/prefs";
private final static int CUPCAKE_SDK_VERSION = 3;
// result values for TestSend
// NotInstalled: Tasker package not found on device
// NoPermission: calling app does not have permission PERMISSION_RUN_TASKS
// NotEnabled: Tasker is not enabled
// AccessBlocked: user prefs disallow external access
// NoReceiver: Tasker has not created a listener for external access (probably a Tasker bug)
// OK: you should be able to send a task to run. Still need to listen for result
// for e.g. task not found
public static enum Status { NotInstalled, NoPermission, NotEnabled, AccessBlocked, NoReceiver, OK };
// -------------------------- PRIVATE VARS ---------------------------- //
private final static String TAG = "TaskerIntent";
private final static String EXTRA_INTENT_VERSION_NUMBER = "version_number";
private final static String INTENT_VERSION_NUMBER = "1.1";
// Inclusive values
private final static int MIN_PRIORITY = 0;
private final static int MAX_PRIORITY = 10;
// For generating random names
private static Random rand = new Random();
// Tracking state
private int actionCount = 0;
private int argCount;
// -------------------------- PUBLIC METHODS ---------------------------- //
public static int getMaxPriority() {
return MAX_PRIORITY;
}
public static boolean validatePriority( int pri ) {
return (
( pri >= MIN_PRIORITY ) ||
( pri <= MAX_PRIORITY )
);
}
// Tasker has different package names for Play Store and non- versions
// for historical reasons
public static String getInstalledTaskerPackage( Context context ) {
String foundPackage = null;
try {
context.getPackageManager().getPackageInfo( TASKER_PACKAGE, 0 );
foundPackage = TASKER_PACKAGE;
}
catch ( PackageManager.NameNotFoundException e ) {
}
try {
context.getPackageManager().getPackageInfo( TASKER_PACKAGE_MARKET, 0 );
foundPackage = TASKER_PACKAGE_MARKET;
}
catch ( PackageManager.NameNotFoundException e ) {
}
return foundPackage;
}
// test we can send a TaskerIntent to Tasker
// use *before* sending an intent
// still need to test the *result after* sending intent
public static Status testStatus( Context c ) {
Status result;
if ( ! taskerInstalled( c ) )
result = Status.NotInstalled;
else if ( ! havePermission( c ) )
result = Status.NoPermission;
else if ( ! TaskerIntent.prefSet( c, PROVIDER_COL_NAME_ENABLED ) )
result = Status.NotEnabled;
else if ( ! TaskerIntent.prefSet( c, PROVIDER_COL_NAME_EXTERNAL_ACCESS ) )
result = Status.AccessBlocked;
else if ( ! new TaskerIntent( "" ).receiverExists( c ) )
result = Status.NoReceiver;
else
result = Status.OK;
return result;
}
// Check if Tasker installed
public static boolean taskerInstalled( Context context ) {
return ( getInstalledTaskerPackage( context ) != null );
}
// Use with startActivity to retrieve Tasker from Android market
public static Intent getTaskerInstallIntent( boolean marketFlag ) {
return new Intent(
Intent.ACTION_VIEW,
Uri.parse(
marketFlag ?
( ( SDKVersion() == CUPCAKE_SDK_VERSION ) ? TASKER_MARKET_URL_CUPCAKE : TASKER_MARKET_URL ) :
TASKER_DOWNLOAD_URL
)
);
}
public static int SDKVersion() {
try {
Field f = android.os.Build.VERSION.class.getField( "SDK_INT" );
return f.getInt( null );
}
catch ( Exception e ) {
return CUPCAKE_SDK_VERSION;
}
}
public static IntentFilter getCompletionFilter( String taskName ) {
IntentFilter filter = new IntentFilter( TaskerIntent.ACTION_TASK_COMPLETE );
filter.addDataScheme( TASK_NAME_DATA_SCHEME );
filter.addDataPath( taskName, PatternMatcher.PATTERN_LITERAL );
return filter;
}
public static Intent getTaskSelectIntent() {
return new Intent( ACTION_TASK_SELECT ).
setFlags(
Intent.FLAG_ACTIVITY_NO_USER_ACTION |
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS |
Intent.FLAG_ACTIVITY_NO_HISTORY
);
}
// public access deprecated, use TaskerIntent.testSend() instead
public static boolean havePermission( Context c ) {
return c.checkPermission( PERMISSION_RUN_TASKS, Process.myPid(), Process.myUid() ) ==
PackageManager.PERMISSION_GRANTED;
}
// Get an intent that will bring up the Tasker prefs screen with the External Access control(s)
// Probably you want to use startActivity or startActivityForResult with it
public static Intent getExternalAccessPrefsIntent() {
return new Intent( ACTION_OPEN_PREFS ).putExtra( EXTRA_OPEN_PREFS_TAB_NO, MISC_PREFS_TAB_NO );
}
// ------------------------------------- INSTANCE METHODS ----------------------------- //
public TaskerIntent() {
super( ACTION_TASK );
setRandomData();
putMetaExtras( getRandomString() );
}
public TaskerIntent( String taskName ) {
super( ACTION_TASK );
setRandomData();
putMetaExtras( taskName );
}
public TaskerIntent setTaskPriority( int priority ) {
if ( validatePriority( priority ) )
putExtra( EXTRA_TASK_PRIORITY, priority );
else
Log.e( TAG, "priority out of range: " + MIN_PRIORITY + ":" + MAX_PRIORITY );
return this;
}
// Sets subsequently %par1, %par2 etc
public TaskerIntent addParameter( String value ) {
int index = 1;
if ( getExtras().containsKey( EXTRA_VAR_NAMES_LIST ) )
index = getExtras().getStringArrayList( EXTRA_VAR_NAMES_LIST ).size() + 1;
Log.d(TAG, "index: " + index );
addLocalVariable( "%" + PARAM_VAR_NAME_PREFIX + index, value );
return this;
}
// Arbitrary specification of (local) variable names and values
public TaskerIntent addLocalVariable( String name, String value ) {
ArrayList<String> names, values;
if ( hasExtra( EXTRA_VAR_NAMES_LIST ) ) {
names = getStringArrayListExtra( EXTRA_VAR_NAMES_LIST );
values = getStringArrayListExtra( EXTRA_VAR_VALUES_LIST );
}
else {
names = new ArrayList<String>();
values = new ArrayList<String>();
putStringArrayListExtra( EXTRA_VAR_NAMES_LIST, names );
putStringArrayListExtra( EXTRA_VAR_VALUES_LIST, values );
}
names.add( name );
values.add( value );
return this;
}
public TaskerIntent addAction( int code ) {
actionCount++;
argCount = 1;
Bundle actionBundle = new Bundle();
actionBundle.putInt( ACTION_CODE, code );
// Add action bundle to intent
putExtra( EXTRA_ACTION_INDEX_PREFIX + Integer.toString( actionCount ), actionBundle );
return this;
}
// string arg
public TaskerIntent addArg( String arg ) {
Bundle b = getActionBundle();
if ( b != null )
b.putString( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), arg );
return this;
}
// int arg
public TaskerIntent addArg( int arg ) {
Bundle b = getActionBundle();
if ( b != null )
b.putInt( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), arg );
return this;
}
// boolean arg
public TaskerIntent addArg( boolean arg ) {
Bundle b = getActionBundle();
if ( b != null )
b.putBoolean( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), arg );
return this;
}
// Application arg
public TaskerIntent addArg( String pkg, String cls ) {
Bundle b = getActionBundle();
if ( b != null ) {
StringBuilder builder = new StringBuilder();
builder.append( APP_ARG_PREFIX ).
append( pkg ). append( "," ). append( cls );
b.putString( ARG_INDEX_PREFIX + Integer.toString( argCount++ ), builder.toString() );
}
return this;
}
public IntentFilter getCompletionFilter() {
return getCompletionFilter( getTaskName() );
}
public String getTaskName() {
return getStringExtra( EXTRA_TASK_NAME );
}
public boolean receiverExists( Context context ) {
List<ResolveInfo> recs = context.getPackageManager().queryBroadcastReceivers( this, 0 );
return (
( recs != null ) &&
( recs.size() > 0 )
);
}
// -------------------- PRIVATE METHODS -------------------- //
private String getRandomString() {
return Long.toString( rand.nextLong() );
}
// so that if multiple TaskerIntents are used in PendingIntents there's virtually no
// clash chance
private void setRandomData() {
setData( Uri.parse( TASK_ID_SCHEME + ":" + getRandomString() ) );
}
private Bundle getActionBundle() {
Bundle toReturn = null;
if ( argCount > MAX_NO_ARGS )
Log.e( TAG, "maximum number of arguments exceeded (" + MAX_NO_ARGS + ")" );
else {
String key = EXTRA_ACTION_INDEX_PREFIX + Integer.toString( actionCount );
if ( this.hasExtra( key ) )
toReturn = getBundleExtra( key );
else
Log.e( TAG, "no actions added yet" );
}
return toReturn;
}
private void putMetaExtras( String taskName ) {
putExtra( EXTRA_INTENT_VERSION_NUMBER, INTENT_VERSION_NUMBER );
putExtra( EXTRA_TASK_NAME, taskName );
}
// for testing that Tasker is enabled and external access is allowed
private static boolean prefSet( Context context, String col ) {
String [] proj = new String [] { col };
Cursor c = context.getContentResolver().query( Uri.parse( TASKER_PREFS_URI ), proj, null, null, null );
boolean acceptingFlag = false;
if ( c == null )
Log.w( TAG, "no cursor for " + TASKER_PREFS_URI );
else {
c.moveToFirst();
if ( Boolean.TRUE.toString().equals( c.getString( 0 ) ) )
acceptingFlag = true;
c.close();
}
return acceptingFlag;
}
}

View File

@ -1,25 +1,18 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.service;
import android.widget.Toast;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Supplier;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.SettingSupplier;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.SettingSupplierImpl;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.SettingSupplier;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.SettingSupplierImpl;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEvent;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.task.TaskerTask;
import nodomain.freeyourgadget.gadgetbridge.tasker.task.TaskerTaskProvider;
/**
* Default impl for {@link AbstractTaskerService}.
* Default implementation for {@link AbstractTaskerService}.
* <p>
* One instance per thread/device! The service is not threadsafe.
* Preferred to use with java based configuration.
*/
public class TaskerService extends AbstractTaskerService {
@ -30,11 +23,25 @@ public class TaskerService extends AbstractTaskerService {
this.enabled = new SettingSupplierImpl<>(enabled);
}
/**
* Set threshold between task calls for {@link TaskerEventType}.
*
* @param type Event
* @param threshold Threshold in milliseconds
* @return Itself
*/
public TaskerService withThreshold(TaskerEventType type, long threshold) {
this.threshold.put(type, new SettingSupplierImpl<>(threshold));
return this;
}
/**
* Sets single task name for {@link TaskerEventType}.
*
* @param type Event
* @param task Single task name
* @return Itself
*/
public TaskerService withTask(TaskerEventType type, final String task) {
typeProvider.put(type, new SettingSupplierImpl<TaskerTaskProvider>(new TaskerTaskProvider() {
@Override
@ -45,13 +52,18 @@ public class TaskerService extends AbstractTaskerService {
return this;
}
/**
* Sets {@link TaskerTaskProvider} for {@link TaskerEventType}.
*
* @param type Event
* @param provider Task name provider
* @return Itself
*/
public TaskerService withProvider(TaskerEventType type, TaskerTaskProvider provider) {
typeProvider.put(type, new SettingSupplierImpl<>(provider));
return this;
}
// Private
protected SettingSupplier<Long> threshold(TaskerEventType type) {
return threshold.get(type);
}

View File

@ -4,6 +4,7 @@ import android.widget.Toast;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerIntent;
/**
* Tasker convenience methods for direct access to tasker without {@link TaskerService}.

View File

@ -1,7 +1,7 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.event;
package nodomain.freeyourgadget.gadgetbridge.tasker.settings;
/**
* Simple supplier.
* Simple setting supplier. Can listen to changes throw {@link SettingListener}.
*
* @param <T> Setting
*/
@ -15,6 +15,11 @@ public interface SettingSupplier<T> {
SettingSupplier<T> onChanged(SettingListener<T> onChanged);
/**
* Listen to changes in {@link SettingSupplier}.
*
* @param <T>
*/
interface SettingListener<T> {
void changed(T object);
}

View File

@ -1,5 +1,10 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.event;
package nodomain.freeyourgadget.gadgetbridge.tasker.settings;
/**
* Default implementation for {@link SettingSupplier}.
*
* @param <T>
*/
public class SettingSupplierImpl<T> implements SettingSupplier<T> {
private T object;
@ -20,7 +25,9 @@ public class SettingSupplierImpl<T> implements SettingSupplier<T> {
@Override
public void set(T object) {
this.object = object;
onChanged.changed(object);
if (onChanged != null) {
onChanged.changed(object);
}
}
@Override

View File

@ -1,16 +1,45 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.settings;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.SettingSupplier;
import nodomain.freeyourgadget.gadgetbridge.tasker.spec.TaskerSpec;
import nodomain.freeyourgadget.gadgetbridge.tasker.task.TaskerTaskProvider;
/**
* Tasker settings. There is one setting per {@link nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType}.
* This is usually wrapped in {@link TaskerSpec}
* and used by {@link nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.TaskerEventActivity} to let the user customize the settings.
* {@link nodomain.freeyourgadget.gadgetbridge.tasker.service.SpecTaskerService} is the out of the box implementation that uses this settings to call tasker.
* <p>
* Extend here for more settings.
*/
public interface TaskerSettings {
/**
* Consumes events or just listens to them.
*
* @return True if consumes events.
*/
SettingSupplier<Boolean> isConsumingEvents();
/**
* Enables the settings.
*
* @return True if settings are enabled.
*/
SettingSupplier<Boolean> isEnabled();
/**
* Threshold for tasker calls. Determines the delay between {@link nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEvent}'s
* and is therefore the main attribute to determine which tasker task is called.
*
* @return Threshold in milliseconds
*/
SettingSupplier<Long> getThreshold();
/**
* {@link TaskerTaskProvider} determines the task names for {@link nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEvent}.
*
* @return Task provider
*/
SettingSupplier<TaskerTaskProvider> getTaskProvider();
}

View File

@ -8,6 +8,11 @@ import android.widget.Button;
import nodomain.freeyourgadget.gadgetbridge.R;
/**
* Simple {@link EditTextPreference} with an button.
* <p>
* Exposes only {@link Button#setOnClickListener(View.OnClickListener)} and {@link Button#setText(int)}
*/
public class ButtonPreference extends EditTextPreference {
private View.OnClickListener onClickListener;
@ -15,6 +20,7 @@ public class ButtonPreference extends EditTextPreference {
public ButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setWidgetLayoutResource(R.layout.button_preference_layout);
}
public ButtonPreference(Context context, AttributeSet attrs) {
@ -35,10 +41,20 @@ public class ButtonPreference extends EditTextPreference {
}
}
/**
* Sets an {@link View.OnClickListener} to the button.
*
* @param clickListener
*/
public void setOnClickListener(View.OnClickListener clickListener) {
this.onClickListener = clickListener;
}
/**
* Set button text with resource id.
*
* @param resourceId {@link R.string}
*/
public void setButtonText(int resourceId) {
if (button != null) {
button.setText(resourceId);

View File

@ -7,16 +7,22 @@ import android.preference.PreferenceCategory;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerDevice;
/**
* Tasker main {@link AbstractSettingsActivity} builds an supported list of {@link TaskerConstants.TaskerDevice}.
* <p>
* Forwards to {@link TaskerEventsActivity}.
*/
public class TaskerActivity extends AbstractSettingsActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.tasker_preferences);
final PreferenceCategory group = (PreferenceCategory) findPreference(TaskerConstants.TASKER_PREF_GROUP);
for (TaskerConstants.TaskerDevice device : TaskerConstants.TaskerDevice.values()) {
final PreferenceCategory group = (PreferenceCategory) findPreference(TaskerConstants.ACTIVITY_TASKER_GROUP);
for (TaskerDevice device : TaskerDevice.values()) {
group.addPreference(preference(device));
}
}
@ -26,14 +32,14 @@ public class TaskerActivity extends AbstractSettingsActivity {
super.onPostCreate(savedInstanceState);
}
private Preference preference(final TaskerConstants.TaskerDevice device) {
private Preference preference(final TaskerDevice device) {
Preference devicePreference = new Preference(this);
devicePreference.setTitle(device.getType().getName());
devicePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent intent = new Intent(TaskerActivity.this, TaskerEventsActivity.class);
intent.putExtra(TaskerConstants.DEVICE_INTENT, device);
intent.putExtra(TaskerConstants.INTENT_DEVICE, device);
startActivity(intent);
return true;
}

View File

@ -4,26 +4,38 @@ import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEvent;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerDevice;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.NoTaskDefinedException;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.TaskerSettings;
import nodomain.freeyourgadget.gadgetbridge.tasker.spec.TaskerSpec;
import nodomain.freeyourgadget.gadgetbridge.tasker.task.TaskerTaskProvider;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
/**
* Tasker event {@link AbstractSettingsActivity} takes {@link TaskerSpec} from {@link TaskerDevice#getSpec()}
* to configure its {@link TaskerSettings} via {@link TaskerSpec#getSettings(TaskerEventType)}.
* <p>
* If you extend {@link TaskerSettings} this is the point to implement the new features for user configuration.
*/
public class TaskerEventActivity extends AbstractSettingsActivity {
private TaskerConstants.TaskerDevice device;
private TaskerDevice device;
private TaskerEventType eventType;
private Prefs prefs = GBApplication.getPrefs();
public TaskerEventActivity() {
}
private List<EditTextPreference> taskPreferences = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -34,16 +46,31 @@ public class TaskerEventActivity extends AbstractSettingsActivity {
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
device = (TaskerConstants.TaskerDevice) getIntent().getSerializableExtra(TaskerConstants.DEVICE_INTENT);
device = (TaskerDevice) getIntent().getSerializableExtra(TaskerConstants.INTENT_DEVICE);
eventType = (TaskerEventType) getIntent().getSerializableExtra(TaskerConstants.INTENT_EVENT);
final TaskerSettings settings = device.getSpec().getSettings(eventType);
eventType = (TaskerEventType) getIntent().getSerializableExtra(TaskerConstants.EVENT_INTENT);
final PreferenceScreen tasks = (PreferenceScreen) findPreference(TaskerConstants.ACTIVITY_TASKS);
SwitchPreference enabled = (SwitchPreference) findPreference(scoped(TaskerConstants.ACTIVITY_EVENT_ENABLED));
settings.isEnabled().set(prefs.getBoolean(scoped(TaskerConstants.ACTIVITY_EVENT_ENABLED), false));
enabled.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
settings.isEnabled().set((Boolean) newValue);
return true;
}
});
eventType = (TaskerEventType) getIntent().getSerializableExtra(TaskerConstants.INTENT_EVENT);
final PreferenceScreen tasks = (PreferenceScreen) findPreference(scoped(TaskerConstants.ACTIVITY_TASKS));
initThreshold(settings, tasks);
initTasks(settings, tasks);
}
private String scoped(TaskerConstants.ScopedString scopedString) {
return scopedString.withScope(device.name()).withScope(eventType.getType()).toString();
}
private void initThreshold(final TaskerSettings settings, final PreferenceScreen tasks) {
EditTextPreference threshold = (EditTextPreference) findPreference(TaskerConstants.ACTIVITY_THRESHOLD);
final EditTextPreference threshold = (EditTextPreference) findPreference(scoped(TaskerConstants.ACTIVITY_THRESHOLD));
setThresholdIfDefined(settings);
threshold.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
@ -51,28 +78,43 @@ public class TaskerEventActivity extends AbstractSettingsActivity {
return true;
}
});
final Preference thresholdEnabled = findPreference(TaskerConstants.ACTIVITY_THESHOLD_ENABELD);
final Preference thresholdEnabled = findPreference(scoped(TaskerConstants.ACTIVITY_THRESHOLD_ENABLED));
if (prefs.getBoolean(scoped(TaskerConstants.ACTIVITY_THRESHOLD_ENABLED), false)) {
settings.getThreshold().set(null);
}
thresholdEnabled.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (newValue.equals(Boolean.FALSE)) {
for (int i = 2; i < tasks.getPreferenceCount(); i++) {
tasks.removePreference(tasks.getPreference(tasks.getPreferenceCount()));
for (EditTextPreference taskPreference : taskPreferences) {
if (!taskPreference.getKey().equals(scoped(TaskerConstants.ACTIVITY_TASK))) {
tasks.removePreference(taskPreference);
}
}
settings.getThreshold().set(null);
return true;
}
settings.getThreshold().set(null);
setThresholdIfDefined(settings);
return true;
}
});
}
private void setThresholdIfDefined(TaskerSettings settings) {
long thresholdValue = prefs.getLong(scoped(TaskerConstants.ACTIVITY_THRESHOLD), 0L);
if (thresholdValue != 0L) {
settings.getThreshold().set(prefs.getLong(scoped(TaskerConstants.ACTIVITY_THRESHOLD), 50L));
}
}
private void initTasks(final TaskerSettings settings, final PreferenceScreen tasks) {
ButtonPreference addTaskButton = (ButtonPreference) findPreference(TaskerConstants.ACTIVITY_TASK_ADD);
final EditTextPreference taskNamePreference = (EditTextPreference) findPreference(TaskerConstants.ACTIVITY_TASK);
final EditTextPreference taskNamePreference = (EditTextPreference) findPreference(scoped(TaskerConstants.ACTIVITY_TASK));
taskPreferences.add(taskNamePreference);
addTaskButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (prefs.getBoolean(TaskerConstants.ACTIVITY_THESHOLD_ENABELD, false)) {
if (prefs.getBoolean(scoped(TaskerConstants.ACTIVITY_THRESHOLD_ENABLED), false)) {
tasks.addPreference(task(tasks, taskNamePreference));
}
}
@ -80,10 +122,12 @@ public class TaskerEventActivity extends AbstractSettingsActivity {
TaskerTaskProvider taskerTaskProvider = new TaskerTaskProvider() {
@Override
public String getTask(TaskerEvent event) {
for (int i = 1; i < tasks.getPreferenceCount(); i++) {
if (event.getCount() == i - 1) {
return ((EditTextPreference) tasks.getPreference(i)).getText();
if (event.getCount() < taskPreferences.size()) {
String text = taskPreferences.get(event.getCount()).getText();
if (StringUtils.isEmpty(text)) {
throw new NoTaskDefinedException();
}
return text;
}
return null;
}
@ -94,17 +138,18 @@ public class TaskerEventActivity extends AbstractSettingsActivity {
private Preference task(final PreferenceScreen tasks, Preference build) {
final ButtonPreference task = new ButtonPreference(this);
task.setKey(TaskerConstants.ACTIVITY_TASK + "_" + tasks.getPreferenceCount());
task.setKey(scoped(TaskerConstants.ACTIVITY_TASK) + "_" + tasks.getPreferenceCount());
task.setTitle(build.getTitle());
task.setSummary(build.getSummary());
task.setButtonText(R.string.tasker_remove);
task.setWidgetLayoutResource(R.layout.tasker_add_button);
task.setWidgetLayoutResource(R.layout.button_preference_layout);
task.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tasks.removePreference(task);
}
});
taskPreferences.add(task);
return task;
}

View File

@ -8,11 +8,17 @@ import android.preference.PreferenceCategory;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerDevice;
/**
* Tasker events {@link AbstractSettingsActivity}. Lists supported {@link TaskerEventType}'s for the specific {@link TaskerDevice}
* <p>
* Forwards to {@link TaskerEventActivity}.
*/
public class TaskerEventsActivity extends AbstractSettingsActivity {
private TaskerConstants.TaskerDevice device;
private TaskerDevice device;
public TaskerEventsActivity() {
}
@ -21,8 +27,8 @@ public class TaskerEventsActivity extends AbstractSettingsActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.tasker_events_preferences);
device = (TaskerConstants.TaskerDevice) getIntent().getSerializableExtra(TaskerConstants.DEVICE_INTENT);
PreferenceCategory category = (PreferenceCategory) findPreference(TaskerConstants.PREF_EVENT_GROUP);
device = (TaskerDevice) getIntent().getSerializableExtra(TaskerConstants.INTENT_DEVICE);
PreferenceCategory category = (PreferenceCategory) findPreference(TaskerConstants.ACTIVITY_EVENT_GROUP);
for (final TaskerEventType eventType : device.getSpec().getSupportedTypes()) {
Preference preference = new Preference(this);
preference.setTitle(eventType.getLocalization());
@ -30,8 +36,8 @@ public class TaskerEventsActivity extends AbstractSettingsActivity {
@Override
public boolean onPreferenceClick(Preference preference) {
Intent intent = new Intent(TaskerEventsActivity.this, TaskerEventActivity.class);
intent.putExtra(TaskerConstants.EVENT_INTENT, eventType);
intent.putExtra(TaskerConstants.DEVICE_INTENT, device);
intent.putExtra(TaskerConstants.INTENT_EVENT, eventType);
intent.putExtra(TaskerConstants.INTENT_DEVICE, device);
startActivity(intent);
return true;
}

View File

@ -1,18 +1,21 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.service;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
package nodomain.freeyourgadget.gadgetbridge.tasker.spec;
import java.util.HashMap;
import java.util.Map;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.SettingSupplier;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.SettingSupplierImpl;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.SettingSupplier;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.SettingSupplierImpl;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.TaskerSettings;
import nodomain.freeyourgadget.gadgetbridge.tasker.task.TaskerTaskProvider;
/**
* Abstract implementation that supplies a {@link TaskerSettings} object to gather user configuration
* via {@link nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.TaskerEventsActivity}.
* <p>
* Its recommended to use this implementation so you don't have to take care of user configurations yourself.
* Always provides a non null {@link TaskerSettings} object regardless of the {@link TaskerEventType}.
*/
public abstract class AbstractTaskerSpec implements TaskerSpec {
private Map<TaskerEventType, TaskerSettings> settings = new HashMap<>();

View File

@ -1,4 +1,4 @@
package nodomain.freeyourgadget.gadgetbridge.tasker.service;
package nodomain.freeyourgadget.gadgetbridge.tasker.spec;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
@ -6,8 +6,14 @@ import android.bluetooth.BluetoothGattCharacteristic;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerConstants;
import nodomain.freeyourgadget.gadgetbridge.tasker.settings.TaskerSettings;
/**
* Tasker specification for a {@link TaskerConstants.TaskerDevice}.
* <p>
* First and only thing to do if you want to support more {@link nodomain.freeyourgadget.gadgetbridge.impl.GBDevice}.
*/
public interface TaskerSpec {
TaskerEventType getEventType(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic);

View File

@ -2,14 +2,22 @@ package nodomain.freeyourgadget.gadgetbridge.tasker.task;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerIntent;
import nodomain.freeyourgadget.gadgetbridge.tasker.plugin.TaskerIntent;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.NoTaskDefinedException;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerService;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEvent;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEventType;
import nodomain.freeyourgadget.gadgetbridge.tasker.service.TaskerUtil;
/**
* Tasker task used by {@link TaskerService} to run a scheduled asynchronous task.
* <p>
* Uses {@link ScheduledExecutorService} with {@link Future} for scheduling.
*/
public class TaskerTask implements Runnable {
private Future task;
@ -39,10 +47,14 @@ public class TaskerTask implements Runnable {
@Override
public void run() {
if (TaskerService.ready()) {
if (task != null) {
GBApplication.getContext().sendBroadcast(new TaskerIntent(provider.getTask(new TaskerEvent(type, count))));
try {
if (TaskerService.isReady()) {
if (task != null) {
GBApplication.getContext().sendBroadcast(new TaskerIntent(provider.getTask(new TaskerEvent(type, count))));
}
}
} catch (NoTaskDefinedException e) {
TaskerUtil.noTaskDefinedInformation();
}
}

View File

@ -2,8 +2,17 @@ package nodomain.freeyourgadget.gadgetbridge.tasker.task;
import nodomain.freeyourgadget.gadgetbridge.tasker.event.TaskerEvent;
/**
* Tasker task provider provides task names {@link TaskerEvent} based.
*/
public interface TaskerTaskProvider {
/**
* Task name for specific {@link TaskerEvent}
*
* @param event
* @return Task name
*/
String getTask(TaskerEvent event);
}

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tasker_remove_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/tasker_remove">
</Button>
</RelativeLayout >

View File

@ -625,14 +625,26 @@
<string name="language_and_region_prefs">Sprach- und Gebietseinstellungen</string>
<!-- Tasker -->
<string name="tasker">Tasker</string>
<string name="tasker_enabled">Aktiv</string>
<string name="tasker_enabled_sum">Aktiviert Tasker aber deaktiviert die Steuerung der Medien</string>
<string name="tasker_task_single">Task für einzelnes drücken</string>
<string name="tasker_task_double">Task für doppeltes drücken</string>
<string name="tasker_task_triple">Task für dreifaches drücken</string>
<string name="tasker_enabled">Aktiviert</string>
<string name="tasker_enabled_sum">Aktiviert die Tasker-Unterstützung</string>
<string name="tasker_add">Hinzufügen</string>
<string name="tasker_remove">Entfernen</string>
<string name="tasker_events">Ereignisse</string>
<string name="tasker_event_button">Knopfdruck-Ereignis</string>
<string name="tasker_event_connection">Verbindungs-Ereignis</string>
<string name="tasker_event_data">Daten-Ereignis</string>
<string name="tasker_event_enabled">Ereignistyp aktiviert</string>
<string name="tasker_threshold_enable">Schwellenwert aktiviert</string>
<string name="tasker_threshold_enable_sum">Aktiviert eine Verzögerung zwischen den Aufgaben</string>
<string name="tasker_threshold">Schwellenwert in Millisekunden</string>
<string name="tasker_threshold_sum">Verzögerung zwischen den Aufrufen der Aufgaben. Z.B. für Schwellenwert 1000: Doppelter Knopfdruck innerhalb einer Sekunde ruft die Aufgabe an zweiter Stelle auf.</string>
<string name="tasker_task">Aufgabe</string>
<string name="tasker_task_sum">Fügt eine Weitere Schwellwert-Aufgahinzube </string>
<string name="tasker_task_name">Aufgabenname</string>
<string name="tasker_info">Tasker ist eine Applikation für Android die Aufgaben (Ein Set von Aktionen)
anhand eines Kontexts (Applikation, Zeit, Datum, Ort, Ereignis, Geste) über benutzerdefinierte
Profile oder klickbare oder zeitgesteuerte Widgets ausfürt.</string>
<string name="tasker_no_task_defined">Tasker ist aktiviert aber es wurde keine Aufgabe angegeben! Bitte gehen sie in die Tasker Einstellungen und definieren sie Aufgaben.</string>
<!-- XWatch -->
<string name="xwatch_settings">XWatch Einstellungen</string>
</resources>

View File

@ -677,9 +677,11 @@
<string name="tasker_enabled_sum">Enables Tasker support</string>
<string name="tasker_add">Add</string>
<string name="tasker_remove">Remove</string>
<string name="tasker_events">Events</string>
<string name="tasker_event_button">Button Events</string>
<string name="tasker_event_connection">Connection Events</string>
<string name="tasker_event_data">Data Events</string>
<string name="tasker_event_enabled">Enable event type</string>
<string name="tasker_threshold_enable">Enable threshold</string>
<string name="tasker_threshold_enable_sum">Enables delay between task</string>
<string name="tasker_threshold">Threshold in milliseconds</string>
@ -691,7 +693,4 @@
(application, time, date, location, event, gesture) in user-defined profiles or in clickable or timer home screen widgets.</string>
<string name="tasker_no_task_defined">No task defined! Please define a task in settings.</string>
<!-- XWatch -->
<string name="xwatch_settings">XWatch settings</string>
</resources>

View File

@ -746,7 +746,7 @@
</PreferenceCategory>
<!--<PreferenceCategory android:key="pref_key_tasker_group">-->
<Preference
android:key="pref_key_tasker"
android:key="act_tasker"
android:title="@string/tasker" />
<!--</PreferenceCategory>-->
</PreferenceScreen>

View File

@ -1,26 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="act_tasker_task_group">
<PreferenceCategory android:key="tasker_event">
<Preference
android:key="tasker_info"
android:persistent="false"
android:selectable="false"
android:summary="@string/tasker_info" />
<SwitchPreference
android:key="act_tasker_threshold_enabled"
android:title="@string/tasker_threshold_enable" />
<EditTextPreference
android:inputType="number"
android:key="act_tasker_threshold"
android:summary="@string/tasker_threshold_sum"
android:title="@string/tasker_threshold" />
<nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.ButtonPreference
android:key="act_tasker_task_add"
android:summary="@string/tasker_task_sum"
android:title="@string/tasker_task"
android:widgetLayout="@layout/tasker_add_button"></nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.ButtonPreference>
</PreferenceCategory>
<SwitchPreference
android:key="act_tasker_event_enabled"
android:title="@string/tasker_event_enabled" />
<SwitchPreference
android:key="act_tasker_threshold_enabled"
android:title="@string/tasker_threshold_enable" />
<EditTextPreference
android:inputType="number"
android:key="act_tasker_threshold"
android:summary="@string/tasker_threshold_sum"
android:title="@string/tasker_threshold" />
<nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.ButtonPreference
android:key="act_tasker_task_add"
android:summary="@string/tasker_task_sum"
android:title="@string/tasker_task"></nodomain.freeyourgadget.gadgetbridge.tasker.settings.activities.ButtonPreference>
<EditTextPreference
android:key="act_tasker_task"
android:summary="@string/tasker_task_name" />

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:key="pref_key_tasker_event_group" android:title="@string/tasker">
</PreferenceCategory>
<PreferenceCategory
android:key="act_event_group"
android:title="@string/tasker_events"></PreferenceCategory>
</PreferenceScreen>

View File

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:key="pref_key_tasker_group" android:title="@string/tasker">
<PreferenceCategory android:key="act_tasker_group" android:title="@string/tasker">
<Preference
android:persistent="false"
android:selectable="false"
android:summary="@string/tasker_info" />
<SwitchPreference
android:defaultValue="false"
android:key="tasker_enabled"
android:key="act_tasker_enabled"
android:summary="@string/tasker_enabled_sum"
android:title="@string/tasker_enabled" />
</PreferenceCategory>