How to create REST API for Android app using PHP, Slim and MySQL – Day 2/2


we have learned fundamental concepts about REST API and preparing your development environment ready by installing the required tools needed. I hope everyone got good knowledge about REST and other technical areas. Also I am assuming that you got all the required tools installed.

android rest api design using php mysql slim

8. Starting PHP Project

As we all know IDEs make development process easier. So I recommend you use an IDE for developing the PHP project instead of using plain notepad. You can go for Eclipse, Aptana Studio, PhpStorm or Netbeans. But I personally felt very comfortable using Netbeans for PHP projects.
PHP Project directory structure
The following diagram will give you an idea about the directory structure of the project which we are going to develop now.
task manager rest api php project directory structure
libs – All the third party libraries goes here. In our case we place Slim library here
include – All the helpers classes we build placed here
index.php – Takes care of all the API requests
.htaccess – Rules for url structure and other apache rules
Now let’s start the PHP project
1. Go to the directory where WAMP is installed. In general wamp will be installed in C:\wamp. (If you have installed any other software rather than WAMP, you should go to the directory recommended by that software).
2. As a first step we start with creating required directories. Inside wamp folder go to www folder (c:\wamp\www\) and create a folder named task_manager. This folder will be the parent directory of our project. Inside task_manager create two more folders named libs, include and v1.
3. Now the paste the Slim library inside libs folder. The download link for Slim is provided in previous part.
4. Normally Slim framework works when index.php includes in the url which makes url not well-formed. So using the .htacess rules we can get rid of index.php from the url and make some friendly urls. Inside v1 folder create a file named .htaccess and paste the following code. (Note that this file name shouldn’t include any additional extension in the name like .txt)
.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ %{ENV:BASE}index.php [QSA,L]

8.1 Preparing Helper Classes

First we start writing set of helper classes required in this project. These helper classes provides necessary functions required to interact with the database.
5. Inside include folder create file named Config.php with following content. This file contains the entire project configuration like database connection parameters and other variables.
Config.php
<?php
/**
 * Database configuration
 */
define('DB_USERNAME', 'root');
define('DB_PASSWORD', '');
define('DB_HOST', 'localhost');
define('DB_NAME', 'task_manager');
define('USER_CREATED_SUCCESSFULLY', 0);
define('USER_CREATE_FAILED', 1);
define('USER_ALREADY_EXISTED', 2);
?>
6. Create another class named DbConnect.php This class file mainly takes care of database connection.
DbConnect.php
<?php
/**
 * Handling database connection
 *
 * @author Ravi Tamada
 */
class DbConnect {
    private $conn;
    function __construct() {       
    }
    /**
     * Establishing database connection
     * @return database connection handler
     */
    function connect() {
        include_once dirname(__FILE__) . './Config.php';
        // Connecting to mysql database
        $this->conn = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);
        // Check for database connection error
        if (mysqli_connect_errno()) {
            echo "Failed to connect to MySQL: " . mysqli_connect_error();
        }
        // returing connection resource
        return $this->conn;
    }
}
?>
Encrypting the password
7. The best way to secure the user passwords is not store them as plain text, instead all the passwords should be encrypted before storing in db. The following class takes care of encrypting the user password. Create another file named PassHash.php and paste the following code.
PassHash.php
<?php
class PassHash {
    // blowfish
    private static $algo = '$2a';
    // cost parameter
    private static $cost = '$10';
    // mainly for internal use
    public static function unique_salt() {
        return substr(sha1(mt_rand()), 0, 22);
    }
    // this will be used to generate a hash
    public static function hash($password) {
        return crypt($password, self::$algo .
                self::$cost .
                '$' . self::unique_salt());
    }
    // this will be used to compare a password against a hash
    public static function check_password($hash, $password) {
        $full_salt = substr($hash, 0, 29);
        $new_hash = crypt($password, $full_salt);
        return ($hash == $new_hash);
    }
}
?>
8. Now create another class named DbHandler.php This class is one of the important files in our project which provides necessary functions to perform CRUD operations on the database. Every function is self explanatory by it’s name and comments, I don’t have to have to explain much about them.
DbHandler.php
<?php
/**
 * Class to handle all db operations
 * This class will have CRUD methods for database tables
 *
 * @author Ravi Tamada
 */
class DbHandler {
    private $conn;
    function __construct() {
        require_once dirname(__FILE__) . './DbConnect.php';
        // opening db connection
        $db = new DbConnect();
        $this->conn = $db->connect();
    }
    /* ------------- `users` table method ------------------ */
    /**
     * Creating new user
     * @param String $name User full name
     * @param String $email User login email id
     * @param String $password User login password
     */
    public function createUser($name, $email, $password) {
        require_once 'PassHash.php';
        $response = array();
        // First check if user already existed in db
        if (!$this->isUserExists($email)) {
            // Generating password hash
            $password_hash = PassHash::hash($password);
            // Generating API key
            $api_key = $this->generateApiKey();
            // insert query
            $stmt = $this->conn->prepare("INSERT INTO users(name, email, password_hash, api_key, status) values(?, ?, ?, ?, 1)");
            $stmt->bind_param("ssss", $name, $email, $password_hash, $api_key);
            $result = $stmt->execute();
            $stmt->close();
            // Check for successful insertion
            if ($result) {
                // User successfully inserted
                return USER_CREATED_SUCCESSFULLY;
            } else {
                // Failed to create user
                return USER_CREATE_FAILED;
            }
        } else {
            // User with same email already existed in the db
            return USER_ALREADY_EXISTED;
        }
        return $response;
    }
    /**
     * Checking user login
     * @param String $email User login email id
     * @param String $password User login password
     * @return boolean User login status success/fail
     */
    public function checkLogin($email, $password) {
        // fetching user by email
        $stmt = $this->conn->prepare("SELECT password_hash FROM users WHERE email = ?");
        $stmt->bind_param("s", $email);
        $stmt->execute();
        $stmt->bind_result($password_hash);
        $stmt->store_result();
        if ($stmt->num_rows > 0) {
            // Found user with the email
            // Now verify the password
            $stmt->fetch();
            $stmt->close();
            if (PassHash::check_password($password_hash, $password)) {
                // User password is correct
                return TRUE;
            } else {
                // user password is incorrect
                return FALSE;
            }
        } else {
            $stmt->close();
            // user not existed with the email
            return FALSE;
        }
    }
    /**
     * Checking for duplicate user by email address
     * @param String $email email to check in db
     * @return boolean
     */
    private function isUserExists($email) {
        $stmt = $this->conn->prepare("SELECT id from users WHERE email = ?");
        $stmt->bind_param("s", $email);
        $stmt->execute();
        $stmt->store_result();
        $num_rows = $stmt->num_rows;
        $stmt->close();
        return $num_rows > 0;
    }
    /**
     * Fetching user by email
     * @param String $email User email id
     */
    public function getUserByEmail($email) {
        $stmt = $this->conn->prepare("SELECT name, email, api_key, status, created_at FROM users WHERE email = ?");
        $stmt->bind_param("s", $email);
        if ($stmt->execute()) {
            $user = $stmt->get_result()->fetch_assoc();
            $stmt->close();
            return $user;
        } else {
            return NULL;
        }
    }
    /**
     * Fetching user api key
     * @param String $user_id user id primary key in user table
     */
    public function getApiKeyById($user_id) {
        $stmt = $this->conn->prepare("SELECT api_key FROM users WHERE id = ?");
        $stmt->bind_param("i", $user_id);
        if ($stmt->execute()) {
            $api_key = $stmt->get_result()->fetch_assoc();
            $stmt->close();
            return $api_key;
        } else {
            return NULL;
        }
    }
    /**
     * Fetching user id by api key
     * @param String $api_key user api key
     */
    public function getUserId($api_key) {
        $stmt = $this->conn->prepare("SELECT id FROM users WHERE api_key = ?");
        $stmt->bind_param("s", $api_key);
        if ($stmt->execute()) {
            $user_id = $stmt->get_result()->fetch_assoc();
            $stmt->close();
            return $user_id;
        } else {
            return NULL;
        }
    }
    /**
     * Validating user api key
     * If the api key is there in db, it is a valid key
     * @param String $api_key user api key
     * @return boolean
     */
    public function isValidApiKey($api_key) {
        $stmt = $this->conn->prepare("SELECT id from users WHERE api_key = ?");
        $stmt->bind_param("s", $api_key);
        $stmt->execute();
        $stmt->store_result();
        $num_rows = $stmt->num_rows;
        $stmt->close();
        return $num_rows > 0;
    }
    /**
     * Generating random Unique MD5 String for user Api key
     */
    private function generateApiKey() {
        return md5(uniqid(rand(), true));
    }
    /* ------------- `tasks` table method ------------------ */
    /**
     * Creating new task
     * @param String $user_id user id to whom task belongs to
     * @param String $task task text
     */
    public function createTask($user_id, $task) {       
        $stmt = $this->conn->prepare("INSERT INTO tasks(task) VALUES(?)");
        $stmt->bind_param("s", $task);
        $result = $stmt->execute();
        $stmt->close();
        if ($result) {
            // task row created
            // now assign the task to user
            $new_task_id = $this->conn->insert_id;
            $res = $this->createUserTask($user_id, $new_task_id);
            if ($res) {
                // task created successfully
                return $new_task_id;
            } else {
                // task failed to create
                return NULL;
            }
        } else {
            // task failed to create
            return NULL;
        }
    }
    /**
     * Fetching single task
     * @param String $task_id id of the task
     */
    public function getTask($task_id, $user_id) {
        $stmt = $this->conn->prepare("SELECT t.id, t.task, t.status, t.created_at from tasks t, user_tasks ut WHERE t.id = ? AND ut.task_id = t.id AND ut.user_id = ?");
        $stmt->bind_param("ii", $task_id, $user_id);
        if ($stmt->execute()) {
            $task = $stmt->get_result()->fetch_assoc();
            $stmt->close();
            return $task;
        } else {
            return NULL;
        }
    }
    /**
     * Fetching all user tasks
     * @param String $user_id id of the user
     */
    public function getAllUserTasks($user_id) {
        $stmt = $this->conn->prepare("SELECT t.* FROM tasks t, user_tasks ut WHERE t.id = ut.task_id AND ut.user_id = ?");
        $stmt->bind_param("i", $user_id);
        $stmt->execute();
        $tasks = $stmt->get_result();
        $stmt->close();
        return $tasks;
    }
    /**
     * Updating task
     * @param String $task_id id of the task
     * @param String $task task text
     * @param String $status task status
     */
    public function updateTask($user_id, $task_id, $task, $status) {
        $stmt = $this->conn->prepare("UPDATE tasks t, user_tasks ut set t.task = ?, t.status = ? WHERE t.id = ? AND t.id = ut.task_id AND ut.user_id = ?");
        $stmt->bind_param("siii", $task, $status, $task_id, $user_id);
        $stmt->execute();
        $num_affected_rows = $stmt->affected_rows;
        $stmt->close();
        return $num_affected_rows > 0;
    }
    /**
     * Deleting a task
     * @param String $task_id id of the task to delete
     */
    public function deleteTask($user_id, $task_id) {
        $stmt = $this->conn->prepare("DELETE t FROM tasks t, user_tasks ut WHERE t.id = ? AND ut.task_id = t.id AND ut.user_id = ?");
        $stmt->bind_param("ii", $task_id, $user_id);
        $stmt->execute();
        $num_affected_rows = $stmt->affected_rows;
        $stmt->close();
        return $num_affected_rows > 0;
    }
    /* ------------- `user_tasks` table method ------------------ */
    /**
     * Function to assign a task to user
     * @param String $user_id id of the user
     * @param String $task_id id of the task
     */
    public function createUserTask($user_id, $task_id) {
        $stmt = $this->conn->prepare("INSERT INTO user_tasks(user_id, task_id) values(?, ?)");
        $stmt->bind_param("ii", $user_id, $task_id);
        $result = $stmt->execute();
        $stmt->close();
        return $result;
    }
}
?>

8.2 Handling the API calls

Now we have all the required classes for the REST API. Now we can start the code to handle all individual api calls.
8. Inside v1 folder create a file named index.php and add the following code. Here we are including required libraries and other helper functions.
verifyRequiredParams() – This function verifies the mandatory parameters in the request.
validateEmail() – Verifies whether email address is valid one or not.
echoRespnse() – This function will echo the JSON response with a status code.
index.php
<?php
require_once '../include/DbHandler.php';
require_once '../include/PassHash.php';
require '.././libs/Slim/Slim.php';
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();
// User id from db - Global Variable
$user_id = NULL;
/**
 * Verifying required params posted or not
 */
function verifyRequiredParams($required_fields) {
    $error = false;
    $error_fields = "";
    $request_params = array();
    $request_params = $_REQUEST;
    // Handling PUT request params
    if ($_SERVER['REQUEST_METHOD'] == 'PUT') {
        $app = \Slim\Slim::getInstance();
        parse_str($app->request()->getBody(), $request_params);
    }
    foreach ($required_fields as $field) {
        if (!isset($request_params[$field]) || strlen(trim($request_params[$field])) <= 0) {
            $error = true;
            $error_fields .= $field . ', ';
        }
    }
    if ($error) {
        // Required field(s) are missing or empty
        // echo error json and stop the app
        $response = array();
        $app = \Slim\Slim::getInstance();
        $response["error"] = true;
        $response["message"] = 'Required field(s) ' . substr($error_fields, 0, -2) . ' is missing or empty';
        echoRespnse(400, $response);
        $app->stop();
    }
}
/**
 * Validating email address
 */
function validateEmail($email) {
    $app = \Slim\Slim::getInstance();
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $response["error"] = true;
        $response["message"] = 'Email address is not valid';
        echoRespnse(400, $response);
        $app->stop();
    }
}
/**
 * Echoing json response to client
 * @param String $status_code Http response code
 * @param Int $response Json response
 */
function echoRespnse($status_code, $response) {
    $app = \Slim\Slim::getInstance();
    // Http response code
    $app->status($status_code);
    // setting response content type to json
    $app->contentType('application/json');
    echo json_encode($response);
}
$app->run();
?>

The JSON response

On calling every API request a JSON response will be issued with a HTTP status code. On the client side you have to verify the response http status code. If the status is 200, the request is processed successfully. Also you can notice a “error” node in the response. If the error value is true, that means some error occurred while processing the user data.


Api Calls without Authentication (without API key in the request header)
These calls don’t have to include Api Key in the request header. The main purpose of these calls is to interact with database without any authentication. User registration and login comes under this category.

⇒ User Registration

In order to interact with the API, the user has to register in our system first. Once he registered an API key will be generated and stored in the database. This API key will be private to that user only.
9. Add the following code in index.php. This function handles user registration.
index.php
/**
 * User Registration
 * url - /register
 * method - POST
 * params - name, email, password
 */
$app->post('/register', function() use ($app) {
            // check for required params
            verifyRequiredParams(array('name', 'email', 'password'));
            $response = array();
            // reading post params
            $name = $app->request->post('name');
            $email = $app->request->post('email');
            $password = $app->request->post('password');
            // validating email address
            validateEmail($email);
            $db = new DbHandler();
            $res = $db->createUser($name, $email, $password);
            if ($res == USER_CREATED_SUCCESSFULLY) {
                $response["error"] = false;
                $response["message"] = "You are successfully registered";
                echoRespnse(201, $response);
            } else if ($res == USER_CREATE_FAILED) {
                $response["error"] = true;
                $response["message"] = "Oops! An error occurred while registereing";
                echoRespnse(200, $response);
            } else if ($res == USER_ALREADY_EXISTED) {
                $response["error"] = true;
                $response["message"] = "Sorry, this email already existed";
                echoRespnse(200, $response);
            }
        });
In the following table you can find the API request information about the URL, HTTP method and the parameters needed to be posted.
URL/register
MethodPOST
Paramsname, email, password
Upon the successful registration the following json response will be issued.
{
    "error": false,
    "message": "You are successfully registered"
}
If the request is missing mandatory parameters the following json will be issued.
{
    "error": true,
    "message": "Required field(s) email, password is missing or empty"
}

⇒ User Login

10. Add the following code to handle user login. After verifying user credentials, the API Key for that user will be issued in the json response. The api key should be included in the request header in all remaining api calls.
index.php
/**
 * User Login
 * url - /login
 * method - POST
 * params - email, password
 */
$app->post('/login', function() use ($app) {
            // check for required params
            verifyRequiredParams(array('email', 'password'));
            // reading post params
            $email = $app->request()->post('email');
            $password = $app->request()->post('password');
            $response = array();
            $db = new DbHandler();
            // check for correct email and password
            if ($db->checkLogin($email, $password)) {
                // get the user by email
                $user = $db->getUserByEmail($email);
                if ($user != NULL) {
                    $response["error"] = false;
                    $response['name'] = $user['name'];
                    $response['email'] = $user['email'];
                    $response['apiKey'] = $user['api_key'];
                    $response['createdAt'] = $user['created_at'];
                } else {
                    // unknown error occurred
                    $response['error'] = true;
                    $response['message'] = "An error occurred. Please try again";
                }
            } else {
                // user credentials are wrong
                $response['error'] = true;
                $response['message'] = 'Login failed. Incorrect credentials';
            }
            echoRespnse(200, $response);
        });
URL/login
MethodPOST
Paramsemail, password
On successful login the following json will be issued.
{
    "error": false,
    "name": "Ravi Tamada",
    "email": "ravi@gmail.com",
    "apiKey": "940bb12af8d7b040876f60f965c5be6d",
    "createdAt": "2014-01-07 23:38:35"
}
If the credentials are wrong, you can expect the following json.
{
    "error": true,
    "message": "Login failed. Incorrect credentials"
}

⇒ Verifying API Key

While dealing with task data, we need to identify the user using the API key in the request header by reading Authorization field. Basically we’ll look into database for matched API key and get the appropriate user. If the API key not present in users table, then we’ll stop the execution and echo the error json.
11. Add the following method in index.php. The method authenticate() will be executed every time before doing any task related operations on database.
index.php
/**
 * Adding Middle Layer to authenticate every request
 * Checking if the request has valid api key in the 'Authorization' header
 */
function authenticate(\Slim\Route $route) {
    // Getting request headers
    $headers = apache_request_headers();
    $response = array();
    $app = \Slim\Slim::getInstance();
    // Verifying Authorization Header
    if (isset($headers['Authorization'])) {
        $db = new DbHandler();
        // get the api key
        $api_key = $headers['Authorization'];
        // validating api key
        if (!$db->isValidApiKey($api_key)) {
            // api key is not present in users table
            $response["error"] = true;
            $response["message"] = "Access Denied. Invalid Api key";
            echoRespnse(401, $response);
            $app->stop();
        } else {
            global $user_id;
            // get user primary key id
            $user = $db->getUserId($api_key);
            if ($user != NULL)
                $user_id = $user["id"];
        }
    } else {
        // api key is missing in header
        $response["error"] = true;
        $response["message"] = "Api key is misssing";
        echoRespnse(400, $response);
        $app->stop();
    }
}
If the api key is missing in the request header, the following json will be echoed with 400 status code.
{
    "error": true,
    "message": "Api key is misssing"
}
If the api key is not valid following json will echoed with 401 status code.
{
    "error": true,
    "message": "Access Denied. Invalid Api key"
}


Api Calls with Authentication (Including API key in the request)
Following are the API calls should have an Api Key in the request header. These api calls primarily deals the user’s task data like creating, reading, updating and deleting.

⇒ Creating New Task

12. Add the follwing method to create a new task. Here you can notice that authenticate method is called to verify the Api key before inserting a new task.
index.php
/**
 * Creating new task in db
 * method POST
 * params - name
 * url - /tasks/
 */
$app->post('/tasks', 'authenticate', function() use ($app) {
            // check for required params
            verifyRequiredParams(array('task'));
            $response = array();
            $task = $app->request->post('task');
            global $user_id;
            $db = new DbHandler();
            // creating new task
            $task_id = $db->createTask($user_id, $task);
            if ($task_id != NULL) {
                $response["error"] = false;
                $response["message"] = "Task created successfully";
                $response["task_id"] = $task_id;
            } else {
                $response["error"] = true;
                $response["message"] = "Failed to create task. Please try again";
            }
            echoRespnse(201, $response);
        });
URL/tasks
MethodPOST
Paramstask
On successful creation of new task following json will be issued. If you got this json, you can see new row inserted in tasks and user_tasks tables.
{
    "error": false,
    "message": "Task created successfully",
    "task_id": 1
}

⇒ Getting All Tasks

13. Following method will list down all user’s tasks. We don’t have to submit any params for this api call.
index.php
/**
 * Listing all tasks of particual user
 * method GET
 * url /tasks         
 */
$app->get('/tasks', 'authenticate', function() {
            global $user_id;
            $response = array();
            $db = new DbHandler();
            // fetching all user tasks
            $result = $db->getAllUserTasks($user_id);
            $response["error"] = false;
            $response["tasks"] = array();
            // looping through result and preparing tasks array
            while ($task = $result->fetch_assoc()) {
                $tmp = array();
                $tmp["id"] = $task["id"];
                $tmp["task"] = $task["task"];
                $tmp["status"] = $task["status"];
                $tmp["createdAt"] = $task["created_at"];
                array_push($response["tasks"], $tmp);
            }
            echoRespnse(200, $response);
        });
URL/tasks
MethodGET
Params-
Following json will be issued for list of tasks. The “tasks” represents list of tasks as an array. Also if the “status” is 0, that means the task is not done yet.
{
    "error": false,
    "tasks": [
        {
            "id": 1,
            "task": "Complete REST article by Sunday",
            "status": 0,
            "createdAt": "2014-01-08 23:35:45"
        },
        {
            "id": 2,
            "task": "Book bus tickets!",
            "status": 0,
            "createdAt": "2014-01-08 23:56:52"
        }
    ]
}

⇒ Getting Single Task

14. Following method will fetch details of single task. You need to append the task id with a / to url. For an example if you want details of task 15, the url will be /tasks/15.
index.php
/**
 * Listing single task of particual user
 * method GET
 * url /tasks/:id
 * Will return 404 if the task doesn't belongs to user
 */
$app->get('/tasks/:id', 'authenticate', function($task_id) {
            global $user_id;
            $response = array();
            $db = new DbHandler();
            // fetch task
            $result = $db->getTask($task_id, $user_id);
            if ($result != NULL) {
                $response["error"] = false;
                $response["id"] = $result["id"];
                $response["task"] = $result["task"];
                $response["status"] = $result["status"];
                $response["createdAt"] = $result["created_at"];
                echoRespnse(200, $response);
            } else {
                $response["error"] = true;
                $response["message"] = "The requested resource doesn't exists";
                echoRespnse(404, $response);
            }
        });
URL/tasks/id (id should be replaced with task id)
MethodGET
Params-
The details of a single task will be in following json format.
{
    "error": false,
    "id": 2,
    "task": "Book bus tickets!",
    "status": 0,
    "createdAt": "2014-01-08 23:56:52"
}
If you pass a task id which is not there in the database, you will get 404 not found error.

⇒ Updating Task

15. Following code will take care of updating a task. The url for this api call is same as getting the details of single task, only difference is we should use PUT method instead of GET.
index.php
/**
 * Updating existing task
 * method PUT
 * params task, status
 * url - /tasks/:id
 */
$app->put('/tasks/:id', 'authenticate', function($task_id) use($app) {
            // check for required params
            verifyRequiredParams(array('task', 'status'));
            global $user_id;           
            $task = $app->request->put('task');
            $status = $app->request->put('status');
            $db = new DbHandler();
            $response = array();
            // updating task
            $result = $db->updateTask($user_id, $task_id, $task, $status);
            if ($result) {
                // task updated successfully
                $response["error"] = false;
                $response["message"] = "Task updated successfully";
            } else {
                // task failed to update
                $response["error"] = true;
                $response["message"] = "Task failed to update. Please try again!";
            }
            echoRespnse(200, $response);
        });
URL/tasks/id (id should be replaced with task id)
MethodPUT
Paramstask, status (0 or 1)
Upon successful updation you will get following json.
{
    "error": false,
    "message": "Task updated successfully"
}

⇒ Deleting Task

16. Again delete task url is same as update task, but this requires DELETE method.
index.php
/**
 * Deleting task. Users can delete only their tasks
 * method DELETE
 * url /tasks
 */
$app->delete('/tasks/:id', 'authenticate', function($task_id) use($app) {
            global $user_id;
            $db = new DbHandler();
            $response = array();
            $result = $db->deleteTask($user_id, $task_id);
            if ($result) {
                // task deleted successfully
                $response["error"] = false;
                $response["message"] = "Task deleted succesfully";
            } else {
                // task failed to delete
                $response["error"] = true;
                $response["message"] = "Task failed to delete. Please try again!";
            }
            echoRespnse(200, $response);
        });
URL/tasks/id (id should be replaced with task id)
MethodDELETE
Params-
You will get following json if the task is deleted successfully.
{
    "error": false,
    "message": "Task deleted succesfully"
}
Here we completes the PHP and MySQL part. Now it’s time to move on to testing the API just to make sure that whatever code we have written is working.

Testing the API

Following is the list of URL we need to test using Chrome Advanced REST client extension with possible combinations of inputs.
URLMethodParametersDescription
http://localhost/task_manager/v1/registerPOSTname, email, passwordUser registration
http://localhost/task_manager/v1/loginPOSTemail, passwordUser login
http://localhost/task_manager/v1/tasksPOSTtaskTo create new task
http://localhost/task_manager/v1/tasksGETFetching all tasks
http://localhost/task_manager/v1/tasks/:idGETFetching single task
http://localhost/task_manager/v1/tasks/:idPUTUpdating single task
http://localhost/task_manager/v1/tasks/:idDELETEtask, statusDeleting single task
The following video shows you how to test the API thoroughly.

Make Your First Android App: Part 1/3

“But when does the Android version come out?”
–The first blog comment after any iOS app gets announced.
Clearly there’s a demand for Android app development, and it’s turning the platform with the lovable green mascot into more and more of a strong first choice rather than just a secondary option to iOS.
With over one billion devices activated, Android is an exciting space to make apps to help you communicate, organize, educate, entertain or anything else you’re passionate about.
If that’s not enough, here are a few more reasons to learn Android:
  • You’ll be plugged into the open source platform with (at the time of press) the largest market share of smart devices worldwide.
  • Android’s policies on device provisioning and app submission are more open than Apple’s, meaning that once you complete your first app—as you’ll do in this tutorial—you and your friends can enjoy it on your devices right away!
  • If you have experience developing for iOS, you can become well-versed in the ways that the two platforms coincide and differ (we’ll discuss a few in this tutorial) and what you like about each. Then you’ll have more tools at your disposal for your next mobile project.
  • It’s not just the iPhone anymore. There are so many smartphones, tablets, glasses, and watches out there, coming from so many manufacturers, and they’re all trying to jump into the game. You don’t have to be any sort of market analyst to know that there are a few important platforms and Android is one of them.
So if you’ve been intent on, thinking about, or simply playing with the idea of learning Android… Make Your First Android App is the tutorial series for you!
nows_your_chance
There aren’t any prerequisites to start. You’ll learn how to set up all the tools you need to become an Android developer-in-training. Then you’ll put together your own full-fledged Android app from scratch! This app will, when completed, help you get details about a book you’re interested in using online search sources.
By the end of Part Three of this series, your app will include useful features like:
  • Saving app data locally on the phone.
  • Loading and interacting with a dynamic list of data.
  • Accessing an online data source.
  • Sharing links through social networks.
Android, and several popular frameworks for it, make all of these features really simple to implement. Why not start learning this easy and powerful platform for yourself, today?

Getting Started

How does Android development go down? First, the zoomed-out basics:
  • You’ll write your programming—what you want your app to do—in Java files and design your layouts—how you want your app to look—in XML files.
  • Once your app is ready, you’ll use a build tool to compile all the project files and package them together into a .apk file that you can run on Android devices and/or submit to Google Play.
  • All of the files you used to put your app together are managed by an Integrated Development Environment (IDE). The IDE is the program you will open to edit your code files and to manage your projects.
  • The standard IDE for Android used to be Eclipse, but this is now being replaced by Google’s own Android Studio.
If you zoom in (metaphorically), you’ll find more in-depth processes going on behind the scenes during all of the above steps. For example, advanced users will want to investigate the role of the Dalvik Virtual Machine and it’s new replacement, ART.
But for now, let’s move on. Here’s what you’re going to accomplish in this part of the tutorial:
  1. Download and install Android Studio.
  2. Set up testing on devices and emulators.
  3. Create a simple “Hello World!” Android app that prints to your device’s screen.
  4. Make small edits to the app so it can congratulate you by name.
In the second part of this tutorial, you’ll make an app that records a message you type, adds it to a list, saves it in memory and shares it with friends. Along the way, you’ll learn how to add and configure various UI elements such as ImageViews, Buttons, ListViews, and EditText controls.
Finally, the third part will cover how to make an app to search an online database of books, display and share the cover images of the search results, and navigate between the different screens of your new app!

Installing Android Studio

It’s really tempting to jump in, start writing code right away and figure out the various Android features as quickly as possible. And you will get there soon! But one of the most important parts of getting started with a new platform is setting up your environment.
Especially for beginners, it’s important to take your time here and follow each step methodically. Even if you follow the steps perfectly, you may have to troubleshoot some small issue, depending on your system configuration or product versions.
It’s important to not let any roadblocks prevent you from your ultimate goal of learning Android. Even seasoned professionals have been known to have some trouble with the new Android Studio.
Note: Just as much as you’re training in programming syntax and frameworks, it’s important to train yourself to have a successful programming mindset — one that won’t accept file X not found as a final answer. 90% of this mindset is simply training yourself to keep trying till you find a solution.
With all of this in mind, let’s quickly check that you have the Java Development Kit (JDK) installed. You might already, even if you don’t know for sure.
To check, you’ll use the Terminal. If you’re unfamiliar with the Terminal, you may want to read a good introductory tutorial about working with the Terminal.
In a nutshell, your Terminal is like looking under your car’s hood; it’s how you really get to know the machine face-to-face, without any complex graphical interface in the middle. You can find the Terminal app quite easily on a Mac using Spotlight. Search for terminal and click the top hit to run Terminal.
screenshot_terminal
Once you have the Terminal open, type in java -version. You should see some output that mentions a version number, like below.
screenshot_terminal2
If you don’t have the JDK installed, your Terminal will tell you command not found. If that’s the case, you should download the JDK from Oracle.
When ready, head over to the Android Studio page and find the button to download the correct version for your platform.
screenshot_android_studio_site_arrow
Google is constantly updating this page, so the version you see may be newer than the screenshot above. Click the Download button and you’ll be asked to agree to the Terms and Conditions:
terms_conditions
After reading these carefully (as you always do) and accepting, your download begins. It will likely take a few minutes. Once done, you can install Android Studio similar to any other program. The original download page contains the familiar Mac and Windows installation instructions in case you need a refresher.
Now that you’ve installed Studio, let’s fire it up! Launch Android Studio. It may ask you if you want to import any settings:
opening_studio_2
Since you’re starting from scratch, if given the choice just select I do not have a previous version… and move on. You’re presented with the nice loading screen, complete with all the various phone and tablet screen sizes in the background. More on screen size diversity later. ;]
opening_studio_3
Once that loads, you are greeted with a Welcome screen.
opening_studio_4
Even though you just downloaded Studio, you might not actually have the latest version. Right away, you need to click check for updates and if necessary, follow any instructions to get the latest version.
Sometimes, Studio automatically lets you know that there’s an update via a screen similar to this:
update_now
In that case, always choose Update and Restart.
Great! As all programmers in the movies say when they are successfully greeted with a new interface: We’re in!

Optional/Advanced: Moving from Eclipse

You can skip to the next section if you are new to Android development.
Android Studio is a new IDE that Google is constantly updating. If you are already involved in Android development, you are probably using Eclipse. For the transition, the Android team has put together a helpful guide on how to move from Eclipse to Studio.
The process can still be a little bumpy, even for advanced users, so the best advice I can offer on that front is to make sure that your version of Gradle is up-to-date, as well as your versions of the Android Platform Tools and Studio itself.
It’s also important to check the PATH of your Android software development kit (SDK) when switching to Studio. Otherwise, Studio may not be able to find the right Android SDK or Build Tools!

Creating OMG Android

It’s time. Let’s make your first project.
You’ll start simple. Many first programs are called “Hello World.” Let’s follow that tradition and then make a few small edits so that the app uses your name to greet you. By the end, you’ll be able to load your new app onto a device and show it to your friends!
Android Studio has a nice little step-by-step tool to help you make your project. Click New Project from the Welcome to Android Studio screen:
opening_studio_16_arrow
Note: If you currently have an Android Studio project open and the Welcome screen isn’t showing, select File\New Project from the menu to create a new project.
Studio will present you with a screen like the following:
opening_studio_17
Fill it out according to the screenshot above. Feel free to replace “example” in your Package name with something else to remove the warning at the bottom of the screen.
You can set the Project location to any location on your hard drive – you do not need to follow the screenshot for that one :]
For the SDK drop downs, pay attention to the Description section at the bottom of the dialog. It explains what each setting is for.
Set the Minimum required SDK as shown in the screenshot. This sets the minimum version of Android needed to run your app. Selecting this value for your own projects is a matter of balancing the SDK capabilities you want and the devices you want to support.
For your first app, I recommend using API version 14, which is Android 4.0 Ice Cream Sandwich. Every app will have different requirements and you may want to choose something else, depending on the situation.
For more information on API versions and their use, check the Android Dashboards, which are constantly updated.
android_dashboard_1
You’ll note that a fair number of devices are still on API level 10, Gingerbread. In case you’re considering supporting Gingerbread in your project, do note that that number is shrinking and would require you to make some accommodations in your app design that often aren’t worth it.
Getting back to the dialog, Target SDK and Compile With aren’t crucial here. They should each just be the highest value possible at the time. As new SDK versions come out, this number will rise.
Note: In some strange cases, users aren’t given choices in any of the SDK drop-downs and can’t proceed. If that happens, from the welcome menu go to Configure > Project Defaults > Project Structure. This gives a menu full of SDK-related drop-downs. You have to check that none of these options are marked red, indicating none or empty values.
Click Next and you’ll see more options.
opening_studio_18
This screen creates the default app icon for you. The default values are fine for now — you’ll change it later. So click Next.
Another step in the creation process appears:
opening_studio_19
This screen offers a few different options that define how your app UI is set up. You can simply accept the default, which creates an (almost) blank screen with an action bar. The action bar is one of the reasons why you set the minimum SDK to Ice Cream Sandwich: it’s the way that modern Android apps help users easily navigate and select app options and it’s only available from API level 14 onwards. Click Next.
You are now presented with the final step in the process:
opening_studio_20
Before you click Finish, take a moment here, because you’re starting to get hints of what your program is going to look like and of terms you should know going forward.
  • Activity Name. This is the first mention you’ve seen of the word Activity, but it certainly won’t be the last. In Android, an Activity is usually thought of as a “screen” in your app. It could be fullscreen or it could be a partial-screen pop-up. It is very flexible. If you want your user interacting with something in your app, that’s at some level happening via an Activity.
    Note: When Android Studio creates your MainActivity, what it’s doing is making a subclass of Activity. Those familiar with object-oriented programming will know what this is, but for newcomers, this basically means that your MainActivity is going to be a customized version of Activity that acts just like the default one, handling things like its lifecycle and the user interface display.
  • Layout Name. You’re going to define your MainActivity in Java, but the layout of everything it will show to the user is defined in a special sort of Android XML. You will learn how to read and edit those files soon.
  • Fragment Layout Name. A fragment is a little like a sub-activity, and can be a useful part of your app design. I won’t go into fragments much in this tutorial—in fact, one of the things you’ll do is remove the one that the New Project wizard makes for you—but I encourage you to further investigate how to effectively use fragments after you finish this tutorial.
  • Navigation Type. For now, just choose None. You won’t need any navigation for a little while, and when you do, it’ll be smarter to build it yourself, from scratch.
Click Finish. Android Studio takes this as its cue to go do a bunch of behind-the-scenes operations and create your project. As it shoots out some descriptions of what it’s doing from time to time, you may notice it say something like the following:
opening_studio_22
You see your project name, which is familiar. But then there is this Gradle word, and then a mention of Maven in the URL. The benefit of having a modern IDE like Android Studio is that it handles a lot for you. But as you’re just beginning to learn Studio, it’s good to know, in general, what it’s doing for you.
  • Gradle is a new build tool that is easy to use, but it also contains a lot of advanced options if you investigate it further. Basically, it takes your Java code and XML layouts, and uses the latest Android build tools to create the app package file, known as an APK file. You can customize your configurations to have development or production versions of the app that behave differently, or add dependencies for third-party libraries.
  • Maven is another project build tool, and it can also refer to the Maven Central repository of java libraries. It is absurdly easy to use Gradle and Maven Central in concert with Android Studio to incorporate all sorts of functionality from the Android development community. Those with an iOS background will know how cool this sort of thing can be from using the CocoaPods tool. You’ll learn more about Maven in Part Three of the tutorial.
After a while, Android Studio will finish building your project. The project is pretty empty, of course, but it still has everything it needs already set up so that it can be launched on an Android device or emulator. You will be dropped off in this spot:
opening_studio_23
You’re looking at a layout file in XML format. Before you get into any programming, let’s talk about how you’re going to get this app running. It’s time to say “Hello world!”

Running on an Emulator or Device

All right: You’ve got Android Studio and you’ve created an app. Let’s see this app live on an emulator or device!
Press Edit Configurations. You’ll find it marked in the image below. Note that some windows have it moved to the right a little and the option may take a minute to appear as Studio finishes all processes.
opening_studio_25_arrow
A new dialog will appear showing you some options for Run/Debug Configurations.
Android Edit Configurations dialog
Well, you want to run your app, so you must be in the right place. Look where it says Target Device. Here’s where you tell Studio where you want to run the app.
Note: In some versions of Android Studio, you may have to select Defaults\Android Application from the left menu pane in order to see the configuration options.
At this point, it would be best if you have an Android device handy — more about readying your device in just a bit. But for those without one, you also have the choice to run on an emulator.
Now, let me say a word about the emulator. Android Studio comes free with the ability to set up a software-based Android device on your computer and run apps on it, browse websites, debug and everything. This capability is known as the Android emulator.
You can set up multiple emulators if you want and you can set the screen size and platform version for each new emulator to whatever you like. This is great, as you can avoid having to buy multiple devices for testing.
The downside to the emulator is a big one. Unfortunately, the emulator is painfully slow. For those coming from iOS development, you will really start to appreciate the iOS Simulator after using the Android emulator.
Note: The truth is that the emulator is prohibitively slow and should generally be avoided unless you have no other option. Over the course of an Android development career, you could literally waste hours of cumulative time waiting for the emulator to launch and load your app.
emulator_ragecomic
All of that being said… let’s set up an emulator anyway.
In Target Device, click the Emulator option, followed by the button to the right of the drop-down.
emulator_creation_arrow
Note: You need to select the button to the right only if you want to create a new emulator. If your Android development set up already contains some emulators you’ve created, then you can simply select one of those from the drop down instead.
This opens the Android Virtual Device (AVD) Manager. This is the place where you can create, edit, and delete the various emulators you might want to work with. Since your list is probably empty (if you are just starting Android development), you need to create your first one. Click New.
opening_studio_27_arrow
Now you see a bunch of options to create your emulator:
opening_android_28
There are options to base your virtual device off a real one (I chose Nexus 4), set its Target API Level (I chose 4.2.2 Jelly Bean) and so on. You have some flexibility here, but if you’re not sure what to choose, you can copy my settings from the image above. Once you’re ready, click OK.
Note: If your Device selection doesn’t automatically pick a CPU, make sure to select an ARM processor for your emulator.
You’ll see a brief summary pop-up of the options you just chose. Dismiss that, and then your newly-created emulator is on the list and ready to run your app!
opening_studio_30
Now, close the AVD Manager to go back to the Run/Debug Configurations dialog. You now have the option to choose your new AVD as the default configuration:
opening_android_31
Set the new AVD as the default configuration, click Apply and then OK. You’re back at Android Studio’s main view. Now that you’ve configure everything, there’s but one step left…
Click the Run button. It looks like a “play” icon.
run_button
You may have to wait a while as the emulator loads, and you may even need to try it more than once for the emulator to get it right, but once it’s ready, you should see something like this:
hello_world
Congratulations! You made your first Android app!
Android apps used to be something you only interacted with on the consumer side, but now… you’re a creator. There’s power and possibility in that. It’s worth taking a moment to think about where you might want to go with this newfound ability.
When you’re ready, you need to revisit something I quickly glossed over earlier — testing on devices.

Navigating the Android Candy Store

One of Android’s advantages, the diversity of devices that can run the platform, is also a major complication for developers. You have to consider just about everything, such as the items on the following non-exhaustive list, to be variable:
  • Screen sizes, both physically and in terms of pixels.
  • Screen density, or the number of pixels per mm.
  • The ratio of the screen width to the screen height.
  • The number of simultaneous touches the touchscreen can register.
  • The quantity and positioning (front vs. back) of cameras.
  • Bluetooth capabilities.
  • Platform and software versions.
If you want to make an app that will run on a hundred different devices, how can you tell if it’s going to work? Well, there are six main strategies I can recommend:
  1. Nail down your target.
  2. Filter your manifest.
  3. Check Android’s best practices.
  4. Emulate.
  5. Pick at least one representative device.
  6. Fake other screens on your device.
Let’s go through them one by one.

1. Nail down your target.

Does your app have some specific, indispensable hardware or software requirement? What about nice-to-haves? Take stock of device needs early, so that if your app is camera-based, or communicates with a specific product through Bluetooth, you’re ready to target your app to devices with those capabilities.
Check the often-updated Android Dashboards to see the prevalence of platform versions as well as screen sizes and densities. You can see, for example, that your choice in this tutorial to only support Ice Cream Sandwich and higher will (at press time) lose you about a quarter of Android users. It’s a reasonable sacrifice in your case.

2. Filter your manifest.

Once you’ve determined you app’s requirements, you need to let Android know about them. That way, the Google Play Store can keep non-compatible devices from purchasing your app.
This will save you a lot of frustration and poor reviews from users who might have downloaded your app, only to find a strange error awaiting them. It won’t, however, absolve you from communicating in any marketing materials the list of devices your users should expect to be able to run your app on.
The device features you need should be listed in a file. This file, available in every project, is called the Android manifest. This is an XML file that contains all the high-level info about your app. Remember when you chose API 14: Ice Cream Sandwich as the minimum SDK when you created the OMG Android project? That choice is now reflected in your Android manifest.
Find AndroidManifest.xml on the left side of the Android Studio window and double-click it to take a look. Can you spot where the code sets the SDK version?
android_manifest
The code sets the minimum and target SDKs via the uses-sdk tag. The target SDK value just lets Android know that you’ve tested your app up to that version and everything’s shiny, not to fret. The target SDK should always be the newest possible SDK.
Just as the uses-sdk tag tells Android to filter out devices that don’t meet the minimum SDK, you can use the uses-feature tag to allow only qualified devices. For a different app — not for this demo — one would add this line to filter out devices without a camera:
<uses-feature android:name="android.hardware.camera" />

3. Check Android’s best practices.

There’s a great list of best practices to address compatibility issues that’s available on the Android site. Some of the most useful tips include:
  • Use density-independent measurements in your layouts, so your specifications will scale along with the screen.
  • When putting together layouts, use relative widths and heights instead of absolute values.
  • Putting in several versions of the same image file, tailored to different screen densities, can also be a good idea.
The tutorial will discuss these in more detail in Part Two, when you lay out views in XML.

4. Emulate.

When you set up your emulator earlier, you saw how many options you have to work with different screen sizes. You also saw how slow the emulator can be. It is a flawed tool, but it can be useful when you have an issue under a specific hardware configuration but do not have the necessary hardware to replicate the issue.

5. Pick at least one representative device.

The most expensive option, unless you already own an Android device, is to go out and buy one. I recommend trying to find a used, unlocked device from the Google Nexus series. If your budget is tight, I’d go two generations back, which at the moment would mean a Galaxy Nexus. Of course, if you’ve got the money, you can go for the new snazzy Nexus 5!
With all the time you will save avoiding the emulator, if you continue on with Android (which I hope you will!), it will definitely be a worthwhile investment.
If you have a device, you don’t need any silly provisioning profiles. You just need to turn on USB debugging for your device. Sometimes the checkbox option is available just by going to Settings > Developer Options on your device. Check these instructions for more details.
Other times, you have to do some weird shenanigans. I can’t make this up! A direct quote from Android: “On Android 4.2 and newer, Developer options is hidden by default. To make it available, go to Settings > About phone and tap Build number seven times. Return to the previous screen to find Developer options.”
No matter if you had to do a little dance or whistle a perfect C to reveal the option, once USB debugging is on, you can go back to the Run/Debug Configurations screen and set your Target Device to USB Device. This will serve you well for the rest of the tutorial.

6. Fake other screens on your device.

If you are lucky enough to have a device and have enabled USB Debugging on it, then you have another testing advantage: you can use it to “fake” other screen sizes. Here’s how.
Open your Terminal as you did earlier, when you checked for the JDK. Then locate a tool called the Android Debug Bridge (adb). With early versions of Android Studio, it will be in the /Applications/Android\ Studio.app/sdk/platform-tools directory, or wherever you installed your copy of Android Studio, if elsewhere. Later versions of Android Studio do not come with the Android SDK bundled in and so, you might have your Android SDK installed in a totally different location.
You can use the following command at the Terminal prompt to see if adb is available in your system PATH:
adb version
The result should be something like this:
check_for_adb
Note: If the adb version command results in an error message, your Android SDK folder is probably not in your PATH. Then you’d need to find the exact location of the Android SDK and change to the correct folder (as in the first steps in the screenshot above) before you can use any adb commands.
The adb version command is just an example to show you how to call adb from the command line. It can run all sorts of commands and you can get a list of available commands by typing adb help.
If not already set up, you can optionally add the Android SDK platform tools folder to your $PATH so that you can run adb from anywhere on your system. I’d suggest that you do this only if you are familiar with UNIX and feel comfortable doing this.
With your device plugged in and with its screen turned off, type the following:
adb shell wm size 640x480
And then type:
adb shell wm density 160
This represents a screen size of 640×480 pixels with 160 pixels per inch pixel density.
Note: In Android versions earlier than 4.3 Jelly Bean, these commands are slightly different, as documented here.
When you turn the device screen back on, you should see that the resolution has changed to match the new values you entered!
Feel free to turn the screen off, try another set of dimensions and turn it back on again.
To return your device to its normal settings, type:
adb shell wm size reset
And then type:
adb shell wm density reset
So you could get a full-size tablet (like a Nexus 10, perhaps) and then easily simulate all sorts of smaller devices, without having to use the emulator!
I hope that information helps you navigate the Gingerbreads, KitKats, Jelly Beans, and all the other varieties of Android candy. Now, back to the app at hand…

So… WHY did that work?

You’ve got your first app behind you. To start making changes and adding cool features, it’s necessary to get a working knowledge of what’s going on behind the scenes.
Take a look at the Project section of Android Studio, with the files and folders on the left side of the screen. You may need to press the little tab on the edge (see below) if the project explorer isn’t visible at the moment.
find_project_files
Browse around for a few minutes without any explicit instructions from me, expanding and collapsing folders and double-clicking on files to see their contents in the main window. If you notice any trends, great. If it all still looks cryptic, not to worry!

Android Project Structure: The Team

Every great team is composed of people who play different roles. Do you want to do the job right? You need the right team. Android Projects have a few key elements and each has a role to play:
  1. Java: The Professional
  2. Resources: The Artist
  3. AndroidManifest.xml: The Boss
  4. Intent: The Job itself

Java: The Professional

It’s the job of your Java code to get things done. Your code is all going to be in the src\main\java directory under your main project folder. I’ll give you all the code you need to complete this tutorial, but if you want to learn or refresh your Java knowledge, here is a nice online interactive tutorial.
It will be worth your time to learn more and more Java as you explore Android development. Your team is relying on the professional.

Resources: The Artist

It’s not enough to just get the job done. It needs to be done in style. Your app is never going to stand out unless it has great icons and images, well-designed layouts, engaging copy text, and maybe even some smooth animations.
Initially, the src\main\res (Resources) folder contains:
  • Drawable folders that hold images — just the default launch icon for now.
  • The layout folder with XML that represents the screen designs.
  • The menu folder with XML of the items that will appear on the Action Bar. More on that later.
  • The values folder with XML containing dimensions, strings, and styles.

AndroidManifest.xml: The Boss

Someone’s got to call the shots. That “someone” would be the Android manifest. This XML file informs your system of the app’s hardware and software requirements and contains your app’s name, icon, and version.
The manifest also filters the Intents coming in. You need a job done by your app? Talk to the boss first. Now, more about the jobs themselves…

Intent: The Job itself

Want to show the user a screen? Want to navigate to a website? Whatever the job is, in Android it is going to take the form of an Intent. If you come from an iOS background, pay close attention because this is a very “Android” concept.
The Android system knows that you will potentially have a lot of apps on your device, and wants to make it easy for them to talk to each other. So, it allows you to send and receive what are essentially requests for jobs to be done.
A job could get picked up by your app’s own boss (the manifest) or another app. When creating an Intent, it’s up to you to either write it very generally to have the option of picking from several apps to perform the job (implicit), or very specifically to follow a certain path (explicit). You’ll see an example of each type if Intent later in this tutorial.
For an immediate example, your app already has an Activity called MainActivity. Your manifest has it labeled with an intent filter that causes the MainActivity to launch when the user selects the app icon from their home screen. You could potentially move that filter to another Activity and then that activity would launch instead of MainActivity. Basically, the app does whatever the boss says.
If you don’t fully grasp everything about Intents right away, don’t worry. Just keep the concept in mind as you see Intents throughout the code, and eventually you will start to get an idea of their potential.

Putting a Personal Stamp on Your App

You’ve made your first app, but what’s the first thing you always want to put on any of your work? No, not a bird… your name!
Navigate to res/values/strings.xml and double-click the file. When you open the file, you’ll see three string resources in XML.
These resources are accessed in different places, but it is very convenient to have all of the text used in your app in one file. If you need to translate it, or if your marketing coworker tells you to remove all the nerdy references from your app, it will be easy to make all the changes here.
Change the hello_world string. That string is the one that the app displays on the screen. So, change it to something more personal that incorporates your own name – something like:
<string name="hello_world">Matt is learning Android!</string>
opening_android_46
So remember: When you launch the app, you’re essentially doing the same thing as sending a launch Intent to the manifest. As the boss, the manifest takes a look at the Intent and decides it has the perfect fit for the job: MainActivity. The Java does the heavy lifting of opening the screen, but for what to display it goes and asks the artist, eventually leading to strings.xml.
Click Run. When the app launches again, you’ll see your personalized message!
personalized_hello_world
Congratulations! If you have a device, you can go around showing off your new app to your friends or take a screenshot from the emulator and send it to them.
You’ve entered the world of Android. You’ve set up your development environment (no easy task!), created your first app, run it on an emulator or device, and changed the app so that it specifically addresses you. Great job!

Updating With the SDK Manager

This tutorial will work with whatever SDK version you downloaded with Android Studio, but it is also a good idea to always keep your SDK versions and Android Platform Tools up-to-date.
Click the sdk_manager_button button in Studio to access the SDK Manager, which allows you to easily update your Android SDK components.
sdk_manager
You can also download older SDKs and other tools, if you need them for future projects, via the SDK Manager.

Where to Go From Here?

There’s a lot still to come, but here are some extra tips to think about before jumping into the next part of the tutorial:
  • Follow Android. The development community around any language or framework can be its strongest asset. It’s never too soon or too late to start checking out Google I/O videos, following the Android Developers blog or watching DevBytes videos.
  • Get the full source for this section of the tutorial on GitHub or as a .zip.
  • Post any comments/suggestions/questions below.
  • Stick around for the second and third sections of the tutorial! Thank you!
sources : http://www.raywenderlich.com/56107/make-first-android-app-part-1

Thousands attend pro-Palestine rally in New Zealand (PHOTOS, VIDEO)

Thousands attend pro-Palestine rally in New Zealand (PHOTOS, VIDEO)

Photo posted by Rashed Al Shaya on Facebook.com
Photo posted by Rashed Al Shaya on Facebook.com
Several thousand people are estimated to have marched through central Auckland to protest the Israeli ground invasion of Gaza, which, along with previous airstrikes, have resulted in over 300 deaths in under two weeks’ time.
Marchers with umbrellas, placards and Palestinian flags in hand took to the heart of New Zealand’s most populous city to show solidarity with the people of Gaza on Saturday. Estimates range between several hundred and several thousand attendees, though footage posted by OccupyNZ indicates the latter figure is likely more accurate.

Chants of “Free, free Palestine!” and “One, two three, four, we don’t want your bloody war!” rang out through the streets as a large black and white banner with the phrase ‘Free Palestine’ headed up the procession down Queens Street.


Many held placards with phrases like ‘All children desire peace’ and ‘Free Gaza.’


Some, however, were far more acerbic in their criticism, defacing the Israeli flag with a swastika or juxtaposing the Star of David with the Nazi symbol to protest Israeli policy in the region.

Photo posted by Rashed Al Shaya on Facebook.com
Photo posted by Rashed Al Shaya on Facebook.com

There were also calls to shut down the Israeli embassy in the city.

Photo posted by Rashed Al Shaya on Facebook.com
Photo posted by Rashed Al Shaya on Facebook.com

A counter-demonstration was also held, though no violent altercations were reported when the two sides crossed paths near the Britomart transport hub.



Protesters later marched to the US consulate on Customs Street to show their opposition to the country's economic and military ties to Israel, holding a moment of silence outside the compound for those who have died since the ground invasion of Gaza kicked off on Friday.

People also laid olive tree branches outside the building, one for each life lost since the latest outbreak of violence hit the region.

"I'm just so sad about all the innocent women and children being killed in Palestine,"
Diane Sisley, who made a peace offering outside the US consulate, told the Herald on Sunday. "I think it's such an unequal, disgusting war."

The protest concluded with the song, 'We are all Palestinians.'


Earlier this week, foreign affairs minister Murray McCully said, “New Zealand fully supports the United Nations Security Council's call for an urgent ceasefire in Gaza."
Associate foreign affairs spokesman Phil Goff, meanwhile, said Israelis, Palestinians and the international community should all take the initiative by making the necessary compromises to achieve lasting peace.
“The Israeli retaliation is always disproportionate," he said in regards the most recent military escalation. "Having been there many times I can understand why the Palestinian people are bitter."
He added, however, that the Jewish state had a right to protect itself from Gaza-based rocket attacks.
"Israel is a fact of life. It has a right to stable borders and peace but so do the Palestinian people."
While the action in Auckland went off peacefully, others have spiraled out of control.


On Friday, Israel decided to reduce its diplomatic delegation in Turkey to the “minimum required” after violent pro-Palestinian protests hit Israeli diplomatic missions in Ankara and Istanbul.
On Thursday, France moved to block pro-Palestinian protests throughout the country after a previous march turned ended in bloodshed. After 10,000 demonstrators took to the streets of Paris on Sunday, some protesters turned violent, lobbing rocks at police, who responded with tear gas.
Three synagogues were also assaulted by rioters, with up to 200 people trapped inside one of them. Three Jews sustained injuries in the attacks and were sent to hospital.
However, a group of 150 men allegedly linked to the Jewish Defence League were also seeing clashing with pro-Palestinian demonstrators. Some of them could be seen brandishing iron bars and cans of pepper spray.

Malaysia Airlines flight MH17 crash: world demands answers from Russia



Firefighters and journalists discuss Malaysia Airlines flight MH17, which was shot down in eastern Ukraine
The US has pointedly criticised Russian arming of rebels in Ukraine as the world demanded answers over the shooting down of Malaysia Airlines flight MH17 by a suspected Russian-made missile, resulting in the death of all 298 people on board the civilian airliner.
The White House stopped short of directly blaming Russia for the plane’s destruction but linked its remarks on the disaster to the Kremlin’s support for separatists in Ukraine, urging Vladimir Putin’s government to stop inflaming the situation in the country and take "concrete steps" towards de-escalation.
The huge loss of life threatens to have wide-ranging and unpredictable consequences, coming just after the US imposed further sanctions on Russia for continuing to provide weapons to the rebels.
The former US secretary of state, Hillary Clinton, made some of the most potent remarks in a television interview, saying there were strong indications Russian-backed militia were to blame and action was needed to "put [Vladimir] Putin on notice that he has gone too far and we are not going to stand idly by".
Clinton called for the EU to increase sanctions on Russia, while the Australian prime minister Tony Abbott demanded that Russia explain the disaster as it “now seems certain it’s been brought down by a Russian-supplied surface-to-air missile”.
The German chancellor, Angela Merkel, said it was too soon to make a decision on tougher sanctions. "The events with the plane, as far as I remember, were not even 24 hours ago and at the moment we need to sort out an independent investigation."
There were 173 Dutch nationals on board the plane, along with 44 Malaysians, 27 Australians, 12 Indonesians, nine passengers believed to be from the UK, four each from Germany and Belgium, three from the Philippines, one Canadian and one from New Zealand. The nationalities of 20 passengers have not yet been verified. A group of international HIV/Aids experts flying to Melbourne were among those killed.
The British foreign secretary, Philip Hammond, said: "We are working through passenger data, cross-checking it and referencing it to establish exactly the numbers and identities of those British nationals."
The Malaysian prime minister, Najib Razak, said the news marked “a tragic day in what has already been a tragic year for Malaysia”, referring to the earlier disappearance without a trace of Malaysia Airlines flight MH370. He said those responsible for tragedy the must be held responsible.
Flags were lowered to half-mast in the Netherlands and Australia.

The Dutch flag flys at half-mast at Schiphol airport
The Dutch flag at half-mast at Schiphol airport Photograph: Christopher Furlong/Getty Images

Kiev and Moscow have blamed each other for the disaster.
Putin ordered Russian military and civilian agencies to co-operate with any investigation but, according to a Kremlin statement, said the "state over whose territory this occurred bears responsibility for this awful tragedy."
The Ukrainian foreign minister, Pavlo Klimkin, said on Friday there was no chance the missile was of Ukrainian military origin. He said the Ukrainian army did not have such missiles in the area, and said none had been seized by separatist fighters in recent weeks.
The jet was flying from Amsterdam to Kuala Lumpur on Thursday when it was blown apart and fell in a shower of fiery wreckage over the village of Grabovo, part of the area controlled by pro-Russia separatists.
The Organisation for Security and Cooperation in Europe (OSCE) said on Friday that separatists had agreed to provide assistance to those investigating the crash of the plane and would ensure safe access for international experts visiting the site.


Defence and security experts said the Russian-made Buk surface-to-air missile system, known to be in the hands of pro-Russia fighters in Ukraine, was most likely used.
The US vice-president, Joe Biden, said the plane appeared to have been "blown out of the sky", while the Ukrainian security services released an audio recording said to be rebel commanders discussing the fact that their forces were responsible with Russian officers.
The UN security council it is to meet on Friday as calls mount for an international response. “There is clearly a need for a full, transparent and international investigation,” said the UN secretary general, Ban Ki-Moon, sending his condolences to the victims’ families.

A Malaysian mother reacts after seeing her daughter's name on the list of passengers on board Malaysia Airlines MH17 when it was shot down over Ukraine with no survivors.
A Malaysian mother reacts after seeing her daughter's name on the list of passengers on board Malaysia Airlines MH17. Photograph: Edgar Su/Reuters

In Kuala Lumpur, Malaysia's transport minister Liow Tiong Lai stressed that MH17 was following "the right route on the right path" amid a barrage of questions from local and foreign reporters as to why Malaysia Airlines would have chosen to fly over a war zone. Qantas, the Australian carrier, said it had been steering clear of the area by 400 nautical miles for several months.
"It is many years that we have taken the same route and many other countries take the same route," he said. He stressed that some 15 of 16 Asia-Pacific Airlines fly "this route over Ukraine" and added: "European airlines also use the same route, and traverse the same airspace. In the hours before the incident, a number of other passenger aircraft from different carriers used the same route."
He also said that there had been "no last-minute instructions" given to the pilots to change the route.
The European air traffic control body, Eurocontrol, said Ukrainian authorities had banned aircraft from flying at 32,000ft or below and the doomed aircraft had been cruising above that, at 33,000ft – however this apparently still left it within range of the sophisticated surface-to-air weaponry that pro-Russia forces have been using recently to target Ukrainian military aircraft. All civilian flights have now been barred from eastern Ukraine.
The field next to the tiny hamlet was a scene of charred earth and twisted metal as shocked local people milled around the scene. Body parts belonging to the 298 on board were strewn around. The body of what appeared to be a young woman had been flung about 500m from the centre of the crash.
US government officials confirmed to media outlets that a surface-to-air missile brought down the plane. US intelligence was reportedly still working to determine the exact location from which the missile was fired, and whether it was on the Russian or the Ukrainian side of the border.
Rebels in the self-declared Donetsk and Luhansk people's republics have shot down several Ukrainian planes and helicopters in recent weeks. But they insisted they had no part in the downing of MH17, claiming instead that Ukrainian fire was responsible.
Ukraine's SBU security services released a recording, which could not immediately be verified, of what it said were rebel commanders saying they had shot down a plane and then discovering with horror it had been a civilian jet.

Ukraine security services recording said to reveal pro-Russia separatists admitting they shot down plane.

On the ground in Grabovo a strong smell of aviation fuel and burnt rubber hung in the air as dozens of pro-Russian separatist fighters milled around the area in which workers from the emergency services were sifting through the wreckage. A dozen fire engines were on the scene.
One local resident, Alexander, had been working in a field a few hundred metres from the crash site and thought the aircraft was going to fall on top of him. Another farmer said he was on his tractor when he heard a loud bang. "Then I saw the plane hit the ground and break in two – there was thick black smoke," he said.
In a conflict that has not been short of dreadful twists, this was by far the most shocking and most gruesome to date. The 298 people on board MH17 had no connection to the fighting – their international flight was simply travelling through airspace above the battle zone.

Malaysia Airlines announces the nationalities of those on board flight MH17.

Throughout the Ukraine conflict the versions of violent incidents provided by Kiev and the Donetsk rebels have diverged wildly, with each side blaming the other for loss of life and the shelling of residential areas.
Now, with such a huge and unexpected loss of life, the stakes are immeasurably higher, and both sides again rushed to claim the other was at fault.
Those blaming pro-Russia rebels for the attack pointed to a post on a social media site attributed to a top rebel commander which claimed to have downed a Ukrainian transport plane around the same time as the first reports of MH17's disappearance surfaced. The post was later deleted.
The US and EU have heavily criticised Russia for providing the separatists in eastern Ukraine with logistical and military support, leading to a new set of White House sanctions against Russian companies, introduced on Wednesday, as rhetoric coming out of both Washington and Moscow has led to talk of a new cold war. Vladimir Putin's spokesman Dmitry Peskov told the Guardian that any allegations of Russian involvement in the MH17 crash were "stupidity".
He said the Kremlin would not make a further statement because "no one knows" who is responsible.
Asked about the possibility of further US sanctions, Peskov said he could not rule it out: "The United States has recently been conducting a very nonconstructive policy and their actions are very unpredictable," he said.
Putin, who on Thursday returned to Russia from a summit of the Brics nations in Brazil, informed Barack Obama about the incident.
"The Russian leader informed the US president of the report from air traffic controllers that the Malaysian plane had crashed on Ukrainian territory, which had arrived immediately before the phone call," said a statement released by the Kremlin.
According to the statement, the pair spent most of the conversation discussing the deterioration of US-Russian relations, and Putin expressed his "serious disappointment" over the latest round of US sanctions against Russian companies.
Later Putin chaired a meeting on the Russian economy which began with a minute's silence and laid the blame for the crash at Ukraine's door: "There is no doubt that the nation over whose airspace this happened bears responsibility for the terrible tragedy," he said.
David Cameron, the British prime minister, tweeted: "I'm shocked and saddened by the Malaysian air disaster. Officials from across Whitehall are meeting to establish the facts."
The crash came four months after another Malaysia Airlines flight, MH370, vanished on a flight from Kuala Lumpur to Beijing with 239 people on board, two-thirds of them Chinese citizens. It has yet to be found despite a huge search.

Ukrainian president says shooting down of plane is a warning for the world on Russian aggression.

Igor Sutyagin, a Russian military specialist at the London-based Royal United Services Institute, agreed that the plane would almost certainly have been shot with a Buk, a vehicle-mounted missile system first developed in the Soviet era. The Malaysian aircraft,was beyond the range of Manpads – shoulder-launched missiles. Kalashnikov-carrying Russian sympathisers in Ukraine would not have had the expertise to fire them and would have needed either specialists who had "volunteered" their services from Russia or locally recruited specialists, he said, noting that the rebels had been firing at Ukrainian aircraft over the last week.
The Associated Press said one of its journalists had seen a similar launcher near the town of Snizhne earlier on Thursday.
Russia's state-owned Channel One avoided speculation of who might have been behind the plane crash in its first bulletins on the subject, while the Kremlin-friendly Life News, whose reporters were first on the scene, said it was likely to have been brought down by Ukrainian fire, claiming that the rebels did not have any missile systems with the capacity to down a plane at that altitude.
However a report on the website of Russian state television from late June described how the rebels in Donetsk had taken control of a Ukrainian missile defence facility that was equipped with Buk systems. The report said that the rebels planned to "defend the sky over Donetsk" using the missiles.
On Thursday afternoon a social media site attributed to Igor Strelkov, a Russian citizen who has emerged as the commander of rebel forces in Donetsk, announced that the rebels had shot down an An-26 Ukrainian transport plane, and also that there was "information about a second plane". The post was later removed.
Audio was circulated on social media, apparently released by Ukrainian security services, purporting to be an intercepted conversation of pro-Russia rebels confirming they had shot down a civilian jet.
The conversation is apparently between a group leader and his superior and suggests that they initially thought they had brought down a military aircraft but later realised their error.
The group leader, "Demon", tells his boss: "A plane has just been shot down. [It was] 'Miner's' group. It crashed outside Enakievo. Our men went to search for and photograph it. It's smouldering."
After his men apparently inspect the crash site, Demon reports back. "Cossacks from the Chernunkhino checkpoint shot down the plane. The plane disintegrated in mid-air … they found the first body. It's a civilian."
He carries on: "I mean. It's definitely a civilian aircraft."
His superior, nicknamed "Greek", asks him: "Were there many people?"
Demon replies: "A fuckton. The debris rained right into the yards."
Greek asks: "What's the aircraft?" and is told: "I haven't figured it out yet. I haven't reached the main section. I only looked at where the bodies began to fall. There are remains of chair mounts, the chairs, the bodies."
Greek asks: "Any weapons there?" and Demon says: "None at all. Civilian things, medical stuff, towels, toilet paper." "Any documents?" asks Greek, and Demon, perhaps realising what has just happened, replies: "Yes, an Indonesian student from Thomson university [in the US]."
Additional reporting by Tania Branigan in Beijing, Ewen MacAskill in London, Paul Lewis in Washington and Warren Murray of Guardian Australia