[ Home ]
[ EN | DE ]
Time Recording: Public Services
Time Recording provides services for integration in other apps (like "Tasker"),
and for developers who want to use these on their own.
Broadcast Receivers
com.dynamicg.timerecording.CHECK_IN
com.dynamicg.timerecording.CHECK_OUT
com.dynamicg.timerecording.PUNCH
com.dynamicg.timerecording.START_NEW_TASK
com.dynamicg.timerecording.DATA_EXPORT
com.dynamicg.timerecording.GET_INFO
Activity actions
com.dynamicg.timerecording.activity.CHECK_IN
com.dynamicg.timerecording.activity.CHECK_OUT
com.dynamicg.timerecording.activity.PUNCH
com.dynamicg.timerecording.activity.SWITCH_TASK
→ Note: these are "action strings", not activity class names. If you absolutely need to also provide the activity class, then use this:
Activity: com.dynamicg.timerecording.DispatcherFilteredActivity
Action: as per preceding list
Activity class names
Alternatively, if you cannot use "Activities with action names", then use one of these classes for punching;
we've originally wanted to remove them with an earlier app version, but some apps like NFC ReTag only accept dedicated class names.
com.dynamicg.timerecording.PublicServices$CheckIn
com.dynamicg.timerecording.PublicServices$CheckOut
com.dynamicg.timerecording.PublicServices$Punch
App package names
Note the activity and broadcast names are identical in both app versions ("Free" and "Pro"); you always need to include the "app package name" as extra argument when calling these, i.e. either of:
com.dynamicg.timerecording
com.dynamicg.timerecording.pro
Simple broadcast test with ADB
The last argument is the app package name, i.e. "Free" respectively "Pro":
adb shell am broadcast -a com.dynamicg.timerecording.GET_INFO com.dynamicg.timerecording
adb shell am broadcast -a com.dynamicg.timerecording.GET_INFO com.dynamicg.timerecording.pro
Simple activity test with ADB
adb shell am start -n com.dynamicg.timerecording/com.dynamicg.timerecording.DispatcherFilteredActivity -a com.dynamicg.timerecording.activity.CHECK_IN
adb shell am start -n com.dynamicg.timerecording.pro/com.dynamicg.timerecording.DispatcherFilteredActivity -a com.dynamicg.timerecording.activity.CHECK_IN
Set specific task when punching
• Set the "com.dynamicg.timerecording.TASK" extra. Value is the numeric Task ID as displayed on the "Edit task" screen.
• Alternatively, set the "com.dynamicg.timerecording.TASK_NAME" extra with the given task name. If the same tasks exists for different clients, use format "taskname[[clientname]]".
• Tasker info: when setting parameters in Tasker, use this notation: com.dynamicg.timerecording.TASK:{ID}
Set specific time when punching
• Set the "com.dynamicg.timerecording.TIME" extra.
• Format is "hh24:mm" (i.e. 00:00 to 23:59).
• If you need to set the "Validity date" to next day: use format "hh24:mm+1", e.g. "00:45+1"
Set work unit notes when punching
• Set the "com.dynamicg.timerecording.NOTES" extra
GET_INFO
• This is for developers who want to integrate Time Recording status information in their own apps or widgets.
GET_INFO sends current task, running total work time, current daily and weekly "delta", and other data to your BroadcastReceiver.
• Sample project is available here: TimeRecInfoGetter-src.zip
• The relevant call is: com.dynamicg.timerecinfogetter.TimeRecDataGetter.getData()
• Alternatively, the app's "Tasker Plugin" provides the "GET_INFO_BROADCAST" action, which returns all GET_INFO information as "key/value bundle".
Check the details popup on the "Time Recording Tasker Plugin" configuration screen when selecting this option.
DATA_EXPORT
Report generation can be triggered through broadcast intent. Sample see below.
What's “Check in” vs. “Punch” vs. “Start new task”
• “Check in” will check in once. Repeated calls are ignored
• “Punch” will do a check in or a check out, depending on the current state.
• “Start new task” performs a "check in" to start a new work unit. If you have been checked in already, the previous work unit is closed with a "check out".
App package detection
Below samples reference variable "timeRecPkgName" as target app package name; you can either hard code this to "com.dynamicg.timerecording" or "com.dynamicg.timerecording.pro",
or you can use the Android package manager to check which app is installed:
public static String getTimeRecPackage(Context context) {
final String pkgFree = "com.dynamicg.timerecording", pkgPro = "com.dynamicg.timerecording.pro";
// caution: these these packages need to be registered as "" in the Android app manifest (since Android 11)
try {
if (context.getPackageManager().getPackageInfo(pkgPro, PackageManager.GET_ACTIVITIES)!=null) {
return pkgPro;
}
} catch (NameNotFoundException e) {}
return pkgFree;
}
GET_TASKS
This is for developers who want to read the task list. Also see "Tasks export/import".
Intent intent = new Intent("com.dynamicg.timerecording.GET_TASKS");
intent.setPackage(timeRecPkgName);
BroadcastReceiver resultReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent resultIntent) {
Bundle extras = this.getResultExtras(true);
if (extras!=null) {
ArrayList taskIds = extras.getIntegerArrayList("com.dynamicg.timerecording.GET_TASKS.IDS");
String[] taskNames = extras.getStringArray("com.dynamicg.timerecording.GET_TASKS.NAMES");
String[] clientNames = extras.getStringArray("com.dynamicg.timerecording.GET_TASKS.CLIENTS");
String[] extra1 = extras.getStringArray("com.dynamicg.timerecording.GET_TASKS.EXTRA1");
String[] extra2 = extras.getStringArray("com.dynamicg.timerecording.GET_TASKS.EXTRA2");
boolean currentlyCheckedIn = extras.getBoolean("com.dynamicg.timerecording.GET_TASKS.STATE_CHECKED_IN");
int currentTaskId = extras.getInt("com.dynamicg.timerecording.GET_TASKS.STATE_TASK_ID");
}
}
};
context.sendOrderedBroadcast(intent, null, resultReceiver, null, Activity.RESULT_OK, null, null);
UPDATE_STAMP_VALUE
• This updates one of the "Value" fields
• Broadcast receiver: com.dynamicg.timerecording.SERVICE_DISPATCHER
with OPERATION=STAMP_VALUE_UPDATE
• Bundle values: key={VALUE_1|VALUE_2|VALUE_A|VALUE_B|VALUE_C|VALUE_D}
, value={the value you want to set}
• By default, the current work unit is updated. Optional bundle value: key=TIME
, value=time stamp in format hh24:mm of the work unit you want to update.
• Sample:
Intent intent = new Intent("com.dynamicg.timerecording.SERVICE_DISPATCHER");
intent.setPackage(timeRecPkgName);
intent.putExtra("OPERATION", "UPDATE_STAMP_VALUE");
intent.putExtra("VALUE_A", "TestA_"+new java.util.Date());
intent.putExtra("TIME", "08:46");
context.sendBroadcast(intent);
DATA_EXPORT example
final String dateFrom = "2017-08-01"; // format "yyyy-mm-yy"
final String dateTo = "2017-08-31"; // format "yyyy-mm-yy"
final String exportType = "e3"; // "e2" to "e10"
final String exportFormat = "html"; // values [html, xls, pdf, csv, xml]
Intent intent = new Intent("com.dynamicg.timerecording.DATA_EXPORT");
intent.setPackage(timeRecPkgName);
intent.putExtra("com.dynamicg.timerecording.DATE_FROM", dateFrom);
intent.putExtra("com.dynamicg.timerecording.DATE_TO", dateTo);
intent.putExtra("com.dynamicg.timerecording.EXPORT_TYPE", exportType);
intent.putExtra("com.dynamicg.timerecording.EXPORT_FORMAT", exportFormat);
// provide your package name so that TimeRec can grant the file uri:
intent.putExtra("com.dynamicg.timerecording.CALLED_BY_PKG", context.getPackageName());
// ALTERNATIVELY: PASS ALL PARAMS WITH ONE SINGLE "EXTRA"
//String exportData = dateFrom+","+dateTo+","+exportType+","+exportFormat;
//intent.putExtra("com.dynamicg.timerecording.EXPORT_DATA", exportData);
BroadcastReceiver resultReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent resultIntent) {
Bundle bundle = this.getResultExtras(true);
String uristring = bundle.getString("com.dynamicg.timerecording.FILE_URI");
android.net.Uri uri = android.net.Uri.parse(uristring);
Toast.makeText(context, "uri: "+uri.toString(), Toast.LENGTH_SHORT).show();
// content can be accessed via the uri's input stream, like so:
// InputStream is = context.getContentResolver().openInputStream(uri);
}
};
context.sendOrderedBroadcast(intent, null, resultReceiver, null, Activity.RESULT_OK, null, null);