sexta-feira, 8 de março de 2013

Maps in Android


Hello everyone.

In this post, it will be presented the concept of Maps in Android.

To run a map application in Android, besides the creation of it's source code (final step), we need to follow some basic steps, which are: configure the project for the GoogleAPI's SDK; include the Google Maps library, and the Internet permission in the AndroidManifest.xml; get the access key of the Google Maps. So, let's start this steps.

Step 1
The first thing we need to do is to configure our project to some GoogleAPI SDK. What this means? Means that we need to include some SDK that have the map's libraries of Google. This can be done like shown below.


Now, we just need to follow the steps described here to create our project.

Step 2
To insert a map in a screen, we need to include the package com.google.android.maps.MapView. This package isn't default in Android. To import it, we need to add a reference for him in the AndroidManifest.xml file. This can be done using the tag <uses-library>. We also need to give Internet permission to our application, using the tag <uses-permission android:name="android.permission.INTERNET"/>. This 2 modifications of the AndroidManifest.xml file are shown below.


Step 3
Now we need to get the access key to Google Maps. For this, we need to access this site and enter with the fingerprint code of your computer. This fingerprint can be obtained with the help of the file debug.keystore. The location of this file is different in each operational system:


  • Windows XP → C:\Documents and Settings\<user>\Local Settings\Application Data\Android\debug.keystore
  • Windows Vista → C:\Users\<user>\AppData\Local\Android\debug.keystore
  • Windows 7 → C:\Users\<user>\.android\debug.keystore
  • OS X e Linux → ~/.android/debug.keystore


The location of this file can be found at Eclipse, through the menus Windows → Preferences → Android → Build, as shown below.


Now that we now the location of debug.keystore, we can generate the fingerprint of the Google Maps access key. This fingerprint can be generated through the command below (for any operational system):

C:\> keytool -v -list -alias androiddebugkey -keystore <local_debug_keystore> -storepass android -keypass android

OBS.: In the case above, the command was typed in Windows.

After this command be executed, will be generated the "Certificate fingerprint (MD5)", as shown below.


Now, to we get the Google Maps key, we need to access this site. If you don't have a Gmail account, it would be necessary to create one. Otherwise, we just need to login and type the fingerprint in the field "My certificate's MD5 fingerprint:" and press the button "Generate API Key". After type this button, another screen will be shown as result, as shown below.


In my case, the key is 03NHxysjybHVX2sHs87S1zn4LGQw20BuQ_PuOGQ. This is the string that I must use (in my machine) to use the class com.google.android.maps.MapView.

To pass this call to our application, there is two ways: through Java source code or through XML layout:


  • Java → We must use in the event onCreate() of the Activity that extends the class MapActivity, as shown below.




  • XML → We must use in the MapView of our XML layout file, as shown below.



Now we can start to write in the source code of our application.

Step 4
To we create a screen with maps, we need to create a child Activity of com.google.android.maps.MapActivity. Then, we need to create a component of the type com.google.android.maps.MapView in the event onCreate() and call the method setContentView().

Below are shown the Java and the XML files, that together enable the use of maps in Android. In this specific case, the maps API key was declared in the layout XML file.



The generated application is shown below.


Above the maps API was declared using the XML file. If it was declared in the Java file, we wouldn't need the XML file. So, the Java file would be as follows.


The example above was the most basic possible. Below are shown more interesting examples, and in the next topic of this blog, more useful examples.

An interesting example is to set a coordenate into the center of a map. For this, we use the class com.google.android.maps.GeoPoint, which represents a location through latitude and longitude coordenates. Also, they must use the microdegrees notation. This notation reffers to a grade multiplied by 1E6, which is the same of 1.000.000. This multiplication is made to force the generated value to be numeric, without float values.

A good example of this funcionality is shown below. In this example, a coordenate is centered in the map, and is given a zoom of factor15 in this coordenate. In Android, the zoom values varies from 1 to 21.


The result is shown below.


-----


That's all. Now we can call maps in our Android applications. There are many other map options. However, they'll be seen in other post's of this blog.

If someone has a question, suggestion or criticism, feel at ease.

sexta-feira, 2 de novembro de 2012

Menus in Android



Hello everyone.

In this post, it'll be seen the concept of Menus on Android.

In devices that have Android OS, usually there are 3 physical buttons: Home, Back and Menu. The Home button is the button that returns to the home screen and, when held, shows the user all currently open applications. The Back button is the button that exits the current screen of the system. And the Menu button is a button that calls specific functions in each application. This varies from application to application.

There are several types of menu on Android:


  • Options Menu → This is the most common type of menu in Android. For him to be called, simply click the menu physical button.
  • Context Menu → This menu is called when we click and hold a particular visual component of Android, such as a button. In doing so, it will be shown on the screen a list of options, which is our context menu.
  • PopUp Menu → This is the most current implementation of menu. This menu is shown on Action Bar, toolbars that are shown at the top of the screen. The Action Bar in Android were created in the API 11 (3.0 or Honeycomb), and since then appears in all subsequent versions of API's. These menus appear in the Action Bar, and Android devices that have no physical button menu.


These types of menu will be presented below, divided into 3 different sections.

Options Menu
A OptionMenu is shown below.


It can be called by both by Java source code, as by an XML file. In both cases, the implementation of a menu is made by the method public boolean onCreateOptionsMenu(Menu menu). The creation of a menu via Java is shown below:


In the above source code, we can see 4 arguments in the method MenuItem.add:


  • group → Used to define in which group the menu should appear. Usually this value is 0.
  • id → Identifier of the menu item. This parameter is used to differentiate the actions generated by the menu. Each event must perform a different action, and for that the id of the item can be used. It is usually created a constant to identify each item.
  • order → Indicates the order of this item, or 0 if the order is not important.
  • text → Represents the text of this menu option.


And now, below we have the creation of the menu options via XML.


And how it's referenced in Java.


To invoke this menu, simply click the Menu physical button. Then, the menu options are shown on the screen. And for some action to occurs when you click a menu option, we need to use another event, called public boolean onOptionsItemSelected(MenuItem item). The declaration of this method is shown below.


And the execution of this action, below.


And it's done! We already know how to create an OptionsMenu.

Context Menu
This type of menu is activated when we click and hold on any visual component, such as a button. A ContextMenu is shown below.


To invoke a ContextMenu, we need to declare some methods in the source code of Java. The image below shows a source code.


Note that in this source code we have new events and methods:


  • registerForContextMenu(mButton) → With this method, we recorded which visual component will receive the context menu event.
  • public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
    With this method, we do a similar work to the method onCreateOptionMenu (report which XML file contains the menu options that will be triggered by context menu).
  • public boolean onContextItemSelected(MenuItem item) → Faz o trabalho análogo ao método onOptionsItemSelected. Ou seja, chama a ação que a opção de menu clicada possui.
    Does the analogous work of the method onOptionsItemSelected.


There is not much secret about the ContextMenu.

PopUp Menu
So far, we have learned how to call a OptionsMenu and a ContextMenu. Both can be used at the same time. However, with the PopUpMenu, the situation is somewhat different.

A PopUpMenu is shown below:


The PopUpMenu is a menu that is shown in the ActionBar of an Activity. A ActionBar is a component that was created from the Android API 11 (3.0 or Honeycomb). It's toolbars shown at the top of the screen. Since they were created, they appear in all subsequent API versions.

However, with the creation of this menu, the OptionsMenu stopped working. In Android versions higher than 3.0, OptionsMenu no longer work natively. There are ways to make it work, but they are not standard.

For we use a PopUpMenu, we just need to be in a project with API 3.0 (or higher), and use the same methods and events explained above in the section on OptionsMenu.

For further informations, a good tip is this link.

-----

That's all. Now we can call our menus in Android applications. There are many other menu options, but the main (and most used) were exposed in this topic.

If someone has a question, suggestion or criticism, feel at ease.

sexta-feira, 12 de outubro de 2012

How to navigate between screens in Android


Hello everyone.

Up to this topic, we have learned how to install Android, create a project and even create fine layouts. What next? So far, in all examples seen was used at most one screen for example. The next step to be taken is to learn to navigate in more than one screen in the same application.

On Android, each screen is a Java class that extends the Activity class. To navigate between more than one Activity, we use the Intent class. If we are in an Activity and want to go to another, we have to call an Intent (ie have the "intention" of changing from one screen to another).

To understand the concept of Intent, we will create three very simple examples that basically pass through multiple screens of the same application. In the 1st example, we will create a simple transition from one screen to another. In the 2nd example, we will create a transition from one screen to another where the source screen sends a variable to the target screen. In the 3rd example, we will create a transition from one screen to another where the target screen returns a value to the source screen. This post will be divided between these three examples.

Simple transition from a source screen to a target screen
In Android, when we create a project in Eclipse, the AndroidManifest.xml file is generated, which is a configuration file where we report various informations, such as which screens exists in the application, which is the minimum and maximum API of the Android API that the application may run, among others. So, the first step to be taken in the creation of our example is to tell the AndroidManifest.xml the screens that we use in our application. Suppose we have 3 screens in our application: Screen1Activity.java, Screen2Activity.java Screen3Activity.java (is advised on Android to have the name of an Activity with the posfix "Activity"). So we need to declare them in the AndroidManifest.xml file, as shown below:



Agora que já temos as Activity's declaradas no AndroidManifest.xml, o próximo passo será criar o layout de cada uma dessas telas. De início, criaremos algo bem simples, como uma TextView sendo mostrada no centro da tela. Algo como isso:



For each screen, the parameter android:text="@string/screen1_title" shall be adjusted to the proper names (for Screen2 for example, the parameter is android:text="@string/screen2_title", and similarly for Screen3).

Then we need to create the Activity's of these screens (Java classes extending the Activity class). They basically follow this model:



Now that we created all our screens, its layout's, and declared all in AndroidManifest.xml, we can finally deal with the Intent's, allowing us to navigate among these 3 screens.

To navigate between screens, we need to create a user input device to select it when this transition occurs between screens. The best device for this case is to create a Button that, when clicked, change the current screen of the application. For that, we'll create a Button in Screen1Activity.java and other Button in Screen2Activity.java. The idea is that the transition occurs from the Screen1 to Screen2, and from Screen2 to Screen3.

Modifying the layout of Screen1, we have the following content in the XML file:



And it's layout will be as shown below:



Now, we need to map the id of the Button in our Activity (as is taught in the previous post). Modifying the structure of the source code of the screen Screen1Activity.java, we have the following content:



Now, we just need to implement the call to Screen2. For we call another screen in Android, we use an Intent. The syntax of a call to a class Intent is shown below:


The constructor of Intent class is: Intent intent = new Intent(packageContext, cls). The argument "packageContext" is the context of the current Activity. The argument "cls" is the class of Activity for which the current Activity want to go. In the image above, the values ​​of these arguments are, respectively, "Screen1Activity.this" and "Screen2Activity.class". So, we have the "intention" to migrate from Screen1 to Screen2.

The complete source code of Screen1Activity.java is shown below:



Now we simply need to adapt this source code for Screen2Activity.java, to have implemented the transition between Screen2 and Screen3. And it's done! We'll have implemented an application with several screens, and the transition between them.

Now, we will see how to implement a transition between two screens in which the target screen will send data to the target screen.

Transition from a source screen to a target screen with sent information between them
In the transition above, we used the method startActivity() to make the transition between screens. However, it was an easy transition, without sending information. This time, we'll send information from one screen to another. To perform this kind of task, we'll use again the method startActivity(). However, we'll modify a bit it's structure, as shown below:



The above image is the updated content of the event onClick(). What has changed here is that was included a Bundle on the Intent that calls the next screen. In Android, Bundle is the class that stores what is sent from one screen to another. This class has several methods. In the image above, we can see the method putString(). This method receives the "key" that will pass the string to the next screen, and it's value. The key is a value (always String) which we use to obtain, in the target screen, the passed data from one screen to another.

Now that we transmited data from the source screen to the target screen, we need to capture these data in the target screen (in this case, in Screen2Activity.java). This is done through the method getIntent().getExtras(), which returns a Bundle. Below is shown the source code of a custom method that performs this task.



Some comments need to be made about the image above:

  • We have to check if the extras are null or not. This is very important because we can call a screen from different parent screens. For example, both Screen1 as Screen2 may call Screen3. And if Screen1 send data to Screen3, the extras from the image above won't be null. But if Screen2 don't send data to Screen3, the extras from the image above will be null.
  • mTextView is an attribute of Screen2Activity.java, which is nothing more than the TextView of this screen. As we are getting data from the previous screen, to check whether these data come from Screen1 to Screen2, we'll update this TextView.

The complete source code for this screen is shown below:



And it's done! We already know how to pass data from one screen to another. Following this topic, we will see how to implement a transition between two screens when the target screen returns a value to the source screen.

Transition from a source screen to a target screen, with information sent from the target screen to the source screen
In the above transitions, we used the method startActivity(). This time we will use another method: startActivityForResult(). With this method, the destiny Activity can return informations to source Activity. This is quite useful in some cases.

For example, suppose we have a Screen1, that can call either Screen2 as Screen3. This case, if Screen1 was a customer base, Screen2 a customers deletion and Screen3 a customer registration, when we open Screen2 or Screen3 and perform some operation, we will be redirected to Screen1. But in this screen we need to know whether the deletion/registration was successful or not. In this case, we need to send some feedback to Screen1, from the end of execution of screens 2 and 3. This is done with the method startActivityForResult().

Below is shown a basic example of this functionality. The idea is that an Activity is called in Screen1, and that the daughter Activity returns an information to Screen1. The Screen1 may call both Screen2 and Screen3. This information will be captured by Screen1 through the event: protected void onActivityResult (int code, int result, Intent intent). Let's see our example.

Below is shown the XML layout of our screens.







And the source code of Screen1Activity.java:



And now, the source code of Screen2Activity.java. Screen3 will be similar to this screen.



Now, let's run this example, to set right all that was said above. Clicking on the "Go to Screen 2," here's what happens:



Now we are in Screen2. Clicking the "Return to previous screen" button, here's what happens:



Basically, what happened was that the Screen1 received a return from it's child Activity. Thus, we can identify which of the screens was called by Screen1.

And it's done! We already know how to pass data from one screen to another in every possible way. But before we close this topic, we will talk about a very useful property layout in Android.

When a button is clicked, the ideal would be the user to have a feedback of what happened. In other words, when the button is clicked, stay in one color. When loose, stay in another. Thus, the user will know if the click event of the button was activated or not. We will implement this in our example.

Initially, we will implement the XML file that "animates" the button. Let's call it "button_behavior.xml". Your source code is:




So, when the button is clicked, a drawable will be called. When he is not clicked, another drawable will be called. Now, we need to understand the content of the mentioned events of the above file (pressed_behavior.xml and normal_behavior.xml). Below is shown the source code of these files:





These files have some parameters:

  • gradient  This parameter selects the color the button will have. It can have 3 different mixed colors. For our example, we will have an identical color gradient (the same for each gradient option) in each drawable.
  • corners  This parameter creates smooth contours on the button. In our case, we have the button corners slightly rounded in a size of 3dp.
  • stroke  Parameter that provides an edge on our button. Here, we have a black border of 1px size.

NOTE: There are other parameters besides the three above. But they will not be seen this time.

Now we need to turn this animation on the buttons of our example. To do this, simply include the parameter android:background="@drawable/button_behavior" in each of the buttons on our application. By doing so, we will have much more stylish buttons, which are very intuitive to the user.

-----

And here ended another blog topic.

If someone has a question, suggestion or criticism, feel at ease.

quinta-feira, 11 de outubro de 2012

Interacting with the Layout


Hello everyone.

Now that we know how to install Android on our machines, create a simple application and do basic layouts, we will learn to create layout's that interacts with the user. This interaction is basically done through the parameter android:id. Through this parameter, we create an identifier for a component of the XML graph which can be mapped directly into Java classes containing the source codes of our application.

To use it as an example of this interaction, was created a test layout, whose XML code is shown below.



And it's layout is shown below.



In this layout we have a EditText, a TextView and a Button. We will use all of these components in our example.

What we will basically do is get a text entered by the user in the EditText, and verify if it content is null or not. If is null, a message appears on the screen, alerting the user. If not, the contents of TextView will be updated with the typed value.

To get the text typed by the user, we need to map in the Java class each component id (contained in the XML). On Android, this mapping is done through the method Context.findViewById(int id), which receives an id from the XML and returns an object, which is nothing more than the mapped XML component in the Java class. As all Activity class inherits from Context, we won't need to call the Context as the prefix of the method findViewById().

Below is showed how we mapped the EditText of our XML into the Activity (screen) MainActivity.java:



As the method findViewById() returns an object, we need to convert it to it's corresponding component. In this case, EditText. Using this method, we can map the other components. To keep our source code organized and didactic, we will group these components into a single layout method, called on the event onCreate(), as is shown below.



To keep the code even more didactic, were defined Attributes in our screen. Attributes are variables that will be seen in the full scope of our screen. In other words, are the "global variables" of our screen. On Android there is a pattern to indicate variables which are attributes. This pattern is to use the character "m" as a prefix of the attribute variable. Note that the attributes of our screen have this prefix.

Through the method mapComponents(), we mapped the graphical components of our screen. Now, the next step in the specification of our example is to verify the content of the EditText. However, such a check should be made only when the button is clicked.

In Android, when a button is clicked, the onClick() event is called. However, this method needs to be implemented. There are two ways to implement this method:


  • Implementing the method OnClickListener in the header of the class, like shown below:


  • Implementing the method directly after the button has been mapped from the XML Activity, as shown below:


In both cases, what will be performed after the button be clicked shall be within the method public void onClick(View v). Then, we will check the EditText content (whether it's null or not) within this event. The updated code of our Activity looks like this:



The message to be shown on screen is invoked by the component Toast. This component shows on the screen, for a brief period (Toast.LENGTH_SHORT or Toast.LENGTH_LONG), a message. Notice that the text of the TextView was modified by the method mTextView.setText(content). This is one of several methods that a TextView have. Most of them is just a association of some parameter with this component in XML. For example, in XML we have android:text="text", and in Activity we have textView.setText("Text"). In XML we have android:visibility="gone", and in Activity we have textView.setVisibility(View.GONE). And so on.

Now, we will create a slightly more complex example, which involves a very common practice in Android: show or hide parts of the screen, depending on the value of a given parameter.

For this example, will be created another component in our layout: a TextView that only will be shown when the button is clicked. If the button won't be clicked, this TextView will stay hidden.

The generated XML is shown below:



And the generated layout:



In the above XML, the TextView is unlocked only to demonstrate how the layout will be at the end of the application execution. But for our application works according to the proposed idea (unlock a component of the screen), we must include the parameter android:visibility="gone" into the LinearLayout that contains the TextView.

Now we need to create this component unlocking behavior in our Activity. Modifying the source code, we have the following:



Now we can run our application. To do this, simply click on our project with the right mouse button:



And then click "Run As" and after, "Android Application". Now, an emulator will be opened.

NOTE: So you can choose which exact emulator opens, we modify the option of running the application. This can be done through the "Run Configurations..." option, as shown below.



Once inside this option, we need to click on the "Target" tab, and then on "Manual" option.



Now we can run our application and choose a specific emulator. Just choose the options "Run As" and then "Android Application". Now, we get the following screen displayed:



After choosing an emulator, our application will begin to be loaded into the emulator. After some time, finally our application will be loaded into the emulator, and we'll have the following situation:



Now we can test the implemented functionality. For this, we'll click the button without entering anything. Doing this, a warning message appears on the screen:



We have to enter something in EditText, otherwise this message will appear. Having typed text, we'll click the button. Here's what happened:



Basically what happened was that when the button was clicked, the TextView property Visibility was changed from GONE to VISIBLE. This practice is very useful in layout creation. For example: in a Client Manager, we must enable the City and State fields only when the Country field is initialized.

-----

Well, we came to the end of another topic.

If someone has a question, suggestion or criticism, feel at ease.