Share My Creation B4Script - On device basic programming

I am pleased to announce B4Script, an enhanced version of B4A master user AGraham's BasicIDE app. Several things have been modified, moved, added or improved.

The core of both BasicIDE and B4Script is the BasicLibIDE script execution library, by AGraham, which has not changed. Only the IDE and Android extensions have been modified. All credit and gratitude for the library belongs to AGraham.

Changes. To start with the menu structure is completely changed. Gone are the buttons, checkboxes and labels under the editor window. Those have been moved to the Debug menu option. All file operations, including project operations, are in the File Menu option. There is also a Settings menu option. Adding and removing line numbers have also been moved to the Debug menu. This is because the editor edittext view now takes up the entire space of the screen, and automatically resizes when the soft keyboard pops up. This is the way it is supposed to be. It feels right now. Thank you Erel.

One thing to note: Some of the menu options and selection lists use InputList, which I don't like much because the appear cheesy, for the sake of reduced development time, and will be replaced with nicer, more functional prompts and dialogs at some point in the future. The help files for now are the standard BasicIDE help files, and will also be reformatted to appear more pleasing at some point in the future.

The file structure has changed. No longer are files stored in the B4Script folder. There is now the concept of projects. A project is a group of files, some are B4Script files, some are other files like text files and bitmaps, that are stored in their own folder in the B4Script/Projects folder. In IDE mode, FileDirAssets points to this folder. In APK mode, which will be introduced at some point to allow compilation of B4Script projects into an actual APK file that can be uploaded to the Android Market, FileDirAssets points to the actual assets folder. It should also be noted, because I forgot to update the help screens, that FileDirInternal and FileDirDefaultExternal, in IDE mode will point to the projects dir in B4Scripts internal and default external dir's. In APK mode, these dir pathnames will correctly point to the dir as specified by their respective package names, and will not be related to B4Script.

Scripts within a project can run each other with the new Chain and Run commands. In this light, each script is an activity that can be started and stopped at will.

As mentioned in the readme file, standalone scripts, ie. those not associated with a project, are stored in the B4Script/Scripts folder. These are listed in the File/Load menu option when a project is not open. To access one of these when a project is open, first close the project, the use the File/Load menu option.

Creating a new project creates the new folder with the new project name, opens the project, and also creates a new B4Script file by the same name in that folder.

Opening an existing project will limit loading and saving scripts to that project. Close the project to access standalone scripts, or scripts in other projects. Place bitmaps and other files in the project folder with the scripts to access them from the project scripts via the FileDirAssets dir.

My apologies for the lack of time to present this project properly. The help files have been updated. Of importance, is to explore it and have fun.

Change Log:
------------
1.0b: 02/28/12 - Initial beta release
1.00b: 02/28/12 - See post 4 for details
1.01b: skipped somehow >blush<
1.02: 04/10/12 - See post 8 for details
1.03.01: 04/29/12 - See this post for details
1.04: 05/14/12 - see this post for details
1.05: 05-22/12 - see this post for details. See this post for a custom menu system

From this point forward, download the completed app file here.

1.07: 11/13/12 - see this post this post for details.
01/08/13 - uploaded Basic4android project so B4Script projects can be compiled directly to a publishable app. See link above.

To Do List:
-----------
Create a scripts 'gallery' as the startup page for single click running and editing of scripts
Tidy up B4A code
*DONE!* Create APK version of project for simple APK compilation
Create nicer prompts and secondary menus
Create new context sensative help system with updated polished content
Make all B4A view events available
Make all B4A constants available (like Gravity_Top, etc...)
*DONE: #INCLUDE directive to include other scripts at runtime
Autoload settings option to automatically reload last edited script at startup
#AUTOLOAD directive to save cursor position and set it back up when script is loaded
#DEBUG directive to save and load the current scripts debug when script is loaded
Create a list of Sub's for quick and easy code access
Code segregation to isolate one sub at a time in the editor window. Will work with Sub list.
Find and replace in the editor
Try to find a way to read and convert B4A's layout files, so your script's screens can be designed in the B4A designer. I'm thinking if I can read them I can create a B4Script layout file which would be no more than a series of addview, setcolor, settextcolor, etc... statements compiled into a single file, then #INCLUDEd into the project's scripts. Gonna need some help with this Erel :)
Setting option for editor edittext background color

Want something added to the To Do List? Just ask :D
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Sounds great!

This is in preparation of a new Basic4Android update that will allow the bottom of the editor window to automatically move up and down with the keyboard. *** I have no other info on this update, other than Erel stated he would put it on his features list for future updates. I hope it's soon
Already implemented: Handle the soft keyboard with the IME library
 

JesseW

Active Member
Licensed User
Version 1.00b as been uploaded in the first post.

Change Details:
1. Used the IME object to cause the editor to resize itself automatically when the soft keyboard pops up, so the editor is full screen when the keyboard is not visible, and the keyboard doesn't overlap the editor when it pops up. This is a major break-through. Thank you Erel!!!
2. Removed the Fling menu option. Fling is now fully integrated into B4Script, and can't be turned off. Remember, if you have scrolled to a new position far away from the cursor, slide your finger to the side a little right where you want the cursor to move it. Just tapping the screen will cause the editor to jump back to where the cursor is instead of moving it. This is frustrating at times, but worked around easily enough.
3. Fixed FileDirInternal and FileDirDefaultExternal so that in IDE mode, the project folder will automatically be created when accessed, instead of having to be checked for and created in the script.
 
Last edited:

JesseW

Active Member
Licensed User
I am still working on B4Script in what little bit of free time I have while I am not driving. I have successfully modified it to compile to an APK and run a script. I have tested this aspect and uploaded a B4Script compiled app to the market. The app is called Recap + or can be found by searching for WarSOFT Apps. Recap + seems to be stable and I use it every day. It's free so you can test it if you like.

I am tweaking B4Script every time I turn around, so I'm not sure when I'll have a release to upload. There are so many ideas floating around in my head and no time to do them. For that, I apologize. If only I had some vacation...

Jesse
 

JesseW

Active Member
Licensed User
after adding the library, you must also either restart b4a or right click the libs tab (located at the bottom right of the window) and select refresh, then place a checkmark next to its entry in the libs tab.
 

JesseW

Active Member
Licensed User
Version 1.02 is now posted. Please see the first post for the download link.

Whats new?

1. Many new functions have been added. See the section Custom Functions in the Android Extensions help file for more info.

2. Folder creation and help file management are now automatic. You no longer have to manually move help files. Help files have been moved from the main project section to the Files dir of the project, so they'll be compiled into the B4Script.apk app and installed automatically.

3. The concept of projects is now working. The projects folder contains all the files that would normally go into the Files tab of B4A, which would be compiled into the DirAssets folder of a compiled app. See below...

4. Scripts can now be easily compiled into a working B4A app. There are now two b4a projects in the project folder, B4ScriptIDE and B4ScriptAPK. The B4ScriptAPK project has instructions at the top of the page for compiling scripts into app's.

Note: The file directory locations will now return different locations based on whether the script is a project script or not, and whether it is being run in the editor, or inside a compiled app.

FileDirAssets: If running as a non-project script it returns /mnt/sdcard/B4Script, which is shared by all non project scripts. If running as a project script it returns its project dir (ie. in a project called MyProject, it will return /mnt/sdcard/B4Script/Projects/MyProject). When running in a compiled app, it returns a reference to that apk's assets folder, the same as any compiled b4a app.

FileDirDefaultExternal: When running as a non-project script, it returns the standard B4Script DefaultExternal dir of /mnt/sdcard/Android/data/com.warsoftapps.b4script/files. When running as a project script, the project name is added, as in /mnt/sdcard/Android/data/com.warsoftapps.b4script/files/MyProject. When running in a compiled app, it returns the appropriate dir based on the package name assigned to the compiled app, which will be /mnt/sdcard/Android/data/<packagename>/files.

FileDirInternal: The internal dir is a protected system area that can only be reached by the app itself or a file browser in root mode. The only concern is that all non-project scripts share a single internal dir, called ScriptsData, so be careful. On that same note, you'll be asking for trouble if you create a project called ScriptsData!
 

JesseW

Active Member
Licensed User
Version 1.03 is now posted. Please see the first post for the download link.

Whats new?

1) I have added the Restart command which restarts the program currently in memory fresh, as if it had just been run. See #2 below for the menu warning.

2) I have pulled most of my hair out trying to figure out how to make Chain and Run work properly in all aspects, and admittedly, I cannot. One attempt has left them almost perfect, lacking only the restart of the activity itself. I have been able to simulate the activity restart in code for all aspects except for menu deconstruction. Sadly, at this time there is no way to remove menu items from the menu. Therefore, if you use Chain, Run or Restart, you will either have to use the same menu options for all the chained scripts, or build your own menu system. I will be building a custom menu system for a project I'm working on, so when I get it working, I will post it here.

3) MANY, many new function and constants have been added. You can see them at the bottom of the script module, or once compiled, from the new help file on the device.

4) The #INCLUDE directive is now working! Included scripts can have a main script section of code AND a section made up of Sub's, just like any script can, and it will process it like this: The main section of the included script, that section above the first Sub statement, replaces the #INCLUDE statement in the main script. The Sub's section of the included script is placed at the end of the main script. This completely separates the main code sections from the Sub's sections, and allows any number of scripts to include and be included containing multiple Sub's.

5) The Activity_Keypress(KeyCode) event is now exposed for scripts to use. As in B4A, return True to consume the event. This is helpful in the situation where you want to process the keystroke/button press without the activity processing it too, as in the case of #2 above, if for example, you have your own menu handling system. You can trap the menu button and consume the event, so Android doesn't try to popup the standard system menu as well. All of Basic4Android's KeyCodes constants, plus a few KeyCode functions have been added. See the help file on the device for more info...
 
Last edited:

agraham

Expert
Licensed User
This code seems to let you rebuild the menu as required
B4X:
Sub Activity_Create(FirstTime As Boolean)
   Activity.LoadLayout("Layout")
   Activity.AddMenuItem("one", "")
   Activity.AddMenuItem("two", "")
End Sub

....

Dim Obj1 As Reflector
Obj1.Target = Obj1.GetActivity
' clear the menu items, the original menu itself still exists
Obj1.SetField2("menuItems", Null) 
   
' add the required menu items
Activity.AddMenuItem("three", "")
Activity.AddMenuItem("four", "")
Activity.AddMenuItem("five", "")
   
' rebuild the menu
Obj1.RunMethod("invalidateOptionsMenu")
 

JesseW

Active Member
Licensed User
Andrew, I tried your code verbatim, and I got this exception:

B4X:
An error has occurred in sub: script_tmrchain_tick(java line: 4929)
java.lang.NoSuchMethodException: invalidateOptionsMenu
Continue?

The article in developer.android.com that I found says that method is for Android 3.0 and above, and I'm running 2.3.6 on my RAZR.

Here is the timer event I modified

B4X:
Sub tmrChain_Tick
   Dim ok As Boolean
   tmrChain.Enabled = False
   If ChainProgram.Length > 0 Then
      Program = ChainProgram
      ChainProgram = ""
   Else If RunProgram.Length > 0 Then
      Program = RunProgram
      RunProgram = ""
      Dim Args(0) As String   'resetting args() and saveddata() is what differentiates run from chain
      Dim SavedData(0) As String
   Else If Restarting Then
      Restarting = False
      Dim SavedData(0) As String
   End If
   ok = Blib.LoadCodeAsString(Include(Program))
   If ok Then
      RemoveAllViews
      Dim Obj1 As Reflector
      Obj1.Target = Obj1.GetActivity
      ' clear the menu items, the original menu itself still exists
      Obj1.SetField2("menuItems", Null) 
          
      ' add the required menu items
      Activity.AddMenuItem("three", "")
      Activity.AddMenuItem("four", "")
      Activity.AddMenuItem("five", "")
          
      ' rebuild the menu
      Obj1.RunMethod("invalidateOptionsMenu")
      FirstRunFlag = True
      ForceActivityResume = True
      Blib.Run(Args)
   Else
      Blib_Ended(Blib.ErrorString)
   End If   
End Sub

The complete project is attached. I don't know if it'll help or not, but I found this article long ago, I just don't have the java expertise to incorporate it.

Dynamically change Options Menu Items in Android « The Developer's Info

I super - appreciate your jumping in to help with this!!!
 
Last edited:

agraham

Expert
Licensed User
From the Timer help
Timers should be declared in Sub Process_Globals. Otherwise you may get multiple timers running when the activity is recreated.
However I don't think you need to use a Timer. As everything is running on the main thread you get the same effect by just calling the Sub directly.

Unfortunately without the availability of invalidateOptionsMenu I can't see any way to get the menu rebuilt from Basic4android code.

I would have thought that the best way to chain would be by letting the Script activity close and doing the checking and restarting logic in Main.Activity_Create. EDIT - I do of course mean Main.Activity_Resume :sign0161:
 
Last edited:

JesseW

Active Member
Licensed User
From the Timer help...

Good point. Fixed...

However I don't think you need to use a Timer. As everything is running on the main thread you get the same effect by just calling the Sub directly.

I used a timer to give the system just enough time to exit the blib_ended event. Are you saying I can call blib.load and blib.run from inside blib_ended, before it has finished? That'd be ok with me...

Unfortunately without the availability of invalidateOptionsMenu I can't see any way to get the menu rebuilt from Basic4android code.

Same wall I was up against. Why I finally gave up trying to do it from code. Better to just have a custom panel with buttons for the menu, and trap the menu button.

I would have thought that the best way to chain would be by letting the Script activity close and doing the checking and restarting logic in Main.Activity_Create. EDIT - I do of course mean Main.Activity_Resume :sign0161:

I would have really liked to have done it that way, but the timing is the problem. It just doesn't cooperate for me in straight-forward code. And if I get the timing right for a 100 line script, it doesn't work on a 1000 line script. What works for a larger script is just dead waiting time for smaller scripts. And I've a fast device. Whose to say what timing works on my dual core 1.2ghz RAZR would work on my old 500mhz Droid? I decided not to go this way because of too many variables, and if timing is stretched out to literally a few seconds to cover all possible sceanrios, the delay between scripts becomes unbearable. Chaining should be as instantaneous as possible.

That said, if you are up for a challenge, and you can get it working correctly, quickly and elegantly, either in the B4A code, or as an integral part of blib itself, I'd gladly pay you $100usd. (this is one of those times I'd like to message you privately)

Thanks for your help Andrew. Your're the best :)
 
Last edited:

agraham

Expert
Licensed User
Are you saying I can call blib.load and blib.run from inside blib_ended, before it has finished?
I missed that, it would probably be OK but there would be some recursion happening so you are correct, it is better with a Timer.

I would have really liked to have done it that way, but the timing is the problem.
I have to admit I don't understand where the timing dependancy comes from as I think that both the Script and the Main activities are running on the same thread, as does the timer tick code so it should all be pretty deterministic. I can see that a timer would be needed to allow Activity_Resume to complete but I don't see where the script length affects things.

I expected the sequence to happen as follows when a script wants to chain.

Script.Activity_Pause runs after the script has requested Activity.Finish and returns to the message loop.

Android, running from the message loop closes the Script Activity and sets up the Main activity and calls Main.Activity_Resume which checks for chaining and if so starts a Timer. The actual Timer interval should be unimportant as it as can't be actioned until the app returns to the message loop.

Main.Activity_Resume returns and Android, running from the message loop finishes anything it has to do to get the Main activity running and returns to the message loop which waits for any events to occur.

The message loop sees the Timer message and calls Timer_Tick which calls blib.load and blib.run. This should be no different from doing the same things from a Button_Click like when the original script was started so I'm puzzled as to where the timing dependancy on script length occurs.
 

JesseW

Active Member
Licensed User
I am puzzled as well, but I had it working at one point by switching activities with a short test script, but when I tried it with a 1000 line script, the Script activity would never come up.

From your timeline analysis, I deduct that Main.activity has a timer, but in your last paragraph...

The message loop sees the Timer message and calls Timer_Tick which calls blib.load and blib.run.

...I am left uncertain whether the timer should be in the Main or Script activity. If in Main, I can't call blib.load and blib.run, because they're in Script, and so the timer should call StartActivity("Script"), correct? If in Script, can it run when that activity is no longer focused?

In my attempts in the past, everything ran fine up until StartActivity("Script") was called, and it just wouldn't. If I unfocused the editor, like pressing the Home button, then long-press home for running apps and went back into it, then the Script activity would be focused, but not without all the run-around. It was very frustrating.

When I stopped trying to do it from Main, and created a new activity Chain, and changed the order from: exit Script - enter Main - process new script - start Script, to: start Chain - process new script - exit Chain - enter Script, it seemed to work a little better, but again, when a long script was calling the Chain statement, it would fall through back to Main instead of Script. I even tried catching it in main and trying to start script again, to no avail. It just wouldn't come up. It was still in the middle of something, I guess...

I am attaching a previous version of the project, 1.02, which uses the Chain activity, and will get up an example for you that I will post here in a little while. I looked for my initial attempt without the Chain activity, but I think it's on the BasicLibIde thread.
 

JesseW

Active Member
Licensed User
Here is the only long script I can let out of my pc for now. It's an actual market app called Recap+, and contains all the project files, with the script slightly modified for this example. To use it, simply unzip the files into a folder under Projects called 'test'. Then it will be available in the Open Project menu. I had to remove the large splash graphic so the forum would allow its upload, so when you run it, you'll be seeing the small graphic stretched out.

I've altered the settings menu option to chain to test2.b4s instead of its normal processing, which is the same script with a different activity title/label. When I run this, all is well until I touch the Settings menu option, then it flashes momentarily then exits back to the editor. What I find interesting, is if I then touch the Run menu option, it runs test2.b4s, the chained to script, not test.b4s which is still active in the editor. So it seems Chain sets up Script correctly, but Script just can't process it at the moment. Also, when the Chain activity exits, it seems to skip right over Script for some reason (is it in the middle of deconstruction?) and land in Main.

I've also uploaded a second test called 'shorttest' which is two very short scripts, and this test runs fine. You'll see what I mean. This is the best example I can give you at the moment how script length affects chaining.

thanks :)

Edit: removed test.zip
 

Attachments

  • shorttest.zip
    320 bytes · Views: 304
Last edited:

JesseW

Active Member
Licensed User
Andrew, could it be the number of views causing th issue instead of the length of the script? the test example has almost 200 labels. when I get a chance, I'm going to try removeallviews as part of the chain.

I just discovered that using the chain activity method, the menu items don't reset, so I wil hav to scrap that way of doing it altogether...
 
Last edited:

JesseW

Active Member
Licensed User
Andrew, I got the chaining working with just the main and script activities. Running the shorttest project, it will switch at 300ms. Using the longer test project, it wants at least 325ms. This is a dramatic improvement from the 600-1000ms from my last attempt, and I believe the difference is I issue a RemoveAllViews just before the activity.finish.

The menu items from the first script are all gone when the chained script runs, which is a good thing, but there is a visible switching, and I don't like that. Unless you have any further ideas or suggestions, I believe I will stick with the script activity performing its own maintenance, and building a custom menu from code. It's quick, seamless, and I don't have to worry if the 325ms I've given it will work for a particular old device running an older android version.

Here is the project...

And as always, thank you so much for your help :)
 

Attachments

  • B4Script.1.03.02.zip
    82.4 KB · Views: 380

JesseW

Active Member
Licensed User
Version 1.04 has been posted to the first message in the thread.

* Fixed Chain/Run/Restart when called from the initial code block above the first sub.
* Various other bug fixes...
* Created menu option in Debug to Merge all the #Include files. While in 'merged' mode, the script cannot be altered or saved. None of the menu options will work except to load or create a new script, or to open or close a project. This is to help when debugging scripts that use #Include's and the script errors with a line number that doesn't match the code in the editor. You can now see the entire merged script at a glance, as well as find the code that caused the error.

A future version will allow merging of sub's, where if a sub in an included file already exists in the code that calls #Include, the code inside the included sub - end sub will be added to the top of the existing code in the sub of the original script. This will allow maintenance routines, for example, to be defined in a common include file so each script of a project doesn't have to have identical code.
 
Last edited:
Top