2017년 8월 21일 월요일

Fun with the clock


The clock in App Inventor has many uses.  You can use it to animate sprites on a canvas, create a timer, design a calendar, and much more.

Here's a couple things I've done with it:

Display text on a label as it's typed in a text box
For this example, add a text box, a label, and a clock to the design screen. Remove the initial text from the label, and set the clock's interval to 50 milliseconds (this will cause the clock to fire every quarter of a second - yeah, very fast).  In the blocks editor, drag out he Clock.Timer event, place inside it a set Label.Text to block and plug the Textbox.Text into that.  Now, anytime you enter text into the text box, it should automatically display on the label as you type.

Determine whether a given year is a leap year
I've been playing around with making a calendar app, and although I don't know if I'll ever finish it, I did need to figure out how to determine whether a given year the user selects is a leap year, and thus alter the number of days available in the month of February.  I was lost at first with how to manipulate the blocks available for the clock to determine a leap year.  I asked myself "How do I determine a year is a leap year?" and then I asked Google.  It turns out that a leap year is any year evenly divisible by 4 but not by 100, unless that same year is evenly divisible by 400.  Confusing enough?  It was for me.  I then stumbled across the Wikipedia leap year article which listed out the psuedocode for programming and I also learned about modular division at the same time.  The combination of the two gave me the answer I needed.  Using the modulo block in App Inventor was able to easily determine whether a given year is evenly divisible by 4 but not 100 unless by 400.  In the picture to the left I have a Clock1.Now block plugged into the instant plug for the Clock1.Year but this can easily be replaced by creating any instant you want with any year.  If you were to choose 1914 or 2763 it would determine for you whether those years are leap years.

Enable a button when text is entered in a text box
This example is similar to the one above about displaying text, except that I want to enable a submit button only after the user has entered a username into the text box of a loginscreen.  I prefer to do it this way so I don't have to worry about error handling or warning the user that they haven't entered their username before trying to log in.  I could handle it by popping up a notification if they pressed submit and saying "Hey!  You didn't enter your username!"  but this creates unnecessary blocks in my opinion.  With this example, I just have to check whether the username is already created and if so then I do my log in procedures and stuff.  If it's not, they have to try again.  Very simple.  Give it a shot.

Calculate milliseconds in minutes, hours and days
When dealing with instants and such with the clock, there are a number of procedures that calculate using milliseconds, so it can be advantageous to know how to find milliseconds in a given time block. To prepare for this, we figure out how many milliseconds in one second (1000), then just multiply that number by how many seconds in a minute (60), then multiply that by minutes in an hour (60) and finally hours in a day (24).  Since we can't make these calculations when defining our variables, we simply initialize all but seconds as 0 and do the multiplication in the Screen.Initialize event.



Web Scraping Tester


Note Result: 25 contains the level value being sought:

The core blocks:

This is a general-purpose web scraper for testing your URLs and prefix/suffix/tag values.
You can save items between sessions which consist of:

⦁ URL of the web page which contains the data value to be mined
⦁ prefix text which occurs right before the data value
⦁ suffix text which occurs right after the data value
⦁ a description to be displayed in an items ListPicker

For the included example URL-
the source is [...level":25,...]
the prefix is [level":]
the suffix is [,]
the scraped result: [25]

HTML or XML tags could be used as well:

[...<actor>Charlie Chaplin</actor>...]
where the prefix is [<actor>]
and the suffix is [</actor>]
and the result is [Charlie Chaplin]

















--

Need Snipplets of how to control Access/Block Apps and Standard System Functions


Im having a problem finding any kind of information regarding Code that has been created using App Inventor 2 block Coding that would allow the Developer to control Access to other installed Apps and Standard System Functions.. 

There are Apps on the market that perform these operations such as AppLock and Smart App Lock. 

Does anyone know of any snipplets or just have an understanding of this kind of coding that can be used with App Inventor 2 block coding?

--

ActivityStarter

A component that can launch an activity using the StartActivity method.
Activities that can be launched include:

⦁ Starting another App Inventor for Android app. To do so, first find out the class of the other application by downloading the source code and using a file explorer or unzip utility to find a file named "youngandroidproject/project.properties". The first line of the file will start with "main=" and be followed by the class name; for example, main=com.gmail.Bitdiddle.Ben.HelloPurr.Screen1. (The first components indicate that it was created by Ben.Bi...@gmail.com.) To make your ActivityStarter launch this application, set the following properties:

  ⚬ ActivityPackage to the class name, dropping the last component (for example, com.gmail.Bitdiddle.Ben.HelloPurr)
  ⚬ ActivityClass to the entire class name (for example, com.gmail.Bitdiddle.Ben.HelloPurr.Screen1)

⦁ Starting the camera application by setting the following properties:

  ⚬ Action: android.intent.action.MAIN
  ⚬ ActivityPackage: com.android.camera
  ⚬ ActivityClass: com.android.camera.Camera

⦁ Performing web search. Assuming the term you want to search for is "vampire" (feel free to substitute your own choice), set the properties to:

  ⚬ Action: android.intent.action.WEB_SEARCH
  ⚬ ExtraKey: query
  ⚬ ExtraValue: vampire
  ⚬ ActivityPackage: com.google.android.providers.enhancedgooglesearch
  ⚬ ActivityClass: com.google.android.providers.enhancedgooglesearch.Launcher

⦁ Opening a browser to a specified web page. Assuming the page you want to go to is "www.facebook.com" (feel free to substitute your own choice), set the properties to:

  ⚬ Action: android.intent.action.VIEW
  ⚬ DataUri: http://www.facebook.com


Using the Activity Starter Component

The activity starter component lets you combine applications by having one application start up other applications. Activity Starter is mostly for advanced developers, but it's a key way to extend the App Inventor, because it means lets you take advantage of applications written by others, and created with other development frameworks.
The apps you start can be App Inventor apps created by you or others; apps like Camera and Maps that are pre-installed on the device; or any app at all, created using App Inventor or not, as long as you have the necessary information to supply to the activity starter.
For applications that are appropriately designed, you can pass values to the applications when starting it. You can also start an application and get back a result from it to use in further processing, provided that the application is designed to return a result. Presently, you can pass and receive text values only.
To start another application, you must supply certain control information to the Android operating system. You do this by setting various properties of Activity Starter before calling the StartActivity method. This section gives some examples.

Starting Another App Inventor Application from your App Inventor App

You can start another app that was created with App Inventor if you know its package name and class name. If you have the source code of the app, you can find these names as follows:

1. Download the source code to your computer.
2. Using a file explorer or unzip utility, find the file youngandroidproject/project.properties.
3. The first line will start with " main= ". Everything after that is the package and class name.

For example, here is a first line you might see for an App named HelloPurr.:

main=appinventor.ai_HomerSimpson.HelloPurr

The HomerSimpson part of the name comes from the App Inventor user account.

To start this app, you would use an activity starter component with these properties:

ActivityPackage: appinventor.ai_HomerSimpson.HelloPurr 
ActivityClass: appinventor.ai_HomerSimpson.HelloPurr.Screen1



Invoking the activity starter's StartActivity method will start HelloPurr. When HelloPurr finishes (if it does), the original app'sActivityStarter.AfterActivity method will be invoked.

Note: If you are going to start another App Inventor app, make sure you use the correct package name. For example, if someone posts the source code (zip file) for an app, and you repackage that app, you'll end up with a different package name than he had. In cases of doubt, or if you don't have the source code, start the activity by hand on the phone and run "adb logcat" to view the Android system log and see what was actually started, as explained below in "Figuring out how to set the properties".

Note: If you will be starting a second App Inventor app that you yourself are writing, it's generally easier and more convenient to design the whole thing as a single multiple screen app, rather than creating two separate apps. See the section below on "Activity Starter versus Multiple Screen Apps".

Starting a Builtin Phone Application from your App Inventor App

Apps that come with the phone can be invoked using package names and class names, as above. Android apps can also launch responses to anintent , which is the Android operating system's way of specifying something to do without necessarily designating a particular app. You can find information about intents (written for advanced developers) in the Android system documentation.

Some apps are designed to take extra information when they are launched. For example, maps can take geographic information that specifies which map to display. Another example is launching a Web search with extra information that specifies the text to search for. You must consult the documentation for the particular app to learn what this extra information is and how to specify it. Generally, you specify the information by setting the activity starter's properties just before the other app is launched.

Here are some examples:

Start the Camera

To launch the Android Camera app, use an activity starter with these properties:

Action: android.intent.action.MAIN 
ActivityPackage: com.google.android.camera 
ActivityClass: com.android.camera.Camera


This is pretty much what the App Inventor Camera component does, although it is much more convenient to use the Camera component.

Launch a Web search

To launch a Web search for a particular query, such as "Homer Simpson", use an activity starter with these properties:

Action: android.intent.action.WEB_SEARCH 
ExtraKey: query 
ExtraValue: Homer Simpson 
ActivityPackage: com.google.android.providers.enhancedgooglesearch 
ActivityClass: com.google.android.providers.enhancedgooglesearch.Launcher

Open the browser to a Web page

Use these activity starter properties to open a specific web page:
Action: android.intent.action.VIEW 
DataUri: http://news.google.com

Start the mailer with pre-addressed message

To start the Android mailer application, use the action android.intent.action.VIEW . You can use Activity starter's DataUri property to specify the recipient, the subject, and the body of the message. In each case, starting the activity will bring up the Android mailer, and you can complete the message and then press "Send".

For example, if you specify:

Action: android.intent.action.VIEW 
DataUri: mailto:sa...@northpole.com



then starting the activity will bring up the mailer, with the addressee filed in.

If you specify:

Action: android.intent.action.VIEW 
DataUri: mailto:sa...@northpole.com?subject=Please Santa&body=Bring me a pony.



then starting the activity will bring up the mailer, with the addressee, the subject, and the body filled in. You can use the mailer to edit these before sending the message, if you prefer.

The DataURI here must be a URL encoded message designed to work with the internet mailto service. Search the Web to find appropriate documentation and tools for creating these, for example Elements of a Mailto: URL

Show a map for a location

If you know the latitude and a longitude of a location, you can show a map using an activity starter with these properties to show a map of the area:

Action: android.intent.action.VIEW 
DataUri: geo:37.8,-122.23?z=23



The format of the DataURI is specific to the app. In this example, the URI specifies a z (zoom) of 23, which is the largest zoom value. Zoom value is optional and ranges from 1 (the entire Earth) to 23.

If you know the zip code, you can set the activity starter properties as follows:

Action: android.intent.action.VIEW 
DataUri: geo:0,0&q=94043



If you have a street address, you can use a DataUri that encodes the address with a scheme called URL encoding:

Action: android.intent.action.VIEW 
DataUri: geo:0,0&q=5000% 20MacArthurBlvd%20Oakland%2CCA



Generally in URI encoding the only characters you have to replace are spaces ( %20 ) and punctuation marks, such as comma ( %2C ) and period ( %2E ).

Play a YouTube video

You'll need to know the URI of the YouTube video. Then set the Activity Starter properties as

Action: android.intent.action.VIEW 
ActivityPackage: com.google.android.youtube 
ActivityClass: com.google.android.youtube.PlayerActivity


and set the Data URI to the URI of the video to be played, for example:


Figuring out how to set the properties

If you can't find documentation for the activities you want to start, one way to figure out how to set the properties is to start up the activity manually and look at what appears in the Android System Log. For example, if you use YouTube to play a video, you'll see in the log:

I/ActivityManager( 86): Starting activity: Intent { act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=http://www.youtube.com/watch?v=8ADwPLSFeY8 flg=0x3800000 cmp=com.google.android.youtube/.PlayerActivity }

If you can find the "cmp=" string, then the ActivityPackage is the part before the slash, and the ActivityClass is is the entire "cmp=" part, without the slash character. As in the YouTube example, there may also be "dat=" information that can specify with the DataUri property.

Starting arbitrary apps

You can use the Activity Starter to start any activity at all if you know the package name and class name, or the appropriate intent. Some developers document these intents for the benefit of other Android developers. For hints on starting other apps using intents, see the Android API documentation or search the Android developer forums.

If you have an app on your phone and you don't have the source code, you might still be able figure out the package name and class name (and sometimes the intent) by launching the app and inspecting the Android system log, as indicated above.

Receiving results from apps that you start

Some apps are constructed to return a result. You can see that result as the result argument of the activity starter's AfterActivity event. Currently, App Inventor can receive text results only.

Returning results from App Inventor apps, and getting the result

You can create App Inventor apps that return a (text) result to their callers, so they can be used as subroutines. To return a result, invoke the commandclose screen with plain text (located in the Control drawer). Your subroutine app will terminate, and the argument of close screen with plain textwill become available to the app that called it. If the calling app was itself an App Inventor app that used an activity starter, it will see that text as the argument to the activity starter's AfterActivity event.

In more detail, suppose there are two App Inventor apps: A SubroutineApp designed to be started with an activity starter and return a value, and aCallerApp that uses an ActivityStarter to call SubroutineApp . To return the result, SubroutineApp executes close screen with plain text , giving it as argument the result (text only) that should be returned to the caller.

On the caller side, CallerApp sets up its Activity Starter with the correct package name and class name for starting SubroutineApp . It must also set theActivityStarter.ResultName property to the special text string APP_INVENTOR_RESULT . Then CallerApp starts the SubroutineApp activity. When the subroutine finishes, the Activity Starter's AfterActivity event triggers, and the result that was passed back from SubroutineApp will be available as theresult argument to AfterActivity . That same information is available as the ActivityStarter's Result property.

Calling App Inventor Apps and passing values to them

If you are writing an App Inventor CallerApp to call an App Inventor SubroutineApp , you can pass a text value to SubroutineApp . To do this, use an Activity Starter in CallerApp with the ExtraKey property to set to the special tag APP_INVENTOR_START and the ExtraValue property set to the text you want to pass. The SubroutineApp can retrieve that value by using the get start plain text block from the Control drawer.
By passing and returning results, you can combine several App Inventor apps, both apps you write, as well as apps you share with others.

Returning results from arbitrary applications

Getting values back from other applications is like getting values back from App Inventor apps. In general in Android, an activity will return a result that is designated by a name, where the result is designated by a name, where the name is specified with the Activity Starter's ResultName property. The name to use for App Inventor apps is APP_INVENTOR_RESULT , as described above. Other applications, not created with App Inventor, will use other names, and you'll need to know those names in order get values back from those applications. In general, you'll need to consult documentation about the app you want to use as a subroutine. Some developers provide this information, or sometimes you'll have access to the source code.

Not all Android apps use the Result and ResultName mechanism. For example, some apps return information via the properties ResultType andResultUri . Again, you'll need to have information from the app developer to know which of these to use.
For advanced developers: More specifically (with reference to the Android developer documentation) an app can be designed to return an intent . The Activity starter uses the specified ResultName to access intent.getStringExtra(resultName) to produce the result. The values for ResultType andResultUri come from intent.getType() and intent.getDataString() .

Example: Picking files from the SD Card

Here's an example that illustrates using a third-party application:
AndExplorer from Lysesoft is an application that lets you pick files for your SD card. You can call AndExplorer with an activity starter to add a file picking capability to your application. You'll need to have AndExplorer installed on your phone. You can get it from the Android Market.

To start AndExplorer to pick a file, use an ActivityStarter with:

Action: android.intent.action.PICK 
dataType: vnd.android.cursor.dir/lysesoft.andexplorer.file 
dataURI: file:///sdcard

When you start the activity and pick a file, the resulting file name will be available as ResultUri . Also, ResultType will give the type of the file, for example, image/jpeg or audio/mpeg. Using this, you can write an app that lets you pick a file from the SD card and either displays the image or plays the music track as appropriate.

Is the application available?

If your app calls other apps as activities, you'll want to check that those other apps are available on your user's phone before trying to start them. You can check this using the Activity Starter method ResolveActivity , which returns the name of the Activity that would be started, given the package or intent information you've provided. If this name is blank, then the required application is not present, and you can warn your user.

Using the Activity Starter versus using multiple screens

The sections above explain how you can create an App Inventor app that calls another App Inventor app, perhaps with passing and returning text values. If you will be writing both apps, it's probably better to make a single multiscreen app rather than create two apps and use the Activity Starter. This will simplify things for your users, because they will need install only one app on their device. Also, with multiple screen apps, you can pass and return lists as values rather than just text, and you can share values between the screens with TinyDB. See the documentation on multiple screen apps for details.

Note on upgrading old apps

The activity starter commands described here have changed from earlier releases, which used close screen with result and get start text , rather than the newer close screen with plain text and get start plain text . If you load the source for an app from before 2012 and release 66, App Inventor will flag the old blocks and require you to replace them with the new versions.

--
as SteveJG said: taking a look at the documentation helps...
and talking about the Activity Starter, see also here 

--
Thank you so very much for your speedy reply Steve, 

You have actually addressed many of my questions/concerns related to use of the the Activity Starter. 

But the primary coding that im looking for would simply be coding that gathers a list of the Apps installed on the device along with some of the more Common Functions (contacts, message history, call history, photos) that are installed on the Android device, And then give the option to block them or allow them to be open or be viewed while my App is running in the background.

I know there may be a function mentioned in your reply that does this, but I just may be a lil to green to perceive the wider use of the those activity functions..

The portion titled: Calling App Inventor Apps and passing values to them:  seems it may contain information related to limiting access to third party apps that have been previously installed, but i cant clearly interpret how i would use this information in my App.

Is there any Examples or Snippet's that could clarify how these techniques are implemented into an app for the type of Locking App that im creating?

--
I guess my issue is that i don't know where to start, I haven't found any discussions or example snippets of how to trigger (deny/allow) access to other programs that may be installed on the device.

And my understanding is not recognizing which actions would be a good place to start. 

I do understand that a broader understanding is always the best policy, but i also believe that sometimes (at lease for for me) it takes specific tasks of interest to show us (me) the path to that Broader Understanding.

I have read much documentation, post and tutorials on App Inventor 2, none of which would point me toward understanding what im trying to accomplish.. Im sure its there I just dont know where to start..  

There are tons of information online about Activity Starter, but at this point, Activity Starter is simply the tool.. what im looking for is the instructions of how to use it in a way that none of the information i have ran across explains. 

I may just need to convert (what i have so far) with Alt Bridge into Eclipse and start from there, Im sure that there is plenty to documentation directly related to the actions im trying to perform, I just wish they could have been accomplished with app inventor.

--
while my App is running in the background.
App Inventor apps can't run in the background
 how to trigger (deny/allow) access to other programs that may be installed on the device.
unfortunately this not possible with App Inventor

--
Thanks for clearing that up for me Taifun

--