Friday, November 1, 2013

Android Studio and Gradle Basics - part 1

With Android Studio there's a new build system called Gradle. In fact Gradle is much more than just a build system but we will focus on the basics here.

First of all lets see the Project Structure :



The root folder contains two Project folders and two gradle files.

For now build.gradle is empty while settings.gradle  :
include ':MyDemo', ':MyLibProject'

Between MyDemo  and MyLibProject Project there are some differences :
1. Library Projects do not generate APK. Instead they generate an .aar package.
2. build.gradle of MyDemo contains a line apply plugin: 'android'  where for Library Project
    we  have apply plugin : 'android-plugin'

Let's have a look at MyDemo build.gradle file :

buildscript {
     repositories {
         mavenCentral()
     }
     dependencies {
          classpath 'com.android.tools.build:gradle:0.6.+'
     }
}
apply plugin: 'android'

repositories {
      mavenCentral()
}

android {
     compileSdkVersion 18
     buildToolsVersion "18.1.1"

     defaultConfig {
          minSdkVersion 8
         targetSdkVersion 18
     }
}


and MyLibProject build.gradle file :

buildscript {
     repositories {
         mavenCentral()
     }
     dependencies {
          classpath 'com.android.tools.build:gradle:0.6.+'
     }
}
apply plugin: 'android-library'

repositories {
      mavenCentral()
}

android {
     compileSdkVersion 18
     buildToolsVersion "18.1.1"

     defaultConfig {
          minSdkVersion 8
         targetSdkVersion 18
     }
}


We can take the first block code of each file ( which is the same ) and move it to the external build.gradle :


buildscript {
     repositories {
         mavenCentral()
     }
     dependencies {
          classpath 'com.android.tools.build:gradle:0.6.+'
     }
}


Android Projects have source folders ( MyDemo ) , Library Projects ( MyLibProject ) and jar file dependencies.
There are three kinds of dependencies :
1. Maven
2. jar file
3. Module

If we choose to add a dependency like ActionBarSherlock to our project from the maven repositories we go to http://search.maven.org/ , write actionbarsherlock to the input area and click search button.
What we see is :


We can use it in our build.gradle code :

 dependencies {
  compile 'com.actionbarsherlock:actionbarsherlock:4.4.0@aar'
 }

Instead of the above way we can also download the rar file, add it to the /libs folder and

 dependencies {
  compile file ('libs/actionbarsherlock.jar')
 }

Or if we had downloaded the source code and add it like a Library Project ( File > Project Structure > Modules ) and add it to the project. Then we had to add to the build.gradle 

 dependencies {
  compile project (':ActionBarSherlock')
 }

Just keep in mind that if we add an artifact as a .jar file to a libs folder and we have the same jar file in another library folder then we are going to have a conflict. We just need to have only one copy of the jar file.
That's a good reason for you to start using the maven repository and don't just add jar files. In that case if we have added the same artifact more than once there will be no conflict.

From the Command Line. Go to the root dir of your project. Gradle works with tasks.
gradlew tasks to see all available tasks.
gradlew assemble to build the project and
gradlew installDebug to install it to the connected devices.

Wednesday, September 11, 2013

Check if Google's location Service is enabled

Check if Google's location Service is enabled by the user, else open Settings > Location so the user enables them.
First get the
String locationProviders = Settings.Secure.getString(getContentResolver(),Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
contains "network" or "gps" or both values separated by comma.

If the string is empty => Google Location Service is closed and you have to prompt the user to open it. Wifi might or not be open.
If the string equals "network" => WiFi and Google Location Service are enabled.
If the string equals "network,gps" => WiFi and GPS and Location Service are enabled.

We need to create a Dialog and ask the user to take the action he wants. In our case we want the user when she clicks Yes to open the Settings > Location , so she can enable the Location Service.
We can achieve that with ACTION_LOCATION_SOURCE_SETTINGS.

The code is :

     if (locationProviders == null || locationProviders.equals("")) {
         
            new AlertDialog.Builder(this)
            .setTitle("Enable Location Service")
            .setMessage("This Application requires the use of Google Location's service.  " +
                    "Do you wish to enable this feature")
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    // show system settings
                    startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                }
            })
            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    // do nothing
                }
            })
            .show();
}

Link : http://stackoverflow.com/questions/10311834/android-dev-how-to-check-if-location-services-are-enabled

Sunday, July 14, 2013

Android Parsing JSON data

When we are dealing with Web Services often the response are in JSON format. That means we have to get the data and with the JSONArray and JSONObject classes parse through the response and extract the data we want.

The whole JSON schema uses the convention of name:value pair. The simplest example we can have here is the JSON Object { "foo":"bar" } where bar is value of foo.
We can easily imagine making a request to the server for a basketball player name and getting the answer in the above format.
Even better we can ask the server for the Personal Information of the player named "lebron james" and get data like position, nationality, weight, height, age, etc...
Then a valid response from the server could be like that :
{
    "age":"28",
     "position":"Forward",
     "nationality":"American",
     "weight":"113",
     "height":"203"
}
Values can be String, number, true, false, null, or even Object and Array.

You can read more about json here.


Now in our application we are going to use the schema ( and the values ) you can see in the image below.
click the image to enlarge

What we see is that we have an Object described by the String "users" and that Object's value is an Array.
Now we just need to think procedural and a) add the data to a JSONObject and from that data b) get the JSONArray described by the name "users".

So our code should look like :
       JSONObject jObj = new JSONObject(data);
       JSONArray sArr = new JSONArray();
     
       sArr = jObj.getJSONArray("users"); //getting the "users"

Now all we need to do is to iterate through the items of the Array and get the values specified by each tag ( id, username and password in our case ).


Since we don't get any response from a web server I stored the answer into a String.

The code is below :




And the XML layout file : 

The result in our Android emulator :
display JSON response from server


Wednesday, June 12, 2013

Root access with ES File Explorer

Open ES File Explore, go to settings  scroll down to Home Directory and change it to "/".
Now you have access to the entire file system.

You can read more here

Tuesday, June 11, 2013

Add/Remove Fragment - Simple Example

What we are going to do :     

A View with a Button. When we click that Button a fragment is being added dynamically in our View. We click again and the fragment is being dynamically removed.


before and after Fragment Transaction took place


What we need: 
One Activity and one Fragment. In the Activity's layout we add two layout objects. That's a Button and a FrameLayout.
In Fragment's layout we have a TextView that contains just text in a color background

So the code for the Activity's and Fragment's layout is: 



Fragment's Layout :
 
Note the android:id = "@+id/fragment_container_1"  in the Activity's layout which is an identifier for our fragment. When we make Transactions like add we refer to a fragment by id.

Activity and Fragment :

Fragment Class :   is a typical Fragment class as we have seen it before


Activity Class :  onClick() begins Transaction. If state is null then we add and commit the fragment else we need to remove and commit again.
So the code is :

Saturday, May 25, 2013

ActionBar/ActionBarSherlock Tabs

Navigation Tabs:
ActionBar supports built-in Tabs or drop-down lists that you can use to change the Fragment is currently  visible. We are going to work with ActionBarSherlock library so we can have backwards compatibility.

Note 1 :  Either Tabs or drop-down lists but not both in ActionBar.
Note 2 :  Every Tab is associated with one Fragment. To change Fragments by using the Tabs,  perform a FragmentTransaction each time a Tab is selected.

Display Tabs :  



Add Tabs :

You can add Tabs with the addTab() method. The first Tab added is the selected one therefore the visible.
Code is like below :



Implement ActionBar.TabListener :

We 're going to split it into 3 parts :

  1. First part the implementation of the Fragments.
  2. Second part the implementation of ActionBar.TabListener 
  3. Third part is to add the Tabs using the TabListener we created before.
The result we expect is the screenshot below :




1) Fragments 
Fragment class is just a basic Fragment class in which we only inflate the layout :


And the corresponding XML layout :



We repeat this process for Fragment_2.

2) TabListener 
TabListener's implementation is the most difficult part of the work.



Our constructor is  public TabListener(Activity activity, String tag, Class<T> clz)  where activity is the host Activity, tag is the identifier Tag of the fragment and cls the Fragment's class so we can instantiate the fragment.

Callbacks in this Interface will handle the event. Specifically when a Tab is clicked then onTabSelected() will execute the Fragment transaction and add the fragment to the Activity.

In our case the Tab content will fill the activity's layout, so our activity doesn't needs a layout. Each fragment is placed in the default root ViewGroup, which we can refer to with the android.R.id.content ID.

3) MainActivity
Because we have to deal with Fragments our MainActivity  will extend FragmentActivity ( or just Activity for Android 3.0 and up ) but in our case with ActionBarSherlock will extend the SherlockFragmentActivity.





All we are doing here is to get the ActionBar item, and add Tabs with the addTab() method.
We set a TabListener for each Tab by calling the setTabListener().
Also we set the tab's title and/or icon with setText() and/or setIcon().

That's all ! Check all the code and/or fork the project from github here so you can see by yourself how it works. 

Tuesday, May 14, 2013

Simple Fragment Transactions

What we are going to do here is a simple Activity with a button. When we click that button a Fragment Transaction takes place and we add the Fragment's layout.

1. You start a new Project and you are using support library if you target API less than 11. So first add the support lib to the project.

2. In my case I'm extending FragmentActivity ( i'm using minimum sdk version 8  ) or for API 11 and above you can use just Activity.

3.  First we are going to create the Fragment.

We extend Fragment class, inflate Fragment's layout at onCreateView() method and declare an Interface for future communication between Fragment and Activity.
So our code is here :


public class Fragment_A extends Fragment {

protected static final String TAG = "FRAGMENTS_A";
private CallbackInterface listener;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_a_layout, container, false);

        return view; //returns view
    }
 
    // ********** declare INTERFACE ***************** //
 
    public interface CallbackInterface {
    public void onSomethingSelected(int position);
      }      

 
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
     
        // This makes sure that the container activity has implemented the callback interface. If not, it throws an exception
        try {
            listener = (CallbackInterface) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement CallbackInterface");
        }
    }
 
 
}

4. Fragment's layout 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:background="@color/cool">
    
    <TextView
        android:id="@+id/tv"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Fragment A" />
</LinearLayout>


5. Now we are going to create our Activity :



public class MainActivity extends FragmentActivity  implements CallbackInterface  {

private static final String TAG = "passNumberTAG";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


final Button button = (Button) findViewById(R.id.button_id);
    button.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
         
       Fragment_A Frag_A = new Fragment_A();
         
       FragmentManager fm1 = getSupportFragmentManager();
        FragmentTransaction transaction = fm1.beginTransaction();
            
        transaction.add(R.id.fragment_container, Frag_A);
        transaction.commit();
            
        }
    });

}

@Override
public void onSomethingSelected(int position) {
Log.d(TAG, "Give me the result  " + position  );
position = position +1;
Log.d(TAG, "Give me the result  " + position  );

}

}

The part where the Transaction takes place is inside the click listener : 
        Fragment_A Frag_A = new Fragment_A();
          
        FragmentManager fm1 = getSupportFragmentManager();
        FragmentTransaction transaction = fm1.beginTransaction();
             
        transaction.add(R.id.fragment_container, Frag_A);
        transaction.commit();


-> new Fragment -> get FragmentManager -> beginTransaction -> add new layout and commit.


One last thing is the Activity's layout. The activity's layout includes an empty FrameLayoutthat acts as the fragment container. 



<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

        <Button 
         android:id="@+id/button_id"
         android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:text="@string/button_text" />

        
        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
        
        
</RelativeLayout>