Android Mobile App Training 2017

Create a mobile app in 2 days

====================

Join my Android development workshop and learn how to build an app and release to app store in just 2 days. Only basic programming knowledge is required.

Upon completion of this course, you will be able to:
a. Build your own applications for Android mobile phones.
b. Understand how Android applications work, Android application components, manifest and Intent
c. Design Android applications with compelling user interfaces by using and creating your own layouts using external resources.
d. Use Android Web APIs for assessing Web Services such as Twitter etc. in background services
e. Take advantage of Android APIs for data storage and retrieval via user preferences, files and local databases.
f. Utilize the powerful Android API on maps, speech, medias and hardware to build complex applications.
g. Debug, test and deploy your own applications on Google Play Store.

Course fee is only RM550/pax (course materials and meals are included). Interested? Fill in your details through below link and I’ll be in touch soon:

http://bit.ly/2vry7Jn

Android Mobile App Training 2017

Android Mobile App Training 2017

Android SQLite Tutorial

In this tutorial you will develop a simple to-do-list native app using SQLite for android.

Download the required software packages

Download and install Android Studio and Android SDK.

Android Studio + SDK – http://developer.android.com/sdk/index.html

Setting up your development environment

Open your Android Studio and choose Start a new Android Studio project.

Start a new Android Studio project

Start a new Android Studio project

Enter your custom Application name, Company Domain and select Project location. Click Next.

Configure your new project.

Configure your new project.

Select Phone and Tablet. Make sure API 15 selected. Click Next.

Configure your new project.

Configure your new project.

Select Empty Activity and click Next.

Add an activity to Mobile.

Add an activity to Mobile.

Click Finish.

Customize the activity.

Customize the activity.

Create a new java class. Right click on my.intellij.androidsqlite package > New >Activity > Java Class.

Create a new java class.

Create a new java class.

Name it as Task and click Ok.

Create New Class

Create New Class

Then replace with this code in Task.java. Set your Task class with all getter and setter methods to maintain single task as an object.

package my.intellij.androidsqlite;

public class Task {

    //private variables
    int taskId;
    String name;
    String description;

    // Empty constructor
    public Task(){

    }
    // constructor
    public Task(int taskId, String name, String description){
        this.taskId = taskId;
        this.name = name;
        this.description = description;
    }

    // constructor
    public Task(String name, String description){
        this.name = name;
        this.description = description;
    }
    // getting taskId
    public int getTaskId(){
        return this.taskId;
    }

    // setting taskId
    public void setID(int taskId){
        this.taskId = taskId;
    }

    // getting name
    public String getName(){
        return this.name;
    }

    // setting name
    public void setName(String name){
        this.name = name;
    }

    // getting description
    public String getDescription(){
        return this.description;
    }

    // setting description
    public void setDescription(String description){
        this.description = description;
    }
}

Create a new java class. Right click on my.intellij.androidsqlite package > New >Activity > Java Class.

Create a new java class.

Create a new java class.

Name it as DatabaseHandler and click Ok.

Create New Class

Create New Class

Write DatabaseHandler class to handle all database CRUD(Create, Read, Update and Delete) operations.

package my.intellij.androidsqlite;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.util.ArrayList;
import java.util.List;

public class DatabaseHandler extends SQLiteOpenHelper {
    // All Static variables
    // Database Version
    private static final int DATABASE_VERSION = 1;

    // Database Name
    private static final String DATABASE_NAME = "tasksManager";

    // Tasks table name
    private static final String TABLE_TASKS = "tasks";

    // Tasks Table Columns names
    private static final String KEY_TASK_ID = "taskId";
    private static final String KEY_NAME = "name";
    private static final String KEY_DESCRIPTION = "description";

    public DatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // Creating Tables
    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_TASKS_TABLE = "CREATE TABLE " + TABLE_TASKS + "("
                + KEY_TASK_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT,"
                + KEY_DESCRIPTION + " TEXT" + ")";
        db.execSQL(CREATE_TASKS_TABLE);
    }

    // Upgrading database
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_TASKS);

        // Create tables again
        onCreate(db);
    }

    /**
     * All CRUD(Create, Read, Update, Delete) Operations
     */

    // Adding new task
    void addTask(Task task) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_NAME, task.getName()); // Task Name
        values.put(KEY_DESCRIPTION, task.getDescription()); // Task Description

        // Inserting Row
        db.insert(TABLE_TASKS, null, values);
        db.close(); // Closing database connection
    }

    // Getting single task
    Task getTask(int taskId) {
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(TABLE_TASKS, new String[] { KEY_TASK_ID,
                        KEY_NAME, KEY_DESCRIPTION }, KEY_TASK_ID + "=?",
                new String[] { String.valueOf(taskId) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        Task task = new Task(Integer.parseInt(cursor.getString(0)),
                cursor.getString(1), cursor.getString(2));
        // return task
        return task;
    }

    // Getting All Tasks
    public List<Task> getAllTasks() {
        List<Task> taskList = new ArrayList<Task>();
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_TASKS;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                Task task = new Task();
                task.setID(Integer.parseInt(cursor.getString(0)));
                task.setName(cursor.getString(1));
                task.setDescription(cursor.getString(2));
                // Adding task to list
                taskList.add(task);
            } while (cursor.moveToNext());
        }

        // return task list
        return taskList;
    }

    // Updating single task
    public int updateTask(Task task) {
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_NAME, task.getName());
        values.put(KEY_DESCRIPTION, task.getDescription());

        // updating row
        return db.update(TABLE_TASKS, values, KEY_TASK_ID + " = ?",
                new String[] { String.valueOf(task.getTaskId()) });
    }

    // Deleting single task
    public void deleteTask(Task task) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_TASKS, KEY_TASK_ID + " = ?",
                new String[] { String.valueOf(task.getTaskId()) });
        db.close();
    }


    // Getting tasks Count
    public int getTasksCount() {
        String countQuery = "SELECT  * FROM " + TABLE_TASKS;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(countQuery, null);
        cursor.close();

        // return count
        return cursor.getCount();
    }
}

Open MainActivity and replace with this code.

package my.intellij.androidsqlite;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import java.util.List;

public class MainActivity extends AppCompatActivity {

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

        DatabaseHandler db = new DatabaseHandler(this);

        /**
         * CRUD Operations
         * */
        // Inserting Tasks
        Log.d("Insert: ", "Inserting ..");
        db.addTask(new Task("Breakfast", "Nasi Lemak"));
        db.addTask(new Task("Lunch", "Nasi Ayam"));
        db.addTask(new Task("Dinner", "MCD"));

        // Reading all tasks
        Log.d("Reading: ", "Reading all tasks..");
        List<Task> tasks = db.getAllTasks();

        for (Task cn : tasks) {
            String log = "TaskId: "+cn.getTaskId()+" ,Name: " + cn.getName() + " ,Description: " + cn.getDescription();
            // Writing Tasks to log
            Log.d("Name: ", log);
        }
    }
}

Build and run the app. The output will be show up like below.

Logcat output.

Logcat output.

Android (GCM) Push Notification Tutorial

In this tutorial, I will show you how to implement push notifications in your native app for android.

Download the required software packages.

  1. Download and install Android Studio and Android SDK.
  2. Android Studio + SDK – http://developer.android.com/sdk/index.html.

Go to Google Developer (https://developers.google.com/mobile/add). Click Pick a platform.

Google services.

Google services.

Click Enable services for my Android App.

Google Services.

Google Services.

Enter your App name and Android package name. Click Choose and configure services.

Google Services.

Google Services.

Select Cloud Messaging and click Enable Google Cloud Messaging.

Google Services.

Google Services.

Make a note of the server API key and press Close.

Google Services.

Google Services.

Click Generate configuration files.

Google Services.

Google Services.

Click Download google-services.json. Once the file has been generated, download it and place it inside your Android Studio project’s app directory.

Google Services.

Google Services.

Setting up your development environment

Open your Android Studio and choose Start a new Android Studio project.

Start a new Android Studio project

Start a new Android Studio project

Enter your custom Application name, Company Domain and select Project location. Click Next.

Configure your new project.

Configure your new project.

Select Phone and Tablet. Make sure API 15 selected. Click Next.

Configure your new project.

Configure your new project.

Select Empty Activity and click Next.

Configure your new project

Configure your new project

Your app must request the C2D_MESSAGE  permissions, if it isn’t doing so already. Add the following lines inside the tag in your AndroidManifest.xml:

<permission android:name="my.intellij.androidpushnotification.permission.C2D_MESSAGE" android:protectionLevel="signature" />
    <uses-permission android:name="my.intellij.androidpushnotification.permission.C2D_MESSAGE" />

The notifications are received in the form of broadcasts. To handle those broadcasts, our app needs a BroadcastReceiver. However, we don’t have to create it manually. We can instead use the GcmReceiver class as the BroadcastReceiver.

The BroadcastReceiver must have an intent-filter that responds to the com.google.android.c2dm.intent.RECEIVE action and the name of its category must match your project’s package name. Add the following code to the manifest

<receiver android:name="com.google.android.gms.gcm.GcmReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <category android:name="my.intellij.androidpushnotification" />
    </intent-filter>
</receiver>

Open build.gradle (Project:AndroidPushNotification) and add into dependencies block

classpath 'com.google.gms:google-services:1.5.0'

Next, apply the plugin in the app module’s build.gradle on the top

apply plugin: 'com.google.gms.google-services'

And this code on bottom part in the app module’s build.gradle.

configurations.all {
    resolutionStrategy {
        force 'com.android.support:design:23.4.0'
        force 'com.android.support:support-v4:23.4.0'
        force 'com.android.support:appcompat-v7:23.4.0'
    }
}

To be able to use the GCM API, add com.google.android.gms:play-services as a compile dependency in the same file

compile "com.google.android.gms:play-services:8.3.0"

Create a new java class. Right click on my.intellij.androidpushnotification package > New >Activity > Java Class.

Create a new java class.

Create a new java class.

Name it as RegistrationService and click Ok.

Create New Class

Create New Class

Then replace with this code in RegistrationService.java.

package my.intellij.androidpushnotification;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

import com.google.android.gms.gcm.GcmPubSub;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.android.gms.iid.InstanceID;

import java.io.IOException;

public class RegistrationService extends IntentService {
    public RegistrationService() {
        super("RegistrationService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        InstanceID myID = InstanceID.getInstance(this);

        try {
            String registrationToken = myID.getToken(
                    getString(R.string.gcm_defaultSenderId),
                    GoogleCloudMessaging.INSTANCE_ID_SCOPE,
                    null
            );

            Log.d("Registration Token", registrationToken);

            GcmPubSub subscription = GcmPubSub.getInstance(this);
            subscription.subscribe(registrationToken, "/topics/my_little_topic", null);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Define the service in AndroidManifest.xml.

<service android:name=".RegistrationService" android:exported="false" />

Create a new java class. Right click on my.intellij.androidpushnotification package > New >Activity > Java Class.

Create a new java class.

Create a new java class.

Name it as TokenRefreshListenerService and click Ok.

Create New Class

Create New Class

Then replace with this code in TokenRefreshListenerService.java.

package my.intellij.androidpushnotification;

import android.content.Intent;
import com.google.android.gms.iid.InstanceIDListenerService;

public class TokenRefreshListenerService extends InstanceIDListenerService {
    @Override
    public void onTokenRefresh() {
        Intent i = new Intent(this, RegistrationService.class);
        startService(i);
    }
}

Define the service in AndroidManifest.xml.

<service android:name=".TokenRefreshListenerService" android:exported="false">
        <intent-filter>
            <action android:name="com.google.android.gms.iid.InstanceID" />
        </intent-filter>
    </service>

Open MainActivity.java and replace with this code.

package my.intellij.androidpushnotification;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

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

        Intent i = new Intent(this, RegistrationService.class);
        startService(i);
    }
}

Create a new java class. Right click on my.intellij.androidpushnotification package > New >Activity > Java Class.

Create a new java class.

Create a new java class.

Name it as NotificationsListenerService and click Ok.

Create New Class

Create New Class

Then replace with this code in NotificationsListenerService.java.

package my.intellij.androidpushnotification;

import com.google.android.gms.gcm.GcmListenerService;

public class NotificationsListenerService extends GcmListenerService {

}

Define the service in AndroidManifest.xml.

<service android:name=".NotificationsListenerService" android:exported="false" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    </intent-filter>
</service>

Go to https://material.io/icons/ and search for cloud icon. Once you download the icon, place it inside the res folder of your project. Use ic_cloud_black_48dp as the icon.

Google’s Material Design Icons Library

Google’s Material Design Icons Library

Build and run your app. You will an output like this in your android studio console.

Create send.py file and replace with this code.

from urllib2 import *
import urllib
import json
import sys

MY_API_KEY="AIzaSyCJu8pl_GmHLhM9SfFc-31vipg9rsfeD5I"

messageTitle = sys.argv[1]
messageBody = sys.argv[2]

data={
    "to" : "/topics/my_little_topic",
    "notification" : {
        "body" : messageBody,
        "title" : messageTitle,
        "icon" : "ic_cloud_black_48dp"
    }
}

dataAsJSON = json.dumps(data)

request = Request(
    "https://gcm-http.googleapis.com/gcm/send",
    dataAsJSON,
    { "Authorization" : "key="+MY_API_KEY,
      "Content-type" : "application/json"
    }
)

print urlopen(request).read()

Open terminal and run the send.py script.

python send.py “My first push notification” “GCM API is wonderful”

Running the Script

Running the Script

Android RTP (Video & Audio Stream via VLC Player)

In this tutorial, you’ll learn how to use Android Studio to start Android RTP project development. You will learn the following:

  • How to use Android Studio to create a native project.
  • How to use RTP in android project.

Download the required software packages

Open Android Studio.

Start a new Android Studio project

Start a new Android Studio project

Select Start a new Android Studio project. Enter your custom Application name, Company Domain and select Project location. Click Next.

Configure your new project.

Configure your new project.

Select Phone and Tablet. Make sure API 15 selected. Click Next.

Configure your new project.

Configure your new project.

Select Empty Activity and click Next.

Add an activity to Mobile.

Add an activity to Mobile.

Click Finish.

Customize the activity.

Customize the activity.

Import the libstreaming library (https://github.com/fyhertz/libstreaming) to Android Studio you can try this:

  • Open your project in Android Studio.
  • Download the library (using Git, or a zip archive to unzip).

Select File > New > Import Module.

New Module.

New Module.

Select library libstreaming source directory and click Next.

New Module.

New Module.

Click Finish.

New Module.

New Module.

On the root of your project directory create/modify the settings.gradle file. It should contain something like the following:

include 'app', ':libstreaming'
  • Gradle clean & build/close the project and reopen/re-import it.
  • Edit your project’s build.gradle to add this in the “depencies” section:
dependencies {
     //...
        compile project(':libstreaming')
     }

Open the MainActivity.java and replace with this code

package my.intellij.androidrtp;

import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.Window;
import android.view.WindowManager;

import net.majorkernelpanic.streaming.Session;
import net.majorkernelpanic.streaming.SessionBuilder;
import net.majorkernelpanic.streaming.audio.AudioQuality;
import net.majorkernelpanic.streaming.gl.SurfaceView;
import net.majorkernelpanic.streaming.rtsp.RtspServer;

/**
 * A straightforward example of how to use the RTSP server included in libstreaming.
 */
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback, RtspServer.CallbackListener, Session.Callback{

    private final static String TAG = "MainActivity";

    private SurfaceView mSurfaceView;
    private  Session mSession;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        setContentView(R.layout.activity_main);

        mSurfaceView = (SurfaceView) findViewById(R.id.surface);

        
        // Sets the port of the RTSP server to 1234
        SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
        editor.putString(  RtspServer.KEY_PORT, String.valueOf(1234));
        editor.commit();



        // Configures the SessionBuilder
        mSession =  SessionBuilder.getInstance()
                .setCallback(this)
                .setSurfaceView((net.majorkernelpanic.streaming.gl.SurfaceView) mSurfaceView)
                .setPreviewOrientation(90)
                .setContext(getApplicationContext())
                .setAudioEncoder(SessionBuilder.AUDIO_AAC)
                .setAudioQuality(new AudioQuality(8000, 16000))
                .setVideoEncoder(SessionBuilder.VIDEO_H264)
                //.setVideoQuality(new VideoQuality(320,240,20,500000))
                .build();

        mSurfaceView.getHolder().addCallback(this);

        ((net.majorkernelpanic.streaming.gl.SurfaceView) mSurfaceView).setAspectRatioMode(net.majorkernelpanic.streaming.gl.SurfaceView.ASPECT_RATIO_PREVIEW);
        String ip, port, path;

        // Starts the RTSP server
        this.startService(new Intent(this,RtspServer.class));

        Log.d("test", "1");



        mSession.startPreview(); //camera preview on phone surface
        mSession.start();

    }

    @Override
    public void onResume()
    {
        super.onResume();
        mSession.stopPreview();
    }

    @Override
    public void onDestroy()
    {
        super.onDestroy();
        mSession.release();
        mSurfaceView.getHolder().removeCallback(this);
    }

    //region   ----------------------------------implement methods required
    @Override
    public void onError(RtspServer server, Exception e, int error) {
        Log.e("Server", e.toString());
    }

    @Override
    public void onMessage(RtspServer server, int message) {
        Log.e("Server", "unkown message");
    }

    @Override
    public void onBitrateUpdate(long bitrate) {

    }

    @Override
    public void onSessionError(int reason, int streamType, Exception e) {

    }

    @Override
    public void onPreviewStarted() {

    }

    @Override
    public void onSessionConfigured() {

    }

    @Override
    public void onSessionStarted() {

    }

    @Override
    public void onSessionStopped() {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    //endregion
}

Open activity_main.xml in app > res > layout and replace with this code.

<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="my.intellij.androidrtp.MainActivity" android:color="@android:color/background_light">

    <net.majorkernelpanic.streaming.gl.SurfaceView android:id="@+id/surface" android:layout_width="match_parent" android:layout_height="match_parent" />

</RelativeLayout>

Open AndroidManifest.xml and replace with this code.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="my.intellij.androidrtp">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name="net.majorkernelpanic.streaming.rtsp.RtspServer" />
    </application>

    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

</manifest>

Build and run the Android rtp sender app. Now start the vlc player and click Media > Open Network Stream menu. Enter the following url (please update with your android ip) and click play button.

rtsp://192.168.0.113:1234

Open Network.

Open Network.

How to create a c++ library with NDK on Android Studio

In this tutorial, you’ll learn how to use Android Studio to start Android NDK project development. You will learn the following:

  • How to use Android Studio to create a native project.
  • How to build and trace native code.

Download the required software packages

Open Android Studio.

Start a new Android Studio project

Start a new Android Studio project

Select Start a new Android Studio project. Enter your custom Application name, Company Domain and select Project location. Click Next.

New Project

New Project

Select Phone and Tablet. Make sure API 15 selected. Click Next.

Configure your new project.

Configure your new project.

Click Next.

Configure your new project

Configure your new project

Select Black Activity and click Next.

Configure your new project

Configure your new project

Click Finish.

Customize the Activity.

Customize the Activity.

Select the menu File > Project Structure > SDK Location and set Android NDK Location.

Project Structure

Project Structure

Add new code inside defaultConfig block.

defaultConfig {
        applicationId "my.intellij.androidrtp"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        ndk {
            moduleName "hello-android-jni"
        }
}

Add JNI function and load jni shared lib into project. Select Android Studio Project pane > app > java > my.intellij.androidrtp > MainActivity, and add JNI function getMsgFromJni() and System.loadLibrary() to the end of class MainActivity.

static {
        System.loadLibrary("hello-android-jni");
    }
    public native String getMsgFromJni();

Configure javah. Select Android Studio > Preferences > Tools > External Tools. Click + symbol.

Create Tool for javah.

Create Tool for javah.

Configure ndk-build.

Create Tool for ndk-build.

Create Tool for ndk-build.

Configure ndk-build clean.

Create Tool for ndk-build clean.

Create Tool for ndk-build clean.

Click Ok.

Preferences.

Preferences.

Configure build.gradle to setup JNI folder location. Open build.gradle file and place this code into android block.

android {
    compileSdkVersion 24
    buildToolsVersion "25.0.0"
    defaultConfig {
        applicationId "my.intellij.androidrtp"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        ndk {
            moduleName "hello-android-jni"
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    sourceSets.main {
        jni.srcDirs = [] 
        jniLibs.srcDirs=['libs']
    }

}

Let’s add one line in ‘gradle.properties’.

android.useDeprecatedNdk=true

Build the project. Select MainActivity, NDK > javah.

NDK javah

NDK javah

Switch to project mode and select NewC/C++ Source File.

C/C++ Source File

C/C++ Source File

Name it as hello-android-jni and click Ok.

Create New C/C++ Source File

Create New C/C++ Source File

Replace with this code in hello-android-jni.cpp.

#include "my_intellij_androidrtp_MainActivity.h"

JNIEXPORT jstring JNICALL Java_my_intellij_androidrtp_MainActivity_getMsgFromJni(JNIEnv *, jobject){

    return (*env)->NewStringUTF(env, "Hello From Jni");
}

Create some MakeFiles. Select jni folder > New > File.

Create some MakeFiles

Create some MakeFiles

Name it as Android.mk. Click Ok.

Create some MakeFiles

Create some MakeFiles

Click Ok.

Register New File Type Association

Register New File Type Association

Repeat same process to create Application.mk file. Replace both files with these codes.

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE		:= hello-android-jni
LOCAL_SRC_FILES		:= hello-android-jni.cpp
include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_MODULES := hello-android-jni

APP_ABI := all

Build NDK Library. Select jni folder > NDK > ndk-build.

Build NDK Library

Build NDK Library

Success message.

Build NDK Library

Build NDK Library

Replace MainActivity.java with this code.

package my.intellij.androidrtp;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

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

        Log.i("MyTag", getMsgFromJni());
    }

    static {
        System.loadLibrary("hello-android-jni");
    }
    public native String getMsgFromJni();
}

Copy all folders that contain .so files in jni folder into jniLibs folder. Build and run.

Output

Output

Output

Simple app using cordova and ratchet 2.

Download the required software packages

Download and install Eclipse Neon and Xcode 7 (if you using Mac for mobile development).

Eclipse Neon – http://www.eclipse.org/neon/
JDK 1.8 – http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
Xcode 7 – https://developer.apple.com/xcode/downloads/
Sublime Text – https://www.sublimetext.com/3

Setup ADT and Android SDK into your eclipse. Then you need to setup cordova using NPM (node package manager) from that link.  Download Node.js (https://nodejs.org/en/) and install cordova after that. Open terminal/command line and type this command to install cordova into your machine.

npm install -g cordova

Download Jquery and Ratchet from their official website. You should unzip it to proper location. For this tutorial, we using Jquery 3.1.1 and Ratchet 2.0.2.

Setting up your development environment

Create a cordova project using command below in your terminal/cmd:

cordova create com.intellij.cordova.todolist.v2

Open config.xml inside com.intellij.cordova.todolist.v2 folder and replace with this code.

config.xml

config.xml

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.intellij.cordova.todolist.v2" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>ToDoList</name>
    <description>
        A sample Apache Cordova application that responds to the deviceready event.
    </description>
    <author email="dev@cordova.apache.org" href="http://cordova.io">
        Apache Cordova Team
    </author>
    <content src="index.html" />
    <plugin name="cordova-plugin-whitelist" spec="1" />
    <access origin="*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <platform name="android">
        <allow-intent href="market:*" />
    </platform>
    <platform name="ios">
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
    </platform>
</widget>

Add platform for iOS and android.

cordova platform add ios
cordova platform add android
cordova platform add android

cordova platform add android

 

cordova platform add ios

cordova platform add ios

Preview your app (android)

Import android project into your eclipse.

import cordova project

import cordova project

Select AndroidExisting Android Code Into Workspace.

import existing android code into workspace

import existing android code into workspace

Browse your project and click Finish.

import android project

import android project

Run android app in your mobile device.

Preview your app (ios)

Go to your project directory and browse for xcode project, platforms > ios > CordovaRatchet.xcodeproj then run xcode project. Click Play on top left side to preview the app on your simulator.

xcode project

xcode project

Learning client side API and building a multi page application

Open cordova project in Sublime Text editor. Right click js folder on your project. Select New File.

New Javascript File

Add New Javascript File

Create 4 javascript files.

  • main.js – initialize function.
  • AddPage.js – to add user details.
  • ListPage.js – to retrieve user list.
  • DetailPage.js – to retrieve user details.

Right click www folder and select New Folder to create a new folder. Name it pages and save it.

Add New Folder

Add New Folder

Then create a few of html pages inside page folder that we already created just now. Right click pages folder and select New File.

Add New HTML File

Add New HTML File

Create 3 html files and click Finish. Repeat.

  • AddPage.html – to add user details.
  • ListPage.html – to retrieve user list.
  • DetailPage.html – to retrieve user details.

Copy Jquery javascript files that you already extract from proper location into js folder. Go to extracted Ratchet directory and select/copy all folders inside ratchet-2.0.2 > dist. Then paste it inside www folder.

latest cordova project directory

latest cordova project directory

Open your index.html and replace with this code.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
 
    <!-- Sets initial viewport load and disables zooming -->
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
 
    <!-- Makes your prototype chrome-less once bookmarked to your phone's home screen -->
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
 
    <!-- Include the compiled Ratchet CSS -->
    <link href="css/ratchet.css" rel="stylesheet">
    <script src="cordova.js" type="text/javascript"></script>
    <script src="js/jquery-3.1.1.min.js"></script>
    <script src="js/ratchet.js"></script>
    <script src="js/main.js"></script>
  </head>
  <body onload="init()">
 
  </body>
</html>

Replace all codes with given codes for each javascript files.

AddPage.js

currentPage={};

currentPage.init = function() {
    console.log("AddPage :: init");
};

currentPage.back = function(){
    console.log("AddPage :: back");
    $("body").load(path + "pages/ListPage.html", function(){
        $.getScript(path + "js/ListPage.js", function() {
            if (currentPage.init) {
                currentPage.init();
            }
        });
    });
};

DetailPage.js

currentPage={};

currentPage.init = function() {
    console.log("DetailPage :: init");
};

currentPage.back = function(){
    console.log("DetailPage :: back");
    $("body").load(path + "pages/ListPage.html", function(){
        $.getScript(path + "js/ListPage.js", function() {
            if (currentPage.init) {
                currentPage.init();
            }
        });
    });
};

ListPage.js

currentPage = {};

currentPage.init = function(){
    console.log("ListPage :: init");
};

currentPage.loadPage = function(pageIndex){
    console.log("ListPage :: loadPage :: pageIndex: " + pageIndex);
    $("body").load(path + "pages/" + pageIndex + ".html");
    $.getScript(path + "js/" + pageIndex +".js", function() {
        if (currentPage.init) {
            currentPage.init();
        }
    });
};

main.js

var pagesHistory = [];
var currentPage = {};
var path = "";

function init(){

    $("body").load(path + "pages/ListPage.html", function(){
        $.getScript(path + "js/ListPage.js", function() {
            if (currentPage.init) {
                currentPage.init();
            }
        });
    });

}

Replace all codes with given codes for each html files.

AddPage.html

<script>
    $.getScript(path + "js/AddPage.js");
</script>

<header class="bar bar-nav">
	<a class="icon icon-left-nav pull-left" onclick="currentPage.back();"></a>
  	<h1 class="title">AddPage</h1>
</header>

DetailPage.html

<script>
    $.getScript(path + "js/DetailPage.js");
</script>

<header class="bar bar-nav">
	<a class="icon icon-left-nav pull-left" onclick="currentPage.back();"></a>
  	<h1 class="title">DetailPage</h1>
</header>

ListPage.html

<script>
    $.getScript(path + "js/ListPage.js");
</script>

<header class="bar bar-nav">
	<button id="LoadAddButton" class="btn pull-right" onclick="currentPage.loadPage('AddPage');">Load Add.html</button>
  	<h1 class="title">ListPage</h1>
</header>

<div class="content">
<div class="content-padded">
    <button id="LoadDetailButton" class="btn btn-positive btn-block" onclick="currentPage.loadPage('DetailPage');">Load Detail.html</button>
</div>
</div>

Preview your app using previous steps.

Now we want to integrate API with app. You need to replace all html files and js files so we can invoke API from there.

AddPage.js

currentPage = {};
currentPage.init = function() {
    console.log("AddPage :: init");
};
currentPage.back = function() {
    console.log("AddPage :: back");
    $("body").load(path + "pages/ListPage.html", function() {
        $.getScript(path + "js/ListPage.js", function() {
            if (currentPage.init) {
                currentPage.init();
            }
        });
    });
};
currentPage.add = function() {
    console.log("AddPage :: add");
    var name = $("#name").val();
    var description = $("#description").val();
    formData = {
        name: $("#name").val(),
        description: $("#description").val()
    }
    if (name == "") {
        alert("Please enter name");
    } else if (description == "") {
        alert("Please enter description");
    } else {
        $.ajax({
            type: "post",
            url: "http://demo.revivalx.com/todolist-api/create_task.php",
            data: formData,
            dataType: "json",
            success: function(data) {
                alert("Add task success");
                $("body").load(path + "pages/ListPage.html", function() {
                    $.getScript(path + "js/ListPage.js", function() {
                        if (currentPage.init) {
                            currentPage.init();
                        }
                    });
                });
            },
            error: function() {
                alert("Add task failure");
            }
        });
    }
};

DetailPage.js

currentPage = {};
currentPage.init = function() {
    console.log("DetailPage :: init");
    detailTask();
};
currentPage.back = function() {
    console.log("DetailPage :: back");
    $("body").load(path + "pages/ListPage.html", function() {
        $.getScript(path + "js/ListPage.js", function() {
            if (currentPage.init) {
                currentPage.init();
            }
        });
    });
};
currentPage.edit = function() {
    console.log("DetailPage :: edit");
    var taskId = sessionStorage.taskId;
    var name = $("#name").val();
    var description = $("#description").val();
    formData = {
        taskId: sessionStorage.taskId,
        name: $("#name").val(),
        description: $("#description").val()
    }
    if (name == "") {
        alert("Please enter name");
    } else if (description == "") {
        alert("Please enter description");
    } else {
        $.ajax({
            type: "post",
            url: "http://demo.revivalx.com/todolist-api/update_task.php",
            data: formData,
            dataType: "json",
            success: function(data) {
                alert("Edit task success");
                $("body").load(path + "pages/ListPage.html", function() {
                    $.getScript(path + "js/ListPage.js", function() {
                        if (currentPage.init) {
                            currentPage.init();
                        }
                    });
                });
            },
            error: function() {
                alert("Edit task failure");
            }
        });
    }
};

function detailTask() {
    formData = {
        taskId: sessionStorage.taskId
    }
    $.ajax({
        type: "get",
        url: "http://demo.revivalx.com/todolist-api/get_task_details.php",
        data: formData,
        dataType: "json",
        success: function(data) {
            $('#name').val(data.task[0].name);
            $('#description').val(data.task[0].description);
        },
        error: function() {
            alert("Detail task failure");
        }
    });
}
currentPage.remove = function() {
    console.log("DetailPage :: delete");
    deleteTask();
};

function deleteTask() {
    formData = {
        taskId: sessionStorage.taskId
    }
    $.ajax({
        type: "post",
        url: "http://demo.revivalx.com/todolist-api/delete_task.php",
        data: formData,
        dataType: "json",
        success: function(data) {
            alert("Delete task success");
            $("body").load(path + "pages/ListPage.html", function() {
                $.getScript(path + "js/ListPage.js", function() {
                    if (currentPage.init) {
                        currentPage.init();
                    }
                });
            });
        },
        error: function() {
            alert("Delete task failure");
        }
    });
}

ListPage.js

currentPage = {};
currentPage.init = function() {
    console.log("ListPage :: init");
    listTasks();
};
currentPage.loadPage = function(pageIndex) {
    console.log("ListPage :: loadPage :: pageIndex: " + pageIndex);
    $("body").load(path + "pages/" + pageIndex + ".html");
    $.getScript(path + "js/" + pageIndex + ".js", function() {
        if (currentPage.init) {
            currentPage.init();
        }
    });
};
currentPage.detailPage = function(taskId) {
    sessionStorage.setItem("taskId", taskId);
    $("body").load(path + "pages/DetailPage.html");
    $.getScript(path + "js/DetailPage.js", function() {
        if (currentPage.init) {
            currentPage.init();
        }
    });
};

function listTasks() {
    $.ajax({
        type: "get",
        url: "http://demo.revivalx.com/todolist-api/get_all_tasks.php",
        dataType: "json",
        success: function(data) {
            var ul = $('#taskList');
            var html = '';
            $.each(data.tasks, function(index, item) {
                html += '<li class="table-view-cell">';
                html += '<a class="navigate-right" onclick="currentPage.detailPage(' + item.taskId + ');" >';
                html += item.name;
                html += '</a></li>';
            });
            ul.append(html);
        },
        error: function() {
            alert("List task failure");
        }
    });
}

AddPage.html

<script>
    $.getScript(path + "js/AddPage.js");
</script>
  
<header class="bar bar-nav">
    <a class="icon icon-left-nav pull-left" onclick="currentPage.back();"></a>
    <h1 class="title">AddPage</h1>
</header>
<div class="content">
	<div class="card">
    <ul class="table-view">
        <li class="table-view-cell table-view-divider">Name:</li>
 
        <li class="table-view-cell"><input id="name" name="name" type="text"></li>
 
        <li class="table-view-cell table-view-divider">Description:</li>
 
        <li class="table-view-cell"><input id="description" name="description" type="text"></li>
 
        <li class="table-view-cell"></li>
    </ul>
   </div>
    <div class="card" style="margin-bottom:40px;">
    	<button class="btn btn-positive btn-block" onclick="currentPage.add();">ADD TASK</button>
    </div>
</div>

DetailPage.html

<script>
    $.getScript(path + "js/DetailPage.js");
</script>
 
<header class="bar bar-nav">
    <a class="icon icon-left-nav pull-left" onclick="currentPage.back();"></a>
    <h1 class="title">DetailPage</h1>
</header>
 
<div class="content">
	<div class="card">
    <ul class="table-view">
        <li class="table-view-cell table-view-divider">Name:</li>
 
        <li class="table-view-cell"><input id="name" name="name" type="text"></li>
 
        <li class="table-view-cell table-view-divider">Description:</li>
 
        <li class="table-view-cell"><input id="description" name="description" type="text"></li>
 
    </ul>
   </div>
   <div class="card" style="margin-bottom:40px;">
    	<button class="btn btn-positive btn-block" onclick="currentPage.edit();">EDIT TASK</button>
   </div>
   <div class="card" style="margin-bottom:40px;">
    	<button class="btn btn-negative btn-block" onclick="currentPage.remove();">REMOVE TASK</button>
   </div> 
</div>

ListPage.html

<script>
    $.getScript(path + "js/ListPage.js");
</script>

<header class="bar bar-nav">
	<button id="LoadAddButton" class="btn pull-right" onclick="currentPage.loadPage('AddPage');">Add</button>
  	<h1 class="title">ListPage</h1>
</header>

<div class="content">
	<ul id="userList" class="table-view"></ul>
</div>

Build and run your app. You can find the source code here: https://github.com/IntellijSys/com.intellij.cordova.todolist.v2

Building a Hybrid Mobile app using Ionic Framework

Getting started with Ionic Framework. This tutorial show you how to do simple CRUD operation using Ionic Framework. What you need for this tutorial are

Outline that cover for this tutorial:

  • Set up your development environment
  • Preview your app
  • Learn client side API
  • Build a multi page application
  • Integration with server side API

Setting up your development environment

After that, install node.js to use npm for package manager. If you not install node.js, you should not be able to invoke node or npm on your command line to install Ionic Framework. Then install Ionic Framework using terminal or command prompt.

npm install -g cordova ionic

After you finish install the Ionic Framework. You can start create your project using Ionic command. Open your terminal/command prompt, type these command.

ionic start IonicToDoList tabs
ionic start IonicToDoList tabs

ionic start IonicToDoList tabs

Open Ionic project with Sublime.

Ionic project with Sublime Text

Ionic project with Sublime Text

Open config.xml and replace with this id.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<widget id="com.ionicframework.ionictodolist" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
  <name>IonicToDoList</name>
  <description>
        An Ionic Framework and Cordova project.
    </description>
  <author email="you@example.com" href="http://example.com.com/">
      Your Name Here
    </author>
  <content src="index.html"/>
  <access origin="*"/>
  <preference name="webviewbounce" value="false"/>
  <preference name="UIWebViewBounce" value="false"/>
  <preference name="DisallowOverscroll" value="true"/>
  <preference name="SplashScreenDelay" value="2000"/>
  <preference name="FadeSplashScreenDuration" value="2000"/>
  <preference name="android-minSdkVersion" value="16"/>
  <preference name="BackupWebStorage" value="none"/>
  <preference name="SplashScreen" value="screen"/>
  <feature name="StatusBar">
    <param name="ios-package" value="CDVStatusBar" onload="true"/>
  </feature>
</widget>

Build android and iOS app using this command.

cd IonicToDoList
ionic platform add android
ionic platform add ios
sudo ionic platform add android

sudo ionic platform add android

Preview your app (android)

Open your eclipse. Select File > Import.

import android project

import android project

Select Existing Android Code Into Workspace. Click Next.

import android project

import android project

Click Browse to select android project and click Finish.

import android project

import android project

Run android app in android simulator.

Preview your app (iOS)

Open your Xcode. Right click on iphone folder and go to Run AsXcode Project.

Xcode

Xcode

Open app.js file in www/js folder. Replace with this code.

angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])

.run(function($ionicPlatform) {
  $ionicPlatform.ready(function() {
    if (window.cordova &amp;&amp; window.cordova.plugins &amp;&amp; window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      cordova.plugins.Keyboard.disableScroll(true);

    }
    if (window.StatusBar) {
      StatusBar.styleDefault();
    }
  });
})

.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
  $stateProvider

    .state('tab', {
    url: '/tab',
    abstract: true,
    templateUrl: 'templates/tabs.html'
  })

  .state('tab.list', {
      url: '/list',
      views: {
        'tab-list': {
          templateUrl: 'templates/list.html',
          controller: 'ListCtrl'
        }
      }
    })
    .state('tab.detail', {
      url: '/detail/:taskId',
      views: {
        'tab-detail': {
          templateUrl: 'templates/detail.html',
          controller: 'DetailCtrl'
        }
      }
    })

  .state('tab.add', {
    url: '/add',
    views: {
      'tab-add': {
        templateUrl: 'templates/add.html',
        controller: 'AddCtrl'
      }
    }
  });

  $urlRouterProvider.otherwise('/tab/list');

})

.directive("initFromForm", function ($parse) {
    return {
        link: function (scope, element, attrs) {
            var attr = attrs.initFromForm || attrs.ngModel || element.attrs('name'),
            val = attrs.value;
            $parse(attr).assign(scope, val);
        }
    };
});

Open services.js file in www/js folder. Replace with this code.

angular.module('starter.services', [])

.factory('todoService', function($http) {
    var baseUrl = 'http://demo.revivalx.com/todolist-api/';
    return {
        getAll: function() {
            return $http.get(baseUrl+'get_all_tasks.php');
        },
        getId: function (taskId){
            return $http.get(baseUrl+'get_task_details.php?taskId='+taskId); 
        },
        create: function (data){
            return $http.post(baseUrl+'create_task.php',data,{
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;'
                }
            });
        },
        update: function (data){
            return $http.post(baseUrl+'update_task.php',data,{
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;'
                }
            });
        },
        delete: function  (taskId){
            return $http.get(baseUrl+'delete_task.php?id='+taskId);
        }
    };
    
});

Open controllers.js file in www/js folder. Replace with this code.

angular.module('starter.controllers', [])

.controller('tabCtrl', function($scope){
})

.controller('ListCtrl', function($scope,$state, todoService){
    $scope.showData = function() {
      todoService.getAll().success(function(data) {
            $scope.datatodos = data;
        }).finally(function() {
            $scope.$broadcast('scroll.refreshComplete');
        });
    };
    $scope.showData();
    
    $scope.reload = function (){
        $state.go('tab.list');
    };
    
    $scope.delete = function (datatodo){
        todoService.delete(datatodo.taskId);
        $scope.datatodos.splice($scope.datatodos.indexOf(datatodo),1);
    };
})

.controller('AddCtrl', function($scope,$ionicPopup,todoService){
    $scope.showAlert = function(msg) {
      $ionicPopup.alert({
          title: msg.title,
          template: msg.message,
          okText: 'Ok',
          okType: 'button-positive'
      });
    };
    
    $scope.datatodo={};
    $scope.save = function (){
        if (!$scope.datatodo.name){
            $scope.showAlert({
                title: "Information",
                message: "Name is required"
            });
        }else if (!$scope.datatodo.description){
            $scope.showAlert({
                title: "Information",
                message: "Description is required"
            });
        }else{
            todoService.create({
                name: $scope.datatodo.name,
                description: $scope.datatodo.description,
            }).success(function(data){
                $scope.showAlert({
                    title: "Information",
                    message: "Successfully recorded"
                });
            });
        }
        
    };
       
})

.controller('DetailCtrl', function($scope,$stateParams,$ionicPopup,$ionicModal,$state,todoService){
        
    $scope.showDataId = function() {
      todoService.getId($stateParams.taskId).success(function(datatodo) {
            $scope.datatodo = datatodo;
        });
        
    };
    $scope.showDataId();
    
    $scope.back = function (){
        $state.go('tab.list');
    };
    
    $ionicModal.fromTemplateUrl('edit.html', function(modal){
        $scope.taskModal = modal;
  }, {
            scope : $scope,
            animation : 'slide-in-up' 
  });
        
        $scope.showAlert = function(msg) {
            $ionicPopup.alert({
                title: msg.title,
                template: msg.message,
                okText: 'Ok',
                okType: 'button-positive'
            });
          };
  
  $scope.editModal = function(){
            $scope.taskModal.show();
  };
  
  $scope.cancel = function(){
            $scope.taskModal.hide();
            $scope.showDataId();
  };
        
  $scope.edit = function(taskId,name,description){
            if (!taskId){
                $scope.showAlert({
                    title: "Information",
                    message: "Id is required"
                });
            }else if (!name){
                $scope.showAlert({
                    title: "Information",
                    message: "Name is required"
                });
            }else if(!description){
                $scope.showAlert({
                    title: "Information",
                    message: "Description is required"
                });
            }else{
                $scope.id = id;
                $scope.name = name;
                $scope.description = description;
                todoService.update({
                    'id' : id,
                    'name': name,
                    'description': description,
                }).then(function(resp) {
                  console.log('Success', resp);
                  $scope.showAlert({
                        title: "Information",
                        message: "Successfully updated"
                    });
                },function(err) {
                  console.error('Error', err);
                }); 
            }
  };
  
});

Delete all the html files in www/templates and create these all 4 files.

  1. add.html.
  2. detail.html.
  3. list.html.
  4. tabs.html.

Replace all codes with given codes for each html files.

tabs.html

<ion-tabs class="tabs-icon-top tabs-color-active-positive">

  <ion-tab title="Status" icon-off="ios-list" icon-on="ion-ios-pulse-strong" href="#/tab/list">
    <ion-nav-view name="tab-list"></ion-nav-view>
  </ion-tab>

  <ion-tab title="Status" icon-off="ios-add" icon-on="ion-ios-pulse-strong" href="#/tab/add">
    <ion-nav-view name="tab-add"></ion-nav-view>
  </ion-tab>

</ion-tabs>

list.html

<ion-header-bar class="bar-positive">
        <button class="button button-icon icon ion-ios7-minus-outline" ng-click="data.showDelete = 
        !data.showDelete; data.showReorder=false"></button>
        <h1 class="title">ToDo List</h1>
        <button class="button button-icon icon ion-ios7-loop" ng-click="reload()"></button>
</ion-header-bar>
<ion-view>
    <ion-content padding="false" class="has-header">
        <ion-refresher
            pulling-text="Pull to refresh..."
            on-refresh="showData()">
          </ion-refresher>
        <ion-list show-Delete = "data.showDelete" show-Reorder = "data.showReorder">
            <ion-item class="item-avatar item-icon-right" ng-repeat="datatodo in datatodos" type="item-text-wrap" href="#/tab/detail/{{datatodo.taskId}}">
                <i class="icon ion-ios7-arrow-right"></i>
                <h2>{{datatodo.name}}
                    <br> 
                    <font size="2" color="gray" >Description : {{datatodo.description}}</font>
                </h2>
                <ion-delete-button class="ion-minus-circled" ng-click="delete(datatodo);"></ion-delete-button>
            </ion-item>
        </ion-list>
    </ion-content>
</ion-view>

add.html

<ion-header-bar class="bar-positive">
        <h1 class="title">Add Task</h1>
</ion-header-bar>
<ion-content class="padding">
      <form>
        <ion-list>
            <label class="item item-input">
                <input type="text" ng-model="datatodo.name" placeholder="Name">
            </label>
            <label class="item item-input">
                <input type="text" ng-model="datatodo.description" placeholder="Description">
            </label>
        </ion-list>
        <div class="spacer" style="height: 5px;"></div>
        <button class="button icon ion-person-stalker button-balanced button-block" ng-click="save();"> Save</button>
    </form>
</ion-content>

detail.html

<ion-header-bar class="bar-positive">
        <button class="button button-icon icon ion-ios7-arrow-left" ng-click="back();">Back</button>
        <h1 class="title">Task Detail</h1>
</ion-header-bar>
<ion-content class="padding" ng-repeat="datatodo in datatodo">
    <h3>Detail :</h3>
    <p>
        <font size="2" color="gray" >Nama : {{datatodo.name}}</font>
    <br>
        <font size="2" color="gray" >Description : {{datatodo.description}}</font>
    </p>
    <button class="button button-balanced button-block" ng-click="editModal()">Edit Task</button>
</ion-content>
<script id="edit.html" type="text/ng-template">
        <div class="modal">
            <ion-header-bar class="bar-stable">
                <button class="button button-icon icon ion-ios7-close-outline" ng-click="cancel()"></button>
                <h1 class="title"> Edit Task</h1>
            </ion-header-bar>
            <ion-content ng-repeat="datatodo in datatodo">
                <form>
                    <div class="list">
                        <label class="item item-input">
                        <span class="input-label">ID :</span>
                            <input type="text" placeholder="{{datatodo.taskId}}" ng-model="id" value="{{datatodo.id}}" init-from-form>
                            <p>{{datatodo.taskId}}</p>
                        </label>
                        <label class="item item-input">
                        <span class="input-label">Name :</span>
                            <input type="text" placeholder="{{datatodo.name}}" ng-model="name" value="{{datatodo.name}}" init-from-form>
                        </label>
                        <label class="item item-input">
                        <span class="input-label">Description :</span>
                            <input type="text" placeholder="{{datatodo.description}}" ng-model="description" value="{{datatodo.description}}" init-from-form>
                        </label>
                        <button class="button button-positive button-block" ng-click="edit(taskId,name,description);">
                            Save
                        </button>
                    </div>
                </form>
        </ion-content>
        </div>
</script>

Build your project using this command and run the app.

ionic build ios
ionic build android

Guideline upload APK file into Google Play from A – Z

Open up your Android Studio. Go to menu, choose Generate Signed APK and click Next.

Generate Signed APK

Generate Signed APK

 

Generate Signed APK

Generate Signed APK

Click Create new.

Generate Signed APK

Generate Signed APK

Enter all the details (all fields are mandatory) below and click Ok.

New Key Store.

New Key Store.

Enter the following details and click Next.

Generate Signed APK

Generate Signed APK

Enter Master Password and click Ok.

Enter Master Password

Enter Master Password

Click Finish.

Generate Signed APK

Generate Signed APK

Open your browser and enter this URL, https://play.google.com/apps/publish/ . (I assume you already have google play developer account). Click Add new application.

google play developer - all applications

google play developer – all applications

Enter Title and click Upload APK.

google play developer - APK

google play developer – APK

Click Upload new APK to Production.

google play developer - APK

google play developer – APK

Click Browse. Select ***.apk file and click Open.

google play developer - APK

google play developer – APK

Wait until it finish uploading.

google developer account - APK

google developer account – APK

Go to Store Listing and enter all details for store listing.

Mandatory

Title: <your_title>
Description: <your_description>

Scroll down.

google developer account - store listing

google developer account – store listing

Insert screenshots at least 2 screenshots. Maximum is 8 screenshots. JPEG or 24-bit PNG (no alpha). Min length for any side: 320px. Max length for any side: 3840px.

google developer account - store listing

google developer account – store listing

Insert your Hi-res icon and Feature Graphic. Your icon size must be 512px x 512px and Feature Graphic must be 1024px x 500px.

google developer account - store listing

google developer account – store listing

Select Application type, Category and Content rating in Categorization section. Then enter all details for Website, Email, Phone and Privacy Policy. Save draft.

google developer account - store listing

google developer account – store listing

Go to Content Rating. Click Continue.

google developer account - content rating

google developer account – content rating

Enter Email address and Confirm email address. Then select your app category. Select UTILITY, PRODUCTIVITY, COMMUNICATION, OR OTHER.

google developer account - content rating

google developer account – content rating

Answer all questionnaire and click Saved questionnaires. Then click Calculate rating.

google developer account - content rating

google developer account – content rating

Click Apply rating.

google developer account - content rating

google developer account – content rating

 

google developer account - content rating

google developer account – content rating

Go to Pricing & Distribution. Choose Free. Then Malaysia in country section. In CONTAINS ADS section, choose No, it has no ads. In CONSENT section, select Content guidelines and US export laws. Scroll up and click Save draft. Then click Publish app.

google developer account - pricing & distribution

google developer account – pricing & distribution

 

Building a To Do List Android Mobile App – Part 2

In the first part of the simple android mobile app (toDoList) tutorial series, you covered the basics of setting environment and user interface.

In this second and final part of the tutorial series, we’ll cover API integration for each activity classes.

We’ll start where we left off last tutorial, so open your project from last time, or go through the previous tutorial first. http://intellij.my/2016/08/11/building-a-to-do-list-android-mobile-app-part-1/

Create a new java class. Right click on my.intellij.androidtodolist package > New >Activity > Java Class.

Create a new java class.

Create a new java class.

Name it as App and click Ok.

Create New Class

Create New Class

Then replace with this code in App.java.

package my.intellij.androidtodolist;

public class App {

    public static final String URL_CREATE="http://demo.revivalx.com/todolist-api/create_task.php";
    public static final String URL_GET_ALL = "http://demo.revivalx.com/todolist-api/get_all_tasks.php";
    public static final String URL_GET_DETAIL = "http://demo.revivalx.com/todolist-api/get_task_details.php?taskId=";
    public static final String URL_UPDATE = "http://demo.revivalx.com/todolist-api/update_task.php?taskId=";
    public static final String URL_DELETE = "http://demo.revivalx.com/todolist-api/delete_task.php?taskId=";

    public static final String KEY_ID = "taskId";
    public static final String KEY_NAME = "name";
    public static final String KEY_DESCRIPTION = "description";

    public static final String TAG_JSON_ARRAY="tasks";
    public static final String TAG_JSON_DETAIL="task";
    public static final String TAG_ID = "taskId";
    public static final String TAG_NAME = "name";
    public static final String TAG_DESCRIPTION = "description";

    public static final String ID = "taskId";
}

Create another java class. Right click on my.intellij.androidtodolist package > New >Activity > Java Class name it as RequestHandler. After that replace with this code.

package my.intellij.androidtodolist;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

public class RequestHandler {

    //Method to send httpPostRequest
    //This method is taking two arguments
    //First argument is the URL of the script to which we will send the request
    //Other is an HashMap with name value pairs containing the data to be send with the request
    public String sendPostRequest(String requestURL,
                                  HashMap<String, String> postDataParams) {
        URL url;

        //StringBuilder object to store the message retrieved from the server
        StringBuilder sb = new StringBuilder();
        try {
            //Initializing Url
            url = new URL(requestURL);

            //Creating an httmlurl connection
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            //Configuring connection properties
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);

            //Creating an output stream
            OutputStream os = conn.getOutputStream();

            //Writing parameters to the request
            //We are using a method getPostDataString which is defined below
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK) {

                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                sb = new StringBuilder();
                String response;
                //Reading server response
                while ((response = br.readLine()) != null){
                    sb.append(response);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    public String sendGetRequest(String requestURL){
        StringBuilder sb =new StringBuilder();
        try {
            URL url = new URL(requestURL);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));

            String s;
            while((s=bufferedReader.readLine())!=null){
                sb.append(s+"\n");
            }
        }catch(Exception e){
        }
        return sb.toString();
    }

    public String sendGetRequestParam(String requestURL, String id){
        StringBuilder sb =new StringBuilder();
        try {
            URL url = new URL(requestURL+id);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));

            String s;
            while((s=bufferedReader.readLine())!=null){
                sb.append(s+"\n");
            }
        }catch(Exception e){
        }
        return sb.toString();
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String>entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }
}

Open activity_list.xml in app > layout >activity_list.xml. Update activity_list.xml with this one.

<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" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="my.intellij.androidtodolist.ListActivity">

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Create Task"
        android:id="@+id/btnCreate"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <ListView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/lv_task"
        android:layout_below="@+id/btnCreate"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

ListActivity.java

package my.intellij.androidtodolist;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;

public class ListActivity extends AppCompatActivity implements ListView.OnItemClickListener {

    private ListView listView;

    private String JSON_STRING;

    private Button buttonAdd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_list);
        listView = (ListView) findViewById(R.id.lv_task);
        listView.setOnItemClickListener(this);
        getJSON();

        buttonAdd = (Button) findViewById(R.id.btnCreate);
        buttonAdd.setOnClickListener(new View.OnClickListener() {

            public void onClick(View arg0) {

                Intent createActivity = new Intent(getApplicationContext(), CreateActivity.class);
                startActivity(createActivity);

            }
        });
    }


    private void showTask(){
        JSONObject jsonObject = null;
        ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String, String>>();
        try {
            jsonObject = new JSONObject(JSON_STRING);
            JSONArray result = jsonObject.getJSONArray(App.TAG_JSON_ARRAY);

            for(int i = 0; i<result.length(); i++){
                JSONObject jo = result.getJSONObject(i);
                String id = jo.getString(App.TAG_ID);
                String name = jo.getString(App.TAG_NAME);

                HashMap<String,String> tasks = new HashMap<>();
                tasks.put(App.TAG_ID,id);
                tasks.put(App.TAG_NAME,name);
                list.add(tasks);
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

        ListAdapter adapter = new SimpleAdapter(
                ListActivity.this, list, R.layout.list_item,
                new String[]{App.TAG_NAME},
                new int[]{R.id.name});

        listView.setAdapter(adapter);
    }

    private void getJSON(){
        class GetJSON extends AsyncTask<Void,Void,String> {

            ProgressDialog loading;
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                loading = ProgressDialog.show(ListActivity.this,"Fetching Data","Wait...",false,false);
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                loading.dismiss();
                JSON_STRING = s;
                showTask();
            }

            @Override
            protected String doInBackground(Void... params) {
                RequestHandler rh = new RequestHandler();
                String s = rh.sendGetRequest(App.URL_GET_ALL);
                return s;
            }
        }
        GetJSON gj = new GetJSON();
        gj.execute();
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Intent intent = new Intent(this, UpdateActivity.class);
        HashMap<String,String> map =(HashMap)parent.getItemAtPosition(position);
        String taskId = map.get(App.TAG_ID).toString();
        intent.putExtra(App.ID,taskId);
        startActivity(intent);
    }
}

CreateActivity.java

package my.intellij.androidtodolist;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.util.HashMap;

public class CreateActivity extends AppCompatActivity implements View.OnClickListener{

    //Defining views
    private EditText editTextName;
    private EditText editTextDesription;

    private Button buttonAdd;
    private Button buttonView;

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

        //Initializing views
        editTextName = (EditText) findViewById(R.id.txtName);
        editTextDesription = (EditText) findViewById(R.id.txtDescription);

        buttonAdd = (Button) findViewById(R.id.btnCreate);
        buttonView = (Button) findViewById(R.id.btnBack);

        //Setting listeners to button
        buttonAdd.setOnClickListener(this);
        buttonView.setOnClickListener(this);
    }


    //Adding a task
    private void addTask(){

        final String name = editTextName.getText().toString().trim();
        final String description = editTextDesription.getText().toString().trim();

        class AddTask extends AsyncTask<Void,Void,String> {

            ProgressDialog loading;

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                loading = ProgressDialog.show(CreateActivity.this,"Adding...","Wait...",false,false);
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                loading.dismiss();
                Toast.makeText(CreateActivity.this,s,Toast.LENGTH_LONG).show();
            }

            @Override
            protected String doInBackground(Void... v) {
                HashMap<String,String> params = new HashMap<>();
                params.put(App.KEY_NAME,name);
                params.put(App.KEY_DESCRIPTION,description);

                RequestHandler rh = new RequestHandler();
                String res = rh.sendPostRequest(App.URL_CREATE, params);
                return res;
            }
        }

        AddTask ae = new AddTask();
        ae.execute();
    }

    @Override
    public void onClick(View v) {
        if(v == buttonAdd){
            addTask();
            startActivity(new Intent(CreateActivity.this,ListActivity.class));
        }

        if(v == buttonView){
            startActivity(new Intent(this,ListActivity.class));
        }
    }
}

Open activity_update.xml in app > layout >activity_update.xml. Update activity_update.xml with this one.

<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" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context="my.intellij.androidtodolist.UpdateActivity">

    <EditText
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/txtName"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:hint="Name"/>

    <EditText
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/txtDescription"
        android:layout_below="@+id/txtName"
        android:layout_centerHorizontal="true"
        android:hint="Description"/>

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Update Task"
        android:id="@+id/btnUpdate"
        android:layout_below="@+id/txtDescription"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Delete Task"
        android:id="@+id/btnDelete"
        android:layout_below="@+id/btnUpdate"
        android:layout_centerHorizontal="true" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Back"
        android:id="@+id/btnBack"
        android:layout_below="@+id/btnDelete"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

UpdateActivity.java

package my.intellij.androidtodolist;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;

public class UpdateActivity extends AppCompatActivity implements View.OnClickListener {

    private EditText editTextName;
    private EditText editTextDescription;

    private Button buttonUpdate;
    private Button buttonDelete;
    private Button buttonView;

    private String id;

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

        Intent intent = getIntent();

        id = getIntent().getExtras().getString(App.ID);

        editTextName = (EditText) findViewById(R.id.txtName);
        editTextDescription = (EditText) findViewById(R.id.txtDescription);

        buttonUpdate = (Button) findViewById(R.id.btnUpdate);
        buttonDelete = (Button) findViewById(R.id.btnDelete);
        buttonView = (Button) findViewById(R.id.btnBack);

        buttonUpdate.setOnClickListener(this);
        buttonDelete.setOnClickListener(this);
        buttonView.setOnClickListener(this);

        getTask();
    }

    private void getTask(){
        class GetTask extends AsyncTask<Void,Void,String> {
            ProgressDialog loading;
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                loading = ProgressDialog.show(UpdateActivity.this,"Fetching...","Wait...",false,false);
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                loading.dismiss();
                showTask(s);
            }

            @Override
            protected String doInBackground(Void... params) {
                RequestHandler rh = new RequestHandler();
                String s = rh.sendGetRequestParam(App.URL_GET_DETAIL,id);
                return s;
            }
        }
        GetTask gt = new GetTask();
        gt.execute();
    }

    private void showTask(String json){
        try {
            JSONObject jsonObject = new JSONObject(json);
            JSONArray result = jsonObject.getJSONArray(App.TAG_JSON_DETAIL);
            JSONObject c = result.getJSONObject(0);
            String name = c.getString(App.TAG_NAME);
            String description = c.getString(App.TAG_DESCRIPTION);

            editTextName.setText(name);
            editTextDescription.setText(description);

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }


    private void updateTask(){
        final String name = editTextName.getText().toString().trim();
        final String description = editTextDescription.getText().toString().trim();

        class UpdateTask extends AsyncTask<Void,Void,String>{
            ProgressDialog loading;
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                loading = ProgressDialog.show(UpdateActivity.this,"Updating...","Wait...",false,false);
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                loading.dismiss();
                Toast.makeText(UpdateActivity.this,s,Toast.LENGTH_LONG).show();
            }

            @Override
            protected String doInBackground(Void... params) {
                HashMap<String,String> hashMap = new HashMap<>();
                hashMap.put(App.KEY_ID,id);
                hashMap.put(App.KEY_NAME,name);
                hashMap.put(App.KEY_DESCRIPTION,description);

                RequestHandler rh = new RequestHandler();

                String s = rh.sendPostRequest(App.URL_UPDATE,hashMap);

                return s;
            }
        }

        UpdateTask ut = new UpdateTask();
        ut.execute();
    }

    private void deleteTask(){
        class DeleteTask extends AsyncTask<Void,Void,String> {
            ProgressDialog loading;

            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                loading = ProgressDialog.show(UpdateActivity.this, "Updating...", "Wait...", false, false);
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                loading.dismiss();
                Toast.makeText(UpdateActivity.this, s, Toast.LENGTH_LONG).show();
            }

            @Override
            protected String doInBackground(Void... params) {
                RequestHandler rh = new RequestHandler();
                String s = rh.sendGetRequestParam(App.URL_DELETE, id);
                return s;
            }
        }

        DeleteTask dt = new DeleteTask();
        dt.execute();
    }

    private void confirmDeleteTask(){
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
        alertDialogBuilder.setMessage("Are you sure you want to delete this task?");

        alertDialogBuilder.setPositiveButton("Yes",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {
                        deleteTask();
                        startActivity(new Intent(UpdateActivity.this,ListActivity.class));
                    }
                });

        alertDialogBuilder.setNegativeButton("No",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface arg0, int arg1) {

                    }
                });

        AlertDialog alertDialog = alertDialogBuilder.create();
        alertDialog.show();
    }

    @Override
    public void onClick(View v) {
        if(v == buttonUpdate){
            updateTask();
        }

        if(v == buttonDelete){
            confirmDeleteTask();
        }

        if(v == buttonView){
            startActivity(new Intent(this,ListActivity.class));
        }
    }
}

Now try running your application.