Skip to main content leehalls.net

Orgmode, Android and Tasker

Yes i know orgzly exists and whilst it is an excellent app it just doesn’t feel right or perhaps quick enough for me, I use it but only as a “refer to” method ie a viewer of pgp encrypted passwords or other entries and not as a capture/entry or agenda viewing system and yet because i wanted a way of quickly capturing tasks & sometimes tasks with photos I created several scenes in Tasker which work for me, using these i have to simply click an icon and can have a task populated with the right orgmode format, date etc and ready to enter text. The capture scenes write to a staging_ground.org file which is automagically sync’d via syncthing to my main machine and the agenda scene simply reads the cron-generated text output of the org agenda.

One downside of this approach is that Tasker is no longer available without Google Play so for an alternative ROM you’re pretty stuffed :anguished:

from the FAQ of Tasker

Why is Tasker only sold via Play Store now ? App prices have been driven so low that the only way to make any profit is to make an extremely large amount of sales.

Any sales channel that has even a little bit of administrative overhead is therefore out of the question because of the formula

large-number-of-sales x little-overhead = large-overhead A small developer can’t handle a large overhead.

The capture scenes look like this;

After attempting to recreate the tasks/scenes on another phone i realise there is quite a bit to them which isnt immediately obvious for example placing the focus on the text edit box. Hence a re-write of this post to try and give more info.

As with all programming it helps if you give the constructs meaningful names so that finding, using and understanding them in the future is easier ie the text edit box in the scene above would normally be called TextEdit1 but i’ve called it My_OrgTextEdit

if you’ve got lots of scenes or tasks it giving them useful names aids identifying what each one does plus note the CamelCase format this is to differentiate between global and local variables

Global vs. Local Variables Variables which have an all-lower-case name (e.g. %fruit_bar) are local, meaning that their value is specific to the task or scene in which they are used.

Variables which have one or more capital letters in their name (e.g. %Car, %WIFI) are global, meaning that wherever they are accessed from the same value is returned.

REF: https://tasker.joaoapps.com/userguide/en/variables.html

Once you’ve created a scene as above (two buttons, 1 label and 1 textedit box) you need the textedit box to have the focus. You can do this by long pressing on the actual box to reveal another menu, from this choose focus and you’ll see the box will now have a star inside it eg

The next thing we need to do with the textedit box is to set a task within it, a short tap on the textedit element opens up its settings screen and here we can set fonts, colours and text changed;

Tasker recognises when the content has changed and because of the task above stores the result in the variable My_OrgTxt a full example is;

Finally for the scene we need a cancel and an ok/accept button, as before a short tap on the button element brings up the settings screen and we create a task this time under the tap function

For the cancel button we simply have the task to destroy the scene if using text entry but if capturing a photo then we want the button to actually delete the unused photo and not litter.

The task element

The capture scenes do nothing without the main task which is made up of multiple steps my photo capture task is the more complex and if you can replicate this then capturing simple text is a lot easier;

Essentially this group of actions in the task perform the following

# Description
1 Tasker opens the camera app and within 3s or so snaps a photo and saves it with the filename we defined
2 We set our own variable to the Tasker internal one which contains the filesystem path of the last photo taken
3 Split the variable and save just the filename part
4 Move this file into our org folder
5 Show the capture scene
6 Set the clipboard to our standard orgmode TODO format with the file details already in
7 Launch another of the Tasker apps (autoinput) to paste the clipboard into the scene

Most of the above is straight forwards, #7 the autoinput element needs a little more explanation, define the action as normal from the Tasker options and then from the autoinput config menu ensure that the Type: is set to focus and Action: to paste as below;

The eagle eyed will see one other line which states Is Tasker Action: true this is necessary otherwise the autoinput task will fail, you can set this option by scrolling to the bottom of the autoinput configuration screen and choosing advanced

Finally if all goes well

So once all that is complete we end up with a scene with auto-populated text waiting for more input;

Type away and pressing the green accept button and within a few seconds the magic of syncthing whirs away in the background, refresh the emacs org agenda and voila.

Opening the task allows me to see any notes i’ve added and of course the photo to go with it.

The “read my agenda” scene

The “read my agenda” scene is much simpler the task reads in the text file and stores the contents in a variable before launching the agenda scene

Whilst the scene has a textbox which reads the variable and prints

Finally the agenda looks like;

Each of the above has an icon on my Android home screen so with one tap i can create a photonote in an org file or read my agenda in true orgmode output. HTML would be better, the agenda looks better but i was not yet able to get HTML output working via a cronjob and using org-super-agenda. 2020-05-27 now working see footnote > 1

XML for the main task above looks like;

xml code snippet start

<TaskerData sr="" dvi="1" tv="5.9.2">
  <Task sr="task4">
      <cdate>1586619219286</cdate>
      <edate>1590482529265</edate>
      <id>4</id>
      <nme>My_OrgPhoto</nme>
      <pri>7</pri>
      <Action sr="act0" ve="7">
          <code>101</code>
          <Int sr="arg0" val="0"/>
          <Str sr="arg1" ve="3">PT-%DATE-%TIME</Str>
          <Int sr="arg2" val="0"/>
          <Int sr="arg3" val="0"/>
          <Int sr="arg4" val="0"/>
          <Str sr="arg5" ve="3">1280x720</Str>
          <Int sr="arg6" val="0"/>
          <Int sr="arg7" val="0"/>
          <Int sr="arg8" val="1"/>
          <Int sr="arg9" val="0"/>
      </Action>
      <Action sr="act1" ve="7">
          <code>547</code>
          <Str sr="arg0" ve="3">%My_OrgPhoto</Str>
          <Str sr="arg1" ve="3">%FOTO</Str>
          <Int sr="arg2" val="0"/>
          <Int sr="arg3" val="0"/>
          <Int sr="arg4" val="0"/>
          <Int sr="arg5" val="3"/>
      </Action>
      <Action sr="act2" ve="7">
          <code>590</code>
          <Str sr="arg0" ve="3">%My_OrgPhoto</Str>
          <Str sr="arg1" ve="3">/</Str>
          <Int sr="arg2" val="0"/>
      </Action>
      <Action sr="act3" ve="7">
          <code>400</code>
          <Str sr="arg0" ve="3">%My_OrgPhoto</Str>
          <Str sr="arg1" ve="3">orgFiles/staging_img</Str>
          <Int sr="arg2" val="0"/>
      </Action>
      <Action sr="act4" ve="7">
          <code>47</code>
          <Str sr="arg0" ve="3">My_OrgPhoto_s</Str>
          <Int sr="arg1" val="3"/>
          <Int sr="arg2" val="100"/>
          <Int sr="arg3" val="100"/>
          <Int sr="arg4" val="0"/>
          <Int sr="arg5" val="1"/>
          <Int sr="arg6" val="1"/>
          <Int sr="arg7" val="1"/>
      </Action>
      <Action sr="act5" ve="7">
          <code>105</code>
          <Str sr="arg0" ve="3">* TODO %DATE-%TIME - PHOTONOTE
[[file:staging_img/%My_OrgPhoto3]]</Str>
          <Int sr="arg1" val="0"/>
      </Action>
      <Action sr="act6" ve="7">
          <code>1732635924</code>
          <Bundle sr="arg0">
              <Vals sr="val">
                  <ActionId>&lt;null&gt;</ActionId>
                  <ActionId-type>java.lang.String</ActionId-type>
                  <ActionType>32768</ActionType>
                  <ActionType-type>java.lang.String</ActionType-type>
                  <EnableDisableAccessibilityService>&lt;null&gt;</EnableDisableAccessibilityService>
                  <EnableDisableAccessibilityService-type>java.lang.String</EnableDisableAccessibilityService-type>
                  <FieldSelectionType>2</FieldSelectionType>
                  <FieldSelectionType-type>java.lang.String</FieldSelectionType-type>
                  <IsFirstAction>false</IsFirstAction>
                  <IsFirstAction-type>java.lang.Boolean</IsFirstAction-type>
                  <IsTaskerAction>true</IsTaskerAction>
                  <IsTaskerAction-type>java.lang.Boolean</IsTaskerAction-type>
                  <NearbyText>&lt;null&gt;</NearbyText>
                  <NearbyText-type>java.lang.String</NearbyText-type>
                  <Password>&lt;null&gt;</Password>
                  <Password-type>java.lang.String</Password-type>
                  <RepeatInterval>&lt;null&gt;</RepeatInterval>
                  <RepeatInterval-type>java.lang.String</RepeatInterval-type>
                  <RepeatTimes>&lt;null&gt;</RepeatTimes>
                  <RepeatTimes-type>java.lang.String</RepeatTimes-type>
                  <StoredAction>&lt;null&gt;</StoredAction>
                  <StoredAction-type>java.lang.String</StoredAction-type>
                  <TextToWrite>&lt;null&gt;</TextToWrite>
                  <TextToWrite-type>java.lang.String</TextToWrite-type>
                  <com.twofortyfouram.locale.intent.extra.BLURB>Type: Focus
Action : Paste
Is Tasker Action: true</com.twofortyfouram.locale.intent.extra.BLURB>
                  <com.twofortyfouram.locale.intent.extra.BLURB-type>java.lang.String</com.twofortyfouram.locale.intent.extra.BLURB-type>
                  <net.dinglisch.android.tasker.RELEVANT_VARIABLES>&lt;StringArray sr=""&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0&gt;%err
Error Code
Only available if you select &amp;lt;b&amp;gt;Continue Task After Error&amp;lt;/b&amp;gt; and the action ends in error&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1&gt;%errmsg
Error Message
Only available if you select &amp;lt;b&amp;gt;Continue Task After Error&amp;lt;/b&amp;gt; and the action ends in error&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1&gt;&lt;/StringArray&gt;</net.dinglisch.android.tasker.RELEVANT_VARIABLES>
                  <net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>[Ljava.lang.String;</net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>
                  <net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>FieldSelectionType ActionType plugininstanceid plugintypeid </net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>
                  <net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>java.lang.String</net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>
                  <net.dinglisch.android.tasker.subbundled>true</net.dinglisch.android.tasker.subbundled>
                  <net.dinglisch.android.tasker.subbundled-type>java.lang.Boolean</net.dinglisch.android.tasker.subbundled-type>
                  <plugininstanceid>931c2a84-a888-45e8-a2e3-8a19eff825e6</plugininstanceid>
                  <plugininstanceid-type>java.lang.String</plugininstanceid-type>
                  <plugintypeid>com.joaomgcd.autoinput.intent.IntentPerformAction</plugintypeid>
                  <plugintypeid-type>java.lang.String</plugintypeid-type>
              </Vals>
          </Bundle>
          <Str sr="arg1" ve="3">com.joaomgcd.autoinput</Str>
          <Str sr="arg2" ve="3">com.joaomgcd.autoinput.activity.ActivityConfigPerformAction</Str>
          <Int sr="arg3" val="23"/>
      </Action>
      <Img sr="icn" ve="2">
          <nme>camera</nme>
          <pkg>net.dinglisch.android.ipack.bluewhitepearlhd</pkg>
      </Img>
  </Task>
</TaskerData>

xml code snippet end

XML for the photocapture scene

xml code snippet start

<TaskerData sr="" dvi="1" tv="5.9.2">
  <dmetric>1440.0,2792.0</dmetric>
  <Scene sr="sceneMy_OrgPhoto_s">
      <cdate>1586846659080</cdate>
      <edate>1590482654993</edate>
      <gridSize>30</gridSize>
      <heightLand>-1</heightLand>
      <heightPort>2086</heightPort>
      <nme>My_OrgPhoto_s</nme>
      <widthLand>-1</widthLand>
      <widthPort>1241</widthPort>
      <EditTextElement sr="elements0" ve="3">
          <flags>12</flags>
          <geom>32,186,1182,1284,35,1225,1290,977</geom>
          <valueselectedTask>55</valueselectedTask>
          <Str sr="arg0" ve="3">TextEdit1</Str>
          <Str sr="arg1" ve="3"/>
          <Int sr="arg2" val="14"/>
          <Int sr="arg3" val="100"/>
          <Str sr="arg4" ve="3">#FF00FF00</Str>
          <Str sr="arg5" ve="3"/>
          <Int sr="arg6" val="5"/>
          <Int sr="arg7" val="0"/>
          <Int sr="arg8" val="1000"/>
          <RectElement sr="background">
              <flags>4</flags>
              <geom>-1,-1,-1,-1,-1,-1,-1,-1</geom>
              <Str sr="arg0" ve="3"/>
              <Int sr="arg1" val="0"/>
              <Str sr="arg2" ve="3">#FF000000</Str>
              <Str sr="arg3" ve="3"/>
              <Int sr="arg4" val="1"/>
              <Str sr="arg5" ve="3">#FF000000</Str>
              <Int sr="arg6" val="0"/>
              <Int sr="arg7" val="0"/>
          </RectElement>
      </EditTextElement>
      <ButtonElement sr="elements1" ve="3">
          <clickTask>57</clickTask>
          <flags>4</flags>
          <geom>1021,25,192,160,472,745,434,775</geom>
          <Str sr="arg0" ve="3">Button1</Str>
          <Str sr="arg1" ve="3"/>
          <Int sr="arg2" val="8"/>
          <Int sr="arg3" val="100"/>
          <Str sr="arg4" ve="3">#FF000000</Str>
          <Str sr="arg5" ve="3"/>
          <Int sr="arg6" val="0"/>
          <Img sr="arg7" ve="2">
              <nme>cuteball_go</nme>
              <pkg>net.dinglisch.android.ipack.ilikebuttonshd</pkg>
          </Img>
      </ButtonElement>
      <ButtonElement sr="elements2" ve="3">
          <clickTask>58</clickTask>
          <flags>4</flags>
          <geom>32,25,186,160,35,1429,205,175</geom>
          <Str sr="arg0" ve="3">Button2</Str>
          <Str sr="arg1" ve="3"/>
          <Int sr="arg2" val="16"/>
          <Int sr="arg3" val="100"/>
          <Str sr="arg4" ve="3">#FF000000</Str>
          <Str sr="arg5" ve="3"/>
          <Int sr="arg6" val="0"/>
          <Img sr="arg7" ve="2">
              <nme>aqua_shutdown</nme>
              <pkg>net.dinglisch.android.ipack.ilikebuttonshd</pkg>
          </Img>
      </ButtonElement>
      <TextElement sr="elements3" ve="3">
          <flags>4</flags>
          <geom>298,25,620,173,327,1429,677,190</geom>
          <Str sr="arg0" ve="3">Text1</Str>
          <Str sr="arg1" ve="3">ORG PHOTO CAPTURE</Str>
          <Int sr="arg2" val="14"/>
          <Int sr="arg3" val="100"/>
          <Str sr="arg4" ve="3">#FF3EFF00</Str>
          <Str sr="arg5" ve="3"/>
          <Int sr="arg6" val="0"/>
          <Int sr="arg7" val="0"/>
          <Int sr="arg8" val="0"/>
          <RectElement sr="background">
              <flags>4</flags>
              <geom>-1,-1,-1,-1,-1,-1,-1,-1</geom>
              <Str sr="arg0" ve="3"/>
              <Int sr="arg1" val="0"/>
              <Str sr="arg2" ve="3">#8D000000</Str>
              <Str sr="arg3" ve="3"/>
              <Int sr="arg4" val="0"/>
              <Str sr="arg5" ve="3">#FF000000</Str>
              <Int sr="arg6" val="0"/>
              <Int sr="arg7" val="0"/>
          </RectElement>
      </TextElement>
      <PropertiesElement sr="props">
          <Int sr="arg0" val="1"/>
          <Int sr="arg1" val="0"/>
          <Str sr="arg2" ve="3">#33FFFFFF</Str>
          <Int sr="arg3" val="0"/>
          <Str sr="arg4" ve="3">Capture</Str>
          <Str sr="arg5" ve="3"/>
          <Img sr="arg6" ve="2"/>
          <Str sr="arg7" ve="3"/>
      </PropertiesElement>
  </Scene>
  <Task sr="task55">
      <cdate>1586900574760</cdate>
      <edate>1586900574760</edate>
      <id>55</id>
      <pri>102</pri>
      <Action sr="act0" ve="7">
          <code>195</code>
          <Str sr="arg0" ve="3">My_OrgPhoto_s</Str>
          <Str sr="arg1" ve="3">TextEdit1</Str>
          <Int sr="arg2" val="2"/>
          <Str sr="arg3" ve="3">%orgTXT</Str>
      </Action>
  </Task>
  <Task sr="task57">
      <cdate>1586846843950</cdate>
      <edate>1586846843950</edate>
      <id>57</id>
      <pri>102</pri>
      <Action sr="act0" ve="7">
          <code>410</code>
          <Str sr="arg0" ve="3">orgFiles/staging_gnd.org</Str>
          <Str sr="arg1" ve="3">%orgTXT</Str>
          <Int sr="arg2" val="1"/>
          <Int sr="arg3" val="1"/>
      </Action>
      <Action sr="act1" ve="7">
          <code>49</code>
          <Str sr="arg0" ve="3">My_OrgPhoto_s</Str>
      </Action>
  </Task>
  <Task sr="task58">
      <cdate>1586900945194</cdate>
      <edate>1586900945194</edate>
      <id>58</id>
      <pri>102</pri>
      <Action sr="act0" ve="7">
          <code>49</code>
          <Str sr="arg0" ve="3">My_OrgPhoto_s</Str>
      </Action>
  </Task>
</TaskerData>

xml code snippet end


  1. new commandline using org-batch-store-agenda-views and a small mod to my dotemacs file code results in HTML output, you can see the explanation here: batch agenda output via html ↩︎